[java-1.7.0-openjdk/f17] Backed out 6664509 and 7201064.patch which cause regressions

Deepak Bhole dbhole at fedoraproject.org
Wed Feb 6 20:13:36 UTC 2013


commit ac9cadb5c043f509188a4a7e337574d7e62f2e3e
Author: Deepak Bhole <dbhole at redhat.com>
Date:   Wed Feb 6 15:09:31 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 6a1449b..63bbf6c 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
@@ -422,6 +422,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
@@ -673,6 +682,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}
 
@@ -1469,6 +1483,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.fc17.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.fc17
 - Updated to 2.3.5
 - Removed unnecessary GENSRCDIR 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