--- a/jdk/src/share/classes/java/util/TimeZone.java Thu Jul 18 18:52:14 2013 +0100
+++ b/jdk/src/share/classes/java/util/TimeZone.java Fri Jul 19 12:14:34 2013 +0900
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, 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
@@ -39,13 +39,9 @@
package java.util;
import java.io.Serializable;
-import java.lang.ref.SoftReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.time.ZoneId;
-import java.util.concurrent.ConcurrentHashMap;
-import sun.misc.JavaAWTAccess;
-import sun.misc.SharedSecrets;
import sun.security.action.GetPropertyAction;
import sun.util.calendar.ZoneInfo;
import sun.util.calendar.ZoneInfoFile;
@@ -596,11 +592,26 @@
private static native String getSystemGMTOffsetID();
/**
- * Gets the default <code>TimeZone</code> for this host.
- * The source of the default <code>TimeZone</code>
- * may vary with implementation.
- * @return a default <code>TimeZone</code>.
- * @see #setDefault
+ * Gets the default {@code TimeZone} of the Java virtual machine. If the
+ * cached default {@code TimeZone} is available, its clone is returned.
+ * Otherwise, the method takes the following steps to determine the default
+ * time zone.
+ *
+ * <p><ul>
+ * <li>Use the {@code user.timezone} property value as the default
+ * time zone ID if it's available.</li>
+ * <li>Detect the platform time zone ID. The source of the
+ * platform time zone and ID mapping may vary with implementation.</li>
+ * <li>Use {@code GMT} as the last resort if the given or detected
+ * time zone ID is unknown.</li>
+ * </ul>
+ *
+ * <p>The default {@code TimeZone} created from the ID is cached,
+ * and its clone is returned. The {@code user.timezone} property
+ * value is set to the ID upon return.
+ *
+ * @return the default {@code TimeZone}
+ * @see #setDefault(TimeZone)
*/
public static TimeZone getDefault() {
return (TimeZone) getDefaultRef().clone();
@@ -611,14 +622,11 @@
* method doesn't create a clone.
*/
static TimeZone getDefaultRef() {
- TimeZone defaultZone = getDefaultInAppContext();
+ TimeZone defaultZone = defaultTimeZone;
if (defaultZone == null) {
- defaultZone = defaultTimeZone;
- if (defaultZone == null) {
- // Need to initialize the default time zone.
- defaultZone = setDefaultZone();
- assert defaultZone != null;
- }
+ // Need to initialize the default time zone.
+ defaultZone = setDefaultZone();
+ assert defaultZone != null;
}
// Don't clone here.
return defaultZone;
@@ -676,95 +684,27 @@
return tz;
}
- private static boolean hasPermission() {
- boolean hasPermission = true;
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- try {
- sm.checkPermission(new PropertyPermission
- ("user.timezone", "write"));
- } catch (SecurityException e) {
- hasPermission = false;
- }
- }
- return hasPermission;
- }
-
/**
- * Sets the <code>TimeZone</code> that is
- * returned by the <code>getDefault</code> method. If <code>zone</code>
- * is null, reset the default to the value it had originally when the
- * VM first started.
- * @param zone the new default time zone
+ * Sets the {@code TimeZone} that is returned by the {@code getDefault}
+ * method. {@code zone} is cached. If {@code zone} is null, the cached
+ * default {@code TimeZone} is cleared. This method doesn't change the value
+ * of the {@code user.timezone} property.
+ *
+ * @param zone the new default {@code TimeZone}, or null
+ * @throws SecurityException if the security manager's {@code checkPermission}
+ * denies {@code PropertyPermission("user.timezone",
+ * "write")}
* @see #getDefault
+ * @see PropertyPermission
*/
public static void setDefault(TimeZone zone)
{
- if (hasPermission()) {
- synchronized (TimeZone.class) {
- defaultTimeZone = zone;
- setDefaultInAppContext(null);
- }
- } else {
- setDefaultInAppContext(zone);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new PropertyPermission
+ ("user.timezone", "write"));
}
- }
-
- /**
- * 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.
- *
- * 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 TimeZone getDefaultInAppContext() {
- // JavaAWTAccess provides access implementation-private methods without using reflection.
- JavaAWTAccess 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.
- *
- * 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 void setDefaultInAppContext(TimeZone tz) {
- // JavaAWTAccess provides access implementation-private methods without using reflection.
- JavaAWTAccess javaAWTAccess = SharedSecrets.getJavaAWTAccess();
-
- if (javaAWTAccess == null) {
- mainAppContextDefault = tz;
- } else {
- if (!javaAWTAccess.isDisposed()) {
- javaAWTAccess.put(TimeZone.class, tz);
- if (javaAWTAccess.isMainAppContext()) {
- mainAppContextDefault = null;
- }
- }
- }
+ defaultTimeZone = zone;
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/SetDefaultSecurityTest.java Fri Jul 19 12:14:34 2013 +0900
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+/*
+ * @test
+ * @bug 8001029
+ * @summary Make sure that TimeZone.setDefault throws a SecurityException if the
+ * security manager doesn't permit.
+ * @run main/othervm SetDefaultSecurityTest
+ */
+
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+public class SetDefaultSecurityTest {
+ static final TimeZone NOWHERE = new SimpleTimeZone(Integer.MAX_VALUE, "Nowhere");
+
+ public static void main(String[] args) {
+ TimeZone defaultZone = TimeZone.getDefault();
+
+ // Make sure that TimeZone.setDefault works for trusted code
+ TimeZone.setDefault(NOWHERE);
+ if (!NOWHERE.equals(TimeZone.getDefault())) {
+ new RuntimeException("TimeZone.setDefault doesn't work for trusted code.");
+ }
+ // Restore defaultZone
+ TimeZone.setDefault(defaultZone);
+ if (!defaultZone.equals(TimeZone.getDefault())) {
+ new RuntimeException("TimeZone.setDefault doesn't restore defaultZone.");
+ }
+
+ // Install a SecurityManager.
+ System.setSecurityManager(new SecurityManager());
+ try {
+ TimeZone.setDefault(NOWHERE);
+ throw new RuntimeException("TimeZone.setDefault doesn't throw a SecurityException.");
+ } catch (SecurityException se) {
+ // OK
+ }
+ TimeZone tz = TimeZone.getDefault();
+ if (!defaultZone.equals(tz)) {
+ throw new RuntimeException("Default TimeZone changed: " + tz);
+ }
+ }
+}