changeset 550:dd8956e41b89

7110687: (tz) java.util.TimeZone.setDefault() should be controlled by a security manager Reviewed-by: okutsu
author coffeys
date Tue, 15 Nov 2011 09:57:58 +0000
parents e11df26be5fc
children ee0f12b18cb8
files make/java/java/FILES_java.gmk src/share/classes/java/util/TimeZone.java src/share/classes/sun/awt/AppContext.java src/share/classes/sun/misc/JavaAWTAccess.java src/share/classes/sun/misc/SharedSecrets.java
diffstat 5 files changed, 130 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/make/java/java/FILES_java.gmk	Fri Nov 11 08:09:54 2011 -0800
+++ b/make/java/java/FILES_java.gmk	Tue Nov 15 09:57:58 2011 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1996, 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
@@ -448,6 +448,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/JavaIODeleteOnExitAccess.java \
--- a/src/share/classes/java/util/TimeZone.java	Fri Nov 11 08:09:54 2011 -0800
+++ b/src/share/classes/java/util/TimeZone.java	Tue Nov 15 09:57:58 2011 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -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;
@@ -542,7 +544,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) {
@@ -633,10 +635,53 @@
         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 = SharedSecrets.getJavaAWTAccess();
+        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 = SharedSecrets.getJavaAWTAccess();
+        if (javaAWTAccess == null) {
+            mainAppContextDefault = tz;
+        } else {
+            if (!javaAWTAccess.isDisposed()) {
+                javaAWTAccess.put(TimeZone.class, tz);
+                if (javaAWTAccess.isMainAppContext()) {
+                    mainAppContextDefault = null;
+                }
+            }
         }
     }
 
@@ -687,12 +732,24 @@
      */
     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;
 
+    /*
+     * Provides access implementation-private methods without using reflection
+     *
+     * 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.
+     */
+    private static JavaAWTAccess javaAWTAccess;
+
+    // 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/src/share/classes/sun/awt/AppContext.java	Fri Nov 11 08:09:54 2011 -0800
+++ b/src/share/classes/sun/awt/AppContext.java	Tue Nov 15 09:57:58 2011 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -767,6 +767,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 MostRecentThreadAppContext {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/misc/JavaAWTAccess.java	Tue Nov 15 09:57:58 2011 +0000
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ *
+ * 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/src/share/classes/sun/misc/SharedSecrets.java	Fri Nov 11 08:09:54 2011 -0800
+++ b/src/share/classes/sun/misc/SharedSecrets.java	Tue Nov 15 09:57:58 2011 +0000
@@ -52,6 +52,7 @@
     private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
     private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess;
     private static JavaSecurityAccess javaSecurityAccess;
+    private static JavaAWTAccess javaAWTAccess;
 
     public static JavaUtilJarAccess javaUtilJarAccess() {
         if (javaUtilJarAccess == null) {
@@ -138,4 +139,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;
+    }
 }