GNU Classpath (0.20) | |
Frames | No Frames |
1: /* SystemFlavorMap.java -- Maps between native flavor names and MIME types. 2: Copyright (C) 2001, 2004 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.awt.datatransfer; 40: 41: import java.util.ArrayList; 42: import java.util.HashMap; 43: import java.util.List; 44: import java.util.Map; 45: import java.util.WeakHashMap; 46: 47: /** 48: * This class maps between native platform type names and DataFlavors. 49: * 50: * XXX - The current implementation does no mapping at all. 51: * 52: * @author Mark Wielaard (mark@klomp.org) 53: * 54: * @since 1.2 55: */ 56: public final class SystemFlavorMap implements FlavorMap, FlavorTable 57: { 58: /** 59: * The map which maps the thread's <code>ClassLoaders</code> to 60: * <code>SystemFlavorMaps</code>. 61: */ 62: private static final Map systemFlavorMaps = new WeakHashMap(); 63: 64: /** 65: * Constant which is used to prefix encode Java MIME types. 66: */ 67: private static final String GNU_JAVA_MIME_PREFIX = "gnu.java:"; 68: 69: /** 70: * This map maps native <code>String</code>s to lists of 71: * <code>DataFlavor</code>s 72: */ 73: private HashMap nativeToFlavorMap = new HashMap(); 74: 75: /** 76: * This map maps <code>DataFlavor</code>s to lists of native 77: * <code>String</code>s 78: */ 79: private HashMap flavorToNativeMap = new HashMap(); 80: 81: /** 82: * Private constructor. 83: */ 84: private SystemFlavorMap () 85: { 86: } 87: 88: /** 89: * Maps the specified <code>DataFlavor</code> objects to the native 90: * data type name. The returned <code>Map</code> has keys that are 91: * the data flavors and values that are strings. The returned map 92: * may be modified. This can be useful for implementing nested mappings. 93: * 94: * @param flavors An array of data flavors to map 95: * or null for all data flavors. 96: * 97: * @return A <code>Map</code> of native data types to data flavors. 98: */ 99: public Map getNativesForFlavors (DataFlavor[] flavors) 100: { 101: return new HashMap(); 102: } 103: 104: /** 105: * Maps the specified native type names to <code>DataFlavor</code>'s. 106: * The returned <code>Map</code> has keys that are strings and values 107: * that are <code>DataFlavor</code>'s. The returned map may be 108: * modified. This can be useful for implementing nested mappings. 109: * 110: * @param natives An array of native types to map 111: * or null for all native types. 112: * 113: * @return A <code>Map</code> of data flavors to native type names. 114: */ 115: public Map getFlavorsForNatives (String[] natives) 116: { 117: return new HashMap(); 118: } 119: 120: /** 121: * Returns the (System)FlavorMap for the current thread's 122: * ClassLoader. 123: */ 124: public static FlavorMap getDefaultFlavorMap () 125: { 126: ClassLoader classLoader = Thread.currentThread() 127: .getContextClassLoader(); 128: 129: //if ContextClassLoader not set, use system default 130: if (classLoader == null) 131: { 132: classLoader = ClassLoader.getSystemClassLoader(); 133: } 134: 135: synchronized(systemFlavorMaps) 136: { 137: FlavorMap map = (FlavorMap) 138: systemFlavorMaps.get(classLoader); 139: if (map == null) 140: { 141: map = new SystemFlavorMap(); 142: systemFlavorMaps.put(classLoader, map); 143: } 144: return map; 145: } 146: } 147: 148: /** 149: * Encodes a MIME type for use as a <code>String</code> native. The format 150: * of an encoded representation of a MIME type is implementation-dependent. 151: * The only restrictions are: 152: * <ul> 153: * <li>The encoded representation is <code>null</code> if and only if the 154: * MIME type <code>String</code> is <code>null</code>.</li> 155: * <li>The encoded representations for two non-<code>null</code> MIME type 156: * <code>String</code>s are equal if and only if these <code>String</code>s 157: * are equal according to <code>String.equals(Object)</code>.</li> 158: * </ul> 159: * <p> 160: * The present implementation of this method returns the specified MIME 161: * type <code>String</code> prefixed with <code>gnu.java:</code>. 162: * 163: * @param mime the MIME type to encode 164: * @return the encoded <code>String</code>, or <code>null</code> if 165: * mimeType is <code>null</code> 166: */ 167: public static String encodeJavaMIMEType (String mime) 168: { 169: if (mime != null) 170: return GNU_JAVA_MIME_PREFIX + mime; 171: else 172: return null; 173: } 174: 175: /** 176: * Encodes a <code>DataFlavor</code> for use as a <code>String</code> 177: * native. The format of an encoded <code>DataFlavor</code> is 178: * implementation-dependent. The only restrictions are: 179: * <ul> 180: * <li>The encoded representation is <code>null</code> if and only if the 181: * specified <code>DataFlavor</code> is <code>null</code> or its MIME type 182: * <code>String</code> is <code>null</code>.</li> 183: * <li>The encoded representations for two non-<code>null</code> 184: * <code>DataFlavor</code>s with non-<code>null</code> MIME type 185: * <code>String</code>s are equal if and only if the MIME type 186: * <code>String</code>s of these <code>DataFlavor</code>s are equal 187: * according to <code>String.equals(Object)</code>.</li> 188: * </ul> 189: * <p> 190: * The present implementation of this method returns the MIME type 191: * <code>String</code> of the specified <code>DataFlavor</code> prefixed 192: * with <code>gnu.java:</code>. 193: * 194: * @param df the <code>DataFlavor</code> to encode 195: * @return the encoded <code>String</code>, or <code>null</code> if 196: * flav is <code>null</code> or has a <code>null</code> MIME type 197: */ 198: public static String encodeDataFlavor (DataFlavor df) 199: { 200: if (df != null) 201: { 202: return encodeJavaMIMEType(df.getMimeType()); 203: } 204: else 205: return null; 206: } 207: 208: /** 209: * Returns true if the native type name can be represented as 210: * a java mime type. Returns <code>false</code> if parameter is 211: * <code>null</code>. 212: */ 213: public static boolean isJavaMIMEType (String name) 214: { 215: return (name != null && name.startsWith(GNU_JAVA_MIME_PREFIX)); 216: } 217: 218: /** 219: * Decodes a <code>String</code> native for use as a Java MIME type. 220: * 221: * @param name the <code>String</code> to decode 222: * @return the decoded Java MIME type, or <code>null</code> if nat 223: * is not an encoded <code>String</code> native 224: */ 225: public static String decodeJavaMIMEType (String name) 226: { 227: if (isJavaMIMEType(name)) 228: { 229: return name.substring(GNU_JAVA_MIME_PREFIX.length()); 230: } 231: else 232: return null; 233: } 234: 235: /** 236: * Returns the data flavor given the native type name 237: * or null when no such data flavor exists. 238: */ 239: public static DataFlavor decodeDataFlavor (String name) 240: throws ClassNotFoundException 241: { 242: String javaMIMEType = decodeJavaMIMEType (name); 243: 244: if (javaMIMEType != null) 245: return new DataFlavor (javaMIMEType); 246: else 247: return null; 248: } 249: 250: /** 251: * Returns a List of <code>DataFlavors</code> to which the specified 252: * <code>String</code> native can be translated by the data transfer 253: * subsystem. The <code>List</code> will be sorted from best 254: * <code>DataFlavor</code> to worst. That is, the first <code>DataFlavor 255: * </code> will best reflect data in the specified native to a Java 256: * application. 257: * <p> 258: * If the specified native is previously unknown to the data transfer 259: * subsystem, and that native has been properly encoded, then invoking 260: * this method will establish a mapping in both directions between the 261: * specified native and a DataFlavor whose MIME type is a decoded 262: * version of the native. 263: */ 264: public List getFlavorsForNative (String nat) 265: { 266: throw new Error ("Not implemented"); 267: } 268: 269: public List getNativesForFlavor (DataFlavor flav) 270: { 271: throw new Error ("Not implemented"); 272: } 273: 274: /** 275: * Adds a mapping from a single <code>String</code> native to a single 276: * <code>DataFlavor</code>. Unlike <code>getFlavorsForNative</code>, the 277: * mapping will only be established in one direction, and the native will 278: * not be encoded. To establish a two-way mapping, call 279: * <code>addUnencodedNativeForFlavor</code> as well. The new mapping will 280: * be of lower priority than any existing mapping. 281: * This method has no effect if a mapping from the specified 282: * <code>String</code> native to the specified or equal 283: * <code>DataFlavor</code> already exists. 284: * 285: * @param nativeStr the <code>String</code> native key for the mapping 286: * @param flavor the <code>DataFlavor</code> value for the mapping 287: * @throws NullPointerException if nat or flav is <code>null</code> 288: * 289: * @see #addUnencodedNativeForFlavor 290: * @since 1.4 291: */ 292: public synchronized void addFlavorForUnencodedNative(String nativeStr, 293: DataFlavor flavor) 294: { 295: if ((nativeStr == null) || (flavor == null)) 296: throw new NullPointerException(); 297: List flavors = (List) nativeToFlavorMap.get(nativeStr); 298: if (flavors == null) 299: { 300: flavors = new ArrayList(); 301: nativeToFlavorMap.put(nativeStr, flavors); 302: } 303: else 304: { 305: if (! flavors.contains(flavor)) 306: flavors.add(flavor); 307: } 308: } 309: 310: /** 311: * Adds a mapping from the specified <code>DataFlavor</code> (and all 312: * <code>DataFlavor</code>s equal to the specified <code>DataFlavor</code>) 313: * to the specified <code>String</code> native. 314: * Unlike <code>getNativesForFlavor</code>, the mapping will only be 315: * established in one direction, and the native will not be encoded. To 316: * establish a two-way mapping, call 317: * <code>addFlavorForUnencodedNative</code> as well. The new mapping will 318: * be of lower priority than any existing mapping. 319: * This method has no effect if a mapping from the specified or equal 320: * <code>DataFlavor</code> to the specified <code>String</code> native 321: * already exists. 322: * 323: * @param flavor the <code>DataFlavor</code> key for the mapping 324: * @param nativeStr the <code>String</code> native value for the mapping 325: * @throws NullPointerException if flav or nat is <code>null</code> 326: * 327: * @see #addFlavorForUnencodedNative 328: * @since 1.4 329: */ 330: public synchronized void addUnencodedNativeForFlavor(DataFlavor flavor, 331: String nativeStr) 332: { 333: if ((nativeStr == null) || (flavor == null)) 334: throw new NullPointerException(); 335: List natives = (List) flavorToNativeMap.get(flavor); 336: if (natives == null) 337: { 338: natives = new ArrayList(); 339: flavorToNativeMap.put(flavor, natives); 340: } 341: else 342: { 343: if (! natives.contains(nativeStr)) 344: natives.add(nativeStr); 345: } 346: } 347: 348: /** 349: * Discards the current mappings for the specified <code>DataFlavor</code> 350: * and all <code>DataFlavor</code>s equal to the specified 351: * <code>DataFlavor</code>, and creates new mappings to the 352: * specified <code>String</code> natives. 353: * Unlike <code>getNativesForFlavor</code>, the mappings will only be 354: * established in one direction, and the natives will not be encoded. To 355: * establish two-way mappings, call <code>setFlavorsForNative</code> 356: * as well. The first native in the array will represent the highest 357: * priority mapping. Subsequent natives will represent mappings of 358: * decreasing priority. 359: * <p> 360: * If the array contains several elements that reference equal 361: * <code>String</code> natives, this method will establish new mappings 362: * for the first of those elements and ignore the rest of them. 363: * <p> 364: * It is recommended that client code not reset mappings established by the 365: * data transfer subsystem. This method should only be used for 366: * application-level mappings. 367: * 368: * @param flavor the <code>DataFlavor</code> key for the mappings 369: * @param natives the <code>String</code> native values for the mappings 370: * @throws NullPointerException if flav or natives is <code>null</code> 371: * or if natives contains <code>null</code> elements 372: * 373: * @see #setFlavorsForNative 374: * @since 1.4 375: */ 376: public synchronized void setNativesForFlavor(DataFlavor flavor, 377: String[] natives) 378: { 379: if ((natives == null) || (flavor == null)) 380: throw new NullPointerException(); 381: 382: flavorToNativeMap.remove(flavor); 383: for (int i = 0; i < natives.length; i++) 384: { 385: addUnencodedNativeForFlavor(flavor, natives[i]); 386: } 387: } 388: 389: /** 390: * Discards the current mappings for the specified <code>String</code> 391: * native, and creates new mappings to the specified 392: * <code>DataFlavor</code>s. Unlike <code>getFlavorsForNative</code>, the 393: * mappings will only be established in one direction, and the natives need 394: * not be encoded. To establish two-way mappings, call 395: * <code>setNativesForFlavor</code> as well. The first 396: * <code>DataFlavor</code> in the array will represent the highest priority 397: * mapping. Subsequent <code>DataFlavor</code>s will represent mappings of 398: * decreasing priority. 399: * <p> 400: * If the array contains several elements that reference equal 401: * <code>DataFlavor</code>s, this method will establish new mappings 402: * for the first of those elements and ignore the rest of them. 403: * <p> 404: * It is recommended that client code not reset mappings established by the 405: * data transfer subsystem. This method should only be used for 406: * application-level mappings. 407: * 408: * @param nativeStr the <code>String</code> native key for the mappings 409: * @param flavors the <code>DataFlavor</code> values for the mappings 410: * @throws NullPointerException if nat or flavors is <code>null</code> 411: * or if flavors contains <code>null</code> elements 412: * 413: * @see #setNativesForFlavor 414: * @since 1.4 415: */ 416: public synchronized void setFlavorsForNative(String nativeStr, 417: DataFlavor[] flavors) 418: { 419: if ((nativeStr == null) || (flavors == null)) 420: throw new NullPointerException(); 421: 422: nativeToFlavorMap.remove(nativeStr); 423: for (int i = 0; i < flavors.length; i++) 424: { 425: addFlavorForUnencodedNative(nativeStr, flavors[i]); 426: } 427: } 428: 429: } // class SystemFlavorMap
GNU Classpath (0.20) |