changeset 4943:752c26f759e3

6351654: (tz) java.util.TimeZone.setDefault() should be controlled by a security manager Reviewed-by: hawtin
author okutsu
date Thu, 20 Oct 2011 16:55:56 +0900
parents beb743497634
children cde3099615e7
files src/share/classes/java/util/TimeZone.java
diffstat 1 files changed, 46 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/TimeZone.java	Mon Sep 26 12:07:08 2011 -0700
+++ b/src/share/classes/java/util/TimeZone.java	Thu Oct 20 16:55:56 2011 +0900
@@ -43,6 +43,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.concurrent.ConcurrentHashMap;
+import sun.awt.AppContext;
 import sun.security.action.GetPropertyAction;
 import sun.util.TimeZoneNameUtility;
 import sun.util.calendar.ZoneInfo;
@@ -615,7 +616,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 +707,49 @@
         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() {
+        if (!hasSetInAppContext) {
+            return null;
+        }
+
+        AppContext ac = AppContext.getAppContext();
+        if (ac != null && !ac.isDisposed()) {
+            return (TimeZone) ac.get(TimeZone.class);
+        }
+        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) {
+        if (!hasSetInAppContext && tz == null) {
+            return;
+        }
+
+        AppContext ac = AppContext.getAppContext();
+        if (ac != null && !ac.isDisposed()) {
+            if (tz != null) {
+                ac.put(TimeZone.class, tz);
+                hasSetInAppContext = true;
+            } else {
+                ac.remove(TimeZone.class);
+            }
         }
     }
 
@@ -760,12 +800,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;
 
+    // true if the default TimeZone has been set in any AppContext
+    private static boolean hasSetInAppContext;
+
     /**
      * 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)