jdk/src/java.desktop/share/classes/java/awt/datatransfer/DataFlavor.java
changeset 29044 37c6512bd1df
parent 29043 1a9a6f8f71f6
parent 29042 7545059c977e
child 29046 c46ad26fb278
equal deleted inserted replaced
29043:1a9a6f8f71f6 29044:37c6512bd1df
     1 /*
       
     2  * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package java.awt.datatransfer;
       
    27 
       
    28 import sun.datatransfer.DataFlavorUtil;
       
    29 import sun.reflect.misc.ReflectUtil;
       
    30 
       
    31 import java.io.ByteArrayInputStream;
       
    32 import java.io.CharArrayReader;
       
    33 import java.io.Externalizable;
       
    34 import java.io.IOException;
       
    35 import java.io.InputStream;
       
    36 import java.io.InputStreamReader;
       
    37 import java.io.ObjectInput;
       
    38 import java.io.ObjectOutput;
       
    39 import java.io.OptionalDataException;
       
    40 import java.io.Reader;
       
    41 import java.io.StringReader;
       
    42 import java.io.UnsupportedEncodingException;
       
    43 import java.nio.ByteBuffer;
       
    44 import java.nio.CharBuffer;
       
    45 import java.util.Arrays;
       
    46 import java.util.Collections;
       
    47 import java.util.Objects;
       
    48 
       
    49 import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION;
       
    50 
       
    51 /**
       
    52  * A {@code DataFlavor} provides meta information about data. {@code DataFlavor}
       
    53  * is typically used to access data on the clipboard, or during
       
    54  * a drag and drop operation.
       
    55  * <p>
       
    56  * An instance of {@code DataFlavor} encapsulates a content type as
       
    57  * defined in <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
       
    58  * and <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a>.
       
    59  * A content type is typically referred to as a MIME type.
       
    60  * <p>
       
    61  * A content type consists of a media type (referred
       
    62  * to as the primary type), a subtype, and optional parameters. See
       
    63  * <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
       
    64  * for details on the syntax of a MIME type.
       
    65  * <p>
       
    66  * The JRE data transfer implementation interprets the parameter &quot;class&quot;
       
    67  * of a MIME type as <B>a representation class</b>.
       
    68  * The representation class reflects the class of the object being
       
    69  * transferred. In other words, the representation class is the type of
       
    70  * object returned by {@link Transferable#getTransferData}.
       
    71  * For example, the MIME type of {@link #imageFlavor} is
       
    72  * {@code "image/x-java-image;class=java.awt.Image"},
       
    73  * the primary type is {@code image}, the subtype is
       
    74  * {@code x-java-image}, and the representation class is
       
    75  * {@code java.awt.Image}. When {@code getTransferData} is invoked
       
    76  * with a {@code DataFlavor} of {@code imageFlavor}, an instance of
       
    77  * {@code java.awt.Image} is returned.
       
    78  * It's important to note that {@code DataFlavor} does no error checking
       
    79  * against the representation class. It is up to consumers of
       
    80  * {@code DataFlavor}, such as {@code Transferable}, to honor the representation
       
    81  * class.
       
    82  * <br>
       
    83  * Note, if you do not specify a representation class when
       
    84  * creating a {@code DataFlavor}, the default
       
    85  * representation class is used. See appropriate documentation for
       
    86  * {@code DataFlavor}'s constructors.
       
    87  * <p>
       
    88  * Also, {@code DataFlavor} instances with the &quot;text&quot; primary
       
    89  * MIME type may have a &quot;charset&quot; parameter. Refer to
       
    90  * <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a> and
       
    91  * {@link #selectBestTextFlavor} for details on &quot;text&quot; MIME types
       
    92  * and the &quot;charset&quot; parameter.
       
    93  * <p>
       
    94  * Equality of {@code DataFlavors} is determined by the primary type,
       
    95  * subtype, and representation class. Refer to {@link #equals(DataFlavor)} for
       
    96  * details. When determining equality, any optional parameters are ignored.
       
    97  * For example, the following produces two {@code DataFlavors} that
       
    98  * are considered identical:
       
    99  * <pre>
       
   100  *   DataFlavor flavor1 = new DataFlavor(Object.class, &quot;X-test/test; class=&lt;java.lang.Object&gt;; foo=bar&quot;);
       
   101  *   DataFlavor flavor2 = new DataFlavor(Object.class, &quot;X-test/test; class=&lt;java.lang.Object&gt;; x=y&quot;);
       
   102  *   // The following returns true.
       
   103  *   flavor1.equals(flavor2);
       
   104  * </pre>
       
   105  * As mentioned, {@code flavor1} and {@code flavor2} are considered identical.
       
   106  * As such, asking a {@code Transferable} for either {@code DataFlavor} returns
       
   107  * the same results.
       
   108  * <p>
       
   109  * For more information on using data transfer with Swing see
       
   110  * the <a href="http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html">
       
   111  * How to Use Drag and Drop and Data Transfer</a>,
       
   112  * section in <em>Java Tutorial</em>.
       
   113  *
       
   114  * @author      Blake Sullivan
       
   115  * @author      Laurence P. G. Cable
       
   116  * @author      Jeff Dunn
       
   117  */
       
   118 public class DataFlavor implements Externalizable, Cloneable {
       
   119 
       
   120     private static final long serialVersionUID = 8367026044764648243L;
       
   121     private static final Class<InputStream> ioInputStreamClass = InputStream.class;
       
   122 
       
   123     /**
       
   124      * Tries to load a class from: the bootstrap loader, the system loader,
       
   125      * the context loader (if one is present) and finally the loader specified.
       
   126      *
       
   127      * @param className the name of the class to be loaded
       
   128      * @param fallback the fallback loader
       
   129      * @return the class loaded
       
   130      * @exception ClassNotFoundException if class is not found
       
   131      */
       
   132     protected final static Class<?> tryToLoadClass(String className,
       
   133                                                    ClassLoader fallback)
       
   134         throws ClassNotFoundException
       
   135     {
       
   136         ReflectUtil.checkPackageAccess(className);
       
   137         try {
       
   138             SecurityManager sm = System.getSecurityManager();
       
   139             if (sm != null) {
       
   140                 sm.checkPermission(GET_CLASSLOADER_PERMISSION);
       
   141             }
       
   142             ClassLoader loader = ClassLoader.getSystemClassLoader();
       
   143             try {
       
   144                 // bootstrap class loader and system class loader if present
       
   145                 return Class.forName(className, true, loader);
       
   146             }
       
   147             catch (ClassNotFoundException exception) {
       
   148                 // thread context class loader if and only if present
       
   149                 loader = Thread.currentThread().getContextClassLoader();
       
   150                 if (loader != null) {
       
   151                     try {
       
   152                         return Class.forName(className, true, loader);
       
   153                     }
       
   154                     catch (ClassNotFoundException e) {
       
   155                         // fallback to user's class loader
       
   156                     }
       
   157                 }
       
   158             }
       
   159         } catch (SecurityException exception) {
       
   160             // ignore secured class loaders
       
   161         }
       
   162         return Class.forName(className, true, fallback);
       
   163     }
       
   164 
       
   165     /*
       
   166      * private initializer
       
   167      */
       
   168     static private DataFlavor createConstant(Class<?> rc, String prn) {
       
   169         try {
       
   170             return new DataFlavor(rc, prn);
       
   171         } catch (Exception e) {
       
   172             return null;
       
   173         }
       
   174     }
       
   175 
       
   176     /*
       
   177      * private initializer
       
   178      */
       
   179     static private DataFlavor createConstant(String mt, String prn) {
       
   180         try {
       
   181             return new DataFlavor(mt, prn);
       
   182         } catch (Exception e) {
       
   183             return null;
       
   184         }
       
   185     }
       
   186 
       
   187     /*
       
   188      * private initializer
       
   189      */
       
   190     static private DataFlavor initHtmlDataFlavor(String htmlFlavorType) {
       
   191         try {
       
   192             return new DataFlavor ("text/html; class=java.lang.String;document=" +
       
   193                                        htmlFlavorType + ";charset=Unicode");
       
   194         } catch (Exception e) {
       
   195             return null;
       
   196         }
       
   197     }
       
   198 
       
   199     /**
       
   200      * The <code>DataFlavor</code> representing a Java Unicode String class,
       
   201      * where:
       
   202      * <pre>
       
   203      *     representationClass = java.lang.String
       
   204      *     mimeType           = "application/x-java-serialized-object"
       
   205      * </pre>
       
   206      */
       
   207     public static final DataFlavor stringFlavor = createConstant(java.lang.String.class, "Unicode String");
       
   208 
       
   209     /**
       
   210      * The <code>DataFlavor</code> representing a Java Image class,
       
   211      * where:
       
   212      * <pre>
       
   213      *     representationClass = java.awt.Image
       
   214      *     mimeType            = "image/x-java-image"
       
   215      * </pre>
       
   216      */
       
   217     public static final DataFlavor imageFlavor = createConstant("image/x-java-image; class=java.awt.Image", "Image");
       
   218 
       
   219     /**
       
   220      * The <code>DataFlavor</code> representing plain text with Unicode
       
   221      * encoding, where:
       
   222      * <pre>
       
   223      *     representationClass = InputStream
       
   224      *     mimeType            = "text/plain; charset=unicode"
       
   225      * </pre>
       
   226      * This <code>DataFlavor</code> has been <b>deprecated</b> because
       
   227      * (1) Its representation is an InputStream, an 8-bit based representation,
       
   228      * while Unicode is a 16-bit character set; and (2) The charset "unicode"
       
   229      * is not well-defined. "unicode" implies a particular platform's
       
   230      * implementation of Unicode, not a cross-platform implementation.
       
   231      *
       
   232      * @deprecated as of 1.3. Use <code>DataFlavor.getReaderForText(Transferable)</code>
       
   233      *             instead of <code>Transferable.getTransferData(DataFlavor.plainTextFlavor)</code>.
       
   234      */
       
   235     @Deprecated
       
   236     public static final DataFlavor plainTextFlavor = createConstant("text/plain; charset=unicode; class=java.io.InputStream", "Plain Text");
       
   237 
       
   238     /**
       
   239      * A MIME Content-Type of application/x-java-serialized-object represents
       
   240      * a graph of Java object(s) that have been made persistent.
       
   241      *
       
   242      * The representation class associated with this <code>DataFlavor</code>
       
   243      * identifies the Java type of an object returned as a reference
       
   244      * from an invocation <code>java.awt.datatransfer.getTransferData</code>.
       
   245      */
       
   246     public static final String javaSerializedObjectMimeType = "application/x-java-serialized-object";
       
   247 
       
   248     /**
       
   249      * To transfer a list of files to/from Java (and the underlying
       
   250      * platform) a <code>DataFlavor</code> of this type/subtype and
       
   251      * representation class of <code>java.util.List</code> is used.
       
   252      * Each element of the list is required/guaranteed to be of type
       
   253      * <code>java.io.File</code>.
       
   254      */
       
   255     public static final DataFlavor javaFileListFlavor = createConstant("application/x-java-file-list;class=java.util.List", null);
       
   256 
       
   257     /**
       
   258      * To transfer a reference to an arbitrary Java object reference that
       
   259      * has no associated MIME Content-type, across a <code>Transferable</code>
       
   260      * interface WITHIN THE SAME JVM, a <code>DataFlavor</code>
       
   261      * with this type/subtype is used, with a <code>representationClass</code>
       
   262      * equal to the type of the class/interface being passed across the
       
   263      * <code>Transferable</code>.
       
   264      * <p>
       
   265      * The object reference returned from
       
   266      * <code>Transferable.getTransferData</code> for a <code>DataFlavor</code>
       
   267      * with this MIME Content-Type is required to be
       
   268      * an instance of the representation Class of the <code>DataFlavor</code>.
       
   269      */
       
   270     public static final String javaJVMLocalObjectMimeType = "application/x-java-jvm-local-objectref";
       
   271 
       
   272     /**
       
   273      * In order to pass a live link to a Remote object via a Drag and Drop
       
   274      * <code>ACTION_LINK</code> operation a Mime Content Type of
       
   275      * application/x-java-remote-object should be used,
       
   276      * where the representation class of the <code>DataFlavor</code>
       
   277      * represents the type of the <code>Remote</code> interface to be
       
   278      * transferred.
       
   279      */
       
   280     public static final String javaRemoteObjectMimeType = "application/x-java-remote-object";
       
   281 
       
   282     /**
       
   283      * Represents a piece of an HTML markup. The markup consists of the part
       
   284      * selected on the source side. Therefore some tags in the markup may be
       
   285      * unpaired. If the flavor is used to represent the data in
       
   286      * a {@link Transferable} instance, no additional changes will be made.
       
   287      * This DataFlavor instance represents the same HTML markup as DataFlavor
       
   288      * instances which content MIME type does not contain document parameter
       
   289      * and representation class is the String class.
       
   290      * <pre>
       
   291      *     representationClass = String
       
   292      *     mimeType           = "text/html"
       
   293      * </pre>
       
   294      */
       
   295     public static DataFlavor selectionHtmlFlavor = initHtmlDataFlavor("selection");
       
   296 
       
   297     /**
       
   298      * Represents a piece of an HTML markup. If possible, the markup received
       
   299      * from a native system is supplemented with pair tags to be
       
   300      * a well-formed HTML markup. If the flavor is used to represent the data in
       
   301      * a {@link Transferable} instance, no additional changes will be made.
       
   302      * <pre>
       
   303      *     representationClass = String
       
   304      *     mimeType           = "text/html"
       
   305      * </pre>
       
   306      */
       
   307     public static DataFlavor fragmentHtmlFlavor = initHtmlDataFlavor("fragment");
       
   308 
       
   309     /**
       
   310      * Represents a piece of an HTML markup. If possible, the markup
       
   311      * received from a native system is supplemented with additional
       
   312      * tags to make up a well-formed HTML document. If the flavor is used to
       
   313      * represent the data in a {@link Transferable} instance,
       
   314      * no additional changes will be made.
       
   315      * <pre>
       
   316      *     representationClass = String
       
   317      *     mimeType           = "text/html"
       
   318      * </pre>
       
   319      */
       
   320     public static  DataFlavor allHtmlFlavor = initHtmlDataFlavor("all");
       
   321 
       
   322     /**
       
   323      * Constructs a new <code>DataFlavor</code>.  This constructor is
       
   324      * provided only for the purpose of supporting the
       
   325      * <code>Externalizable</code> interface.  It is not
       
   326      * intended for public (client) use.
       
   327      *
       
   328      * @since 1.2
       
   329      */
       
   330     public DataFlavor() {
       
   331         super();
       
   332     }
       
   333 
       
   334     /**
       
   335      * Constructs a fully specified <code>DataFlavor</code>.
       
   336      *
       
   337      * @exception NullPointerException if either <code>primaryType</code>,
       
   338      *            <code>subType</code> or <code>representationClass</code> is null
       
   339      */
       
   340     private DataFlavor(String primaryType, String subType, MimeTypeParameterList params, Class<?> representationClass, String humanPresentableName) {
       
   341         super();
       
   342         if (primaryType == null) {
       
   343             throw new NullPointerException("primaryType");
       
   344         }
       
   345         if (subType == null) {
       
   346             throw new NullPointerException("subType");
       
   347         }
       
   348         if (representationClass == null) {
       
   349             throw new NullPointerException("representationClass");
       
   350         }
       
   351 
       
   352         if (params == null) params = new MimeTypeParameterList();
       
   353 
       
   354         params.set("class", representationClass.getName());
       
   355 
       
   356         if (humanPresentableName == null) {
       
   357             humanPresentableName = params.get("humanPresentableName");
       
   358 
       
   359             if (humanPresentableName == null)
       
   360                 humanPresentableName = primaryType + "/" + subType;
       
   361         }
       
   362 
       
   363         try {
       
   364             mimeType = new MimeType(primaryType, subType, params);
       
   365         } catch (MimeTypeParseException mtpe) {
       
   366             throw new IllegalArgumentException("MimeType Parse Exception: " + mtpe.getMessage());
       
   367         }
       
   368 
       
   369         this.representationClass  = representationClass;
       
   370         this.humanPresentableName = humanPresentableName;
       
   371 
       
   372         mimeType.removeParameter("humanPresentableName");
       
   373     }
       
   374 
       
   375     /**
       
   376      * Constructs a <code>DataFlavor</code> that represents a Java class.
       
   377      * <p>
       
   378      * The returned <code>DataFlavor</code> will have the following
       
   379      * characteristics:
       
   380      * <pre>
       
   381      *    representationClass = representationClass
       
   382      *    mimeType            = application/x-java-serialized-object
       
   383      * </pre>
       
   384      * @param representationClass the class used to transfer data in this flavor
       
   385      * @param humanPresentableName the human-readable string used to identify
       
   386      *                 this flavor; if this parameter is <code>null</code>
       
   387      *                 then the value of the MIME Content Type is used
       
   388      * @exception NullPointerException if <code>representationClass</code> is null
       
   389      */
       
   390     public DataFlavor(Class<?> representationClass, String humanPresentableName) {
       
   391         this("application", "x-java-serialized-object", null, representationClass, humanPresentableName);
       
   392         if (representationClass == null) {
       
   393             throw new NullPointerException("representationClass");
       
   394         }
       
   395     }
       
   396 
       
   397     /**
       
   398      * Constructs a <code>DataFlavor</code> that represents a
       
   399      * <code>MimeType</code>.
       
   400      * <p>
       
   401      * The returned <code>DataFlavor</code> will have the following
       
   402      * characteristics:
       
   403      * <p>
       
   404      * If the <code>mimeType</code> is
       
   405      * "application/x-java-serialized-object; class=&lt;representation class&gt;",
       
   406      * the result is the same as calling
       
   407      * <code>new DataFlavor(Class.forName(&lt;representation class&gt;)</code>.
       
   408      * <p>
       
   409      * Otherwise:
       
   410      * <pre>
       
   411      *     representationClass = InputStream
       
   412      *     mimeType            = mimeType
       
   413      * </pre>
       
   414      * @param mimeType the string used to identify the MIME type for this flavor;
       
   415      *                 if the <code>mimeType</code> does not specify a
       
   416      *                 "class=" parameter, or if the class is not successfully
       
   417      *                 loaded, then an <code>IllegalArgumentException</code>
       
   418      *                 is thrown
       
   419      * @param humanPresentableName the human-readable string used to identify
       
   420      *                 this flavor; if this parameter is <code>null</code>
       
   421      *                 then the value of the MIME Content Type is used
       
   422      * @exception IllegalArgumentException if <code>mimeType</code> is
       
   423      *                 invalid or if the class is not successfully loaded
       
   424      * @exception NullPointerException if <code>mimeType</code> is null
       
   425      */
       
   426     public DataFlavor(String mimeType, String humanPresentableName) {
       
   427         super();
       
   428         if (mimeType == null) {
       
   429             throw new NullPointerException("mimeType");
       
   430         }
       
   431         try {
       
   432             initialize(mimeType, humanPresentableName, this.getClass().getClassLoader());
       
   433         } catch (MimeTypeParseException mtpe) {
       
   434             throw new IllegalArgumentException("failed to parse:" + mimeType);
       
   435         } catch (ClassNotFoundException cnfe) {
       
   436             throw new IllegalArgumentException("can't find specified class: " + cnfe.getMessage());
       
   437         }
       
   438     }
       
   439 
       
   440     /**
       
   441      * Constructs a <code>DataFlavor</code> that represents a
       
   442      * <code>MimeType</code>.
       
   443      * <p>
       
   444      * The returned <code>DataFlavor</code> will have the following
       
   445      * characteristics:
       
   446      * <p>
       
   447      * If the mimeType is
       
   448      * "application/x-java-serialized-object; class=&lt;representation class&gt;",
       
   449      * the result is the same as calling
       
   450      * <code>new DataFlavor(Class.forName(&lt;representation class&gt;)</code>.
       
   451      * <p>
       
   452      * Otherwise:
       
   453      * <pre>
       
   454      *     representationClass = InputStream
       
   455      *     mimeType            = mimeType
       
   456      * </pre>
       
   457      * @param mimeType the string used to identify the MIME type for this flavor
       
   458      * @param humanPresentableName the human-readable string used to
       
   459      *          identify this flavor
       
   460      * @param classLoader the class loader to use
       
   461      * @exception ClassNotFoundException if the class is not loaded
       
   462      * @exception IllegalArgumentException if <code>mimeType</code> is
       
   463      *                 invalid
       
   464      * @exception NullPointerException if <code>mimeType</code> is null
       
   465      */
       
   466     public DataFlavor(String mimeType, String humanPresentableName, ClassLoader classLoader) throws ClassNotFoundException {
       
   467         super();
       
   468         if (mimeType == null) {
       
   469             throw new NullPointerException("mimeType");
       
   470         }
       
   471         try {
       
   472             initialize(mimeType, humanPresentableName, classLoader);
       
   473         } catch (MimeTypeParseException mtpe) {
       
   474             throw new IllegalArgumentException("failed to parse:" + mimeType);
       
   475         }
       
   476     }
       
   477 
       
   478     /**
       
   479      * Constructs a <code>DataFlavor</code> from a <code>mimeType</code> string.
       
   480      * The string can specify a "class=&lt;fully specified Java class name&gt;"
       
   481      * parameter to create a <code>DataFlavor</code> with the desired
       
   482      * representation class. If the string does not contain "class=" parameter,
       
   483      * <code>java.io.InputStream</code> is used as default.
       
   484      *
       
   485      * @param mimeType the string used to identify the MIME type for this flavor;
       
   486      *                 if the class specified by "class=" parameter is not
       
   487      *                 successfully loaded, then an
       
   488      *                 <code>ClassNotFoundException</code> is thrown
       
   489      * @exception ClassNotFoundException if the class is not loaded
       
   490      * @exception IllegalArgumentException if <code>mimeType</code> is
       
   491      *                 invalid
       
   492      * @exception NullPointerException if <code>mimeType</code> is null
       
   493      */
       
   494     public DataFlavor(String mimeType) throws ClassNotFoundException {
       
   495         super();
       
   496         if (mimeType == null) {
       
   497             throw new NullPointerException("mimeType");
       
   498         }
       
   499         try {
       
   500             initialize(mimeType, null, this.getClass().getClassLoader());
       
   501         } catch (MimeTypeParseException mtpe) {
       
   502             throw new IllegalArgumentException("failed to parse:" + mimeType);
       
   503         }
       
   504     }
       
   505 
       
   506    /**
       
   507     * Common initialization code called from various constructors.
       
   508     *
       
   509     * @param mimeType the MIME Content Type (must have a class= param)
       
   510     * @param humanPresentableName the human Presentable Name or
       
   511     *                 <code>null</code>
       
   512     * @param classLoader the fallback class loader to resolve against
       
   513     *
       
   514     * @throws MimeTypeParseException
       
   515     * @throws ClassNotFoundException
       
   516     * @throws  NullPointerException if <code>mimeType</code> is null
       
   517     *
       
   518     * @see #tryToLoadClass
       
   519     */
       
   520     private void initialize(String mimeType, String humanPresentableName, ClassLoader classLoader) throws MimeTypeParseException, ClassNotFoundException {
       
   521         if (mimeType == null) {
       
   522             throw new NullPointerException("mimeType");
       
   523         }
       
   524 
       
   525         this.mimeType = new MimeType(mimeType); // throws
       
   526 
       
   527         String rcn = getParameter("class");
       
   528 
       
   529         if (rcn == null) {
       
   530             if ("application/x-java-serialized-object".equals(this.mimeType.getBaseType()))
       
   531 
       
   532                 throw new IllegalArgumentException("no representation class specified for:" + mimeType);
       
   533             else
       
   534                 representationClass = java.io.InputStream.class; // default
       
   535         } else { // got a class name
       
   536             representationClass = DataFlavor.tryToLoadClass(rcn, classLoader);
       
   537         }
       
   538 
       
   539         this.mimeType.setParameter("class", representationClass.getName());
       
   540 
       
   541         if (humanPresentableName == null) {
       
   542             humanPresentableName = this.mimeType.getParameter("humanPresentableName");
       
   543             if (humanPresentableName == null)
       
   544                 humanPresentableName = this.mimeType.getPrimaryType() + "/" + this.mimeType.getSubType();
       
   545         }
       
   546 
       
   547         this.humanPresentableName = humanPresentableName; // set it.
       
   548 
       
   549         this.mimeType.removeParameter("humanPresentableName"); // just in case
       
   550     }
       
   551 
       
   552     /**
       
   553      * String representation of this <code>DataFlavor</code> and its
       
   554      * parameters. The resulting <code>String</code> contains the name of
       
   555      * the <code>DataFlavor</code> class, this flavor's MIME type, and its
       
   556      * representation class. If this flavor has a primary MIME type of "text",
       
   557      * supports the charset parameter, and has an encoded representation, the
       
   558      * flavor's charset is also included. See <code>selectBestTextFlavor</code>
       
   559      * for a list of text flavors which support the charset parameter.
       
   560      *
       
   561      * @return  string representation of this <code>DataFlavor</code>
       
   562      * @see #selectBestTextFlavor
       
   563      */
       
   564     public String toString() {
       
   565         String string = getClass().getName();
       
   566         string += "["+paramString()+"]";
       
   567         return string;
       
   568     }
       
   569 
       
   570     private String paramString() {
       
   571         String params = "";
       
   572         params += "mimetype=";
       
   573         if (mimeType == null) {
       
   574             params += "null";
       
   575         } else {
       
   576             params += mimeType.getBaseType();
       
   577         }
       
   578         params += ";representationclass=";
       
   579         if (representationClass == null) {
       
   580            params += "null";
       
   581         } else {
       
   582            params += representationClass.getName();
       
   583         }
       
   584         if (DataFlavorUtil.isFlavorCharsetTextType(this) &&
       
   585             (isRepresentationClassInputStream() ||
       
   586              isRepresentationClassByteBuffer() ||
       
   587              byte[].class.equals(representationClass)))
       
   588         {
       
   589             params += ";charset=" + DataFlavorUtil.getTextCharset(this);
       
   590         }
       
   591         return params;
       
   592     }
       
   593 
       
   594     /**
       
   595      * Returns a <code>DataFlavor</code> representing plain text with Unicode
       
   596      * encoding, where:
       
   597      * <pre>
       
   598      *     representationClass = java.io.InputStream
       
   599      *     mimeType            = "text/plain;
       
   600      *                            charset=&lt;platform default Unicode encoding&gt;"
       
   601      * </pre>
       
   602      * Sun's implementation for Microsoft Windows uses the encoding <code>utf-16le</code>.
       
   603      * Sun's implementation for Solaris and Linux uses the encoding
       
   604      * <code>iso-10646-ucs-2</code>.
       
   605      *
       
   606      * @return a <code>DataFlavor</code> representing plain text
       
   607      *    with Unicode encoding
       
   608      * @since 1.3
       
   609      */
       
   610     public static final DataFlavor getTextPlainUnicodeFlavor() {
       
   611         return new DataFlavor(
       
   612             "text/plain;charset=" + DataFlavorUtil.getDesktopService().getDefaultUnicodeEncoding()
       
   613             +";class=java.io.InputStream", "Plain Text");
       
   614     }
       
   615 
       
   616     /**
       
   617      * Selects the best text <code>DataFlavor</code> from an array of <code>
       
   618      * DataFlavor</code>s. Only <code>DataFlavor.stringFlavor</code>, and
       
   619      * equivalent flavors, and flavors that have a primary MIME type of "text",
       
   620      * are considered for selection.
       
   621      * <p>
       
   622      * Flavors are first sorted by their MIME types in the following order:
       
   623      * <ul>
       
   624      * <li>"text/sgml"
       
   625      * <li>"text/xml"
       
   626      * <li>"text/html"
       
   627      * <li>"text/rtf"
       
   628      * <li>"text/enriched"
       
   629      * <li>"text/richtext"
       
   630      * <li>"text/uri-list"
       
   631      * <li>"text/tab-separated-values"
       
   632      * <li>"text/t140"
       
   633      * <li>"text/rfc822-headers"
       
   634      * <li>"text/parityfec"
       
   635      * <li>"text/directory"
       
   636      * <li>"text/css"
       
   637      * <li>"text/calendar"
       
   638      * <li>"application/x-java-serialized-object"
       
   639      * <li>"text/plain"
       
   640      * <li>"text/&lt;other&gt;"
       
   641      * </ul>
       
   642      * <p>For example, "text/sgml" will be selected over
       
   643      * "text/html", and <code>DataFlavor.stringFlavor</code> will be chosen
       
   644      * over <code>DataFlavor.plainTextFlavor</code>.
       
   645      * <p>
       
   646      * If two or more flavors share the best MIME type in the array, then that
       
   647      * MIME type will be checked to see if it supports the charset parameter.
       
   648      * <p>
       
   649      * The following MIME types support, or are treated as though they support,
       
   650      * the charset parameter:
       
   651      * <ul>
       
   652      * <li>"text/sgml"
       
   653      * <li>"text/xml"
       
   654      * <li>"text/html"
       
   655      * <li>"text/enriched"
       
   656      * <li>"text/richtext"
       
   657      * <li>"text/uri-list"
       
   658      * <li>"text/directory"
       
   659      * <li>"text/css"
       
   660      * <li>"text/calendar"
       
   661      * <li>"application/x-java-serialized-object"
       
   662      * <li>"text/plain"
       
   663      * </ul>
       
   664      * The following MIME types do not support, or are treated as though they
       
   665      * do not support, the charset parameter:
       
   666      * <ul>
       
   667      * <li>"text/rtf"
       
   668      * <li>"text/tab-separated-values"
       
   669      * <li>"text/t140"
       
   670      * <li>"text/rfc822-headers"
       
   671      * <li>"text/parityfec"
       
   672      * </ul>
       
   673      * For "text/&lt;other&gt;" MIME types, the first time the JRE needs to
       
   674      * determine whether the MIME type supports the charset parameter, it will
       
   675      * check whether the parameter is explicitly listed in an arbitrarily
       
   676      * chosen <code>DataFlavor</code> which uses that MIME type. If so, the JRE
       
   677      * will assume from that point on that the MIME type supports the charset
       
   678      * parameter and will not check again. If the parameter is not explicitly
       
   679      * listed, the JRE will assume from that point on that the MIME type does
       
   680      * not support the charset parameter and will not check again. Because
       
   681      * this check is performed on an arbitrarily chosen
       
   682      * <code>DataFlavor</code>, developers must ensure that all
       
   683      * <code>DataFlavor</code>s with a "text/&lt;other&gt;" MIME type specify
       
   684      * the charset parameter if it is supported by that MIME type. Developers
       
   685      * should never rely on the JRE to substitute the platform's default
       
   686      * charset for a "text/&lt;other&gt;" DataFlavor. Failure to adhere to this
       
   687      * restriction will lead to undefined behavior.
       
   688      * <p>
       
   689      * If the best MIME type in the array does not support the charset
       
   690      * parameter, the flavors which share that MIME type will then be sorted by
       
   691      * their representation classes in the following order:
       
   692      * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
       
   693      * <code>[B</code>, &lt;all others&gt;.
       
   694      * <p>
       
   695      * If two or more flavors share the best representation class, or if no
       
   696      * flavor has one of the three specified representations, then one of those
       
   697      * flavors will be chosen non-deterministically.
       
   698      * <p>
       
   699      * If the best MIME type in the array does support the charset parameter,
       
   700      * the flavors which share that MIME type will then be sorted by their
       
   701      * representation classes in the following order:
       
   702      * <code>java.io.Reader</code>, <code>java.lang.String</code>,
       
   703      * <code>java.nio.CharBuffer</code>, <code>[C</code>, &lt;all others&gt;.
       
   704      * <p>
       
   705      * If two or more flavors share the best representation class, and that
       
   706      * representation is one of the four explicitly listed, then one of those
       
   707      * flavors will be chosen non-deterministically. If, however, no flavor has
       
   708      * one of the four specified representations, the flavors will then be
       
   709      * sorted by their charsets. Unicode charsets, such as "UTF-16", "UTF-8",
       
   710      * "UTF-16BE", "UTF-16LE", and their aliases, are considered best. After
       
   711      * them, the platform default charset and its aliases are selected.
       
   712      * "US-ASCII" and its aliases are worst. All other charsets are chosen in
       
   713      * alphabetical order, but only charsets supported by this implementation
       
   714      * of the Java platform will be considered.
       
   715      * <p>
       
   716      * If two or more flavors share the best charset, the flavors will then
       
   717      * again be sorted by their representation classes in the following order:
       
   718      * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
       
   719      * <code>[B</code>, &lt;all others&gt;.
       
   720      * <p>
       
   721      * If two or more flavors share the best representation class, or if no
       
   722      * flavor has one of the three specified representations, then one of those
       
   723      * flavors will be chosen non-deterministically.
       
   724      *
       
   725      * @param availableFlavors an array of available <code>DataFlavor</code>s
       
   726      * @return the best (highest fidelity) flavor according to the rules
       
   727      *         specified above, or <code>null</code>,
       
   728      *         if <code>availableFlavors</code> is <code>null</code>,
       
   729      *         has zero length, or contains no text flavors
       
   730      * @since 1.3
       
   731      */
       
   732     public static final DataFlavor selectBestTextFlavor(
       
   733                                        DataFlavor[] availableFlavors) {
       
   734         if (availableFlavors == null || availableFlavors.length == 0) {
       
   735             return null;
       
   736         }
       
   737 
       
   738         DataFlavor bestFlavor = Collections.max(Arrays.asList(availableFlavors),
       
   739                                                 DataFlavorUtil.getTextFlavorComparator());
       
   740 
       
   741         if (!bestFlavor.isFlavorTextType()) {
       
   742             return null;
       
   743         }
       
   744 
       
   745         return bestFlavor;
       
   746     }
       
   747 
       
   748     /**
       
   749      * Gets a Reader for a text flavor, decoded, if necessary, for the expected
       
   750      * charset (encoding). The supported representation classes are
       
   751      * <code>java.io.Reader</code>, <code>java.lang.String</code>,
       
   752      * <code>java.nio.CharBuffer</code>, <code>[C</code>,
       
   753      * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
       
   754      * and <code>[B</code>.
       
   755      * <p>
       
   756      * Because text flavors which do not support the charset parameter are
       
   757      * encoded in a non-standard format, this method should not be called for
       
   758      * such flavors. However, in order to maintain backward-compatibility,
       
   759      * if this method is called for such a flavor, this method will treat the
       
   760      * flavor as though it supports the charset parameter and attempt to
       
   761      * decode it accordingly. See <code>selectBestTextFlavor</code> for a list
       
   762      * of text flavors which do not support the charset parameter.
       
   763      *
       
   764      * @param transferable the <code>Transferable</code> whose data will be
       
   765      *        requested in this flavor
       
   766      *
       
   767      * @return a <code>Reader</code> to read the <code>Transferable</code>'s
       
   768      *         data
       
   769      *
       
   770      * @exception IllegalArgumentException if the representation class
       
   771      *            is not one of the seven listed above
       
   772      * @exception IllegalArgumentException if the <code>Transferable</code>
       
   773      *            has <code>null</code> data
       
   774      * @exception NullPointerException if the <code>Transferable</code> is
       
   775      *            <code>null</code>
       
   776      * @exception UnsupportedEncodingException if this flavor's representation
       
   777      *            is <code>java.io.InputStream</code>,
       
   778      *            <code>java.nio.ByteBuffer</code>, or <code>[B</code> and
       
   779      *            this flavor's encoding is not supported by this
       
   780      *            implementation of the Java platform
       
   781      * @exception UnsupportedFlavorException if the <code>Transferable</code>
       
   782      *            does not support this flavor
       
   783      * @exception IOException if the data cannot be read because of an
       
   784      *            I/O error
       
   785      * @see #selectBestTextFlavor
       
   786      * @since 1.3
       
   787      */
       
   788     public Reader getReaderForText(Transferable transferable)
       
   789         throws UnsupportedFlavorException, IOException
       
   790     {
       
   791         Object transferObject = transferable.getTransferData(this);
       
   792         if (transferObject == null) {
       
   793             throw new IllegalArgumentException
       
   794                 ("getTransferData() returned null");
       
   795         }
       
   796 
       
   797         if (transferObject instanceof Reader) {
       
   798             return (Reader)transferObject;
       
   799         } else if (transferObject instanceof String) {
       
   800             return new StringReader((String)transferObject);
       
   801         } else if (transferObject instanceof CharBuffer) {
       
   802             CharBuffer buffer = (CharBuffer)transferObject;
       
   803             int size = buffer.remaining();
       
   804             char[] chars = new char[size];
       
   805             buffer.get(chars, 0, size);
       
   806             return new CharArrayReader(chars);
       
   807         } else if (transferObject instanceof char[]) {
       
   808             return new CharArrayReader((char[])transferObject);
       
   809         }
       
   810 
       
   811         InputStream stream = null;
       
   812 
       
   813         if (transferObject instanceof InputStream) {
       
   814             stream = (InputStream)transferObject;
       
   815         } else if (transferObject instanceof ByteBuffer) {
       
   816             ByteBuffer buffer = (ByteBuffer)transferObject;
       
   817             int size = buffer.remaining();
       
   818             byte[] bytes = new byte[size];
       
   819             buffer.get(bytes, 0, size);
       
   820             stream = new ByteArrayInputStream(bytes);
       
   821         } else if (transferObject instanceof byte[]) {
       
   822             stream = new ByteArrayInputStream((byte[])transferObject);
       
   823         }
       
   824 
       
   825         if (stream == null) {
       
   826             throw new IllegalArgumentException("transfer data is not Reader, String, CharBuffer, char array, InputStream, ByteBuffer, or byte array");
       
   827         }
       
   828 
       
   829         String encoding = getParameter("charset");
       
   830         return (encoding == null)
       
   831             ? new InputStreamReader(stream)
       
   832             : new InputStreamReader(stream, encoding);
       
   833     }
       
   834 
       
   835     /**
       
   836      * Returns the MIME type string for this <code>DataFlavor</code>.
       
   837      * @return the MIME type string for this flavor
       
   838      */
       
   839     public String getMimeType() {
       
   840         return (mimeType != null) ? mimeType.toString() : null;
       
   841     }
       
   842 
       
   843     /**
       
   844      * Returns the <code>Class</code> which objects supporting this
       
   845      * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
       
   846      * is requested.
       
   847      * @return the <code>Class</code> which objects supporting this
       
   848      * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
       
   849      * is requested
       
   850      */
       
   851     public Class<?> getRepresentationClass() {
       
   852         return representationClass;
       
   853     }
       
   854 
       
   855     /**
       
   856      * Returns the human presentable name for the data format that this
       
   857      * <code>DataFlavor</code> represents.  This name would be localized
       
   858      * for different countries.
       
   859      * @return the human presentable name for the data format that this
       
   860      *    <code>DataFlavor</code> represents
       
   861      */
       
   862     public String getHumanPresentableName() {
       
   863         return humanPresentableName;
       
   864     }
       
   865 
       
   866     /**
       
   867      * Returns the primary MIME type for this <code>DataFlavor</code>.
       
   868      * @return the primary MIME type of this <code>DataFlavor</code>
       
   869      */
       
   870     public String getPrimaryType() {
       
   871         return (mimeType != null) ? mimeType.getPrimaryType() : null;
       
   872     }
       
   873 
       
   874     /**
       
   875      * Returns the sub MIME type of this <code>DataFlavor</code>.
       
   876      * @return the Sub MIME type of this <code>DataFlavor</code>
       
   877      */
       
   878     public String getSubType() {
       
   879         return (mimeType != null) ? mimeType.getSubType() : null;
       
   880     }
       
   881 
       
   882     /**
       
   883      * Returns the human presentable name for this <code>DataFlavor</code>
       
   884      * if <code>paramName</code> equals "humanPresentableName".  Otherwise
       
   885      * returns the MIME type value associated with <code>paramName</code>.
       
   886      *
       
   887      * @param paramName the parameter name requested
       
   888      * @return the value of the name parameter, or <code>null</code>
       
   889      *  if there is no associated value
       
   890      */
       
   891     public String getParameter(String paramName) {
       
   892         if (paramName.equals("humanPresentableName")) {
       
   893             return humanPresentableName;
       
   894         } else {
       
   895             return (mimeType != null)
       
   896                 ? mimeType.getParameter(paramName) : null;
       
   897         }
       
   898     }
       
   899 
       
   900     /**
       
   901      * Sets the human presentable name for the data format that this
       
   902      * <code>DataFlavor</code> represents. This name would be localized
       
   903      * for different countries.
       
   904      * @param humanPresentableName the new human presentable name
       
   905      */
       
   906     public void setHumanPresentableName(String humanPresentableName) {
       
   907         this.humanPresentableName = humanPresentableName;
       
   908     }
       
   909 
       
   910     /**
       
   911      * {@inheritDoc}
       
   912      * <p>
       
   913      * The equals comparison for the {@code DataFlavor} class is implemented
       
   914      * as follows: Two <code>DataFlavor</code>s are considered equal if and
       
   915      * only if their MIME primary type and subtype and representation class are
       
   916      * equal. Additionally, if the primary type is "text", the subtype denotes
       
   917      * a text flavor which supports the charset parameter, and the
       
   918      * representation class is not <code>java.io.Reader</code>,
       
   919      * <code>java.lang.String</code>, <code>java.nio.CharBuffer</code>, or
       
   920      * <code>[C</code>, the <code>charset</code> parameter must also be equal.
       
   921      * If a charset is not explicitly specified for one or both
       
   922      * <code>DataFlavor</code>s, the platform default encoding is assumed. See
       
   923      * <code>selectBestTextFlavor</code> for a list of text flavors which
       
   924      * support the charset parameter.
       
   925      *
       
   926      * @param o the <code>Object</code> to compare with <code>this</code>
       
   927      * @return <code>true</code> if <code>that</code> is equivalent to this
       
   928      *         <code>DataFlavor</code>; <code>false</code> otherwise
       
   929      * @see #selectBestTextFlavor
       
   930      */
       
   931     public boolean equals(Object o) {
       
   932         return ((o instanceof DataFlavor) && equals((DataFlavor)o));
       
   933     }
       
   934 
       
   935     /**
       
   936      * This method has the same behavior as {@link #equals(Object)}.
       
   937      * The only difference being that it takes a {@code DataFlavor} instance
       
   938      * as a parameter.
       
   939      *
       
   940      * @param that the <code>DataFlavor</code> to compare with
       
   941      *        <code>this</code>
       
   942      * @return <code>true</code> if <code>that</code> is equivalent to this
       
   943      *         <code>DataFlavor</code>; <code>false</code> otherwise
       
   944      * @see #selectBestTextFlavor
       
   945      */
       
   946     public boolean equals(DataFlavor that) {
       
   947         if (that == null) {
       
   948             return false;
       
   949         }
       
   950         if (this == that) {
       
   951             return true;
       
   952         }
       
   953 
       
   954         if (!Objects.equals(this.getRepresentationClass(), that.getRepresentationClass())) {
       
   955             return false;
       
   956         }
       
   957 
       
   958         if (mimeType == null) {
       
   959             if (that.mimeType != null) {
       
   960                 return false;
       
   961             }
       
   962         } else {
       
   963             if (!mimeType.match(that.mimeType)) {
       
   964                 return false;
       
   965             }
       
   966 
       
   967             if ("text".equals(getPrimaryType())) {
       
   968                 if (DataFlavorUtil.doesSubtypeSupportCharset(this)
       
   969                         && representationClass != null
       
   970                         && !isStandardTextRepresentationClass()) {
       
   971                     String thisCharset =
       
   972                             DataFlavorUtil.canonicalName(this.getParameter("charset"));
       
   973                     String thatCharset =
       
   974                             DataFlavorUtil.canonicalName(that.getParameter("charset"));
       
   975                     if (!Objects.equals(thisCharset, thatCharset)) {
       
   976                         return false;
       
   977                     }
       
   978                 }
       
   979 
       
   980                 if ("html".equals(getSubType())) {
       
   981                     String thisDocument = this.getParameter("document");
       
   982                     String thatDocument = that.getParameter("document");
       
   983                     if (!Objects.equals(thisDocument, thatDocument)) {
       
   984                         return false;
       
   985                     }
       
   986                 }
       
   987             }
       
   988         }
       
   989 
       
   990         return true;
       
   991     }
       
   992 
       
   993     /**
       
   994      * Compares only the <code>mimeType</code> against the passed in
       
   995      * <code>String</code> and <code>representationClass</code> is
       
   996      * not considered in the comparison.
       
   997      *
       
   998      * If <code>representationClass</code> needs to be compared, then
       
   999      * <code>equals(new DataFlavor(s))</code> may be used.
       
  1000      * @deprecated As inconsistent with <code>hashCode()</code> contract,
       
  1001      *             use <code>isMimeTypeEqual(String)</code> instead.
       
  1002      * @param s the {@code mimeType} to compare.
       
  1003      * @return true if the String (MimeType) is equal; false otherwise or if
       
  1004      *         {@code s} is {@code null}
       
  1005      */
       
  1006     @Deprecated
       
  1007     public boolean equals(String s) {
       
  1008         if (s == null || mimeType == null)
       
  1009             return false;
       
  1010         return isMimeTypeEqual(s);
       
  1011     }
       
  1012 
       
  1013     /**
       
  1014      * Returns hash code for this <code>DataFlavor</code>.
       
  1015      * For two equal <code>DataFlavor</code>s, hash codes are equal.
       
  1016      * For the <code>String</code>
       
  1017      * that matches <code>DataFlavor.equals(String)</code>, it is not
       
  1018      * guaranteed that <code>DataFlavor</code>'s hash code is equal
       
  1019      * to the hash code of the <code>String</code>.
       
  1020      *
       
  1021      * @return a hash code for this <code>DataFlavor</code>
       
  1022      */
       
  1023     public int hashCode() {
       
  1024         int total = 0;
       
  1025 
       
  1026         if (representationClass != null) {
       
  1027             total += representationClass.hashCode();
       
  1028         }
       
  1029 
       
  1030         if (mimeType != null) {
       
  1031             String primaryType = mimeType.getPrimaryType();
       
  1032             if (primaryType != null) {
       
  1033                 total += primaryType.hashCode();
       
  1034             }
       
  1035 
       
  1036             // Do not add subType.hashCode() to the total. equals uses
       
  1037             // MimeType.match which reports a match if one or both of the
       
  1038             // subTypes is '*', regardless of the other subType.
       
  1039 
       
  1040             if ("text".equals(primaryType)) {
       
  1041                 if (DataFlavorUtil.doesSubtypeSupportCharset(this)
       
  1042                         && representationClass != null
       
  1043                         && !isStandardTextRepresentationClass()) {
       
  1044                     String charset = DataFlavorUtil.canonicalName(getParameter("charset"));
       
  1045                     if (charset != null) {
       
  1046                         total += charset.hashCode();
       
  1047                     }
       
  1048                 }
       
  1049 
       
  1050                 if ("html".equals(getSubType())) {
       
  1051                     String document = this.getParameter("document");
       
  1052                     if (document != null) {
       
  1053                         total += document.hashCode();
       
  1054                     }
       
  1055                 }
       
  1056             }
       
  1057         }
       
  1058 
       
  1059         return total;
       
  1060     }
       
  1061 
       
  1062     /**
       
  1063      * Identical to {@link #equals(DataFlavor)}.
       
  1064      *
       
  1065      * @param that the <code>DataFlavor</code> to compare with
       
  1066      *        <code>this</code>
       
  1067      * @return <code>true</code> if <code>that</code> is equivalent to this
       
  1068      *         <code>DataFlavor</code>; <code>false</code> otherwise
       
  1069      * @see #selectBestTextFlavor
       
  1070      * @since 1.3
       
  1071      */
       
  1072     public boolean match(DataFlavor that) {
       
  1073         return equals(that);
       
  1074     }
       
  1075 
       
  1076     /**
       
  1077      * Returns whether the string representation of the MIME type passed in
       
  1078      * is equivalent to the MIME type of this <code>DataFlavor</code>.
       
  1079      * Parameters are not included in the comparison.
       
  1080      *
       
  1081      * @param mimeType the string representation of the MIME type
       
  1082      * @return true if the string representation of the MIME type passed in is
       
  1083      *         equivalent to the MIME type of this <code>DataFlavor</code>;
       
  1084      *         false otherwise
       
  1085      * @throws NullPointerException if mimeType is <code>null</code>
       
  1086      */
       
  1087     public boolean isMimeTypeEqual(String mimeType) {
       
  1088         // JCK Test DataFlavor0117: if 'mimeType' is null, throw NPE
       
  1089         if (mimeType == null) {
       
  1090             throw new NullPointerException("mimeType");
       
  1091         }
       
  1092         if (this.mimeType == null) {
       
  1093             return false;
       
  1094         }
       
  1095         try {
       
  1096             return this.mimeType.match(new MimeType(mimeType));
       
  1097         } catch (MimeTypeParseException mtpe) {
       
  1098             return false;
       
  1099         }
       
  1100     }
       
  1101 
       
  1102     /**
       
  1103      * Compares the <code>mimeType</code> of two <code>DataFlavor</code>
       
  1104      * objects. No parameters are considered.
       
  1105      *
       
  1106      * @param dataFlavor the <code>DataFlavor</code> to be compared
       
  1107      * @return true if the <code>MimeType</code>s are equal,
       
  1108      *  otherwise false
       
  1109      */
       
  1110 
       
  1111     public final boolean isMimeTypeEqual(DataFlavor dataFlavor) {
       
  1112         return isMimeTypeEqual(dataFlavor.mimeType);
       
  1113     }
       
  1114 
       
  1115     /**
       
  1116      * Compares the <code>mimeType</code> of two <code>DataFlavor</code>
       
  1117      * objects.  No parameters are considered.
       
  1118      *
       
  1119      * @return true if the <code>MimeType</code>s are equal,
       
  1120      *  otherwise false
       
  1121      */
       
  1122 
       
  1123     private boolean isMimeTypeEqual(MimeType mtype) {
       
  1124         if (this.mimeType == null) {
       
  1125             return (mtype == null);
       
  1126         }
       
  1127         return mimeType.match(mtype);
       
  1128     }
       
  1129 
       
  1130     /**
       
  1131      * Checks if the representation class is one of the standard text
       
  1132      * representation classes.
       
  1133      *
       
  1134      * @return true if the representation class is one of the standard text
       
  1135      *              representation classes, otherwise false
       
  1136      */
       
  1137     private boolean isStandardTextRepresentationClass() {
       
  1138         return isRepresentationClassReader()
       
  1139                 || String.class.equals(representationClass)
       
  1140                 || isRepresentationClassCharBuffer()
       
  1141                 || char[].class.equals(representationClass);
       
  1142     }
       
  1143 
       
  1144    /**
       
  1145     * Does the <code>DataFlavor</code> represent a serialized object?
       
  1146     * @return whether or not a serialized object is represented
       
  1147     */
       
  1148     public boolean isMimeTypeSerializedObject() {
       
  1149         return isMimeTypeEqual(javaSerializedObjectMimeType);
       
  1150     }
       
  1151 
       
  1152     /**
       
  1153      * Returns the default representation class.
       
  1154      * @return the default representation class
       
  1155      */
       
  1156     public final Class<?> getDefaultRepresentationClass() {
       
  1157         return ioInputStreamClass;
       
  1158     }
       
  1159 
       
  1160     /**
       
  1161      * Returns the name of the default representation class.
       
  1162      * @return the name of the default representation class
       
  1163      */
       
  1164     public final String getDefaultRepresentationClassAsString() {
       
  1165         return getDefaultRepresentationClass().getName();
       
  1166     }
       
  1167 
       
  1168    /**
       
  1169     * Does the <code>DataFlavor</code> represent a
       
  1170     * <code>java.io.InputStream</code>?
       
  1171     * @return whether or not this {@code DataFlavor} represent a
       
  1172     * {@code java.io.InputStream}
       
  1173     */
       
  1174     public boolean isRepresentationClassInputStream() {
       
  1175         return ioInputStreamClass.isAssignableFrom(representationClass);
       
  1176     }
       
  1177 
       
  1178     /**
       
  1179      * Returns whether the representation class for this
       
  1180      * <code>DataFlavor</code> is <code>java.io.Reader</code> or a subclass
       
  1181      * thereof.
       
  1182      * @return whether or not the representation class for this
       
  1183      * {@code DataFlavor} is {@code java.io.Reader} or a subclass
       
  1184      * thereof
       
  1185      *
       
  1186      * @since 1.4
       
  1187      */
       
  1188     public boolean isRepresentationClassReader() {
       
  1189         return java.io.Reader.class.isAssignableFrom(representationClass);
       
  1190     }
       
  1191 
       
  1192     /**
       
  1193      * Returns whether the representation class for this
       
  1194      * <code>DataFlavor</code> is <code>java.nio.CharBuffer</code> or a
       
  1195      * subclass thereof.
       
  1196      * @return whether or not the representation class for this
       
  1197      * {@code DataFlavor} is {@code java.nio.CharBuffer} or a subclass
       
  1198      * thereof
       
  1199      *
       
  1200      * @since 1.4
       
  1201      */
       
  1202     public boolean isRepresentationClassCharBuffer() {
       
  1203         return java.nio.CharBuffer.class.isAssignableFrom(representationClass);
       
  1204     }
       
  1205 
       
  1206     /**
       
  1207      * Returns whether the representation class for this
       
  1208      * <code>DataFlavor</code> is <code>java.nio.ByteBuffer</code> or a
       
  1209      * subclass thereof.
       
  1210      * @return whether or not the representation class for this
       
  1211      * {@code DataFlavor} is {@code java.nio.ByteBuffer} or a subclass
       
  1212      * thereof
       
  1213      *
       
  1214      * @since 1.4
       
  1215      */
       
  1216     public boolean isRepresentationClassByteBuffer() {
       
  1217         return java.nio.ByteBuffer.class.isAssignableFrom(representationClass);
       
  1218     }
       
  1219 
       
  1220    /**
       
  1221     * Returns true if the representation class can be serialized.
       
  1222     * @return true if the representation class can be serialized
       
  1223     */
       
  1224 
       
  1225     public boolean isRepresentationClassSerializable() {
       
  1226         return java.io.Serializable.class.isAssignableFrom(representationClass);
       
  1227     }
       
  1228 
       
  1229    /**
       
  1230     * Returns true if the representation class is <code>Remote</code>.
       
  1231     * @return true if the representation class is <code>Remote</code>
       
  1232     */
       
  1233     public boolean isRepresentationClassRemote() {
       
  1234         return DataFlavorUtil.RMI.isRemote(representationClass);
       
  1235     }
       
  1236 
       
  1237    /**
       
  1238     * Returns true if the <code>DataFlavor</code> specified represents
       
  1239     * a serialized object.
       
  1240     * @return true if the <code>DataFlavor</code> specified represents
       
  1241     *   a Serialized Object
       
  1242     */
       
  1243 
       
  1244     public boolean isFlavorSerializedObjectType() {
       
  1245         return isRepresentationClassSerializable() && isMimeTypeEqual(javaSerializedObjectMimeType);
       
  1246     }
       
  1247 
       
  1248     /**
       
  1249      * Returns true if the <code>DataFlavor</code> specified represents
       
  1250      * a remote object.
       
  1251      * @return true if the <code>DataFlavor</code> specified represents
       
  1252      *  a Remote Object
       
  1253      */
       
  1254 
       
  1255     public boolean isFlavorRemoteObjectType() {
       
  1256         return isRepresentationClassRemote()
       
  1257             && isRepresentationClassSerializable()
       
  1258             && isMimeTypeEqual(javaRemoteObjectMimeType);
       
  1259     }
       
  1260 
       
  1261 
       
  1262    /**
       
  1263     * Returns true if the <code>DataFlavor</code> specified represents
       
  1264     * a list of file objects.
       
  1265     * @return true if the <code>DataFlavor</code> specified represents
       
  1266     *   a List of File objects
       
  1267     */
       
  1268 
       
  1269    public boolean isFlavorJavaFileListType() {
       
  1270         if (mimeType == null || representationClass == null)
       
  1271             return false;
       
  1272         return java.util.List.class.isAssignableFrom(representationClass) &&
       
  1273                mimeType.match(javaFileListFlavor.mimeType);
       
  1274 
       
  1275    }
       
  1276 
       
  1277     /**
       
  1278      * Returns whether this <code>DataFlavor</code> is a valid text flavor for
       
  1279      * this implementation of the Java platform. Only flavors equivalent to
       
  1280      * <code>DataFlavor.stringFlavor</code> and <code>DataFlavor</code>s with
       
  1281      * a primary MIME type of "text" can be valid text flavors.
       
  1282      * <p>
       
  1283      * If this flavor supports the charset parameter, it must be equivalent to
       
  1284      * <code>DataFlavor.stringFlavor</code>, or its representation must be
       
  1285      * <code>java.io.Reader</code>, <code>java.lang.String</code>,
       
  1286      * <code>java.nio.CharBuffer</code>, <code>[C</code>,
       
  1287      * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
       
  1288      * <code>[B</code>. If the representation is
       
  1289      * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
       
  1290      * <code>[B</code>, then this flavor's <code>charset</code> parameter must
       
  1291      * be supported by this implementation of the Java platform. If a charset
       
  1292      * is not specified, then the platform default charset, which is always
       
  1293      * supported, is assumed.
       
  1294      * <p>
       
  1295      * If this flavor does not support the charset parameter, its
       
  1296      * representation must be <code>java.io.InputStream</code>,
       
  1297      * <code>java.nio.ByteBuffer</code>, or <code>[B</code>.
       
  1298      * <p>
       
  1299      * See <code>selectBestTextFlavor</code> for a list of text flavors which
       
  1300      * support the charset parameter.
       
  1301      *
       
  1302      * @return <code>true</code> if this <code>DataFlavor</code> is a valid
       
  1303      *         text flavor as described above; <code>false</code> otherwise
       
  1304      * @see #selectBestTextFlavor
       
  1305      * @since 1.4
       
  1306      */
       
  1307     public boolean isFlavorTextType() {
       
  1308         return (DataFlavorUtil.isFlavorCharsetTextType(this) ||
       
  1309                 DataFlavorUtil.isFlavorNoncharsetTextType(this));
       
  1310     }
       
  1311 
       
  1312    /**
       
  1313     * Serializes this <code>DataFlavor</code>.
       
  1314     */
       
  1315 
       
  1316    public synchronized void writeExternal(ObjectOutput os) throws IOException {
       
  1317        if (mimeType != null) {
       
  1318            mimeType.setParameter("humanPresentableName", humanPresentableName);
       
  1319            os.writeObject(mimeType);
       
  1320            mimeType.removeParameter("humanPresentableName");
       
  1321        } else {
       
  1322            os.writeObject(null);
       
  1323        }
       
  1324 
       
  1325        os.writeObject(representationClass);
       
  1326    }
       
  1327 
       
  1328    /**
       
  1329     * Restores this <code>DataFlavor</code> from a Serialized state.
       
  1330     */
       
  1331 
       
  1332    public synchronized void readExternal(ObjectInput is) throws IOException , ClassNotFoundException {
       
  1333        String rcn = null;
       
  1334         mimeType = (MimeType)is.readObject();
       
  1335 
       
  1336         if (mimeType != null) {
       
  1337             humanPresentableName =
       
  1338                 mimeType.getParameter("humanPresentableName");
       
  1339             mimeType.removeParameter("humanPresentableName");
       
  1340             rcn = mimeType.getParameter("class");
       
  1341             if (rcn == null) {
       
  1342                 throw new IOException("no class parameter specified in: " +
       
  1343                                       mimeType);
       
  1344             }
       
  1345         }
       
  1346 
       
  1347         try {
       
  1348             representationClass = (Class)is.readObject();
       
  1349         } catch (OptionalDataException ode) {
       
  1350             if (!ode.eof || ode.length != 0) {
       
  1351                 throw ode;
       
  1352             }
       
  1353             // Ensure backward compatibility.
       
  1354             // Old versions didn't write the representation class to the stream.
       
  1355             if (rcn != null) {
       
  1356                 representationClass =
       
  1357                     DataFlavor.tryToLoadClass(rcn, getClass().getClassLoader());
       
  1358             }
       
  1359         }
       
  1360    }
       
  1361 
       
  1362    /**
       
  1363     * Returns a clone of this <code>DataFlavor</code>.
       
  1364     * @return a clone of this <code>DataFlavor</code>
       
  1365     */
       
  1366 
       
  1367     public Object clone() throws CloneNotSupportedException {
       
  1368         Object newObj = super.clone();
       
  1369         if (mimeType != null) {
       
  1370             ((DataFlavor)newObj).mimeType = (MimeType)mimeType.clone();
       
  1371         }
       
  1372         return newObj;
       
  1373     } // clone()
       
  1374 
       
  1375    /**
       
  1376     * Called on <code>DataFlavor</code> for every MIME Type parameter
       
  1377     * to allow <code>DataFlavor</code> subclasses to handle special
       
  1378     * parameters like the text/plain <code>charset</code>
       
  1379     * parameters, whose values are case insensitive.  (MIME type parameter
       
  1380     * values are supposed to be case sensitive.
       
  1381     * <p>
       
  1382     * This method is called for each parameter name/value pair and should
       
  1383     * return the normalized representation of the <code>parameterValue</code>.
       
  1384     *
       
  1385     * This method is never invoked by this implementation from 1.1 onwards.
       
  1386     *
       
  1387     * @param parameterName the parameter name
       
  1388     * @param parameterValue the parameter value
       
  1389     * @return the parameter value
       
  1390     * @deprecated
       
  1391     */
       
  1392     @Deprecated
       
  1393     protected String normalizeMimeTypeParameter(String parameterName, String parameterValue) {
       
  1394         return parameterValue;
       
  1395     }
       
  1396 
       
  1397    /**
       
  1398     * Called for each MIME type string to give <code>DataFlavor</code> subtypes
       
  1399     * the opportunity to change how the normalization of MIME types is
       
  1400     * accomplished.  One possible use would be to add default
       
  1401     * parameter/value pairs in cases where none are present in the MIME
       
  1402     * type string passed in.
       
  1403     *
       
  1404     * This method is never invoked by this implementation from 1.1 onwards.
       
  1405     *
       
  1406     * @param mimeType the mime type
       
  1407     * @return the mime type
       
  1408     * @deprecated
       
  1409     */
       
  1410     @Deprecated
       
  1411     protected String normalizeMimeType(String mimeType) {
       
  1412         return mimeType;
       
  1413     }
       
  1414 
       
  1415     /*
       
  1416      * fields
       
  1417      */
       
  1418 
       
  1419     /* placeholder for caching any platform-specific data for flavor */
       
  1420 
       
  1421     transient int       atom;
       
  1422 
       
  1423     /* Mime Type of DataFlavor */
       
  1424 
       
  1425     MimeType            mimeType;
       
  1426 
       
  1427     private String      humanPresentableName;
       
  1428 
       
  1429     /** Java class of objects this DataFlavor represents **/
       
  1430 
       
  1431     private Class<?>       representationClass;
       
  1432 
       
  1433 } // class DataFlavor