--- 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]);
}