6603256: Startup: Defer initialization of DropTarget's flavorMap
authorson
Thu, 13 Mar 2008 16:32:15 +0300
changeset 109 ddfda358e547
parent 108 deaaed5cedb7
child 110 dc692e475ed0
6603256: Startup: Defer initialization of DropTarget's flavorMap Summary: SystemFlavorMap is lazily initialized now. Reviewed-by: uta
jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java
jdk/src/share/classes/java/awt/dnd/DropTarget.java
--- a/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java	Thu Mar 13 16:27:20 2008 +0300
+++ b/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java	Thu Mar 13 16:32:15 2008 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2008 Sun Microsystems, Inc.  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
@@ -49,7 +49,6 @@
 
 import sun.awt.datatransfer.DataTransferer;
 
-
 /**
  * The SystemFlavorMap is a configurable map between "natives" (Strings), which
  * correspond to platform-specific data formats, and "flavors" (DataFlavors),
@@ -117,16 +116,51 @@
     /**
      * Maps native Strings to Lists of DataFlavors (or base type Strings for
      * text DataFlavors).
+     * Do not use the field directly, use getNativeToFlavor() instead.
      */
     private Map nativeToFlavor = new HashMap();
 
     /**
+     * Accessor to nativeToFlavor map.  Since we use lazy initialization we must
+     * use this accessor instead of direct access to the field which may not be
+     * initialized yet.  This method will initialize the field if needed.
+     *
+     * @return nativeToFlavor
+     */
+    private Map getNativeToFlavor() {
+        if (!isMapInitialized) {
+            initSystemFlavorMap();
+        }
+        return nativeToFlavor;
+    }
+
+    /**
      * Maps DataFlavors (or base type Strings for text DataFlavors) to Lists of
      * native Strings.
+     * Do not use the field directly, use getFlavorToNative() instead.
      */
     private Map flavorToNative = new HashMap();
 
     /**
+     * Accessor to flavorToNative map.  Since we use lazy initialization we must
+     * use this accessor instead of direct access to the field which may not be
+     * initialized yet.  This method will initialize the field if needed.
+     *
+     * @return flavorToNative
+     */
+    private synchronized Map getFlavorToNative() {
+        if (!isMapInitialized) {
+            initSystemFlavorMap();
+        }
+        return flavorToNative;
+    }
+
+    /**
+     * Shows if the object has been initialized.
+     */
+    private boolean isMapInitialized = false;
+
+    /**
      * Caches the result of getNativesForFlavor(). Maps DataFlavors to
      * SoftReferences which reference Lists of String natives.
      */
@@ -169,15 +203,24 @@
         return fm;
     }
 
+    private SystemFlavorMap() {
+    }
+
     /**
-     * Constructs a SystemFlavorMap by reading flavormap.properties and
+     * Initializes a SystemFlavorMap by reading flavormap.properties and
      * AWT.DnD.flavorMapFileURL.
+     * For thread-safety must be called under lock on this.
      */
-    private SystemFlavorMap() {
-        BufferedReader flavormapDotProperties = (BufferedReader)
+    private void initSystemFlavorMap() {
+        if (isMapInitialized) {
+            return;
+        }
+
+        isMapInitialized = true;
+        BufferedReader flavormapDotProperties =
             java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction() {
-                    public Object run() {
+                new java.security.PrivilegedAction<BufferedReader>() {
+                    public BufferedReader run() {
                         String fileName =
                             System.getProperty("java.home") +
                             File.separator +
@@ -197,12 +240,11 @@
                     }
                 });
 
-        BufferedReader flavormapURL = (BufferedReader)
+        BufferedReader flavormapURL =
             java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction() {
-                    public Object run() {
-                        String url = Toolkit.getDefaultToolkit().getProperty
-                            ("AWT.DnD.flavorMapFileURL", null);
+                new java.security.PrivilegedAction<BufferedReader>() {
+                    public BufferedReader run() {
+                        String url = Toolkit.getProperty("AWT.DnD.flavorMapFileURL", null);
 
                         if (url == null) {
                             return null;
@@ -237,7 +279,6 @@
             }
         }
     }
-
     /**
      * Copied code from java.util.Properties. Parsing the data ourselves is the
      * only way to handle duplicate keys and values.
@@ -388,11 +429,11 @@
                     // For text/* flavors, store mappings in separate maps to
                     // enable dynamic mapping generation at a run-time.
                     if ("text".equals(flavor.getPrimaryType())) {
-                        store(value, key, flavorToNative);
-                        store(key, value, nativeToFlavor);
+                        store(value, key, getFlavorToNative());
+                        store(key, value, getNativeToFlavor());
                     } else {
-                        store(flavor, key, flavorToNative);
-                        store(key, flavor, nativeToFlavor);
+                        store(flavor, key, getFlavorToNative());
+                        store(key, flavor, getNativeToFlavor());
                     }
                 }
             }
@@ -494,7 +535,7 @@
      * only if the specified native is encoded as a Java MIME type.
      */
     private List nativeToFlavorLookup(String nat) {
-        List flavors = (List)nativeToFlavor.get(nat);
+        List flavors = (List)getNativeToFlavor().get(nat);
 
         if (nat != null && !disabledMappingGenerationKeys.contains(nat)) {
             DataTransferer transferer = DataTransferer.getInstance();
@@ -530,15 +571,15 @@
 
             if (flavor != null) {
                 flavors = new ArrayList(1);
-                nativeToFlavor.put(nat, flavors);
+                getNativeToFlavor().put(nat, flavors);
                 flavors.add(flavor);
                 getFlavorsForNativeCache.remove(nat);
                 getFlavorsForNativeCache.remove(null);
 
-                List natives = (List)flavorToNative.get(flavor);
+                List natives = (List)getFlavorToNative().get(flavor);
                 if (natives == null) {
                     natives = new ArrayList(1);
-                    flavorToNative.put(flavor, natives);
+                    getFlavorToNative().put(flavor, natives);
                 }
                 natives.add(nat);
                 getNativesForFlavorCache.remove(flavor);
@@ -559,7 +600,7 @@
      */
     private List flavorToNativeLookup(final DataFlavor flav,
                                       final boolean synthesize) {
-        List natives = (List)flavorToNative.get(flav);
+        List natives = (List)getFlavorToNative().get(flav);
 
         if (flav != null && !disabledMappingGenerationKeys.contains(flav)) {
             DataTransferer transferer = DataTransferer.getInstance();
@@ -584,15 +625,15 @@
             if (synthesize) {
                 String encoded = encodeDataFlavor(flav);
                 natives = new ArrayList(1);
-                flavorToNative.put(flav, natives);
+                getFlavorToNative().put(flav, natives);
                 natives.add(encoded);
                 getNativesForFlavorCache.remove(flav);
                 getNativesForFlavorCache.remove(null);
 
-                List flavors = (List)nativeToFlavor.get(encoded);
+                List flavors = (List)getNativeToFlavor().get(encoded);
                 if (flavors == null) {
                     flavors = new ArrayList(1);
-                    nativeToFlavor.put(encoded, flavors);
+                    getNativeToFlavor().put(encoded, flavors);
                 }
                 flavors.add(flav);
                 getFlavorsForNativeCache.remove(encoded);
@@ -645,7 +686,7 @@
         }
 
         if (flav == null) {
-            retval = new ArrayList(nativeToFlavor.keySet());
+            retval = new ArrayList(getNativeToFlavor().keySet());
         } else if (disabledMappingGenerationKeys.contains(flav)) {
             // In this case we shouldn't synthesize a native for this flavor,
             // since its mappings were explicitly specified.
@@ -655,7 +696,7 @@
             // For text/* flavors, flavor-to-native mappings specified in
             // flavormap.properties are stored per flavor's base type.
             if ("text".equals(flav.getPrimaryType())) {
-                retval = (List)flavorToNative.get(flav.mimeType.getBaseType());
+                retval = (List)getFlavorToNative().get(flav.mimeType.getBaseType());
                 if (retval != null) {
                     // To prevent the List stored in the map from modification.
                     retval = new ArrayList(retval);
@@ -663,7 +704,7 @@
             }
 
             // Also include text/plain natives, but don't duplicate Strings
-            List textPlainList = (List)flavorToNative.get(TEXT_PLAIN_BASE_TYPE);
+            List textPlainList = (List)getFlavorToNative().get(TEXT_PLAIN_BASE_TYPE);
 
             if (textPlainList != null && !textPlainList.isEmpty()) {
                 // To prevent the List stored in the map from modification.
@@ -699,7 +740,7 @@
                 }
             }
         } else if (DataTransferer.isFlavorNoncharsetTextType(flav)) {
-            retval = (List)flavorToNative.get(flav.mimeType.getBaseType());
+            retval = (List)getFlavorToNative().get(flav.mimeType.getBaseType());
 
             if (retval == null || retval.isEmpty()) {
                 retval = flavorToNativeLookup(flav, SYNTHESIZE_IF_NOT_FOUND);
@@ -1025,10 +1066,10 @@
             throw new NullPointerException("null arguments not permitted");
         }
 
-        List natives = (List)flavorToNative.get(flav);
+        List natives = (List)getFlavorToNative().get(flav);
         if (natives == null) {
             natives = new ArrayList(1);
-            flavorToNative.put(flav, natives);
+            getFlavorToNative().put(flav, natives);
         } else if (natives.contains(nat)) {
             return;
         }
@@ -1071,7 +1112,7 @@
             throw new NullPointerException("null arguments not permitted");
         }
 
-        flavorToNative.remove(flav);
+        getFlavorToNative().remove(flav);
         for (int i = 0; i < natives.length; i++) {
             addUnencodedNativeForFlavor(flav, natives[i]);
         }
@@ -1105,10 +1146,10 @@
             throw new NullPointerException("null arguments not permitted");
         }
 
-        List flavors = (List)nativeToFlavor.get(nat);
+        List flavors = (List)getNativeToFlavor().get(nat);
         if (flavors == null) {
             flavors = new ArrayList(1);
-            nativeToFlavor.put(nat, flavors);
+            getNativeToFlavor().put(nat, flavors);
         } else if (flavors.contains(flav)) {
             return;
         }
@@ -1150,7 +1191,7 @@
             throw new NullPointerException("null arguments not permitted");
         }
 
-        nativeToFlavor.remove(nat);
+        getNativeToFlavor().remove(nat);
         for (int i = 0; i < flavors.length; i++) {
             addFlavorForUnencodedNative(nat, flavors[i]);
         }
--- a/jdk/src/share/classes/java/awt/dnd/DropTarget.java	Thu Mar 13 16:27:20 2008 +0300
+++ b/jdk/src/share/classes/java/awt/dnd/DropTarget.java	Thu Mar 13 16:32:15 2008 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2008 Sun Microsystems, Inc.  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
@@ -110,7 +110,11 @@
             setActive(act);
         }
 
-        if (fm != null) flavorMap = fm;
+        if (fm != null) {
+            flavorMap = fm;
+        } else {
+            flavorMap = SystemFlavorMap.getDefaultFlavorMap();
+        }
     }
 
     /**
@@ -850,5 +854,5 @@
      * The FlavorMap
      */
 
-    private transient FlavorMap flavorMap = SystemFlavorMap.getDefaultFlavorMap();
+    private transient FlavorMap flavorMap;
 }