--- old/src/java.desktop/share/classes/java/awt/datatransfer/DataFlavor.java 2015-01-12 23:23:51.678818700 +0400 +++ /dev/null 2015-01-12 23:23:51.000000000 +0400 @@ -1,1433 +0,0 @@ -/* - * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.awt.datatransfer; - -import sun.datatransfer.DataFlavorUtil; -import sun.reflect.misc.ReflectUtil; - -import java.io.ByteArrayInputStream; -import java.io.CharArrayReader; -import java.io.Externalizable; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.io.OptionalDataException; -import java.io.Reader; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.util.Arrays; -import java.util.Collections; -import java.util.Objects; - -import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; - -/** - * A {@code DataFlavor} provides meta information about data. {@code DataFlavor} - * is typically used to access data on the clipboard, or during - * a drag and drop operation. - *

- * An instance of {@code DataFlavor} encapsulates a content type as - * defined in RFC 2045 - * and RFC 2046. - * A content type is typically referred to as a MIME type. - *

- * A content type consists of a media type (referred - * to as the primary type), a subtype, and optional parameters. See - * RFC 2045 - * for details on the syntax of a MIME type. - *

- * The JRE data transfer implementation interprets the parameter "class" - * of a MIME type as a representation class. - * The representation class reflects the class of the object being - * transferred. In other words, the representation class is the type of - * object returned by {@link Transferable#getTransferData}. - * For example, the MIME type of {@link #imageFlavor} is - * {@code "image/x-java-image;class=java.awt.Image"}, - * the primary type is {@code image}, the subtype is - * {@code x-java-image}, and the representation class is - * {@code java.awt.Image}. When {@code getTransferData} is invoked - * with a {@code DataFlavor} of {@code imageFlavor}, an instance of - * {@code java.awt.Image} is returned. - * It's important to note that {@code DataFlavor} does no error checking - * against the representation class. It is up to consumers of - * {@code DataFlavor}, such as {@code Transferable}, to honor the representation - * class. - *
- * Note, if you do not specify a representation class when - * creating a {@code DataFlavor}, the default - * representation class is used. See appropriate documentation for - * {@code DataFlavor}'s constructors. - *

- * Also, {@code DataFlavor} instances with the "text" primary - * MIME type may have a "charset" parameter. Refer to - * RFC 2046 and - * {@link #selectBestTextFlavor} for details on "text" MIME types - * and the "charset" parameter. - *

- * Equality of {@code DataFlavors} is determined by the primary type, - * subtype, and representation class. Refer to {@link #equals(DataFlavor)} for - * details. When determining equality, any optional parameters are ignored. - * For example, the following produces two {@code DataFlavors} that - * are considered identical: - *

- *   DataFlavor flavor1 = new DataFlavor(Object.class, "X-test/test; class=<java.lang.Object>; foo=bar");
- *   DataFlavor flavor2 = new DataFlavor(Object.class, "X-test/test; class=<java.lang.Object>; x=y");
- *   // The following returns true.
- *   flavor1.equals(flavor2);
- * 
- * As mentioned, {@code flavor1} and {@code flavor2} are considered identical. - * As such, asking a {@code Transferable} for either {@code DataFlavor} returns - * the same results. - *

- * For more information on using data transfer with Swing see - * the - * How to Use Drag and Drop and Data Transfer, - * section in Java Tutorial. - * - * @author Blake Sullivan - * @author Laurence P. G. Cable - * @author Jeff Dunn - */ -public class DataFlavor implements Externalizable, Cloneable { - - private static final long serialVersionUID = 8367026044764648243L; - private static final Class ioInputStreamClass = InputStream.class; - - /** - * Tries to load a class from: the bootstrap loader, the system loader, - * the context loader (if one is present) and finally the loader specified. - * - * @param className the name of the class to be loaded - * @param fallback the fallback loader - * @return the class loaded - * @exception ClassNotFoundException if class is not found - */ - protected final static Class tryToLoadClass(String className, - ClassLoader fallback) - throws ClassNotFoundException - { - ReflectUtil.checkPackageAccess(className); - try { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(GET_CLASSLOADER_PERMISSION); - } - ClassLoader loader = ClassLoader.getSystemClassLoader(); - try { - // bootstrap class loader and system class loader if present - return Class.forName(className, true, loader); - } - catch (ClassNotFoundException exception) { - // thread context class loader if and only if present - loader = Thread.currentThread().getContextClassLoader(); - if (loader != null) { - try { - return Class.forName(className, true, loader); - } - catch (ClassNotFoundException e) { - // fallback to user's class loader - } - } - } - } catch (SecurityException exception) { - // ignore secured class loaders - } - return Class.forName(className, true, fallback); - } - - /* - * private initializer - */ - static private DataFlavor createConstant(Class rc, String prn) { - try { - return new DataFlavor(rc, prn); - } catch (Exception e) { - return null; - } - } - - /* - * private initializer - */ - static private DataFlavor createConstant(String mt, String prn) { - try { - return new DataFlavor(mt, prn); - } catch (Exception e) { - return null; - } - } - - /* - * private initializer - */ - static private DataFlavor initHtmlDataFlavor(String htmlFlavorType) { - try { - return new DataFlavor ("text/html; class=java.lang.String;document=" + - htmlFlavorType + ";charset=Unicode"); - } catch (Exception e) { - return null; - } - } - - /** - * The DataFlavor representing a Java Unicode String class, - * where: - *

-     *     representationClass = java.lang.String
-     *     mimeType           = "application/x-java-serialized-object"
-     * 
- */ - public static final DataFlavor stringFlavor = createConstant(java.lang.String.class, "Unicode String"); - - /** - * The DataFlavor representing a Java Image class, - * where: - *
-     *     representationClass = java.awt.Image
-     *     mimeType            = "image/x-java-image"
-     * 
- */ - public static final DataFlavor imageFlavor = createConstant("image/x-java-image; class=java.awt.Image", "Image"); - - /** - * The DataFlavor representing plain text with Unicode - * encoding, where: - *
-     *     representationClass = InputStream
-     *     mimeType            = "text/plain; charset=unicode"
-     * 
- * This DataFlavor has been deprecated because - * (1) Its representation is an InputStream, an 8-bit based representation, - * while Unicode is a 16-bit character set; and (2) The charset "unicode" - * is not well-defined. "unicode" implies a particular platform's - * implementation of Unicode, not a cross-platform implementation. - * - * @deprecated as of 1.3. Use DataFlavor.getReaderForText(Transferable) - * instead of Transferable.getTransferData(DataFlavor.plainTextFlavor). - */ - @Deprecated - public static final DataFlavor plainTextFlavor = createConstant("text/plain; charset=unicode; class=java.io.InputStream", "Plain Text"); - - /** - * A MIME Content-Type of application/x-java-serialized-object represents - * a graph of Java object(s) that have been made persistent. - * - * The representation class associated with this DataFlavor - * identifies the Java type of an object returned as a reference - * from an invocation java.awt.datatransfer.getTransferData. - */ - public static final String javaSerializedObjectMimeType = "application/x-java-serialized-object"; - - /** - * To transfer a list of files to/from Java (and the underlying - * platform) a DataFlavor of this type/subtype and - * representation class of java.util.List is used. - * Each element of the list is required/guaranteed to be of type - * java.io.File. - */ - public static final DataFlavor javaFileListFlavor = createConstant("application/x-java-file-list;class=java.util.List", null); - - /** - * To transfer a reference to an arbitrary Java object reference that - * has no associated MIME Content-type, across a Transferable - * interface WITHIN THE SAME JVM, a DataFlavor - * with this type/subtype is used, with a representationClass - * equal to the type of the class/interface being passed across the - * Transferable. - *

- * The object reference returned from - * Transferable.getTransferData for a DataFlavor - * with this MIME Content-Type is required to be - * an instance of the representation Class of the DataFlavor. - */ - public static final String javaJVMLocalObjectMimeType = "application/x-java-jvm-local-objectref"; - - /** - * In order to pass a live link to a Remote object via a Drag and Drop - * ACTION_LINK operation a Mime Content Type of - * application/x-java-remote-object should be used, - * where the representation class of the DataFlavor - * represents the type of the Remote interface to be - * transferred. - */ - public static final String javaRemoteObjectMimeType = "application/x-java-remote-object"; - - /** - * Represents a piece of an HTML markup. The markup consists of the part - * selected on the source side. Therefore some tags in the markup may be - * unpaired. If the flavor is used to represent the data in - * a {@link Transferable} instance, no additional changes will be made. - * This DataFlavor instance represents the same HTML markup as DataFlavor - * instances which content MIME type does not contain document parameter - * and representation class is the String class. - *

-     *     representationClass = String
-     *     mimeType           = "text/html"
-     * 
- */ - public static DataFlavor selectionHtmlFlavor = initHtmlDataFlavor("selection"); - - /** - * Represents a piece of an HTML markup. If possible, the markup received - * from a native system is supplemented with pair tags to be - * a well-formed HTML markup. If the flavor is used to represent the data in - * a {@link Transferable} instance, no additional changes will be made. - *
-     *     representationClass = String
-     *     mimeType           = "text/html"
-     * 
- */ - public static DataFlavor fragmentHtmlFlavor = initHtmlDataFlavor("fragment"); - - /** - * Represents a piece of an HTML markup. If possible, the markup - * received from a native system is supplemented with additional - * tags to make up a well-formed HTML document. If the flavor is used to - * represent the data in a {@link Transferable} instance, - * no additional changes will be made. - *
-     *     representationClass = String
-     *     mimeType           = "text/html"
-     * 
- */ - public static DataFlavor allHtmlFlavor = initHtmlDataFlavor("all"); - - /** - * Constructs a new DataFlavor. This constructor is - * provided only for the purpose of supporting the - * Externalizable interface. It is not - * intended for public (client) use. - * - * @since 1.2 - */ - public DataFlavor() { - super(); - } - - /** - * Constructs a fully specified DataFlavor. - * - * @exception NullPointerException if either primaryType, - * subType or representationClass is null - */ - private DataFlavor(String primaryType, String subType, MimeTypeParameterList params, Class representationClass, String humanPresentableName) { - super(); - if (primaryType == null) { - throw new NullPointerException("primaryType"); - } - if (subType == null) { - throw new NullPointerException("subType"); - } - if (representationClass == null) { - throw new NullPointerException("representationClass"); - } - - if (params == null) params = new MimeTypeParameterList(); - - params.set("class", representationClass.getName()); - - if (humanPresentableName == null) { - humanPresentableName = params.get("humanPresentableName"); - - if (humanPresentableName == null) - humanPresentableName = primaryType + "/" + subType; - } - - try { - mimeType = new MimeType(primaryType, subType, params); - } catch (MimeTypeParseException mtpe) { - throw new IllegalArgumentException("MimeType Parse Exception: " + mtpe.getMessage()); - } - - this.representationClass = representationClass; - this.humanPresentableName = humanPresentableName; - - mimeType.removeParameter("humanPresentableName"); - } - - /** - * Constructs a DataFlavor that represents a Java class. - *

- * The returned DataFlavor will have the following - * characteristics: - *

-     *    representationClass = representationClass
-     *    mimeType            = application/x-java-serialized-object
-     * 
- * @param representationClass the class used to transfer data in this flavor - * @param humanPresentableName the human-readable string used to identify - * this flavor; if this parameter is null - * then the value of the MIME Content Type is used - * @exception NullPointerException if representationClass is null - */ - public DataFlavor(Class representationClass, String humanPresentableName) { - this("application", "x-java-serialized-object", null, representationClass, humanPresentableName); - if (representationClass == null) { - throw new NullPointerException("representationClass"); - } - } - - /** - * Constructs a DataFlavor that represents a - * MimeType. - *

- * The returned DataFlavor will have the following - * characteristics: - *

- * If the mimeType is - * "application/x-java-serialized-object; class=<representation class>", - * the result is the same as calling - * new DataFlavor(Class.forName(<representation class>). - *

- * Otherwise: - *

-     *     representationClass = InputStream
-     *     mimeType            = mimeType
-     * 
- * @param mimeType the string used to identify the MIME type for this flavor; - * if the mimeType does not specify a - * "class=" parameter, or if the class is not successfully - * loaded, then an IllegalArgumentException - * is thrown - * @param humanPresentableName the human-readable string used to identify - * this flavor; if this parameter is null - * then the value of the MIME Content Type is used - * @exception IllegalArgumentException if mimeType is - * invalid or if the class is not successfully loaded - * @exception NullPointerException if mimeType is null - */ - public DataFlavor(String mimeType, String humanPresentableName) { - super(); - if (mimeType == null) { - throw new NullPointerException("mimeType"); - } - try { - initialize(mimeType, humanPresentableName, this.getClass().getClassLoader()); - } catch (MimeTypeParseException mtpe) { - throw new IllegalArgumentException("failed to parse:" + mimeType); - } catch (ClassNotFoundException cnfe) { - throw new IllegalArgumentException("can't find specified class: " + cnfe.getMessage()); - } - } - - /** - * Constructs a DataFlavor that represents a - * MimeType. - *

- * The returned DataFlavor will have the following - * characteristics: - *

- * If the mimeType is - * "application/x-java-serialized-object; class=<representation class>", - * the result is the same as calling - * new DataFlavor(Class.forName(<representation class>). - *

- * Otherwise: - *

-     *     representationClass = InputStream
-     *     mimeType            = mimeType
-     * 
- * @param mimeType the string used to identify the MIME type for this flavor - * @param humanPresentableName the human-readable string used to - * identify this flavor - * @param classLoader the class loader to use - * @exception ClassNotFoundException if the class is not loaded - * @exception IllegalArgumentException if mimeType is - * invalid - * @exception NullPointerException if mimeType is null - */ - public DataFlavor(String mimeType, String humanPresentableName, ClassLoader classLoader) throws ClassNotFoundException { - super(); - if (mimeType == null) { - throw new NullPointerException("mimeType"); - } - try { - initialize(mimeType, humanPresentableName, classLoader); - } catch (MimeTypeParseException mtpe) { - throw new IllegalArgumentException("failed to parse:" + mimeType); - } - } - - /** - * Constructs a DataFlavor from a mimeType string. - * The string can specify a "class=<fully specified Java class name>" - * parameter to create a DataFlavor with the desired - * representation class. If the string does not contain "class=" parameter, - * java.io.InputStream is used as default. - * - * @param mimeType the string used to identify the MIME type for this flavor; - * if the class specified by "class=" parameter is not - * successfully loaded, then an - * ClassNotFoundException is thrown - * @exception ClassNotFoundException if the class is not loaded - * @exception IllegalArgumentException if mimeType is - * invalid - * @exception NullPointerException if mimeType is null - */ - public DataFlavor(String mimeType) throws ClassNotFoundException { - super(); - if (mimeType == null) { - throw new NullPointerException("mimeType"); - } - try { - initialize(mimeType, null, this.getClass().getClassLoader()); - } catch (MimeTypeParseException mtpe) { - throw new IllegalArgumentException("failed to parse:" + mimeType); - } - } - - /** - * Common initialization code called from various constructors. - * - * @param mimeType the MIME Content Type (must have a class= param) - * @param humanPresentableName the human Presentable Name or - * null - * @param classLoader the fallback class loader to resolve against - * - * @throws MimeTypeParseException - * @throws ClassNotFoundException - * @throws NullPointerException if mimeType is null - * - * @see #tryToLoadClass - */ - private void initialize(String mimeType, String humanPresentableName, ClassLoader classLoader) throws MimeTypeParseException, ClassNotFoundException { - if (mimeType == null) { - throw new NullPointerException("mimeType"); - } - - this.mimeType = new MimeType(mimeType); // throws - - String rcn = getParameter("class"); - - if (rcn == null) { - if ("application/x-java-serialized-object".equals(this.mimeType.getBaseType())) - - throw new IllegalArgumentException("no representation class specified for:" + mimeType); - else - representationClass = java.io.InputStream.class; // default - } else { // got a class name - representationClass = DataFlavor.tryToLoadClass(rcn, classLoader); - } - - this.mimeType.setParameter("class", representationClass.getName()); - - if (humanPresentableName == null) { - humanPresentableName = this.mimeType.getParameter("humanPresentableName"); - if (humanPresentableName == null) - humanPresentableName = this.mimeType.getPrimaryType() + "/" + this.mimeType.getSubType(); - } - - this.humanPresentableName = humanPresentableName; // set it. - - this.mimeType.removeParameter("humanPresentableName"); // just in case - } - - /** - * String representation of this DataFlavor and its - * parameters. The resulting String contains the name of - * the DataFlavor class, this flavor's MIME type, and its - * representation class. If this flavor has a primary MIME type of "text", - * supports the charset parameter, and has an encoded representation, the - * flavor's charset is also included. See selectBestTextFlavor - * for a list of text flavors which support the charset parameter. - * - * @return string representation of this DataFlavor - * @see #selectBestTextFlavor - */ - public String toString() { - String string = getClass().getName(); - string += "["+paramString()+"]"; - return string; - } - - private String paramString() { - String params = ""; - params += "mimetype="; - if (mimeType == null) { - params += "null"; - } else { - params += mimeType.getBaseType(); - } - params += ";representationclass="; - if (representationClass == null) { - params += "null"; - } else { - params += representationClass.getName(); - } - if (DataFlavorUtil.isFlavorCharsetTextType(this) && - (isRepresentationClassInputStream() || - isRepresentationClassByteBuffer() || - byte[].class.equals(representationClass))) - { - params += ";charset=" + DataFlavorUtil.getTextCharset(this); - } - return params; - } - - /** - * Returns a DataFlavor representing plain text with Unicode - * encoding, where: - *
-     *     representationClass = java.io.InputStream
-     *     mimeType            = "text/plain;
-     *                            charset=<platform default Unicode encoding>"
-     * 
- * Sun's implementation for Microsoft Windows uses the encoding utf-16le. - * Sun's implementation for Solaris and Linux uses the encoding - * iso-10646-ucs-2. - * - * @return a DataFlavor representing plain text - * with Unicode encoding - * @since 1.3 - */ - public static final DataFlavor getTextPlainUnicodeFlavor() { - return new DataFlavor( - "text/plain;charset=" + DataFlavorUtil.getDesktopService().getDefaultUnicodeEncoding() - +";class=java.io.InputStream", "Plain Text"); - } - - /** - * Selects the best text DataFlavor from an array of - * DataFlavors. Only DataFlavor.stringFlavor, and - * equivalent flavors, and flavors that have a primary MIME type of "text", - * are considered for selection. - *

- * Flavors are first sorted by their MIME types in the following order: - *

- *

For example, "text/sgml" will be selected over - * "text/html", and DataFlavor.stringFlavor will be chosen - * over DataFlavor.plainTextFlavor. - *

- * If two or more flavors share the best MIME type in the array, then that - * MIME type will be checked to see if it supports the charset parameter. - *

- * The following MIME types support, or are treated as though they support, - * the charset parameter: - *

- * The following MIME types do not support, or are treated as though they - * do not support, the charset parameter: - * - * For "text/<other>" MIME types, the first time the JRE needs to - * determine whether the MIME type supports the charset parameter, it will - * check whether the parameter is explicitly listed in an arbitrarily - * chosen DataFlavor which uses that MIME type. If so, the JRE - * will assume from that point on that the MIME type supports the charset - * parameter and will not check again. If the parameter is not explicitly - * listed, the JRE will assume from that point on that the MIME type does - * not support the charset parameter and will not check again. Because - * this check is performed on an arbitrarily chosen - * DataFlavor, developers must ensure that all - * DataFlavors with a "text/<other>" MIME type specify - * the charset parameter if it is supported by that MIME type. Developers - * should never rely on the JRE to substitute the platform's default - * charset for a "text/<other>" DataFlavor. Failure to adhere to this - * restriction will lead to undefined behavior. - *

- * If the best MIME type in the array does not support the charset - * parameter, the flavors which share that MIME type will then be sorted by - * their representation classes in the following order: - * java.io.InputStream, java.nio.ByteBuffer, - * [B, <all others>. - *

- * If two or more flavors share the best representation class, or if no - * flavor has one of the three specified representations, then one of those - * flavors will be chosen non-deterministically. - *

- * If the best MIME type in the array does support the charset parameter, - * the flavors which share that MIME type will then be sorted by their - * representation classes in the following order: - * java.io.Reader, java.lang.String, - * java.nio.CharBuffer, [C, <all others>. - *

- * If two or more flavors share the best representation class, and that - * representation is one of the four explicitly listed, then one of those - * flavors will be chosen non-deterministically. If, however, no flavor has - * one of the four specified representations, the flavors will then be - * sorted by their charsets. Unicode charsets, such as "UTF-16", "UTF-8", - * "UTF-16BE", "UTF-16LE", and their aliases, are considered best. After - * them, the platform default charset and its aliases are selected. - * "US-ASCII" and its aliases are worst. All other charsets are chosen in - * alphabetical order, but only charsets supported by this implementation - * of the Java platform will be considered. - *

- * If two or more flavors share the best charset, the flavors will then - * again be sorted by their representation classes in the following order: - * java.io.InputStream, java.nio.ByteBuffer, - * [B, <all others>. - *

- * If two or more flavors share the best representation class, or if no - * flavor has one of the three specified representations, then one of those - * flavors will be chosen non-deterministically. - * - * @param availableFlavors an array of available DataFlavors - * @return the best (highest fidelity) flavor according to the rules - * specified above, or null, - * if availableFlavors is null, - * has zero length, or contains no text flavors - * @since 1.3 - */ - public static final DataFlavor selectBestTextFlavor( - DataFlavor[] availableFlavors) { - if (availableFlavors == null || availableFlavors.length == 0) { - return null; - } - - DataFlavor bestFlavor = Collections.max(Arrays.asList(availableFlavors), - DataFlavorUtil.getTextFlavorComparator()); - - if (!bestFlavor.isFlavorTextType()) { - return null; - } - - return bestFlavor; - } - - /** - * Gets a Reader for a text flavor, decoded, if necessary, for the expected - * charset (encoding). The supported representation classes are - * java.io.Reader, java.lang.String, - * java.nio.CharBuffer, [C, - * java.io.InputStream, java.nio.ByteBuffer, - * and [B. - *

- * Because text flavors which do not support the charset parameter are - * encoded in a non-standard format, this method should not be called for - * such flavors. However, in order to maintain backward-compatibility, - * if this method is called for such a flavor, this method will treat the - * flavor as though it supports the charset parameter and attempt to - * decode it accordingly. See selectBestTextFlavor for a list - * of text flavors which do not support the charset parameter. - * - * @param transferable the Transferable whose data will be - * requested in this flavor - * - * @return a Reader to read the Transferable's - * data - * - * @exception IllegalArgumentException if the representation class - * is not one of the seven listed above - * @exception IllegalArgumentException if the Transferable - * has null data - * @exception NullPointerException if the Transferable is - * null - * @exception UnsupportedEncodingException if this flavor's representation - * is java.io.InputStream, - * java.nio.ByteBuffer, or [B and - * this flavor's encoding is not supported by this - * implementation of the Java platform - * @exception UnsupportedFlavorException if the Transferable - * does not support this flavor - * @exception IOException if the data cannot be read because of an - * I/O error - * @see #selectBestTextFlavor - * @since 1.3 - */ - public Reader getReaderForText(Transferable transferable) - throws UnsupportedFlavorException, IOException - { - Object transferObject = transferable.getTransferData(this); - if (transferObject == null) { - throw new IllegalArgumentException - ("getTransferData() returned null"); - } - - if (transferObject instanceof Reader) { - return (Reader)transferObject; - } else if (transferObject instanceof String) { - return new StringReader((String)transferObject); - } else if (transferObject instanceof CharBuffer) { - CharBuffer buffer = (CharBuffer)transferObject; - int size = buffer.remaining(); - char[] chars = new char[size]; - buffer.get(chars, 0, size); - return new CharArrayReader(chars); - } else if (transferObject instanceof char[]) { - return new CharArrayReader((char[])transferObject); - } - - InputStream stream = null; - - if (transferObject instanceof InputStream) { - stream = (InputStream)transferObject; - } else if (transferObject instanceof ByteBuffer) { - ByteBuffer buffer = (ByteBuffer)transferObject; - int size = buffer.remaining(); - byte[] bytes = new byte[size]; - buffer.get(bytes, 0, size); - stream = new ByteArrayInputStream(bytes); - } else if (transferObject instanceof byte[]) { - stream = new ByteArrayInputStream((byte[])transferObject); - } - - if (stream == null) { - throw new IllegalArgumentException("transfer data is not Reader, String, CharBuffer, char array, InputStream, ByteBuffer, or byte array"); - } - - String encoding = getParameter("charset"); - return (encoding == null) - ? new InputStreamReader(stream) - : new InputStreamReader(stream, encoding); - } - - /** - * Returns the MIME type string for this DataFlavor. - * @return the MIME type string for this flavor - */ - public String getMimeType() { - return (mimeType != null) ? mimeType.toString() : null; - } - - /** - * Returns the Class which objects supporting this - * DataFlavor will return when this DataFlavor - * is requested. - * @return the Class which objects supporting this - * DataFlavor will return when this DataFlavor - * is requested - */ - public Class getRepresentationClass() { - return representationClass; - } - - /** - * Returns the human presentable name for the data format that this - * DataFlavor represents. This name would be localized - * for different countries. - * @return the human presentable name for the data format that this - * DataFlavor represents - */ - public String getHumanPresentableName() { - return humanPresentableName; - } - - /** - * Returns the primary MIME type for this DataFlavor. - * @return the primary MIME type of this DataFlavor - */ - public String getPrimaryType() { - return (mimeType != null) ? mimeType.getPrimaryType() : null; - } - - /** - * Returns the sub MIME type of this DataFlavor. - * @return the Sub MIME type of this DataFlavor - */ - public String getSubType() { - return (mimeType != null) ? mimeType.getSubType() : null; - } - - /** - * Returns the human presentable name for this DataFlavor - * if paramName equals "humanPresentableName". Otherwise - * returns the MIME type value associated with paramName. - * - * @param paramName the parameter name requested - * @return the value of the name parameter, or null - * if there is no associated value - */ - public String getParameter(String paramName) { - if (paramName.equals("humanPresentableName")) { - return humanPresentableName; - } else { - return (mimeType != null) - ? mimeType.getParameter(paramName) : null; - } - } - - /** - * Sets the human presentable name for the data format that this - * DataFlavor represents. This name would be localized - * for different countries. - * @param humanPresentableName the new human presentable name - */ - public void setHumanPresentableName(String humanPresentableName) { - this.humanPresentableName = humanPresentableName; - } - - /** - * {@inheritDoc} - *

- * The equals comparison for the {@code DataFlavor} class is implemented - * as follows: Two DataFlavors are considered equal if and - * only if their MIME primary type and subtype and representation class are - * equal. Additionally, if the primary type is "text", the subtype denotes - * a text flavor which supports the charset parameter, and the - * representation class is not java.io.Reader, - * java.lang.String, java.nio.CharBuffer, or - * [C, the charset parameter must also be equal. - * If a charset is not explicitly specified for one or both - * DataFlavors, the platform default encoding is assumed. See - * selectBestTextFlavor for a list of text flavors which - * support the charset parameter. - * - * @param o the Object to compare with this - * @return true if that is equivalent to this - * DataFlavor; false otherwise - * @see #selectBestTextFlavor - */ - public boolean equals(Object o) { - return ((o instanceof DataFlavor) && equals((DataFlavor)o)); - } - - /** - * This method has the same behavior as {@link #equals(Object)}. - * The only difference being that it takes a {@code DataFlavor} instance - * as a parameter. - * - * @param that the DataFlavor to compare with - * this - * @return true if that is equivalent to this - * DataFlavor; false otherwise - * @see #selectBestTextFlavor - */ - public boolean equals(DataFlavor that) { - if (that == null) { - return false; - } - if (this == that) { - return true; - } - - if (!Objects.equals(this.getRepresentationClass(), that.getRepresentationClass())) { - return false; - } - - if (mimeType == null) { - if (that.mimeType != null) { - return false; - } - } else { - if (!mimeType.match(that.mimeType)) { - return false; - } - - if ("text".equals(getPrimaryType())) { - if (DataFlavorUtil.doesSubtypeSupportCharset(this) - && representationClass != null - && !isStandardTextRepresentationClass()) { - String thisCharset = - DataFlavorUtil.canonicalName(this.getParameter("charset")); - String thatCharset = - DataFlavorUtil.canonicalName(that.getParameter("charset")); - if (!Objects.equals(thisCharset, thatCharset)) { - return false; - } - } - - if ("html".equals(getSubType())) { - String thisDocument = this.getParameter("document"); - String thatDocument = that.getParameter("document"); - if (!Objects.equals(thisDocument, thatDocument)) { - return false; - } - } - } - } - - return true; - } - - /** - * Compares only the mimeType against the passed in - * String and representationClass is - * not considered in the comparison. - * - * If representationClass needs to be compared, then - * equals(new DataFlavor(s)) may be used. - * @deprecated As inconsistent with hashCode() contract, - * use isMimeTypeEqual(String) instead. - * @param s the {@code mimeType} to compare. - * @return true if the String (MimeType) is equal; false otherwise or if - * {@code s} is {@code null} - */ - @Deprecated - public boolean equals(String s) { - if (s == null || mimeType == null) - return false; - return isMimeTypeEqual(s); - } - - /** - * Returns hash code for this DataFlavor. - * For two equal DataFlavors, hash codes are equal. - * For the String - * that matches DataFlavor.equals(String), it is not - * guaranteed that DataFlavor's hash code is equal - * to the hash code of the String. - * - * @return a hash code for this DataFlavor - */ - public int hashCode() { - int total = 0; - - if (representationClass != null) { - total += representationClass.hashCode(); - } - - if (mimeType != null) { - String primaryType = mimeType.getPrimaryType(); - if (primaryType != null) { - total += primaryType.hashCode(); - } - - // Do not add subType.hashCode() to the total. equals uses - // MimeType.match which reports a match if one or both of the - // subTypes is '*', regardless of the other subType. - - if ("text".equals(primaryType)) { - if (DataFlavorUtil.doesSubtypeSupportCharset(this) - && representationClass != null - && !isStandardTextRepresentationClass()) { - String charset = DataFlavorUtil.canonicalName(getParameter("charset")); - if (charset != null) { - total += charset.hashCode(); - } - } - - if ("html".equals(getSubType())) { - String document = this.getParameter("document"); - if (document != null) { - total += document.hashCode(); - } - } - } - } - - return total; - } - - /** - * Identical to {@link #equals(DataFlavor)}. - * - * @param that the DataFlavor to compare with - * this - * @return true if that is equivalent to this - * DataFlavor; false otherwise - * @see #selectBestTextFlavor - * @since 1.3 - */ - public boolean match(DataFlavor that) { - return equals(that); - } - - /** - * Returns whether the string representation of the MIME type passed in - * is equivalent to the MIME type of this DataFlavor. - * Parameters are not included in the comparison. - * - * @param mimeType the string representation of the MIME type - * @return true if the string representation of the MIME type passed in is - * equivalent to the MIME type of this DataFlavor; - * false otherwise - * @throws NullPointerException if mimeType is null - */ - public boolean isMimeTypeEqual(String mimeType) { - // JCK Test DataFlavor0117: if 'mimeType' is null, throw NPE - if (mimeType == null) { - throw new NullPointerException("mimeType"); - } - if (this.mimeType == null) { - return false; - } - try { - return this.mimeType.match(new MimeType(mimeType)); - } catch (MimeTypeParseException mtpe) { - return false; - } - } - - /** - * Compares the mimeType of two DataFlavor - * objects. No parameters are considered. - * - * @param dataFlavor the DataFlavor to be compared - * @return true if the MimeTypes are equal, - * otherwise false - */ - - public final boolean isMimeTypeEqual(DataFlavor dataFlavor) { - return isMimeTypeEqual(dataFlavor.mimeType); - } - - /** - * Compares the mimeType of two DataFlavor - * objects. No parameters are considered. - * - * @return true if the MimeTypes are equal, - * otherwise false - */ - - private boolean isMimeTypeEqual(MimeType mtype) { - if (this.mimeType == null) { - return (mtype == null); - } - return mimeType.match(mtype); - } - - /** - * Checks if the representation class is one of the standard text - * representation classes. - * - * @return true if the representation class is one of the standard text - * representation classes, otherwise false - */ - private boolean isStandardTextRepresentationClass() { - return isRepresentationClassReader() - || String.class.equals(representationClass) - || isRepresentationClassCharBuffer() - || char[].class.equals(representationClass); - } - - /** - * Does the DataFlavor represent a serialized object? - * @return whether or not a serialized object is represented - */ - public boolean isMimeTypeSerializedObject() { - return isMimeTypeEqual(javaSerializedObjectMimeType); - } - - /** - * Returns the default representation class. - * @return the default representation class - */ - public final Class getDefaultRepresentationClass() { - return ioInputStreamClass; - } - - /** - * Returns the name of the default representation class. - * @return the name of the default representation class - */ - public final String getDefaultRepresentationClassAsString() { - return getDefaultRepresentationClass().getName(); - } - - /** - * Does the DataFlavor represent a - * java.io.InputStream? - * @return whether or not this {@code DataFlavor} represent a - * {@code java.io.InputStream} - */ - public boolean isRepresentationClassInputStream() { - return ioInputStreamClass.isAssignableFrom(representationClass); - } - - /** - * Returns whether the representation class for this - * DataFlavor is java.io.Reader or a subclass - * thereof. - * @return whether or not the representation class for this - * {@code DataFlavor} is {@code java.io.Reader} or a subclass - * thereof - * - * @since 1.4 - */ - public boolean isRepresentationClassReader() { - return java.io.Reader.class.isAssignableFrom(representationClass); - } - - /** - * Returns whether the representation class for this - * DataFlavor is java.nio.CharBuffer or a - * subclass thereof. - * @return whether or not the representation class for this - * {@code DataFlavor} is {@code java.nio.CharBuffer} or a subclass - * thereof - * - * @since 1.4 - */ - public boolean isRepresentationClassCharBuffer() { - return java.nio.CharBuffer.class.isAssignableFrom(representationClass); - } - - /** - * Returns whether the representation class for this - * DataFlavor is java.nio.ByteBuffer or a - * subclass thereof. - * @return whether or not the representation class for this - * {@code DataFlavor} is {@code java.nio.ByteBuffer} or a subclass - * thereof - * - * @since 1.4 - */ - public boolean isRepresentationClassByteBuffer() { - return java.nio.ByteBuffer.class.isAssignableFrom(representationClass); - } - - /** - * Returns true if the representation class can be serialized. - * @return true if the representation class can be serialized - */ - - public boolean isRepresentationClassSerializable() { - return java.io.Serializable.class.isAssignableFrom(representationClass); - } - - /** - * Returns true if the representation class is Remote. - * @return true if the representation class is Remote - */ - public boolean isRepresentationClassRemote() { - return DataFlavorUtil.RMI.isRemote(representationClass); - } - - /** - * Returns true if the DataFlavor specified represents - * a serialized object. - * @return true if the DataFlavor specified represents - * a Serialized Object - */ - - public boolean isFlavorSerializedObjectType() { - return isRepresentationClassSerializable() && isMimeTypeEqual(javaSerializedObjectMimeType); - } - - /** - * Returns true if the DataFlavor specified represents - * a remote object. - * @return true if the DataFlavor specified represents - * a Remote Object - */ - - public boolean isFlavorRemoteObjectType() { - return isRepresentationClassRemote() - && isRepresentationClassSerializable() - && isMimeTypeEqual(javaRemoteObjectMimeType); - } - - - /** - * Returns true if the DataFlavor specified represents - * a list of file objects. - * @return true if the DataFlavor specified represents - * a List of File objects - */ - - public boolean isFlavorJavaFileListType() { - if (mimeType == null || representationClass == null) - return false; - return java.util.List.class.isAssignableFrom(representationClass) && - mimeType.match(javaFileListFlavor.mimeType); - - } - - /** - * Returns whether this DataFlavor is a valid text flavor for - * this implementation of the Java platform. Only flavors equivalent to - * DataFlavor.stringFlavor and DataFlavors with - * a primary MIME type of "text" can be valid text flavors. - *

- * If this flavor supports the charset parameter, it must be equivalent to - * DataFlavor.stringFlavor, or its representation must be - * java.io.Reader, java.lang.String, - * java.nio.CharBuffer, [C, - * java.io.InputStream, java.nio.ByteBuffer, or - * [B. If the representation is - * java.io.InputStream, java.nio.ByteBuffer, or - * [B, then this flavor's charset parameter must - * be supported by this implementation of the Java platform. If a charset - * is not specified, then the platform default charset, which is always - * supported, is assumed. - *

- * If this flavor does not support the charset parameter, its - * representation must be java.io.InputStream, - * java.nio.ByteBuffer, or [B. - *

- * See selectBestTextFlavor for a list of text flavors which - * support the charset parameter. - * - * @return true if this DataFlavor is a valid - * text flavor as described above; false otherwise - * @see #selectBestTextFlavor - * @since 1.4 - */ - public boolean isFlavorTextType() { - return (DataFlavorUtil.isFlavorCharsetTextType(this) || - DataFlavorUtil.isFlavorNoncharsetTextType(this)); - } - - /** - * Serializes this DataFlavor. - */ - - public synchronized void writeExternal(ObjectOutput os) throws IOException { - if (mimeType != null) { - mimeType.setParameter("humanPresentableName", humanPresentableName); - os.writeObject(mimeType); - mimeType.removeParameter("humanPresentableName"); - } else { - os.writeObject(null); - } - - os.writeObject(representationClass); - } - - /** - * Restores this DataFlavor from a Serialized state. - */ - - public synchronized void readExternal(ObjectInput is) throws IOException , ClassNotFoundException { - String rcn = null; - mimeType = (MimeType)is.readObject(); - - if (mimeType != null) { - humanPresentableName = - mimeType.getParameter("humanPresentableName"); - mimeType.removeParameter("humanPresentableName"); - rcn = mimeType.getParameter("class"); - if (rcn == null) { - throw new IOException("no class parameter specified in: " + - mimeType); - } - } - - try { - representationClass = (Class)is.readObject(); - } catch (OptionalDataException ode) { - if (!ode.eof || ode.length != 0) { - throw ode; - } - // Ensure backward compatibility. - // Old versions didn't write the representation class to the stream. - if (rcn != null) { - representationClass = - DataFlavor.tryToLoadClass(rcn, getClass().getClassLoader()); - } - } - } - - /** - * Returns a clone of this DataFlavor. - * @return a clone of this DataFlavor - */ - - public Object clone() throws CloneNotSupportedException { - Object newObj = super.clone(); - if (mimeType != null) { - ((DataFlavor)newObj).mimeType = (MimeType)mimeType.clone(); - } - return newObj; - } // clone() - - /** - * Called on DataFlavor for every MIME Type parameter - * to allow DataFlavor subclasses to handle special - * parameters like the text/plain charset - * parameters, whose values are case insensitive. (MIME type parameter - * values are supposed to be case sensitive. - *

- * This method is called for each parameter name/value pair and should - * return the normalized representation of the parameterValue. - * - * This method is never invoked by this implementation from 1.1 onwards. - * - * @param parameterName the parameter name - * @param parameterValue the parameter value - * @return the parameter value - * @deprecated - */ - @Deprecated - protected String normalizeMimeTypeParameter(String parameterName, String parameterValue) { - return parameterValue; - } - - /** - * Called for each MIME type string to give DataFlavor subtypes - * the opportunity to change how the normalization of MIME types is - * accomplished. One possible use would be to add default - * parameter/value pairs in cases where none are present in the MIME - * type string passed in. - * - * This method is never invoked by this implementation from 1.1 onwards. - * - * @param mimeType the mime type - * @return the mime type - * @deprecated - */ - @Deprecated - protected String normalizeMimeType(String mimeType) { - return mimeType; - } - - /* - * fields - */ - - /* placeholder for caching any platform-specific data for flavor */ - - transient int atom; - - /* Mime Type of DataFlavor */ - - MimeType mimeType; - - private String humanPresentableName; - - /** Java class of objects this DataFlavor represents **/ - - private Class representationClass; - -} // class DataFlavor --- /dev/null 2015-01-12 23:23:51.000000000 +0400 +++ new/src/java.datatransfer/share/classes/java/awt/datatransfer/DataFlavor.java 2015-01-12 23:23:51.447805500 +0400 @@ -0,0 +1,1433 @@ +/* + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.awt.datatransfer; + +import sun.datatransfer.DataFlavorUtil; +import sun.reflect.misc.ReflectUtil; + +import java.io.ByteArrayInputStream; +import java.io.CharArrayReader; +import java.io.Externalizable; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.OptionalDataException; +import java.io.Reader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.util.Arrays; +import java.util.Collections; +import java.util.Objects; + +import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; + +/** + * A {@code DataFlavor} provides meta information about data. {@code DataFlavor} + * is typically used to access data on the clipboard, or during + * a drag and drop operation. + *

+ * An instance of {@code DataFlavor} encapsulates a content type as + * defined in RFC 2045 + * and RFC 2046. + * A content type is typically referred to as a MIME type. + *

+ * A content type consists of a media type (referred + * to as the primary type), a subtype, and optional parameters. See + * RFC 2045 + * for details on the syntax of a MIME type. + *

+ * The JRE data transfer implementation interprets the parameter "class" + * of a MIME type as a representation class. + * The representation class reflects the class of the object being + * transferred. In other words, the representation class is the type of + * object returned by {@link Transferable#getTransferData}. + * For example, the MIME type of {@link #imageFlavor} is + * {@code "image/x-java-image;class=java.awt.Image"}, + * the primary type is {@code image}, the subtype is + * {@code x-java-image}, and the representation class is + * {@code java.awt.Image}. When {@code getTransferData} is invoked + * with a {@code DataFlavor} of {@code imageFlavor}, an instance of + * {@code java.awt.Image} is returned. + * It's important to note that {@code DataFlavor} does no error checking + * against the representation class. It is up to consumers of + * {@code DataFlavor}, such as {@code Transferable}, to honor the representation + * class. + *
+ * Note, if you do not specify a representation class when + * creating a {@code DataFlavor}, the default + * representation class is used. See appropriate documentation for + * {@code DataFlavor}'s constructors. + *

+ * Also, {@code DataFlavor} instances with the "text" primary + * MIME type may have a "charset" parameter. Refer to + * RFC 2046 and + * {@link #selectBestTextFlavor} for details on "text" MIME types + * and the "charset" parameter. + *

+ * Equality of {@code DataFlavors} is determined by the primary type, + * subtype, and representation class. Refer to {@link #equals(DataFlavor)} for + * details. When determining equality, any optional parameters are ignored. + * For example, the following produces two {@code DataFlavors} that + * are considered identical: + *

+ *   DataFlavor flavor1 = new DataFlavor(Object.class, "X-test/test; class=<java.lang.Object>; foo=bar");
+ *   DataFlavor flavor2 = new DataFlavor(Object.class, "X-test/test; class=<java.lang.Object>; x=y");
+ *   // The following returns true.
+ *   flavor1.equals(flavor2);
+ * 
+ * As mentioned, {@code flavor1} and {@code flavor2} are considered identical. + * As such, asking a {@code Transferable} for either {@code DataFlavor} returns + * the same results. + *

+ * For more information on using data transfer with Swing see + * the + * How to Use Drag and Drop and Data Transfer, + * section in Java Tutorial. + * + * @author Blake Sullivan + * @author Laurence P. G. Cable + * @author Jeff Dunn + */ +public class DataFlavor implements Externalizable, Cloneable { + + private static final long serialVersionUID = 8367026044764648243L; + private static final Class ioInputStreamClass = InputStream.class; + + /** + * Tries to load a class from: the bootstrap loader, the system loader, + * the context loader (if one is present) and finally the loader specified. + * + * @param className the name of the class to be loaded + * @param fallback the fallback loader + * @return the class loaded + * @exception ClassNotFoundException if class is not found + */ + protected final static Class tryToLoadClass(String className, + ClassLoader fallback) + throws ClassNotFoundException + { + ReflectUtil.checkPackageAccess(className); + try { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(GET_CLASSLOADER_PERMISSION); + } + ClassLoader loader = ClassLoader.getSystemClassLoader(); + try { + // bootstrap class loader and system class loader if present + return Class.forName(className, true, loader); + } + catch (ClassNotFoundException exception) { + // thread context class loader if and only if present + loader = Thread.currentThread().getContextClassLoader(); + if (loader != null) { + try { + return Class.forName(className, true, loader); + } + catch (ClassNotFoundException e) { + // fallback to user's class loader + } + } + } + } catch (SecurityException exception) { + // ignore secured class loaders + } + return Class.forName(className, true, fallback); + } + + /* + * private initializer + */ + static private DataFlavor createConstant(Class rc, String prn) { + try { + return new DataFlavor(rc, prn); + } catch (Exception e) { + return null; + } + } + + /* + * private initializer + */ + static private DataFlavor createConstant(String mt, String prn) { + try { + return new DataFlavor(mt, prn); + } catch (Exception e) { + return null; + } + } + + /* + * private initializer + */ + static private DataFlavor initHtmlDataFlavor(String htmlFlavorType) { + try { + return new DataFlavor ("text/html; class=java.lang.String;document=" + + htmlFlavorType + ";charset=Unicode"); + } catch (Exception e) { + return null; + } + } + + /** + * The DataFlavor representing a Java Unicode String class, + * where: + *

+     *     representationClass = java.lang.String
+     *     mimeType           = "application/x-java-serialized-object"
+     * 
+ */ + public static final DataFlavor stringFlavor = createConstant(java.lang.String.class, "Unicode String"); + + /** + * The DataFlavor representing a Java Image class, + * where: + *
+     *     representationClass = java.awt.Image
+     *     mimeType            = "image/x-java-image"
+     * 
+ */ + public static final DataFlavor imageFlavor = createConstant("image/x-java-image; class=java.awt.Image", "Image"); + + /** + * The DataFlavor representing plain text with Unicode + * encoding, where: + *
+     *     representationClass = InputStream
+     *     mimeType            = "text/plain; charset=unicode"
+     * 
+ * This DataFlavor has been deprecated because + * (1) Its representation is an InputStream, an 8-bit based representation, + * while Unicode is a 16-bit character set; and (2) The charset "unicode" + * is not well-defined. "unicode" implies a particular platform's + * implementation of Unicode, not a cross-platform implementation. + * + * @deprecated as of 1.3. Use DataFlavor.getReaderForText(Transferable) + * instead of Transferable.getTransferData(DataFlavor.plainTextFlavor). + */ + @Deprecated + public static final DataFlavor plainTextFlavor = createConstant("text/plain; charset=unicode; class=java.io.InputStream", "Plain Text"); + + /** + * A MIME Content-Type of application/x-java-serialized-object represents + * a graph of Java object(s) that have been made persistent. + * + * The representation class associated with this DataFlavor + * identifies the Java type of an object returned as a reference + * from an invocation java.awt.datatransfer.getTransferData. + */ + public static final String javaSerializedObjectMimeType = "application/x-java-serialized-object"; + + /** + * To transfer a list of files to/from Java (and the underlying + * platform) a DataFlavor of this type/subtype and + * representation class of java.util.List is used. + * Each element of the list is required/guaranteed to be of type + * java.io.File. + */ + public static final DataFlavor javaFileListFlavor = createConstant("application/x-java-file-list;class=java.util.List", null); + + /** + * To transfer a reference to an arbitrary Java object reference that + * has no associated MIME Content-type, across a Transferable + * interface WITHIN THE SAME JVM, a DataFlavor + * with this type/subtype is used, with a representationClass + * equal to the type of the class/interface being passed across the + * Transferable. + *

+ * The object reference returned from + * Transferable.getTransferData for a DataFlavor + * with this MIME Content-Type is required to be + * an instance of the representation Class of the DataFlavor. + */ + public static final String javaJVMLocalObjectMimeType = "application/x-java-jvm-local-objectref"; + + /** + * In order to pass a live link to a Remote object via a Drag and Drop + * ACTION_LINK operation a Mime Content Type of + * application/x-java-remote-object should be used, + * where the representation class of the DataFlavor + * represents the type of the Remote interface to be + * transferred. + */ + public static final String javaRemoteObjectMimeType = "application/x-java-remote-object"; + + /** + * Represents a piece of an HTML markup. The markup consists of the part + * selected on the source side. Therefore some tags in the markup may be + * unpaired. If the flavor is used to represent the data in + * a {@link Transferable} instance, no additional changes will be made. + * This DataFlavor instance represents the same HTML markup as DataFlavor + * instances which content MIME type does not contain document parameter + * and representation class is the String class. + *

+     *     representationClass = String
+     *     mimeType           = "text/html"
+     * 
+ */ + public static DataFlavor selectionHtmlFlavor = initHtmlDataFlavor("selection"); + + /** + * Represents a piece of an HTML markup. If possible, the markup received + * from a native system is supplemented with pair tags to be + * a well-formed HTML markup. If the flavor is used to represent the data in + * a {@link Transferable} instance, no additional changes will be made. + *
+     *     representationClass = String
+     *     mimeType           = "text/html"
+     * 
+ */ + public static DataFlavor fragmentHtmlFlavor = initHtmlDataFlavor("fragment"); + + /** + * Represents a piece of an HTML markup. If possible, the markup + * received from a native system is supplemented with additional + * tags to make up a well-formed HTML document. If the flavor is used to + * represent the data in a {@link Transferable} instance, + * no additional changes will be made. + *
+     *     representationClass = String
+     *     mimeType           = "text/html"
+     * 
+ */ + public static DataFlavor allHtmlFlavor = initHtmlDataFlavor("all"); + + /** + * Constructs a new DataFlavor. This constructor is + * provided only for the purpose of supporting the + * Externalizable interface. It is not + * intended for public (client) use. + * + * @since 1.2 + */ + public DataFlavor() { + super(); + } + + /** + * Constructs a fully specified DataFlavor. + * + * @exception NullPointerException if either primaryType, + * subType or representationClass is null + */ + private DataFlavor(String primaryType, String subType, MimeTypeParameterList params, Class representationClass, String humanPresentableName) { + super(); + if (primaryType == null) { + throw new NullPointerException("primaryType"); + } + if (subType == null) { + throw new NullPointerException("subType"); + } + if (representationClass == null) { + throw new NullPointerException("representationClass"); + } + + if (params == null) params = new MimeTypeParameterList(); + + params.set("class", representationClass.getName()); + + if (humanPresentableName == null) { + humanPresentableName = params.get("humanPresentableName"); + + if (humanPresentableName == null) + humanPresentableName = primaryType + "/" + subType; + } + + try { + mimeType = new MimeType(primaryType, subType, params); + } catch (MimeTypeParseException mtpe) { + throw new IllegalArgumentException("MimeType Parse Exception: " + mtpe.getMessage()); + } + + this.representationClass = representationClass; + this.humanPresentableName = humanPresentableName; + + mimeType.removeParameter("humanPresentableName"); + } + + /** + * Constructs a DataFlavor that represents a Java class. + *

+ * The returned DataFlavor will have the following + * characteristics: + *

+     *    representationClass = representationClass
+     *    mimeType            = application/x-java-serialized-object
+     * 
+ * @param representationClass the class used to transfer data in this flavor + * @param humanPresentableName the human-readable string used to identify + * this flavor; if this parameter is null + * then the value of the MIME Content Type is used + * @exception NullPointerException if representationClass is null + */ + public DataFlavor(Class representationClass, String humanPresentableName) { + this("application", "x-java-serialized-object", null, representationClass, humanPresentableName); + if (representationClass == null) { + throw new NullPointerException("representationClass"); + } + } + + /** + * Constructs a DataFlavor that represents a + * MimeType. + *

+ * The returned DataFlavor will have the following + * characteristics: + *

+ * If the mimeType is + * "application/x-java-serialized-object; class=<representation class>", + * the result is the same as calling + * new DataFlavor(Class.forName(<representation class>). + *

+ * Otherwise: + *

+     *     representationClass = InputStream
+     *     mimeType            = mimeType
+     * 
+ * @param mimeType the string used to identify the MIME type for this flavor; + * if the mimeType does not specify a + * "class=" parameter, or if the class is not successfully + * loaded, then an IllegalArgumentException + * is thrown + * @param humanPresentableName the human-readable string used to identify + * this flavor; if this parameter is null + * then the value of the MIME Content Type is used + * @exception IllegalArgumentException if mimeType is + * invalid or if the class is not successfully loaded + * @exception NullPointerException if mimeType is null + */ + public DataFlavor(String mimeType, String humanPresentableName) { + super(); + if (mimeType == null) { + throw new NullPointerException("mimeType"); + } + try { + initialize(mimeType, humanPresentableName, this.getClass().getClassLoader()); + } catch (MimeTypeParseException mtpe) { + throw new IllegalArgumentException("failed to parse:" + mimeType); + } catch (ClassNotFoundException cnfe) { + throw new IllegalArgumentException("can't find specified class: " + cnfe.getMessage()); + } + } + + /** + * Constructs a DataFlavor that represents a + * MimeType. + *

+ * The returned DataFlavor will have the following + * characteristics: + *

+ * If the mimeType is + * "application/x-java-serialized-object; class=<representation class>", + * the result is the same as calling + * new DataFlavor(Class.forName(<representation class>). + *

+ * Otherwise: + *

+     *     representationClass = InputStream
+     *     mimeType            = mimeType
+     * 
+ * @param mimeType the string used to identify the MIME type for this flavor + * @param humanPresentableName the human-readable string used to + * identify this flavor + * @param classLoader the class loader to use + * @exception ClassNotFoundException if the class is not loaded + * @exception IllegalArgumentException if mimeType is + * invalid + * @exception NullPointerException if mimeType is null + */ + public DataFlavor(String mimeType, String humanPresentableName, ClassLoader classLoader) throws ClassNotFoundException { + super(); + if (mimeType == null) { + throw new NullPointerException("mimeType"); + } + try { + initialize(mimeType, humanPresentableName, classLoader); + } catch (MimeTypeParseException mtpe) { + throw new IllegalArgumentException("failed to parse:" + mimeType); + } + } + + /** + * Constructs a DataFlavor from a mimeType string. + * The string can specify a "class=<fully specified Java class name>" + * parameter to create a DataFlavor with the desired + * representation class. If the string does not contain "class=" parameter, + * java.io.InputStream is used as default. + * + * @param mimeType the string used to identify the MIME type for this flavor; + * if the class specified by "class=" parameter is not + * successfully loaded, then an + * ClassNotFoundException is thrown + * @exception ClassNotFoundException if the class is not loaded + * @exception IllegalArgumentException if mimeType is + * invalid + * @exception NullPointerException if mimeType is null + */ + public DataFlavor(String mimeType) throws ClassNotFoundException { + super(); + if (mimeType == null) { + throw new NullPointerException("mimeType"); + } + try { + initialize(mimeType, null, this.getClass().getClassLoader()); + } catch (MimeTypeParseException mtpe) { + throw new IllegalArgumentException("failed to parse:" + mimeType); + } + } + + /** + * Common initialization code called from various constructors. + * + * @param mimeType the MIME Content Type (must have a class= param) + * @param humanPresentableName the human Presentable Name or + * null + * @param classLoader the fallback class loader to resolve against + * + * @throws MimeTypeParseException + * @throws ClassNotFoundException + * @throws NullPointerException if mimeType is null + * + * @see #tryToLoadClass + */ + private void initialize(String mimeType, String humanPresentableName, ClassLoader classLoader) throws MimeTypeParseException, ClassNotFoundException { + if (mimeType == null) { + throw new NullPointerException("mimeType"); + } + + this.mimeType = new MimeType(mimeType); // throws + + String rcn = getParameter("class"); + + if (rcn == null) { + if ("application/x-java-serialized-object".equals(this.mimeType.getBaseType())) + + throw new IllegalArgumentException("no representation class specified for:" + mimeType); + else + representationClass = java.io.InputStream.class; // default + } else { // got a class name + representationClass = DataFlavor.tryToLoadClass(rcn, classLoader); + } + + this.mimeType.setParameter("class", representationClass.getName()); + + if (humanPresentableName == null) { + humanPresentableName = this.mimeType.getParameter("humanPresentableName"); + if (humanPresentableName == null) + humanPresentableName = this.mimeType.getPrimaryType() + "/" + this.mimeType.getSubType(); + } + + this.humanPresentableName = humanPresentableName; // set it. + + this.mimeType.removeParameter("humanPresentableName"); // just in case + } + + /** + * String representation of this DataFlavor and its + * parameters. The resulting String contains the name of + * the DataFlavor class, this flavor's MIME type, and its + * representation class. If this flavor has a primary MIME type of "text", + * supports the charset parameter, and has an encoded representation, the + * flavor's charset is also included. See selectBestTextFlavor + * for a list of text flavors which support the charset parameter. + * + * @return string representation of this DataFlavor + * @see #selectBestTextFlavor + */ + public String toString() { + String string = getClass().getName(); + string += "["+paramString()+"]"; + return string; + } + + private String paramString() { + String params = ""; + params += "mimetype="; + if (mimeType == null) { + params += "null"; + } else { + params += mimeType.getBaseType(); + } + params += ";representationclass="; + if (representationClass == null) { + params += "null"; + } else { + params += representationClass.getName(); + } + if (DataFlavorUtil.isFlavorCharsetTextType(this) && + (isRepresentationClassInputStream() || + isRepresentationClassByteBuffer() || + byte[].class.equals(representationClass))) + { + params += ";charset=" + DataFlavorUtil.getTextCharset(this); + } + return params; + } + + /** + * Returns a DataFlavor representing plain text with Unicode + * encoding, where: + *
+     *     representationClass = java.io.InputStream
+     *     mimeType            = "text/plain;
+     *                            charset=<platform default Unicode encoding>"
+     * 
+ * Sun's implementation for Microsoft Windows uses the encoding utf-16le. + * Sun's implementation for Solaris and Linux uses the encoding + * iso-10646-ucs-2. + * + * @return a DataFlavor representing plain text + * with Unicode encoding + * @since 1.3 + */ + public static final DataFlavor getTextPlainUnicodeFlavor() { + return new DataFlavor( + "text/plain;charset=" + DataFlavorUtil.getDesktopService().getDefaultUnicodeEncoding() + +";class=java.io.InputStream", "Plain Text"); + } + + /** + * Selects the best text DataFlavor from an array of + * DataFlavors. Only DataFlavor.stringFlavor, and + * equivalent flavors, and flavors that have a primary MIME type of "text", + * are considered for selection. + *

+ * Flavors are first sorted by their MIME types in the following order: + *

+ *

For example, "text/sgml" will be selected over + * "text/html", and DataFlavor.stringFlavor will be chosen + * over DataFlavor.plainTextFlavor. + *

+ * If two or more flavors share the best MIME type in the array, then that + * MIME type will be checked to see if it supports the charset parameter. + *

+ * The following MIME types support, or are treated as though they support, + * the charset parameter: + *

+ * The following MIME types do not support, or are treated as though they + * do not support, the charset parameter: + * + * For "text/<other>" MIME types, the first time the JRE needs to + * determine whether the MIME type supports the charset parameter, it will + * check whether the parameter is explicitly listed in an arbitrarily + * chosen DataFlavor which uses that MIME type. If so, the JRE + * will assume from that point on that the MIME type supports the charset + * parameter and will not check again. If the parameter is not explicitly + * listed, the JRE will assume from that point on that the MIME type does + * not support the charset parameter and will not check again. Because + * this check is performed on an arbitrarily chosen + * DataFlavor, developers must ensure that all + * DataFlavors with a "text/<other>" MIME type specify + * the charset parameter if it is supported by that MIME type. Developers + * should never rely on the JRE to substitute the platform's default + * charset for a "text/<other>" DataFlavor. Failure to adhere to this + * restriction will lead to undefined behavior. + *

+ * If the best MIME type in the array does not support the charset + * parameter, the flavors which share that MIME type will then be sorted by + * their representation classes in the following order: + * java.io.InputStream, java.nio.ByteBuffer, + * [B, <all others>. + *

+ * If two or more flavors share the best representation class, or if no + * flavor has one of the three specified representations, then one of those + * flavors will be chosen non-deterministically. + *

+ * If the best MIME type in the array does support the charset parameter, + * the flavors which share that MIME type will then be sorted by their + * representation classes in the following order: + * java.io.Reader, java.lang.String, + * java.nio.CharBuffer, [C, <all others>. + *

+ * If two or more flavors share the best representation class, and that + * representation is one of the four explicitly listed, then one of those + * flavors will be chosen non-deterministically. If, however, no flavor has + * one of the four specified representations, the flavors will then be + * sorted by their charsets. Unicode charsets, such as "UTF-16", "UTF-8", + * "UTF-16BE", "UTF-16LE", and their aliases, are considered best. After + * them, the platform default charset and its aliases are selected. + * "US-ASCII" and its aliases are worst. All other charsets are chosen in + * alphabetical order, but only charsets supported by this implementation + * of the Java platform will be considered. + *

+ * If two or more flavors share the best charset, the flavors will then + * again be sorted by their representation classes in the following order: + * java.io.InputStream, java.nio.ByteBuffer, + * [B, <all others>. + *

+ * If two or more flavors share the best representation class, or if no + * flavor has one of the three specified representations, then one of those + * flavors will be chosen non-deterministically. + * + * @param availableFlavors an array of available DataFlavors + * @return the best (highest fidelity) flavor according to the rules + * specified above, or null, + * if availableFlavors is null, + * has zero length, or contains no text flavors + * @since 1.3 + */ + public static final DataFlavor selectBestTextFlavor( + DataFlavor[] availableFlavors) { + if (availableFlavors == null || availableFlavors.length == 0) { + return null; + } + + DataFlavor bestFlavor = Collections.max(Arrays.asList(availableFlavors), + DataFlavorUtil.getTextFlavorComparator()); + + if (!bestFlavor.isFlavorTextType()) { + return null; + } + + return bestFlavor; + } + + /** + * Gets a Reader for a text flavor, decoded, if necessary, for the expected + * charset (encoding). The supported representation classes are + * java.io.Reader, java.lang.String, + * java.nio.CharBuffer, [C, + * java.io.InputStream, java.nio.ByteBuffer, + * and [B. + *

+ * Because text flavors which do not support the charset parameter are + * encoded in a non-standard format, this method should not be called for + * such flavors. However, in order to maintain backward-compatibility, + * if this method is called for such a flavor, this method will treat the + * flavor as though it supports the charset parameter and attempt to + * decode it accordingly. See selectBestTextFlavor for a list + * of text flavors which do not support the charset parameter. + * + * @param transferable the Transferable whose data will be + * requested in this flavor + * + * @return a Reader to read the Transferable's + * data + * + * @exception IllegalArgumentException if the representation class + * is not one of the seven listed above + * @exception IllegalArgumentException if the Transferable + * has null data + * @exception NullPointerException if the Transferable is + * null + * @exception UnsupportedEncodingException if this flavor's representation + * is java.io.InputStream, + * java.nio.ByteBuffer, or [B and + * this flavor's encoding is not supported by this + * implementation of the Java platform + * @exception UnsupportedFlavorException if the Transferable + * does not support this flavor + * @exception IOException if the data cannot be read because of an + * I/O error + * @see #selectBestTextFlavor + * @since 1.3 + */ + public Reader getReaderForText(Transferable transferable) + throws UnsupportedFlavorException, IOException + { + Object transferObject = transferable.getTransferData(this); + if (transferObject == null) { + throw new IllegalArgumentException + ("getTransferData() returned null"); + } + + if (transferObject instanceof Reader) { + return (Reader)transferObject; + } else if (transferObject instanceof String) { + return new StringReader((String)transferObject); + } else if (transferObject instanceof CharBuffer) { + CharBuffer buffer = (CharBuffer)transferObject; + int size = buffer.remaining(); + char[] chars = new char[size]; + buffer.get(chars, 0, size); + return new CharArrayReader(chars); + } else if (transferObject instanceof char[]) { + return new CharArrayReader((char[])transferObject); + } + + InputStream stream = null; + + if (transferObject instanceof InputStream) { + stream = (InputStream)transferObject; + } else if (transferObject instanceof ByteBuffer) { + ByteBuffer buffer = (ByteBuffer)transferObject; + int size = buffer.remaining(); + byte[] bytes = new byte[size]; + buffer.get(bytes, 0, size); + stream = new ByteArrayInputStream(bytes); + } else if (transferObject instanceof byte[]) { + stream = new ByteArrayInputStream((byte[])transferObject); + } + + if (stream == null) { + throw new IllegalArgumentException("transfer data is not Reader, String, CharBuffer, char array, InputStream, ByteBuffer, or byte array"); + } + + String encoding = getParameter("charset"); + return (encoding == null) + ? new InputStreamReader(stream) + : new InputStreamReader(stream, encoding); + } + + /** + * Returns the MIME type string for this DataFlavor. + * @return the MIME type string for this flavor + */ + public String getMimeType() { + return (mimeType != null) ? mimeType.toString() : null; + } + + /** + * Returns the Class which objects supporting this + * DataFlavor will return when this DataFlavor + * is requested. + * @return the Class which objects supporting this + * DataFlavor will return when this DataFlavor + * is requested + */ + public Class getRepresentationClass() { + return representationClass; + } + + /** + * Returns the human presentable name for the data format that this + * DataFlavor represents. This name would be localized + * for different countries. + * @return the human presentable name for the data format that this + * DataFlavor represents + */ + public String getHumanPresentableName() { + return humanPresentableName; + } + + /** + * Returns the primary MIME type for this DataFlavor. + * @return the primary MIME type of this DataFlavor + */ + public String getPrimaryType() { + return (mimeType != null) ? mimeType.getPrimaryType() : null; + } + + /** + * Returns the sub MIME type of this DataFlavor. + * @return the Sub MIME type of this DataFlavor + */ + public String getSubType() { + return (mimeType != null) ? mimeType.getSubType() : null; + } + + /** + * Returns the human presentable name for this DataFlavor + * if paramName equals "humanPresentableName". Otherwise + * returns the MIME type value associated with paramName. + * + * @param paramName the parameter name requested + * @return the value of the name parameter, or null + * if there is no associated value + */ + public String getParameter(String paramName) { + if (paramName.equals("humanPresentableName")) { + return humanPresentableName; + } else { + return (mimeType != null) + ? mimeType.getParameter(paramName) : null; + } + } + + /** + * Sets the human presentable name for the data format that this + * DataFlavor represents. This name would be localized + * for different countries. + * @param humanPresentableName the new human presentable name + */ + public void setHumanPresentableName(String humanPresentableName) { + this.humanPresentableName = humanPresentableName; + } + + /** + * {@inheritDoc} + *

+ * The equals comparison for the {@code DataFlavor} class is implemented + * as follows: Two DataFlavors are considered equal if and + * only if their MIME primary type and subtype and representation class are + * equal. Additionally, if the primary type is "text", the subtype denotes + * a text flavor which supports the charset parameter, and the + * representation class is not java.io.Reader, + * java.lang.String, java.nio.CharBuffer, or + * [C, the charset parameter must also be equal. + * If a charset is not explicitly specified for one or both + * DataFlavors, the platform default encoding is assumed. See + * selectBestTextFlavor for a list of text flavors which + * support the charset parameter. + * + * @param o the Object to compare with this + * @return true if that is equivalent to this + * DataFlavor; false otherwise + * @see #selectBestTextFlavor + */ + public boolean equals(Object o) { + return ((o instanceof DataFlavor) && equals((DataFlavor)o)); + } + + /** + * This method has the same behavior as {@link #equals(Object)}. + * The only difference being that it takes a {@code DataFlavor} instance + * as a parameter. + * + * @param that the DataFlavor to compare with + * this + * @return true if that is equivalent to this + * DataFlavor; false otherwise + * @see #selectBestTextFlavor + */ + public boolean equals(DataFlavor that) { + if (that == null) { + return false; + } + if (this == that) { + return true; + } + + if (!Objects.equals(this.getRepresentationClass(), that.getRepresentationClass())) { + return false; + } + + if (mimeType == null) { + if (that.mimeType != null) { + return false; + } + } else { + if (!mimeType.match(that.mimeType)) { + return false; + } + + if ("text".equals(getPrimaryType())) { + if (DataFlavorUtil.doesSubtypeSupportCharset(this) + && representationClass != null + && !isStandardTextRepresentationClass()) { + String thisCharset = + DataFlavorUtil.canonicalName(this.getParameter("charset")); + String thatCharset = + DataFlavorUtil.canonicalName(that.getParameter("charset")); + if (!Objects.equals(thisCharset, thatCharset)) { + return false; + } + } + + if ("html".equals(getSubType())) { + String thisDocument = this.getParameter("document"); + String thatDocument = that.getParameter("document"); + if (!Objects.equals(thisDocument, thatDocument)) { + return false; + } + } + } + } + + return true; + } + + /** + * Compares only the mimeType against the passed in + * String and representationClass is + * not considered in the comparison. + * + * If representationClass needs to be compared, then + * equals(new DataFlavor(s)) may be used. + * @deprecated As inconsistent with hashCode() contract, + * use isMimeTypeEqual(String) instead. + * @param s the {@code mimeType} to compare. + * @return true if the String (MimeType) is equal; false otherwise or if + * {@code s} is {@code null} + */ + @Deprecated + public boolean equals(String s) { + if (s == null || mimeType == null) + return false; + return isMimeTypeEqual(s); + } + + /** + * Returns hash code for this DataFlavor. + * For two equal DataFlavors, hash codes are equal. + * For the String + * that matches DataFlavor.equals(String), it is not + * guaranteed that DataFlavor's hash code is equal + * to the hash code of the String. + * + * @return a hash code for this DataFlavor + */ + public int hashCode() { + int total = 0; + + if (representationClass != null) { + total += representationClass.hashCode(); + } + + if (mimeType != null) { + String primaryType = mimeType.getPrimaryType(); + if (primaryType != null) { + total += primaryType.hashCode(); + } + + // Do not add subType.hashCode() to the total. equals uses + // MimeType.match which reports a match if one or both of the + // subTypes is '*', regardless of the other subType. + + if ("text".equals(primaryType)) { + if (DataFlavorUtil.doesSubtypeSupportCharset(this) + && representationClass != null + && !isStandardTextRepresentationClass()) { + String charset = DataFlavorUtil.canonicalName(getParameter("charset")); + if (charset != null) { + total += charset.hashCode(); + } + } + + if ("html".equals(getSubType())) { + String document = this.getParameter("document"); + if (document != null) { + total += document.hashCode(); + } + } + } + } + + return total; + } + + /** + * Identical to {@link #equals(DataFlavor)}. + * + * @param that the DataFlavor to compare with + * this + * @return true if that is equivalent to this + * DataFlavor; false otherwise + * @see #selectBestTextFlavor + * @since 1.3 + */ + public boolean match(DataFlavor that) { + return equals(that); + } + + /** + * Returns whether the string representation of the MIME type passed in + * is equivalent to the MIME type of this DataFlavor. + * Parameters are not included in the comparison. + * + * @param mimeType the string representation of the MIME type + * @return true if the string representation of the MIME type passed in is + * equivalent to the MIME type of this DataFlavor; + * false otherwise + * @throws NullPointerException if mimeType is null + */ + public boolean isMimeTypeEqual(String mimeType) { + // JCK Test DataFlavor0117: if 'mimeType' is null, throw NPE + if (mimeType == null) { + throw new NullPointerException("mimeType"); + } + if (this.mimeType == null) { + return false; + } + try { + return this.mimeType.match(new MimeType(mimeType)); + } catch (MimeTypeParseException mtpe) { + return false; + } + } + + /** + * Compares the mimeType of two DataFlavor + * objects. No parameters are considered. + * + * @param dataFlavor the DataFlavor to be compared + * @return true if the MimeTypes are equal, + * otherwise false + */ + + public final boolean isMimeTypeEqual(DataFlavor dataFlavor) { + return isMimeTypeEqual(dataFlavor.mimeType); + } + + /** + * Compares the mimeType of two DataFlavor + * objects. No parameters are considered. + * + * @return true if the MimeTypes are equal, + * otherwise false + */ + + private boolean isMimeTypeEqual(MimeType mtype) { + if (this.mimeType == null) { + return (mtype == null); + } + return mimeType.match(mtype); + } + + /** + * Checks if the representation class is one of the standard text + * representation classes. + * + * @return true if the representation class is one of the standard text + * representation classes, otherwise false + */ + private boolean isStandardTextRepresentationClass() { + return isRepresentationClassReader() + || String.class.equals(representationClass) + || isRepresentationClassCharBuffer() + || char[].class.equals(representationClass); + } + + /** + * Does the DataFlavor represent a serialized object? + * @return whether or not a serialized object is represented + */ + public boolean isMimeTypeSerializedObject() { + return isMimeTypeEqual(javaSerializedObjectMimeType); + } + + /** + * Returns the default representation class. + * @return the default representation class + */ + public final Class getDefaultRepresentationClass() { + return ioInputStreamClass; + } + + /** + * Returns the name of the default representation class. + * @return the name of the default representation class + */ + public final String getDefaultRepresentationClassAsString() { + return getDefaultRepresentationClass().getName(); + } + + /** + * Does the DataFlavor represent a + * java.io.InputStream? + * @return whether or not this {@code DataFlavor} represent a + * {@code java.io.InputStream} + */ + public boolean isRepresentationClassInputStream() { + return ioInputStreamClass.isAssignableFrom(representationClass); + } + + /** + * Returns whether the representation class for this + * DataFlavor is java.io.Reader or a subclass + * thereof. + * @return whether or not the representation class for this + * {@code DataFlavor} is {@code java.io.Reader} or a subclass + * thereof + * + * @since 1.4 + */ + public boolean isRepresentationClassReader() { + return java.io.Reader.class.isAssignableFrom(representationClass); + } + + /** + * Returns whether the representation class for this + * DataFlavor is java.nio.CharBuffer or a + * subclass thereof. + * @return whether or not the representation class for this + * {@code DataFlavor} is {@code java.nio.CharBuffer} or a subclass + * thereof + * + * @since 1.4 + */ + public boolean isRepresentationClassCharBuffer() { + return java.nio.CharBuffer.class.isAssignableFrom(representationClass); + } + + /** + * Returns whether the representation class for this + * DataFlavor is java.nio.ByteBuffer or a + * subclass thereof. + * @return whether or not the representation class for this + * {@code DataFlavor} is {@code java.nio.ByteBuffer} or a subclass + * thereof + * + * @since 1.4 + */ + public boolean isRepresentationClassByteBuffer() { + return java.nio.ByteBuffer.class.isAssignableFrom(representationClass); + } + + /** + * Returns true if the representation class can be serialized. + * @return true if the representation class can be serialized + */ + + public boolean isRepresentationClassSerializable() { + return java.io.Serializable.class.isAssignableFrom(representationClass); + } + + /** + * Returns true if the representation class is Remote. + * @return true if the representation class is Remote + */ + public boolean isRepresentationClassRemote() { + return DataFlavorUtil.RMI.isRemote(representationClass); + } + + /** + * Returns true if the DataFlavor specified represents + * a serialized object. + * @return true if the DataFlavor specified represents + * a Serialized Object + */ + + public boolean isFlavorSerializedObjectType() { + return isRepresentationClassSerializable() && isMimeTypeEqual(javaSerializedObjectMimeType); + } + + /** + * Returns true if the DataFlavor specified represents + * a remote object. + * @return true if the DataFlavor specified represents + * a Remote Object + */ + + public boolean isFlavorRemoteObjectType() { + return isRepresentationClassRemote() + && isRepresentationClassSerializable() + && isMimeTypeEqual(javaRemoteObjectMimeType); + } + + + /** + * Returns true if the DataFlavor specified represents + * a list of file objects. + * @return true if the DataFlavor specified represents + * a List of File objects + */ + + public boolean isFlavorJavaFileListType() { + if (mimeType == null || representationClass == null) + return false; + return java.util.List.class.isAssignableFrom(representationClass) && + mimeType.match(javaFileListFlavor.mimeType); + + } + + /** + * Returns whether this DataFlavor is a valid text flavor for + * this implementation of the Java platform. Only flavors equivalent to + * DataFlavor.stringFlavor and DataFlavors with + * a primary MIME type of "text" can be valid text flavors. + *

+ * If this flavor supports the charset parameter, it must be equivalent to + * DataFlavor.stringFlavor, or its representation must be + * java.io.Reader, java.lang.String, + * java.nio.CharBuffer, [C, + * java.io.InputStream, java.nio.ByteBuffer, or + * [B. If the representation is + * java.io.InputStream, java.nio.ByteBuffer, or + * [B, then this flavor's charset parameter must + * be supported by this implementation of the Java platform. If a charset + * is not specified, then the platform default charset, which is always + * supported, is assumed. + *

+ * If this flavor does not support the charset parameter, its + * representation must be java.io.InputStream, + * java.nio.ByteBuffer, or [B. + *

+ * See selectBestTextFlavor for a list of text flavors which + * support the charset parameter. + * + * @return true if this DataFlavor is a valid + * text flavor as described above; false otherwise + * @see #selectBestTextFlavor + * @since 1.4 + */ + public boolean isFlavorTextType() { + return (DataFlavorUtil.isFlavorCharsetTextType(this) || + DataFlavorUtil.isFlavorNoncharsetTextType(this)); + } + + /** + * Serializes this DataFlavor. + */ + + public synchronized void writeExternal(ObjectOutput os) throws IOException { + if (mimeType != null) { + mimeType.setParameter("humanPresentableName", humanPresentableName); + os.writeObject(mimeType); + mimeType.removeParameter("humanPresentableName"); + } else { + os.writeObject(null); + } + + os.writeObject(representationClass); + } + + /** + * Restores this DataFlavor from a Serialized state. + */ + + public synchronized void readExternal(ObjectInput is) throws IOException , ClassNotFoundException { + String rcn = null; + mimeType = (MimeType)is.readObject(); + + if (mimeType != null) { + humanPresentableName = + mimeType.getParameter("humanPresentableName"); + mimeType.removeParameter("humanPresentableName"); + rcn = mimeType.getParameter("class"); + if (rcn == null) { + throw new IOException("no class parameter specified in: " + + mimeType); + } + } + + try { + representationClass = (Class)is.readObject(); + } catch (OptionalDataException ode) { + if (!ode.eof || ode.length != 0) { + throw ode; + } + // Ensure backward compatibility. + // Old versions didn't write the representation class to the stream. + if (rcn != null) { + representationClass = + DataFlavor.tryToLoadClass(rcn, getClass().getClassLoader()); + } + } + } + + /** + * Returns a clone of this DataFlavor. + * @return a clone of this DataFlavor + */ + + public Object clone() throws CloneNotSupportedException { + Object newObj = super.clone(); + if (mimeType != null) { + ((DataFlavor)newObj).mimeType = (MimeType)mimeType.clone(); + } + return newObj; + } // clone() + + /** + * Called on DataFlavor for every MIME Type parameter + * to allow DataFlavor subclasses to handle special + * parameters like the text/plain charset + * parameters, whose values are case insensitive. (MIME type parameter + * values are supposed to be case sensitive. + *

+ * This method is called for each parameter name/value pair and should + * return the normalized representation of the parameterValue. + * + * This method is never invoked by this implementation from 1.1 onwards. + * + * @param parameterName the parameter name + * @param parameterValue the parameter value + * @return the parameter value + * @deprecated + */ + @Deprecated + protected String normalizeMimeTypeParameter(String parameterName, String parameterValue) { + return parameterValue; + } + + /** + * Called for each MIME type string to give DataFlavor subtypes + * the opportunity to change how the normalization of MIME types is + * accomplished. One possible use would be to add default + * parameter/value pairs in cases where none are present in the MIME + * type string passed in. + * + * This method is never invoked by this implementation from 1.1 onwards. + * + * @param mimeType the mime type + * @return the mime type + * @deprecated + */ + @Deprecated + protected String normalizeMimeType(String mimeType) { + return mimeType; + } + + /* + * fields + */ + + /* placeholder for caching any platform-specific data for flavor */ + + transient int atom; + + /* Mime Type of DataFlavor */ + + MimeType mimeType; + + private String humanPresentableName; + + /** Java class of objects this DataFlavor represents **/ + + private Class representationClass; + +} // class DataFlavor