1. /*
  2. * @(#)DataFlavor.java 1.75 04/01/13
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt.datatransfer;
  8. import java.awt.Toolkit;
  9. import java.io.*;
  10. import java.nio.*;
  11. import java.util.*;
  12. import sun.awt.datatransfer.DataTransferer;
  13. /**
  14. * Each instance represents the opaque concept of a data format as would
  15. * appear on a clipboard, during drag and drop, or in a file system.
  16. * <p>
  17. * <code>DataFlavor</code> objects are constant and never change once
  18. * instantiated.
  19. * </p>
  20. *
  21. * @version 1.75, 01/13/04
  22. * @author Blake Sullivan
  23. * @author Laurence P. G. Cable
  24. * @author Jeff Dunn
  25. */
  26. public class DataFlavor implements Externalizable, Cloneable {
  27. private static final long serialVersionUID = 8367026044764648243L;
  28. private static final Class ioInputStreamClass = java.io.InputStream.class;
  29. /**
  30. * Tries to load a class from: the bootstrap loader, the system loader,
  31. * the context loader (if one is present) and finally the loader specified.
  32. *
  33. * @param className the name of the class to be loaded
  34. * @param fallback the fallback loader
  35. * @return the class loaded
  36. * @exception ClassNotFoundException if class is not found
  37. */
  38. protected final static Class tryToLoadClass(String className,
  39. ClassLoader fallback)
  40. throws ClassNotFoundException
  41. {
  42. ClassLoader systemClassLoader = (ClassLoader)
  43. java.security.AccessController.doPrivileged(
  44. new java.security.PrivilegedAction() {
  45. public Object run() {
  46. ClassLoader cl = Thread.currentThread().
  47. getContextClassLoader();
  48. return (cl != null)
  49. ? cl
  50. : ClassLoader.getSystemClassLoader();
  51. }
  52. });
  53. try {
  54. return Class.forName(className, true, systemClassLoader);
  55. } catch (ClassNotFoundException e2) {
  56. if (fallback != null) {
  57. return Class.forName(className, true, fallback);
  58. } else {
  59. throw new ClassNotFoundException(className);
  60. }
  61. }
  62. }
  63. /*
  64. * private initializer
  65. */
  66. static private DataFlavor createConstant(Class rc, String prn) {
  67. try {
  68. return new DataFlavor(rc, prn);
  69. } catch (Exception e) {
  70. return null;
  71. }
  72. }
  73. /*
  74. * private initializer
  75. */
  76. static private DataFlavor createConstant(String mt, String prn) {
  77. try {
  78. return new DataFlavor(mt, prn);
  79. } catch (Exception e) {
  80. return null;
  81. }
  82. }
  83. /**
  84. * The <code>DataFlavor</code> representing a Java Unicode String class,
  85. * where:
  86. * <pre>
  87. * representationClass = java.lang.String
  88. * mimeType = "application/x-java-serialized-object"
  89. * </pre>
  90. */
  91. public static final DataFlavor stringFlavor = createConstant(java.lang.String.class, "Unicode String");
  92. /**
  93. * The <code>DataFlavor</code> representing a Java Image class,
  94. * where:
  95. * <pre>
  96. * representationClass = java.awt.Image
  97. * mimeType = "image/x-java-image"
  98. * </pre>
  99. */
  100. public static final DataFlavor imageFlavor = createConstant("image/x-java-image; class=java.awt.Image", "Image");
  101. /**
  102. * The <code>DataFlavor</code> representing plain text with Unicode
  103. * encoding, where:
  104. * <pre>
  105. * representationClass = InputStream
  106. * mimeType = "text/plain; charset=unicode"
  107. * </pre>
  108. * This <code>DataFlavor</code> has been <b>deprecated</b> because
  109. * (1) Its representation is an InputStream, an 8-bit based representation,
  110. * while Unicode is a 16-bit character set; and (2) The charset "unicode"
  111. * is not well-defined. "unicode" implies a particular platform's
  112. * implementation of Unicode, not a cross-platform implementation.
  113. *
  114. * @deprecated as of 1.3. Use <code>DataFlavor.getReaderForText(
  115. * Transferable)</code> instead of <code>Transferable.
  116. * getTransferData(DataFlavor.plainTextFlavor)</code>.
  117. */
  118. public static final DataFlavor plainTextFlavor = createConstant("text/plain; charset=unicode; class=java.io.InputStream", "Plain Text");
  119. /**
  120. * A MIME Content-Type of application/x-java-serialized-object represents
  121. * a graph of Java object(s) that have been made persistent.
  122. *
  123. * The representation class associated with this <code>DataFlavor</code>
  124. * identifies the Java type of an object returned as a reference
  125. * from an invocation <code>java.awt.datatransfer.getTransferData</code>.
  126. *
  127. */
  128. public static final String javaSerializedObjectMimeType = "application/x-java-serialized-object";
  129. /**
  130. * To transfer a list of files to/from Java (and the underlying
  131. * platform) a <code>DataFlavor</code> of this type/subtype and
  132. * representation class of <code>java.util.List</code> is used.
  133. * Each element of the list is required/guaranteed to be of type
  134. * <code>java.io.File</code>.
  135. */
  136. public static final DataFlavor javaFileListFlavor = createConstant("application/x-java-file-list;class=java.util.List", null);
  137. /**
  138. * To transfer a reference to an arbitrary Java object reference that
  139. * has no associated MIME Content-type, across a <code>Transferable</code>
  140. * interface WITHIN THE SAME JVM, a <code>DataFlavor</code>
  141. * with this type/subtype is used, with a <code>representationClass</code>
  142. * equal to the type of the class/interface being passed across the
  143. * <code>Transferble</code>.
  144. * <p>
  145. * The object reference returned from
  146. * <code>Transferable.getTransferData</code> for a <code>DataFlavor</code>
  147. * with this MIME Content-Type is required to be
  148. * an instance of the representation Class of the <code>DataFlavor</code>.
  149. */
  150. public static final String javaJVMLocalObjectMimeType = "application/x-java-jvm-local-objectref";
  151. /**
  152. * In order to pass a live link to a Remote object via a Drag and Drop
  153. * <code>ACTION_LINK</code> operation a Mime Content Type of
  154. * application/x-java-remote-object should be used,
  155. * where the representation class of the <code>DataFlavor</code>
  156. * represents the type of the <code>Remote</code> interface to be
  157. * transferred.
  158. */
  159. public static final String javaRemoteObjectMimeType = "application/x-java-remote-object";
  160. /**
  161. * Constructs a new <code>DataFlavor</code>. This constructor is
  162. * provided only for the purpose of supporting the
  163. * <code>Externalizable</code> interface. It is not
  164. * intended for public (client) use.
  165. *
  166. * @since 1.2
  167. */
  168. public DataFlavor() {
  169. super();
  170. }
  171. /**
  172. * Constructs a fully specified <code>DataFlavor</code>.
  173. *
  174. * @exception NullPointerException if either <code>primaryType</code>,
  175. * <code>subType</code> or <code>representationClass</code> is null
  176. */
  177. private DataFlavor(String primaryType, String subType, MimeTypeParameterList params, Class representationClass, String humanPresentableName) {
  178. super();
  179. if (primaryType == null) {
  180. throw new NullPointerException("primaryType");
  181. }
  182. if (subType == null) {
  183. throw new NullPointerException("subType");
  184. }
  185. if (representationClass == null) {
  186. throw new NullPointerException("representationClass");
  187. }
  188. if (params == null) params = new MimeTypeParameterList();
  189. params.set("class", representationClass.getName());
  190. if (humanPresentableName == null) {
  191. humanPresentableName = (String)params.get("humanPresentableName");
  192. if (humanPresentableName == null)
  193. humanPresentableName = primaryType + "/" + subType;
  194. }
  195. try {
  196. mimeType = new MimeType(primaryType, subType, params);
  197. } catch (MimeTypeParseException mtpe) {
  198. throw new IllegalArgumentException("MimeType Parse Exception: " + mtpe.getMessage());
  199. }
  200. this.representationClass = representationClass;
  201. this.humanPresentableName = humanPresentableName;
  202. mimeType.removeParameter("humanPresentableName");
  203. }
  204. /**
  205. * Constructs a <code>DataFlavor</code> that represents a Java class.
  206. * <p>
  207. * The returned <code>DataFlavor</code> will have the following
  208. * characteristics:
  209. * <pre>
  210. * representationClass = representationClass
  211. * mimeType = application/x-java-serialized-object
  212. * </pre>
  213. * @param representationClass the class used to transfer data in this flavor
  214. * @param humanPresentableName the human-readable string used to identify
  215. * this flavor; if this parameter is <code>null</code>
  216. * then the value of the the MIME Content Type is used
  217. * @exception NullPointerException if <code>representationClass</code> is null
  218. */
  219. public DataFlavor(Class representationClass, String humanPresentableName) {
  220. this("application", "x-java-serialized-object", null, representationClass, humanPresentableName);
  221. if (representationClass == null) {
  222. throw new NullPointerException("representationClass");
  223. }
  224. }
  225. /**
  226. * Constructs a <code>DataFlavor</code> that represents a
  227. * <code>MimeType</code>.
  228. * <p>
  229. * The returned <code>DataFlavor</code> will have the following
  230. * characteristics:
  231. * <p>
  232. * If the <code>mimeType</code> is
  233. * "application/x-java-serialized-object; class=<representation class>",
  234. * the result is the same as calling
  235. * <code>new DataFlavor(Class:forName(<representation class>)</code>.
  236. * <p>
  237. * Otherwise:
  238. * <pre>
  239. * representationClass = InputStream
  240. * mimeType = mimeType
  241. * </pre>
  242. * @param mimeType the string used to identify the MIME type for this flavor;
  243. * if the the <code>mimeType</code> does not specify a
  244. * "class=" parameter, or if the class is not successfully
  245. * loaded, then an <code>IllegalArgumentException</code>
  246. * is thrown
  247. * @param humanPresentableName the human-readable string used to identify
  248. * this flavor; if this parameter is <code>null</code>
  249. * then the value of the the MIME Content Type is used
  250. * @exception IllegalArgumentException if <code>mimeType</code> is
  251. * invalid or if the class is not successfully loaded
  252. * @exception NullPointerException if <code>mimeType</code> is null
  253. */
  254. public DataFlavor(String mimeType, String humanPresentableName) {
  255. super();
  256. if (mimeType == null) {
  257. throw new NullPointerException("mimeType");
  258. }
  259. try {
  260. initialize(mimeType, humanPresentableName, this.getClass().getClassLoader());
  261. } catch (MimeTypeParseException mtpe) {
  262. throw new IllegalArgumentException("failed to parse:" + mimeType);
  263. } catch (ClassNotFoundException cnfe) {
  264. throw new IllegalArgumentException("can't find specified class: " + cnfe.getMessage());
  265. }
  266. }
  267. /**
  268. * Constructs a <code>DataFlavor</code> that represents a
  269. * <code>MimeType</code>.
  270. * <p>
  271. * The returned <code>DataFlavor</code> will have the following
  272. * characteristics:
  273. * <p>
  274. * If the mimeType is
  275. * "application/x-java-serialized-object; class=<representation class>",
  276. * the result is the same as calling
  277. * <code>new DataFlavor(Class:forName(<representation class>)</code>.
  278. * <p>
  279. * Otherwise:
  280. * <pre>
  281. * representationClass = InputStream
  282. * mimeType = mimeType
  283. * </pre>
  284. * @param mimeType the string used to identify the MIME type for this flavor
  285. * @param humanPresentableName the human-readable string used to
  286. * identify this flavor
  287. * @param classLoader the class loader to use
  288. * @exception ClassNotFoundException if the class is not loaded
  289. * @exception IllegalArgumentException if <code>mimeType</code> is
  290. * invalid
  291. * @exception NullPointerException if <code>mimeType</code> is null
  292. */
  293. public DataFlavor(String mimeType, String humanPresentableName, ClassLoader classLoader) throws ClassNotFoundException {
  294. super();
  295. if (mimeType == null) {
  296. throw new NullPointerException("mimeType");
  297. }
  298. try {
  299. initialize(mimeType, humanPresentableName, classLoader);
  300. } catch (MimeTypeParseException mtpe) {
  301. throw new IllegalArgumentException("failed to parse:" + mimeType);
  302. }
  303. }
  304. /**
  305. * Constructs a <code>DataFlavor</code> from a <code>mimeType</code> string.
  306. * The string can specify a "class=<fully specified Java class name>"
  307. * parameter to create a <code>DataFlavor</code> with the desired
  308. * representation class. If the string does not contain "class=" parameter,
  309. * <code>java.io.InputStream</code> is used as default.
  310. *
  311. * @param mimeType the string used to identify the MIME type for this flavor;
  312. * if the class specified by "class=" parameter is not
  313. * successfully loaded, then an
  314. * <code>ClassNotFoundException</code> is thrown
  315. * @exception ClassNotFoundException if the class is not loaded
  316. * @exception IllegalArgumentException if <code>mimeType</code> is
  317. * invalid
  318. * @exception NullPointerException if <code>mimeType</code> is null
  319. */
  320. public DataFlavor(String mimeType) throws ClassNotFoundException {
  321. super();
  322. if (mimeType == null) {
  323. throw new NullPointerException("mimeType");
  324. }
  325. try {
  326. initialize(mimeType, null, this.getClass().getClassLoader());
  327. } catch (MimeTypeParseException mtpe) {
  328. throw new IllegalArgumentException("failed to parse:" + mimeType);
  329. }
  330. }
  331. /**
  332. * Common initialization code called from various constructors.
  333. *
  334. * @param mimeType the MIME Content Type (must have a class= param)
  335. * @param humanPresentableName the human Presentable Name or
  336. * <code>null</code>
  337. * @param classLoader the fallback class loader to resolve against
  338. *
  339. * @throws MimeTypeParseException
  340. * @throws ClassNotFoundException
  341. * @throws NullPointerException if <code>mimeType</code> is null
  342. *
  343. * @see tryToLoadClass
  344. */
  345. private void initialize(String mimeType, String humanPresentableName, ClassLoader classLoader) throws MimeTypeParseException, ClassNotFoundException {
  346. if (mimeType == null) {
  347. throw new NullPointerException("mimeType");
  348. }
  349. this.mimeType = new MimeType(mimeType); // throws
  350. String rcn = getParameter("class");
  351. if (rcn == null) {
  352. if ("application/x-java-serialized-object".equals(this.mimeType.getBaseType()))
  353. throw new IllegalArgumentException("no representation class specified for:" + mimeType);
  354. else
  355. representationClass = java.io.InputStream.class; // default
  356. } else { // got a class name
  357. representationClass = DataFlavor.tryToLoadClass(rcn, classLoader);
  358. }
  359. this.mimeType.setParameter("class", representationClass.getName());
  360. if (humanPresentableName == null) {
  361. humanPresentableName = this.mimeType.getParameter("humanPresentableName");
  362. if (humanPresentableName == null)
  363. humanPresentableName = this.mimeType.getPrimaryType() + "/" + this.mimeType.getSubType();
  364. }
  365. this.humanPresentableName = humanPresentableName; // set it.
  366. this.mimeType.removeParameter("humanPresentableName"); // just in case
  367. }
  368. /**
  369. * String representation of this <code>DataFlavor</code> and its
  370. * parameters. The resulting <code>String</code> contains the name of
  371. * the <code>DataFlavor</code> class, this flavor's MIME type, and its
  372. * representation class. If this flavor has a primary MIME type of "text",
  373. * supports the charset parameter, and has an encoded representation, the
  374. * flavor's charset is also included. See <code>selectBestTextFlavor</code>
  375. * for a list of text flavors which support the charset parameter.
  376. *
  377. * @return string representation of this <code>DataFlavor</code>
  378. * @see #selectBestTextFlavor
  379. */
  380. public String toString() {
  381. String string = getClass().getName();
  382. string += "["+paramString()+"]";
  383. return string;
  384. }
  385. private String paramString() {
  386. String params = "";
  387. params += "mimetype=";
  388. if (mimeType == null) {
  389. params += "null";
  390. } else {
  391. params += mimeType.getBaseType();
  392. }
  393. params += ";representationclass=";
  394. if (representationClass == null) {
  395. params += "null";
  396. } else {
  397. params += representationClass.getName();
  398. }
  399. if (DataTransferer.isFlavorCharsetTextType(this) &&
  400. (isRepresentationClassInputStream() ||
  401. isRepresentationClassByteBuffer() ||
  402. DataTransferer.byteArrayClass.equals(representationClass)))
  403. {
  404. params += ";charset=" + DataTransferer.getTextCharset(this);
  405. }
  406. return params;
  407. }
  408. /**
  409. * Returns a <code>DataFlavor</code> representing plain text with Unicode
  410. * encoding, where:
  411. * <pre>
  412. * representationClass = java.io.InputStream
  413. * mimeType = "text/plain;
  414. * charset=<platform default Unicode encoding>"
  415. * </pre>
  416. * Sun's implementation for Microsoft Windows use the encoding <code>utf-16le</code>.
  417. * Sun's implementation for Solaris and Linux use the encoding
  418. * <code>iso-10646-ucs-2</code>.
  419. *
  420. * @return a <code>DataFlavor</code> representing plain text
  421. * with Unicode encoding
  422. */
  423. public static final DataFlavor getTextPlainUnicodeFlavor() {
  424. String encoding = null;
  425. DataTransferer transferer = DataTransferer.getInstance();
  426. if (transferer != null) {
  427. encoding = transferer.getDefaultUnicodeEncoding();
  428. }
  429. return new DataFlavor(
  430. "text/plain;charset="+encoding
  431. +";class=java.io.InputStream", "Plain Text");
  432. }
  433. /**
  434. * Selects the best text <code>DataFlavor</code> from an array of <code>
  435. * DataFlavor</code>s. Only <code>DataFlavor.stringFlavor</code>, and
  436. * equivalent flavors, and flavors that have a primary MIME type of "text",
  437. * are considered for selection.
  438. * <p>
  439. * Flavors are first sorted by their MIME types in the following order:
  440. * <ul>
  441. * <li>"text/sgml"
  442. * <li>"text/xml"
  443. * <li>"text/html"
  444. * <li>"text/rtf"
  445. * <li>"text/enriched"
  446. * <li>"text/richtext"
  447. * <li>"text/uri-list"
  448. * <li>"text/tab-separated-values"
  449. * <li>"text/t140"
  450. * <li>"text/rfc822-headers"
  451. * <li>"text/parityfec"
  452. * <li>"text/directory"
  453. * <li>"text/css"
  454. * <li>"text/calendar"
  455. * <li>"application/x-java-serialized-object"
  456. * <li>"text/plain"
  457. * <li>"text/<other>"
  458. * </ul>
  459. * <p>For example, "text/sgml" will be selected over
  460. * "text/html", and <code>DataFlavor.stringFlavor</code> will be chosen
  461. * over <code>DataFlavor.plainTextFlavor</code>.
  462. * <p>
  463. * If two or more flavors share the best MIME type in the array, then that
  464. * MIME type will be checked to see if it supports the charset parameter.
  465. * <p>
  466. * The following MIME types support, or are treated as though they support,
  467. * the charset parameter:
  468. * <ul>
  469. * <li>"text/sgml"
  470. * <li>"text/xml"
  471. * <li>"text/html"
  472. * <li>"text/enriched"
  473. * <li>"text/richtext"
  474. * <li>"text/uri-list"
  475. * <li>"text/directory"
  476. * <li>"text/css"
  477. * <li>"text/calendar"
  478. * <li>"application/x-java-serialized-object"
  479. * <li>"text/plain"
  480. * </ul>
  481. * The following MIME types do not support, or are treated as though they
  482. * do not support, the charset parameter:
  483. * <ul>
  484. * <li>"text/rtf"
  485. * <li>"text/tab-separated-values"
  486. * <li>"text/t140"
  487. * <li>"text/rfc822-headers"
  488. * <li>"text/parityfec"
  489. * </ul>
  490. * For "text/<other>" MIME types, the first time the JRE needs to
  491. * determine whether the MIME type supports the charset parameter, it will
  492. * check whether the parameter is explicitly listed in an arbitrarily
  493. * chosen <code>DataFlavor</code> which uses that MIME type. If so, the JRE
  494. * will assume from that point on that the MIME type supports the charset
  495. * parameter and will not check again. If the parameter is not explicitly
  496. * listed, the JRE will assume from that point on that the MIME type does
  497. * not support the charset parameter and will not check again. Because
  498. * this check is performed on an arbitrarily chosen
  499. * <code>DataFlavor</code>, developers must ensure that all
  500. * <code>DataFlavor</code>s with a "text/<other>" MIME type specify
  501. * the charset parameter if it is supported by that MIME type. Developers
  502. * should never rely on the JRE to substitute the platform's default
  503. * charset for a "text/<other>" DataFlavor. Failure to adhere to this
  504. * restriction will lead to undefined behavior.
  505. * <p>
  506. * If the best MIME type in the array does not support the charset
  507. * parameter, the flavors which share that MIME type will then be sorted by
  508. * their representation classes in the following order:
  509. * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
  510. * <code>[B</code>, <all others>.
  511. * <p>
  512. * If two or more flavors share the best representation class, or if no
  513. * flavor has one of the three specified representations, then one of those
  514. * flavors will be chosen non-deterministically.
  515. * <p>
  516. * If the best MIME type in the array does support the charset parameter,
  517. * the flavors which share that MIME type will then be sorted by their
  518. * representation classes in the following order:
  519. * <code>java.io.Reader</code>, <code>java.lang.String</code>,
  520. * <code>java.nio.CharBuffer</code>, <code>[C</code>, <all others>.
  521. * <p>
  522. * If two or more flavors share the best representation class, and that
  523. * representation is one of the four explicitly listed, then one of those
  524. * flavors will be chosen non-deterministically. If, however, no flavor has
  525. * one of the four specified representations, the flavors will then be
  526. * sorted by their charsets. Unicode charsets, such as "UTF-16", "UTF-8",
  527. * "UTF-16BE", "UTF-16LE", and their aliases, are considered best. After
  528. * them, the platform default charset and its aliases are selected.
  529. * "US-ASCII" and its aliases are worst. All other charsets are chosen in
  530. * alphabetical order, but only charsets supported by this implementation
  531. * of the Java platform will be considered.
  532. * <p>
  533. * If two or more flavors share the best charset, the flavors will then
  534. * again be sorted by their representation classes in the following order:
  535. * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
  536. * <code>[B</code>, <all others>.
  537. * <p>
  538. * If two or more flavors share the best representation class, or if no
  539. * flavor has one of the three specified representations, then one of those
  540. * flavors will be chosen non-deterministically.
  541. *
  542. * @param availableFlavors an array of available <code>DataFlavor</code>s
  543. * @return the best (highest fidelity) flavor according to the rules
  544. * specified above, or <code>null</code>,
  545. * if <code>availableFlavors</code> is <code>null</code>,
  546. * has zero length, or contains no text flavors
  547. * @since 1.3
  548. */
  549. public static final DataFlavor selectBestTextFlavor(
  550. DataFlavor[] availableFlavors) {
  551. if (availableFlavors == null || availableFlavors.length == 0) {
  552. return null;
  553. }
  554. if (textFlavorComparator == null) {
  555. textFlavorComparator = new TextFlavorComparator();
  556. }
  557. DataFlavor bestFlavor =
  558. (DataFlavor)Collections.max(Arrays.asList(availableFlavors),
  559. textFlavorComparator);
  560. if (!bestFlavor.isFlavorTextType()) {
  561. return null;
  562. }
  563. return bestFlavor;
  564. }
  565. private static Comparator textFlavorComparator;
  566. static class TextFlavorComparator
  567. extends DataTransferer.DataFlavorComparator {
  568. /**
  569. * Compares two <code>DataFlavor</code> objects. Returns a negative
  570. * integer, zero, or a positive integer as the first
  571. * <code>DataFlavor</code> is worse than, equal to, or better than the
  572. * second.
  573. * <p>
  574. * <code>DataFlavor</code>s are ordered according to the rules outlined
  575. * for <code>selectBestTextFlavor</code>.
  576. *
  577. * @param obj1 the first <code>DataFlavor</code> to be compared
  578. * @param obj2 the second <code>DataFlavor</code> to be compared
  579. * @return a negative integer, zero, or a positive integer as the first
  580. * argument is worse, equal to, or better than the second
  581. * @throws ClassCastException if either of the arguments is not an
  582. * instance of <code>DataFlavor</code>
  583. * @throws NullPointerException if either of the arguments is
  584. * <code>null</code>
  585. *
  586. * @see #selectBestTextFlavor
  587. */
  588. public int compare(Object obj1, Object obj2) {
  589. DataFlavor flavor1 = (DataFlavor)obj1;
  590. DataFlavor flavor2 = (DataFlavor)obj2;
  591. if (flavor1.isFlavorTextType()) {
  592. if (flavor2.isFlavorTextType()) {
  593. return super.compare(obj1, obj2);
  594. } else {
  595. return 1;
  596. }
  597. } else if (flavor2.isFlavorTextType()) {
  598. return -1;
  599. } else {
  600. return 0;
  601. }
  602. }
  603. }
  604. /**
  605. * Gets a Reader for a text flavor, decoded, if necessary, for the expected
  606. * charset (encoding). The supported representation classes are
  607. * <code>java.io.Reader</code>, <code>java.lang.String</code>,
  608. * <code>java.nio.CharBuffer</code>, <code>[C</code>,
  609. * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
  610. * and <code>[B</code>.
  611. * <p>
  612. * Because text flavors which do not support the charset parameter are
  613. * encoded in a non-standard format, this method should not be called for
  614. * such flavors. However, in order to maintain backward-compatibility,
  615. * if this method is called for such a flavor, this method will treat the
  616. * flavor as though it supports the charset parameter and attempt to
  617. * decode it accordingly. See <code>selectBestTextFlavor</code> for a list
  618. * of text flavors which do not support the charset parameter.
  619. *
  620. * @param transferable the <code>Transferable</code> whose data will be
  621. * requested in this flavor
  622. *
  623. * @return a <code>Reader</code> to read the <code>Transferable</code>'s
  624. * data
  625. *
  626. * @exception IllegalArgumentException if the representation class
  627. * is not one of the seven listed above
  628. * @exception IllegalArgumentException if the <code>Transferable</code>
  629. * has <code>null</code> data
  630. * @exception NullPointerException if the <code>Transferable</code> is
  631. * <code>null</code>
  632. * @exception UnsupportedEncodingException if this flavor's representation
  633. * is <code>java.io.InputStream</code>,
  634. * <code>java.nio.ByteBuffer</code>, or <code>[B</code> and
  635. * this flavor's encoding is not supported by this
  636. * implementation of the Java platform
  637. * @exception UnsupportedFlavorException if the <code>Transferable</code>
  638. * does not support this flavor
  639. * @exception IOException if the data cannot be read because of an
  640. * I/O error
  641. * @see #selectBestTextFlavor
  642. * @since 1.3
  643. */
  644. public Reader getReaderForText(Transferable transferable)
  645. throws UnsupportedFlavorException, IOException
  646. {
  647. Object transferObject = transferable.getTransferData(this);
  648. if (transferObject == null) {
  649. throw new IllegalArgumentException
  650. ("getTransferData() returned null");
  651. }
  652. if (transferObject instanceof Reader) {
  653. return (Reader)transferObject;
  654. } else if (transferObject instanceof String) {
  655. return new StringReader((String)transferObject);
  656. } else if (transferObject instanceof CharBuffer) {
  657. CharBuffer buffer = (CharBuffer)transferObject;
  658. int size = buffer.remaining();
  659. char[] chars = new char[size];
  660. buffer.get(chars, 0, size);
  661. return new CharArrayReader(chars);
  662. } else if (transferObject instanceof char[]) {
  663. return new CharArrayReader((char[])transferObject);
  664. }
  665. InputStream stream = null;
  666. if (transferObject instanceof InputStream) {
  667. stream = (InputStream)transferObject;
  668. } else if (transferObject instanceof ByteBuffer) {
  669. ByteBuffer buffer = (ByteBuffer)transferObject;
  670. int size = buffer.remaining();
  671. byte[] bytes = new byte[size];
  672. buffer.get(bytes, 0, size);
  673. stream = new ByteArrayInputStream(bytes);
  674. } else if (transferObject instanceof byte[]) {
  675. stream = new ByteArrayInputStream((byte[])transferObject);
  676. }
  677. if (stream == null) {
  678. throw new IllegalArgumentException("transfer data is not Reader, String, CharBuffer, char array, InputStream, ByteBuffer, or byte array");
  679. }
  680. String encoding = getParameter("charset");
  681. return (encoding == null)
  682. ? new InputStreamReader(stream)
  683. : new InputStreamReader(stream, encoding);
  684. }
  685. /**
  686. * Returns the MIME type string for this <code>DataFlavor</code>.
  687. * @return the MIME type string for this flavor
  688. */
  689. public String getMimeType() {
  690. return (mimeType != null) ? mimeType.toString() : null;
  691. }
  692. /**
  693. * Returns the <code>Class</code> which objects supporting this
  694. * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
  695. * is requested.
  696. * @return the <code>Class</code> which objects supporting this
  697. * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
  698. * is requested
  699. */
  700. public Class getRepresentationClass() {
  701. return representationClass;
  702. }
  703. /**
  704. * Returns the human presentable name for the data format that this
  705. * <code>DataFlavor</code> represents. This name would be localized
  706. * for different countries.
  707. * @return the human presentable name for the data format that this
  708. * <code>DataFlavor</code> represents
  709. */
  710. public String getHumanPresentableName() {
  711. return humanPresentableName;
  712. }
  713. /**
  714. * Returns the primary MIME type for this <code>DataFlavor</code>.
  715. * @return the primary MIME type of this <code>DataFlavor</code>
  716. */
  717. public String getPrimaryType() {
  718. return (mimeType != null) ? mimeType.getPrimaryType() : null;
  719. }
  720. /**
  721. * Returns the sub MIME type of this <code>DataFlavor</code>.
  722. * @return the Sub MIME type of this <code>DataFlavor</code>
  723. */
  724. public String getSubType() {
  725. return (mimeType != null) ? mimeType.getSubType() : null;
  726. }
  727. /**
  728. * Returns the human presentable name for this <code>DataFlavor</code>
  729. * if <code>paramName</code> equals "humanPresentableName". Otherwise
  730. * returns the MIME type value associated with <code>paramName</code>.
  731. *
  732. * @param paramName the parameter name requested
  733. * @return the value of the name parameter, or <code>null</code>
  734. * if there is no associated value
  735. * @see MimeType#getParameter()
  736. */
  737. public String getParameter(String paramName) {
  738. if (paramName.equals("humanPresentableName")) {
  739. return humanPresentableName;
  740. } else {
  741. return (mimeType != null)
  742. ? mimeType.getParameter(paramName) : null;
  743. }
  744. }
  745. /**
  746. * Sets the human presentable name for the data format that this
  747. * <code>DataFlavor</code> represents. This name would be localized
  748. * for different countries.
  749. * @param humanPresentableName the new human presentable name
  750. */
  751. public void setHumanPresentableName(String humanPresentableName) {
  752. this.humanPresentableName = humanPresentableName;
  753. }
  754. /**
  755. * Tests an arbitrary <code>Object</code> to this <code>DataFlavor</code>
  756. * for equality. Two <code>DataFlavor</code>s are considered equal if and
  757. * only if their MIME primary type and subtype and representation class are
  758. * equal. Additionally, if the primary type is "text", the subtype denotes
  759. * a text flavor which supports the charset parameter, and the
  760. * representation class is not <code>java.io.Reader</code>,
  761. * <code>java.lang.String</code>, <code>java.nio.CharBuffer</code>, or
  762. * <code>[C</code>, the <code>charset</code> parameter must also be equal.
  763. * If a charset is not explicitly specified for one or both
  764. * <code>DataFlavor</code>s, the platform default encoding is assumed. See
  765. * <code>selectBestTextFlavor</code> for a list of text flavors which
  766. * support the charset parameter.
  767. *
  768. * @param o the <code>Object</code> to compare with <code>this</code>
  769. * @return <code>true</code> if <code>that</code> is equivalent to this
  770. * <code>DataFlavor</code> <code>false</code> otherwise
  771. * @see #selectBestTextFlavor
  772. */
  773. public boolean equals(Object o) {
  774. return ((o instanceof DataFlavor) && equals((DataFlavor)o));
  775. }
  776. /**
  777. * Tests a <code>DataFlavor</code> to this <code>DataFlavor</code> for
  778. * equality. Two <code>DataFlavor</code>s are considered equal if and only
  779. * if their MIME primary type and subtype and representation class are
  780. * equal. Additionally, if the primary type is "text", the subtype denotes
  781. * a text flavor which supports the charset parameter, and the
  782. * representation class is not <code>java.io.Reader</code>,
  783. * <code>java.lang.String</code>, <code>java.nio.CharBuffer</code>, or
  784. * <code>[C</code>, the <code>charset</code> parameter must also be equal.
  785. * If a charset is not explicitly specified for one or both
  786. * <code>DataFlavor</code>s, the platform default encoding is assumed. See
  787. * <code>selectBestTextFlavor</code> for a list of text flavors which
  788. * support the charset parameter.
  789. *
  790. * @param that the <code>DataFlavor</code> to compare with
  791. * <code>this</code>
  792. * @return <code>true</code> if <code>that</code> is equivalent to this
  793. * <code>DataFlavor</code> <code>false</code> otherwise
  794. * @see #selectBestTextFlavor
  795. */
  796. public boolean equals(DataFlavor that) {
  797. if (that == null) {
  798. return false;
  799. }
  800. if (this == that) {
  801. return true;
  802. }
  803. if (representationClass == null) {
  804. if (that.getRepresentationClass() != null) {
  805. return false;
  806. }
  807. } else {
  808. if (!representationClass.equals(that.getRepresentationClass())) {
  809. return false;
  810. }
  811. }
  812. if (mimeType == null) {
  813. if (that.mimeType != null) {
  814. return false;
  815. }
  816. } else {
  817. if (!mimeType.match(that.mimeType)) {
  818. return false;
  819. }
  820. if ("text".equals(getPrimaryType()) &&
  821. DataTransferer.doesSubtypeSupportCharset(this) &&
  822. representationClass != null &&
  823. !(isRepresentationClassReader() ||
  824. String.class.equals(representationClass) ||
  825. isRepresentationClassCharBuffer() ||
  826. DataTransferer.charArrayClass.equals(representationClass)))
  827. {
  828. String thisCharset =
  829. DataTransferer.canonicalName(getParameter("charset"));
  830. String thatCharset =
  831. DataTransferer.canonicalName(that.getParameter("charset"));
  832. if (thisCharset == null) {
  833. if (thatCharset != null) {
  834. return false;
  835. }
  836. } else {
  837. if (!thisCharset.equals(thatCharset)) {
  838. return false;
  839. }
  840. }
  841. }
  842. }
  843. return true;
  844. }
  845. /**
  846. * Compares only the <code>mimeType</code> against the passed in
  847. * <code>String</code> and <code>representationClass</code> is
  848. * not considered in the comparison.
  849. * If <code>representationClass</code> needs to be compared, then
  850. * <code>equals(new DataFlavor(s))</code> may be used.
  851. *
  852. * @deprecated As inconsistent with <code>hashCode()</code> contract,
  853. * use <code>isMimeTypeEqual(String)</code> instead.
  854. * @return true if the String (MimeType) is equal
  855. */
  856. public boolean equals(String s) {
  857. if (s == null || mimeType == null)
  858. return false;
  859. return isMimeTypeEqual(s);
  860. }
  861. /**
  862. * Returns hash code for this <code>DataFlavor</code>.
  863. * For two equal <code>DataFlavor</code>s, hash codes are equal.
  864. * For the <code>String</code>
  865. * that matches <code>DataFlavor.equals(String)</code>, it is not
  866. * guaranteed that <code>DataFlavor</code>'s hash code is equal
  867. * to the hash code of the <code>String</code>.
  868. *
  869. * @return a hash code for this <code>DataFlavor</code>
  870. */
  871. public int hashCode() {
  872. int total = 0;
  873. if (representationClass != null) {
  874. total += representationClass.hashCode();
  875. }
  876. if (mimeType != null) {
  877. String primaryType = mimeType.getPrimaryType();
  878. if (primaryType != null) {
  879. total += primaryType.hashCode();
  880. }
  881. // Do not add subType.hashCode() to the total. equals uses
  882. // MimeType.match which reports a match if one or both of the
  883. // subTypes is '*', regardless of the other subType.
  884. if ("text".equals(primaryType) &&
  885. DataTransferer.doesSubtypeSupportCharset(this) &&
  886. representationClass != null &&
  887. !(isRepresentationClassReader() ||
  888. String.class.equals(representationClass) ||
  889. isRepresentationClassCharBuffer() ||
  890. DataTransferer.charArrayClass.equals
  891. (representationClass)))
  892. {
  893. String charset =
  894. DataTransferer.canonicalName(getParameter("charset"));
  895. if (charset != null) {
  896. total += charset.hashCode();
  897. }
  898. }
  899. }
  900. return total;
  901. }
  902. /**
  903. * Tests a <code>DataFlavor</code> to this <code>DataFlavor</code> for
  904. * equality. Two <code>DataFlavor</code>s are considered equal if and only
  905. * if their MIME primary type and subtype and representation class are
  906. * equal. Additionally, if the primary type is "text", the subtype denotes
  907. * a text flavor which supports the charset parameter, and the
  908. * representation class is not <code>java.io.Reader</code>,
  909. * <code>java.lang.String</code>, <code>java.nio.CharBuffer</code>, or
  910. * <code>[C</code>, the <code>charset</code> parameter must also be equal.
  911. * If a charset is not explicitly specified for one or both
  912. * <code>DataFlavor</code>s, the platform default encoding is assumed. See
  913. * <code>selectBestTextFlavor</code> for a list of text flavors which
  914. * support the charset parameter.
  915. *
  916. * @param that the <code>DataFlavor</code> to compare with
  917. * <code>this</code>
  918. * @return <code>true</code> if <code>that</code> is equivalent to this
  919. * <code>DataFlavor</code> <code>false</code> otherwise
  920. * @see #selectBestTextFlavor
  921. */
  922. public boolean match(DataFlavor that) {
  923. return equals(that);
  924. }
  925. /**
  926. * Returns whether the string representation of the MIME type passed in
  927. * is equivalent to the MIME type of this <code>DataFlavor</code>.
  928. * Parameters are not included in the comparison.
  929. *
  930. * @param mimeType the string representation of the MIME type
  931. * @return true if the string representation of the MIME type passed in is
  932. * equivalent to the MIME type of this <code>DataFlavor</code>
  933. * false otherwise
  934. * @throws NullPointerException if mimeType is <code>null</code>
  935. */
  936. public boolean isMimeTypeEqual(String mimeType) {
  937. // JCK Test DataFlavor0117: if 'mimeType' is null, throw NPE
  938. if (mimeType == null) {
  939. throw new NullPointerException("mimeType");
  940. }
  941. if (this.mimeType == null) {
  942. return false;
  943. }
  944. try {
  945. return this.mimeType.match(new MimeType(mimeType));
  946. } catch (MimeTypeParseException mtpe) {
  947. return false;
  948. }
  949. }
  950. /**
  951. * Compares the <code>mimeType</code> of two <code>DataFlavor</code>
  952. * objects. No parameters are considered.
  953. *
  954. * @param dataFlavor the <code>DataFlavor</code> to be compared
  955. * @return true if the <code>MimeType</code>s are equal,
  956. * otherwise false
  957. */
  958. public final boolean isMimeTypeEqual(DataFlavor dataFlavor) {
  959. return isMimeTypeEqual(dataFlavor.mimeType);
  960. }
  961. /**
  962. * Compares the <code>mimeType</code> of two <code>DataFlavor</code>
  963. * objects. No parameters are considered.
  964. *
  965. * @return true if the <code>MimeType</code>s are equal,
  966. * otherwise false
  967. */
  968. private boolean isMimeTypeEqual(MimeType mtype) {
  969. if (this.mimeType == null) {
  970. return (mtype == null);
  971. }
  972. return mimeType.match(mtype);
  973. }
  974. /**
  975. * Does the <code>DataFlavor</code> represent a serialized object?
  976. */
  977. public boolean isMimeTypeSerializedObject() {
  978. return isMimeTypeEqual(javaSerializedObjectMimeType);
  979. }
  980. public final Class getDefaultRepresentationClass() {
  981. return ioInputStreamClass;
  982. }
  983. public final String getDefaultRepresentationClassAsString() {
  984. return getDefaultRepresentationClass().getName();
  985. }
  986. /**
  987. * Does the <code>DataFlavor</code> represent a
  988. * <code>java.io.InputStream</code>?
  989. */
  990. public boolean isRepresentationClassInputStream() {
  991. return ioInputStreamClass.isAssignableFrom(representationClass);
  992. }
  993. /**
  994. * Returns whether the representation class for this
  995. * <code>DataFlavor</code> is <code>java.io.Reader</code> or a subclass
  996. * thereof.
  997. *
  998. * @since 1.4
  999. */
  1000. public boolean isRepresentationClassReader() {
  1001. return java.io.Reader.class.isAssignableFrom(representationClass);
  1002. }
  1003. /**
  1004. * Returns whether the representation class for this
  1005. * <code>DataFlavor</code> is <code>java.nio.CharBuffer</code> or a
  1006. * subclass thereof.
  1007. *
  1008. * @since 1.4
  1009. */
  1010. public boolean isRepresentationClassCharBuffer() {
  1011. return java.nio.CharBuffer.class.isAssignableFrom(representationClass);
  1012. }
  1013. /**
  1014. * Returns whether the representation class for this
  1015. * <code>DataFlavor</code> is <code>java.nio.ByteBuffer</code> or a
  1016. * subclass thereof.
  1017. *
  1018. * @since 1.4
  1019. */
  1020. public boolean isRepresentationClassByteBuffer() {
  1021. return java.nio.ByteBuffer.class.isAssignableFrom(representationClass);
  1022. }
  1023. /**
  1024. * Returns true if the representation class can be serialized.
  1025. * @return true if the representation class can be serialized
  1026. */
  1027. public boolean isRepresentationClassSerializable() {
  1028. return java.io.Serializable.class.isAssignableFrom(representationClass);
  1029. }
  1030. /**
  1031. * Returns true if the representation class is <code>Remote</code>.
  1032. * @return true if the representation class is <code>Remote</code>
  1033. */
  1034. public boolean isRepresentationClassRemote() {
  1035. return java.rmi.Remote.class.isAssignableFrom(representationClass);
  1036. }
  1037. /**
  1038. * Returns true if the <code>DataFlavor</code> specified represents
  1039. * a serialized object.
  1040. * @return true if the <code>DataFlavor</code> specified represents
  1041. * a Serialized Object
  1042. */
  1043. public boolean isFlavorSerializedObjectType() {
  1044. return isRepresentationClassSerializable() && isMimeTypeEqual(javaSerializedObjectMimeType);
  1045. }
  1046. /**
  1047. * Returns true if the <code>DataFlavor</code> specified represents
  1048. * a remote object.
  1049. * @return true if the <code>DataFlavor</code> specified represents
  1050. * a Remote Object
  1051. */
  1052. public boolean isFlavorRemoteObjectType() {
  1053. return isRepresentationClassRemote()
  1054. && isRepresentationClassSerializable()
  1055. && isMimeTypeEqual(javaRemoteObjectMimeType);
  1056. }
  1057. /**
  1058. * Returns true if the <code>DataFlavor</code> specified represents
  1059. * a list of file objects.
  1060. * @return true if the <code>DataFlavor</code> specified represents
  1061. * a List of File objects
  1062. */
  1063. public boolean isFlavorJavaFileListType() {
  1064. if (mimeType == null || representationClass == null)
  1065. return false;
  1066. return java.util.List.class.isAssignableFrom(representationClass) &&
  1067. mimeType.match(javaFileListFlavor.mimeType);
  1068. }
  1069. /**
  1070. * Returns whether this <code>DataFlavor</code> is a valid text flavor for
  1071. * this implementation of the Java platform. Only flavors equivalent to
  1072. * <code>DataFlavor.stringFlavor</code> and <code>DataFlavor</code>s with
  1073. * a primary MIME type of "text" can be valid text flavors.
  1074. * <p>
  1075. * If this flavor supports the charset parameter, it must be equivalent to
  1076. * <code>DataFlavor.stringFlavor</code>, or its representation must be
  1077. * <code>java.io.Reader</code>, <code>java.lang.String</code>,
  1078. * <code>java.nio.CharBuffer</code>, <code>[C</code>,
  1079. * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
  1080. * <code>[B</code>. If the representation is
  1081. * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
  1082. * <code>[B</code>, then this flavor's <code>charset</code> parameter must
  1083. * be supported by this implementation of the Java platform. If a charset
  1084. * is not specified, then the platform default charset, which is always
  1085. * supported, is assumed.
  1086. * <p>
  1087. * If this flavor does not support the charset parameter, its
  1088. * representation must be <code>java.io.InputStream</code>,
  1089. * <code>java.nio.ByteBuffer</code>, or <code>[B</code>.
  1090. * <p>
  1091. * See <code>selectBestTextFlavor</code> for a list of text flavors which
  1092. * support the charset parameter.
  1093. *
  1094. * @return <code>true</code> if this <code>DataFlavor</code> is a valid
  1095. * text flavor as described above; <code>false</code> otherwise
  1096. * @see #selectBestTextFlavor
  1097. * @since 1.4
  1098. */
  1099. public boolean isFlavorTextType() {
  1100. return (DataTransferer.isFlavorCharsetTextType(this) ||
  1101. DataTransferer.isFlavorNoncharsetTextType(this));
  1102. }
  1103. /**
  1104. * Serializes this <code>DataFlavor</code>.
  1105. */
  1106. public synchronized void writeExternal(ObjectOutput os) throws IOException {
  1107. if (mimeType != null) {
  1108. mimeType.setParameter("humanPresentableName", humanPresentableName);
  1109. os.writeObject(mimeType);
  1110. mimeType.removeParameter("humanPresentableName");
  1111. } else {
  1112. os.writeObject(null);
  1113. }
  1114. os.writeObject(representationClass);
  1115. }
  1116. /**
  1117. * Restores this <code>DataFlavor</code> from a Serialized state.
  1118. */
  1119. public synchronized void readExternal(ObjectInput is) throws IOException , ClassNotFoundException {
  1120. String rcn = null;
  1121. mimeType = (MimeType)is.readObject();
  1122. if (mimeType != null) {
  1123. humanPresentableName =
  1124. mimeType.getParameter("humanPresentableName");
  1125. mimeType.removeParameter("humanPresentableName");
  1126. rcn = mimeType.getParameter("class");
  1127. if (rcn == null) {
  1128. throw new IOException("no class parameter specified in: " +
  1129. mimeType);
  1130. }
  1131. }
  1132. try {
  1133. representationClass = (Class)is.readObject();
  1134. } catch (OptionalDataException ode) {
  1135. if (rcn != null) {
  1136. representationClass =
  1137. DataFlavor.tryToLoadClass(rcn, getClass().getClassLoader());
  1138. }
  1139. }
  1140. }
  1141. /**
  1142. * Returns a clone of this <code>DataFlavor</code>.
  1143. * @return a clone of this <code>DataFlavor</code>
  1144. */
  1145. public Object clone() throws CloneNotSupportedException {
  1146. Object newObj = super.clone();
  1147. if (mimeType != null) {
  1148. ((DataFlavor)newObj).mimeType = (MimeType)mimeType.clone();
  1149. }
  1150. return newObj;
  1151. } // clone()
  1152. /**
  1153. * Called on <code>DataFlavor</code> for every MIME Type parameter
  1154. * to allow <code>DataFlavor</code> subclasses to handle special
  1155. * parameters like the text/plain <code>charset</code>
  1156. * parameters, whose values are case insensitive. (MIME type parameter
  1157. * values are supposed to be case sensitive.
  1158. * <p>
  1159. * This method is called for each parameter name/value pair and should
  1160. * return the normalized representation of the <code>parameterValue</code>.
  1161. *
  1162. * This method is never invoked by this implementation from 1.1 onwards.
  1163. *
  1164. * @deprecated
  1165. */
  1166. protected String normalizeMimeTypeParameter(String parameterName, String parameterValue) {
  1167. return parameterValue;
  1168. }
  1169. /**
  1170. * Called for each MIME type string to give <code>DataFlavor</code> subtypes
  1171. * the opportunity to change how the normalization of MIME types is
  1172. * accomplished. One possible use would be to add default
  1173. * parameter/value pairs in cases where none are present in the MIME
  1174. * type string passed in.
  1175. *
  1176. * This method is never invoked by this implementation from 1.1 onwards.
  1177. *
  1178. * @deprecated
  1179. */
  1180. protected String normalizeMimeType(String mimeType) {
  1181. return mimeType;
  1182. }
  1183. /*
  1184. * fields
  1185. */
  1186. /* placeholder for caching any platform-specific data for flavor */
  1187. transient int atom;
  1188. /* Mime Type of DataFlavor */
  1189. MimeType mimeType;
  1190. private String humanPresentableName;
  1191. /** Java class of objects this DataFlavor represents **/
  1192. private Class representationClass;
  1193. } // class DataFlavor