6351654: Problem with java/classes_util_i18n
authorokutsu
Wed, 14 Dec 2011 11:23:21 +0900
changeset 11896 eb4d5334fccf
parent 11895 77896d5ad69b
child 11897 9e80dbac0293
6351654: Problem with java/classes_util_i18n Reviewed-by: hawtin, coffeys
jdk/make/java/java/FILES_java.gmk
jdk/src/share/classes/java/util/TimeZone.java
jdk/src/share/classes/sun/awt/AppContext.java
jdk/src/share/classes/sun/misc/JavaAWTAccess.java
jdk/src/share/classes/sun/misc/SharedSecrets.java
--- a/jdk/make/java/java/FILES_java.gmk	Thu Nov 17 15:04:46 2011 -0800
+++ b/jdk/make/java/java/FILES_java.gmk	Wed Dec 14 11:23:21 2011 +0900
@@ -475,6 +475,7 @@
     sun/misc/MessageUtils.java \
     sun/misc/GC.java \
     sun/misc/Service.java \
+    sun/misc/JavaAWTAccess.java \
     sun/misc/JavaLangAccess.java \
     sun/misc/JavaIOAccess.java \
     sun/misc/JavaIOFileDescriptorAccess.java \
--- a/jdk/src/share/classes/java/util/TimeZone.java	Thu Nov 17 15:04:46 2011 -0800
+++ b/jdk/src/share/classes/java/util/TimeZone.java	Wed Dec 14 11:23:21 2011 +0900
@@ -43,6 +43,8 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.concurrent.ConcurrentHashMap;
+import sun.misc.SharedSecrets;
+import sun.misc.JavaAWTAccess;
 import sun.security.action.GetPropertyAction;
 import sun.util.TimeZoneNameUtility;
 import sun.util.calendar.ZoneInfo;
@@ -615,7 +617,7 @@
      * method doesn't create a clone.
      */
     static TimeZone getDefaultRef() {
-        TimeZone defaultZone = defaultZoneTL.get();
+        TimeZone defaultZone = getDefaultInAppContext();
         if (defaultZone == null) {
             defaultZone = defaultTimeZone;
             if (defaultZone == null) {
@@ -706,10 +708,65 @@
         if (hasPermission()) {
             synchronized (TimeZone.class) {
                 defaultTimeZone = zone;
-                defaultZoneTL.set(null);
+                setDefaultInAppContext(null);
             }
         } else {
-            defaultZoneTL.set(zone);
+            setDefaultInAppContext(zone);
+        }
+    }
+
+    /**
+     * Returns the default TimeZone in an AppContext if any AppContext
+     * has ever used. null is returned if any AppContext hasn't been
+     * used or if the AppContext doesn't have the default TimeZone.
+     */
+    private synchronized static TimeZone getDefaultInAppContext() {
+        // JavaAWTAccess provides access implementation-private methods without using reflection.
+        JavaAWTAccess javaAWTAccess = SharedSecrets.getJavaAWTAccess();
+
+        // Note that javaAWTAccess may be null if sun.awt.AppContext class hasn't
+        // been loaded. If so, it implies that AWTSecurityManager is not our
+        // SecurityManager and we can use a local static variable.
+        // This works around a build time issue.
+        if (javaAWTAccess == null) {
+            return mainAppContextDefault;
+        } else {
+            if (!javaAWTAccess.isDisposed()) {
+                TimeZone tz = (TimeZone)
+                    javaAWTAccess.get(TimeZone.class);
+                if (tz == null && javaAWTAccess.isMainAppContext()) {
+                    return mainAppContextDefault;
+                } else {
+                    return tz;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Sets the default TimeZone in the AppContext to the given
+     * tz. null is handled special: do nothing if any AppContext
+     * hasn't been used, remove the default TimeZone in the
+     * AppContext otherwise.
+     */
+    private synchronized static void setDefaultInAppContext(TimeZone tz) {
+        // JavaAWTAccess provides access implementation-private methods without using reflection.
+        JavaAWTAccess javaAWTAccess = SharedSecrets.getJavaAWTAccess();
+
+        // Note that javaAWTAccess may be null if sun.awt.AppContext class hasn't
+        // been loaded. If so, it implies that AWTSecurityManager is not our
+        // SecurityManager and we can use a local static variable.
+        // This works around a build time issue.
+        if (javaAWTAccess == null) {
+            mainAppContextDefault = tz;
+        } else {
+            if (!javaAWTAccess.isDisposed()) {
+                javaAWTAccess.put(TimeZone.class, tz);
+                if (javaAWTAccess.isMainAppContext()) {
+                    mainAppContextDefault = null;
+                }
+            }
         }
     }
 
@@ -760,12 +817,13 @@
      */
     private String           ID;
     private static volatile TimeZone defaultTimeZone;
-    private static final InheritableThreadLocal<TimeZone> defaultZoneTL
-                                        = new InheritableThreadLocal<TimeZone>();
 
     static final String         GMT_ID        = "GMT";
     private static final int    GMT_ID_LENGTH = 3;
 
+    // a static TimeZone we can reference if no AppContext is in place
+    private static TimeZone mainAppContextDefault;
+
     /**
      * Parses a custom time zone identifier and returns a corresponding zone.
      * This method doesn't support the RFC 822 time zone format. (e.g., +hhmm)
--- a/jdk/src/share/classes/sun/awt/AppContext.java	Thu Nov 17 15:04:46 2011 -0800
+++ b/jdk/src/share/classes/sun/awt/AppContext.java	Wed Dec 14 11:23:21 2011 +0900
@@ -777,6 +777,27 @@
         }
         return changeSupport.getPropertyChangeListeners(propertyName);
     }
+
+    // Set up JavaAWTAccess in SharedSecrets
+    static {
+        sun.misc.SharedSecrets.setJavaAWTAccess(new sun.misc.JavaAWTAccess() {
+            public Object get(Object key) {
+                return getAppContext().get(key);
+            }
+            public void put(Object key, Object value) {
+                getAppContext().put(key, value);
+            }
+            public void remove(Object key) {
+                getAppContext().remove(key);
+            }
+            public boolean isDisposed() {
+                return getAppContext().isDisposed();
+            }
+            public boolean isMainAppContext() {
+                return (numAppContexts == 1);
+            }
+        });
+    }
 }
 
 final class MostRecentKeyValue {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/misc/JavaAWTAccess.java	Wed Dec 14 11:23:21 2011 +0900
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+public interface JavaAWTAccess {
+    public Object get(Object key);
+    public void put(Object key, Object value);
+    public void remove(Object key);
+    public boolean isDisposed();
+    public boolean isMainAppContext();
+}
--- a/jdk/src/share/classes/sun/misc/SharedSecrets.java	Thu Nov 17 15:04:46 2011 -0800
+++ b/jdk/src/share/classes/sun/misc/SharedSecrets.java	Wed Dec 14 11:23:21 2011 +0900
@@ -51,6 +51,7 @@
     private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
     private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess;
     private static JavaSecurityAccess javaSecurityAccess;
+    private static JavaAWTAccess javaAWTAccess;
 
     public static JavaUtilJarAccess javaUtilJarAccess() {
         if (javaUtilJarAccess == null) {
@@ -139,4 +140,14 @@
         }
         return javaSecurityAccess;
     }
+
+    public static void setJavaAWTAccess(JavaAWTAccess jaa) {
+        javaAWTAccess = jaa;
+    }
+
+    public static JavaAWTAccess getJavaAWTAccess() {
+        // this may return null in which case calling code needs to
+        // provision for.
+        return javaAWTAccess;
+    }
 }