0001 /*
0002 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.awt.datatransfer;
0027
0028 import java.awt.Toolkit;
0029 import java.io.*;
0030 import java.nio.*;
0031 import java.util.*;
0032
0033 import sun.awt.datatransfer.DataTransferer;
0034
0035 /**
0036 * A {@code DataFlavor} provides meta information about data. {@code DataFlavor}
0037 * is typically used to access data on the clipboard, or during
0038 * a drag and drop operation.
0039 * <p>
0040 * An instance of {@code DataFlavor} encapsulates a content type as
0041 * defined in <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
0042 * and <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a>.
0043 * A content type is typically referred to as a MIME type.
0044 * <p>
0045 * A content type consists of a media type (referred
0046 * to as the primary type), a subtype, and optional parameters. See
0047 * <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
0048 * for details on the syntax of a MIME type.
0049 * <p>
0050 * The JRE data transfer implementation interprets the parameter "class"
0051 * of a MIME type as <B>a representation class</b>.
0052 * The representation class reflects the class of the object being
0053 * transferred. In other words, the representation class is the type of
0054 * object returned by {@link Transferable#getTransferData}.
0055 * For example, the MIME type of {@link #imageFlavor} is
0056 * {@code "image/x-java-image;class=java.awt.Image"},
0057 * the primary type is {@code image}, the subtype is
0058 * {@code x-java-image}, and the representation class is
0059 * {@code java.awt.Image}. When {@code getTransferData} is invoked
0060 * with a {@code DataFlavor} of {@code imageFlavor}, an instance of
0061 * {@code java.awt.Image} is returned.
0062 * It's important to note that {@code DataFlavor} does no error checking
0063 * against the representation class. It is up to consumers of
0064 * {@code DataFlavor}, such as {@code Transferable}, to honor the representation
0065 * class.
0066 * <br>
0067 * Note, if you do not specify a representation class when
0068 * creating a {@code DataFlavor}, the default
0069 * representation class is used. See appropriate documentation for
0070 * {@code DataFlavor}'s constructors.
0071 * <p>
0072 * Also, {@code DataFlavor} instances with the "text" primary
0073 * MIME type may have a "charset" parameter. Refer to
0074 * <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a> and
0075 * {@link #selectBestTextFlavor} for details on "text" MIME types
0076 * and the "charset" parameter.
0077 * <p>
0078 * Equality of {@code DataFlavors} is determined by the primary type,
0079 * subtype, and representation class. Refer to {@link #equals(DataFlavor)} for
0080 * details. When determining equality, any optional parameters are ignored.
0081 * For example, the following produces two {@code DataFlavors} that
0082 * are considered identical:
0083 * <pre>
0084 * DataFlavor flavor1 = new DataFlavor(Object.class, "X-test/test; class=<java.lang.Object>; foo=bar");
0085 * DataFlavor flavor2 = new DataFlavor(Object.class, "X-test/test; class=<java.lang.Object>; x=y");
0086 * // The following returns true.
0087 * flavor1.equals(flavor2);
0088 * </pre>
0089 * As mentioned, {@code flavor1} and {@code flavor2} are considered identical.
0090 * As such, asking a {@code Transferable} for either {@code DataFlavor} returns
0091 * the same results.
0092 * <p>
0093 * For more information on the using data transfer with Swing see
0094 * the <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/dnd.html">
0095 * How to Use Drag and Drop and Data Transfer</a>,
0096 * section in <em>Java Tutorial</em>.
0097 *
0098 * @version 1.90, 05/05/07
0099 * @author Blake Sullivan
0100 * @author Laurence P. G. Cable
0101 * @author Jeff Dunn
0102 */
0103 public class DataFlavor implements Externalizable, Cloneable {
0104
0105 private static final long serialVersionUID = 8367026044764648243L;
0106 private static final Class ioInputStreamClass = java.io.InputStream.class;
0107
0108 /**
0109 * Tries to load a class from: the bootstrap loader, the system loader,
0110 * the context loader (if one is present) and finally the loader specified.
0111 *
0112 * @param className the name of the class to be loaded
0113 * @param fallback the fallback loader
0114 * @return the class loaded
0115 * @exception ClassNotFoundException if class is not found
0116 */
0117 protected final static Class<?> tryToLoadClass(String className,
0118 ClassLoader fallback) throws ClassNotFoundException {
0119 ClassLoader systemClassLoader = (ClassLoader) java.security.AccessController
0120 .doPrivileged(new java.security.PrivilegedAction() {
0121 public Object run() {
0122 ClassLoader cl = Thread.currentThread()
0123 .getContextClassLoader();
0124 return (cl != null) ? cl : ClassLoader
0125 .getSystemClassLoader();
0126 }
0127 });
0128
0129 try {
0130 return Class.forName(className, true, systemClassLoader);
0131 } catch (ClassNotFoundException e2) {
0132 if (fallback != null) {
0133 return Class.forName(className, true, fallback);
0134 } else {
0135 throw new ClassNotFoundException(className);
0136 }
0137 }
0138 }
0139
0140 /*
0141 * private initializer
0142 */
0143 static private DataFlavor createConstant(Class rc, String prn) {
0144 try {
0145 return new DataFlavor(rc, prn);
0146 } catch (Exception e) {
0147 return null;
0148 }
0149 }
0150
0151 /*
0152 * private initializer
0153 */
0154 static private DataFlavor createConstant(String mt, String prn) {
0155 try {
0156 return new DataFlavor(mt, prn);
0157 } catch (Exception e) {
0158 return null;
0159 }
0160 }
0161
0162 /**
0163 * The <code>DataFlavor</code> representing a Java Unicode String class,
0164 * where:
0165 * <pre>
0166 * representationClass = java.lang.String
0167 * mimeType = "application/x-java-serialized-object"
0168 * </pre>
0169 */
0170 public static final DataFlavor stringFlavor = createConstant(
0171 java.lang.String.class, "Unicode String");
0172
0173 /**
0174 * The <code>DataFlavor</code> representing a Java Image class,
0175 * where:
0176 * <pre>
0177 * representationClass = java.awt.Image
0178 * mimeType = "image/x-java-image"
0179 * </pre>
0180 */
0181 public static final DataFlavor imageFlavor = createConstant(
0182 "image/x-java-image; class=java.awt.Image", "Image");
0183
0184 /**
0185 * The <code>DataFlavor</code> representing plain text with Unicode
0186 * encoding, where:
0187 * <pre>
0188 * representationClass = InputStream
0189 * mimeType = "text/plain; charset=unicode"
0190 * </pre>
0191 * This <code>DataFlavor</code> has been <b>deprecated</b> because
0192 * (1) Its representation is an InputStream, an 8-bit based representation,
0193 * while Unicode is a 16-bit character set; and (2) The charset "unicode"
0194 * is not well-defined. "unicode" implies a particular platform's
0195 * implementation of Unicode, not a cross-platform implementation.
0196 *
0197 * @deprecated as of 1.3. Use <code>DataFlavor.getReaderForText(Transferable)</code>
0198 * instead of <code>Transferable.getTransferData(DataFlavor.plainTextFlavor)</code>.
0199 */
0200 @Deprecated
0201 public static final DataFlavor plainTextFlavor = createConstant(
0202 "text/plain; charset=unicode; class=java.io.InputStream",
0203 "Plain Text");
0204
0205 /**
0206 * A MIME Content-Type of application/x-java-serialized-object represents
0207 * a graph of Java object(s) that have been made persistent.
0208 *
0209 * The representation class associated with this <code>DataFlavor</code>
0210 * identifies the Java type of an object returned as a reference
0211 * from an invocation <code>java.awt.datatransfer.getTransferData</code>.
0212 */
0213 public static final String javaSerializedObjectMimeType = "application/x-java-serialized-object";
0214
0215 /**
0216 * To transfer a list of files to/from Java (and the underlying
0217 * platform) a <code>DataFlavor</code> of this type/subtype and
0218 * representation class of <code>java.util.List</code> is used.
0219 * Each element of the list is required/guaranteed to be of type
0220 * <code>java.io.File</code>.
0221 */
0222 public static final DataFlavor javaFileListFlavor = createConstant(
0223 "application/x-java-file-list;class=java.util.List", null);
0224
0225 /**
0226 * To transfer a reference to an arbitrary Java object reference that
0227 * has no associated MIME Content-type, across a <code>Transferable</code>
0228 * interface WITHIN THE SAME JVM, a <code>DataFlavor</code>
0229 * with this type/subtype is used, with a <code>representationClass</code>
0230 * equal to the type of the class/interface being passed across the
0231 * <code>Transferable</code>.
0232 * <p>
0233 * The object reference returned from
0234 * <code>Transferable.getTransferData</code> for a <code>DataFlavor</code>
0235 * with this MIME Content-Type is required to be
0236 * an instance of the representation Class of the <code>DataFlavor</code>.
0237 */
0238 public static final String javaJVMLocalObjectMimeType = "application/x-java-jvm-local-objectref";
0239
0240 /**
0241 * In order to pass a live link to a Remote object via a Drag and Drop
0242 * <code>ACTION_LINK</code> operation a Mime Content Type of
0243 * application/x-java-remote-object should be used,
0244 * where the representation class of the <code>DataFlavor</code>
0245 * represents the type of the <code>Remote</code> interface to be
0246 * transferred.
0247 */
0248 public static final String javaRemoteObjectMimeType = "application/x-java-remote-object";
0249
0250 /**
0251 * Constructs a new <code>DataFlavor</code>. This constructor is
0252 * provided only for the purpose of supporting the
0253 * <code>Externalizable</code> interface. It is not
0254 * intended for public (client) use.
0255 *
0256 * @since 1.2
0257 */
0258 public DataFlavor() {
0259 super ();
0260 }
0261
0262 /**
0263 * Constructs a fully specified <code>DataFlavor</code>.
0264 *
0265 * @exception NullPointerException if either <code>primaryType</code>,
0266 * <code>subType</code> or <code>representationClass</code> is null
0267 */
0268 private DataFlavor(String primaryType, String subType,
0269 MimeTypeParameterList params, Class representationClass,
0270 String humanPresentableName) {
0271 super ();
0272 if (primaryType == null) {
0273 throw new NullPointerException("primaryType");
0274 }
0275 if (subType == null) {
0276 throw new NullPointerException("subType");
0277 }
0278 if (representationClass == null) {
0279 throw new NullPointerException("representationClass");
0280 }
0281
0282 if (params == null)
0283 params = new MimeTypeParameterList();
0284
0285 params.set("class", representationClass.getName());
0286
0287 if (humanPresentableName == null) {
0288 humanPresentableName = (String) params
0289 .get("humanPresentableName");
0290
0291 if (humanPresentableName == null)
0292 humanPresentableName = primaryType + "/" + subType;
0293 }
0294
0295 try {
0296 mimeType = new MimeType(primaryType, subType, params);
0297 } catch (MimeTypeParseException mtpe) {
0298 throw new IllegalArgumentException(
0299 "MimeType Parse Exception: " + mtpe.getMessage());
0300 }
0301
0302 this .representationClass = representationClass;
0303 this .humanPresentableName = humanPresentableName;
0304
0305 mimeType.removeParameter("humanPresentableName");
0306 }
0307
0308 /**
0309 * Constructs a <code>DataFlavor</code> that represents a Java class.
0310 * <p>
0311 * The returned <code>DataFlavor</code> will have the following
0312 * characteristics:
0313 * <pre>
0314 * representationClass = representationClass
0315 * mimeType = application/x-java-serialized-object
0316 * </pre>
0317 * @param representationClass the class used to transfer data in this flavor
0318 * @param humanPresentableName the human-readable string used to identify
0319 * this flavor; if this parameter is <code>null</code>
0320 * then the value of the the MIME Content Type is used
0321 * @exception NullPointerException if <code>representationClass</code> is null
0322 */
0323 public DataFlavor(Class<?> representationClass,
0324 String humanPresentableName) {
0325 this ("application", "x-java-serialized-object", null,
0326 representationClass, humanPresentableName);
0327 if (representationClass == null) {
0328 throw new NullPointerException("representationClass");
0329 }
0330 }
0331
0332 /**
0333 * Constructs a <code>DataFlavor</code> that represents a
0334 * <code>MimeType</code>.
0335 * <p>
0336 * The returned <code>DataFlavor</code> will have the following
0337 * characteristics:
0338 * <p>
0339 * If the <code>mimeType</code> is
0340 * "application/x-java-serialized-object; class=<representation class>",
0341 * the result is the same as calling
0342 * <code>new DataFlavor(Class:forName(<representation class>)</code>.
0343 * <p>
0344 * Otherwise:
0345 * <pre>
0346 * representationClass = InputStream
0347 * mimeType = mimeType
0348 * </pre>
0349 * @param mimeType the string used to identify the MIME type for this flavor;
0350 * if the the <code>mimeType</code> does not specify a
0351 * "class=" parameter, or if the class is not successfully
0352 * loaded, then an <code>IllegalArgumentException</code>
0353 * is thrown
0354 * @param humanPresentableName the human-readable string used to identify
0355 * this flavor; if this parameter is <code>null</code>
0356 * then the value of the the MIME Content Type is used
0357 * @exception IllegalArgumentException if <code>mimeType</code> is
0358 * invalid or if the class is not successfully loaded
0359 * @exception NullPointerException if <code>mimeType</code> is null
0360 */
0361 public DataFlavor(String mimeType, String humanPresentableName) {
0362 super ();
0363 if (mimeType == null) {
0364 throw new NullPointerException("mimeType");
0365 }
0366 try {
0367 initialize(mimeType, humanPresentableName, this .getClass()
0368 .getClassLoader());
0369 } catch (MimeTypeParseException mtpe) {
0370 throw new IllegalArgumentException("failed to parse:"
0371 + mimeType);
0372 } catch (ClassNotFoundException cnfe) {
0373 throw new IllegalArgumentException(
0374 "can't find specified class: " + cnfe.getMessage());
0375 }
0376 }
0377
0378 /**
0379 * Constructs a <code>DataFlavor</code> that represents a
0380 * <code>MimeType</code>.
0381 * <p>
0382 * The returned <code>DataFlavor</code> will have the following
0383 * characteristics:
0384 * <p>
0385 * If the mimeType is
0386 * "application/x-java-serialized-object; class=<representation class>",
0387 * the result is the same as calling
0388 * <code>new DataFlavor(Class:forName(<representation class>)</code>.
0389 * <p>
0390 * Otherwise:
0391 * <pre>
0392 * representationClass = InputStream
0393 * mimeType = mimeType
0394 * </pre>
0395 * @param mimeType the string used to identify the MIME type for this flavor
0396 * @param humanPresentableName the human-readable string used to
0397 * identify this flavor
0398 * @param classLoader the class loader to use
0399 * @exception ClassNotFoundException if the class is not loaded
0400 * @exception IllegalArgumentException if <code>mimeType</code> is
0401 * invalid
0402 * @exception NullPointerException if <code>mimeType</code> is null
0403 */
0404 public DataFlavor(String mimeType, String humanPresentableName,
0405 ClassLoader classLoader) throws ClassNotFoundException {
0406 super ();
0407 if (mimeType == null) {
0408 throw new NullPointerException("mimeType");
0409 }
0410 try {
0411 initialize(mimeType, humanPresentableName, classLoader);
0412 } catch (MimeTypeParseException mtpe) {
0413 throw new IllegalArgumentException("failed to parse:"
0414 + mimeType);
0415 }
0416 }
0417
0418 /**
0419 * Constructs a <code>DataFlavor</code> from a <code>mimeType</code> string.
0420 * The string can specify a "class=<fully specified Java class name>"
0421 * parameter to create a <code>DataFlavor</code> with the desired
0422 * representation class. If the string does not contain "class=" parameter,
0423 * <code>java.io.InputStream</code> is used as default.
0424 *
0425 * @param mimeType the string used to identify the MIME type for this flavor;
0426 * if the class specified by "class=" parameter is not
0427 * successfully loaded, then an
0428 * <code>ClassNotFoundException</code> is thrown
0429 * @exception ClassNotFoundException if the class is not loaded
0430 * @exception IllegalArgumentException if <code>mimeType</code> is
0431 * invalid
0432 * @exception NullPointerException if <code>mimeType</code> is null
0433 */
0434 public DataFlavor(String mimeType) throws ClassNotFoundException {
0435 super ();
0436 if (mimeType == null) {
0437 throw new NullPointerException("mimeType");
0438 }
0439 try {
0440 initialize(mimeType, null, this .getClass().getClassLoader());
0441 } catch (MimeTypeParseException mtpe) {
0442 throw new IllegalArgumentException("failed to parse:"
0443 + mimeType);
0444 }
0445 }
0446
0447 /**
0448 * Common initialization code called from various constructors.
0449 *
0450 * @param mimeType the MIME Content Type (must have a class= param)
0451 * @param humanPresentableName the human Presentable Name or
0452 * <code>null</code>
0453 * @param classLoader the fallback class loader to resolve against
0454 *
0455 * @throws MimeTypeParseException
0456 * @throws ClassNotFoundException
0457 * @throws NullPointerException if <code>mimeType</code> is null
0458 *
0459 * @see tryToLoadClass
0460 */
0461 private void initialize(String mimeType,
0462 String humanPresentableName, ClassLoader classLoader)
0463 throws MimeTypeParseException, ClassNotFoundException {
0464 if (mimeType == null) {
0465 throw new NullPointerException("mimeType");
0466 }
0467
0468 this .mimeType = new MimeType(mimeType); // throws
0469
0470 String rcn = getParameter("class");
0471
0472 if (rcn == null) {
0473 if ("application/x-java-serialized-object"
0474 .equals(this .mimeType.getBaseType()))
0475
0476 throw new IllegalArgumentException(
0477 "no representation class specified for:"
0478 + mimeType);
0479 else
0480 representationClass = java.io.InputStream.class; // default
0481 } else { // got a class name
0482 representationClass = DataFlavor.tryToLoadClass(rcn,
0483 classLoader);
0484 }
0485
0486 this .mimeType.setParameter("class", representationClass
0487 .getName());
0488
0489 if (humanPresentableName == null) {
0490 humanPresentableName = this .mimeType
0491 .getParameter("humanPresentableName");
0492 if (humanPresentableName == null)
0493 humanPresentableName = this .mimeType.getPrimaryType()
0494 + "/" + this .mimeType.getSubType();
0495 }
0496
0497 this .humanPresentableName = humanPresentableName; // set it.
0498
0499 this .mimeType.removeParameter("humanPresentableName"); // just in case
0500 }
0501
0502 /**
0503 * String representation of this <code>DataFlavor</code> and its
0504 * parameters. The resulting <code>String</code> contains the name of
0505 * the <code>DataFlavor</code> class, this flavor's MIME type, and its
0506 * representation class. If this flavor has a primary MIME type of "text",
0507 * supports the charset parameter, and has an encoded representation, the
0508 * flavor's charset is also included. See <code>selectBestTextFlavor</code>
0509 * for a list of text flavors which support the charset parameter.
0510 *
0511 * @return string representation of this <code>DataFlavor</code>
0512 * @see #selectBestTextFlavor
0513 */
0514 public String toString() {
0515 String string = getClass().getName();
0516 string += "[" + paramString() + "]";
0517 return string;
0518 }
0519
0520 private String paramString() {
0521 String params = "";
0522 params += "mimetype=";
0523 if (mimeType == null) {
0524 params += "null";
0525 } else {
0526 params += mimeType.getBaseType();
0527 }
0528 params += ";representationclass=";
0529 if (representationClass == null) {
0530 params += "null";
0531 } else {
0532 params += representationClass.getName();
0533 }
0534 if (DataTransferer.isFlavorCharsetTextType(this )
0535 && (isRepresentationClassInputStream()
0536 || isRepresentationClassByteBuffer() || DataTransferer.byteArrayClass
0537 .equals(representationClass))) {
0538 params += ";charset=" + DataTransferer.getTextCharset(this );
0539 }
0540 return params;
0541 }
0542
0543 /**
0544 * Returns a <code>DataFlavor</code> representing plain text with Unicode
0545 * encoding, where:
0546 * <pre>
0547 * representationClass = java.io.InputStream
0548 * mimeType = "text/plain;
0549 * charset=<platform default Unicode encoding>"
0550 * </pre>
0551 * Sun's implementation for Microsoft Windows uses the encoding <code>utf-16le</code>.
0552 * Sun's implementation for Solaris and Linux uses the encoding
0553 * <code>iso-10646-ucs-2</code>.
0554 *
0555 * @return a <code>DataFlavor</code> representing plain text
0556 * with Unicode encoding
0557 * @since 1.3
0558 */
0559 public static final DataFlavor getTextPlainUnicodeFlavor() {
0560 String encoding = null;
0561 DataTransferer transferer = DataTransferer.getInstance();
0562 if (transferer != null) {
0563 encoding = transferer.getDefaultUnicodeEncoding();
0564 }
0565 return new DataFlavor("text/plain;charset=" + encoding
0566 + ";class=java.io.InputStream", "Plain Text");
0567 }
0568
0569 /**
0570 * Selects the best text <code>DataFlavor</code> from an array of <code>
0571 * DataFlavor</code>s. Only <code>DataFlavor.stringFlavor</code>, and
0572 * equivalent flavors, and flavors that have a primary MIME type of "text",
0573 * are considered for selection.
0574 * <p>
0575 * Flavors are first sorted by their MIME types in the following order:
0576 * <ul>
0577 * <li>"text/sgml"
0578 * <li>"text/xml"
0579 * <li>"text/html"
0580 * <li>"text/rtf"
0581 * <li>"text/enriched"
0582 * <li>"text/richtext"
0583 * <li>"text/uri-list"
0584 * <li>"text/tab-separated-values"
0585 * <li>"text/t140"
0586 * <li>"text/rfc822-headers"
0587 * <li>"text/parityfec"
0588 * <li>"text/directory"
0589 * <li>"text/css"
0590 * <li>"text/calendar"
0591 * <li>"application/x-java-serialized-object"
0592 * <li>"text/plain"
0593 * <li>"text/<other>"
0594 * </ul>
0595 * <p>For example, "text/sgml" will be selected over
0596 * "text/html", and <code>DataFlavor.stringFlavor</code> will be chosen
0597 * over <code>DataFlavor.plainTextFlavor</code>.
0598 * <p>
0599 * If two or more flavors share the best MIME type in the array, then that
0600 * MIME type will be checked to see if it supports the charset parameter.
0601 * <p>
0602 * The following MIME types support, or are treated as though they support,
0603 * the charset parameter:
0604 * <ul>
0605 * <li>"text/sgml"
0606 * <li>"text/xml"
0607 * <li>"text/html"
0608 * <li>"text/enriched"
0609 * <li>"text/richtext"
0610 * <li>"text/uri-list"
0611 * <li>"text/directory"
0612 * <li>"text/css"
0613 * <li>"text/calendar"
0614 * <li>"application/x-java-serialized-object"
0615 * <li>"text/plain"
0616 * </ul>
0617 * The following MIME types do not support, or are treated as though they
0618 * do not support, the charset parameter:
0619 * <ul>
0620 * <li>"text/rtf"
0621 * <li>"text/tab-separated-values"
0622 * <li>"text/t140"
0623 * <li>"text/rfc822-headers"
0624 * <li>"text/parityfec"
0625 * </ul>
0626 * For "text/<other>" MIME types, the first time the JRE needs to
0627 * determine whether the MIME type supports the charset parameter, it will
0628 * check whether the parameter is explicitly listed in an arbitrarily
0629 * chosen <code>DataFlavor</code> which uses that MIME type. If so, the JRE
0630 * will assume from that point on that the MIME type supports the charset
0631 * parameter and will not check again. If the parameter is not explicitly
0632 * listed, the JRE will assume from that point on that the MIME type does
0633 * not support the charset parameter and will not check again. Because
0634 * this check is performed on an arbitrarily chosen
0635 * <code>DataFlavor</code>, developers must ensure that all
0636 * <code>DataFlavor</code>s with a "text/<other>" MIME type specify
0637 * the charset parameter if it is supported by that MIME type. Developers
0638 * should never rely on the JRE to substitute the platform's default
0639 * charset for a "text/<other>" DataFlavor. Failure to adhere to this
0640 * restriction will lead to undefined behavior.
0641 * <p>
0642 * If the best MIME type in the array does not support the charset
0643 * parameter, the flavors which share that MIME type will then be sorted by
0644 * their representation classes in the following order:
0645 * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
0646 * <code>[B</code>, <all others>.
0647 * <p>
0648 * If two or more flavors share the best representation class, or if no
0649 * flavor has one of the three specified representations, then one of those
0650 * flavors will be chosen non-deterministically.
0651 * <p>
0652 * If the best MIME type in the array does support the charset parameter,
0653 * the flavors which share that MIME type will then be sorted by their
0654 * representation classes in the following order:
0655 * <code>java.io.Reader</code>, <code>java.lang.String</code>,
0656 * <code>java.nio.CharBuffer</code>, <code>[C</code>, <all others>.
0657 * <p>
0658 * If two or more flavors share the best representation class, and that
0659 * representation is one of the four explicitly listed, then one of those
0660 * flavors will be chosen non-deterministically. If, however, no flavor has
0661 * one of the four specified representations, the flavors will then be
0662 * sorted by their charsets. Unicode charsets, such as "UTF-16", "UTF-8",
0663 * "UTF-16BE", "UTF-16LE", and their aliases, are considered best. After
0664 * them, the platform default charset and its aliases are selected.
0665 * "US-ASCII" and its aliases are worst. All other charsets are chosen in
0666 * alphabetical order, but only charsets supported by this implementation
0667 * of the Java platform will be considered.
0668 * <p>
0669 * If two or more flavors share the best charset, the flavors will then
0670 * again be sorted by their representation classes in the following order:
0671 * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
0672 * <code>[B</code>, <all others>.
0673 * <p>
0674 * If two or more flavors share the best representation class, or if no
0675 * flavor has one of the three specified representations, then one of those
0676 * flavors will be chosen non-deterministically.
0677 *
0678 * @param availableFlavors an array of available <code>DataFlavor</code>s
0679 * @return the best (highest fidelity) flavor according to the rules
0680 * specified above, or <code>null</code>,
0681 * if <code>availableFlavors</code> is <code>null</code>,
0682 * has zero length, or contains no text flavors
0683 * @since 1.3
0684 */
0685 public static final DataFlavor selectBestTextFlavor(
0686 DataFlavor[] availableFlavors) {
0687 if (availableFlavors == null || availableFlavors.length == 0) {
0688 return null;
0689 }
0690
0691 if (textFlavorComparator == null) {
0692 textFlavorComparator = new TextFlavorComparator();
0693 }
0694
0695 DataFlavor bestFlavor = (DataFlavor) Collections.max(Arrays
0696 .asList(availableFlavors), textFlavorComparator);
0697
0698 if (!bestFlavor.isFlavorTextType()) {
0699 return null;
0700 }
0701
0702 return bestFlavor;
0703 }
0704
0705 private static Comparator textFlavorComparator;
0706
0707 static class TextFlavorComparator extends
0708 DataTransferer.DataFlavorComparator {
0709
0710 /**
0711 * Compares two <code>DataFlavor</code> objects. Returns a negative
0712 * integer, zero, or a positive integer as the first
0713 * <code>DataFlavor</code> is worse than, equal to, or better than the
0714 * second.
0715 * <p>
0716 * <code>DataFlavor</code>s are ordered according to the rules outlined
0717 * for <code>selectBestTextFlavor</code>.
0718 *
0719 * @param obj1 the first <code>DataFlavor</code> to be compared
0720 * @param obj2 the second <code>DataFlavor</code> to be compared
0721 * @return a negative integer, zero, or a positive integer as the first
0722 * argument is worse, equal to, or better than the second
0723 * @throws ClassCastException if either of the arguments is not an
0724 * instance of <code>DataFlavor</code>
0725 * @throws NullPointerException if either of the arguments is
0726 * <code>null</code>
0727 *
0728 * @see #selectBestTextFlavor
0729 */
0730 public int compare(Object obj1, Object obj2) {
0731 DataFlavor flavor1 = (DataFlavor) obj1;
0732 DataFlavor flavor2 = (DataFlavor) obj2;
0733
0734 if (flavor1.isFlavorTextType()) {
0735 if (flavor2.isFlavorTextType()) {
0736 return super .compare(obj1, obj2);
0737 } else {
0738 return 1;
0739 }
0740 } else if (flavor2.isFlavorTextType()) {
0741 return -1;
0742 } else {
0743 return 0;
0744 }
0745 }
0746 }
0747
0748 /**
0749 * Gets a Reader for a text flavor, decoded, if necessary, for the expected
0750 * charset (encoding). The supported representation classes are
0751 * <code>java.io.Reader</code>, <code>java.lang.String</code>,
0752 * <code>java.nio.CharBuffer</code>, <code>[C</code>,
0753 * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
0754 * and <code>[B</code>.
0755 * <p>
0756 * Because text flavors which do not support the charset parameter are
0757 * encoded in a non-standard format, this method should not be called for
0758 * such flavors. However, in order to maintain backward-compatibility,
0759 * if this method is called for such a flavor, this method will treat the
0760 * flavor as though it supports the charset parameter and attempt to
0761 * decode it accordingly. See <code>selectBestTextFlavor</code> for a list
0762 * of text flavors which do not support the charset parameter.
0763 *
0764 * @param transferable the <code>Transferable</code> whose data will be
0765 * requested in this flavor
0766 *
0767 * @return a <code>Reader</code> to read the <code>Transferable</code>'s
0768 * data
0769 *
0770 * @exception IllegalArgumentException if the representation class
0771 * is not one of the seven listed above
0772 * @exception IllegalArgumentException if the <code>Transferable</code>
0773 * has <code>null</code> data
0774 * @exception NullPointerException if the <code>Transferable</code> is
0775 * <code>null</code>
0776 * @exception UnsupportedEncodingException if this flavor's representation
0777 * is <code>java.io.InputStream</code>,
0778 * <code>java.nio.ByteBuffer</code>, or <code>[B</code> and
0779 * this flavor's encoding is not supported by this
0780 * implementation of the Java platform
0781 * @exception UnsupportedFlavorException if the <code>Transferable</code>
0782 * does not support this flavor
0783 * @exception IOException if the data cannot be read because of an
0784 * I/O error
0785 * @see #selectBestTextFlavor
0786 * @since 1.3
0787 */
0788 public Reader getReaderForText(Transferable transferable)
0789 throws UnsupportedFlavorException, IOException {
0790 Object transferObject = transferable.getTransferData(this );
0791 if (transferObject == null) {
0792 throw new IllegalArgumentException(
0793 "getTransferData() returned null");
0794 }
0795
0796 if (transferObject instanceof Reader) {
0797 return (Reader) transferObject;
0798 } else if (transferObject instanceof String) {
0799 return new StringReader((String) transferObject);
0800 } else if (transferObject instanceof CharBuffer) {
0801 CharBuffer buffer = (CharBuffer) transferObject;
0802 int size = buffer.remaining();
0803 char[] chars = new char[size];
0804 buffer.get(chars, 0, size);
0805 return new CharArrayReader(chars);
0806 } else if (transferObject instanceof char[]) {
0807 return new CharArrayReader((char[]) transferObject);
0808 }
0809
0810 InputStream stream = null;
0811
0812 if (transferObject instanceof InputStream) {
0813 stream = (InputStream) transferObject;
0814 } else if (transferObject instanceof ByteBuffer) {
0815 ByteBuffer buffer = (ByteBuffer) transferObject;
0816 int size = buffer.remaining();
0817 byte[] bytes = new byte[size];
0818 buffer.get(bytes, 0, size);
0819 stream = new ByteArrayInputStream(bytes);
0820 } else if (transferObject instanceof byte[]) {
0821 stream = new ByteArrayInputStream((byte[]) transferObject);
0822 }
0823
0824 if (stream == null) {
0825 throw new IllegalArgumentException(
0826 "transfer data is not Reader, String, CharBuffer, char array, InputStream, ByteBuffer, or byte array");
0827 }
0828
0829 String encoding = getParameter("charset");
0830 return (encoding == null) ? new InputStreamReader(stream)
0831 : new InputStreamReader(stream, encoding);
0832 }
0833
0834 /**
0835 * Returns the MIME type string for this <code>DataFlavor</code>.
0836 * @return the MIME type string for this flavor
0837 */
0838 public String getMimeType() {
0839 return (mimeType != null) ? mimeType.toString() : null;
0840 }
0841
0842 /**
0843 * Returns the <code>Class</code> which objects supporting this
0844 * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
0845 * is requested.
0846 * @return the <code>Class</code> which objects supporting this
0847 * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
0848 * is requested
0849 */
0850 public Class<?> getRepresentationClass() {
0851 return representationClass;
0852 }
0853
0854 /**
0855 * Returns the human presentable name for the data format that this
0856 * <code>DataFlavor</code> represents. This name would be localized
0857 * for different countries.
0858 * @return the human presentable name for the data format that this
0859 * <code>DataFlavor</code> represents
0860 */
0861 public String getHumanPresentableName() {
0862 return humanPresentableName;
0863 }
0864
0865 /**
0866 * Returns the primary MIME type for this <code>DataFlavor</code>.
0867 * @return the primary MIME type of this <code>DataFlavor</code>
0868 */
0869 public String getPrimaryType() {
0870 return (mimeType != null) ? mimeType.getPrimaryType() : null;
0871 }
0872
0873 /**
0874 * Returns the sub MIME type of this <code>DataFlavor</code>.
0875 * @return the Sub MIME type of this <code>DataFlavor</code>
0876 */
0877 public String getSubType() {
0878 return (mimeType != null) ? mimeType.getSubType() : null;
0879 }
0880
0881 /**
0882 * Returns the human presentable name for this <code>DataFlavor</code>
0883 * if <code>paramName</code> equals "humanPresentableName". Otherwise
0884 * returns the MIME type value associated with <code>paramName</code>.
0885 *
0886 * @param paramName the parameter name requested
0887 * @return the value of the name parameter, or <code>null</code>
0888 * if there is no associated value
0889 */
0890 public String getParameter(String paramName) {
0891 if (paramName.equals("humanPresentableName")) {
0892 return humanPresentableName;
0893 } else {
0894 return (mimeType != null) ? mimeType
0895 .getParameter(paramName) : null;
0896 }
0897 }
0898
0899 /**
0900 * Sets the human presentable name for the data format that this
0901 * <code>DataFlavor</code> represents. This name would be localized
0902 * for different countries.
0903 * @param humanPresentableName the new human presentable name
0904 */
0905 public void setHumanPresentableName(String humanPresentableName) {
0906 this .humanPresentableName = humanPresentableName;
0907 }
0908
0909 /**
0910 * {@inheritDoc}
0911 * <p>
0912 * The equals comparison for the {@code DataFlavor} class is implemented
0913 * as follows: Two <code>DataFlavor</code>s are considered equal if and
0914 * only if their MIME primary type and subtype and representation class are
0915 * equal. Additionally, if the primary type is "text", the subtype denotes
0916 * a text flavor which supports the charset parameter, and the
0917 * representation class is not <code>java.io.Reader</code>,
0918 * <code>java.lang.String</code>, <code>java.nio.CharBuffer</code>, or
0919 * <code>[C</code>, the <code>charset</code> parameter must also be equal.
0920 * If a charset is not explicitly specified for one or both
0921 * <code>DataFlavor</code>s, the platform default encoding is assumed. See
0922 * <code>selectBestTextFlavor</code> for a list of text flavors which
0923 * support the charset parameter.
0924 *
0925 * @param o the <code>Object</code> to compare with <code>this</code>
0926 * @return <code>true</code> if <code>that</code> is equivalent to this
0927 * <code>DataFlavor</code>; <code>false</code> otherwise
0928 * @see #selectBestTextFlavor
0929 */
0930 public boolean equals(Object o) {
0931 return ((o instanceof DataFlavor) && equals((DataFlavor) o));
0932 }
0933
0934 /**
0935 * This method has the same behavior as {@link #equals(Object)}.
0936 * The only difference being that it takes a {@code DataFlavor} instance
0937 * as a parameter.
0938 *
0939 * @param that the <code>DataFlavor</code> to compare with
0940 * <code>this</code>
0941 * @return <code>true</code> if <code>that</code> is equivalent to this
0942 * <code>DataFlavor</code>; <code>false</code> otherwise
0943 * @see #selectBestTextFlavor
0944 */
0945 public boolean equals(DataFlavor that) {
0946 if (that == null) {
0947 return false;
0948 }
0949 if (this == that) {
0950 return true;
0951 }
0952
0953 if (representationClass == null) {
0954 if (that.getRepresentationClass() != null) {
0955 return false;
0956 }
0957 } else {
0958 if (!representationClass.equals(that
0959 .getRepresentationClass())) {
0960 return false;
0961 }
0962 }
0963
0964 if (mimeType == null) {
0965 if (that.mimeType != null) {
0966 return false;
0967 }
0968 } else {
0969 if (!mimeType.match(that.mimeType)) {
0970 return false;
0971 }
0972
0973 if ("text".equals(getPrimaryType())
0974 && DataTransferer.doesSubtypeSupportCharset(this )
0975 && representationClass != null
0976 && !(isRepresentationClassReader()
0977 || String.class.equals(representationClass)
0978 || isRepresentationClassCharBuffer() || DataTransferer.charArrayClass
0979 .equals(representationClass))) {
0980 String this Charset = DataTransferer
0981 .canonicalName(getParameter("charset"));
0982 String thatCharset = DataTransferer.canonicalName(that
0983 .getParameter("charset"));
0984 if (this Charset == null) {
0985 if (thatCharset != null) {
0986 return false;
0987 }
0988 } else {
0989 if (!this Charset.equals(thatCharset)) {
0990 return false;
0991 }
0992 }
0993 }
0994 }
0995
0996 return true;
0997 }
0998
0999 /**
1000 * Compares only the <code>mimeType</code> against the passed in
1001 * <code>String</code> and <code>representationClass</code> is
1002 * not considered in the comparison.
1003 *
1004 * If <code>representationClass</code> needs to be compared, then
1005 * <code>equals(new DataFlavor(s))</code> may be used.
1006 * @deprecated As inconsistent with <code>hashCode()</code> contract,
1007 * use <code>isMimeTypeEqual(String)</code> instead.
1008 * @param s the {@code mimeType} to compare.
1009 * @return true if the String (MimeType) is equal; false otherwise or if
1010 * {@code s} is {@code null}
1011 */
1012 @Deprecated
1013 public boolean equals(String s) {
1014 if (s == null || mimeType == null)
1015 return false;
1016 return isMimeTypeEqual(s);
1017 }
1018
1019 /**
1020 * Returns hash code for this <code>DataFlavor</code>.
1021 * For two equal <code>DataFlavor</code>s, hash codes are equal.
1022 * For the <code>String</code>
1023 * that matches <code>DataFlavor.equals(String)</code>, it is not
1024 * guaranteed that <code>DataFlavor</code>'s hash code is equal
1025 * to the hash code of the <code>String</code>.
1026 *
1027 * @return a hash code for this <code>DataFlavor</code>
1028 */
1029 public int hashCode() {
1030 int total = 0;
1031
1032 if (representationClass != null) {
1033 total += representationClass.hashCode();
1034 }
1035
1036 if (mimeType != null) {
1037 String primaryType = mimeType.getPrimaryType();
1038 if (primaryType != null) {
1039 total += primaryType.hashCode();
1040 }
1041
1042 // Do not add subType.hashCode() to the total. equals uses
1043 // MimeType.match which reports a match if one or both of the
1044 // subTypes is '*', regardless of the other subType.
1045
1046 if ("text".equals(primaryType)
1047 && DataTransferer.doesSubtypeSupportCharset(this )
1048 && representationClass != null
1049 && !(isRepresentationClassReader()
1050 || String.class.equals(representationClass)
1051 || isRepresentationClassCharBuffer() || DataTransferer.charArrayClass
1052 .equals(representationClass))) {
1053 String charset = DataTransferer
1054 .canonicalName(getParameter("charset"));
1055 if (charset != null) {
1056 total += charset.hashCode();
1057 }
1058 }
1059 }
1060
1061 return total;
1062 }
1063
1064 /**
1065 * Identical to {@link #equals(DataFlavor)}.
1066 *
1067 * @param that the <code>DataFlavor</code> to compare with
1068 * <code>this</code>
1069 * @return <code>true</code> if <code>that</code> is equivalent to this
1070 * <code>DataFlavor</code>; <code>false</code> otherwise
1071 * @see #selectBestTextFlavor
1072 * @since 1.3
1073 */
1074 public boolean match(DataFlavor that) {
1075 return equals(that);
1076 }
1077
1078 /**
1079 * Returns whether the string representation of the MIME type passed in
1080 * is equivalent to the MIME type of this <code>DataFlavor</code>.
1081 * Parameters are not included in the comparison.
1082 *
1083 * @param mimeType the string representation of the MIME type
1084 * @return true if the string representation of the MIME type passed in is
1085 * equivalent to the MIME type of this <code>DataFlavor</code>;
1086 * false otherwise
1087 * @throws NullPointerException if mimeType is <code>null</code>
1088 */
1089 public boolean isMimeTypeEqual(String mimeType) {
1090 // JCK Test DataFlavor0117: if 'mimeType' is null, throw NPE
1091 if (mimeType == null) {
1092 throw new NullPointerException("mimeType");
1093 }
1094 if (this .mimeType == null) {
1095 return false;
1096 }
1097 try {
1098 return this .mimeType.match(new MimeType(mimeType));
1099 } catch (MimeTypeParseException mtpe) {
1100 return false;
1101 }
1102 }
1103
1104 /**
1105 * Compares the <code>mimeType</code> of two <code>DataFlavor</code>
1106 * objects. No parameters are considered.
1107 *
1108 * @param dataFlavor the <code>DataFlavor</code> to be compared
1109 * @return true if the <code>MimeType</code>s are equal,
1110 * otherwise false
1111 */
1112
1113 public final boolean isMimeTypeEqual(DataFlavor dataFlavor) {
1114 return isMimeTypeEqual(dataFlavor.mimeType);
1115 }
1116
1117 /**
1118 * Compares the <code>mimeType</code> of two <code>DataFlavor</code>
1119 * objects. No parameters are considered.
1120 *
1121 * @return true if the <code>MimeType</code>s are equal,
1122 * otherwise false
1123 */
1124
1125 private boolean isMimeTypeEqual(MimeType mtype) {
1126 if (this .mimeType == null) {
1127 return (mtype == null);
1128 }
1129 return mimeType.match(mtype);
1130 }
1131
1132 /**
1133 * Does the <code>DataFlavor</code> represent a serialized object?
1134 */
1135
1136 public boolean isMimeTypeSerializedObject() {
1137 return isMimeTypeEqual(javaSerializedObjectMimeType);
1138 }
1139
1140 public final Class<?> getDefaultRepresentationClass() {
1141 return ioInputStreamClass;
1142 }
1143
1144 public final String getDefaultRepresentationClassAsString() {
1145 return getDefaultRepresentationClass().getName();
1146 }
1147
1148 /**
1149 * Does the <code>DataFlavor</code> represent a
1150 * <code>java.io.InputStream</code>?
1151 */
1152
1153 public boolean isRepresentationClassInputStream() {
1154 return ioInputStreamClass.isAssignableFrom(representationClass);
1155 }
1156
1157 /**
1158 * Returns whether the representation class for this
1159 * <code>DataFlavor</code> is <code>java.io.Reader</code> or a subclass
1160 * thereof.
1161 *
1162 * @since 1.4
1163 */
1164 public boolean isRepresentationClassReader() {
1165 return java.io.Reader.class
1166 .isAssignableFrom(representationClass);
1167 }
1168
1169 /**
1170 * Returns whether the representation class for this
1171 * <code>DataFlavor</code> is <code>java.nio.CharBuffer</code> or a
1172 * subclass thereof.
1173 *
1174 * @since 1.4
1175 */
1176 public boolean isRepresentationClassCharBuffer() {
1177 return java.nio.CharBuffer.class
1178 .isAssignableFrom(representationClass);
1179 }
1180
1181 /**
1182 * Returns whether the representation class for this
1183 * <code>DataFlavor</code> is <code>java.nio.ByteBuffer</code> or a
1184 * subclass thereof.
1185 *
1186 * @since 1.4
1187 */
1188 public boolean isRepresentationClassByteBuffer() {
1189 return java.nio.ByteBuffer.class
1190 .isAssignableFrom(representationClass);
1191 }
1192
1193 /**
1194 * Returns true if the representation class can be serialized.
1195 * @return true if the representation class can be serialized
1196 */
1197
1198 public boolean isRepresentationClassSerializable() {
1199 return java.io.Serializable.class
1200 .isAssignableFrom(representationClass);
1201 }
1202
1203 /**
1204 * Returns true if the representation class is <code>Remote</code>.
1205 * @return true if the representation class is <code>Remote</code>
1206 */
1207
1208 public boolean isRepresentationClassRemote() {
1209 return java.rmi.Remote.class
1210 .isAssignableFrom(representationClass);
1211 }
1212
1213 /**
1214 * Returns true if the <code>DataFlavor</code> specified represents
1215 * a serialized object.
1216 * @return true if the <code>DataFlavor</code> specified represents
1217 * a Serialized Object
1218 */
1219
1220 public boolean isFlavorSerializedObjectType() {
1221 return isRepresentationClassSerializable()
1222 && isMimeTypeEqual(javaSerializedObjectMimeType);
1223 }
1224
1225 /**
1226 * Returns true if the <code>DataFlavor</code> specified represents
1227 * a remote object.
1228 * @return true if the <code>DataFlavor</code> specified represents
1229 * a Remote Object
1230 */
1231
1232 public boolean isFlavorRemoteObjectType() {
1233 return isRepresentationClassRemote()
1234 && isRepresentationClassSerializable()
1235 && isMimeTypeEqual(javaRemoteObjectMimeType);
1236 }
1237
1238 /**
1239 * Returns true if the <code>DataFlavor</code> specified represents
1240 * a list of file objects.
1241 * @return true if the <code>DataFlavor</code> specified represents
1242 * a List of File objects
1243 */
1244
1245 public boolean isFlavorJavaFileListType() {
1246 if (mimeType == null || representationClass == null)
1247 return false;
1248 return java.util.List.class
1249 .isAssignableFrom(representationClass)
1250 && mimeType.match(javaFileListFlavor.mimeType);
1251
1252 }
1253
1254 /**
1255 * Returns whether this <code>DataFlavor</code> is a valid text flavor for
1256 * this implementation of the Java platform. Only flavors equivalent to
1257 * <code>DataFlavor.stringFlavor</code> and <code>DataFlavor</code>s with
1258 * a primary MIME type of "text" can be valid text flavors.
1259 * <p>
1260 * If this flavor supports the charset parameter, it must be equivalent to
1261 * <code>DataFlavor.stringFlavor</code>, or its representation must be
1262 * <code>java.io.Reader</code>, <code>java.lang.String</code>,
1263 * <code>java.nio.CharBuffer</code>, <code>[C</code>,
1264 * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
1265 * <code>[B</code>. If the representation is
1266 * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
1267 * <code>[B</code>, then this flavor's <code>charset</code> parameter must
1268 * be supported by this implementation of the Java platform. If a charset
1269 * is not specified, then the platform default charset, which is always
1270 * supported, is assumed.
1271 * <p>
1272 * If this flavor does not support the charset parameter, its
1273 * representation must be <code>java.io.InputStream</code>,
1274 * <code>java.nio.ByteBuffer</code>, or <code>[B</code>.
1275 * <p>
1276 * See <code>selectBestTextFlavor</code> for a list of text flavors which
1277 * support the charset parameter.
1278 *
1279 * @return <code>true</code> if this <code>DataFlavor</code> is a valid
1280 * text flavor as described above; <code>false</code> otherwise
1281 * @see #selectBestTextFlavor
1282 * @since 1.4
1283 */
1284 public boolean isFlavorTextType() {
1285 return (DataTransferer.isFlavorCharsetTextType(this ) || DataTransferer
1286 .isFlavorNoncharsetTextType(this ));
1287 }
1288
1289 /**
1290 * Serializes this <code>DataFlavor</code>.
1291 */
1292
1293 public synchronized void writeExternal(ObjectOutput os)
1294 throws IOException {
1295 if (mimeType != null) {
1296 mimeType.setParameter("humanPresentableName",
1297 humanPresentableName);
1298 os.writeObject(mimeType);
1299 mimeType.removeParameter("humanPresentableName");
1300 } else {
1301 os.writeObject(null);
1302 }
1303
1304 os.writeObject(representationClass);
1305 }
1306
1307 /**
1308 * Restores this <code>DataFlavor</code> from a Serialized state.
1309 */
1310
1311 public synchronized void readExternal(ObjectInput is)
1312 throws IOException, ClassNotFoundException {
1313 String rcn = null;
1314 mimeType = (MimeType) is.readObject();
1315
1316 if (mimeType != null) {
1317 humanPresentableName = mimeType
1318 .getParameter("humanPresentableName");
1319 mimeType.removeParameter("humanPresentableName");
1320 rcn = mimeType.getParameter("class");
1321 if (rcn == null) {
1322 throw new IOException(
1323 "no class parameter specified in: " + mimeType);
1324 }
1325 }
1326
1327 try {
1328 representationClass = (Class) is.readObject();
1329 } catch (OptionalDataException ode) {
1330 if (!ode.eof || ode.length != 0) {
1331 throw ode;
1332 }
1333 // Ensure backward compatibility.
1334 // Old versions didn't write the representation class to the stream.
1335 if (rcn != null) {
1336 representationClass = DataFlavor.tryToLoadClass(rcn,
1337 getClass().getClassLoader());
1338 }
1339 }
1340 }
1341
1342 /**
1343 * Returns a clone of this <code>DataFlavor</code>.
1344 * @return a clone of this <code>DataFlavor</code>
1345 */
1346
1347 public Object clone() throws CloneNotSupportedException {
1348 Object newObj = super .clone();
1349 if (mimeType != null) {
1350 ((DataFlavor) newObj).mimeType = (MimeType) mimeType
1351 .clone();
1352 }
1353 return newObj;
1354 } // clone()
1355
1356 /**
1357 * Called on <code>DataFlavor</code> for every MIME Type parameter
1358 * to allow <code>DataFlavor</code> subclasses to handle special
1359 * parameters like the text/plain <code>charset</code>
1360 * parameters, whose values are case insensitive. (MIME type parameter
1361 * values are supposed to be case sensitive.
1362 * <p>
1363 * This method is called for each parameter name/value pair and should
1364 * return the normalized representation of the <code>parameterValue</code>.
1365 *
1366 * This method is never invoked by this implementation from 1.1 onwards.
1367 *
1368 * @deprecated
1369 */
1370 @Deprecated
1371 protected String normalizeMimeTypeParameter(String parameterName,
1372 String parameterValue) {
1373 return parameterValue;
1374 }
1375
1376 /**
1377 * Called for each MIME type string to give <code>DataFlavor</code> subtypes
1378 * the opportunity to change how the normalization of MIME types is
1379 * accomplished. One possible use would be to add default
1380 * parameter/value pairs in cases where none are present in the MIME
1381 * type string passed in.
1382 *
1383 * This method is never invoked by this implementation from 1.1 onwards.
1384 *
1385 * @deprecated
1386 */
1387 @Deprecated
1388 protected String normalizeMimeType(String mimeType) {
1389 return mimeType;
1390 }
1391
1392 /*
1393 * fields
1394 */
1395
1396 /* placeholder for caching any platform-specific data for flavor */
1397
1398 transient int atom;
1399
1400 /* Mime Type of DataFlavor */
1401
1402 MimeType mimeType;
1403
1404 private String humanPresentableName;
1405
1406 /** Java class of objects this DataFlavor represents **/
1407
1408 private Class representationClass;
1409
1410 } // class DataFlavor
|