[java-1.7.0-openjdk] Backed out 6664509 and 7201064.patch which cause regressions
Deepak Bhole
dbhole at fedoraproject.org
Wed Feb 6 20:13:46 UTC 2013
commit 3178bc6abf394496fde0b87826d71d8a3f5e07c9
Author: Deepak Bhole <dbhole at redhat.com>
Date: Wed Feb 6 15:13:03 2013 -0500
Backed out 6664509 and 7201064.patch which cause regressions
java-1.7.0-openjdk.spec | 19 +-
sec-2013-02-01-6664509.patch | 1365 ++++++++++++++++++++++++++++++++++++++++++
sec-2013-02-01-7201064.patch | 123 ++++
3 files changed, 1506 insertions(+), 1 deletions(-)
---
diff --git a/java-1.7.0-openjdk.spec b/java-1.7.0-openjdk.spec
index 028fe10..9eb56ba 100644
--- a/java-1.7.0-openjdk.spec
+++ b/java-1.7.0-openjdk.spec
@@ -153,7 +153,7 @@
Name: java-%{javaver}-%{origin}
Version: %{javaver}.%{buildver}
-Release: %{icedtea_version}%{?dist}
+Release: %{icedtea_version}%{?dist}.1
# java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons,
# and this change was brought into RHEL-4. java-1.5.0-ibm packages
# also included the epoch in their virtual provides. This created a
@@ -424,6 +424,15 @@ Patch302: systemtap.patch
# Rhino support
Patch400: rhino-icedtea-2.1.1.patch
+# Temporary patches
+# Patches to reverse 2 2012-02-01 security update
+
+# Back out 6664509 which bnreaks custom log managers
+Patch1000: sec-2013-02-01-6664509.patch
+
+# Back out 7201064 which breaks TCK
+Patch1001: sec-2013-02-01-7201064.patch
+
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: alsa-lib-devel
@@ -675,6 +684,11 @@ for TP in $TMPPATCHES ; do
fi;
done ;
+pushd openjdk/jdk/
+%patch1000 -p1 -R
+%patch1001 -p1 -R
+popd
+
# If bootstrapping, apply additional patches
%if %{gcjbootstrap}
@@ -1473,6 +1487,9 @@ exit 0
%doc %{buildoutputdir}/j2sdk-image/jre/LICENSE
%changelog
+* Wed Feb 06 2013 Deepak Bhole <dbhole at redhat.com> - 1.7.0.9-2.3.5.fc19.1
+- Backed out 6664509 and 7201064.patch which cause regressions
+
* Sun Feb 03 2013 Deepak Bhole <dbhole at redhat.com> - 1.7.0.9-2.3.5.fc19
- Bumped to 2.3.5
- Removed unnecessary GENSRC flag
diff --git a/sec-2013-02-01-6664509.patch b/sec-2013-02-01-6664509.patch
new file mode 100644
index 0000000..cd55ce7
--- /dev/null
+++ b/sec-2013-02-01-6664509.patch
@@ -0,0 +1,1365 @@
+# HG changeset patch
+# User mchung
+# Date 1353965537 28800
+# Node ID f26def552d2c4873aeaee00241f60efc462a11a7
+# Parent 6f9dde55bd49829cf41bd45b766780c2ec7e0bc1
+6664509: Add logging context
+6664528: Find log level matching its name or value given at construction time
+Reviewed-by: alanb, ahgross, jgish, hawtin
+
+diff --git a/src/share/classes/java/util/logging/Level.java b/src/share/classes/java/util/logging/Level.java
+--- a/src/share/classes/java/util/logging/Level.java
++++ b/src/share/classes/java/util/logging/Level.java
+@@ -24,6 +24,10 @@
+ */
+
+ package java.util.logging;
++import java.util.ArrayList;
++import java.util.HashMap;
++import java.util.List;
++import java.util.Map;
+ import java.util.ResourceBundle;
+
+ /**
+@@ -59,7 +63,6 @@ import java.util.ResourceBundle;
+ */
+
+ public class Level implements java.io.Serializable {
+- private static java.util.ArrayList<Level> known = new java.util.ArrayList<>();
+ private static String defaultBundle = "sun.util.logging.resources.logging";
+
+ /**
+@@ -76,6 +79,9 @@ public class Level implements java.io.Se
+ * @serial The resource bundle name to be used in localizing the level name.
+ */
+ private final String resourceBundleName;
++
++ // localized level name
++ private String localizedLevelName;
+
+ /**
+ * OFF is a special level that can be used to turn off logging.
+@@ -202,9 +208,8 @@ public class Level implements java.io.Se
+ this.name = name;
+ this.value = value;
+ this.resourceBundleName = resourceBundleName;
+- synchronized (Level.class) {
+- known.add(this);
+- }
++ this.localizedLevelName = resourceBundleName == null ? name : null;
++ KnownLevel.add(this);
+ }
+
+ /**
+@@ -236,12 +241,76 @@ public class Level implements java.io.Se
+ * @return localized name
+ */
+ public String getLocalizedName() {
++ return getLocalizedLevelName();
++ }
++
++ // package-private getLevelName() is used by the implementation
++ // instead of getName() to avoid calling the subclass's version
++ final String getLevelName() {
++ return this.name;
++ }
++
++ final synchronized String getLocalizedLevelName() {
++ if (localizedLevelName != null) {
++ return localizedLevelName;
++ }
++
+ try {
+ ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName);
+- return rb.getString(name);
++ localizedLevelName = rb.getString(name);
+ } catch (Exception ex) {
+- return name;
++ localizedLevelName = name;
+ }
++ return localizedLevelName;
++ }
++
++ // Returns a mirrored Level object that matches the given name as
++ // specified in the Level.parse method. Returns null if not found.
++ //
++ // It returns the same Level object as the one returned by Level.parse
++ // method if the given name is a non-localized name or integer.
++ //
++ // If the name is a localized name, findLevel and parse method may
++ // return a different level value if there is a custom Level subclass
++ // that overrides Level.getLocalizedName() to return a different string
++ // than what's returned by the default implementation.
++ //
++ static Level findLevel(String name) {
++ if (name == null) {
++ throw new NullPointerException();
++ }
++
++ KnownLevel level;
++
++ // Look for a known Level with the given non-localized name.
++ level = KnownLevel.findByName(name);
++ if (level != null) {
++ return level.mirroredLevel;
++ }
++
++ // Now, check if the given name is an integer. If so,
++ // first look for a Level with the given value and then
++ // if necessary create one.
++ try {
++ int x = Integer.parseInt(name);
++ level = KnownLevel.findByValue(x);
++ if (level == null) {
++ // add new Level
++ Level levelObject = new Level(name, x);
++ level = KnownLevel.findByValue(x);
++ }
++ return level.mirroredLevel;
++ } catch (NumberFormatException ex) {
++ // Not an integer.
++ // Drop through.
++ }
++
++ level = KnownLevel.findByLocalizedLevelName(name);
++ if (level != null) {
++ return level.mirroredLevel;
++ }
++
++ return null;
+ }
+
+ /**
+@@ -268,21 +337,15 @@ public class Level implements java.io.Se
+ // Serialization magic to prevent "doppelgangers".
+ // This is a performance optimization.
+ private Object readResolve() {
+- synchronized (Level.class) {
+- for (int i = 0; i < known.size(); i++) {
+- Level other = known.get(i);
+- if (this.name.equals(other.name) && this.value == other.value
+- && (this.resourceBundleName == other.resourceBundleName ||
+- (this.resourceBundleName != null &&
+- this.resourceBundleName.equals(other.resourceBundleName)))) {
+- return other;
+- }
+- }
+- // Woops. Whoever sent us this object knows
+- // about a new log level. Add it to our list.
+- known.add(this);
+- return this;
++ KnownLevel o = KnownLevel.matches(this);
++ if (o != null) {
++ return o.levelObject;
+ }
++
++ // Woops. Whoever sent us this object knows
++ // about a new log level. Add it to our list.
++ Level level = new Level(this.name, this.value, this.resourceBundleName);
++ return level;
+ }
+
+ /**
+@@ -296,6 +359,7 @@ public class Level implements java.io.Se
+ * <li> "SEVERE"
+ * <li> "1000"
+ * </ul>
++ *
+ * @param name string to be parsed
+ * @throws NullPointerException if the name is null
+ * @throws IllegalArgumentException if the value is not valid.
+@@ -315,12 +379,12 @@ public class Level implements java.io.Se
+ // Check that name is not null.
+ name.length();
+
++ KnownLevel level;
++
+ // Look for a known Level with the given non-localized name.
+- for (int i = 0; i < known.size(); i++) {
+- Level l = known.get(i);
+- if (name.equals(l.name)) {
+- return l;
+- }
++ level = KnownLevel.findByName(name);
++ if (level != null) {
++ return level.levelObject;
+ }
+
+ // Now, check if the given name is an integer. If so,
+@@ -328,14 +392,13 @@ public class Level implements java.io.Se
+ // if necessary create one.
+ try {
+ int x = Integer.parseInt(name);
+- for (int i = 0; i < known.size(); i++) {
+- Level l = known.get(i);
+- if (l.value == x) {
+- return l;
+- }
++ level = KnownLevel.findByValue(x);
++ if (level == null) {
++ // add new Level
++ Level levelObject = new Level(name, x);
++ level = KnownLevel.findByValue(x);
+ }
+- // Create a new Level.
+- return new Level(name, x);
++ return level.levelObject;
+ } catch (NumberFormatException ex) {
+ // Not an integer.
+ // Drop through.
+@@ -344,11 +407,9 @@ public class Level implements java.io.Se
+ // Finally, look for a known level with the given localized name,
+ // in the current default locale.
+ // This is relatively expensive, but not excessively so.
+- for (int i = 0; i < known.size(); i++) {
+- Level l = known.get(i);
+- if (name.equals(l.getLocalizedName())) {
+- return l;
+- }
++ level = KnownLevel.findByLocalizedName(name);
++ if (level != null) {
++ return level.levelObject;
+ }
+
+ // OK, we've tried everything and failed
+@@ -375,4 +436,124 @@ public class Level implements java.io.Se
+ public int hashCode() {
+ return this.value;
+ }
++
++ // KnownLevel class maintains the global list of all known levels.
++ // The API allows multiple custom Level instances of the same name/value
++ // be created. This class provides convenient methods to find a level
++ // by a given name, by a given value, or by a given localized name.
++ //
++ // KnownLevel wraps the following Level objects:
++ // 1. levelObject: standard Level object or custom Level object
++ // 2. mirroredLevel: Level object representing the level specified in the
++ // logging configuration.
++ //
++ // Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods
++ // are non-final but the name and resource bundle name are parameters to
++ // the Level constructor. Use the mirroredLevel object instead of the
++ // levelObject to prevent the logging framework to execute foreign code
++ // implemented by untrusted Level subclass.
++ //
++ // Implementation Notes:
++ // If Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods
++ // were final, the following KnownLevel implementation can be removed.
++ // Future API change should take this into consideration.
++ static final class KnownLevel {
++ private static Map<String, List<KnownLevel>> nameToLevels = new HashMap<>();
++ private static Map<Integer, List<KnownLevel>> intToLevels = new HashMap<>();
++ final Level levelObject; // instance of Level class or Level subclass
++ final Level mirroredLevel; // instance of Level class
++ KnownLevel(Level l) {
++ this.levelObject = l;
++ if (l.getClass() == Level.class) {
++ this.mirroredLevel = l;
++ } else {
++ this.mirroredLevel = new Level(l.name, l.value, l.resourceBundleName);
++ }
++ }
++
++ static synchronized void add(Level l) {
++ // the mirroredLevel object is always added to the list
++ // before the custom Level instance
++ KnownLevel o = new KnownLevel(l);
++ List<KnownLevel> list = nameToLevels.get(l.name);
++ if (list == null) {
++ list = new ArrayList<>();
++ nameToLevels.put(l.name, list);
++ }
++ list.add(o);
++
++ list = intToLevels.get(l.value);
++ if (list == null) {
++ list = new ArrayList<>();
++ intToLevels.put(l.value, list);
++ }
++ list.add(o);
++ }
++
++ // Returns a KnownLevel with the given non-localized name.
++ static synchronized KnownLevel findByName(String name) {
++ List<KnownLevel> list = nameToLevels.get(name);
++ if (list != null) {
++ return list.get(0);
++ }
++ return null;
++ }
++
++ // Returns a KnownLevel with the given value.
++ static synchronized KnownLevel findByValue(int value) {
++ List<KnownLevel> list = intToLevels.get(value);
++ if (list != null) {
++ return list.get(0);
++ }
++ return null;
++ }
++
++ // Returns a KnownLevel with the given localized name matching
++ // by calling the Level.getLocalizedLevelName() method (i.e. found
++ // from the resourceBundle associated with the Level object).
++ // This method does not call Level.getLocalizedName() that may
++ // be overridden in a subclass implementation
++ static synchronized KnownLevel findByLocalizedLevelName(String name) {
++ for (List<KnownLevel> levels : nameToLevels.values()) {
++ for (KnownLevel l : levels) {
++ String lname = l.levelObject.getLocalizedLevelName();
++ if (name.equals(lname)) {
++ return l;
++ }
++ }
++ }
++ return null;
++ }
++
++ // Returns a KnownLevel with the given localized name matching
++ // by calling the Level.getLocalizedName() method
++ static synchronized KnownLevel findByLocalizedName(String name) {
++ for (List<KnownLevel> levels : nameToLevels.values()) {
++ for (KnownLevel l : levels) {
++ String lname = l.levelObject.getLocalizedName();
++ if (name.equals(lname)) {
++ return l;
++ }
++ }
++ }
++ return null;
++ }
++
++ static synchronized KnownLevel matches(Level l) {
++ List<KnownLevel> list = nameToLevels.get(l.name);
++ if (list != null) {
++ for (KnownLevel level : list) {
++ Level other = level.mirroredLevel;
++ if (l.value == other.value &&
++ (l.resourceBundleName == other.resourceBundleName ||
++ (l.resourceBundleName != null &&
++ l.resourceBundleName.equals(other.resourceBundleName)))) {
++ return level;
++ }
++ }
++ }
++ return null;
++ }
++ }
++
+ }
+diff --git a/src/share/classes/java/util/logging/LogManager.java b/src/share/classes/java/util/logging/LogManager.java
+--- a/src/share/classes/java/util/logging/LogManager.java
++++ b/src/share/classes/java/util/logging/LogManager.java
+@@ -34,6 +34,8 @@ import java.beans.PropertyChangeListener
+ import java.beans.PropertyChangeListener;
+ import java.beans.PropertyChangeSupport;
+ import java.net.URL;
++import sun.misc.JavaAWTAccess;
++import sun.misc.SharedSecrets;
+ import sun.security.action.GetPropertyAction;
+
+ /**
+@@ -155,10 +157,9 @@ public class LogManager {
+ = new PropertyChangeSupport(LogManager.class);
+ private final static Level defaultLevel = Level.INFO;
+
+- // Table of named Loggers that maps names to Loggers.
+- private Hashtable<String,LoggerWeakRef> namedLoggers = new Hashtable<>();
+- // Tree of named Loggers
+- private LogNode root = new LogNode(null);
++ // LoggerContext for system loggers and user loggers
++ private final LoggerContext systemContext = new SystemLoggerContext();
++ private final LoggerContext userContext = new UserLoggerContext();
+ private Logger rootLogger;
+
+ // Have we done the primordial reading of the configuration file?
+@@ -196,12 +197,13 @@ public class LogManager {
+
+ // Create and retain Logger for the root of the namespace.
+ manager.rootLogger = manager.new RootLogger();
+- manager.addLogger(manager.rootLogger);
++ manager.systemContext.addLogger(manager.rootLogger);
++ manager.userContext.addLogger(manager.rootLogger);
+
+ // Adding the global Logger. Doing so in the Logger.<clinit>
+ // would deadlock with the LogManager.<clinit>.
+ Logger.global.setLogManager(manager);
+- manager.addLogger(Logger.global);
++ manager.systemContext.addLogger(Logger.global);
+
+ // We don't call readConfiguration() here, as we may be running
+ // very early in the JVM startup sequence. Instead readConfiguration
+@@ -279,14 +281,14 @@ public class LogManager {
+ return;
+ }
+ readPrimordialConfiguration = true;
++
+ try {
+- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+- public Object run() throws Exception {
++ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
++ public Void run() throws Exception {
+ readConfiguration();
+
+ // Platform loggers begin to delegate to java.util.logging.Logger
+ sun.util.logging.PlatformLogger.redirectPlatformLoggers();
+-
+ return null;
+ }
+ });
+@@ -337,62 +339,290 @@ public class LogManager {
+ changes.removePropertyChangeListener(l);
+ }
+
+- // Package-level method.
+- // Find or create a specified logger instance. If a logger has
+- // already been created with the given name it is returned.
+- // Otherwise a new logger instance is created and registered
+- // in the LogManager global namespace.
++ // Returns the LoggerContext for the user code (i.e. application or AppContext).
++ // Loggers are isolated from each AppContext.
++ LoggerContext getUserContext() {
++ LoggerContext context = null;
+
+- // This method will always return a non-null Logger object.
+- // Synchronization is not required here. All synchronization for
+- // adding a new Logger object is handled by addLogger().
+- Logger demandLogger(String name) {
+- Logger result = getLogger(name);
+- if (result == null) {
+- // only allocate the new logger once
+- Logger newLogger = new Logger(name, null);
+- do {
+- if (addLogger(newLogger)) {
+- // We successfully added the new Logger that we
+- // created above so return it without refetching.
+- return newLogger;
++ SecurityManager sm = System.getSecurityManager();
++ JavaAWTAccess javaAwtAccess = SharedSecrets.getJavaAWTAccess();
++ if (sm != null && javaAwtAccess != null) {
++ synchronized (javaAwtAccess) {
++ // AppContext.getAppContext() returns the system AppContext if called
++ // from a system thread but Logger.getLogger might be called from
++ // an applet code. Instead, find the AppContext of the applet code
++ // from the execution stack.
++ Object ecx = javaAwtAccess.getExecutionContext();
++ if (ecx == null) {
++ // fall back to AppContext.getAppContext()
++ ecx = javaAwtAccess.getContext();
+ }
+-
+- // We didn't add the new Logger that we created above
+- // because another thread added a Logger with the same
+- // name after our null check above and before our call
+- // to addLogger(). We have to refetch the Logger because
+- // addLogger() returns a boolean instead of the Logger
+- // reference itself. However, if the thread that created
+- // the other Logger is not holding a strong reference to
+- // the other Logger, then it is possible for the other
+- // Logger to be GC'ed after we saw it in addLogger() and
+- // before we can refetch it. If it has been GC'ed then
+- // we'll just loop around and try again.
+- result = getLogger(name);
+- } while (result == null);
++ context = (LoggerContext)javaAwtAccess.get(ecx, LoggerContext.class);
++ if (context == null) {
++ if (javaAwtAccess.isMainAppContext()) {
++ context = userContext;
++ } else {
++ context = new UserLoggerContext();
++ context.addLogger(manager.rootLogger);
++ }
++ javaAwtAccess.put(ecx, LoggerContext.class, context);
++ }
++ }
++ } else {
++ context = userContext;
+ }
+- return result;
++ return context;
+ }
+
+- // If logger.getUseParentHandlers() returns 'true' and any of the logger's
+- // parents have levels or handlers defined, make sure they are instantiated.
+- private void processParentHandlers(Logger logger, String name) {
+- int ix = 1;
+- for (;;) {
+- int ix2 = name.indexOf(".", ix);
+- if (ix2 < 0) {
+- break;
++ LoggerContext getSystemContext() {
++ return systemContext;
++ }
++
++ private List<LoggerContext> contexts() {
++ List<LoggerContext> cxs = new ArrayList<>();
++ cxs.add(systemContext);
++ cxs.add(getUserContext());
++ return cxs;
++ }
++
++ static class LoggerContext {
++ // Table of named Loggers that maps names to Loggers.
++ private final Hashtable<String,LoggerWeakRef> namedLoggers = new Hashtable<>();
++ // Tree of named Loggers
++ private final LogNode root;
++
++ private LoggerContext() {
++ this.root = new LogNode(null, this);
++ }
++
++ synchronized Logger findLogger(String name) {
++ LoggerWeakRef ref = namedLoggers.get(name);
++ if (ref == null) {
++ return null;
+ }
+- String pname = name.substring(0,ix2);
++ Logger logger = ref.get();
++ if (logger == null) {
++ // Hashtable holds stale weak reference
++ // to a logger which has been GC-ed.
++ removeLogger(name);
++ }
++ return logger;
++ }
+
+- if (getProperty(pname+".level") != null ||
+- getProperty(pname+".handlers") != null) {
+- // This pname has a level/handlers definition.
+- // Make sure it exists.
+- demandLogger(pname);
++ synchronized boolean addLogger(Logger logger) {
++ final String name = logger.getName();
++ if (name == null) {
++ throw new NullPointerException();
+ }
+- ix = ix2+1;
++
++ // cleanup some Loggers that have been GC'ed
++ manager.drainLoggerRefQueueBounded();
++
++ LoggerWeakRef ref = namedLoggers.get(name);
++ if (ref != null) {
++ if (ref.get() == null) {
++ // It's possible that the Logger was GC'ed after the
++ // drainLoggerRefQueueBounded() call above so allow
++ // a new one to be registered.
++ removeLogger(name);
++ } else {
++ // We already have a registered logger with the given name.
++ return false;
++ }
++ }
++
++ // We're adding a new logger.
++ // Note that we are creating a weak reference here.
++ ref = manager.new LoggerWeakRef(logger);
++ namedLoggers.put(name, ref);
++
++ // Apply any initial level defined for the new logger.
++ Level level = manager.getLevelProperty(name + ".level", null);
++ if (level != null) {
++ doSetLevel(logger, level);
++ }
++
++ // Do we have a per logger handler too?
++ // Note: this will add a 200ms penalty
++ manager.loadLoggerHandlers(logger, name, name + ".handlers");
++ processParentHandlers(logger, name);
++
++ // Find the new node and its parent.
++ LogNode node = getNode(name);
++ node.loggerRef = ref;
++ Logger parent = null;
++ LogNode nodep = node.parent;
++ while (nodep != null) {
++ LoggerWeakRef nodeRef = nodep.loggerRef;
++ if (nodeRef != null) {
++ parent = nodeRef.get();
++ if (parent != null) {
++ break;
++ }
++ }
++ nodep = nodep.parent;
++ }
++
++ if (parent != null) {
++ doSetParent(logger, parent);
++ }
++ // Walk over the children and tell them we are their new parent.
++ node.walkAndSetParent(logger);
++ // new LogNode is ready so tell the LoggerWeakRef about it
++ ref.setNode(node);
++ return true;
++ }
++
++ void removeLogger(String name) {
++ namedLoggers.remove(name);
++ }
++
++ synchronized Enumeration<String> getLoggerNames() {
++ return namedLoggers.keys();
++ }
++
++ Logger demandLogger(String name) {
++ return demandLogger(name, null);
++ }
++
++ // Find or create a specified logger instance. If a logger has
++ // already been created with the given name it is returned.
++ // Otherwise a new logger instance is created and registered
++ // in the LogManager global namespace.
++
++ // This method will always return a non-null Logger object.
++ // Synchronization is not required here. All synchronization for
++ // adding a new Logger object is handled by addLogger().
++ Logger demandLogger(String name, String resourceBundleName) {
++ Logger result = findLogger(name);
++ if (result == null) {
++ // only allocate the new logger once
++ Logger newLogger = new Logger(name, resourceBundleName);
++ do {
++ if (addLogger(newLogger)) {
++ // We successfully added the new Logger that we
++ // created above so return it without refetching.
++ return newLogger;
++ }
++
++ // We didn't add the new Logger that we created above
++ // because another thread added a Logger with the same
++ // name after our null check above and before our call
++ // to addLogger(). We have to refetch the Logger because
++ // addLogger() returns a boolean instead of the Logger
++ // reference itself. However, if the thread that created
++ // the other Logger is not holding a strong reference to
++ // the other Logger, then it is possible for the other
++ // Logger to be GC'ed after we saw it in addLogger() and
++ // before we can refetch it. If it has been GC'ed then
++ // we'll just loop around and try again.
++ result = findLogger(name);
++ } while (result == null);
++ }
++ return result;
++ }
++
++ // If logger.getUseParentHandlers() returns 'true' and any of the logger's
++ // parents have levels or handlers defined, make sure they are instantiated.
++ private void processParentHandlers(Logger logger, String name) {
++ int ix = 1;
++ for (;;) {
++ int ix2 = name.indexOf(".", ix);
++ if (ix2 < 0) {
++ break;
++ }
++ String pname = name.substring(0, ix2);
++
++ if (manager.getProperty(pname + ".level") != null ||
++ manager.getProperty(pname + ".handlers") != null) {
++ // This pname has a level/handlers definition.
++ // Make sure it exists.
++ demandLogger(pname);
++ }
++ ix = ix2+1;
++ }
++ }
++
++ // Gets a node in our tree of logger nodes.
++ // If necessary, create it.
++ LogNode getNode(String name) {
++ if (name == null || name.equals("")) {
++ return root;
++ }
++ LogNode node = root;
++ while (name.length() > 0) {
++ int ix = name.indexOf(".");
++ String head;
++ if (ix > 0) {
++ head = name.substring(0, ix);
++ name = name.substring(ix + 1);
++ } else {
++ head = name;
++ name = "";
++ }
++ if (node.children == null) {
++ node.children = new HashMap<>();
++ }
++ LogNode child = node.children.get(head);
++ if (child == null) {
++ child = new LogNode(node, this);
++ node.children.put(head, child);
++ }
++ node = child;
++ }
++ return node;
++ }
++ }
++
++ static class SystemLoggerContext extends LoggerContext {
++ // Default resource bundle for all system loggers
++ Logger demandLogger(String name) {
++ // default to use the system logger's resource bundle
++ return super.demandLogger(name, Logger.SYSTEM_LOGGER_RB_NAME);
++ }
++ }
++
++ static class UserLoggerContext extends LoggerContext {
++ /**
++ * Returns a Logger of the given name if there is one registered
++ * in this context. Otherwise, it will return the one registered
++ * in the system context if there is one. The returned Logger
++ * instance may be initialized with a different resourceBundleName.
++ * If no such logger exists, a new Logger instance will be created
++ * and registered in this context.
++ */
++ Logger demandLogger(String name, String resourceBundleName) {
++ Logger result = findLogger(name);
++ if (result == null) {
++ // use the system logger if exists; or allocate a new logger.
++ // The system logger is added to the app logger context so that
++ // any child logger created in the app logger context can have
++ // a system logger as its parent if already exist.
++ Logger logger = manager.systemContext.findLogger(name);
++ Logger newLogger =
++ logger != null ? logger : new Logger(name, resourceBundleName);
++ do {
++ if (addLogger(newLogger)) {
++ // We successfully added the new Logger that we
++ // created above so return it without refetching.
++ return newLogger;
++ }
++
++ // We didn't add the new Logger that we created above
++ // because another thread added a Logger with the same
++ // name after our null check above and before our call
++ // to addLogger(). We have to refetch the Logger because
++ // addLogger() returns a boolean instead of the Logger
++ // reference itself. However, if the thread that created
++ // the other Logger is not holding a strong reference to
++ // the other Logger, then it is possible for the other
++ // Logger to be GC'ed after we saw it in addLogger() and
++ // before we can refetch it. If it has been GC'ed then
++ // we'll just loop around and try again.
++ result = findLogger(name);
++ } while (result == null);
++ }
++ return result;
+ }
+ }
+
+@@ -415,18 +645,19 @@ public class LogManager {
+ for (int i = 0; i < names.length; i++) {
+ String word = names[i];
+ try {
+- Class clz = ClassLoader.getSystemClassLoader().loadClass(word);
+- Handler hdl = (Handler) clz.newInstance();
+- try {
+- // Check if there is a property defining the
+- // this handler's level.
+- String levs = getProperty(word + ".level");
+- if (levs != null) {
+- hdl.setLevel(Level.parse(levs));
++ Class clz = ClassLoader.getSystemClassLoader().loadClass(word);
++ Handler hdl = (Handler) clz.newInstance();
++ // Check if there is a property defining the
++ // this handler's level.
++ String levs = getProperty(word + ".level");
++ if (levs != null) {
++ Level l = Level.findLevel(levs);
++ if (l != null) {
++ hdl.setLevel(l);
++ } else {
++ // Probably a bad level. Drop through.
++ System.err.println("Can't set level for " + word);
+ }
+- } catch (Exception ex) {
+- System.err.println("Can't set level for " + word);
+- // Probably a bad level. Drop through.
+ }
+ // Add this Handler to the logger
+ logger.addHandler(hdl);
+@@ -482,7 +713,7 @@ public class LogManager {
+ if (node != null) {
+ // if we have a LogNode, then we were a named Logger
+ // so clear namedLoggers weak ref to us
+- manager.namedLoggers.remove(name);
++ node.context.removeLogger(name);
+ name = null; // clear our ref to the Logger's name
+
+ node.loggerRef = null; // clear LogNode's weak ref to us
+@@ -571,70 +802,15 @@ public class LogManager {
+ * false if a logger of that name already exists.
+ * @exception NullPointerException if the logger name is null.
+ */
+- public synchronized boolean addLogger(Logger logger) {
++ public boolean addLogger(Logger logger) {
+ final String name = logger.getName();
+ if (name == null) {
+ throw new NullPointerException();
+ }
+-
+- // cleanup some Loggers that have been GC'ed
+- drainLoggerRefQueueBounded();
+-
+- LoggerWeakRef ref = namedLoggers.get(name);
+- if (ref != null) {
+- if (ref.get() == null) {
+- // It's possible that the Logger was GC'ed after the
+- // drainLoggerRefQueueBounded() call above so allow
+- // a new one to be registered.
+- namedLoggers.remove(name);
+- } else {
+- // We already have a registered logger with the given name.
+- return false;
+- }
++ if (systemContext.findLogger(name) != null) {
++ return false;
+ }
+-
+- // We're adding a new logger.
+- // Note that we are creating a weak reference here.
+- ref = new LoggerWeakRef(logger);
+- namedLoggers.put(name, ref);
+-
+- // Apply any initial level defined for the new logger.
+- Level level = getLevelProperty(name+".level", null);
+- if (level != null) {
+- doSetLevel(logger, level);
+- }
+-
+- // Do we have a per logger handler too?
+- // Note: this will add a 200ms penalty
+- loadLoggerHandlers(logger, name, name+".handlers");
+- processParentHandlers(logger, name);
+-
+- // Find the new node and its parent.
+- LogNode node = findNode(name);
+- node.loggerRef = ref;
+- Logger parent = null;
+- LogNode nodep = node.parent;
+- while (nodep != null) {
+- LoggerWeakRef nodeRef = nodep.loggerRef;
+- if (nodeRef != null) {
+- parent = nodeRef.get();
+- if (parent != null) {
+- break;
+- }
+- }
+- nodep = nodep.parent;
+- }
+-
+- if (parent != null) {
+- doSetParent(logger, parent);
+- }
+- // Walk over the children and tell them we are their new parent.
+- node.walkAndSetParent(logger);
+-
+- // new LogNode is ready so tell the LoggerWeakRef about it
+- ref.setNode(node);
+-
+- return true;
++ return getUserContext().addLogger(logger);
+ }
+
+
+@@ -676,36 +852,6 @@ public class LogManager {
+ }});
+ }
+
+- // Find a node in our tree of logger nodes.
+- // If necessary, create it.
+- private LogNode findNode(String name) {
+- if (name == null || name.equals("")) {
+- return root;
+- }
+- LogNode node = root;
+- while (name.length() > 0) {
+- int ix = name.indexOf(".");
+- String head;
+- if (ix > 0) {
+- head = name.substring(0,ix);
+- name = name.substring(ix+1);
+- } else {
+- head = name;
+- name = "";
+- }
+- if (node.children == null) {
+- node.children = new HashMap<>();
+- }
+- LogNode child = node.children.get(head);
+- if (child == null) {
+- child = new LogNode(node);
+- node.children.put(head, child);
+- }
+- node = child;
+- }
+- return node;
+- }
+-
+ /**
+ * Method to find a named logger.
+ * <p>
+@@ -721,18 +867,16 @@ public class LogManager {
+ * @param name name of the logger
+ * @return matching logger or null if none is found
+ */
+- public synchronized Logger getLogger(String name) {
+- LoggerWeakRef ref = namedLoggers.get(name);
+- if (ref == null) {
+- return null;
+- }
+- Logger logger = ref.get();
+- if (logger == null) {
+- // Hashtable holds stale weak reference
+- // to a logger which has been GC-ed.
+- namedLoggers.remove(name);
+- }
+- return logger;
++ public Logger getLogger(String name) {
++ // return the first logger added
++ //
++ // once a system logger is added in the system context, no one can
++ // adds a logger with the same name in the global context
++ // (see LogManager.addLogger). So if there is a logger in the global
++ // context with the same name as one in the system context, it must be
++ // added before the system logger was created.
++ Logger logger = getUserContext().findLogger(name);
++ return logger != null ? logger : systemContext.findLogger(name);
+ }
+
+ /**
+@@ -751,8 +895,11 @@ public class LogManager {
+ * <p>
+ * @return enumeration of logger name strings
+ */
+- public synchronized Enumeration<String> getLoggerNames() {
+- return namedLoggers.keys();
++ public Enumeration<String> getLoggerNames() {
++ // only return unique names
++ Set<String> names = new HashSet<>(Collections.list(systemContext.getLoggerNames()));
++ names.addAll(Collections.list(getUserContext().getLoggerNames()));
++ return Collections.enumeration(names);
+ }
+
+ /**
+@@ -837,20 +984,20 @@ public class LogManager {
+ // the global handlers, if they haven't been initialized yet.
+ initializedGlobalHandlers = true;
+ }
+- Enumeration enum_ = getLoggerNames();
+- while (enum_.hasMoreElements()) {
+- String name = (String)enum_.nextElement();
+- resetLogger(name);
++ for (LoggerContext cx : contexts()) {
++ Enumeration<String> enum_ = cx.getLoggerNames();
++ while (enum_.hasMoreElements()) {
++ String name = enum_.nextElement();
++ Logger logger = cx.findLogger(name);
++ if (logger != null) {
++ resetLogger(logger);
++ }
++ }
+ }
+ }
+
+-
+ // Private method to reset an individual target logger.
+- private void resetLogger(String name) {
+- Logger logger = getLogger(name);
+- if (logger == null) {
+- return;
+- }
++ private void resetLogger(Logger logger) {
+ // Close all the Logger's handlers.
+ Handler[] targets = logger.getHandlers();
+ for (int i = 0; i < targets.length; i++) {
+@@ -862,6 +1009,7 @@ public class LogManager {
+ // Problems closing a handler? Keep going...
+ }
+ }
++ String name = logger.getName();
+ if (name != null && name.equals("")) {
+ // This is the root logger.
+ logger.setLevel(defaultLevel);
+@@ -1009,11 +1157,8 @@ public class LogManager {
+ if (val == null) {
+ return defaultValue;
+ }
+- try {
+- return Level.parse(val.trim());
+- } catch (Exception ex) {
+- return defaultValue;
+- }
++ Level l = Level.findLevel(val.trim());
++ return l != null ? l : defaultValue;
+ }
+
+ // Package private method to get a filter property.
+@@ -1104,9 +1249,11 @@ public class LogManager {
+ HashMap<String,LogNode> children;
+ LoggerWeakRef loggerRef;
+ LogNode parent;
++ final LoggerContext context;
+
+- LogNode(LogNode parent) {
++ LogNode(LogNode parent, LoggerContext context) {
+ this.parent = parent;
++ this.context = context;
+ }
+
+ // Recursive method to walk the tree below a node and set
+@@ -1165,7 +1312,7 @@ public class LogManager {
+ // Private method to be called when the configuration has
+ // changed to apply any level settings to any pre-existing loggers.
+ synchronized private void setLevelsOnExistingLoggers() {
+- Enumeration enum_ = props.propertyNames();
++ Enumeration<?> enum_ = props.propertyNames();
+ while (enum_.hasMoreElements()) {
+ String key = (String)enum_.nextElement();
+ if (!key.endsWith(".level")) {
+@@ -1179,11 +1326,13 @@ public class LogManager {
+ System.err.println("Bad level value for property: " + key);
+ continue;
+ }
+- Logger l = getLogger(name);
+- if (l == null) {
+- continue;
++ for (LoggerContext cx : contexts()) {
++ Logger l = cx.findLogger(name);
++ if (l == null) {
++ continue;
++ }
++ l.setLevel(level);
+ }
+- l.setLevel(level);
+ }
+ }
+
+diff --git a/src/share/classes/java/util/logging/Logger.java b/src/share/classes/java/util/logging/Logger.java
+--- a/src/share/classes/java/util/logging/Logger.java
++++ b/src/share/classes/java/util/logging/Logger.java
+@@ -30,6 +30,7 @@ import java.util.concurrent.CopyOnWriteA
+ import java.util.concurrent.CopyOnWriteArrayList;
+ import java.security.*;
+ import java.lang.ref.WeakReference;
++import java.util.logging.LogManager.LoggerContext;
+
+ /**
+ * A Logger object is used to log messages for a specific
+@@ -283,6 +284,26 @@ public class Logger {
+ }
+ }
+
++ // Until all JDK code converted to call sun.util.logging.PlatformLogger
++ // (see 7054233), we need to determine if Logger.getLogger is to add
++ // a system logger or user logger.
++ //
++ // As an interim solution, if the immediate caller whose caller loader is
++ // null, we assume it's a system logger and add it to the system context.
++ private static LoggerContext getLoggerContext() {
++ LogManager manager = LogManager.getLogManager();
++ SecurityManager sm = System.getSecurityManager();
++ if (sm != null) {
++ // 0: Reflection 1: Logger.getLoggerContext 2: Logger.getLogger 3: caller
++ final int SKIP_FRAMES = 3;
++ Class<?> caller = sun.reflect.Reflection.getCallerClass(SKIP_FRAMES);
++ if (caller.getClassLoader() == null) {
++ return manager.getSystemContext();
++ }
++ }
++ return manager.getUserContext();
++ }
++
+ /**
+ * Find or create a logger for a named subsystem. If a logger has
+ * already been created with the given name it is returned. Otherwise
+@@ -324,8 +345,8 @@ public class Logger {
+ // would throw an IllegalArgumentException in the second call
+ // because the wrapper would result in an attempt to replace
+ // the existing "resourceBundleForFoo" with null.
+- LogManager manager = LogManager.getLogManager();
+- return manager.demandLogger(name);
++ LoggerContext context = getLoggerContext();
++ return context.demandLogger(name);
+ }
+
+ /**
+@@ -372,8 +393,8 @@ public class Logger {
+ // Synchronization is not required here. All synchronization for
+ // adding a new Logger object is handled by LogManager.addLogger().
+ public static Logger getLogger(String name, String resourceBundleName) {
+- LogManager manager = LogManager.getLogManager();
+- Logger result = manager.demandLogger(name);
++ LoggerContext context = getLoggerContext();
++ Logger result = context.demandLogger(name, resourceBundleName);
+ if (result.resourceBundleName == null) {
+ // Note: we may get a MissingResourceException here.
+ result.setupResourceInfo(resourceBundleName);
+@@ -384,6 +405,18 @@ public class Logger {
+ return result;
+ }
+
++ // package-private
++ // Add a platform logger to the system context.
++ // i.e. caller of sun.util.logging.PlatformLogger.getLogger
++ static Logger getPlatformLogger(String name) {
++ LogManager manager = LogManager.getLogManager();
++ LoggerContext context = manager.getSystemContext();
++
++ // all loggers in the system context will default to
++ // the system logger's resource bundle
++ Logger result = context.demandLogger(name);
++ return result;
++ }
+
+ /**
+ * Create an anonymous Logger. The newly created Logger is not
+@@ -536,7 +569,7 @@ public class Logger {
+ private void doLog(LogRecord lr) {
+ lr.setLoggerName(name);
+ String ebname = getEffectiveResourceBundleName();
+- if (ebname != null) {
++ if (ebname != null && !ebname.equals(SYSTEM_LOGGER_RB_NAME)) {
+ lr.setResourceBundleName(ebname);
+ lr.setResourceBundle(findResourceBundle(ebname));
+ }
+@@ -1285,6 +1318,22 @@ public class Logger {
+ // May also return null if we can't find the resource bundle and
+ // there is no suitable previous cached value.
+
++ static final String SYSTEM_LOGGER_RB_NAME = "sun.util.logging.resources.logging";
++
++ private static ResourceBundle findSystemResourceBundle(final Locale locale) {
++ // the resource bundle is in a restricted package
++ return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {
++ public ResourceBundle run() {
++ try {
++ return ResourceBundle.getBundle(SYSTEM_LOGGER_RB_NAME,
++ locale);
++ } catch (MissingResourceException e) {
++ throw new InternalError(e.toString());
++ }
++ }
++ });
++ }
++
+ private synchronized ResourceBundle findResourceBundle(String name) {
+ // Return a null bundle for a null name.
+ if (name == null) {
+@@ -1296,6 +1345,13 @@ public class Logger {
+ // Normally we should hit on our simple one entry cache.
+ if (catalog != null && currentLocale == catalogLocale
+ && name == catalogName) {
++ return catalog;
++ }
++
++ if (name.equals(SYSTEM_LOGGER_RB_NAME)) {
++ catalog = findSystemResourceBundle(currentLocale);
++ catalogName = name;
++ catalogLocale = currentLocale;
+ return catalog;
+ }
+
+@@ -1314,7 +1370,6 @@ public class Logger {
+ // Woops. We can't find the ResourceBundle in the default
+ // ClassLoader. Drop through.
+ }
+-
+
+ // Fall back to searching up the call stack and trying each
+ // calling ClassLoader.
+diff --git a/src/share/classes/java/util/logging/Logging.java b/src/share/classes/java/util/logging/Logging.java
+--- a/src/share/classes/java/util/logging/Logging.java
++++ b/src/share/classes/java/util/logging/Logging.java
+@@ -34,15 +34,15 @@ import java.util.ArrayList;
+ *
+ * The <tt>LoggingMXBean</tt> interface provides a standard
+ * method for management access to the individual
+- * java.util.Logger objects available at runtime.
++ * {@code Logger} objects available at runtime.
+ *
+ * @author Ron Mann
+ * @author Mandy Chung
+ * @since 1.5
+ *
+ * @see javax.management
+- * @see java.util.Logger
+- * @see java.util.LogManager
++ * @see Logger
++ * @see LogManager
+ */
+ class Logging implements LoggingMXBean {
+
+@@ -75,7 +75,7 @@ class Logging implements LoggingMXBean {
+ if (level == null) {
+ return EMPTY_STRING;
+ } else {
+- return level.getName();
++ return level.getLevelName();
+ }
+ }
+
+@@ -85,7 +85,6 @@ class Logging implements LoggingMXBean {
+ }
+
+ Logger logger = logManager.getLogger(loggerName);
+-
+ if (logger == null) {
+ throw new IllegalArgumentException("Logger " + loggerName +
+ "does not exist");
+@@ -94,7 +93,10 @@ class Logging implements LoggingMXBean {
+ Level level = null;
+ if (levelName != null) {
+ // parse will throw IAE if logLevel is invalid
+- level = Level.parse(levelName);
++ level = Level.findLevel(levelName);
++ if (level == null) {
++ throw new IllegalArgumentException("Unknown level \"" + levelName + "\"");
++ }
+ }
+
+ logger.setLevel(level);
+diff --git a/src/share/classes/java/util/logging/LoggingProxyImpl.java b/src/share/classes/java/util/logging/LoggingProxyImpl.java
+--- a/src/share/classes/java/util/logging/LoggingProxyImpl.java
++++ b/src/share/classes/java/util/logging/LoggingProxyImpl.java
+@@ -37,7 +37,8 @@ class LoggingProxyImpl implements Loggin
+
+ @Override
+ public Object getLogger(String name) {
+- return Logger.getLogger(name);
++ // always create a platform logger with the resource bundle name
++ return Logger.getPlatformLogger(name);
+ }
+
+ @Override
+@@ -92,12 +93,16 @@ class LoggingProxyImpl implements Loggin
+
+ @Override
+ public Object parseLevel(String levelName) {
+- return Level.parse(levelName);
++ Level level = Level.findLevel(levelName);
++ if (level == null) {
++ throw new IllegalArgumentException("Unknown level \"" + levelName + "\"");
++ }
++ return level;
+ }
+
+ @Override
+ public String getLevelName(Object level) {
+- return ((Level) level).getName();
++ return ((Level) level).getLevelName();
+ }
+
+ @Override
+diff --git a/src/share/classes/java/util/logging/SimpleFormatter.java b/src/share/classes/java/util/logging/SimpleFormatter.java
+--- a/src/share/classes/java/util/logging/SimpleFormatter.java
++++ b/src/share/classes/java/util/logging/SimpleFormatter.java
+@@ -162,7 +162,7 @@ public class SimpleFormatter extends For
+ dat,
+ source,
+ record.getLoggerName(),
+- record.getLevel().getLocalizedName(),
++ record.getLevel().getLocalizedLevelName(),
+ message,
+ throwable);
+ }
+diff --git a/src/share/classes/sun/awt/AppContext.java b/src/share/classes/sun/awt/AppContext.java
+--- a/src/share/classes/sun/awt/AppContext.java
++++ b/src/share/classes/sun/awt/AppContext.java
+@@ -327,19 +327,25 @@ public final class AppContext {
+ // Before we return the main "system" AppContext, check to
+ // see if there's an AWTSecurityManager installed. If so,
+ // allow it to choose the AppContext to return.
+- SecurityManager securityManager = System.getSecurityManager();
+- if ((securityManager != null) &&
+- (securityManager instanceof AWTSecurityManager))
+- {
+- AWTSecurityManager awtSecMgr = (AWTSecurityManager)securityManager;
+- AppContext secAppContext = awtSecMgr.getAppContext();
+- if (secAppContext != null) {
+- appContext = secAppContext; // Return what we're told
+- }
++ AppContext secAppContext = getExecutionAppContext();
++ if (secAppContext != null) {
++ appContext = secAppContext; // Return what we're told
+ }
+ }
+
+ return appContext;
++ }
++
++ private final static AppContext getExecutionAppContext() {
++ SecurityManager securityManager = System.getSecurityManager();
++ if ((securityManager != null) &&
++ (securityManager instanceof AWTSecurityManager))
++ {
++ AWTSecurityManager awtSecMgr = (AWTSecurityManager) securityManager;
++ AppContext secAppContext = awtSecMgr.getAppContext();
++ return secAppContext; // Return what we're told
++ }
++ return null;
+ }
+
+ /**
+@@ -806,6 +812,21 @@ public final class AppContext {
+ public boolean isMainAppContext() {
+ return (numAppContexts == 1);
+ }
++ public Object getContext() {
++ return getAppContext();
++ }
++ public Object getExecutionContext() {
++ return getExecutionAppContext();
++ }
++ public Object get(Object context, Object key) {
++ return ((AppContext)context).get(key);
++ }
++ public void put(Object context, Object key, Object value) {
++ ((AppContext)context).put(key, value);
++ }
++ public void remove(Object context, Object key) {
++ ((AppContext)context).remove(key);
++ }
+ });
+ }
+ }
+diff --git a/src/share/classes/sun/misc/JavaAWTAccess.java b/src/share/classes/sun/misc/JavaAWTAccess.java
+--- a/src/share/classes/sun/misc/JavaAWTAccess.java
++++ b/src/share/classes/sun/misc/JavaAWTAccess.java
+@@ -26,6 +26,14 @@ package sun.misc;
+ package sun.misc;
+
+ public interface JavaAWTAccess {
++ public Object getContext();
++ public Object getExecutionContext();
++
++ public Object get(Object context, Object key);
++ public void put(Object context, Object key, Object value);
++ public void remove(Object context, Object key);
++
++ // convenience methods whose context is the object returned by getContext()
+ public Object get(Object key);
+ public void put(Object key, Object value);
+ public void remove(Object key);
+diff --git a/src/share/lib/security/java.security b/src/share/lib/security/java.security
+--- a/src/share/lib/security/java.security
++++ b/src/share/lib/security/java.security
+@@ -126,6 +126,9 @@ package.access=sun.,\
+ package.access=sun.,\
+ com.sun.xml.internal.,\
+ com.sun.imageio.,\
++ com.sun.istack.internal.,\
++ com.sun.jmx.default.,\
++ com.sun.jmx.remote.util.,\
+ com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.xalan.internal.utils.,\
+ com.sun.org.glassfish.external.,\
+@@ -144,6 +147,9 @@ package.definition=sun.,\
+ package.definition=sun.,\
+ com.sun.xml.internal.,\
+ com.sun.imageio.,\
++ com.sun.istack.internal.,\
++ com.sun.jmx.default.,\
++ com.sun.jmx.remote.util.,\
+ com.sun.org.apache.xerces.internal.utils.,\
+ com.sun.org.apache.xalan.internal.utils.,\
+ com.sun.org.glassfish.external.,\
diff --git a/sec-2013-02-01-7201064.patch b/sec-2013-02-01-7201064.patch
new file mode 100644
index 0000000..4fef618
--- /dev/null
+++ b/sec-2013-02-01-7201064.patch
@@ -0,0 +1,123 @@
+# HG changeset patch
+# User denis
+# Date 1353673652 -14400
+# Node ID 6f9dde55bd49829cf41bd45b766780c2ec7e0bc1
+# Parent 49a37df9e80fae205a7b70d862cd303a62049c2c
+7201064: Better dialogue checking
+Reviewed-by: serb, skoivu
+
+diff --git a/src/share/classes/java/awt/Dialog.java b/src/share/classes/java/awt/Dialog.java
+--- a/src/share/classes/java/awt/Dialog.java
++++ b/src/share/classes/java/awt/Dialog.java
+@@ -39,6 +39,7 @@ import sun.awt.util.IdentityArrayList;
+ import sun.awt.util.IdentityArrayList;
+ import sun.awt.util.IdentityLinkedList;
+ import sun.security.util.SecurityConstants;
++import java.security.AccessControlException;
+
+ /**
+ * A Dialog is a top-level window with a title and a border
+@@ -127,6 +128,8 @@ public class Dialog extends Window {
+ * @since 1.4
+ */
+ boolean undecorated = false;
++
++ private transient boolean initialized = false;
+
+ /**
+ * Modal dialogs block all input to some top-level windows.
+@@ -671,6 +674,7 @@ public class Dialog extends Window {
+ this.title = title;
+ setModalityType(modalityType);
+ SunToolkit.checkAndSetPolicy(this);
++ initialized = true;
+ }
+
+ /**
+@@ -722,6 +726,7 @@ public class Dialog extends Window {
+ this.title = title;
+ setModalityType(modalityType);
+ SunToolkit.checkAndSetPolicy(this);
++ initialized = true;
+ }
+
+ /**
+@@ -851,12 +856,9 @@ public class Dialog extends Window {
+ if (modalityType == type) {
+ return;
+ }
+- if (type == ModalityType.TOOLKIT_MODAL) {
+- SecurityManager sm = System.getSecurityManager();
+- if (sm != null) {
+- sm.checkPermission(SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION);
+- }
+- }
++
++ checkModalityPermission(type);
++
+ modalityType = type;
+ modal = (modalityType != ModalityType.MODELESS);
+ }
+@@ -1025,6 +1027,9 @@ public class Dialog extends Window {
+ */
+ @Deprecated
+ public void show() {
++ if (!initialized) throw new IllegalStateException(
++ "The dialog component has not been initialized properly");
++
+ beforeFirstShow = false;
+ if (!isModal()) {
+ conditionalShow(null, null);
+@@ -1600,18 +1605,50 @@ public class Dialog extends Window {
+ }
+ }
+
++ private void checkModalityPermission(ModalityType mt) {
++ if (mt == ModalityType.TOOLKIT_MODAL) {
++ SecurityManager sm = System.getSecurityManager();
++ if (sm != null) {
++ sm.checkPermission(
++ SecurityConstants.AWT.TOOLKIT_MODALITY_PERMISSION
++ );
++ }
++ }
++ }
++
+ private void readObject(ObjectInputStream s)
+ throws ClassNotFoundException, IOException, HeadlessException
+ {
+ GraphicsEnvironment.checkHeadless();
+- s.defaultReadObject();
++
++ java.io.ObjectInputStream.GetField fields =
++ s.readFields();
++
++ ModalityType localModalityType = (ModalityType)fields.get("modalityType", null);
++
++ try {
++ checkModalityPermission(localModalityType);
++ } catch (AccessControlException ace) {
++ localModalityType = DEFAULT_MODALITY_TYPE;
++ }
+
+ // in 1.5 or earlier modalityType was absent, so use "modal" instead
+- if (modalityType == null) {
++ if (localModalityType == null) {
++ this.modal = fields.get("modal", false);
+ setModal(modal);
+ }
+
++ this.resizable = fields.get("resizable", true);
++ this.undecorated = fields.get("undecorated", false);
++ this.title = (String)fields.get("title", "");
++ this.modalityType = localModalityType;
++
+ blockedWindows = new IdentityArrayList();
++
++ SunToolkit.checkAndSetPolicy(this);
++
++ initialized = true;
++
+ }
+
+ /*
More information about the scm-commits
mailing list