1. /*
  2. * @(#)DataFlavor.java 1.53 01/02/09
  3. *
  4. * Copyright 1996-2001 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.*;
  13. import java.util.*;
  14. import sun.awt.SunToolkit;
  15. import sun.awt.DataTransferer;
  16. /**
  17. * Each instance represents the opaque concept of a data format as would
  18. * appear on a clipboard, during drag and drop, or in a file system.
  19. * <p>
  20. * <code>DataFlavor</code> objects are constant and never change once
  21. * instantiated.
  22. * </p>
  23. *
  24. * @version 1.53, 02/09/01
  25. * @author Blake Sullivan
  26. * @author Laurence P. G. Cable
  27. * @author Jeff Dunn
  28. */
  29. public class DataFlavor implements Externalizable, Cloneable {
  30. private static final long serialVersionUID = 8367026044764648243L;
  31. private static final Class ioInputStreamClass = java.io.InputStream.class;
  32. /**
  33. * tried to load a class from: the bootstrap loader, the system loader,
  34. * the context loader (if one is present) and finally the loader specified
  35. *
  36. * @param fallback the fallback loader
  37. *
  38. * @throws ClassNotFoundException
  39. */
  40. protected final static Class tryToLoadClass(String className,
  41. ClassLoader fallback)
  42. throws ClassNotFoundException
  43. {
  44. ClassLoader systemClassLoader = (ClassLoader)
  45. java.security.AccessController.doPrivileged(
  46. new java.security.PrivilegedAction() {
  47. public Object run() {
  48. ClassLoader cl = Thread.currentThread().
  49. getContextClassLoader();
  50. return (cl != null)
  51. ? cl
  52. : ClassLoader.getSystemClassLoader();
  53. }
  54. });
  55. try {
  56. return Class.forName(className, true, systemClassLoader);
  57. } catch (ClassNotFoundException e2) {
  58. if (fallback != null) {
  59. return Class.forName(className, true, fallback);
  60. } else {
  61. throw new ClassNotFoundException(className);
  62. }
  63. }
  64. }
  65. /*
  66. * private initializer
  67. */
  68. static private DataFlavor createConstant(Class rc, String prn) {
  69. try {
  70. return new DataFlavor(rc, prn);
  71. } catch (Exception e) {
  72. return null;
  73. }
  74. }
  75. /*
  76. * private initializer
  77. */
  78. static private DataFlavor createConstant(String mt, String prn) {
  79. try {
  80. return new DataFlavor(mt, prn);
  81. } catch (Exception e) {
  82. return null;
  83. }
  84. }
  85. /**
  86. * The DataFlavor representing a Java Unicode String class, where:
  87. * <p>
  88. * representationClass = java.lang.String<br>
  89. * mimeType = "application/x-java-serialized-object"
  90. * <p>
  91. */
  92. public static final DataFlavor stringFlavor = createConstant(java.lang.String.class, "Unicode String");
  93. /**
  94. * The DataFlavor representing plain text with unicode encoding, where:
  95. * <p>
  96. * representationClass = InputStream<br>
  97. * mimeType = "text/plain; charset=unicode"
  98. * <p>
  99. * This DataFlavor has been <b>deprecated</b> because (1) Its
  100. * representation is an InputStream, an 8-bit based representation,
  101. * while Unicode is a 16-bit character set; and (2) The charset "unicode"
  102. * is not well-defined. "unicode" implies a particular platform's
  103. * implementation of Unicode, not a cross-platform implementation.
  104. *
  105. * @deprecated as of 1.3. Use <code>DataFlavor.getReaderForText(
  106. * Transferable)</code> instead of <code>Transferable.
  107. * getTransferData(DataFlavor.plainTextFlavor)</code>.
  108. */
  109. public static final DataFlavor plainTextFlavor = createConstant("text/plain; charset=unicode; class=java.io.InputStream", "Plain Text");
  110. /**
  111. * a MIME Content-Type of application/x-java-serialized-object represents
  112. * a graph of Java object(s) that have been made persistent.
  113. *
  114. * The representation class associated with this DataFlavor identifies
  115. * the Java type of an object returned as a reference from an invocation
  116. * java.awt.datatransfer.getTransferData().
  117. *
  118. */
  119. public static final String javaSerializedObjectMimeType = "application/x-java-serialized-object";
  120. /**
  121. * To transfer a list of files to/from Java (and the underlying
  122. * platform) a DataFlavor of this type/subtype and representation class
  123. * of java.util.List is used.
  124. *
  125. * Each element of the list is required/guaranteed to be of type
  126. * java.io.File.
  127. */
  128. public static final DataFlavor javaFileListFlavor = createConstant("application/x-java-file-list;class=java.util.List", null);
  129. /**
  130. * to transfer a reference to an arbitrary Java object reference that
  131. * has no associated MIME Content-type, across a Transferable interface
  132. * WITHIN THE SAME JVM, a DataFlavor with this type/subtype is used,
  133. * with a representationClass equal to the type of the class/interface
  134. * being passed across the Transferble.
  135. *
  136. * The object reference returned from Transferable.getTransferData()
  137. * for a DataFlavor with this MIME Content-Type is required to be
  138. * an instanceof the representation Class of the DataFlavor.
  139. */
  140. public static final String javaJVMLocalObjectMimeType = "application/x-java-jvm-local-objectref";
  141. /**
  142. * In order to pass a live link to a Remote object via a Drag and Drop
  143. * ACTION_LINK operation a Mime Content Type of application/x-java-remote-object
  144. * should be used, where the representation class of the DataFlavor
  145. * represents the type of the Remote interface to be transferred.
  146. */
  147. public static final String javaRemoteObjectMimeType = "application/x-java-remote-object";
  148. /**
  149. * Constructs a new DataFlavor. This constructor is provided only for
  150. * the purpose of supporting the Externalizable interface. It is not
  151. * intended for public (client) use.
  152. *
  153. * @since 1.2
  154. */
  155. public DataFlavor() {
  156. super();
  157. }
  158. /**
  159. * Cloning constructor. Package-private.
  160. */
  161. DataFlavor(DataFlavor that) {
  162. this.mimeType = null;
  163. if (that.mimeType != null) {
  164. try {
  165. this.mimeType = (MimeType)that.mimeType.clone();
  166. } catch (CloneNotSupportedException e) {
  167. }
  168. }
  169. this.representationClass = that.representationClass;
  170. this.humanPresentableName = that.humanPresentableName;
  171. this.atom = that.atom;
  172. } // DataFlavor()
  173. /**
  174. * Construct a fully specified DataFlavor
  175. */
  176. private DataFlavor(String primaryType, String subType, MimeTypeParameterList params, Class representationClass, String humanPresentableName) {
  177. super();
  178. if (params == null) params = new MimeTypeParameterList();
  179. params.set("class", representationClass.getName());
  180. if (humanPresentableName == null) {
  181. humanPresentableName = (String)params.get("humanPresentableName");
  182. if (humanPresentableName == null)
  183. humanPresentableName = primaryType + "/" + subType;
  184. }
  185. try {
  186. mimeType = new MimeType(primaryType, subType, params);
  187. } catch (MimeTypeParseException mtpe) {
  188. throw new IllegalArgumentException("MimeType Parse Exception: " + mtpe.getMessage());
  189. }
  190. this.representationClass = representationClass;
  191. this.humanPresentableName = humanPresentableName;
  192. mimeType.removeParameter("humanPresentableName");
  193. }
  194. /**
  195. * Construct a DataFlavor that represents a Java class
  196. * <p>
  197. * The returned DataFlavor will have the following characteristics
  198. * <p>
  199. * representationClass = representationClass<br>
  200. * mimeType = application/x-java-serialized-object
  201. * <p>
  202. * @param representationClass the class used to transfer data in this flavor
  203. * @param humanPresentableName the human-readable string used to identify
  204. * this flavor.
  205. * If this parameter is null then the value of the
  206. * the MIME Content Type is used.
  207. */
  208. public DataFlavor(Class representationClass, String humanPresentableName) {
  209. this("application", "x-java-serialized-object", null, representationClass, humanPresentableName);
  210. }
  211. /**
  212. * Construct a DataFlavor that represents a MimeType
  213. * <p>
  214. * The returned DataFlavor will have the following characteristics:
  215. * <p>
  216. * If the mimeType is
  217. * "application/x-java-serialized-object; class=<representation class>",
  218. * the result is the same as calling
  219. * new DataFlavor(Class:forName(<representation class>) as above
  220. * <p>
  221. * otherwise:
  222. * <p>
  223. * representationClass = InputStream<br>
  224. * mimeType = mimeType
  225. * <p>
  226. * @param mimeType the string used to identify the MIME type for this flavor.
  227. * If the the mimeType does not specify a
  228. * "class=" parameter, or if the class is not successfully
  229. * loaded, then an IllegalArgumentException is thrown.
  230. * @param humanPresentableName the human-readable string used to identify
  231. * this flavor.
  232. * If this parameter is null then the value of the
  233. * the MIME Content Type is used.
  234. */
  235. public DataFlavor(String mimeType, String humanPresentableName) {
  236. super();
  237. try {
  238. initialize(mimeType, humanPresentableName, this.getClass().getClassLoader());
  239. } catch (MimeTypeParseException mtpe) {
  240. throw new IllegalArgumentException("failed to parse:" + mimeType);
  241. } catch (ClassNotFoundException cnfe) {
  242. throw new IllegalArgumentException("cant find specified class: " + cnfe.getMessage());
  243. }
  244. }
  245. /**
  246. * Construct a DataFlavor that represents a MimeType
  247. * <p>
  248. * The returned DataFlavor will have the following characteristics:
  249. * <p>
  250. * If the mimeType is
  251. * "application/x-java-serialized-object; class=<representation class>",
  252. * the result is the same as calling
  253. * new DataFlavor(Class:forName(<representation class>) as above
  254. * <p>
  255. * otherwise:
  256. * <p>
  257. * representationClass = InputStream<br>
  258. * mimeType = mimeType
  259. * <p>
  260. * @param mimeType the string used to identify the MIME type for this flavor
  261. * @param humanPresentableName the human-readible string used to identify this flavor
  262. */
  263. public DataFlavor(String mimeType, String humanPresentableName, ClassLoader classLoader) throws ClassNotFoundException {
  264. super();
  265. try {
  266. initialize(mimeType, humanPresentableName, classLoader);
  267. } catch (MimeTypeParseException mtpe) {
  268. throw new IllegalArgumentException("failed to parse:" + mimeType);
  269. }
  270. }
  271. /**
  272. * Construct a DataFlavor from a Mime Type string.
  273. * The string can specify a "class=<fully specified Java class name>"
  274. * parameter to create a DataFlavor with the desired representation
  275. * class. If the string does not contain "class=" parameter,
  276. * java.io.InputStream is used as default.
  277. *
  278. * @param mimeType the string used to identify the MIME type for this flavor.
  279. * If the class specified by "class=" parameter is not
  280. * successfully loaded, then an IllegalArgumentException
  281. * is thrown.
  282. */
  283. public DataFlavor(String mimeType) throws ClassNotFoundException {
  284. super();
  285. try {
  286. initialize(mimeType, null, this.getClass().getClassLoader());
  287. } catch (MimeTypeParseException mtpe) {
  288. throw new IllegalArgumentException("failed to parse:" + mimeType);
  289. }
  290. }
  291. /**
  292. * common initialization code called from various constructors.
  293. *
  294. * @param mimeType The MIME Content Type (must have a class= param)
  295. * @param humanPresentableName The human Presentable Name or null
  296. * @param classLoader The fallback class loader to resolve against
  297. *
  298. * @throws MimeTypeParseException
  299. * @throws ClassNotFoundException
  300. *
  301. * @see tryToLoadClass
  302. */
  303. private void initialize(String mimeType, String humanPresentableName, ClassLoader classLoader) throws MimeTypeParseException, ClassNotFoundException {
  304. this.mimeType = new MimeType(mimeType); // throws
  305. String rcn = getParameter("class");
  306. if (rcn == null) {
  307. if ("application/x-java-serialized-object".equals(this.mimeType.getBaseType()))
  308. throw new IllegalArgumentException("no representation class specified for:" + mimeType);
  309. else
  310. representationClass = java.io.InputStream.class; // default
  311. } else { // got a class name
  312. representationClass = DataFlavor.tryToLoadClass(rcn, classLoader);
  313. }
  314. this.mimeType.setParameter("class", representationClass.getName());
  315. if (humanPresentableName == null) {
  316. humanPresentableName = this.mimeType.getParameter("humanPresentableName");
  317. if (humanPresentableName == null)
  318. humanPresentableName = this.mimeType.getPrimaryType() + "/" + this.mimeType.getSubType();
  319. }
  320. this.humanPresentableName = humanPresentableName; // set it.
  321. this.mimeType.removeParameter("humanPresentableName"); // just in case
  322. }
  323. /**
  324. * used by clone implementation
  325. */
  326. private DataFlavor(MimeType mt, Class rc, String hrn, int a) {
  327. super();
  328. mimeType = mt;
  329. representationClass = rc;
  330. humanPresentableName = hrn;
  331. atom = a;
  332. }
  333. /**
  334. * String representation of this <code>DataFlavor</code>
  335. * and its parameters. The result String contains name of
  336. * <code>DataFlavor</code> class, representation class
  337. * and Mime type of this Flavor.
  338. *
  339. * @return string representation of this <code>DataFlavor</code>
  340. */
  341. public String toString() {
  342. String string = getClass().getName();
  343. string += "["+paramString()+"]";
  344. return string;
  345. }
  346. private String paramString() {
  347. String params = "";
  348. params += "representationclass=";
  349. if (representationClass == null) {
  350. params += "null";
  351. } else {
  352. params += representationClass.getName();
  353. }
  354. params += ";mimetype=";
  355. if (mimeType == null) {
  356. params += "null";
  357. } else {
  358. params += mimeType.getBaseType();
  359. }
  360. return params;
  361. }
  362. public static final DataFlavor getTextPlainUnicodeFlavor() {
  363. Toolkit toolkit = Toolkit.getDefaultToolkit();
  364. SunToolkit sunToolkit = null;
  365. String encoding = null;
  366. if (toolkit instanceof SunToolkit) {
  367. encoding = ((SunToolkit)toolkit).getDefaultUnicodeEncoding();
  368. }
  369. return new DataFlavor(
  370. "text/plain; charset="+encoding
  371. +"; class=java.io.InputStream", "Plain Text");
  372. } // getTextPlainUnicodeFlavor()
  373. /**
  374. * @return the best (highest fidelity) flavor in an encoding supported
  375. * by the JDK, or null if none can be found.
  376. */
  377. public static final DataFlavor selectBestTextFlavor(
  378. DataFlavor[] availableFlavors) {
  379. if (availableFlavors == null) {
  380. return null;
  381. }
  382. DataFlavor selectedFlavor = null;
  383. for (int i = 0;
  384. (selectedFlavor == null) && (i < availableFlavors.length);
  385. ++i) {
  386. DataFlavor flavor = availableFlavors[i];
  387. if (flavor.match(stringFlavor)) {
  388. // A serialized java.lang.String
  389. selectedFlavor = flavor;
  390. continue;
  391. }
  392. String primaryType = flavor.getPrimaryType();
  393. if ((primaryType == null) || (!("text".equals(primaryType)))) {
  394. continue;
  395. }
  396. String charset = flavor.getParameter("charset");
  397. if (charset == null) {
  398. // Take the platform default
  399. selectedFlavor = flavor;
  400. } else {
  401. if (DataTransferer.isEncodingSupported(charset)) {
  402. selectedFlavor = flavor;
  403. }
  404. }
  405. }
  406. //System.out.println("selectBestTextFlavor()->"+ selectedFlavor);
  407. return selectedFlavor;
  408. } // selectBestTextFlavor()
  409. /**
  410. * Gets a reader for an input stream, decoded for the expected
  411. * charset (encoding). This works only if the
  412. * representation class of this flavor is java.io.InputStream
  413. * (or a subclass). In case of representation class being Reader
  414. * the result will be this class itself.
  415. *
  416. * @return a Reader to read the data
  417. *
  418. * @exception IllegalArgumentException if the representation class
  419. * is not java.io.InputStream or java.lang.String
  420. * @exception IllegalArgumentException if the charset (character
  421. * encoding) is not supported by the JDK.
  422. * @exception IllegalArgumentException if the transferable has null
  423. * data.
  424. * @exception NullPointerException if the transferable argument is
  425. * null.
  426. * @exception UnsupportedEncodingException if the encoding is
  427. * not supported by this flavor.
  428. * @exception UnsupportedFlavorException if the transferable does
  429. * not support this flavor.
  430. * @exception IOException if the data cannot be read because of an
  431. * I/O error.
  432. */
  433. public Reader getReaderForText(Transferable transferable)
  434. throws UnsupportedFlavorException, IOException
  435. {
  436. Object transferObject = transferable.getTransferData(this);
  437. if (transferObject == null) {
  438. throw new IllegalArgumentException("getTransferData() returned null");
  439. }
  440. if (transferObject instanceof Reader) {
  441. return (Reader)transferObject;
  442. } else if (transferObject instanceof String) {
  443. return new StringReader((String)transferObject);
  444. } else if (transferObject instanceof InputStream) {
  445. InputStream stream = (InputStream)transferObject;
  446. String encoding = DataTransferer.getTextCharset(this);
  447. if (encoding == null) {
  448. return new InputStreamReader(stream);
  449. } else {
  450. return new InputStreamReader(stream, encoding);
  451. }
  452. } else {
  453. throw new IllegalArgumentException(
  454. "transfer data is not InputStream or String or Reader");
  455. }
  456. } // getReaderForText()
  457. /**
  458. * Returns the MIME type string for this DataFlavor
  459. */
  460. public String getMimeType() {
  461. return mimeType.toString();
  462. }
  463. /**
  464. * Returns the Class which objects supporting this DataFlavor
  465. * will return when this DataFlavor is requested.
  466. */
  467. public Class getRepresentationClass() {
  468. return representationClass;
  469. }
  470. /**
  471. * Returns the human presentable name for the data foramt that this
  472. * DataFlavor represents. This name would be localized for different
  473. * countries
  474. */
  475. public String getHumanPresentableName() {
  476. return humanPresentableName;
  477. }
  478. /**
  479. * @return the primary MIME type of this DataFlavor
  480. */
  481. public String getPrimaryType() { return mimeType.getPrimaryType(); }
  482. /**
  483. * @return the Sub MIME type of this DataFlavor
  484. */
  485. public String getSubType() { return mimeType.getSubType(); }
  486. /**
  487. * @return the value of the name parameter
  488. */
  489. public String getParameter(String paramName) {
  490. return paramName.equals("humanPresentableName") ? humanPresentableName : mimeType.getParameter(paramName);
  491. }
  492. /**
  493. * Sets the human presentable name for the data format that this
  494. * DataFlavor represents. This name would be localized for different
  495. * countries
  496. */
  497. public void setHumanPresentableName(String humanPresentableName) {
  498. this.humanPresentableName = humanPresentableName;
  499. }
  500. /**
  501. * If the object is an instance of DataFlavor, representationClass
  502. * and MIME type will be compared.
  503. * This method does not use equals(String) method, so it does not
  504. * return <code>true</code> for the objects of String type.
  505. *
  506. * @return if the objects are equal
  507. */
  508. public boolean equals(Object o) {
  509. return ((o instanceof DataFlavor) && equals((DataFlavor)o));
  510. }
  511. /**
  512. * Two DataFlavors are considered equal if and only if their
  513. * MIME primary type and subtype and representation class are
  514. * equal. Additionally, if the primary type is "text", the
  515. * charset parameter must also be equal. If
  516. * either DataFlavor is of primary type "text", but no charset
  517. * is specified, the platform default charset is assumed for
  518. * that DataFlavor.
  519. *
  520. * @return if the DataFlavors represent exactly the same type.
  521. */
  522. public boolean equals(DataFlavor that) {
  523. if (that == null) {
  524. return false;
  525. }
  526. if (this == that) {
  527. return true;
  528. }
  529. if (representationClass == null) {
  530. if (that.getRepresentationClass() != null) {
  531. return false;
  532. }
  533. } else {
  534. if (!representationClass.equals(that.getRepresentationClass())) {
  535. return false;
  536. }
  537. }
  538. if (mimeType == null) {
  539. if (that.mimeType != null) {
  540. return false;
  541. }
  542. } else {
  543. if (!mimeType.match(that.mimeType)) {
  544. return false;
  545. }
  546. if ("text".equals(getPrimaryType())) {
  547. String thisCharset = DataTransferer.getTextCharset(this);
  548. String thatCharset = DataTransferer.getTextCharset(that);
  549. if (thisCharset == null) {
  550. if (thatCharset != null) {
  551. return false;
  552. }
  553. } else {
  554. if (!thisCharset.equals(thatCharset)) {
  555. return false;
  556. }
  557. }
  558. }
  559. }
  560. return true;
  561. }
  562. /**
  563. * Compare only the mimeType against the passed in String
  564. * and representationClass is not considered in the comparison.
  565. * If representationClass needs to be compared, then
  566. * equals(new DataFlavor(s))
  567. * may be used.
  568. *
  569. * @deprecated As inconsistent with <code>hashCode()</code> contract,
  570. * use <code>isMimeTypeEqual(String)</code> instead.
  571. * @return if the String (MimeType) is equal
  572. */
  573. public boolean equals(String s) {
  574. if (s == null || mimeType == null)
  575. return false;
  576. return isMimeTypeEqual(s);
  577. }
  578. /**
  579. * Returns hash code for this <code>DataFlavor</code>.
  580. * For two equal DataFlavors, hash codes are equal. For the String
  581. * that matches <code>DataFlavor.equals(String)</code>, it is not
  582. * guaranteed that DataFlavor's hash code is equal to the hash code
  583. * of the String.
  584. *
  585. * @return a hash code for this DataFlavor
  586. */
  587. public int hashCode() {
  588. int representationClassPortion = 0, mimeTypePortion = 0,
  589. charsetPortion = 0;
  590. if (representationClass != null) {
  591. representationClassPortion = representationClass.hashCode();
  592. }
  593. if (mimeType != null) {
  594. String primaryType = mimeType.getPrimaryType();
  595. if (primaryType != null) {
  596. mimeTypePortion = primaryType.hashCode();
  597. if ("text".equals(primaryType)) {
  598. String charset = DataTransferer.getTextCharset(this);
  599. if (charset != null) {
  600. charsetPortion = charset.hashCode();
  601. }
  602. }
  603. }
  604. }
  605. int total = representationClassPortion + mimeTypePortion +
  606. charsetPortion;
  607. return (total != 0) ? total : 25431009;
  608. }
  609. /**
  610. * Two DataFlavors match if their primary types, subtypes,
  611. * and representation classes are all equal. Additionally, if
  612. * the primary type is "text", the charset parameter is also
  613. * considered. If either DataFlavor is of primary type "text",
  614. * but no charset is specified, the platform default charset
  615. * is assumed for that DataFlavor.
  616. */
  617. public boolean match(DataFlavor that) {
  618. if (that == null) {
  619. return false;
  620. }
  621. if ((this.mimeType == null) || (that.mimeType == null)) {
  622. return false;
  623. }
  624. String thisPrimaryType = this.getPrimaryType();
  625. String thatPrimaryType = that.getPrimaryType();
  626. if ((thisPrimaryType == null) || (thatPrimaryType == null) ||
  627. (!thisPrimaryType.equals(thatPrimaryType))) {
  628. return false;
  629. }
  630. String thisSubType = this.getSubType();
  631. String thatSubType = that.getSubType();
  632. if ((thisSubType == null) || (thatSubType == null) ||
  633. (!thisSubType.equals(thatSubType))) {
  634. return false;
  635. }
  636. Class thisRepresentationClass = this.getRepresentationClass();
  637. Class thatRepresentationClass = that.getRepresentationClass();
  638. if ((thisRepresentationClass == null) ||
  639. (thatRepresentationClass == null) ||
  640. (!thisRepresentationClass.equals(thatRepresentationClass))) {
  641. return false;
  642. }
  643. if (thisPrimaryType.equals("text")) {
  644. String thisCharset = DataTransferer.getTextCharset(this);
  645. String thatCharset = DataTransferer.getTextCharset(that);
  646. if ((thisCharset == null) || (thatCharset == null) ||
  647. (!thisCharset.equals(thatCharset))) {
  648. return false;
  649. }
  650. }
  651. return true;
  652. } // match()
  653. /**
  654. * Returns whether the string representation of the MIME type passed in
  655. * is equivalent to the MIME type of this <code>DataFlavor</code>.
  656. * Parameters are not incuded in the comparison. The comparison may involve
  657. * adding default attributes for some MIME types (such as adding
  658. * <code>charset=US-ASCII</code> to text/plain MIME types that have
  659. * no <code>charset</code> parameter specified).
  660. *
  661. * @param mimeType the string representation of the MIME type
  662. * @return true if the string representation of the MIME type passed in is
  663. * equivalent to the MIME type of this <code>DataFlavor</code>
  664. * false otherwise.
  665. * @throws NullPointerException if mimeType is <code>null</code>
  666. */
  667. public boolean isMimeTypeEqual(String mimeType) {
  668. // JCK Test DataFlavor0117: if 'mimeType' is null, throw NPE
  669. if (mimeType == null) {
  670. throw new NullPointerException("mimeType");
  671. }
  672. if (this.mimeType == null) {
  673. return false;
  674. }
  675. try {
  676. return this.mimeType.match(new MimeType(mimeType));
  677. } catch (MimeTypeParseException mtpe) {
  678. return false;
  679. }
  680. }
  681. /**
  682. * Compare the mimeType of two DataFlavor objects
  683. * no parameters are considered
  684. *
  685. * @return if the MimeTypes are equal
  686. */
  687. public final boolean isMimeTypeEqual(DataFlavor dataFlavor) {
  688. return isMimeTypeEqual(dataFlavor.mimeType);
  689. }
  690. /**
  691. * Compare the mimeType of two DataFlavor objects
  692. * no parameters are considered
  693. *
  694. * @return if the MimeTypes are equal
  695. */
  696. private boolean isMimeTypeEqual(MimeType mtype) {
  697. return mimeType.match(mtype);
  698. }
  699. /**
  700. * does the DataFlavor represent a serialized object?
  701. */
  702. public boolean isMimeTypeSerializedObject() {
  703. return isMimeTypeEqual(javaSerializedObjectMimeType);
  704. }
  705. public final Class getDefaultRepresentationClass() {
  706. return ioInputStreamClass;
  707. }
  708. public final String getDefaultRepresentationClassAsString() {
  709. return getDefaultRepresentationClass().getName();
  710. }
  711. /**
  712. * does the DataFlavor represent a java.io.InputStream
  713. */
  714. public boolean isRepresentationClassInputStream() {
  715. return ioInputStreamClass.isAssignableFrom(representationClass);
  716. }
  717. /**
  718. * @return true if the representation class can be serialized
  719. */
  720. public boolean isRepresentationClassSerializable() {
  721. return java.io.Serializable.class.isAssignableFrom(representationClass);
  722. }
  723. /**
  724. * @return true if the representation class is Remote
  725. */
  726. public boolean isRepresentationClassRemote() {
  727. return java.rmi.Remote.class.isAssignableFrom(representationClass);
  728. }
  729. /**
  730. * @return if the DataFlavor specified represents a Serialized Object
  731. */
  732. public boolean isFlavorSerializedObjectType() {
  733. return isRepresentationClassSerializable() && isMimeTypeEqual(javaSerializedObjectMimeType);
  734. }
  735. /**
  736. * @return if the DataFlavor specified represents a Remote Object
  737. */
  738. public boolean isFlavorRemoteObjectType() {
  739. return isRepresentationClassRemote()
  740. && isRepresentationClassSerializable()
  741. && isMimeTypeEqual(javaRemoteObjectMimeType);
  742. }
  743. /**
  744. * @return if flavor specified represents a List of File objects
  745. */
  746. public boolean isFlavorJavaFileListType() {
  747. if (mimeType == null || representationClass == null)
  748. return false;
  749. return java.util.List.class.isAssignableFrom(representationClass) &&
  750. mimeType.match(javaFileListFlavor.mimeType);
  751. }
  752. /**
  753. * Serialize this DataFlavor
  754. */
  755. public synchronized void writeExternal(ObjectOutput os) throws IOException {
  756. mimeType.setParameter("humanPresentableName", humanPresentableName);
  757. os.writeObject(mimeType);
  758. mimeType.removeParameter("humanPresentableName");
  759. }
  760. /**
  761. * restore this DataFlavor from an Serialized state
  762. */
  763. public synchronized void readExternal(ObjectInput is) throws IOException , ClassNotFoundException {
  764. mimeType = (MimeType)is.readObject();
  765. humanPresentableName = mimeType.getParameter("humanPresentableName");
  766. mimeType.removeParameter("humanPresentableName");
  767. String rcn = mimeType.getParameter("class");
  768. if (rcn == null) throw new IOException("no class parameter specified in: " + mimeType);
  769. representationClass = DataFlavor.tryToLoadClass(rcn, this.getClass().getClassLoader());
  770. }
  771. /**
  772. * @return a clone of this DataFlavor
  773. */
  774. public Object clone() throws CloneNotSupportedException {
  775. DataFlavor clonedFlavor = new DataFlavor(this);
  776. return clonedFlavor;
  777. } // clone()
  778. /**
  779. * Called on DataFlavor for every MIME Type parameter to allow DataFlavor
  780. * subclasses to handle special parameters like the text/plain charset
  781. * parameters, whose values are case insensitive. (MIME type parameter
  782. * values are supposed to be case sensitive.
  783. * <p>
  784. * This method is called for each parameter name/value pair and should
  785. * return the normalized representation of the parameterValue
  786. *
  787. * This method is never invoked by this implementation from 1.1 onwards
  788. *
  789. * @deprecated
  790. */
  791. protected String normalizeMimeTypeParameter(String parameterName, String parameterValue) {
  792. return parameterValue;
  793. }
  794. /**
  795. * Called for each MIME type string to give DataFlavor subtypes the
  796. * opportunity to change how the normalization of MIME types is accomplished.
  797. * One possible use would be to add default parameter/value pairs in cases
  798. * where none are present in the MIME type string passed in
  799. *
  800. * This method is never invoked by this implementation from 1.1 onwards
  801. *
  802. * @deprecated
  803. */
  804. protected String normalizeMimeType(String mimeType) {
  805. return mimeType;
  806. }
  807. //DEBUG void debugTestMimeEquals(DataFlavor that) {
  808. //DEBUG String areThey = "?????";
  809. //DEBUG if ((this.mimeType != null) && (that.mimeType != null)) {
  810. //DEBUG if (this.mimeType.equals(that.mimeType)) {
  811. //DEBUG areThey = " TRUE";
  812. //DEBUG } else {
  813. //DEBUG areThey = "FALSE";
  814. //DEBUG }
  815. //DEBUG }
  816. //DEBUG System.out.println(areThey + ": " + this.mimeType);
  817. //DEBUG System.out.println(" "+ ": " + that.mimeType);
  818. //DEBUG }
  819. /*
  820. * fields
  821. */
  822. /* placeholder for caching any platform-specific data for flavor */
  823. transient int atom;
  824. /* Mime Type of DataFlavor */
  825. MimeType mimeType;
  826. private String humanPresentableName;
  827. /** Java class of objects this DataFlavor represents **/
  828. private Class representationClass;
  829. } // class DataFlavor