1. /*
  2. * @(#)SystemFlavorMap.java 1.19 00/02/02
  3. *
  4. * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.awt.datatransfer;
  11. import java.awt.Toolkit;
  12. import java.io.File;
  13. import java.io.InputStream;
  14. import java.io.IOException;
  15. import java.net.URL;
  16. import java.net.MalformedURLException;
  17. import java.util.Enumeration;
  18. import java.util.Hashtable;
  19. import java.util.HashMap;
  20. import java.util.WeakHashMap;
  21. import java.util.Map;
  22. import java.util.Properties;
  23. /**
  24. * <p>
  25. * The SystemFlavorMap is an externally configurable map that maps platform native
  26. * type names (strings) to MIME type strings, and also their associated
  27. * DataFlavors.
  28. * </p>
  29. * This map is used by the DnD system to map platform data types to MIME
  30. * types to enable the transfer of objects between Java and the platform via
  31. * the platform DnD System.
  32. * </p>
  33. *
  34. * @version 1.19, 02/02/00
  35. * @since 1.2
  36. *
  37. */
  38. public final class SystemFlavorMap implements FlavorMap {
  39. /**
  40. * constant prefix used to tag Java types converted to native platform type
  41. */
  42. private static String JavaMIME = "JAVA_DATAFLAVOR:";
  43. /*
  44. * system singleton
  45. */
  46. private static final WeakHashMap flavorMaps = new WeakHashMap();
  47. /**
  48. * get the default system implementation
  49. */
  50. public static FlavorMap getDefaultFlavorMap() {
  51. ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
  52. if (contextClassLoader == null)
  53. contextClassLoader = ClassLoader.getSystemClassLoader();
  54. FlavorMap fm;
  55. synchronized(flavorMaps) {
  56. if ((fm = (FlavorMap)flavorMaps.get(contextClassLoader)) == null)
  57. flavorMaps.put(contextClassLoader, fm = new SystemFlavorMap());
  58. }
  59. return fm;
  60. }
  61. /**
  62. * construct a SystemFlavorMap
  63. */
  64. private SystemFlavorMap() {
  65. super();
  66. final Properties defaults[] = {null};
  67. final boolean shouldReturn[]= {false};
  68. java.security.AccessController.doPrivileged(
  69. new java.security.PrivilegedAction() {
  70. public Object run() {
  71. String sep = File.separator;
  72. String home = System.getProperty("java.home");
  73. String deffmURL = "file:" +
  74. home +
  75. sep +
  76. "lib" +
  77. sep +
  78. "flavormap.properties";
  79. try {
  80. defaults[0] = new Properties();
  81. defaults[0].load(((URL)new URL(deffmURL)).openStream());
  82. } catch (Exception e) {
  83. System.err.println("Exception:" + e + " while loading default flavormap.properties file URL:" + deffmURL);
  84. defaults[0] = null;
  85. }
  86. nativeToMIME = new Properties(defaults[0]);
  87. String propURLName = Toolkit.getDefaultToolkit().getProperty("AWT.DnD.flavorMapFileURL", null);
  88. InputStream is = null;
  89. if (propURLName != null) try {
  90. is = ((URL)new URL(propURLName)).openStream();
  91. } catch (MalformedURLException fnfe) {
  92. System.err.println(getClass().getName() + ": Malformed URL for flavormap: " + propURLName);
  93. } catch (IOException ioe) {
  94. System.err.println(getClass().getName() + ": IOException during open of flavormap: " + propURLName);
  95. }
  96. if (is != null) try {
  97. nativeToMIME.load(is);
  98. } catch (IOException ioe) {
  99. System.err.println(getClass().getName() + "IOException during load of flavormap: " + propURLName);
  100. shouldReturn[0] = true;
  101. return null;
  102. }
  103. return null;
  104. }
  105. });
  106. if (shouldReturn[0])
  107. return;
  108. int tsize = nativeToMIME.size() + (defaults[0] != null ? defaults[0].size() : 0);
  109. int size = tsize > 0 ? tsize : 1;
  110. flavorToNative = new HashMap(size);
  111. nativeToFlavor = new HashMap(size);
  112. if (tsize > 0) {
  113. Enumeration e = nativeToMIME.propertyNames();
  114. while (e.hasMoreElements()) {
  115. String natives = (String)e.nextElement();
  116. String mime = (String)nativeToMIME.getProperty(natives);
  117. DataFlavor df = null;
  118. // we try the first form of the constructor to see if
  119. // the Mime Type fully specifies a MIME for a DataFlavor
  120. // if that fails we'll construct using another form that
  121. // enforces a default representation class and HPN
  122. try {
  123. df = new DataFlavor(mime);
  124. } catch (Exception ee) {
  125. try {
  126. df = new DataFlavor(mime, (String)null);
  127. } catch (Exception eee) {
  128. eee.printStackTrace();
  129. continue;
  130. }
  131. }
  132. flavorToNative.put(df.getMimeType(), natives);
  133. nativeToFlavor.put(natives, df);
  134. }
  135. }
  136. }
  137. /**
  138. * map flavors to native data types names
  139. */
  140. public synchronized Map getNativesForFlavors(DataFlavor[] flavors) {
  141. int i;
  142. if (flavors == null) return (Map)flavorToNative.clone();
  143. if (flavors.length == 0) return null;
  144. Map map = new HashMap(flavors.length);
  145. for (i = 0; i < flavors.length; i++) {
  146. DataFlavor df = flavors[i];
  147. String mts = df.getMimeType();
  148. String n = (String)flavorToNative.get(mts);
  149. if (n == null) {
  150. String emts = encodeJavaMIMEType(mts);
  151. map.put(df, emts);
  152. nativeToFlavor.put(emts, df);
  153. flavorToNative.put(mts, emts);
  154. } else {
  155. map.put(df, n);
  156. }
  157. }
  158. return map;
  159. }
  160. /**
  161. * map natives to corresponding flavors
  162. */
  163. public synchronized Map getFlavorsForNatives(String[] natives) {
  164. int nonnull = 0;
  165. int i;
  166. if (natives == null) return (Map)nativeToFlavor.clone();
  167. if (natives.length == 0) return new HashMap();
  168. Map map = new HashMap(natives.length);
  169. for (i = 0; i < natives.length ; i++) {
  170. String n = natives[i];
  171. DataFlavor df = null;
  172. if (isJavaMIMEType(natives[i])) {
  173. String emts = natives[i];
  174. if ((df = (DataFlavor)nativeToFlavor.get(emts)) == null) {
  175. String mts = decodeJavaMIMEType(natives[i]);
  176. try {
  177. df = new DataFlavor(mts);
  178. } catch (Exception e) {
  179. System.err.println("Exception \"" + e.getClass().getName() + ": " + e.getMessage() + "\"while constructing DataFlavor for: " + mts);
  180. df = null;
  181. }
  182. if (df != null) {
  183. nativeToFlavor.put(emts, df);
  184. flavorToNative.put(df.getMimeType(), emts);
  185. }
  186. }
  187. } else df = (DataFlavor)nativeToFlavor.get(n);
  188. if (df != null) map.put(n, df);
  189. }
  190. return map;
  191. }
  192. /**
  193. * @return encode a Java MIMEType for use as a native type name
  194. */
  195. public static String encodeJavaMIMEType(String mimeType) {
  196. return JavaMIME + mimeType;
  197. }
  198. /**
  199. * @return encode a Java MIMEType for use as a native type name
  200. */
  201. public static String encodeDataFlavor(DataFlavor df) {
  202. return JavaMIME + df.getMimeType();
  203. }
  204. /**
  205. * @return if the native type string is an encoded Java MIMEType
  206. */
  207. public static boolean isJavaMIMEType(String atom) {
  208. return atom != null && atom.startsWith(JavaMIME, 0);
  209. }
  210. /**
  211. * @return the decoded Java MIMEType string
  212. */
  213. public static String decodeJavaMIMEType(String atom) {
  214. if (!isJavaMIMEType(atom)) return null;
  215. return atom.substring(JavaMIME.length(), atom.length()).trim();
  216. }
  217. /**
  218. * @return the decoded Java MIMEType as a DataFlavor
  219. */
  220. public static DataFlavor decodeDataFlavor(String atom) throws ClassNotFoundException {
  221. if (!isJavaMIMEType(atom)) return null;
  222. return new DataFlavor(atom.substring(JavaMIME.length(), atom.length()).trim());
  223. }
  224. /*
  225. * fields
  226. */
  227. private Properties nativeToMIME;
  228. private HashMap flavorToNative;
  229. private HashMap nativeToFlavor;
  230. }