# HG changeset patch # User son # Date 1205415135 -10800 # Node ID ddfda358e5472c43b14960cd6a778a0b42da5ee7 # Parent deaaed5cedb777bc1ded7ed8518537a6169dee03 6603256: Startup: Defer initialization of DropTarget's flavorMap Summary: SystemFlavorMap is lazily initialized now. Reviewed-by: uta diff -r deaaed5cedb7 -r ddfda358e547 jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.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() { + 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() { + 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]); } diff -r deaaed5cedb7 -r ddfda358e547 jdk/src/share/classes/java/awt/dnd/DropTarget.java --- 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; }