8056298: Separate java.awt.datatransfer from the desktop module
Reviewed-by: erikj, alanb, mchung, alexsch
--- a/jdk/make/src/classes/build/tools/module/boot.modules Fri Jan 16 19:11:10 2015 +0400
+++ b/jdk/make/src/classes/build/tools/module/boot.modules Fri Jan 16 18:46:16 2015 +0300
@@ -1,4 +1,5 @@
java.base
+java.datatransfer
java.desktop
java.activation
java.annotations.common
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/macosx/classes/sun/datatransfer/resources/flavormap.properties Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,76 @@
+#
+# This properties file is used to initialize the default
+# java.awt.datatransfer.SystemFlavorMap. It contains the Mac OS X platform-specific,
+# default mappings between common Mac OS X selection atoms and platform-independent
+# MIME type strings, which will be converted into
+# java.awt.datatransfer.DataFlavors.
+#
+# The standard format is:
+#
+# <native>=<MIME type>,<MIME type>, ...
+#
+# <native> should be a string identifier that the native platform will
+# recognize as a valid data format. <MIME type> should specify both a MIME
+# primary type and a MIME subtype separated by a '/'. The MIME type may include
+# parameters, where each parameter is a key/value pair separated by '=', and
+# where each parameter to the MIME type is separated by a ';'.
+#
+# Because SystemFlavorMap implements FlavorTable, developers are free to
+# duplicate DataFlavor values and set multiple values for a single native by
+# separating them with ",". If a mapping contains a duplicate key or value,
+# earlier mappings which included this key or value will be preferred.
+#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", and which support the charset parameter, should specify the exact
+# format in which the native platform expects the data. The "charset"
+# parameter specifies the char to byte encoding, the "eoln" parameter
+# specifies the end-of-line marker, and the "terminators" parameter specifies
+# the number of terminating NUL bytes. Note that "eoln" and "terminators"
+# are not standardized MIME type parameters. They are specific to this file
+# format ONLY. They will not appear in any of the DataFlavors returned by the
+# SystemFlavorMap at the Java level.
+#
+# If the "charset" parameter is omitted, or has zero length, the platform
+# default encoding is assumed. If the "eoln" parameter is omitted, or has
+# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
+# or has a value less than zero, zero is assumed.
+#
+# Upon initialization, the data transfer subsystem will record the specified
+# details of the native text format, but the default SystemFlavorMap will
+# present a large set of synthesized DataFlavors which map, in both
+# directions, to the native. After receiving data from the application in one
+# of the synthetic DataFlavors, the data transfer subsystem will transform
+# the data stream into the format specified in this file before passing the
+# transformed stream to the native system.
+#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", but which do not support the charset parameter, will be treated as
+# opaque, 8-bit data. They will not undergo any transformation process, and
+# any "charset", "eoln", or "terminators" parameters specified in this file
+# will be ignored.
+#
+# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
+# text flavors which support the charset parameter.
+
+UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
+
+# The COMPOUND_TEXT support for inter-client text transfer is disabled by
+# default. The reason is that many native applications prefer this format over
+# other native text formats, but are unable to decode the textual data in this
+# format properly. This results in java-to-native text transfer failures.
+# To enable the COMPOUND_TEXT support for this JRE installation uncomment
+# the line below.
+
+# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0
+
+TEXT=text/plain;eoln="\n";terminators=0
+STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
+FILE_NAME=application/x-java-file-list;class=java.util.List
+text/uri-list=application/x-java-file-list;class=java.util.List
+PNG=image/x-java-image;class=java.awt.Image
+JFIF=image/x-java-image;class=java.awt.Image
+TIFF=image/x-java-image;class=java.awt.Image
+RICH_TEXT=text/rtf
+HTML=text/html;charset=utf-8;eoln="\r\n";terminators=1
+URL=application/x-java-url;class=java.net.URL,\
+ text/uri-list;eoln="\r\n";terminators=1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/Clipboard.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,352 @@
+/*
+ * 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 java.util.Objects;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Arrays;
+
+import java.io.IOException;
+
+/**
+ * A class that implements a mechanism to transfer data using
+ * cut/copy/paste operations.
+ * <p>
+ * {@link FlavorListener}s may be registered on an instance of the
+ * Clipboard class to be notified about changes to the set of
+ * {@link DataFlavor}s available on this clipboard (see
+ * {@link #addFlavorListener}).
+ *
+ * @see java.awt.Toolkit#getSystemClipboard
+ * @see java.awt.Toolkit#getSystemSelection
+ *
+ * @author Amy Fowler
+ * @author Alexander Gerasimov
+ */
+public class Clipboard {
+
+ String name;
+
+ /**
+ * The owner of the clipboard.
+ */
+ protected ClipboardOwner owner;
+ /**
+ * Contents of the clipboard.
+ */
+ protected Transferable contents;
+
+ /**
+ * An aggregate of flavor listeners registered on this local clipboard.
+ *
+ * @since 1.5
+ */
+ private Set<FlavorListener> flavorListeners;
+
+ /**
+ * A set of <code>DataFlavor</code>s that is available on
+ * this local clipboard. It is used for tracking changes
+ * of <code>DataFlavor</code>s available on this clipboard.
+ *
+ * @since 1.5
+ */
+ private Set<DataFlavor> currentDataFlavors;
+
+ /**
+ * Creates a clipboard object.
+ * @param name for the clipboard
+ * @see java.awt.Toolkit#getSystemClipboard
+ */
+ public Clipboard(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns the name of this clipboard object.
+ * @return the name of this clipboard object
+ *
+ * @see java.awt.Toolkit#getSystemClipboard
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the current contents of the clipboard to the specified
+ * transferable object and registers the specified clipboard owner
+ * as the owner of the new contents.
+ * <p>
+ * If there is an existing owner different from the argument
+ * <code>owner</code>, that owner is notified that it no longer
+ * holds ownership of the clipboard contents via an invocation
+ * of <code>ClipboardOwner.lostOwnership()</code> on that owner.
+ * An implementation of <code>setContents()</code> is free not
+ * to invoke <code>lostOwnership()</code> directly from this method.
+ * For example, <code>lostOwnership()</code> may be invoked later on
+ * a different thread. The same applies to <code>FlavorListener</code>s
+ * registered on this clipboard.
+ * <p>
+ * The method throws <code>IllegalStateException</code> if the clipboard
+ * is currently unavailable. For example, on some platforms, the system
+ * clipboard is unavailable while it is accessed by another application.
+ *
+ * @param contents the transferable object representing the
+ * clipboard content
+ * @param owner the object which owns the clipboard content
+ * @throws IllegalStateException if the clipboard is currently unavailable
+ * @see java.awt.Toolkit#getSystemClipboard
+ */
+ public synchronized void setContents(Transferable contents, ClipboardOwner owner) {
+ final ClipboardOwner oldOwner = this.owner;
+ final Transferable oldContents = this.contents;
+
+ this.owner = owner;
+ this.contents = contents;
+
+ if (oldOwner != null && oldOwner != owner) {
+ DataFlavorUtil.getDesktopService().invokeOnEventThread(() ->
+ oldOwner.lostOwnership(Clipboard.this, oldContents));
+ }
+ fireFlavorsChanged();
+ }
+
+ /**
+ * Returns a transferable object representing the current contents
+ * of the clipboard. If the clipboard currently has no contents,
+ * it returns <code>null</code>. The parameter Object requestor is
+ * not currently used. The method throws
+ * <code>IllegalStateException</code> if the clipboard is currently
+ * unavailable. For example, on some platforms, the system clipboard is
+ * unavailable while it is accessed by another application.
+ *
+ * @param requestor the object requesting the clip data (not used)
+ * @return the current transferable object on the clipboard
+ * @throws IllegalStateException if the clipboard is currently unavailable
+ * @see java.awt.Toolkit#getSystemClipboard
+ */
+ public synchronized Transferable getContents(Object requestor) {
+ return contents;
+ }
+
+
+ /**
+ * Returns an array of <code>DataFlavor</code>s in which the current
+ * contents of this clipboard can be provided. If there are no
+ * <code>DataFlavor</code>s available, this method returns a zero-length
+ * array.
+ *
+ * @return an array of <code>DataFlavor</code>s in which the current
+ * contents of this clipboard can be provided
+ *
+ * @throws IllegalStateException if this clipboard is currently unavailable
+ *
+ * @since 1.5
+ */
+ public DataFlavor[] getAvailableDataFlavors() {
+ Transferable cntnts = getContents(null);
+ if (cntnts == null) {
+ return new DataFlavor[0];
+ }
+ return cntnts.getTransferDataFlavors();
+ }
+
+ /**
+ * Returns whether or not the current contents of this clipboard can be
+ * provided in the specified <code>DataFlavor</code>.
+ *
+ * @param flavor the requested <code>DataFlavor</code> for the contents
+ *
+ * @return <code>true</code> if the current contents of this clipboard
+ * can be provided in the specified <code>DataFlavor</code>;
+ * <code>false</code> otherwise
+ *
+ * @throws NullPointerException if <code>flavor</code> is <code>null</code>
+ * @throws IllegalStateException if this clipboard is currently unavailable
+ *
+ * @since 1.5
+ */
+ public boolean isDataFlavorAvailable(DataFlavor flavor) {
+ if (flavor == null) {
+ throw new NullPointerException("flavor");
+ }
+
+ Transferable cntnts = getContents(null);
+ if (cntnts == null) {
+ return false;
+ }
+ return cntnts.isDataFlavorSupported(flavor);
+ }
+
+ /**
+ * Returns an object representing the current contents of this clipboard
+ * in the specified <code>DataFlavor</code>.
+ * The class of the object returned is defined by the representation
+ * class of <code>flavor</code>.
+ *
+ * @param flavor the requested <code>DataFlavor</code> for the contents
+ *
+ * @return an object representing the current contents of this clipboard
+ * in the specified <code>DataFlavor</code>
+ *
+ * @throws NullPointerException if <code>flavor</code> is <code>null</code>
+ * @throws IllegalStateException if this clipboard is currently unavailable
+ * @throws UnsupportedFlavorException if the requested <code>DataFlavor</code>
+ * is not available
+ * @throws IOException if the data in the requested <code>DataFlavor</code>
+ * can not be retrieved
+ *
+ * @see DataFlavor#getRepresentationClass
+ *
+ * @since 1.5
+ */
+ public Object getData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException {
+ if (flavor == null) {
+ throw new NullPointerException("flavor");
+ }
+
+ Transferable cntnts = getContents(null);
+ if (cntnts == null) {
+ throw new UnsupportedFlavorException(flavor);
+ }
+ return cntnts.getTransferData(flavor);
+ }
+
+
+ /**
+ * Registers the specified <code>FlavorListener</code> to receive
+ * <code>FlavorEvent</code>s from this clipboard.
+ * If <code>listener</code> is <code>null</code>, no exception
+ * is thrown and no action is performed.
+ *
+ * @param listener the listener to be added
+ *
+ * @see #removeFlavorListener
+ * @see #getFlavorListeners
+ * @see FlavorListener
+ * @see FlavorEvent
+ * @since 1.5
+ */
+ public synchronized void addFlavorListener(FlavorListener listener) {
+ if (listener == null) {
+ return;
+ }
+
+ if (flavorListeners == null) {
+ flavorListeners = new HashSet<>();
+ currentDataFlavors = getAvailableDataFlavorSet();
+ }
+
+ flavorListeners.add(listener);
+ }
+
+ /**
+ * Removes the specified <code>FlavorListener</code> so that it no longer
+ * receives <code>FlavorEvent</code>s from this <code>Clipboard</code>.
+ * This method performs no function, nor does it throw an exception, if
+ * the listener specified by the argument was not previously added to this
+ * <code>Clipboard</code>.
+ * If <code>listener</code> is <code>null</code>, no exception
+ * is thrown and no action is performed.
+ *
+ * @param listener the listener to be removed
+ *
+ * @see #addFlavorListener
+ * @see #getFlavorListeners
+ * @see FlavorListener
+ * @see FlavorEvent
+ * @since 1.5
+ */
+ public synchronized void removeFlavorListener(FlavorListener listener) {
+ if (listener == null || flavorListeners == null) {
+ return;
+ }
+ flavorListeners.remove(listener);
+ }
+
+ /**
+ * Returns an array of all the <code>FlavorListener</code>s currently
+ * registered on this <code>Clipboard</code>.
+ *
+ * @return all of this clipboard's <code>FlavorListener</code>s or an empty
+ * array if no listeners are currently registered
+ * @see #addFlavorListener
+ * @see #removeFlavorListener
+ * @see FlavorListener
+ * @see FlavorEvent
+ * @since 1.5
+ */
+ public synchronized FlavorListener[] getFlavorListeners() {
+ return flavorListeners == null ? new FlavorListener[0] :
+ flavorListeners.toArray(new FlavorListener[flavorListeners.size()]);
+ }
+
+ /**
+ * Checks change of the <code>DataFlavor</code>s and, if necessary,
+ * notifies all listeners that have registered interest for notification
+ * on <code>FlavorEvent</code>s.
+ *
+ * @since 1.5
+ */
+ private void fireFlavorsChanged() {
+ if (flavorListeners == null) {
+ return;
+ }
+
+ Set<DataFlavor> prevDataFlavors = currentDataFlavors;
+ currentDataFlavors = getAvailableDataFlavorSet();
+ if (Objects.equals(prevDataFlavors, currentDataFlavors)) {
+ return;
+ }
+ flavorListeners.forEach(listener ->
+ DataFlavorUtil.getDesktopService().invokeOnEventThread(() ->
+ listener.flavorsChanged(new FlavorEvent(Clipboard.this))));
+ }
+
+ /**
+ * Returns a set of <code>DataFlavor</code>s currently available
+ * on this clipboard.
+ *
+ * @return a set of <code>DataFlavor</code>s currently available
+ * on this clipboard
+ *
+ * @since 1.5
+ */
+ private Set<DataFlavor> getAvailableDataFlavorSet() {
+ Set<DataFlavor> set = new HashSet<>();
+ Transferable contents = getContents(null);
+ if (contents != null) {
+ DataFlavor[] flavors = contents.getTransferDataFlavors();
+ if (flavors != null) {
+ set.addAll(Arrays.asList(flavors));
+ }
+ }
+ return set;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/ClipboardOwner.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1996, 2002, 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;
+
+/**
+ * Defines the interface for classes that will provide data to
+ * a clipboard. An instance of this interface becomes the owner
+ * of the contents of a clipboard (clipboard owner) if it is
+ * passed as an argument to
+ * {@link java.awt.datatransfer.Clipboard#setContents} method of
+ * the clipboard and this method returns successfully.
+ * The instance remains the clipboard owner until another application
+ * or another object within this application asserts ownership
+ * of this clipboard.
+ *
+ * @see java.awt.datatransfer.Clipboard
+ *
+ * @author Amy Fowler
+ */
+
+public interface ClipboardOwner {
+
+ /**
+ * Notifies this object that it is no longer the clipboard owner.
+ * This method will be called when another application or another
+ * object within this application asserts ownership of the clipboard.
+ *
+ * @param clipboard the clipboard that is no longer owned
+ * @param contents the contents which this owner had placed on the clipboard
+ */
+ public void lostOwnership(Clipboard clipboard, Transferable contents);
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/DataFlavor.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,1431 @@
+/*
+ * Copyright (c) 1996, 2015, 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;
+
+/**
+ * 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.
+ * <p>
+ * An instance of {@code DataFlavor} encapsulates a content type as
+ * defined in <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
+ * and <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a>.
+ * A content type is typically referred to as a MIME type.
+ * <p>
+ * A content type consists of a media type (referred
+ * to as the primary type), a subtype, and optional parameters. See
+ * <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
+ * for details on the syntax of a MIME type.
+ * <p>
+ * The JRE data transfer implementation interprets the parameter "class"
+ * of a MIME type as <B>a representation class</b>.
+ * 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.
+ * <br>
+ * 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.
+ * <p>
+ * Also, {@code DataFlavor} instances with the "text" primary
+ * MIME type may have a "charset" parameter. Refer to
+ * <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a> and
+ * {@link #selectBestTextFlavor} for details on "text" MIME types
+ * and the "charset" parameter.
+ * <p>
+ * 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:
+ * <pre>
+ * 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);
+ * </pre>
+ * As mentioned, {@code flavor1} and {@code flavor2} are considered identical.
+ * As such, asking a {@code Transferable} for either {@code DataFlavor} returns
+ * the same results.
+ * <p>
+ * For more information on using data transfer with Swing see
+ * the <a href="http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html">
+ * How to Use Drag and Drop and Data Transfer</a>,
+ * section in <em>Java Tutorial</em>.
+ *
+ * @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<InputStream> 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(new RuntimePermission("getClassLoader"));
+ }
+ 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 <code>DataFlavor</code> representing a Java Unicode String class,
+ * where:
+ * <pre>
+ * representationClass = java.lang.String
+ * mimeType = "application/x-java-serialized-object"
+ * </pre>
+ */
+ public static final DataFlavor stringFlavor = createConstant(java.lang.String.class, "Unicode String");
+
+ /**
+ * The <code>DataFlavor</code> representing a Java Image class,
+ * where:
+ * <pre>
+ * representationClass = java.awt.Image
+ * mimeType = "image/x-java-image"
+ * </pre>
+ */
+ public static final DataFlavor imageFlavor = createConstant("image/x-java-image; class=java.awt.Image", "Image");
+
+ /**
+ * The <code>DataFlavor</code> representing plain text with Unicode
+ * encoding, where:
+ * <pre>
+ * representationClass = InputStream
+ * mimeType = "text/plain; charset=unicode"
+ * </pre>
+ * This <code>DataFlavor</code> has been <b>deprecated</b> 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 <code>DataFlavor.getReaderForText(Transferable)</code>
+ * instead of <code>Transferable.getTransferData(DataFlavor.plainTextFlavor)</code>.
+ */
+ @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 <code>DataFlavor</code>
+ * identifies the Java type of an object returned as a reference
+ * from an invocation <code>java.awt.datatransfer.getTransferData</code>.
+ */
+ public static final String javaSerializedObjectMimeType = "application/x-java-serialized-object";
+
+ /**
+ * To transfer a list of files to/from Java (and the underlying
+ * platform) a <code>DataFlavor</code> of this type/subtype and
+ * representation class of <code>java.util.List</code> is used.
+ * Each element of the list is required/guaranteed to be of type
+ * <code>java.io.File</code>.
+ */
+ 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 <code>Transferable</code>
+ * interface WITHIN THE SAME JVM, a <code>DataFlavor</code>
+ * with this type/subtype is used, with a <code>representationClass</code>
+ * equal to the type of the class/interface being passed across the
+ * <code>Transferable</code>.
+ * <p>
+ * The object reference returned from
+ * <code>Transferable.getTransferData</code> for a <code>DataFlavor</code>
+ * with this MIME Content-Type is required to be
+ * an instance of the representation Class of the <code>DataFlavor</code>.
+ */
+ 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
+ * <code>ACTION_LINK</code> operation a Mime Content Type of
+ * application/x-java-remote-object should be used,
+ * where the representation class of the <code>DataFlavor</code>
+ * represents the type of the <code>Remote</code> 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.
+ * <pre>
+ * representationClass = String
+ * mimeType = "text/html"
+ * </pre>
+ */
+ 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.
+ * <pre>
+ * representationClass = String
+ * mimeType = "text/html"
+ * </pre>
+ */
+ 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.
+ * <pre>
+ * representationClass = String
+ * mimeType = "text/html"
+ * </pre>
+ */
+ public static DataFlavor allHtmlFlavor = initHtmlDataFlavor("all");
+
+ /**
+ * Constructs a new <code>DataFlavor</code>. This constructor is
+ * provided only for the purpose of supporting the
+ * <code>Externalizable</code> interface. It is not
+ * intended for public (client) use.
+ *
+ * @since 1.2
+ */
+ public DataFlavor() {
+ super();
+ }
+
+ /**
+ * Constructs a fully specified <code>DataFlavor</code>.
+ *
+ * @exception NullPointerException if either <code>primaryType</code>,
+ * <code>subType</code> or <code>representationClass</code> 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 <code>DataFlavor</code> that represents a Java class.
+ * <p>
+ * The returned <code>DataFlavor</code> will have the following
+ * characteristics:
+ * <pre>
+ * representationClass = representationClass
+ * mimeType = application/x-java-serialized-object
+ * </pre>
+ * @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 <code>null</code>
+ * then the value of the MIME Content Type is used
+ * @exception NullPointerException if <code>representationClass</code> 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 <code>DataFlavor</code> that represents a
+ * <code>MimeType</code>.
+ * <p>
+ * The returned <code>DataFlavor</code> will have the following
+ * characteristics:
+ * <p>
+ * If the <code>mimeType</code> is
+ * "application/x-java-serialized-object; class=<representation class>",
+ * the result is the same as calling
+ * <code>new DataFlavor(Class.forName(<representation class>)</code>.
+ * <p>
+ * Otherwise:
+ * <pre>
+ * representationClass = InputStream
+ * mimeType = mimeType
+ * </pre>
+ * @param mimeType the string used to identify the MIME type for this flavor;
+ * if the <code>mimeType</code> does not specify a
+ * "class=" parameter, or if the class is not successfully
+ * loaded, then an <code>IllegalArgumentException</code>
+ * is thrown
+ * @param humanPresentableName the human-readable string used to identify
+ * this flavor; if this parameter is <code>null</code>
+ * then the value of the MIME Content Type is used
+ * @exception IllegalArgumentException if <code>mimeType</code> is
+ * invalid or if the class is not successfully loaded
+ * @exception NullPointerException if <code>mimeType</code> 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 <code>DataFlavor</code> that represents a
+ * <code>MimeType</code>.
+ * <p>
+ * The returned <code>DataFlavor</code> will have the following
+ * characteristics:
+ * <p>
+ * If the mimeType is
+ * "application/x-java-serialized-object; class=<representation class>",
+ * the result is the same as calling
+ * <code>new DataFlavor(Class.forName(<representation class>)</code>.
+ * <p>
+ * Otherwise:
+ * <pre>
+ * representationClass = InputStream
+ * mimeType = mimeType
+ * </pre>
+ * @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 <code>mimeType</code> is
+ * invalid
+ * @exception NullPointerException if <code>mimeType</code> 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 <code>DataFlavor</code> from a <code>mimeType</code> string.
+ * The string can specify a "class=<fully specified Java class name>"
+ * parameter to create a <code>DataFlavor</code> with the desired
+ * representation class. If the string does not contain "class=" parameter,
+ * <code>java.io.InputStream</code> 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
+ * <code>ClassNotFoundException</code> is thrown
+ * @exception ClassNotFoundException if the class is not loaded
+ * @exception IllegalArgumentException if <code>mimeType</code> is
+ * invalid
+ * @exception NullPointerException if <code>mimeType</code> 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
+ * <code>null</code>
+ * @param classLoader the fallback class loader to resolve against
+ *
+ * @throws MimeTypeParseException
+ * @throws ClassNotFoundException
+ * @throws NullPointerException if <code>mimeType</code> 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 <code>DataFlavor</code> and its
+ * parameters. The resulting <code>String</code> contains the name of
+ * the <code>DataFlavor</code> 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 <code>selectBestTextFlavor</code>
+ * for a list of text flavors which support the charset parameter.
+ *
+ * @return string representation of this <code>DataFlavor</code>
+ * @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 <code>DataFlavor</code> representing plain text with Unicode
+ * encoding, where:
+ * <pre>
+ * representationClass = java.io.InputStream
+ * mimeType = "text/plain;
+ * charset=<platform default Unicode encoding>"
+ * </pre>
+ * Sun's implementation for Microsoft Windows uses the encoding <code>utf-16le</code>.
+ * Sun's implementation for Solaris and Linux uses the encoding
+ * <code>iso-10646-ucs-2</code>.
+ *
+ * @return a <code>DataFlavor</code> 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 <code>DataFlavor</code> from an array of <code>
+ * DataFlavor</code>s. Only <code>DataFlavor.stringFlavor</code>, and
+ * equivalent flavors, and flavors that have a primary MIME type of "text",
+ * are considered for selection.
+ * <p>
+ * Flavors are first sorted by their MIME types in the following order:
+ * <ul>
+ * <li>"text/sgml"
+ * <li>"text/xml"
+ * <li>"text/html"
+ * <li>"text/rtf"
+ * <li>"text/enriched"
+ * <li>"text/richtext"
+ * <li>"text/uri-list"
+ * <li>"text/tab-separated-values"
+ * <li>"text/t140"
+ * <li>"text/rfc822-headers"
+ * <li>"text/parityfec"
+ * <li>"text/directory"
+ * <li>"text/css"
+ * <li>"text/calendar"
+ * <li>"application/x-java-serialized-object"
+ * <li>"text/plain"
+ * <li>"text/<other>"
+ * </ul>
+ * <p>For example, "text/sgml" will be selected over
+ * "text/html", and <code>DataFlavor.stringFlavor</code> will be chosen
+ * over <code>DataFlavor.plainTextFlavor</code>.
+ * <p>
+ * 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.
+ * <p>
+ * The following MIME types support, or are treated as though they support,
+ * the charset parameter:
+ * <ul>
+ * <li>"text/sgml"
+ * <li>"text/xml"
+ * <li>"text/html"
+ * <li>"text/enriched"
+ * <li>"text/richtext"
+ * <li>"text/uri-list"
+ * <li>"text/directory"
+ * <li>"text/css"
+ * <li>"text/calendar"
+ * <li>"application/x-java-serialized-object"
+ * <li>"text/plain"
+ * </ul>
+ * The following MIME types do not support, or are treated as though they
+ * do not support, the charset parameter:
+ * <ul>
+ * <li>"text/rtf"
+ * <li>"text/tab-separated-values"
+ * <li>"text/t140"
+ * <li>"text/rfc822-headers"
+ * <li>"text/parityfec"
+ * </ul>
+ * 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 <code>DataFlavor</code> 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
+ * <code>DataFlavor</code>, developers must ensure that all
+ * <code>DataFlavor</code>s 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.
+ * <p>
+ * 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:
+ * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
+ * <code>[B</code>, <all others>.
+ * <p>
+ * 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.
+ * <p>
+ * 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:
+ * <code>java.io.Reader</code>, <code>java.lang.String</code>,
+ * <code>java.nio.CharBuffer</code>, <code>[C</code>, <all others>.
+ * <p>
+ * 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.
+ * <p>
+ * If two or more flavors share the best charset, the flavors will then
+ * again be sorted by their representation classes in the following order:
+ * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
+ * <code>[B</code>, <all others>.
+ * <p>
+ * 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 <code>DataFlavor</code>s
+ * @return the best (highest fidelity) flavor according to the rules
+ * specified above, or <code>null</code>,
+ * if <code>availableFlavors</code> is <code>null</code>,
+ * 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
+ * <code>java.io.Reader</code>, <code>java.lang.String</code>,
+ * <code>java.nio.CharBuffer</code>, <code>[C</code>,
+ * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
+ * and <code>[B</code>.
+ * <p>
+ * 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 <code>selectBestTextFlavor</code> for a list
+ * of text flavors which do not support the charset parameter.
+ *
+ * @param transferable the <code>Transferable</code> whose data will be
+ * requested in this flavor
+ *
+ * @return a <code>Reader</code> to read the <code>Transferable</code>'s
+ * data
+ *
+ * @exception IllegalArgumentException if the representation class
+ * is not one of the seven listed above
+ * @exception IllegalArgumentException if the <code>Transferable</code>
+ * has <code>null</code> data
+ * @exception NullPointerException if the <code>Transferable</code> is
+ * <code>null</code>
+ * @exception UnsupportedEncodingException if this flavor's representation
+ * is <code>java.io.InputStream</code>,
+ * <code>java.nio.ByteBuffer</code>, or <code>[B</code> and
+ * this flavor's encoding is not supported by this
+ * implementation of the Java platform
+ * @exception UnsupportedFlavorException if the <code>Transferable</code>
+ * 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 <code>DataFlavor</code>.
+ * @return the MIME type string for this flavor
+ */
+ public String getMimeType() {
+ return (mimeType != null) ? mimeType.toString() : null;
+ }
+
+ /**
+ * Returns the <code>Class</code> which objects supporting this
+ * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
+ * is requested.
+ * @return the <code>Class</code> which objects supporting this
+ * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
+ * is requested
+ */
+ public Class<?> getRepresentationClass() {
+ return representationClass;
+ }
+
+ /**
+ * Returns the human presentable name for the data format that this
+ * <code>DataFlavor</code> represents. This name would be localized
+ * for different countries.
+ * @return the human presentable name for the data format that this
+ * <code>DataFlavor</code> represents
+ */
+ public String getHumanPresentableName() {
+ return humanPresentableName;
+ }
+
+ /**
+ * Returns the primary MIME type for this <code>DataFlavor</code>.
+ * @return the primary MIME type of this <code>DataFlavor</code>
+ */
+ public String getPrimaryType() {
+ return (mimeType != null) ? mimeType.getPrimaryType() : null;
+ }
+
+ /**
+ * Returns the sub MIME type of this <code>DataFlavor</code>.
+ * @return the Sub MIME type of this <code>DataFlavor</code>
+ */
+ public String getSubType() {
+ return (mimeType != null) ? mimeType.getSubType() : null;
+ }
+
+ /**
+ * Returns the human presentable name for this <code>DataFlavor</code>
+ * if <code>paramName</code> equals "humanPresentableName". Otherwise
+ * returns the MIME type value associated with <code>paramName</code>.
+ *
+ * @param paramName the parameter name requested
+ * @return the value of the name parameter, or <code>null</code>
+ * 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
+ * <code>DataFlavor</code> 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}
+ * <p>
+ * The equals comparison for the {@code DataFlavor} class is implemented
+ * as follows: Two <code>DataFlavor</code>s 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 <code>java.io.Reader</code>,
+ * <code>java.lang.String</code>, <code>java.nio.CharBuffer</code>, or
+ * <code>[C</code>, the <code>charset</code> parameter must also be equal.
+ * If a charset is not explicitly specified for one or both
+ * <code>DataFlavor</code>s, the platform default encoding is assumed. See
+ * <code>selectBestTextFlavor</code> for a list of text flavors which
+ * support the charset parameter.
+ *
+ * @param o the <code>Object</code> to compare with <code>this</code>
+ * @return <code>true</code> if <code>that</code> is equivalent to this
+ * <code>DataFlavor</code>; <code>false</code> 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 <code>DataFlavor</code> to compare with
+ * <code>this</code>
+ * @return <code>true</code> if <code>that</code> is equivalent to this
+ * <code>DataFlavor</code>; <code>false</code> 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 <code>mimeType</code> against the passed in
+ * <code>String</code> and <code>representationClass</code> is
+ * not considered in the comparison.
+ *
+ * If <code>representationClass</code> needs to be compared, then
+ * <code>equals(new DataFlavor(s))</code> may be used.
+ * @deprecated As inconsistent with <code>hashCode()</code> contract,
+ * use <code>isMimeTypeEqual(String)</code> 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 <code>DataFlavor</code>.
+ * For two equal <code>DataFlavor</code>s, hash codes are equal.
+ * For the <code>String</code>
+ * that matches <code>DataFlavor.equals(String)</code>, it is not
+ * guaranteed that <code>DataFlavor</code>'s hash code is equal
+ * to the hash code of the <code>String</code>.
+ *
+ * @return a hash code for this <code>DataFlavor</code>
+ */
+ 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 <code>DataFlavor</code> to compare with
+ * <code>this</code>
+ * @return <code>true</code> if <code>that</code> is equivalent to this
+ * <code>DataFlavor</code>; <code>false</code> 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 <code>DataFlavor</code>.
+ * 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 <code>DataFlavor</code>;
+ * false otherwise
+ * @throws NullPointerException if mimeType is <code>null</code>
+ */
+ 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 <code>mimeType</code> of two <code>DataFlavor</code>
+ * objects. No parameters are considered.
+ *
+ * @param dataFlavor the <code>DataFlavor</code> to be compared
+ * @return true if the <code>MimeType</code>s are equal,
+ * otherwise false
+ */
+
+ public final boolean isMimeTypeEqual(DataFlavor dataFlavor) {
+ return isMimeTypeEqual(dataFlavor.mimeType);
+ }
+
+ /**
+ * Compares the <code>mimeType</code> of two <code>DataFlavor</code>
+ * objects. No parameters are considered.
+ *
+ * @return true if the <code>MimeType</code>s 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 <code>DataFlavor</code> 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 <code>DataFlavor</code> represent a
+ * <code>java.io.InputStream</code>?
+ * @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
+ * <code>DataFlavor</code> is <code>java.io.Reader</code> 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
+ * <code>DataFlavor</code> is <code>java.nio.CharBuffer</code> 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
+ * <code>DataFlavor</code> is <code>java.nio.ByteBuffer</code> 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 <code>Remote</code>.
+ * @return true if the representation class is <code>Remote</code>
+ */
+ public boolean isRepresentationClassRemote() {
+ return DataFlavorUtil.RMI.isRemote(representationClass);
+ }
+
+ /**
+ * Returns true if the <code>DataFlavor</code> specified represents
+ * a serialized object.
+ * @return true if the <code>DataFlavor</code> specified represents
+ * a Serialized Object
+ */
+
+ public boolean isFlavorSerializedObjectType() {
+ return isRepresentationClassSerializable() && isMimeTypeEqual(javaSerializedObjectMimeType);
+ }
+
+ /**
+ * Returns true if the <code>DataFlavor</code> specified represents
+ * a remote object.
+ * @return true if the <code>DataFlavor</code> specified represents
+ * a Remote Object
+ */
+
+ public boolean isFlavorRemoteObjectType() {
+ return isRepresentationClassRemote()
+ && isRepresentationClassSerializable()
+ && isMimeTypeEqual(javaRemoteObjectMimeType);
+ }
+
+
+ /**
+ * Returns true if the <code>DataFlavor</code> specified represents
+ * a list of file objects.
+ * @return true if the <code>DataFlavor</code> 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 <code>DataFlavor</code> is a valid text flavor for
+ * this implementation of the Java platform. Only flavors equivalent to
+ * <code>DataFlavor.stringFlavor</code> and <code>DataFlavor</code>s with
+ * a primary MIME type of "text" can be valid text flavors.
+ * <p>
+ * If this flavor supports the charset parameter, it must be equivalent to
+ * <code>DataFlavor.stringFlavor</code>, or its representation must be
+ * <code>java.io.Reader</code>, <code>java.lang.String</code>,
+ * <code>java.nio.CharBuffer</code>, <code>[C</code>,
+ * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
+ * <code>[B</code>. If the representation is
+ * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
+ * <code>[B</code>, then this flavor's <code>charset</code> 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.
+ * <p>
+ * If this flavor does not support the charset parameter, its
+ * representation must be <code>java.io.InputStream</code>,
+ * <code>java.nio.ByteBuffer</code>, or <code>[B</code>.
+ * <p>
+ * See <code>selectBestTextFlavor</code> for a list of text flavors which
+ * support the charset parameter.
+ *
+ * @return <code>true</code> if this <code>DataFlavor</code> is a valid
+ * text flavor as described above; <code>false</code> otherwise
+ * @see #selectBestTextFlavor
+ * @since 1.4
+ */
+ public boolean isFlavorTextType() {
+ return (DataFlavorUtil.isFlavorCharsetTextType(this) ||
+ DataFlavorUtil.isFlavorNoncharsetTextType(this));
+ }
+
+ /**
+ * Serializes this <code>DataFlavor</code>.
+ */
+
+ 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 <code>DataFlavor</code> 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 <code>DataFlavor</code>.
+ * @return a clone of this <code>DataFlavor</code>
+ */
+
+ public Object clone() throws CloneNotSupportedException {
+ Object newObj = super.clone();
+ if (mimeType != null) {
+ ((DataFlavor)newObj).mimeType = (MimeType)mimeType.clone();
+ }
+ return newObj;
+ } // clone()
+
+ /**
+ * Called on <code>DataFlavor</code> for every MIME Type parameter
+ * to allow <code>DataFlavor</code> subclasses to handle special
+ * parameters like the text/plain <code>charset</code>
+ * parameters, whose values are case insensitive. (MIME type parameter
+ * values are supposed to be case sensitive.
+ * <p>
+ * This method is called for each parameter name/value pair and should
+ * return the normalized representation of the <code>parameterValue</code>.
+ *
+ * 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 <code>DataFlavor</code> 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 Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/FlavorEvent.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2003, 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 java.util.EventObject;
+
+
+/**
+ * <code>FlavorEvent</code> is used to notify interested parties
+ * that available {@link DataFlavor}s have changed in the
+ * {@link Clipboard} (the event source).
+ *
+ * @see FlavorListener
+ *
+ * @author Alexander Gerasimov
+ * @since 1.5
+ */
+public class FlavorEvent extends EventObject {
+ private static final long serialVersionUID = -5842664112252414548L;
+
+ /**
+ * Constructs a <code>FlavorEvent</code> object.
+ *
+ * @param source the <code>Clipboard</code> that is the source of the event
+ *
+ * @throws IllegalArgumentException if the {@code source} is {@code null}
+ */
+ public FlavorEvent(Clipboard source) {
+ super(source);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/FlavorListener.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003, 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 java.util.EventListener;
+
+
+/**
+ * Defines an object which listens for {@link FlavorEvent}s.
+ *
+ * @author Alexander Gerasimov
+ * @since 1.5
+ */
+public interface FlavorListener extends EventListener {
+ /**
+ * Invoked when the target {@link Clipboard} of the listener
+ * has changed its available {@link DataFlavor}s.
+ * <p>
+ * Some notifications may be redundant — they are not
+ * caused by a change of the set of DataFlavors available
+ * on the clipboard.
+ * For example, if the clipboard subsystem supposes that
+ * the system clipboard's contents has been changed but it
+ * can't ascertain whether its DataFlavors have been changed
+ * because of some exceptional condition when accessing the
+ * clipboard, the notification is sent to ensure from omitting
+ * a significant notification. Ordinarily, those redundant
+ * notifications should be occasional.
+ *
+ * @param e a <code>FlavorEvent</code> object
+ */
+ void flavorsChanged(FlavorEvent e);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/FlavorMap.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1997, 2013, 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 java.util.Map;
+
+
+/**
+ * A two-way Map between "natives" (Strings), which correspond to platform-
+ * specific data formats, and "flavors" (DataFlavors), which correspond to
+ * platform-independent MIME types. FlavorMaps need not be symmetric, but
+ * typically are.
+ *
+ *
+ * @since 1.2
+ */
+public interface FlavorMap {
+
+ /**
+ * Returns a <code>Map</code> of the specified <code>DataFlavor</code>s to
+ * their corresponding <code>String</code> native. The returned
+ * <code>Map</code> is a modifiable copy of this <code>FlavorMap</code>'s
+ * internal data. Client code is free to modify the <code>Map</code>
+ * without affecting this object.
+ *
+ * @param flavors an array of <code>DataFlavor</code>s which will be the
+ * key set of the returned <code>Map</code>. If <code>null</code> is
+ * specified, a mapping of all <code>DataFlavor</code>s currently
+ * known to this <code>FlavorMap</code> to their corresponding
+ * <code>String</code> natives will be returned.
+ * @return a <code>java.util.Map</code> of <code>DataFlavor</code>s to
+ * <code>String</code> natives
+ */
+ Map<DataFlavor,String> getNativesForFlavors(DataFlavor[] flavors);
+
+ /**
+ * Returns a <code>Map</code> of the specified <code>String</code> natives
+ * to their corresponding <code>DataFlavor</code>. The returned
+ * <code>Map</code> is a modifiable copy of this <code>FlavorMap</code>'s
+ * internal data. Client code is free to modify the <code>Map</code>
+ * without affecting this object.
+ *
+ * @param natives an array of <code>String</code>s which will be the
+ * key set of the returned <code>Map</code>. If <code>null</code> is
+ * specified, a mapping of all <code>String</code> natives currently
+ * known to this <code>FlavorMap</code> to their corresponding
+ * <code>DataFlavor</code>s will be returned.
+ * @return a <code>java.util.Map</code> of <code>String</code> natives to
+ * <code>DataFlavor</code>s
+ */
+ Map<String,DataFlavor> getFlavorsForNatives(String[] natives);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/FlavorTable.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2000, 2004, 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 java.util.List;
+
+
+/**
+ * A FlavorMap which relaxes the traditional 1-to-1 restriction of a Map. A
+ * flavor is permitted to map to any number of natives, and likewise a native
+ * is permitted to map to any number of flavors. FlavorTables need not be
+ * symmetric, but typically are.
+ *
+ * @author David Mendenhall
+ *
+ * @since 1.4
+ */
+public interface FlavorTable extends FlavorMap {
+
+ /**
+ * Returns a <code>List</code> of <code>String</code> natives to which the
+ * specified <code>DataFlavor</code> corresponds. The <code>List</code>
+ * will be sorted from best native to worst. That is, the first native will
+ * best reflect data in the specified flavor to the underlying native
+ * platform. The returned <code>List</code> is a modifiable copy of this
+ * <code>FlavorTable</code>'s internal data. Client code is free to modify
+ * the <code>List</code> without affecting this object.
+ *
+ * @param flav the <code>DataFlavor</code> whose corresponding natives
+ * should be returned. If <code>null</code> is specified, all
+ * natives currently known to this <code>FlavorTable</code> are
+ * returned in a non-deterministic order.
+ * @return a <code>java.util.List</code> of <code>java.lang.String</code>
+ * objects which are platform-specific representations of platform-
+ * specific data formats
+ */
+ List<String> getNativesForFlavor(DataFlavor flav);
+
+ /**
+ * Returns a <code>List</code> of <code>DataFlavor</code>s to which the
+ * specified <code>String</code> corresponds. The <code>List</code> will be
+ * sorted from best <code>DataFlavor</code> to worst. That is, the first
+ * <code>DataFlavor</code> will best reflect data in the specified
+ * native to a Java application. The returned <code>List</code> is a
+ * modifiable copy of this <code>FlavorTable</code>'s internal data.
+ * Client code is free to modify the <code>List</code> without affecting
+ * this object.
+ *
+ * @param nat the native whose corresponding <code>DataFlavor</code>s
+ * should be returned. If <code>null</code> is specified, all
+ * <code>DataFlavor</code>s currently known to this
+ * <code>FlavorTable</code> are returned in a non-deterministic
+ * order.
+ * @return a <code>java.util.List</code> of <code>DataFlavor</code>
+ * objects into which platform-specific data in the specified,
+ * platform-specific native can be translated
+ */
+ List<DataFlavor> getFlavorsForNative(String nat);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/MimeType.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 1997, 2012, 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 java.io.Externalizable;
+import java.io.ObjectOutput;
+import java.io.ObjectInput;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Locale;
+
+
+/**
+ * A Multipurpose Internet Mail Extension (MIME) type, as defined
+ * in RFC 2045 and 2046.
+ *
+ * THIS IS *NOT* - REPEAT *NOT* - A PUBLIC CLASS! DataFlavor IS
+ * THE PUBLIC INTERFACE, AND THIS IS PROVIDED AS A ***PRIVATE***
+ * (THAT IS AS IN *NOT* PUBLIC) HELPER CLASS!
+ */
+class MimeType implements Externalizable, Cloneable {
+
+ /*
+ * serialization support
+ */
+
+ static final long serialVersionUID = -6568722458793895906L;
+
+ /**
+ * Constructor for externalization; this constructor should not be
+ * called directly by an application, since the result will be an
+ * uninitialized, immutable <code>MimeType</code> object.
+ */
+ public MimeType() {
+ }
+
+ /**
+ * Builds a <code>MimeType</code> from a <code>String</code>.
+ *
+ * @param rawdata text used to initialize the <code>MimeType</code>
+ * @throws NullPointerException if <code>rawdata</code> is null
+ */
+ public MimeType(String rawdata) throws MimeTypeParseException {
+ parse(rawdata);
+ }
+
+ /**
+ * Builds a <code>MimeType</code> with the given primary and sub
+ * type but has an empty parameter list.
+ *
+ * @param primary the primary type of this <code>MimeType</code>
+ * @param sub the subtype of this <code>MimeType</code>
+ * @throws NullPointerException if either <code>primary</code> or
+ * <code>sub</code> is null
+ */
+ public MimeType(String primary, String sub) throws MimeTypeParseException {
+ this(primary, sub, new MimeTypeParameterList());
+ }
+
+ /**
+ * Builds a <code>MimeType</code> with a pre-defined
+ * and valid (or empty) parameter list.
+ *
+ * @param primary the primary type of this <code>MimeType</code>
+ * @param sub the subtype of this <code>MimeType</code>
+ * @param mtpl the requested parameter list
+ * @throws NullPointerException if either <code>primary</code>,
+ * <code>sub</code> or <code>mtpl</code> is null
+ */
+ public MimeType(String primary, String sub, MimeTypeParameterList mtpl) throws
+MimeTypeParseException {
+ // check to see if primary is valid
+ if(isValidToken(primary)) {
+ primaryType = primary.toLowerCase(Locale.ENGLISH);
+ } else {
+ throw new MimeTypeParseException("Primary type is invalid.");
+ }
+
+ // check to see if sub is valid
+ if(isValidToken(sub)) {
+ subType = sub.toLowerCase(Locale.ENGLISH);
+ } else {
+ throw new MimeTypeParseException("Sub type is invalid.");
+ }
+
+ parameters = (MimeTypeParameterList)mtpl.clone();
+ }
+
+ public int hashCode() {
+
+ // We sum up the hash codes for all of the strings. This
+ // way, the order of the strings is irrelevant
+ int code = 0;
+ code += primaryType.hashCode();
+ code += subType.hashCode();
+ code += parameters.hashCode();
+ return code;
+ } // hashCode()
+
+ /**
+ * <code>MimeType</code>s are equal if their primary types,
+ * subtypes, and parameters are all equal. No default values
+ * are taken into account.
+ * @param thatObject the object to be evaluated as a
+ * <code>MimeType</code>
+ * @return <code>true</code> if <code>thatObject</code> is
+ * a <code>MimeType</code>; otherwise returns <code>false</code>
+ */
+ public boolean equals(Object thatObject) {
+ if (!(thatObject instanceof MimeType)) {
+ return false;
+ }
+ MimeType that = (MimeType)thatObject;
+ boolean isIt =
+ ((this.primaryType.equals(that.primaryType)) &&
+ (this.subType.equals(that.subType)) &&
+ (this.parameters.equals(that.parameters)));
+ return isIt;
+ } // equals()
+
+ /**
+ * A routine for parsing the MIME type out of a String.
+ *
+ * @throws NullPointerException if <code>rawdata</code> is null
+ */
+ private void parse(String rawdata) throws MimeTypeParseException {
+ int slashIndex = rawdata.indexOf('/');
+ int semIndex = rawdata.indexOf(';');
+ if((slashIndex < 0) && (semIndex < 0)) {
+ // neither character is present, so treat it
+ // as an error
+ throw new MimeTypeParseException("Unable to find a sub type.");
+ } else if((slashIndex < 0) && (semIndex >= 0)) {
+ // we have a ';' (and therefore a parameter list),
+ // but no '/' indicating a sub type is present
+ throw new MimeTypeParseException("Unable to find a sub type.");
+ } else if((slashIndex >= 0) && (semIndex < 0)) {
+ // we have a primary and sub type but no parameter list
+ primaryType = rawdata.substring(0,slashIndex).
+ trim().toLowerCase(Locale.ENGLISH);
+ subType = rawdata.substring(slashIndex + 1).
+ trim().toLowerCase(Locale.ENGLISH);
+ parameters = new MimeTypeParameterList();
+ } else if (slashIndex < semIndex) {
+ // we have all three items in the proper sequence
+ primaryType = rawdata.substring(0, slashIndex).
+ trim().toLowerCase(Locale.ENGLISH);
+ subType = rawdata.substring(slashIndex + 1,
+ semIndex).trim().toLowerCase(Locale.ENGLISH);
+ parameters = new
+MimeTypeParameterList(rawdata.substring(semIndex));
+ } else {
+ // we have a ';' lexically before a '/' which means we have a primary type
+ // & a parameter list but no sub type
+ throw new MimeTypeParseException("Unable to find a sub type.");
+ }
+
+ // now validate the primary and sub types
+
+ // check to see if primary is valid
+ if(!isValidToken(primaryType)) {
+ throw new MimeTypeParseException("Primary type is invalid.");
+ }
+
+ // check to see if sub is valid
+ if(!isValidToken(subType)) {
+ throw new MimeTypeParseException("Sub type is invalid.");
+ }
+ }
+
+ /**
+ * Retrieve the primary type of this object.
+ */
+ public String getPrimaryType() {
+ return primaryType;
+ }
+
+ /**
+ * Retrieve the sub type of this object.
+ */
+ public String getSubType() {
+ return subType;
+ }
+
+ /**
+ * Retrieve a copy of this object's parameter list.
+ */
+ public MimeTypeParameterList getParameters() {
+ return (MimeTypeParameterList)parameters.clone();
+ }
+
+ /**
+ * Retrieve the value associated with the given name, or null if there
+ * is no current association.
+ */
+ public String getParameter(String name) {
+ return parameters.get(name);
+ }
+
+ /**
+ * Set the value to be associated with the given name, replacing
+ * any previous association.
+ *
+ * @throw IllegalArgumentException if parameter or value is illegal
+ */
+ public void setParameter(String name, String value) {
+ parameters.set(name, value);
+ }
+
+ /**
+ * Remove any value associated with the given name.
+ *
+ * @throw IllegalArgumentException if parameter may not be deleted
+ */
+ public void removeParameter(String name) {
+ parameters.remove(name);
+ }
+
+ /**
+ * Return the String representation of this object.
+ */
+ public String toString() {
+ return getBaseType() + parameters.toString();
+ }
+
+ /**
+ * Return a String representation of this object
+ * without the parameter list.
+ */
+ public String getBaseType() {
+ return primaryType + "/" + subType;
+ }
+
+ /**
+ * Returns <code>true</code> if the primary type and the
+ * subtype of this object are the same as the specified
+ * <code>type</code>; otherwise returns <code>false</code>.
+ *
+ * @param type the type to compare to <code>this</code>'s type
+ * @return <code>true</code> if the primary type and the
+ * subtype of this object are the same as the
+ * specified <code>type</code>; otherwise returns
+ * <code>false</code>
+ */
+ public boolean match(MimeType type) {
+ if (type == null)
+ return false;
+ return primaryType.equals(type.getPrimaryType())
+ && (subType.equals("*")
+ || type.getSubType().equals("*")
+ || (subType.equals(type.getSubType())));
+ }
+
+ /**
+ * Returns <code>true</code> if the primary type and the
+ * subtype of this object are the same as the content type
+ * described in <code>rawdata</code>; otherwise returns
+ * <code>false</code>.
+ *
+ * @param rawdata the raw data to be examined
+ * @return <code>true</code> if the primary type and the
+ * subtype of this object are the same as the content type
+ * described in <code>rawdata</code>; otherwise returns
+ * <code>false</code>; if <code>rawdata</code> is
+ * <code>null</code>, returns <code>false</code>
+ */
+ public boolean match(String rawdata) throws MimeTypeParseException {
+ if (rawdata == null)
+ return false;
+ return match(new MimeType(rawdata));
+ }
+
+ /**
+ * The object implements the writeExternal method to save its contents
+ * by calling the methods of DataOutput for its primitive values or
+ * calling the writeObject method of ObjectOutput for objects, strings
+ * and arrays.
+ * @exception IOException Includes any I/O exceptions that may occur
+ */
+ public void writeExternal(ObjectOutput out) throws IOException {
+ String s = toString(); // contains ASCII chars only
+ // one-to-one correspondence between ASCII char and byte in UTF string
+ if (s.length() <= 65535) { // 65535 is max length of UTF string
+ out.writeUTF(s);
+ } else {
+ out.writeByte(0);
+ out.writeByte(0);
+ out.writeInt(s.length());
+ out.write(s.getBytes());
+ }
+ }
+
+ /**
+ * The object implements the readExternal method to restore its
+ * contents by calling the methods of DataInput for primitive
+ * types and readObject for objects, strings and arrays. The
+ * readExternal method must read the values in the same sequence
+ * and with the same types as were written by writeExternal.
+ * @exception ClassNotFoundException If the class for an object being
+ * restored cannot be found.
+ */
+ public void readExternal(ObjectInput in) throws IOException,
+ClassNotFoundException {
+ String s = in.readUTF();
+ if (s == null || s.length() == 0) { // long mime type
+ byte[] ba = new byte[in.readInt()];
+ in.readFully(ba);
+ s = new String(ba);
+ }
+ try {
+ parse(s);
+ } catch(MimeTypeParseException e) {
+ throw new IOException(e.toString());
+ }
+ }
+
+ /**
+ * Returns a clone of this object.
+ * @return a clone of this object
+ */
+
+ public Object clone() {
+ MimeType newObj = null;
+ try {
+ newObj = (MimeType)super.clone();
+ } catch (CloneNotSupportedException cannotHappen) {
+ }
+ newObj.parameters = (MimeTypeParameterList)parameters.clone();
+ return newObj;
+ }
+
+ private String primaryType;
+ private String subType;
+ private MimeTypeParameterList parameters;
+
+ // below here be scary parsing related things
+
+ /**
+ * Determines whether or not a given character belongs to a legal token.
+ */
+ private static boolean isTokenChar(char c) {
+ return ((c > 040) && (c < 0177)) && (TSPECIALS.indexOf(c) < 0);
+ }
+
+ /**
+ * Determines whether or not a given string is a legal token.
+ *
+ * @throws NullPointerException if <code>s</code> is null
+ */
+ private boolean isValidToken(String s) {
+ int len = s.length();
+ if(len > 0) {
+ for (int i = 0; i < len; ++i) {
+ char c = s.charAt(i);
+ if (!isTokenChar(c)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * A string that holds all the special chars.
+ */
+
+ private static final String TSPECIALS = "()<>@,;:\\\"/[]?=";
+
+} // class MimeType
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/MimeTypeParameterList.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 1997, 2013, 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 java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * An object that encapsulates the parameter list of a MimeType
+ * as defined in RFC 2045 and 2046.
+ *
+ * @author jeff.dunn@eng.sun.com
+ */
+class MimeTypeParameterList implements Cloneable {
+
+ /**
+ * Default constructor.
+ */
+ public MimeTypeParameterList() {
+ parameters = new Hashtable<>();
+ }
+
+ public MimeTypeParameterList(String rawdata)
+ throws MimeTypeParseException
+ {
+ parameters = new Hashtable<>();
+
+ // now parse rawdata
+ parse(rawdata);
+ }
+
+ public int hashCode() {
+ int code = Integer.MAX_VALUE/45; // "random" value for empty lists
+ String paramName = null;
+ Enumeration<String> enum_ = this.getNames();
+
+ while (enum_.hasMoreElements()) {
+ paramName = enum_.nextElement();
+ code += paramName.hashCode();
+ code += this.get(paramName).hashCode();
+ }
+
+ return code;
+ } // hashCode()
+
+ /**
+ * Two parameter lists are considered equal if they have exactly
+ * the same set of parameter names and associated values. The
+ * order of the parameters is not considered.
+ */
+ public boolean equals(Object thatObject) {
+ //System.out.println("MimeTypeParameterList.equals("+this+","+thatObject+")");
+ if (!(thatObject instanceof MimeTypeParameterList)) {
+ return false;
+ }
+ MimeTypeParameterList that = (MimeTypeParameterList)thatObject;
+ if (this.size() != that.size()) {
+ return false;
+ }
+ String name = null;
+ String thisValue = null;
+ String thatValue = null;
+ Set<Map.Entry<String, String>> entries = parameters.entrySet();
+ Iterator<Map.Entry<String, String>> iterator = entries.iterator();
+ Map.Entry<String, String> entry = null;
+ while (iterator.hasNext()) {
+ entry = iterator.next();
+ name = entry.getKey();
+ thisValue = entry.getValue();
+ thatValue = that.parameters.get(name);
+ if ((thisValue == null) || (thatValue == null)) {
+ // both null -> equal, only one null -> not equal
+ if (thisValue != thatValue) {
+ return false;
+ }
+ } else if (!thisValue.equals(thatValue)) {
+ return false;
+ }
+ } // while iterator
+
+ return true;
+ } // equals()
+
+ /**
+ * A routine for parsing the parameter list out of a String.
+ */
+ protected void parse(String rawdata) throws MimeTypeParseException {
+ int length = rawdata.length();
+ if(length > 0) {
+ int currentIndex = skipWhiteSpace(rawdata, 0);
+ int lastIndex = 0;
+
+ if(currentIndex < length) {
+ char currentChar = rawdata.charAt(currentIndex);
+ while ((currentIndex < length) && (currentChar == ';')) {
+ String name;
+ String value;
+ boolean foundit;
+
+ // eat the ';'
+ ++currentIndex;
+
+ // now parse the parameter name
+
+ // skip whitespace
+ currentIndex = skipWhiteSpace(rawdata, currentIndex);
+
+ if(currentIndex < length) {
+ // find the end of the token char run
+ lastIndex = currentIndex;
+ currentChar = rawdata.charAt(currentIndex);
+ while((currentIndex < length) && isTokenChar(currentChar)) {
+ ++currentIndex;
+ currentChar = rawdata.charAt(currentIndex);
+ }
+ name = rawdata.substring(lastIndex, currentIndex).toLowerCase();
+
+ // now parse the '=' that separates the name from the value
+
+ // skip whitespace
+ currentIndex = skipWhiteSpace(rawdata, currentIndex);
+
+ if((currentIndex < length) && (rawdata.charAt(currentIndex) == '=')) {
+ // eat it and parse the parameter value
+ ++currentIndex;
+
+ // skip whitespace
+ currentIndex = skipWhiteSpace(rawdata, currentIndex);
+
+ if(currentIndex < length) {
+ // now find out whether or not we have a quoted value
+ currentChar = rawdata.charAt(currentIndex);
+ if(currentChar == '"') {
+ // yup it's quoted so eat it and capture the quoted string
+ ++currentIndex;
+ lastIndex = currentIndex;
+
+ if(currentIndex < length) {
+ // find the next unescaped quote
+ foundit = false;
+ while((currentIndex < length) && !foundit) {
+ currentChar = rawdata.charAt(currentIndex);
+ if(currentChar == '\\') {
+ // found an escape sequence so pass this and the next character
+ currentIndex += 2;
+ } else if(currentChar == '"') {
+ // found it!
+ foundit = true;
+ } else {
+ ++currentIndex;
+ }
+ }
+ if(currentChar == '"') {
+ value = unquote(rawdata.substring(lastIndex, currentIndex));
+ // eat the quote
+ ++currentIndex;
+ } else {
+ throw new MimeTypeParseException("Encountered unterminated quoted parameter value.");
+ }
+ } else {
+ throw new MimeTypeParseException("Encountered unterminated quoted parameter value.");
+ }
+ } else if(isTokenChar(currentChar)) {
+ // nope it's an ordinary token so it ends with a non-token char
+ lastIndex = currentIndex;
+ foundit = false;
+ while((currentIndex < length) && !foundit) {
+ currentChar = rawdata.charAt(currentIndex);
+
+ if(isTokenChar(currentChar)) {
+ ++currentIndex;
+ } else {
+ foundit = true;
+ }
+ }
+ value = rawdata.substring(lastIndex, currentIndex);
+ } else {
+ // it ain't a value
+ throw new MimeTypeParseException("Unexpected character encountered at index " + currentIndex);
+ }
+
+ // now put the data into the hashtable
+ parameters.put(name, value);
+ } else {
+ throw new MimeTypeParseException("Couldn't find a value for parameter named " + name);
+ }
+ } else {
+ throw new MimeTypeParseException("Couldn't find the '=' that separates a parameter name from its value.");
+ }
+ } else {
+ throw new MimeTypeParseException("Couldn't find parameter name");
+ }
+
+ // setup the next iteration
+ currentIndex = skipWhiteSpace(rawdata, currentIndex);
+ if(currentIndex < length) {
+ currentChar = rawdata.charAt(currentIndex);
+ }
+ }
+ if(currentIndex < length) {
+ throw new MimeTypeParseException("More characters encountered in input than expected.");
+ }
+ }
+ }
+ }
+
+ /**
+ * return the number of name-value pairs in this list.
+ */
+ public int size() {
+ return parameters.size();
+ }
+
+ /**
+ * Determine whether or not this list is empty.
+ */
+ public boolean isEmpty() {
+ return parameters.isEmpty();
+ }
+
+ /**
+ * Retrieve the value associated with the given name, or null if there
+ * is no current association.
+ */
+ public String get(String name) {
+ return parameters.get(name.trim().toLowerCase());
+ }
+
+ /**
+ * Set the value to be associated with the given name, replacing
+ * any previous association.
+ */
+ public void set(String name, String value) {
+ parameters.put(name.trim().toLowerCase(), value);
+ }
+
+ /**
+ * Remove any value associated with the given name.
+ */
+ public void remove(String name) {
+ parameters.remove(name.trim().toLowerCase());
+ }
+
+ /**
+ * Retrieve an enumeration of all the names in this list.
+ */
+ public Enumeration<String> getNames() {
+ return parameters.keys();
+ }
+
+ public String toString() {
+ // Heuristic: 8 characters per field
+ StringBuilder buffer = new StringBuilder(parameters.size() * 16);
+
+ Enumeration<String> keys = parameters.keys();
+ while(keys.hasMoreElements())
+ {
+ buffer.append("; ");
+
+ String key = keys.nextElement();
+ buffer.append(key);
+ buffer.append('=');
+ buffer.append(quote(parameters.get(key)));
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * @return a clone of this object
+ */
+ @SuppressWarnings("unchecked") // Cast from clone
+ public Object clone() {
+ MimeTypeParameterList newObj = null;
+ try {
+ newObj = (MimeTypeParameterList)super.clone();
+ } catch (CloneNotSupportedException cannotHappen) {
+ }
+ newObj.parameters = (Hashtable<String, String>)parameters.clone();
+ return newObj;
+ }
+
+ private Hashtable<String, String> parameters;
+
+ // below here be scary parsing related things
+
+ /**
+ * Determine whether or not a given character belongs to a legal token.
+ */
+ private static boolean isTokenChar(char c) {
+ return ((c > 040) && (c < 0177)) && (TSPECIALS.indexOf(c) < 0);
+ }
+
+ /**
+ * return the index of the first non white space character in
+ * rawdata at or after index i.
+ */
+ private static int skipWhiteSpace(String rawdata, int i) {
+ int length = rawdata.length();
+ if (i < length) {
+ char c = rawdata.charAt(i);
+ while ((i < length) && Character.isWhitespace(c)) {
+ ++i;
+ c = rawdata.charAt(i);
+ }
+ }
+
+ return i;
+ }
+
+ /**
+ * A routine that knows how and when to quote and escape the given value.
+ */
+ private static String quote(String value) {
+ boolean needsQuotes = false;
+
+ // check to see if we actually have to quote this thing
+ int length = value.length();
+ for(int i = 0; (i < length) && !needsQuotes; ++i) {
+ needsQuotes = !isTokenChar(value.charAt(i));
+ }
+
+ if(needsQuotes) {
+ StringBuilder buffer = new StringBuilder((int)(length * 1.5));
+
+ // add the initial quote
+ buffer.append('"');
+
+ // add the properly escaped text
+ for(int i = 0; i < length; ++i) {
+ char c = value.charAt(i);
+ if((c == '\\') || (c == '"')) {
+ buffer.append('\\');
+ }
+ buffer.append(c);
+ }
+
+ // add the closing quote
+ buffer.append('"');
+
+ return buffer.toString();
+ }
+ else
+ {
+ return value;
+ }
+ }
+
+ /**
+ * A routine that knows how to strip the quotes and escape sequences from the given value.
+ */
+ private static String unquote(String value) {
+ int valueLength = value.length();
+ StringBuilder buffer = new StringBuilder(valueLength);
+
+ boolean escaped = false;
+ for(int i = 0; i < valueLength; ++i) {
+ char currentChar = value.charAt(i);
+ if(!escaped && (currentChar != '\\')) {
+ buffer.append(currentChar);
+ } else if(escaped) {
+ buffer.append(currentChar);
+ escaped = false;
+ } else {
+ escaped = true;
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * A string that holds all the special chars.
+ */
+ private static final String TSPECIALS = "()<>@,;:\\\"/[]?=";
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/MimeTypeParseException.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1997, 2006, 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;
+
+
+/**
+ * A class to encapsulate MimeType parsing related exceptions
+ *
+ * @serial exclude
+ * @since 1.3
+ */
+public class MimeTypeParseException extends Exception {
+
+ // use serialVersionUID from JDK 1.2.2 for interoperability
+ private static final long serialVersionUID = -5604407764691570741L;
+
+ /**
+ * Constructs a MimeTypeParseException with no specified detail message.
+ */
+ public MimeTypeParseException() {
+ super();
+ }
+
+ /**
+ * Constructs a MimeTypeParseException with the specified detail message.
+ *
+ * @param s the detail message.
+ */
+ public MimeTypeParseException(String s) {
+ super(s);
+ }
+} // class MimeTypeParseException
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/StringSelection.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,143 @@
+/*
+ * 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 java.io.*;
+
+
+/**
+ * A <code>Transferable</code> which implements the capability required
+ * to transfer a <code>String</code>.
+ *
+ * This <code>Transferable</code> properly supports
+ * <code>DataFlavor.stringFlavor</code>
+ * and all equivalent flavors. Support for
+ * <code>DataFlavor.plainTextFlavor</code>
+ * and all equivalent flavors is <b>deprecated</b>. No other
+ * <code>DataFlavor</code>s are supported.
+ *
+ * @see java.awt.datatransfer.DataFlavor#stringFlavor
+ * @see java.awt.datatransfer.DataFlavor#plainTextFlavor
+ */
+public class StringSelection implements Transferable, ClipboardOwner {
+
+ private static final int STRING = 0;
+ private static final int PLAIN_TEXT = 1;
+
+ @SuppressWarnings("deprecation")
+ private static final DataFlavor[] flavors = {
+ DataFlavor.stringFlavor,
+ DataFlavor.plainTextFlavor // deprecated
+ };
+
+ private String data;
+
+ /**
+ * Creates a <code>Transferable</code> capable of transferring
+ * the specified <code>String</code>.
+ * @param data the string to be transferred
+ */
+ public StringSelection(String data) {
+ this.data = data;
+ }
+
+ /**
+ * Returns an array of flavors in which this <code>Transferable</code>
+ * can provide the data. <code>DataFlavor.stringFlavor</code>
+ * is properly supported.
+ * Support for <code>DataFlavor.plainTextFlavor</code> is
+ * <b>deprecated</b>.
+ *
+ * @return an array of length two, whose elements are <code>DataFlavor.
+ * stringFlavor</code> and <code>DataFlavor.plainTextFlavor</code>
+ */
+ public DataFlavor[] getTransferDataFlavors() {
+ // returning flavors itself would allow client code to modify
+ // our internal behavior
+ return flavors.clone();
+ }
+
+ /**
+ * Returns whether the requested flavor is supported by this
+ * <code>Transferable</code>.
+ *
+ * @param flavor the requested flavor for the data
+ * @return true if <code>flavor</code> is equal to
+ * <code>DataFlavor.stringFlavor</code> or
+ * <code>DataFlavor.plainTextFlavor</code>; false if <code>flavor</code>
+ * is not one of the above flavors
+ * @throws NullPointerException if flavor is <code>null</code>
+ */
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ // JCK Test StringSelection0003: if 'flavor' is null, throw NPE
+ for (int i = 0; i < flavors.length; i++) {
+ if (flavor.equals(flavors[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the <code>Transferable</code>'s data in the requested
+ * <code>DataFlavor</code> if possible. If the desired flavor is
+ * <code>DataFlavor.stringFlavor</code>, or an equivalent flavor,
+ * the <code>String</code> representing the selection is
+ * returned. If the desired flavor is
+ * <code>DataFlavor.plainTextFlavor</code>,
+ * or an equivalent flavor, a <code>Reader</code> is returned.
+ * <b>Note:</b> The behavior of this method for
+ * <code>DataFlavor.plainTextFlavor</code>
+ * and equivalent <code>DataFlavor</code>s is inconsistent with the
+ * definition of <code>DataFlavor.plainTextFlavor</code>.
+ *
+ * @param flavor the requested flavor for the data
+ * @return the data in the requested flavor, as outlined above
+ * @throws UnsupportedFlavorException if the requested data flavor is
+ * not equivalent to either <code>DataFlavor.stringFlavor</code>
+ * or <code>DataFlavor.plainTextFlavor</code>
+ * @throws IOException if an IOException occurs while retrieving the data.
+ * By default, StringSelection never throws this exception, but a
+ * subclass may.
+ * @throws NullPointerException if flavor is <code>null</code>
+ * @see java.io.Reader
+ */
+ public Object getTransferData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException
+ {
+ // JCK Test StringSelection0007: if 'flavor' is null, throw NPE
+ if (flavor.equals(flavors[STRING])) {
+ return (Object)data;
+ } else if (flavor.equals(flavors[PLAIN_TEXT])) {
+ return new StringReader(data == null ? "" : data);
+ } else {
+ throw new UnsupportedFlavorException(flavor);
+ }
+ }
+
+ public void lostOwnership(Clipboard clipboard, Transferable contents) {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/SystemFlavorMap.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,1094 @@
+/*
+ * Copyright (c) 1997, 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.datatransfer.DesktopDatatransferService;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * The SystemFlavorMap is a configurable map between "natives" (Strings), which
+ * correspond to platform-specific data formats, and "flavors" (DataFlavors),
+ * which correspond to platform-independent MIME types. This mapping is used
+ * by the data transfer subsystem to transfer data between Java and native
+ * applications, and between Java applications in separate VMs.
+ *
+ * @since 1.2
+ */
+public final class SystemFlavorMap implements FlavorMap, FlavorTable {
+
+ /**
+ * Constant prefix used to tag Java types converted to native platform
+ * type.
+ */
+ private static String JavaMIME = "JAVA_DATAFLAVOR:";
+
+ private static final Object FLAVOR_MAP_KEY = new Object();
+
+ /**
+ * The list of valid, decoded text flavor representation classes, in order
+ * from best to worst.
+ */
+ private static final String[] UNICODE_TEXT_CLASSES = {
+ "java.io.Reader", "java.lang.String", "java.nio.CharBuffer", "\"[C\""
+ };
+
+ /**
+ * The list of valid, encoded text flavor representation classes, in order
+ * from best to worst.
+ */
+ private static final String[] ENCODED_TEXT_CLASSES = {
+ "java.io.InputStream", "java.nio.ByteBuffer", "\"[B\""
+ };
+
+ /**
+ * A String representing text/plain MIME type.
+ */
+ private static final String TEXT_PLAIN_BASE_TYPE = "text/plain";
+
+ /**
+ * A String representing text/html MIME type.
+ */
+ private static final String HTML_TEXT_BASE_TYPE = "text/html";
+
+ /**
+ * Maps native Strings to Lists of DataFlavors (or base type Strings for
+ * text DataFlavors).
+ * Do not use the field directly, use getNativeToFlavor() instead.
+ */
+ private final Map<String, LinkedHashSet<DataFlavor>> nativeToFlavor = new HashMap<>();
+
+ /**
+ * Accessor to nativeToFlavor map. Since we use lazy initialization we must
+ * use this accessor instead of direct access to the field which may not be
+ * initialized yet. This method will initialize the field if needed.
+ *
+ * @return nativeToFlavor
+ */
+ private Map<String, LinkedHashSet<DataFlavor>> getNativeToFlavor() {
+ if (!isMapInitialized) {
+ initSystemFlavorMap();
+ }
+ return nativeToFlavor;
+ }
+
+ /**
+ * Maps DataFlavors (or base type Strings for text DataFlavors) to Lists of
+ * native Strings.
+ * Do not use the field directly, use getFlavorToNative() instead.
+ */
+ private final Map<DataFlavor, LinkedHashSet<String>> flavorToNative = new HashMap<>();
+
+ /**
+ * Accessor to flavorToNative map. Since we use lazy initialization we must
+ * use this accessor instead of direct access to the field which may not be
+ * initialized yet. This method will initialize the field if needed.
+ *
+ * @return flavorToNative
+ */
+ private synchronized Map<DataFlavor, LinkedHashSet<String>> getFlavorToNative() {
+ if (!isMapInitialized) {
+ initSystemFlavorMap();
+ }
+ return flavorToNative;
+ }
+
+ /**
+ * Maps a text DataFlavor primary mime-type to the native. Used only to store
+ * standard mappings registered in the flavormap.properties
+ * Do not use this field directly, use getTextTypeToNative() instead.
+ */
+ private Map<String, LinkedHashSet<String>> textTypeToNative = new HashMap<>();
+
+ /**
+ * Shows if the object has been initialized.
+ */
+ private boolean isMapInitialized = false;
+
+ /**
+ * An accessor to textTypeToNative map. Since we use lazy initialization we
+ * must use this accessor instead of direct access to the field which may not
+ * be initialized yet. This method will initialize the field if needed.
+ *
+ * @return textTypeToNative
+ */
+ private synchronized Map<String, LinkedHashSet<String>> getTextTypeToNative() {
+ if (!isMapInitialized) {
+ initSystemFlavorMap();
+ // From this point the map should not be modified
+ textTypeToNative = Collections.unmodifiableMap(textTypeToNative);
+ }
+ return textTypeToNative;
+ }
+
+ /**
+ * Caches the result of getNativesForFlavor(). Maps DataFlavors to
+ * SoftReferences which reference LinkedHashSet of String natives.
+ */
+ private final SoftCache<DataFlavor, String> nativesForFlavorCache = new SoftCache<>();
+
+ /**
+ * Caches the result getFlavorsForNative(). Maps String natives to
+ * SoftReferences which reference LinkedHashSet of DataFlavors.
+ */
+ private final SoftCache<String, DataFlavor> flavorsForNativeCache = new SoftCache<>();
+
+ /**
+ * Dynamic mapping generation used for text mappings should not be applied
+ * to the DataFlavors and String natives for which the mappings have been
+ * explicitly specified with setFlavorsForNative() or
+ * setNativesForFlavor(). This keeps all such keys.
+ */
+ private Set<Object> disabledMappingGenerationKeys = new HashSet<>();
+
+ /**
+ * Returns the default FlavorMap for this thread's ClassLoader.
+ *
+ * @return the default FlavorMap for this thread's ClassLoader
+ */
+ public static FlavorMap getDefaultFlavorMap() {
+ return DataFlavorUtil.getDesktopService().getFlavorMap(SystemFlavorMap::new);
+ }
+
+ private SystemFlavorMap() {
+ }
+
+ /**
+ * Initializes a SystemFlavorMap by reading flavormap.properties
+ * For thread-safety must be called under lock on this.
+ */
+ private void initSystemFlavorMap() {
+ if (isMapInitialized) {
+ return;
+ }
+ isMapInitialized = true;
+
+ InputStream is = SystemFlavorMap.class.getResourceAsStream("/sun/datatransfer/resources/flavormap.properties");
+ if (is == null) {
+ throw new InternalError("Default flavor mapping not found");
+ }
+
+ try (InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader reader = new BufferedReader(isr)) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ line = line.trim();
+ if (line.startsWith("#") || line.isEmpty()) continue;
+ while (line.endsWith("\\")) {
+ line = line.substring(0, line.length() - 1) + reader.readLine().trim();
+ }
+ int delimiterPosition = line.indexOf('=');
+ String key = line.substring(0, delimiterPosition).replaceAll("\\ ", " ");
+ String[] values = line.substring(delimiterPosition + 1, line.length()).split(",");
+ for (String value : values) {
+ try {
+ value = loadConvert(value);
+ MimeType mime = new MimeType(value);
+ if ("text".equals(mime.getPrimaryType())) {
+ String charset = mime.getParameter("charset");
+ if (DataFlavorUtil.doesSubtypeSupportCharset(mime.getSubType(), charset))
+ {
+ // We need to store the charset and eoln
+ // parameters, if any, so that the
+ // DataTransferer will have this information
+ // for conversion into the native format.
+ DesktopDatatransferService desktopService =
+ DataFlavorUtil.getDesktopService();
+ if (desktopService.isDesktopPresent()) {
+ desktopService.registerTextFlavorProperties(
+ key, charset,
+ mime.getParameter("eoln"),
+ mime.getParameter("terminators"));
+ }
+ }
+
+ // But don't store any of these parameters in the
+ // DataFlavor itself for any text natives (even
+ // non-charset ones). The SystemFlavorMap will
+ // synthesize the appropriate mappings later.
+ mime.removeParameter("charset");
+ mime.removeParameter("class");
+ mime.removeParameter("eoln");
+ mime.removeParameter("terminators");
+ value = mime.toString();
+ }
+ } catch (MimeTypeParseException e) {
+ e.printStackTrace();
+ continue;
+ }
+
+ DataFlavor flavor;
+ try {
+ flavor = new DataFlavor(value);
+ } catch (Exception e) {
+ try {
+ flavor = new DataFlavor(value, null);
+ } catch (Exception ee) {
+ ee.printStackTrace();
+ continue;
+ }
+ }
+
+ final LinkedHashSet<DataFlavor> dfs = new LinkedHashSet<>();
+ dfs.add(flavor);
+
+ if ("text".equals(flavor.getPrimaryType())) {
+ dfs.addAll(convertMimeTypeToDataFlavors(value));
+ store(flavor.mimeType.getBaseType(), key, getTextTypeToNative());
+ }
+
+ for (DataFlavor df : dfs) {
+ store(df, key, getFlavorToNative());
+ store(key, df, getNativeToFlavor());
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new InternalError("Error reading default flavor mapping", e);
+ }
+ }
+
+ // Copied from java.util.Properties
+ private static String loadConvert(String theString) {
+ char aChar;
+ int len = theString.length();
+ StringBuilder outBuffer = new StringBuilder(len);
+
+ for (int x = 0; x < len; ) {
+ aChar = theString.charAt(x++);
+ if (aChar == '\\') {
+ aChar = theString.charAt(x++);
+ if (aChar == 'u') {
+ // Read the xxxx
+ int value = 0;
+ for (int i = 0; i < 4; i++) {
+ aChar = theString.charAt(x++);
+ switch (aChar) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9': {
+ value = (value << 4) + aChar - '0';
+ break;
+ }
+ case 'a': case 'b': case 'c':
+ case 'd': case 'e': case 'f': {
+ value = (value << 4) + 10 + aChar - 'a';
+ break;
+ }
+ case 'A': case 'B': case 'C':
+ case 'D': case 'E': case 'F': {
+ value = (value << 4) + 10 + aChar - 'A';
+ break;
+ }
+ default: {
+ throw new IllegalArgumentException(
+ "Malformed \\uxxxx encoding.");
+ }
+ }
+ }
+ outBuffer.append((char)value);
+ } else {
+ if (aChar == 't') {
+ aChar = '\t';
+ } else if (aChar == 'r') {
+ aChar = '\r';
+ } else if (aChar == 'n') {
+ aChar = '\n';
+ } else if (aChar == 'f') {
+ aChar = '\f';
+ }
+ outBuffer.append(aChar);
+ }
+ } else {
+ outBuffer.append(aChar);
+ }
+ }
+ return outBuffer.toString();
+ }
+
+ /**
+ * Stores the listed object under the specified hash key in map. Unlike a
+ * standard map, the listed object will not replace any object already at
+ * the appropriate Map location, but rather will be appended to a List
+ * stored in that location.
+ */
+ private <H, L> void store(H hashed, L listed, Map<H, LinkedHashSet<L>> map) {
+ LinkedHashSet<L> list = map.get(hashed);
+ if (list == null) {
+ list = new LinkedHashSet<>(1);
+ map.put(hashed, list);
+ }
+ if (!list.contains(listed)) {
+ list.add(listed);
+ }
+ }
+
+ /**
+ * Semantically equivalent to 'nativeToFlavor.get(nat)'. This method
+ * handles the case where 'nat' is not found in 'nativeToFlavor'. In that
+ * case, a new DataFlavor is synthesized, stored, and returned, if and
+ * only if the specified native is encoded as a Java MIME type.
+ */
+ private LinkedHashSet<DataFlavor> nativeToFlavorLookup(String nat) {
+ LinkedHashSet<DataFlavor> flavors = getNativeToFlavor().get(nat);
+
+ if (nat != null && !disabledMappingGenerationKeys.contains(nat)) {
+ DesktopDatatransferService desktopService = DataFlavorUtil.getDesktopService();
+ if (desktopService.isDesktopPresent()) {
+ LinkedHashSet<DataFlavor> platformFlavors =
+ desktopService.getPlatformMappingsForNative(nat);
+ if (!platformFlavors.isEmpty()) {
+ if (flavors != null) {
+ // Prepending the platform-specific mappings ensures
+ // that the flavors added with
+ // addFlavorForUnencodedNative() are at the end of
+ // list.
+ platformFlavors.addAll(flavors);
+ }
+ flavors = platformFlavors;
+ }
+ }
+ }
+
+ if (flavors == null && isJavaMIMEType(nat)) {
+ String decoded = decodeJavaMIMEType(nat);
+ DataFlavor flavor = null;
+
+ try {
+ flavor = new DataFlavor(decoded);
+ } catch (Exception e) {
+ System.err.println("Exception \"" + e.getClass().getName() +
+ ": " + e.getMessage() +
+ "\"while constructing DataFlavor for: " +
+ decoded);
+ }
+
+ if (flavor != null) {
+ flavors = new LinkedHashSet<>(1);
+ getNativeToFlavor().put(nat, flavors);
+ flavors.add(flavor);
+ flavorsForNativeCache.remove(nat);
+
+ LinkedHashSet<String> natives = getFlavorToNative().get(flavor);
+ if (natives == null) {
+ natives = new LinkedHashSet<>(1);
+ getFlavorToNative().put(flavor, natives);
+ }
+ natives.add(nat);
+ nativesForFlavorCache.remove(flavor);
+ }
+ }
+
+ return (flavors != null) ? flavors : new LinkedHashSet<>(0);
+ }
+
+ /**
+ * Semantically equivalent to 'flavorToNative.get(flav)'. This method
+ * handles the case where 'flav' is not found in 'flavorToNative' depending
+ * on the value of passes 'synthesize' parameter. If 'synthesize' is
+ * SYNTHESIZE_IF_NOT_FOUND a native is synthesized, stored, and returned by
+ * encoding the DataFlavor's MIME type. Otherwise an empty List is returned
+ * and 'flavorToNative' remains unaffected.
+ */
+ private LinkedHashSet<String> flavorToNativeLookup(final DataFlavor flav,
+ final boolean synthesize) {
+
+ LinkedHashSet<String> natives = getFlavorToNative().get(flav);
+
+ if (flav != null && !disabledMappingGenerationKeys.contains(flav)) {
+ DesktopDatatransferService desktopService = DataFlavorUtil.getDesktopService();
+ if (desktopService.isDesktopPresent()) {
+ LinkedHashSet<String> platformNatives =
+ desktopService.getPlatformMappingsForFlavor(flav);
+ if (!platformNatives.isEmpty()) {
+ if (natives != null) {
+ // Prepend the platform-specific mappings to ensure
+ // that the natives added with
+ // addUnencodedNativeForFlavor() are at the end of
+ // list.
+ platformNatives.addAll(natives);
+ }
+ natives = platformNatives;
+ }
+ }
+ }
+
+ if (natives == null) {
+ if (synthesize) {
+ String encoded = encodeDataFlavor(flav);
+ natives = new LinkedHashSet<>(1);
+ getFlavorToNative().put(flav, natives);
+ natives.add(encoded);
+
+ LinkedHashSet<DataFlavor> flavors = getNativeToFlavor().get(encoded);
+ if (flavors == null) {
+ flavors = new LinkedHashSet<>(1);
+ getNativeToFlavor().put(encoded, flavors);
+ }
+ flavors.add(flav);
+
+ nativesForFlavorCache.remove(flav);
+ flavorsForNativeCache.remove(encoded);
+ } else {
+ natives = new LinkedHashSet<>(0);
+ }
+ }
+
+ return new LinkedHashSet<>(natives);
+ }
+
+ /**
+ * Returns a <code>List</code> of <code>String</code> natives to which the
+ * specified <code>DataFlavor</code> can be translated by the data transfer
+ * subsystem. The <code>List</code> will be sorted from best native to
+ * worst. That is, the first native will best reflect data in the specified
+ * flavor to the underlying native platform.
+ * <p>
+ * If the specified <code>DataFlavor</code> is previously unknown to the
+ * data transfer subsystem and the data transfer subsystem is unable to
+ * translate this <code>DataFlavor</code> to any existing native, then
+ * invoking this method will establish a
+ * mapping in both directions between the specified <code>DataFlavor</code>
+ * and an encoded version of its MIME type as its native.
+ *
+ * @param flav the <code>DataFlavor</code> whose corresponding natives
+ * should be returned. If <code>null</code> is specified, all
+ * natives currently known to the data transfer subsystem are
+ * returned in a non-deterministic order.
+ * @return a <code>java.util.List</code> of <code>java.lang.String</code>
+ * objects which are platform-specific representations of platform-
+ * specific data formats
+ *
+ * @see #encodeDataFlavor
+ * @since 1.4
+ */
+ @Override
+ public synchronized List<String> getNativesForFlavor(DataFlavor flav) {
+ LinkedHashSet<String> retval = nativesForFlavorCache.check(flav);
+ if (retval != null) {
+ return new ArrayList<>(retval);
+ }
+
+ if (flav == null) {
+ retval = new LinkedHashSet<>(getNativeToFlavor().keySet());
+ } else if (disabledMappingGenerationKeys.contains(flav)) {
+ // In this case we shouldn't synthesize a native for this flavor,
+ // since its mappings were explicitly specified.
+ retval = flavorToNativeLookup(flav, false);
+ } else if (DataFlavorUtil.isFlavorCharsetTextType(flav)) {
+ retval = new LinkedHashSet<>(0);
+
+ // For text/* flavors, flavor-to-native mappings specified in
+ // flavormap.properties are stored per flavor's base type.
+ if ("text".equals(flav.getPrimaryType())) {
+ LinkedHashSet<String> textTypeNatives =
+ getTextTypeToNative().get(flav.mimeType.getBaseType());
+ if (textTypeNatives != null) {
+ retval.addAll(textTypeNatives);
+ }
+ }
+
+ // Also include text/plain natives, but don't duplicate Strings
+ LinkedHashSet<String> textTypeNatives =
+ getTextTypeToNative().get(TEXT_PLAIN_BASE_TYPE);
+ if (textTypeNatives != null) {
+ retval.addAll(textTypeNatives);
+ }
+
+ if (retval.isEmpty()) {
+ retval = flavorToNativeLookup(flav, true);
+ } else {
+ // In this branch it is guaranteed that natives explicitly
+ // listed for flav's MIME type were added with
+ // addUnencodedNativeForFlavor(), so they have lower priority.
+ retval.addAll(flavorToNativeLookup(flav, false));
+ }
+ } else if (DataFlavorUtil.isFlavorNoncharsetTextType(flav)) {
+ retval = getTextTypeToNative().get(flav.mimeType.getBaseType());
+
+ if (retval == null || retval.isEmpty()) {
+ retval = flavorToNativeLookup(flav, true);
+ } else {
+ // In this branch it is guaranteed that natives explicitly
+ // listed for flav's MIME type were added with
+ // addUnencodedNativeForFlavor(), so they have lower priority.
+ retval.addAll(flavorToNativeLookup(flav, false));
+ }
+ } else {
+ retval = flavorToNativeLookup(flav, true);
+ }
+
+ nativesForFlavorCache.put(flav, retval);
+ // Create a copy, because client code can modify the returned list.
+ return new ArrayList<>(retval);
+ }
+
+ /**
+ * Returns a <code>List</code> of <code>DataFlavor</code>s to which the
+ * specified <code>String</code> native can be translated by the data
+ * transfer subsystem. The <code>List</code> will be sorted from best
+ * <code>DataFlavor</code> to worst. That is, the first
+ * <code>DataFlavor</code> will best reflect data in the specified
+ * native to a Java application.
+ * <p>
+ * If the specified native is previously unknown to the data transfer
+ * subsystem, and that native has been properly encoded, then invoking this
+ * method will establish a mapping in both directions between the specified
+ * native and a <code>DataFlavor</code> whose MIME type is a decoded
+ * version of the native.
+ * <p>
+ * If the specified native is not a properly encoded native and the
+ * mappings for this native have not been altered with
+ * <code>setFlavorsForNative</code>, then the contents of the
+ * <code>List</code> is platform dependent, but <code>null</code>
+ * cannot be returned.
+ *
+ * @param nat the native whose corresponding <code>DataFlavor</code>s
+ * should be returned. If <code>null</code> is specified, all
+ * <code>DataFlavor</code>s currently known to the data transfer
+ * subsystem are returned in a non-deterministic order.
+ * @return a <code>java.util.List</code> of <code>DataFlavor</code>
+ * objects into which platform-specific data in the specified,
+ * platform-specific native can be translated
+ *
+ * @see #encodeJavaMIMEType
+ * @since 1.4
+ */
+ @Override
+ public synchronized List<DataFlavor> getFlavorsForNative(String nat) {
+ LinkedHashSet<DataFlavor> returnValue = flavorsForNativeCache.check(nat);
+ if (returnValue != null) {
+ return new ArrayList<>(returnValue);
+ } else {
+ returnValue = new LinkedHashSet<>();
+ }
+
+ if (nat == null) {
+ for (String n : getNativesForFlavor(null)) {
+ returnValue.addAll(getFlavorsForNative(n));
+ }
+ } else {
+ final LinkedHashSet<DataFlavor> flavors = nativeToFlavorLookup(nat);
+ if (disabledMappingGenerationKeys.contains(nat)) {
+ return new ArrayList<>(flavors);
+ }
+
+ final LinkedHashSet<DataFlavor> flavorsWithSynthesized =
+ nativeToFlavorLookup(nat);
+
+ for (DataFlavor df : flavorsWithSynthesized) {
+ returnValue.add(df);
+ if ("text".equals(df.getPrimaryType())) {
+ String baseType = df.mimeType.getBaseType();
+ returnValue.addAll(convertMimeTypeToDataFlavors(baseType));
+ }
+ }
+ }
+ flavorsForNativeCache.put(nat, returnValue);
+ return new ArrayList<>(returnValue);
+ }
+
+ @SuppressWarnings("deprecation")
+ private static Set<DataFlavor> convertMimeTypeToDataFlavors(
+ final String baseType) {
+
+ final Set<DataFlavor> returnValue = new LinkedHashSet<>();
+
+ String subType = null;
+
+ try {
+ final MimeType mimeType = new MimeType(baseType);
+ subType = mimeType.getSubType();
+ } catch (MimeTypeParseException mtpe) {
+ // Cannot happen, since we checked all mappings
+ // on load from flavormap.properties.
+ }
+
+ if (DataFlavorUtil.doesSubtypeSupportCharset(subType, null)) {
+ if (TEXT_PLAIN_BASE_TYPE.equals(baseType))
+ {
+ returnValue.add(DataFlavor.stringFlavor);
+ }
+
+ for (String unicodeClassName : UNICODE_TEXT_CLASSES) {
+ final String mimeType = baseType + ";charset=Unicode;class=" +
+ unicodeClassName;
+
+ final LinkedHashSet<String> mimeTypes =
+ handleHtmlMimeTypes(baseType, mimeType);
+ for (String mt : mimeTypes) {
+ DataFlavor toAdd = null;
+ try {
+ toAdd = new DataFlavor(mt);
+ } catch (ClassNotFoundException cannotHappen) {
+ }
+ returnValue.add(toAdd);
+ }
+ }
+
+ for (String charset : DataFlavorUtil.standardEncodings()) {
+
+ for (String encodedTextClass : ENCODED_TEXT_CLASSES) {
+ final String mimeType =
+ baseType + ";charset=" + charset +
+ ";class=" + encodedTextClass;
+
+ final LinkedHashSet<String> mimeTypes =
+ handleHtmlMimeTypes(baseType, mimeType);
+
+ for (String mt : mimeTypes) {
+
+ DataFlavor df = null;
+
+ try {
+ df = new DataFlavor(mt);
+ // Check for equality to plainTextFlavor so
+ // that we can ensure that the exact charset of
+ // plainTextFlavor, not the canonical charset
+ // or another equivalent charset with a
+ // different name, is used.
+ if (df.equals(DataFlavor.plainTextFlavor)) {
+ df = DataFlavor.plainTextFlavor;
+ }
+ } catch (ClassNotFoundException cannotHappen) {
+ }
+
+ returnValue.add(df);
+ }
+ }
+ }
+
+ if (TEXT_PLAIN_BASE_TYPE.equals(baseType))
+ {
+ returnValue.add(DataFlavor.plainTextFlavor);
+ }
+ } else {
+ // Non-charset text natives should be treated as
+ // opaque, 8-bit data in any of its various
+ // representations.
+ for (String encodedTextClassName : ENCODED_TEXT_CLASSES) {
+ DataFlavor toAdd = null;
+ try {
+ toAdd = new DataFlavor(baseType +
+ ";class=" + encodedTextClassName);
+ } catch (ClassNotFoundException cannotHappen) {
+ }
+ returnValue.add(toAdd);
+ }
+ }
+ return returnValue;
+ }
+
+ private static final String [] htmlDocumentTypes =
+ new String [] {"all", "selection", "fragment"};
+
+ private static LinkedHashSet<String> handleHtmlMimeTypes(String baseType,
+ String mimeType) {
+
+ LinkedHashSet<String> returnValues = new LinkedHashSet<>();
+
+ if (HTML_TEXT_BASE_TYPE.equals(baseType)) {
+ for (String documentType : htmlDocumentTypes) {
+ returnValues.add(mimeType + ";document=" + documentType);
+ }
+ } else {
+ returnValues.add(mimeType);
+ }
+
+ return returnValues;
+ }
+
+ /**
+ * Returns a <code>Map</code> of the specified <code>DataFlavor</code>s to
+ * their most preferred <code>String</code> native. Each native value will
+ * be the same as the first native in the List returned by
+ * <code>getNativesForFlavor</code> for the specified flavor.
+ * <p>
+ * If a specified <code>DataFlavor</code> is previously unknown to the
+ * data transfer subsystem, then invoking this method will establish a
+ * mapping in both directions between the specified <code>DataFlavor</code>
+ * and an encoded version of its MIME type as its native.
+ *
+ * @param flavors an array of <code>DataFlavor</code>s which will be the
+ * key set of the returned <code>Map</code>. If <code>null</code> is
+ * specified, a mapping of all <code>DataFlavor</code>s known to the
+ * data transfer subsystem to their most preferred
+ * <code>String</code> natives will be returned.
+ * @return a <code>java.util.Map</code> of <code>DataFlavor</code>s to
+ * <code>String</code> natives
+ *
+ * @see #getNativesForFlavor
+ * @see #encodeDataFlavor
+ */
+ @Override
+ public synchronized Map<DataFlavor,String> getNativesForFlavors(DataFlavor[] flavors)
+ {
+ // Use getNativesForFlavor to generate extra natives for text flavors
+ // and stringFlavor
+
+ if (flavors == null) {
+ List<DataFlavor> flavor_list = getFlavorsForNative(null);
+ flavors = new DataFlavor[flavor_list.size()];
+ flavor_list.toArray(flavors);
+ }
+
+ Map<DataFlavor, String> retval = new HashMap<>(flavors.length, 1.0f);
+ for (DataFlavor flavor : flavors) {
+ List<String> natives = getNativesForFlavor(flavor);
+ String nat = (natives.isEmpty()) ? null : natives.get(0);
+ retval.put(flavor, nat);
+ }
+
+ return retval;
+ }
+
+ /**
+ * Returns a <code>Map</code> of the specified <code>String</code> natives
+ * to their most preferred <code>DataFlavor</code>. Each
+ * <code>DataFlavor</code> value will be the same as the first
+ * <code>DataFlavor</code> in the List returned by
+ * <code>getFlavorsForNative</code> for the specified native.
+ * <p>
+ * If a specified native is previously unknown to the data transfer
+ * subsystem, and that native has been properly encoded, then invoking this
+ * method will establish a mapping in both directions between the specified
+ * native and a <code>DataFlavor</code> whose MIME type is a decoded
+ * version of the native.
+ *
+ * @param natives an array of <code>String</code>s which will be the
+ * key set of the returned <code>Map</code>. If <code>null</code> is
+ * specified, a mapping of all supported <code>String</code> natives
+ * to their most preferred <code>DataFlavor</code>s will be
+ * returned.
+ * @return a <code>java.util.Map</code> of <code>String</code> natives to
+ * <code>DataFlavor</code>s
+ *
+ * @see #getFlavorsForNative
+ * @see #encodeJavaMIMEType
+ */
+ @Override
+ public synchronized Map<String,DataFlavor> getFlavorsForNatives(String[] natives)
+ {
+ // Use getFlavorsForNative to generate extra flavors for text natives
+ if (natives == null) {
+ List<String> nativesList = getNativesForFlavor(null);
+ natives = new String[nativesList.size()];
+ nativesList.toArray(natives);
+ }
+
+ Map<String, DataFlavor> retval = new HashMap<>(natives.length, 1.0f);
+ for (String aNative : natives) {
+ List<DataFlavor> flavors = getFlavorsForNative(aNative);
+ DataFlavor flav = (flavors.isEmpty())? null : flavors.get(0);
+ retval.put(aNative, flav);
+ }
+ return retval;
+ }
+
+ /**
+ * Adds a mapping from the specified <code>DataFlavor</code> (and all
+ * <code>DataFlavor</code>s equal to the specified <code>DataFlavor</code>)
+ * to the specified <code>String</code> native.
+ * Unlike <code>getNativesForFlavor</code>, the mapping will only be
+ * established in one direction, and the native will not be encoded. To
+ * establish a two-way mapping, call
+ * <code>addFlavorForUnencodedNative</code> as well. The new mapping will
+ * be of lower priority than any existing mapping.
+ * This method has no effect if a mapping from the specified or equal
+ * <code>DataFlavor</code> to the specified <code>String</code> native
+ * already exists.
+ *
+ * @param flav the <code>DataFlavor</code> key for the mapping
+ * @param nat the <code>String</code> native value for the mapping
+ * @throws NullPointerException if flav or nat is <code>null</code>
+ *
+ * @see #addFlavorForUnencodedNative
+ * @since 1.4
+ */
+ public synchronized void addUnencodedNativeForFlavor(DataFlavor flav,
+ String nat) {
+ Objects.requireNonNull(nat, "Null native not permitted");
+ Objects.requireNonNull(flav, "Null flavor not permitted");
+
+ LinkedHashSet<String> natives = getFlavorToNative().get(flav);
+ if (natives == null) {
+ natives = new LinkedHashSet<>(1);
+ getFlavorToNative().put(flav, natives);
+ }
+ natives.add(nat);
+ nativesForFlavorCache.remove(flav);
+ }
+
+ /**
+ * Discards the current mappings for the specified <code>DataFlavor</code>
+ * and all <code>DataFlavor</code>s equal to the specified
+ * <code>DataFlavor</code>, and creates new mappings to the
+ * specified <code>String</code> natives.
+ * Unlike <code>getNativesForFlavor</code>, the mappings will only be
+ * established in one direction, and the natives will not be encoded. To
+ * establish two-way mappings, call <code>setFlavorsForNative</code>
+ * as well. The first native in the array will represent the highest
+ * priority mapping. Subsequent natives will represent mappings of
+ * decreasing priority.
+ * <p>
+ * If the array contains several elements that reference equal
+ * <code>String</code> natives, this method will establish new mappings
+ * for the first of those elements and ignore the rest of them.
+ * <p>
+ * It is recommended that client code not reset mappings established by the
+ * data transfer subsystem. This method should only be used for
+ * application-level mappings.
+ *
+ * @param flav the <code>DataFlavor</code> key for the mappings
+ * @param natives the <code>String</code> native values for the mappings
+ * @throws NullPointerException if flav or natives is <code>null</code>
+ * or if natives contains <code>null</code> elements
+ *
+ * @see #setFlavorsForNative
+ * @since 1.4
+ */
+ public synchronized void setNativesForFlavor(DataFlavor flav,
+ String[] natives) {
+ Objects.requireNonNull(natives, "Null natives not permitted");
+ Objects.requireNonNull(flav, "Null flavors not permitted");
+
+ getFlavorToNative().remove(flav);
+ for (String aNative : natives) {
+ addUnencodedNativeForFlavor(flav, aNative);
+ }
+ disabledMappingGenerationKeys.add(flav);
+ nativesForFlavorCache.remove(flav);
+ }
+
+ /**
+ * Adds a mapping from a single <code>String</code> native to a single
+ * <code>DataFlavor</code>. Unlike <code>getFlavorsForNative</code>, the
+ * mapping will only be established in one direction, and the native will
+ * not be encoded. To establish a two-way mapping, call
+ * <code>addUnencodedNativeForFlavor</code> as well. The new mapping will
+ * be of lower priority than any existing mapping.
+ * This method has no effect if a mapping from the specified
+ * <code>String</code> native to the specified or equal
+ * <code>DataFlavor</code> already exists.
+ *
+ * @param nat the <code>String</code> native key for the mapping
+ * @param flav the <code>DataFlavor</code> value for the mapping
+ * @throws NullPointerException if nat or flav is <code>null</code>
+ *
+ * @see #addUnencodedNativeForFlavor
+ * @since 1.4
+ */
+ public synchronized void addFlavorForUnencodedNative(String nat,
+ DataFlavor flav) {
+ Objects.requireNonNull(nat, "Null native not permitted");
+ Objects.requireNonNull(flav, "Null flavor not permitted");
+
+ LinkedHashSet<DataFlavor> flavors = getNativeToFlavor().get(nat);
+ if (flavors == null) {
+ flavors = new LinkedHashSet<>(1);
+ getNativeToFlavor().put(nat, flavors);
+ }
+ flavors.add(flav);
+ flavorsForNativeCache.remove(nat);
+ }
+
+ /**
+ * Discards the current mappings for the specified <code>String</code>
+ * native, and creates new mappings to the specified
+ * <code>DataFlavor</code>s. Unlike <code>getFlavorsForNative</code>, the
+ * mappings will only be established in one direction, and the natives need
+ * not be encoded. To establish two-way mappings, call
+ * <code>setNativesForFlavor</code> as well. The first
+ * <code>DataFlavor</code> in the array will represent the highest priority
+ * mapping. Subsequent <code>DataFlavor</code>s will represent mappings of
+ * decreasing priority.
+ * <p>
+ * If the array contains several elements that reference equal
+ * <code>DataFlavor</code>s, this method will establish new mappings
+ * for the first of those elements and ignore the rest of them.
+ * <p>
+ * It is recommended that client code not reset mappings established by the
+ * data transfer subsystem. This method should only be used for
+ * application-level mappings.
+ *
+ * @param nat the <code>String</code> native key for the mappings
+ * @param flavors the <code>DataFlavor</code> values for the mappings
+ * @throws NullPointerException if nat or flavors is <code>null</code>
+ * or if flavors contains <code>null</code> elements
+ *
+ * @see #setNativesForFlavor
+ * @since 1.4
+ */
+ public synchronized void setFlavorsForNative(String nat,
+ DataFlavor[] flavors) {
+ Objects.requireNonNull(nat, "Null native not permitted");
+ Objects.requireNonNull(flavors, "Null flavors not permitted");
+
+ getNativeToFlavor().remove(nat);
+ for (DataFlavor flavor : flavors) {
+ addFlavorForUnencodedNative(nat, flavor);
+ }
+ disabledMappingGenerationKeys.add(nat);
+ flavorsForNativeCache.remove(nat);
+ }
+
+ /**
+ * Encodes a MIME type for use as a <code>String</code> native. The format
+ * of an encoded representation of a MIME type is implementation-dependent.
+ * The only restrictions are:
+ * <ul>
+ * <li>The encoded representation is <code>null</code> if and only if the
+ * MIME type <code>String</code> is <code>null</code>.</li>
+ * <li>The encoded representations for two non-<code>null</code> MIME type
+ * <code>String</code>s are equal if and only if these <code>String</code>s
+ * are equal according to <code>String.equals(Object)</code>.</li>
+ * </ul>
+ * <p>
+ * The reference implementation of this method returns the specified MIME
+ * type <code>String</code> prefixed with <code>JAVA_DATAFLAVOR:</code>.
+ *
+ * @param mimeType the MIME type to encode
+ * @return the encoded <code>String</code>, or <code>null</code> if
+ * mimeType is <code>null</code>
+ */
+ public static String encodeJavaMIMEType(String mimeType) {
+ return (mimeType != null)
+ ? JavaMIME + mimeType
+ : null;
+ }
+
+ /**
+ * Encodes a <code>DataFlavor</code> for use as a <code>String</code>
+ * native. The format of an encoded <code>DataFlavor</code> is
+ * implementation-dependent. The only restrictions are:
+ * <ul>
+ * <li>The encoded representation is <code>null</code> if and only if the
+ * specified <code>DataFlavor</code> is <code>null</code> or its MIME type
+ * <code>String</code> is <code>null</code>.</li>
+ * <li>The encoded representations for two non-<code>null</code>
+ * <code>DataFlavor</code>s with non-<code>null</code> MIME type
+ * <code>String</code>s are equal if and only if the MIME type
+ * <code>String</code>s of these <code>DataFlavor</code>s are equal
+ * according to <code>String.equals(Object)</code>.</li>
+ * </ul>
+ * <p>
+ * The reference implementation of this method returns the MIME type
+ * <code>String</code> of the specified <code>DataFlavor</code> prefixed
+ * with <code>JAVA_DATAFLAVOR:</code>.
+ *
+ * @param flav the <code>DataFlavor</code> to encode
+ * @return the encoded <code>String</code>, or <code>null</code> if
+ * flav is <code>null</code> or has a <code>null</code> MIME type
+ */
+ public static String encodeDataFlavor(DataFlavor flav) {
+ return (flav != null)
+ ? SystemFlavorMap.encodeJavaMIMEType(flav.getMimeType())
+ : null;
+ }
+
+ /**
+ * Returns whether the specified <code>String</code> is an encoded Java
+ * MIME type.
+ *
+ * @param str the <code>String</code> to test
+ * @return <code>true</code> if the <code>String</code> is encoded;
+ * <code>false</code> otherwise
+ */
+ public static boolean isJavaMIMEType(String str) {
+ return (str != null && str.startsWith(JavaMIME, 0));
+ }
+
+ /**
+ * Decodes a <code>String</code> native for use as a Java MIME type.
+ *
+ * @param nat the <code>String</code> to decode
+ * @return the decoded Java MIME type, or <code>null</code> if nat is not
+ * an encoded <code>String</code> native
+ */
+ public static String decodeJavaMIMEType(String nat) {
+ return (isJavaMIMEType(nat))
+ ? nat.substring(JavaMIME.length(), nat.length()).trim()
+ : null;
+ }
+
+ /**
+ * Decodes a <code>String</code> native for use as a
+ * <code>DataFlavor</code>.
+ *
+ * @param nat the <code>String</code> to decode
+ * @return the decoded <code>DataFlavor</code>, or <code>null</code> if
+ * nat is not an encoded <code>String</code> native
+ * @throws ClassNotFoundException if the class of the data flavor
+ * is not loaded
+ */
+ public static DataFlavor decodeDataFlavor(String nat)
+ throws ClassNotFoundException
+ {
+ String retval_str = SystemFlavorMap.decodeJavaMIMEType(nat);
+ return (retval_str != null)
+ ? new DataFlavor(retval_str)
+ : null;
+ }
+
+ private static final class SoftCache<K, V> {
+ Map<K, SoftReference<LinkedHashSet<V>>> cache;
+
+ public void put(K key, LinkedHashSet<V> value) {
+ if (cache == null) {
+ cache = new HashMap<>(1);
+ }
+ cache.put(key, new SoftReference<>(value));
+ }
+
+ public void remove(K key) {
+ if (cache == null) return;
+ cache.remove(null);
+ cache.remove(key);
+ }
+
+ public LinkedHashSet<V> check(K key) {
+ if (cache == null) return null;
+ SoftReference<LinkedHashSet<V>> ref = cache.get(key);
+ if (ref != null) {
+ return ref.get();
+ }
+ return null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/Transferable.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,74 @@
+/*
+ * 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 java.io.IOException;
+
+/**
+ * Defines the interface for classes that can be used to provide data
+ * for a transfer operation.
+ * <p>
+ * For information on using data transfer with Swing, see
+ * <a href="http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html">
+ * How to Use Drag and Drop and Data Transfer</a>,
+ * a section in <em>The Java Tutorial</em>, for more information.
+ *
+ * @author Amy Fowler
+ */
+
+public interface Transferable {
+
+ /**
+ * Returns an array of DataFlavor objects indicating the flavors the data
+ * can be provided in. The array should be ordered according to preference
+ * for providing the data (from most richly descriptive to least descriptive).
+ * @return an array of data flavors in which this data can be transferred
+ */
+ public DataFlavor[] getTransferDataFlavors();
+
+ /**
+ * Returns whether or not the specified data flavor is supported for
+ * this object.
+ * @param flavor the requested flavor for the data
+ * @return boolean indicating whether or not the data flavor is supported
+ */
+ public boolean isDataFlavorSupported(DataFlavor flavor);
+
+ /**
+ * Returns an object which represents the data to be transferred. The class
+ * of the object returned is defined by the representation class of the flavor.
+ *
+ * @param flavor the requested flavor for the data
+ * @return an object which represents the data to be transferred
+ * @see DataFlavor#getRepresentationClass
+ * @exception IOException if the data is no longer available
+ * in the requested flavor.
+ * @exception UnsupportedFlavorException if the requested data flavor is
+ * not supported.
+ */
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException;
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/UnsupportedFlavorException.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1996, 2000, 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;
+
+/**
+ * Signals that the requested data is not supported in this flavor.
+ * @see Transferable#getTransferData
+ *
+ * @author Amy Fowler
+ */
+public class UnsupportedFlavorException extends Exception {
+
+ /*
+ * JDK 1.1 serialVersionUID
+ */
+ private static final long serialVersionUID = 5383814944251665601L;
+
+ /**
+ * Constructs an UnsupportedFlavorException.
+ *
+ * @param flavor the flavor object which caused the exception. May
+ * be <code>null</code>.
+ */
+ public UnsupportedFlavorException(DataFlavor flavor) {
+ super((flavor != null) ? flavor.getHumanPresentableName() : null);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/package.html Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,64 @@
+<!--
+ Copyright (c) 1998, 2013, 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.
+-->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head><title></title></head>
+<body bgcolor="white">
+
+Provides interfaces and classes for transferring data
+between and within applications. It defines the notion of a
+"transferable" object, which is an object capable of being
+transferred between or within applications. An object identifies
+itself as being transferable by implementing the Transferable
+interface.
+<p>
+It also provides a clipboard mechanism, which is an object that
+temporarily holds a transferable object that can be transferred
+between or within an application. The clipboard is typically used
+for copy and paste operations. Although it is possible to create
+a clipboard to use within an application, most applications will
+use the system clipboard to ensure the data can be transferred
+across applications running on the platform.
+
+<!--
+<h2>Package Specification</h2>
+
+##### FILL IN ANY SPECS NEEDED BY JAVA COMPATIBILITY KIT #####
+<ul>
+ <li><a href="">##### REFER TO ANY FRAMEMAKER SPECIFICATION HERE #####</a>
+</ul>
+
+<h2>Related Documentation</h2>
+
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+ <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
+</ul>
+-->
+
+@since 1.1
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/sun/datatransfer/DataFlavorUtil.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,841 @@
+/*
+ * Copyright (c) 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 sun.datatransfer;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.FlavorMap;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.function.Supplier;
+
+
+/**
+ * Utility class with different datatransfer helper functions
+ *
+ * @see 1.9
+ */
+public class DataFlavorUtil {
+
+ private DataFlavorUtil() {
+ // Avoid instantiation
+ }
+
+ private static Comparator<String> getCharsetComparator() {
+ return CharsetComparator.INSTANCE;
+ }
+
+ public static Comparator<DataFlavor> getDataFlavorComparator() {
+ return DataFlavorComparator.INSTANCE;
+ }
+
+ public static Comparator<Long> getIndexOrderComparator(Map<Long, Integer> indexMap) {
+ return new IndexOrderComparator(indexMap);
+ }
+
+ public static Comparator<DataFlavor> getTextFlavorComparator() {
+ return TextFlavorComparator.INSTANCE;
+ }
+
+ /**
+ * Tracks whether a particular text/* MIME type supports the charset
+ * parameter. The Map is initialized with all of the standard MIME types
+ * listed in the DataFlavor.selectBestTextFlavor method comment. Additional
+ * entries may be added during the life of the JRE for text/<other> types.
+ */
+ private static final Map<String, Boolean> textMIMESubtypeCharsetSupport;
+
+ static {
+ Map<String, Boolean> tempMap = new HashMap<>(17);
+ tempMap.put("sgml", Boolean.TRUE);
+ tempMap.put("xml", Boolean.TRUE);
+ tempMap.put("html", Boolean.TRUE);
+ tempMap.put("enriched", Boolean.TRUE);
+ tempMap.put("richtext", Boolean.TRUE);
+ tempMap.put("uri-list", Boolean.TRUE);
+ tempMap.put("directory", Boolean.TRUE);
+ tempMap.put("css", Boolean.TRUE);
+ tempMap.put("calendar", Boolean.TRUE);
+ tempMap.put("plain", Boolean.TRUE);
+ tempMap.put("rtf", Boolean.FALSE);
+ tempMap.put("tab-separated-values", Boolean.FALSE);
+ tempMap.put("t140", Boolean.FALSE);
+ tempMap.put("rfc822-headers", Boolean.FALSE);
+ tempMap.put("parityfec", Boolean.FALSE);
+ textMIMESubtypeCharsetSupport = Collections.synchronizedMap(tempMap);
+ }
+
+ /**
+ * Lazy initialization of Standard Encodings.
+ */
+ private static class StandardEncodingsHolder {
+ private static final SortedSet<String> standardEncodings = load();
+
+ private static SortedSet<String> load() {
+ final SortedSet<String> tempSet = new TreeSet<>(getCharsetComparator().reversed());
+ tempSet.add("US-ASCII");
+ tempSet.add("ISO-8859-1");
+ tempSet.add("UTF-8");
+ tempSet.add("UTF-16BE");
+ tempSet.add("UTF-16LE");
+ tempSet.add("UTF-16");
+ tempSet.add(Charset.defaultCharset().name());
+ return Collections.unmodifiableSortedSet(tempSet);
+ }
+ }
+
+ /**
+ * Returns a {@code SortedSet} of Strings which are a total order of the standard
+ * character sets supported by the JRE. The ordering follows the same principles as
+ * {@link java.awt.datatransfer.DataFlavor#selectBestTextFlavor(java.awt.datatransfer.DataFlavor[])}.
+ * So as to avoid loading all available character converters, optional, non-standard,
+ * character sets are not included.
+ */
+ public static Set<String> standardEncodings() {
+ return StandardEncodingsHolder.standardEncodings;
+ }
+
+ /**
+ * Converts an arbitrary text encoding to its canonical name.
+ */
+ public static String canonicalName(String encoding) {
+ if (encoding == null) {
+ return null;
+ }
+ try {
+ return Charset.forName(encoding).name();
+ } catch (IllegalCharsetNameException icne) {
+ return encoding;
+ } catch (UnsupportedCharsetException uce) {
+ return encoding;
+ }
+ }
+
+ /**
+ * Tests only whether the flavor's MIME type supports the charset
+ * parameter. Must only be called for flavors with a primary type of
+ * "text".
+ */
+ public static boolean doesSubtypeSupportCharset(DataFlavor flavor) {
+ String subType = flavor.getSubType();
+ if (subType == null) {
+ return false;
+ }
+
+ Boolean support = textMIMESubtypeCharsetSupport.get(subType);
+
+ if (support != null) {
+ return support;
+ }
+
+ boolean ret_val = (flavor.getParameter("charset") != null);
+ textMIMESubtypeCharsetSupport.put(subType, ret_val);
+ return ret_val;
+ }
+ public static boolean doesSubtypeSupportCharset(String subType,
+ String charset)
+ {
+ Boolean support = textMIMESubtypeCharsetSupport.get(subType);
+
+ if (support != null) {
+ return support;
+ }
+
+ boolean ret_val = (charset != null);
+ textMIMESubtypeCharsetSupport.put(subType, ret_val);
+ return ret_val;
+ }
+
+
+ /**
+ * Returns whether this flavor is a text type which supports the
+ * 'charset' parameter.
+ */
+ public static boolean isFlavorCharsetTextType(DataFlavor flavor) {
+ // Although stringFlavor doesn't actually support the charset
+ // parameter (because its primary MIME type is not "text"), it should
+ // be treated as though it does. stringFlavor is semantically
+ // equivalent to "text/plain" data.
+ if (DataFlavor.stringFlavor.equals(flavor)) {
+ return true;
+ }
+
+ if (!"text".equals(flavor.getPrimaryType()) ||
+ !doesSubtypeSupportCharset(flavor))
+ {
+ return false;
+ }
+
+ Class<?> rep_class = flavor.getRepresentationClass();
+
+ if (flavor.isRepresentationClassReader() ||
+ String.class.equals(rep_class) ||
+ flavor.isRepresentationClassCharBuffer() ||
+ char[].class.equals(rep_class))
+ {
+ return true;
+ }
+
+ if (!(flavor.isRepresentationClassInputStream() ||
+ flavor.isRepresentationClassByteBuffer() ||
+ byte[].class.equals(rep_class))) {
+ return false;
+ }
+
+ String charset = flavor.getParameter("charset");
+
+ // null equals default encoding which is always supported
+ return (charset == null) || isEncodingSupported(charset);
+ }
+
+ /**
+ * Returns whether this flavor is a text type which does not support the
+ * 'charset' parameter.
+ */
+ public static boolean isFlavorNoncharsetTextType(DataFlavor flavor) {
+ if (!"text".equals(flavor.getPrimaryType()) || doesSubtypeSupportCharset(flavor)) {
+ return false;
+ }
+
+ return (flavor.isRepresentationClassInputStream() ||
+ flavor.isRepresentationClassByteBuffer() ||
+ byte[].class.equals(flavor.getRepresentationClass()));
+ }
+
+ /**
+ * If the specified flavor is a text flavor which supports the "charset"
+ * parameter, then this method returns that parameter, or the default
+ * charset if no such parameter was specified at construction. For non-
+ * text DataFlavors, and for non-charset text flavors, this method returns
+ * null.
+ */
+ public static String getTextCharset(DataFlavor flavor) {
+ if (!isFlavorCharsetTextType(flavor)) {
+ return null;
+ }
+
+ String encoding = flavor.getParameter("charset");
+
+ return (encoding != null) ? encoding : Charset.defaultCharset().name();
+ }
+
+ /**
+ * Determines whether this JRE can both encode and decode text in the
+ * specified encoding.
+ */
+ private static boolean isEncodingSupported(String encoding) {
+ if (encoding == null) {
+ return false;
+ }
+ try {
+ return Charset.isSupported(encoding);
+ } catch (IllegalCharsetNameException icne) {
+ return false;
+ }
+ }
+
+ /**
+ * Helper method to compare two objects by their Integer indices in the
+ * given map. If the map doesn't contain an entry for either of the
+ * objects, the fallback index will be used for the object instead.
+ *
+ * @param indexMap the map which maps objects into Integer indexes.
+ * @param obj1 the first object to be compared.
+ * @param obj2 the second object to be compared.
+ * @param fallbackIndex the Integer to be used as a fallback index.
+ * @return a negative integer, zero, or a positive integer as the
+ * first object is mapped to a less, equal to, or greater
+ * index than the second.
+ */
+ static <T> int compareIndices(Map<T, Integer> indexMap,
+ T obj1, T obj2,
+ Integer fallbackIndex) {
+ Integer index1 = indexMap.getOrDefault(obj1, fallbackIndex);
+ Integer index2 = indexMap.getOrDefault(obj2, fallbackIndex);
+ return index1.compareTo(index2);
+ }
+
+ /**
+ * An IndexedComparator which compares two String charsets. The comparison
+ * follows the rules outlined in DataFlavor.selectBestTextFlavor. In order
+ * to ensure that non-Unicode, non-ASCII, non-default charsets are sorted
+ * in alphabetical order, charsets are not automatically converted to their
+ * canonical forms.
+ */
+ private static class CharsetComparator implements Comparator<String> {
+ static final CharsetComparator INSTANCE = new CharsetComparator();
+
+ private static final Map<String, Integer> charsets;
+
+ private static final Integer DEFAULT_CHARSET_INDEX = 2;
+ private static final Integer OTHER_CHARSET_INDEX = 1;
+ private static final Integer WORST_CHARSET_INDEX = 0;
+ private static final Integer UNSUPPORTED_CHARSET_INDEX = Integer.MIN_VALUE;
+
+ private static final String UNSUPPORTED_CHARSET = "UNSUPPORTED";
+
+ static {
+ Map<String, Integer> charsetsMap = new HashMap<>(8, 1.0f);
+
+ // we prefer Unicode charsets
+ charsetsMap.put(canonicalName("UTF-16LE"), 4);
+ charsetsMap.put(canonicalName("UTF-16BE"), 5);
+ charsetsMap.put(canonicalName("UTF-8"), 6);
+ charsetsMap.put(canonicalName("UTF-16"), 7);
+
+ // US-ASCII is the worst charset supported
+ charsetsMap.put(canonicalName("US-ASCII"), WORST_CHARSET_INDEX);
+
+ charsetsMap.putIfAbsent(Charset.defaultCharset().name(), DEFAULT_CHARSET_INDEX);
+
+ charsetsMap.put(UNSUPPORTED_CHARSET, UNSUPPORTED_CHARSET_INDEX);
+
+ charsets = Collections.unmodifiableMap(charsetsMap);
+ }
+
+ /**
+ * Compares charsets. Returns a negative integer, zero, or a positive
+ * integer as the first charset is worse than, equal to, or better than
+ * the second.
+ * <p>
+ * Charsets are ordered according to the following rules:
+ * <ul>
+ * <li>All unsupported charsets are equal.
+ * <li>Any unsupported charset is worse than any supported charset.
+ * <li>Unicode charsets, such as "UTF-16", "UTF-8", "UTF-16BE" and
+ * "UTF-16LE", are considered best.
+ * <li>After them, platform default charset is selected.
+ * <li>"US-ASCII" is the worst of supported charsets.
+ * <li>For all other supported charsets, the lexicographically less
+ * one is considered the better.
+ * </ul>
+ *
+ * @param charset1 the first charset to be compared
+ * @param charset2 the second charset to be compared.
+ * @return a negative integer, zero, or a positive integer as the
+ * first argument is worse, equal to, or better than the
+ * second.
+ */
+ public int compare(String charset1, String charset2) {
+ charset1 = getEncoding(charset1);
+ charset2 = getEncoding(charset2);
+
+ int comp = compareIndices(charsets, charset1, charset2, OTHER_CHARSET_INDEX);
+
+ if (comp == 0) {
+ return charset2.compareTo(charset1);
+ }
+
+ return comp;
+ }
+
+ /**
+ * Returns encoding for the specified charset according to the
+ * following rules:
+ * <ul>
+ * <li>If the charset is <code>null</code>, then <code>null</code> will
+ * be returned.
+ * <li>Iff the charset specifies an encoding unsupported by this JRE,
+ * <code>UNSUPPORTED_CHARSET</code> will be returned.
+ * <li>If the charset specifies an alias name, the corresponding
+ * canonical name will be returned iff the charset is a known
+ * Unicode, ASCII, or default charset.
+ * </ul>
+ *
+ * @param charset the charset.
+ * @return an encoding for this charset.
+ */
+ static String getEncoding(String charset) {
+ if (charset == null) {
+ return null;
+ } else if (!isEncodingSupported(charset)) {
+ return UNSUPPORTED_CHARSET;
+ } else {
+ // Only convert to canonical form if the charset is one
+ // of the charsets explicitly listed in the known charsets
+ // map. This will happen only for Unicode, ASCII, or default
+ // charsets.
+ String canonicalName = canonicalName(charset);
+ return (charsets.containsKey(canonicalName))
+ ? canonicalName
+ : charset;
+ }
+ }
+ }
+
+ /**
+ * An IndexedComparator which compares two DataFlavors. For text flavors,
+ * the comparison follows the rules outlined in
+ * DataFlavor.selectBestTextFlavor. For non-text flavors, unknown
+ * application MIME types are preferred, followed by known
+ * application/x-java-* MIME types. Unknown application types are preferred
+ * because if the user provides his own data flavor, it will likely be the
+ * most descriptive one. For flavors which are otherwise equal, the
+ * flavors' string representation are compared in the alphabetical order.
+ */
+ private static class DataFlavorComparator implements Comparator<DataFlavor> {
+
+ static final DataFlavorComparator INSTANCE = new DataFlavorComparator();
+
+ private static final Map<String, Integer> exactTypes;
+ private static final Map<String, Integer> primaryTypes;
+ private static final Map<Class<?>, Integer> nonTextRepresentations;
+ private static final Map<String, Integer> textTypes;
+ private static final Map<Class<?>, Integer> decodedTextRepresentations;
+ private static final Map<Class<?>, Integer> encodedTextRepresentations;
+
+ private static final Integer UNKNOWN_OBJECT_LOSES = Integer.MIN_VALUE;
+ private static final Integer UNKNOWN_OBJECT_WINS = Integer.MAX_VALUE;
+
+ static {
+ {
+ Map<String, Integer> exactTypesMap = new HashMap<>(4, 1.0f);
+
+ // application/x-java-* MIME types
+ exactTypesMap.put("application/x-java-file-list", 0);
+ exactTypesMap.put("application/x-java-serialized-object", 1);
+ exactTypesMap.put("application/x-java-jvm-local-objectref", 2);
+ exactTypesMap.put("application/x-java-remote-object", 3);
+
+ exactTypes = Collections.unmodifiableMap(exactTypesMap);
+ }
+
+ {
+ Map<String, Integer> primaryTypesMap = new HashMap<>(1, 1.0f);
+
+ primaryTypesMap.put("application", 0);
+
+ primaryTypes = Collections.unmodifiableMap(primaryTypesMap);
+ }
+
+ {
+ Map<Class<?>, Integer> nonTextRepresentationsMap = new HashMap<>(3, 1.0f);
+
+ nonTextRepresentationsMap.put(java.io.InputStream.class, 0);
+ nonTextRepresentationsMap.put(java.io.Serializable.class, 1);
+
+ nonTextRepresentationsMap.put(RMI.remoteClass(), 2);
+
+ nonTextRepresentations = Collections.unmodifiableMap(nonTextRepresentationsMap);
+ }
+
+ {
+ Map<String, Integer> textTypesMap = new HashMap<>(16, 1.0f);
+
+ // plain text
+ textTypesMap.put("text/plain", 0);
+
+ // stringFlavor
+ textTypesMap.put("application/x-java-serialized-object", 1);
+
+ // misc
+ textTypesMap.put("text/calendar", 2);
+ textTypesMap.put("text/css", 3);
+ textTypesMap.put("text/directory", 4);
+ textTypesMap.put("text/parityfec", 5);
+ textTypesMap.put("text/rfc822-headers", 6);
+ textTypesMap.put("text/t140", 7);
+ textTypesMap.put("text/tab-separated-values", 8);
+ textTypesMap.put("text/uri-list", 9);
+
+ // enriched
+ textTypesMap.put("text/richtext", 10);
+ textTypesMap.put("text/enriched", 11);
+ textTypesMap.put("text/rtf", 12);
+
+ // markup
+ textTypesMap.put("text/html", 13);
+ textTypesMap.put("text/xml", 14);
+ textTypesMap.put("text/sgml", 15);
+
+ textTypes = Collections.unmodifiableMap(textTypesMap);
+ }
+
+ {
+ Map<Class<?>, Integer> decodedTextRepresentationsMap = new HashMap<>(4, 1.0f);
+
+ decodedTextRepresentationsMap.put(char[].class, 0);
+ decodedTextRepresentationsMap.put(CharBuffer.class, 1);
+ decodedTextRepresentationsMap.put(String.class, 2);
+ decodedTextRepresentationsMap.put(Reader.class, 3);
+
+ decodedTextRepresentations =
+ Collections.unmodifiableMap(decodedTextRepresentationsMap);
+ }
+
+ {
+ Map<Class<?>, Integer> encodedTextRepresentationsMap = new HashMap<>(3, 1.0f);
+
+ encodedTextRepresentationsMap.put(byte[].class, 0);
+ encodedTextRepresentationsMap.put(ByteBuffer.class, 1);
+ encodedTextRepresentationsMap.put(InputStream.class, 2);
+
+ encodedTextRepresentations =
+ Collections.unmodifiableMap(encodedTextRepresentationsMap);
+ }
+ }
+
+
+ public int compare(DataFlavor flavor1, DataFlavor flavor2) {
+ if (flavor1.equals(flavor2)) {
+ return 0;
+ }
+
+ int comp;
+
+ String primaryType1 = flavor1.getPrimaryType();
+ String subType1 = flavor1.getSubType();
+ String mimeType1 = primaryType1 + "/" + subType1;
+ Class<?> class1 = flavor1.getRepresentationClass();
+
+ String primaryType2 = flavor2.getPrimaryType();
+ String subType2 = flavor2.getSubType();
+ String mimeType2 = primaryType2 + "/" + subType2;
+ Class<?> class2 = flavor2.getRepresentationClass();
+
+ if (flavor1.isFlavorTextType() && flavor2.isFlavorTextType()) {
+ // First, compare MIME types
+ comp = compareIndices(textTypes, mimeType1, mimeType2, UNKNOWN_OBJECT_LOSES);
+ if (comp != 0) {
+ return comp;
+ }
+
+ // Only need to test one flavor because they both have the
+ // same MIME type. Also don't need to worry about accidentally
+ // passing stringFlavor because either
+ // 1. Both flavors are stringFlavor, in which case the
+ // equality test at the top of the function succeeded.
+ // 2. Only one flavor is stringFlavor, in which case the MIME
+ // type comparison returned a non-zero value.
+ if (doesSubtypeSupportCharset(flavor1)) {
+ // Next, prefer the decoded text representations of Reader,
+ // String, CharBuffer, and [C, in that order.
+ comp = compareIndices(decodedTextRepresentations, class1,
+ class2, UNKNOWN_OBJECT_LOSES);
+ if (comp != 0) {
+ return comp;
+ }
+
+ // Next, compare charsets
+ comp = CharsetComparator.INSTANCE.compare(getTextCharset(flavor1),
+ getTextCharset(flavor2));
+ if (comp != 0) {
+ return comp;
+ }
+ }
+
+ // Finally, prefer the encoded text representations of
+ // InputStream, ByteBuffer, and [B, in that order.
+ comp = compareIndices(encodedTextRepresentations, class1,
+ class2, UNKNOWN_OBJECT_LOSES);
+ if (comp != 0) {
+ return comp;
+ }
+ } else {
+ // First, prefer application types.
+ comp = compareIndices(primaryTypes, primaryType1, primaryType2,
+ UNKNOWN_OBJECT_LOSES);
+ if (comp != 0) {
+ return comp;
+ }
+
+ // Next prefer text types
+ if (flavor1.isFlavorTextType()) {
+ return 1;
+ }
+
+ if (flavor2.isFlavorTextType()) {
+ return -1;
+ }
+
+ // Next, look for application/x-java-* types. Prefer unknown
+ // MIME types because if the user provides his own data flavor,
+ // it will likely be the most descriptive one.
+ comp = compareIndices(exactTypes, mimeType1, mimeType2,
+ UNKNOWN_OBJECT_WINS);
+ if (comp != 0) {
+ return comp;
+ }
+
+ // Finally, prefer the representation classes of Remote,
+ // Serializable, and InputStream, in that order.
+ comp = compareIndices(nonTextRepresentations, class1, class2,
+ UNKNOWN_OBJECT_LOSES);
+ if (comp != 0) {
+ return comp;
+ }
+ }
+
+ // The flavours are not equal but still not distinguishable.
+ // Compare String representations in alphabetical order
+ return flavor1.getMimeType().compareTo(flavor2.getMimeType());
+ }
+ }
+
+ /*
+ * Given the Map that maps objects to Integer indices and a boolean value,
+ * this Comparator imposes a direct or reverse order on set of objects.
+ * <p>
+ * If the specified boolean value is SELECT_BEST, the Comparator imposes the
+ * direct index-based order: an object A is greater than an object B if and
+ * only if the index of A is greater than the index of B. An object that
+ * doesn't have an associated index is less or equal than any other object.
+ * <p>
+ * If the specified boolean value is SELECT_WORST, the Comparator imposes the
+ * reverse index-based order: an object A is greater than an object B if and
+ * only if A is less than B with the direct index-based order.
+ */
+ private static class IndexOrderComparator implements Comparator<Long> {
+ private final Map<Long, Integer> indexMap;
+ private static final Integer FALLBACK_INDEX = Integer.MIN_VALUE;
+
+ public IndexOrderComparator(Map<Long, Integer> indexMap) {
+ this.indexMap = indexMap;
+ }
+
+ public int compare(Long obj1, Long obj2) {
+ return compareIndices(indexMap, obj1, obj2, FALLBACK_INDEX);
+ }
+ }
+
+ private static class TextFlavorComparator extends DataFlavorComparator {
+
+ static final TextFlavorComparator INSTANCE = new TextFlavorComparator();
+ /**
+ * Compares two <code>DataFlavor</code> objects. Returns a negative
+ * integer, zero, or a positive integer as the first
+ * <code>DataFlavor</code> is worse than, equal to, or better than the
+ * second.
+ * <p>
+ * <code>DataFlavor</code>s are ordered according to the rules outlined
+ * for <code>selectBestTextFlavor</code>.
+ *
+ * @param flavor1 the first <code>DataFlavor</code> to be compared
+ * @param flavor2 the second <code>DataFlavor</code> to be compared
+ * @return a negative integer, zero, or a positive integer as the first
+ * argument is worse, equal to, or better than the second
+ * @throws ClassCastException if either of the arguments is not an
+ * instance of <code>DataFlavor</code>
+ * @throws NullPointerException if either of the arguments is
+ * <code>null</code>
+ *
+ * @see java.awt.datatransfer.DataFlavor#selectBestTextFlavor
+ */
+ public int compare(DataFlavor flavor1, DataFlavor flavor2) {
+ if (flavor1.isFlavorTextType()) {
+ if (flavor2.isFlavorTextType()) {
+ return super.compare(flavor1, flavor2);
+ } else {
+ return 1;
+ }
+ } else if (flavor2.isFlavorTextType()) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ /**
+ * A fallback implementation of {@link sun.datatransfer.DesktopDatatransferService}
+ * used if there is no desktop.
+ */
+ private static final class DefaultDesktopDatatransferService implements DesktopDatatransferService {
+ static final DesktopDatatransferService INSTANCE = getDesktopService();
+
+ private static DesktopDatatransferService getDesktopService() {
+ ServiceLoader<DesktopDatatransferService> loader =
+ ServiceLoader.load(DesktopDatatransferService.class, null);
+ Iterator<DesktopDatatransferService> iterator = loader.iterator();
+ if (iterator.hasNext()) {
+ return iterator.next();
+ } else {
+ return new DefaultDesktopDatatransferService();
+ }
+ }
+
+ /**
+ * System singleton FlavorTable.
+ * Only used if there is no desktop
+ * to provide an appropriate FlavorMap.
+ */
+ private volatile FlavorMap flavorMap;
+
+ @Override
+ public void invokeOnEventThread(Runnable r) {
+ r.run();
+ }
+
+ @Override
+ public String getDefaultUnicodeEncoding() {
+ return StandardCharsets.UTF_8.name();
+ }
+
+ @Override
+ public FlavorMap getFlavorMap(Supplier<FlavorMap> supplier) {
+ FlavorMap map = flavorMap;
+ if (map == null) {
+ synchronized (this) {
+ map = flavorMap;
+ if (map == null) {
+ flavorMap = map = supplier.get();
+ }
+ }
+ }
+ return map;
+ }
+
+ @Override
+ public boolean isDesktopPresent() {
+ return false;
+ }
+
+ @Override
+ public LinkedHashSet<DataFlavor> getPlatformMappingsForNative(String nat) {
+ return new LinkedHashSet<>();
+ }
+
+ @Override
+ public LinkedHashSet<String> getPlatformMappingsForFlavor(DataFlavor df) {
+ return new LinkedHashSet<>();
+ }
+
+ @Override
+ public void registerTextFlavorProperties(String nat, String charset,
+ String eoln, String terminators) {
+ // Not needed if desktop module is absent
+ }
+ }
+
+ public static DesktopDatatransferService getDesktopService() {
+ return DefaultDesktopDatatransferService.INSTANCE;
+ }
+
+ /**
+ * A class that provides access to java.rmi.Remote and java.rmi.MarshalledObject
+ * without creating a static dependency.
+ */
+ public static class RMI {
+ private static final Class<?> remoteClass = getClass("java.rmi.Remote");
+ private static final Class<?> marshallObjectClass = getClass("java.rmi.MarshalledObject");
+ private static final Constructor<?> marshallCtor = getConstructor(marshallObjectClass, Object.class);
+ private static final Method marshallGet = getMethod(marshallObjectClass, "get");
+
+ private static Class<?> getClass(String name) {
+ try {
+ return Class.forName(name, true, null);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ private static Constructor<?> getConstructor(Class<?> c, Class<?>... types) {
+ try {
+ return (c == null) ? null : c.getDeclaredConstructor(types);
+ } catch (NoSuchMethodException x) {
+ throw new AssertionError(x);
+ }
+ }
+
+ private static Method getMethod(Class<?> c, String name, Class<?>... types) {
+ try {
+ return (c == null) ? null : c.getMethod(name, types);
+ } catch (NoSuchMethodException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /**
+ * Returns java.rmi.Remote.class if RMI is present; otherwise {@code null}.
+ */
+ static Class<?> remoteClass() {
+ return remoteClass;
+ }
+
+ /**
+ * Returns {@code true} if the given class is java.rmi.Remote.
+ */
+ public static boolean isRemote(Class<?> c) {
+ return (remoteClass != null) && remoteClass.isAssignableFrom(c);
+ }
+
+ /**
+ * Returns a new MarshalledObject containing the serialized representation
+ * of the given object.
+ */
+ public static Object newMarshalledObject(Object obj) throws IOException {
+ try {
+ return marshallCtor == null ? null : marshallCtor.newInstance(obj);
+ } catch (InstantiationException | IllegalAccessException x) {
+ throw new AssertionError(x);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ if (cause instanceof IOException)
+ throw (IOException) cause;
+ throw new AssertionError(x);
+ }
+ }
+
+ /**
+ * Returns a new copy of the contained marshalled object.
+ */
+ public static Object getMarshalledObject(Object obj)
+ throws IOException, ClassNotFoundException {
+ try {
+ return marshallGet == null ? null : marshallGet.invoke(obj);
+ } catch (IllegalAccessException x) {
+ throw new AssertionError(x);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ if (cause instanceof IOException)
+ throw (IOException) cause;
+ if (cause instanceof ClassNotFoundException)
+ throw (ClassNotFoundException) cause;
+ throw new AssertionError(x);
+ }
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/share/classes/sun/datatransfer/DesktopDatatransferService.java Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 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 sun.datatransfer;
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.FlavorMap;
+import java.util.LinkedHashSet;
+import java.util.function.Supplier;
+
+/**
+ * Contains services which desktop provides to the datatransfer system
+ * to enrich it's functionality
+ *
+ * @author Petr Pchelko
+ * @since 1.9
+ */
+public interface DesktopDatatransferService {
+
+ /**
+ * If desktop is present - invokes a {@code Runnable} on
+ * the event dispatch thread. Otherwise invokes a {@code run()}
+ * method directly.
+ *
+ * @param r a {@code Runnable} to invoke
+ */
+ void invokeOnEventThread(Runnable r);
+
+ /**
+ * Get a platform-dependent default unicode encoding to use in
+ * datatransfer system.
+ *
+ * @return default unicode encoding
+ */
+ String getDefaultUnicodeEncoding();
+
+ /**
+ * Takes an appropriate {@code FlavorMap} from the desktop.
+ * If no appropriate table is found - uses a provided supplier to
+ * instantiate a table. If the desktop is absent - creates and returns
+ * a system singleton.
+ *
+ * @param supplier a constructor that should be used to create a new instance of
+ * the {@code FlavorMap}
+ * @return a {@code FlavorMap}
+ */
+ FlavorMap getFlavorMap(Supplier<FlavorMap> supplier);
+
+ /**
+ * Checks if desktop is present
+ *
+ * @return {@code true} is the desktop is present
+ */
+ boolean isDesktopPresent();
+
+ /**
+ * Returns platform-specific mappings for the specified native format.
+ * If there are no platform-specific mappings for this native, the method
+ * returns an empty {@code Set}
+ *
+ * @param nat a native format to return flavors for
+ * @return set of platform-specific mappings for a native format
+ */
+ LinkedHashSet<DataFlavor> getPlatformMappingsForNative(String nat);
+
+ /**
+ * Returns platform-specific mappings for the specified flavor.
+ * If there are no platform-specific mappings for this flavor, the method
+ * returns an empty {@code Set}
+ *
+ * @param df {@code DataFlavor} to return mappings for
+ * @return set of platform-specific mappings for a {@code DataFlavor}
+ */
+ LinkedHashSet<String> getPlatformMappingsForFlavor(DataFlavor df);
+
+ /**
+ * This method is called for text flavor mappings established while parsing
+ * the default flavor mappings file. It stores the "eoln" and "terminators"
+ * parameters which are not officially part of the MIME type. They are
+ * MIME parameters specific to the flavormap.properties file format.
+ */
+ void registerTextFlavorProperties(String nat, String charset,
+ String eoln, String terminators);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/unix/classes/sun/datatransfer/resources/flavormap.properties Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,71 @@
+#
+# This properties file is used to initialize the default
+# java.awt.datatransfer.SystemFlavorMap. It contains the X11 platform-specific,
+# default mappings between common X11 selection atoms and platform-independent
+# MIME type strings, which will be converted into
+# java.awt.datatransfer.DataFlavors.
+#
+# The standard format is:
+#
+# <native>=<MIME type>,<MIME type>, ...
+#
+# <native> should be a string identifier that the native platform will
+# recognize as a valid data format. <MIME type> should specify both a MIME
+# primary type and a MIME subtype separated by a '/'. The MIME type may include
+# parameters, where each parameter is a key/value pair separated by '=', and
+# where each parameter to the MIME type is separated by a ';'.
+#
+# Because SystemFlavorMap implements FlavorTable, developers are free to
+# duplicate DataFlavor values and set multiple values for a single native by
+# separating them with ",". If a mapping contains a duplicate key or value,
+# earlier mappings which included this key or value will be preferred.
+#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", and which support the charset parameter, should specify the exact
+# format in which the native platform expects the data. The "charset"
+# parameter specifies the char to byte encoding, the "eoln" parameter
+# specifies the end-of-line marker, and the "terminators" parameter specifies
+# the number of terminating NUL bytes. Note that "eoln" and "terminators"
+# are not standardized MIME type parameters. They are specific to this file
+# format ONLY. They will not appear in any of the DataFlavors returned by the
+# SystemFlavorMap at the Java level.
+#
+# If the "charset" parameter is omitted, or has zero length, the platform
+# default encoding is assumed. If the "eoln" parameter is omitted, or has
+# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
+# or has a value less than zero, zero is assumed.
+#
+# Upon initialization, the data transfer subsystem will record the specified
+# details of the native text format, but the default SystemFlavorMap will
+# present a large set of synthesized DataFlavors which map, in both
+# directions, to the native. After receiving data from the application in one
+# of the synthetic DataFlavors, the data transfer subsystem will transform
+# the data stream into the format specified in this file before passing the
+# transformed stream to the native system.
+#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", but which do not support the charset parameter, will be treated as
+# opaque, 8-bit data. They will not undergo any transformation process, and
+# any "charset", "eoln", or "terminators" parameters specified in this file
+# will be ignored.
+#
+# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
+# text flavors which support the charset parameter.
+
+UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
+
+# The COMPOUND_TEXT support for inter-client text transfer is disabled by
+# default. The reason is that many native applications prefer this format over
+# other native text formats, but are unable to decode the textual data in this
+# format properly. This results in java-to-native text transfer failures.
+# To enable the COMPOUND_TEXT support for this JRE installation uncomment
+# the line below.
+
+# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0
+
+TEXT=text/plain;eoln="\n";terminators=0
+STRING=text/plain;charset=iso8859-1;eoln="\n";terminators=0
+FILE_NAME=application/x-java-file-list;class=java.util.List
+text/uri-list=application/x-java-file-list;class=java.util.List
+PNG=image/x-java-image;class=java.awt.Image
+JFIF=image/x-java-image;class=java.awt.Image
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/windows/classes/sun/datatransfer/resources/flavormap.properties Fri Jan 16 18:46:16 2015 +0300
@@ -0,0 +1,69 @@
+#
+# This properties file is used to initialize the default
+# java.awt.datatransfer.SystemFlavorMap. It contains the Win32 platform-
+# specific, default mappings between common Win32 Clipboard atoms and platform-
+# independent MIME type strings, which will be converted into
+# java.awt.datatransfer.DataFlavors.
+#
+# The standard format is:
+#
+# <native>=<MIME type>,<MIME type>, ...
+#
+# <native> should be a string identifier that the native platform will
+# recognize as a valid data format. <MIME type> should specify both a MIME
+# primary type and a MIME subtype separated by a '/'. The MIME type may include
+# parameters, where each parameter is a key/value pair separated by '=', and
+# where each parameter to the MIME type is separated by a ';'.
+#
+# Because SystemFlavorMap implements FlavorTable, developers are free to
+# duplicate DataFlavor values and set multiple values for a single native by
+# separating them with ",". If a mapping contains a duplicate key or value,
+# earlier mappings which included this key or value will be preferred.#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", and which support the charset parameter, should specify the exact
+# format in which the native platform expects the data. The "charset"
+# parameter specifies the char to byte encoding, the "eoln" parameter
+# specifies the end-of-line marker, and the "terminators" parameter specifies
+# the number of terminating NUL bytes. Note that "eoln" and "terminators"
+# are not standardized MIME type parameters. They are specific to this file
+# format ONLY. They will not appear in any of the DataFlavors returned by the
+# SystemFlavorMap at the Java level.
+#
+# If the "charset" parameter is omitted, or has zero length, the platform
+# default encoding is assumed. If the "eoln" parameter is omitted, or has
+# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
+# or has a value less than zero, zero is assumed.
+#
+# Upon initialization, the data transfer subsystem will record the specified
+# details of the native text format, but the default SystemFlavorMap will
+# present a large set of synthesized DataFlavors which map, in both
+# directions, to the native. After receiving data from the application in one
+# of the synthetic DataFlavors, the data transfer subsystem will transform
+# the data stream into the format specified in this file before passing the
+# transformed stream to the native system.
+#
+# Mappings whose values specify DataFlavors with primary MIME types of
+# "text", but which do not support the charset parameter, will be treated as
+# opaque, 8-bit data. They will not undergo any transformation process, and
+# any "charset", "eoln", or "terminators" parameters specified in this file
+# will be ignored.
+#
+# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
+# text flavors which support the charset parameter.
+
+UNICODE\ TEXT=text/plain;charset=utf-16le;eoln="\r\n";terminators=2
+TEXT=text/plain;eoln="\r\n";terminators=1
+HTML\ Format=text/html;charset=utf-8;eoln="\r\n";terminators=1
+Rich\ Text\ Format=text/rtf
+HDROP=application/x-java-file-list;class=java.util.List
+PNG=image/x-java-image;class=java.awt.Image
+JFIF=image/x-java-image;class=java.awt.Image
+DIB=image/x-java-image;class=java.awt.Image
+ENHMETAFILE=image/x-java-image;class=java.awt.Image
+METAFILEPICT=image/x-java-image;class=java.awt.Image
+LOCALE=application/x-java-text-encoding;class="[B"
+UniformResourceLocator=application/x-java-url;class=java.net.URL,\
+ text/uri-list;eoln="\r\n";terminators=1,\
+ text/plain;eoln="\r\n";terminators=1
+FileGroupDescriptorW=application/x-java-file-list;class=java.util.List
+FileGroupDescriptor=application/x-java-file-list;class=java.util.List
--- a/jdk/src/java.desktop/macosx/classes/sun/datatransfer/resources/flavormap.properties Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-#
-# This properties file is used to initialize the default
-# java.awt.datatransfer.SystemFlavorMap. It contains the Mac OS X platform-specific,
-# default mappings between common Mac OS X selection atoms and platform-independent
-# MIME type strings, which will be converted into
-# java.awt.datatransfer.DataFlavors.
-#
-# The standard format is:
-#
-# <native>=<MIME type>,<MIME type>, ...
-#
-# <native> should be a string identifier that the native platform will
-# recognize as a valid data format. <MIME type> should specify both a MIME
-# primary type and a MIME subtype separated by a '/'. The MIME type may include
-# parameters, where each parameter is a key/value pair separated by '=', and
-# where each parameter to the MIME type is separated by a ';'.
-#
-# Because SystemFlavorMap implements FlavorTable, developers are free to
-# duplicate DataFlavor values and set multiple values for a single native by
-# separating them with ",". If a mapping contains a duplicate key or value,
-# earlier mappings which included this key or value will be preferred.
-#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", and which support the charset parameter, should specify the exact
-# format in which the native platform expects the data. The "charset"
-# parameter specifies the char to byte encoding, the "eoln" parameter
-# specifies the end-of-line marker, and the "terminators" parameter specifies
-# the number of terminating NUL bytes. Note that "eoln" and "terminators"
-# are not standardized MIME type parameters. They are specific to this file
-# format ONLY. They will not appear in any of the DataFlavors returned by the
-# SystemFlavorMap at the Java level.
-#
-# If the "charset" parameter is omitted, or has zero length, the platform
-# default encoding is assumed. If the "eoln" parameter is omitted, or has
-# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
-# or has a value less than zero, zero is assumed.
-#
-# Upon initialization, the data transfer subsystem will record the specified
-# details of the native text format, but the default SystemFlavorMap will
-# present a large set of synthesized DataFlavors which map, in both
-# directions, to the native. After receiving data from the application in one
-# of the synthetic DataFlavors, the data transfer subsystem will transform
-# the data stream into the format specified in this file before passing the
-# transformed stream to the native system.
-#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", but which do not support the charset parameter, will be treated as
-# opaque, 8-bit data. They will not undergo any transformation process, and
-# any "charset", "eoln", or "terminators" parameters specified in this file
-# will be ignored.
-#
-# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
-# text flavors which support the charset parameter.
-
-UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
-
-# The COMPOUND_TEXT support for inter-client text transfer is disabled by
-# default. The reason is that many native applications prefer this format over
-# other native text formats, but are unable to decode the textual data in this
-# format properly. This results in java-to-native text transfer failures.
-# To enable the COMPOUND_TEXT support for this JRE installation uncomment
-# the line below.
-
-# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0
-
-TEXT=text/plain;eoln="\n";terminators=0
-STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
-FILE_NAME=application/x-java-file-list;class=java.util.List
-text/uri-list=application/x-java-file-list;class=java.util.List
-PNG=image/x-java-image;class=java.awt.Image
-JFIF=image/x-java-image;class=java.awt.Image
-TIFF=image/x-java-image;class=java.awt.Image
-RICH_TEXT=text/rtf
-HTML=text/html;charset=utf-8;eoln="\r\n";terminators=1
-URL=application/x-java-url;class=java.net.URL,\
- text/uri-list;eoln="\r\n";terminators=1
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/Clipboard.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +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 java.util.Objects;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Arrays;
-
-import java.io.IOException;
-
-/**
- * A class that implements a mechanism to transfer data using
- * cut/copy/paste operations.
- * <p>
- * {@link FlavorListener}s may be registered on an instance of the
- * Clipboard class to be notified about changes to the set of
- * {@link DataFlavor}s available on this clipboard (see
- * {@link #addFlavorListener}).
- *
- * @see java.awt.Toolkit#getSystemClipboard
- * @see java.awt.Toolkit#getSystemSelection
- *
- * @author Amy Fowler
- * @author Alexander Gerasimov
- */
-public class Clipboard {
-
- String name;
-
- /**
- * The owner of the clipboard.
- */
- protected ClipboardOwner owner;
- /**
- * Contents of the clipboard.
- */
- protected Transferable contents;
-
- /**
- * An aggregate of flavor listeners registered on this local clipboard.
- *
- * @since 1.5
- */
- private Set<FlavorListener> flavorListeners;
-
- /**
- * A set of <code>DataFlavor</code>s that is available on
- * this local clipboard. It is used for tracking changes
- * of <code>DataFlavor</code>s available on this clipboard.
- *
- * @since 1.5
- */
- private Set<DataFlavor> currentDataFlavors;
-
- /**
- * Creates a clipboard object.
- * @param name for the clipboard
- * @see java.awt.Toolkit#getSystemClipboard
- */
- public Clipboard(String name) {
- this.name = name;
- }
-
- /**
- * Returns the name of this clipboard object.
- * @return the name of this clipboard object
- *
- * @see java.awt.Toolkit#getSystemClipboard
- */
- public String getName() {
- return name;
- }
-
- /**
- * Sets the current contents of the clipboard to the specified
- * transferable object and registers the specified clipboard owner
- * as the owner of the new contents.
- * <p>
- * If there is an existing owner different from the argument
- * <code>owner</code>, that owner is notified that it no longer
- * holds ownership of the clipboard contents via an invocation
- * of <code>ClipboardOwner.lostOwnership()</code> on that owner.
- * An implementation of <code>setContents()</code> is free not
- * to invoke <code>lostOwnership()</code> directly from this method.
- * For example, <code>lostOwnership()</code> may be invoked later on
- * a different thread. The same applies to <code>FlavorListener</code>s
- * registered on this clipboard.
- * <p>
- * The method throws <code>IllegalStateException</code> if the clipboard
- * is currently unavailable. For example, on some platforms, the system
- * clipboard is unavailable while it is accessed by another application.
- *
- * @param contents the transferable object representing the
- * clipboard content
- * @param owner the object which owns the clipboard content
- * @throws IllegalStateException if the clipboard is currently unavailable
- * @see java.awt.Toolkit#getSystemClipboard
- */
- public synchronized void setContents(Transferable contents, ClipboardOwner owner) {
- final ClipboardOwner oldOwner = this.owner;
- final Transferable oldContents = this.contents;
-
- this.owner = owner;
- this.contents = contents;
-
- if (oldOwner != null && oldOwner != owner) {
- DataFlavorUtil.getDesktopService().invokeOnEventThread(() ->
- oldOwner.lostOwnership(Clipboard.this, oldContents));
- }
- fireFlavorsChanged();
- }
-
- /**
- * Returns a transferable object representing the current contents
- * of the clipboard. If the clipboard currently has no contents,
- * it returns <code>null</code>. The parameter Object requestor is
- * not currently used. The method throws
- * <code>IllegalStateException</code> if the clipboard is currently
- * unavailable. For example, on some platforms, the system clipboard is
- * unavailable while it is accessed by another application.
- *
- * @param requestor the object requesting the clip data (not used)
- * @return the current transferable object on the clipboard
- * @throws IllegalStateException if the clipboard is currently unavailable
- * @see java.awt.Toolkit#getSystemClipboard
- */
- public synchronized Transferable getContents(Object requestor) {
- return contents;
- }
-
-
- /**
- * Returns an array of <code>DataFlavor</code>s in which the current
- * contents of this clipboard can be provided. If there are no
- * <code>DataFlavor</code>s available, this method returns a zero-length
- * array.
- *
- * @return an array of <code>DataFlavor</code>s in which the current
- * contents of this clipboard can be provided
- *
- * @throws IllegalStateException if this clipboard is currently unavailable
- *
- * @since 1.5
- */
- public DataFlavor[] getAvailableDataFlavors() {
- Transferable cntnts = getContents(null);
- if (cntnts == null) {
- return new DataFlavor[0];
- }
- return cntnts.getTransferDataFlavors();
- }
-
- /**
- * Returns whether or not the current contents of this clipboard can be
- * provided in the specified <code>DataFlavor</code>.
- *
- * @param flavor the requested <code>DataFlavor</code> for the contents
- *
- * @return <code>true</code> if the current contents of this clipboard
- * can be provided in the specified <code>DataFlavor</code>;
- * <code>false</code> otherwise
- *
- * @throws NullPointerException if <code>flavor</code> is <code>null</code>
- * @throws IllegalStateException if this clipboard is currently unavailable
- *
- * @since 1.5
- */
- public boolean isDataFlavorAvailable(DataFlavor flavor) {
- if (flavor == null) {
- throw new NullPointerException("flavor");
- }
-
- Transferable cntnts = getContents(null);
- if (cntnts == null) {
- return false;
- }
- return cntnts.isDataFlavorSupported(flavor);
- }
-
- /**
- * Returns an object representing the current contents of this clipboard
- * in the specified <code>DataFlavor</code>.
- * The class of the object returned is defined by the representation
- * class of <code>flavor</code>.
- *
- * @param flavor the requested <code>DataFlavor</code> for the contents
- *
- * @return an object representing the current contents of this clipboard
- * in the specified <code>DataFlavor</code>
- *
- * @throws NullPointerException if <code>flavor</code> is <code>null</code>
- * @throws IllegalStateException if this clipboard is currently unavailable
- * @throws UnsupportedFlavorException if the requested <code>DataFlavor</code>
- * is not available
- * @throws IOException if the data in the requested <code>DataFlavor</code>
- * can not be retrieved
- *
- * @see DataFlavor#getRepresentationClass
- *
- * @since 1.5
- */
- public Object getData(DataFlavor flavor)
- throws UnsupportedFlavorException, IOException {
- if (flavor == null) {
- throw new NullPointerException("flavor");
- }
-
- Transferable cntnts = getContents(null);
- if (cntnts == null) {
- throw new UnsupportedFlavorException(flavor);
- }
- return cntnts.getTransferData(flavor);
- }
-
-
- /**
- * Registers the specified <code>FlavorListener</code> to receive
- * <code>FlavorEvent</code>s from this clipboard.
- * If <code>listener</code> is <code>null</code>, no exception
- * is thrown and no action is performed.
- *
- * @param listener the listener to be added
- *
- * @see #removeFlavorListener
- * @see #getFlavorListeners
- * @see FlavorListener
- * @see FlavorEvent
- * @since 1.5
- */
- public synchronized void addFlavorListener(FlavorListener listener) {
- if (listener == null) {
- return;
- }
-
- if (flavorListeners == null) {
- flavorListeners = new HashSet<>();
- currentDataFlavors = getAvailableDataFlavorSet();
- }
-
- flavorListeners.add(listener);
- }
-
- /**
- * Removes the specified <code>FlavorListener</code> so that it no longer
- * receives <code>FlavorEvent</code>s from this <code>Clipboard</code>.
- * This method performs no function, nor does it throw an exception, if
- * the listener specified by the argument was not previously added to this
- * <code>Clipboard</code>.
- * If <code>listener</code> is <code>null</code>, no exception
- * is thrown and no action is performed.
- *
- * @param listener the listener to be removed
- *
- * @see #addFlavorListener
- * @see #getFlavorListeners
- * @see FlavorListener
- * @see FlavorEvent
- * @since 1.5
- */
- public synchronized void removeFlavorListener(FlavorListener listener) {
- if (listener == null || flavorListeners == null) {
- return;
- }
- flavorListeners.remove(listener);
- }
-
- /**
- * Returns an array of all the <code>FlavorListener</code>s currently
- * registered on this <code>Clipboard</code>.
- *
- * @return all of this clipboard's <code>FlavorListener</code>s or an empty
- * array if no listeners are currently registered
- * @see #addFlavorListener
- * @see #removeFlavorListener
- * @see FlavorListener
- * @see FlavorEvent
- * @since 1.5
- */
- public synchronized FlavorListener[] getFlavorListeners() {
- return flavorListeners == null ? new FlavorListener[0] :
- flavorListeners.toArray(new FlavorListener[flavorListeners.size()]);
- }
-
- /**
- * Checks change of the <code>DataFlavor</code>s and, if necessary,
- * notifies all listeners that have registered interest for notification
- * on <code>FlavorEvent</code>s.
- *
- * @since 1.5
- */
- private void fireFlavorsChanged() {
- if (flavorListeners == null) {
- return;
- }
-
- Set<DataFlavor> prevDataFlavors = currentDataFlavors;
- currentDataFlavors = getAvailableDataFlavorSet();
- if (Objects.equals(prevDataFlavors, currentDataFlavors)) {
- return;
- }
- flavorListeners.forEach(listener ->
- DataFlavorUtil.getDesktopService().invokeOnEventThread(() ->
- listener.flavorsChanged(new FlavorEvent(Clipboard.this))));
- }
-
- /**
- * Returns a set of <code>DataFlavor</code>s currently available
- * on this clipboard.
- *
- * @return a set of <code>DataFlavor</code>s currently available
- * on this clipboard
- *
- * @since 1.5
- */
- private Set<DataFlavor> getAvailableDataFlavorSet() {
- Set<DataFlavor> set = new HashSet<>();
- Transferable contents = getContents(null);
- if (contents != null) {
- DataFlavor[] flavors = contents.getTransferDataFlavors();
- if (flavors != null) {
- set.addAll(Arrays.asList(flavors));
- }
- }
- return set;
- }
-}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/ClipboardOwner.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 1996, 2002, 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;
-
-/**
- * Defines the interface for classes that will provide data to
- * a clipboard. An instance of this interface becomes the owner
- * of the contents of a clipboard (clipboard owner) if it is
- * passed as an argument to
- * {@link java.awt.datatransfer.Clipboard#setContents} method of
- * the clipboard and this method returns successfully.
- * The instance remains the clipboard owner until another application
- * or another object within this application asserts ownership
- * of this clipboard.
- *
- * @see java.awt.datatransfer.Clipboard
- *
- * @author Amy Fowler
- */
-
-public interface ClipboardOwner {
-
- /**
- * Notifies this object that it is no longer the clipboard owner.
- * This method will be called when another application or another
- * object within this application asserts ownership of the clipboard.
- *
- * @param clipboard the clipboard that is no longer owned
- * @param contents the contents which this owner had placed on the clipboard
- */
- public void lostOwnership(Clipboard clipboard, Transferable contents);
-
-}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/DataFlavor.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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.
- * <p>
- * An instance of {@code DataFlavor} encapsulates a content type as
- * defined in <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
- * and <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a>.
- * A content type is typically referred to as a MIME type.
- * <p>
- * A content type consists of a media type (referred
- * to as the primary type), a subtype, and optional parameters. See
- * <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
- * for details on the syntax of a MIME type.
- * <p>
- * The JRE data transfer implementation interprets the parameter "class"
- * of a MIME type as <B>a representation class</b>.
- * 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.
- * <br>
- * 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.
- * <p>
- * Also, {@code DataFlavor} instances with the "text" primary
- * MIME type may have a "charset" parameter. Refer to
- * <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a> and
- * {@link #selectBestTextFlavor} for details on "text" MIME types
- * and the "charset" parameter.
- * <p>
- * 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:
- * <pre>
- * 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);
- * </pre>
- * As mentioned, {@code flavor1} and {@code flavor2} are considered identical.
- * As such, asking a {@code Transferable} for either {@code DataFlavor} returns
- * the same results.
- * <p>
- * For more information on using data transfer with Swing see
- * the <a href="http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html">
- * How to Use Drag and Drop and Data Transfer</a>,
- * section in <em>Java Tutorial</em>.
- *
- * @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<InputStream> 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 <code>DataFlavor</code> representing a Java Unicode String class,
- * where:
- * <pre>
- * representationClass = java.lang.String
- * mimeType = "application/x-java-serialized-object"
- * </pre>
- */
- public static final DataFlavor stringFlavor = createConstant(java.lang.String.class, "Unicode String");
-
- /**
- * The <code>DataFlavor</code> representing a Java Image class,
- * where:
- * <pre>
- * representationClass = java.awt.Image
- * mimeType = "image/x-java-image"
- * </pre>
- */
- public static final DataFlavor imageFlavor = createConstant("image/x-java-image; class=java.awt.Image", "Image");
-
- /**
- * The <code>DataFlavor</code> representing plain text with Unicode
- * encoding, where:
- * <pre>
- * representationClass = InputStream
- * mimeType = "text/plain; charset=unicode"
- * </pre>
- * This <code>DataFlavor</code> has been <b>deprecated</b> 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 <code>DataFlavor.getReaderForText(Transferable)</code>
- * instead of <code>Transferable.getTransferData(DataFlavor.plainTextFlavor)</code>.
- */
- @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 <code>DataFlavor</code>
- * identifies the Java type of an object returned as a reference
- * from an invocation <code>java.awt.datatransfer.getTransferData</code>.
- */
- public static final String javaSerializedObjectMimeType = "application/x-java-serialized-object";
-
- /**
- * To transfer a list of files to/from Java (and the underlying
- * platform) a <code>DataFlavor</code> of this type/subtype and
- * representation class of <code>java.util.List</code> is used.
- * Each element of the list is required/guaranteed to be of type
- * <code>java.io.File</code>.
- */
- 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 <code>Transferable</code>
- * interface WITHIN THE SAME JVM, a <code>DataFlavor</code>
- * with this type/subtype is used, with a <code>representationClass</code>
- * equal to the type of the class/interface being passed across the
- * <code>Transferable</code>.
- * <p>
- * The object reference returned from
- * <code>Transferable.getTransferData</code> for a <code>DataFlavor</code>
- * with this MIME Content-Type is required to be
- * an instance of the representation Class of the <code>DataFlavor</code>.
- */
- 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
- * <code>ACTION_LINK</code> operation a Mime Content Type of
- * application/x-java-remote-object should be used,
- * where the representation class of the <code>DataFlavor</code>
- * represents the type of the <code>Remote</code> 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.
- * <pre>
- * representationClass = String
- * mimeType = "text/html"
- * </pre>
- */
- 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.
- * <pre>
- * representationClass = String
- * mimeType = "text/html"
- * </pre>
- */
- 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.
- * <pre>
- * representationClass = String
- * mimeType = "text/html"
- * </pre>
- */
- public static DataFlavor allHtmlFlavor = initHtmlDataFlavor("all");
-
- /**
- * Constructs a new <code>DataFlavor</code>. This constructor is
- * provided only for the purpose of supporting the
- * <code>Externalizable</code> interface. It is not
- * intended for public (client) use.
- *
- * @since 1.2
- */
- public DataFlavor() {
- super();
- }
-
- /**
- * Constructs a fully specified <code>DataFlavor</code>.
- *
- * @exception NullPointerException if either <code>primaryType</code>,
- * <code>subType</code> or <code>representationClass</code> 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 <code>DataFlavor</code> that represents a Java class.
- * <p>
- * The returned <code>DataFlavor</code> will have the following
- * characteristics:
- * <pre>
- * representationClass = representationClass
- * mimeType = application/x-java-serialized-object
- * </pre>
- * @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 <code>null</code>
- * then the value of the MIME Content Type is used
- * @exception NullPointerException if <code>representationClass</code> 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 <code>DataFlavor</code> that represents a
- * <code>MimeType</code>.
- * <p>
- * The returned <code>DataFlavor</code> will have the following
- * characteristics:
- * <p>
- * If the <code>mimeType</code> is
- * "application/x-java-serialized-object; class=<representation class>",
- * the result is the same as calling
- * <code>new DataFlavor(Class.forName(<representation class>)</code>.
- * <p>
- * Otherwise:
- * <pre>
- * representationClass = InputStream
- * mimeType = mimeType
- * </pre>
- * @param mimeType the string used to identify the MIME type for this flavor;
- * if the <code>mimeType</code> does not specify a
- * "class=" parameter, or if the class is not successfully
- * loaded, then an <code>IllegalArgumentException</code>
- * is thrown
- * @param humanPresentableName the human-readable string used to identify
- * this flavor; if this parameter is <code>null</code>
- * then the value of the MIME Content Type is used
- * @exception IllegalArgumentException if <code>mimeType</code> is
- * invalid or if the class is not successfully loaded
- * @exception NullPointerException if <code>mimeType</code> 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 <code>DataFlavor</code> that represents a
- * <code>MimeType</code>.
- * <p>
- * The returned <code>DataFlavor</code> will have the following
- * characteristics:
- * <p>
- * If the mimeType is
- * "application/x-java-serialized-object; class=<representation class>",
- * the result is the same as calling
- * <code>new DataFlavor(Class.forName(<representation class>)</code>.
- * <p>
- * Otherwise:
- * <pre>
- * representationClass = InputStream
- * mimeType = mimeType
- * </pre>
- * @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 <code>mimeType</code> is
- * invalid
- * @exception NullPointerException if <code>mimeType</code> 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 <code>DataFlavor</code> from a <code>mimeType</code> string.
- * The string can specify a "class=<fully specified Java class name>"
- * parameter to create a <code>DataFlavor</code> with the desired
- * representation class. If the string does not contain "class=" parameter,
- * <code>java.io.InputStream</code> 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
- * <code>ClassNotFoundException</code> is thrown
- * @exception ClassNotFoundException if the class is not loaded
- * @exception IllegalArgumentException if <code>mimeType</code> is
- * invalid
- * @exception NullPointerException if <code>mimeType</code> 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
- * <code>null</code>
- * @param classLoader the fallback class loader to resolve against
- *
- * @throws MimeTypeParseException
- * @throws ClassNotFoundException
- * @throws NullPointerException if <code>mimeType</code> 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 <code>DataFlavor</code> and its
- * parameters. The resulting <code>String</code> contains the name of
- * the <code>DataFlavor</code> 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 <code>selectBestTextFlavor</code>
- * for a list of text flavors which support the charset parameter.
- *
- * @return string representation of this <code>DataFlavor</code>
- * @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 <code>DataFlavor</code> representing plain text with Unicode
- * encoding, where:
- * <pre>
- * representationClass = java.io.InputStream
- * mimeType = "text/plain;
- * charset=<platform default Unicode encoding>"
- * </pre>
- * Sun's implementation for Microsoft Windows uses the encoding <code>utf-16le</code>.
- * Sun's implementation for Solaris and Linux uses the encoding
- * <code>iso-10646-ucs-2</code>.
- *
- * @return a <code>DataFlavor</code> 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 <code>DataFlavor</code> from an array of <code>
- * DataFlavor</code>s. Only <code>DataFlavor.stringFlavor</code>, and
- * equivalent flavors, and flavors that have a primary MIME type of "text",
- * are considered for selection.
- * <p>
- * Flavors are first sorted by their MIME types in the following order:
- * <ul>
- * <li>"text/sgml"
- * <li>"text/xml"
- * <li>"text/html"
- * <li>"text/rtf"
- * <li>"text/enriched"
- * <li>"text/richtext"
- * <li>"text/uri-list"
- * <li>"text/tab-separated-values"
- * <li>"text/t140"
- * <li>"text/rfc822-headers"
- * <li>"text/parityfec"
- * <li>"text/directory"
- * <li>"text/css"
- * <li>"text/calendar"
- * <li>"application/x-java-serialized-object"
- * <li>"text/plain"
- * <li>"text/<other>"
- * </ul>
- * <p>For example, "text/sgml" will be selected over
- * "text/html", and <code>DataFlavor.stringFlavor</code> will be chosen
- * over <code>DataFlavor.plainTextFlavor</code>.
- * <p>
- * 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.
- * <p>
- * The following MIME types support, or are treated as though they support,
- * the charset parameter:
- * <ul>
- * <li>"text/sgml"
- * <li>"text/xml"
- * <li>"text/html"
- * <li>"text/enriched"
- * <li>"text/richtext"
- * <li>"text/uri-list"
- * <li>"text/directory"
- * <li>"text/css"
- * <li>"text/calendar"
- * <li>"application/x-java-serialized-object"
- * <li>"text/plain"
- * </ul>
- * The following MIME types do not support, or are treated as though they
- * do not support, the charset parameter:
- * <ul>
- * <li>"text/rtf"
- * <li>"text/tab-separated-values"
- * <li>"text/t140"
- * <li>"text/rfc822-headers"
- * <li>"text/parityfec"
- * </ul>
- * 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 <code>DataFlavor</code> 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
- * <code>DataFlavor</code>, developers must ensure that all
- * <code>DataFlavor</code>s 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.
- * <p>
- * 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:
- * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
- * <code>[B</code>, <all others>.
- * <p>
- * 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.
- * <p>
- * 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:
- * <code>java.io.Reader</code>, <code>java.lang.String</code>,
- * <code>java.nio.CharBuffer</code>, <code>[C</code>, <all others>.
- * <p>
- * 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.
- * <p>
- * If two or more flavors share the best charset, the flavors will then
- * again be sorted by their representation classes in the following order:
- * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
- * <code>[B</code>, <all others>.
- * <p>
- * 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 <code>DataFlavor</code>s
- * @return the best (highest fidelity) flavor according to the rules
- * specified above, or <code>null</code>,
- * if <code>availableFlavors</code> is <code>null</code>,
- * 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
- * <code>java.io.Reader</code>, <code>java.lang.String</code>,
- * <code>java.nio.CharBuffer</code>, <code>[C</code>,
- * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
- * and <code>[B</code>.
- * <p>
- * 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 <code>selectBestTextFlavor</code> for a list
- * of text flavors which do not support the charset parameter.
- *
- * @param transferable the <code>Transferable</code> whose data will be
- * requested in this flavor
- *
- * @return a <code>Reader</code> to read the <code>Transferable</code>'s
- * data
- *
- * @exception IllegalArgumentException if the representation class
- * is not one of the seven listed above
- * @exception IllegalArgumentException if the <code>Transferable</code>
- * has <code>null</code> data
- * @exception NullPointerException if the <code>Transferable</code> is
- * <code>null</code>
- * @exception UnsupportedEncodingException if this flavor's representation
- * is <code>java.io.InputStream</code>,
- * <code>java.nio.ByteBuffer</code>, or <code>[B</code> and
- * this flavor's encoding is not supported by this
- * implementation of the Java platform
- * @exception UnsupportedFlavorException if the <code>Transferable</code>
- * 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 <code>DataFlavor</code>.
- * @return the MIME type string for this flavor
- */
- public String getMimeType() {
- return (mimeType != null) ? mimeType.toString() : null;
- }
-
- /**
- * Returns the <code>Class</code> which objects supporting this
- * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
- * is requested.
- * @return the <code>Class</code> which objects supporting this
- * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
- * is requested
- */
- public Class<?> getRepresentationClass() {
- return representationClass;
- }
-
- /**
- * Returns the human presentable name for the data format that this
- * <code>DataFlavor</code> represents. This name would be localized
- * for different countries.
- * @return the human presentable name for the data format that this
- * <code>DataFlavor</code> represents
- */
- public String getHumanPresentableName() {
- return humanPresentableName;
- }
-
- /**
- * Returns the primary MIME type for this <code>DataFlavor</code>.
- * @return the primary MIME type of this <code>DataFlavor</code>
- */
- public String getPrimaryType() {
- return (mimeType != null) ? mimeType.getPrimaryType() : null;
- }
-
- /**
- * Returns the sub MIME type of this <code>DataFlavor</code>.
- * @return the Sub MIME type of this <code>DataFlavor</code>
- */
- public String getSubType() {
- return (mimeType != null) ? mimeType.getSubType() : null;
- }
-
- /**
- * Returns the human presentable name for this <code>DataFlavor</code>
- * if <code>paramName</code> equals "humanPresentableName". Otherwise
- * returns the MIME type value associated with <code>paramName</code>.
- *
- * @param paramName the parameter name requested
- * @return the value of the name parameter, or <code>null</code>
- * 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
- * <code>DataFlavor</code> 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}
- * <p>
- * The equals comparison for the {@code DataFlavor} class is implemented
- * as follows: Two <code>DataFlavor</code>s 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 <code>java.io.Reader</code>,
- * <code>java.lang.String</code>, <code>java.nio.CharBuffer</code>, or
- * <code>[C</code>, the <code>charset</code> parameter must also be equal.
- * If a charset is not explicitly specified for one or both
- * <code>DataFlavor</code>s, the platform default encoding is assumed. See
- * <code>selectBestTextFlavor</code> for a list of text flavors which
- * support the charset parameter.
- *
- * @param o the <code>Object</code> to compare with <code>this</code>
- * @return <code>true</code> if <code>that</code> is equivalent to this
- * <code>DataFlavor</code>; <code>false</code> 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 <code>DataFlavor</code> to compare with
- * <code>this</code>
- * @return <code>true</code> if <code>that</code> is equivalent to this
- * <code>DataFlavor</code>; <code>false</code> 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 <code>mimeType</code> against the passed in
- * <code>String</code> and <code>representationClass</code> is
- * not considered in the comparison.
- *
- * If <code>representationClass</code> needs to be compared, then
- * <code>equals(new DataFlavor(s))</code> may be used.
- * @deprecated As inconsistent with <code>hashCode()</code> contract,
- * use <code>isMimeTypeEqual(String)</code> 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 <code>DataFlavor</code>.
- * For two equal <code>DataFlavor</code>s, hash codes are equal.
- * For the <code>String</code>
- * that matches <code>DataFlavor.equals(String)</code>, it is not
- * guaranteed that <code>DataFlavor</code>'s hash code is equal
- * to the hash code of the <code>String</code>.
- *
- * @return a hash code for this <code>DataFlavor</code>
- */
- 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 <code>DataFlavor</code> to compare with
- * <code>this</code>
- * @return <code>true</code> if <code>that</code> is equivalent to this
- * <code>DataFlavor</code>; <code>false</code> 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 <code>DataFlavor</code>.
- * 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 <code>DataFlavor</code>;
- * false otherwise
- * @throws NullPointerException if mimeType is <code>null</code>
- */
- 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 <code>mimeType</code> of two <code>DataFlavor</code>
- * objects. No parameters are considered.
- *
- * @param dataFlavor the <code>DataFlavor</code> to be compared
- * @return true if the <code>MimeType</code>s are equal,
- * otherwise false
- */
-
- public final boolean isMimeTypeEqual(DataFlavor dataFlavor) {
- return isMimeTypeEqual(dataFlavor.mimeType);
- }
-
- /**
- * Compares the <code>mimeType</code> of two <code>DataFlavor</code>
- * objects. No parameters are considered.
- *
- * @return true if the <code>MimeType</code>s 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 <code>DataFlavor</code> 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 <code>DataFlavor</code> represent a
- * <code>java.io.InputStream</code>?
- * @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
- * <code>DataFlavor</code> is <code>java.io.Reader</code> 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
- * <code>DataFlavor</code> is <code>java.nio.CharBuffer</code> 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
- * <code>DataFlavor</code> is <code>java.nio.ByteBuffer</code> 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 <code>Remote</code>.
- * @return true if the representation class is <code>Remote</code>
- */
- public boolean isRepresentationClassRemote() {
- return DataFlavorUtil.RMI.isRemote(representationClass);
- }
-
- /**
- * Returns true if the <code>DataFlavor</code> specified represents
- * a serialized object.
- * @return true if the <code>DataFlavor</code> specified represents
- * a Serialized Object
- */
-
- public boolean isFlavorSerializedObjectType() {
- return isRepresentationClassSerializable() && isMimeTypeEqual(javaSerializedObjectMimeType);
- }
-
- /**
- * Returns true if the <code>DataFlavor</code> specified represents
- * a remote object.
- * @return true if the <code>DataFlavor</code> specified represents
- * a Remote Object
- */
-
- public boolean isFlavorRemoteObjectType() {
- return isRepresentationClassRemote()
- && isRepresentationClassSerializable()
- && isMimeTypeEqual(javaRemoteObjectMimeType);
- }
-
-
- /**
- * Returns true if the <code>DataFlavor</code> specified represents
- * a list of file objects.
- * @return true if the <code>DataFlavor</code> 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 <code>DataFlavor</code> is a valid text flavor for
- * this implementation of the Java platform. Only flavors equivalent to
- * <code>DataFlavor.stringFlavor</code> and <code>DataFlavor</code>s with
- * a primary MIME type of "text" can be valid text flavors.
- * <p>
- * If this flavor supports the charset parameter, it must be equivalent to
- * <code>DataFlavor.stringFlavor</code>, or its representation must be
- * <code>java.io.Reader</code>, <code>java.lang.String</code>,
- * <code>java.nio.CharBuffer</code>, <code>[C</code>,
- * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
- * <code>[B</code>. If the representation is
- * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
- * <code>[B</code>, then this flavor's <code>charset</code> 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.
- * <p>
- * If this flavor does not support the charset parameter, its
- * representation must be <code>java.io.InputStream</code>,
- * <code>java.nio.ByteBuffer</code>, or <code>[B</code>.
- * <p>
- * See <code>selectBestTextFlavor</code> for a list of text flavors which
- * support the charset parameter.
- *
- * @return <code>true</code> if this <code>DataFlavor</code> is a valid
- * text flavor as described above; <code>false</code> otherwise
- * @see #selectBestTextFlavor
- * @since 1.4
- */
- public boolean isFlavorTextType() {
- return (DataFlavorUtil.isFlavorCharsetTextType(this) ||
- DataFlavorUtil.isFlavorNoncharsetTextType(this));
- }
-
- /**
- * Serializes this <code>DataFlavor</code>.
- */
-
- 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 <code>DataFlavor</code> 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 <code>DataFlavor</code>.
- * @return a clone of this <code>DataFlavor</code>
- */
-
- public Object clone() throws CloneNotSupportedException {
- Object newObj = super.clone();
- if (mimeType != null) {
- ((DataFlavor)newObj).mimeType = (MimeType)mimeType.clone();
- }
- return newObj;
- } // clone()
-
- /**
- * Called on <code>DataFlavor</code> for every MIME Type parameter
- * to allow <code>DataFlavor</code> subclasses to handle special
- * parameters like the text/plain <code>charset</code>
- * parameters, whose values are case insensitive. (MIME type parameter
- * values are supposed to be case sensitive.
- * <p>
- * This method is called for each parameter name/value pair and should
- * return the normalized representation of the <code>parameterValue</code>.
- *
- * 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 <code>DataFlavor</code> 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
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/FlavorEvent.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2003, 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 java.util.EventObject;
-
-
-/**
- * <code>FlavorEvent</code> is used to notify interested parties
- * that available {@link DataFlavor}s have changed in the
- * {@link Clipboard} (the event source).
- *
- * @see FlavorListener
- *
- * @author Alexander Gerasimov
- * @since 1.5
- */
-public class FlavorEvent extends EventObject {
- private static final long serialVersionUID = -5842664112252414548L;
-
- /**
- * Constructs a <code>FlavorEvent</code> object.
- *
- * @param source the <code>Clipboard</code> that is the source of the event
- *
- * @throws IllegalArgumentException if the {@code source} is {@code null}
- */
- public FlavorEvent(Clipboard source) {
- super(source);
- }
-}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/FlavorListener.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2003, 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 java.util.EventListener;
-
-
-/**
- * Defines an object which listens for {@link FlavorEvent}s.
- *
- * @author Alexander Gerasimov
- * @since 1.5
- */
-public interface FlavorListener extends EventListener {
- /**
- * Invoked when the target {@link Clipboard} of the listener
- * has changed its available {@link DataFlavor}s.
- * <p>
- * Some notifications may be redundant — they are not
- * caused by a change of the set of DataFlavors available
- * on the clipboard.
- * For example, if the clipboard subsystem supposes that
- * the system clipboard's contents has been changed but it
- * can't ascertain whether its DataFlavors have been changed
- * because of some exceptional condition when accessing the
- * clipboard, the notification is sent to ensure from omitting
- * a significant notification. Ordinarily, those redundant
- * notifications should be occasional.
- *
- * @param e a <code>FlavorEvent</code> object
- */
- void flavorsChanged(FlavorEvent e);
-}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/FlavorMap.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 1997, 2013, 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 java.util.Map;
-
-
-/**
- * A two-way Map between "natives" (Strings), which correspond to platform-
- * specific data formats, and "flavors" (DataFlavors), which correspond to
- * platform-independent MIME types. FlavorMaps need not be symmetric, but
- * typically are.
- *
- *
- * @since 1.2
- */
-public interface FlavorMap {
-
- /**
- * Returns a <code>Map</code> of the specified <code>DataFlavor</code>s to
- * their corresponding <code>String</code> native. The returned
- * <code>Map</code> is a modifiable copy of this <code>FlavorMap</code>'s
- * internal data. Client code is free to modify the <code>Map</code>
- * without affecting this object.
- *
- * @param flavors an array of <code>DataFlavor</code>s which will be the
- * key set of the returned <code>Map</code>. If <code>null</code> is
- * specified, a mapping of all <code>DataFlavor</code>s currently
- * known to this <code>FlavorMap</code> to their corresponding
- * <code>String</code> natives will be returned.
- * @return a <code>java.util.Map</code> of <code>DataFlavor</code>s to
- * <code>String</code> natives
- */
- Map<DataFlavor,String> getNativesForFlavors(DataFlavor[] flavors);
-
- /**
- * Returns a <code>Map</code> of the specified <code>String</code> natives
- * to their corresponding <code>DataFlavor</code>. The returned
- * <code>Map</code> is a modifiable copy of this <code>FlavorMap</code>'s
- * internal data. Client code is free to modify the <code>Map</code>
- * without affecting this object.
- *
- * @param natives an array of <code>String</code>s which will be the
- * key set of the returned <code>Map</code>. If <code>null</code> is
- * specified, a mapping of all <code>String</code> natives currently
- * known to this <code>FlavorMap</code> to their corresponding
- * <code>DataFlavor</code>s will be returned.
- * @return a <code>java.util.Map</code> of <code>String</code> natives to
- * <code>DataFlavor</code>s
- */
- Map<String,DataFlavor> getFlavorsForNatives(String[] natives);
-}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/FlavorTable.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2000, 2004, 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 java.util.List;
-
-
-/**
- * A FlavorMap which relaxes the traditional 1-to-1 restriction of a Map. A
- * flavor is permitted to map to any number of natives, and likewise a native
- * is permitted to map to any number of flavors. FlavorTables need not be
- * symmetric, but typically are.
- *
- * @author David Mendenhall
- *
- * @since 1.4
- */
-public interface FlavorTable extends FlavorMap {
-
- /**
- * Returns a <code>List</code> of <code>String</code> natives to which the
- * specified <code>DataFlavor</code> corresponds. The <code>List</code>
- * will be sorted from best native to worst. That is, the first native will
- * best reflect data in the specified flavor to the underlying native
- * platform. The returned <code>List</code> is a modifiable copy of this
- * <code>FlavorTable</code>'s internal data. Client code is free to modify
- * the <code>List</code> without affecting this object.
- *
- * @param flav the <code>DataFlavor</code> whose corresponding natives
- * should be returned. If <code>null</code> is specified, all
- * natives currently known to this <code>FlavorTable</code> are
- * returned in a non-deterministic order.
- * @return a <code>java.util.List</code> of <code>java.lang.String</code>
- * objects which are platform-specific representations of platform-
- * specific data formats
- */
- List<String> getNativesForFlavor(DataFlavor flav);
-
- /**
- * Returns a <code>List</code> of <code>DataFlavor</code>s to which the
- * specified <code>String</code> corresponds. The <code>List</code> will be
- * sorted from best <code>DataFlavor</code> to worst. That is, the first
- * <code>DataFlavor</code> will best reflect data in the specified
- * native to a Java application. The returned <code>List</code> is a
- * modifiable copy of this <code>FlavorTable</code>'s internal data.
- * Client code is free to modify the <code>List</code> without affecting
- * this object.
- *
- * @param nat the native whose corresponding <code>DataFlavor</code>s
- * should be returned. If <code>null</code> is specified, all
- * <code>DataFlavor</code>s currently known to this
- * <code>FlavorTable</code> are returned in a non-deterministic
- * order.
- * @return a <code>java.util.List</code> of <code>DataFlavor</code>
- * objects into which platform-specific data in the specified,
- * platform-specific native can be translated
- */
- List<DataFlavor> getFlavorsForNative(String nat);
-}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/MimeType.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,394 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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 java.io.Externalizable;
-import java.io.ObjectOutput;
-import java.io.ObjectInput;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Locale;
-
-
-/**
- * A Multipurpose Internet Mail Extension (MIME) type, as defined
- * in RFC 2045 and 2046.
- *
- * THIS IS *NOT* - REPEAT *NOT* - A PUBLIC CLASS! DataFlavor IS
- * THE PUBLIC INTERFACE, AND THIS IS PROVIDED AS A ***PRIVATE***
- * (THAT IS AS IN *NOT* PUBLIC) HELPER CLASS!
- */
-class MimeType implements Externalizable, Cloneable {
-
- /*
- * serialization support
- */
-
- static final long serialVersionUID = -6568722458793895906L;
-
- /**
- * Constructor for externalization; this constructor should not be
- * called directly by an application, since the result will be an
- * uninitialized, immutable <code>MimeType</code> object.
- */
- public MimeType() {
- }
-
- /**
- * Builds a <code>MimeType</code> from a <code>String</code>.
- *
- * @param rawdata text used to initialize the <code>MimeType</code>
- * @throws NullPointerException if <code>rawdata</code> is null
- */
- public MimeType(String rawdata) throws MimeTypeParseException {
- parse(rawdata);
- }
-
- /**
- * Builds a <code>MimeType</code> with the given primary and sub
- * type but has an empty parameter list.
- *
- * @param primary the primary type of this <code>MimeType</code>
- * @param sub the subtype of this <code>MimeType</code>
- * @throws NullPointerException if either <code>primary</code> or
- * <code>sub</code> is null
- */
- public MimeType(String primary, String sub) throws MimeTypeParseException {
- this(primary, sub, new MimeTypeParameterList());
- }
-
- /**
- * Builds a <code>MimeType</code> with a pre-defined
- * and valid (or empty) parameter list.
- *
- * @param primary the primary type of this <code>MimeType</code>
- * @param sub the subtype of this <code>MimeType</code>
- * @param mtpl the requested parameter list
- * @throws NullPointerException if either <code>primary</code>,
- * <code>sub</code> or <code>mtpl</code> is null
- */
- public MimeType(String primary, String sub, MimeTypeParameterList mtpl) throws
-MimeTypeParseException {
- // check to see if primary is valid
- if(isValidToken(primary)) {
- primaryType = primary.toLowerCase(Locale.ENGLISH);
- } else {
- throw new MimeTypeParseException("Primary type is invalid.");
- }
-
- // check to see if sub is valid
- if(isValidToken(sub)) {
- subType = sub.toLowerCase(Locale.ENGLISH);
- } else {
- throw new MimeTypeParseException("Sub type is invalid.");
- }
-
- parameters = (MimeTypeParameterList)mtpl.clone();
- }
-
- public int hashCode() {
-
- // We sum up the hash codes for all of the strings. This
- // way, the order of the strings is irrelevant
- int code = 0;
- code += primaryType.hashCode();
- code += subType.hashCode();
- code += parameters.hashCode();
- return code;
- } // hashCode()
-
- /**
- * <code>MimeType</code>s are equal if their primary types,
- * subtypes, and parameters are all equal. No default values
- * are taken into account.
- * @param thatObject the object to be evaluated as a
- * <code>MimeType</code>
- * @return <code>true</code> if <code>thatObject</code> is
- * a <code>MimeType</code>; otherwise returns <code>false</code>
- */
- public boolean equals(Object thatObject) {
- if (!(thatObject instanceof MimeType)) {
- return false;
- }
- MimeType that = (MimeType)thatObject;
- boolean isIt =
- ((this.primaryType.equals(that.primaryType)) &&
- (this.subType.equals(that.subType)) &&
- (this.parameters.equals(that.parameters)));
- return isIt;
- } // equals()
-
- /**
- * A routine for parsing the MIME type out of a String.
- *
- * @throws NullPointerException if <code>rawdata</code> is null
- */
- private void parse(String rawdata) throws MimeTypeParseException {
- int slashIndex = rawdata.indexOf('/');
- int semIndex = rawdata.indexOf(';');
- if((slashIndex < 0) && (semIndex < 0)) {
- // neither character is present, so treat it
- // as an error
- throw new MimeTypeParseException("Unable to find a sub type.");
- } else if((slashIndex < 0) && (semIndex >= 0)) {
- // we have a ';' (and therefore a parameter list),
- // but no '/' indicating a sub type is present
- throw new MimeTypeParseException("Unable to find a sub type.");
- } else if((slashIndex >= 0) && (semIndex < 0)) {
- // we have a primary and sub type but no parameter list
- primaryType = rawdata.substring(0,slashIndex).
- trim().toLowerCase(Locale.ENGLISH);
- subType = rawdata.substring(slashIndex + 1).
- trim().toLowerCase(Locale.ENGLISH);
- parameters = new MimeTypeParameterList();
- } else if (slashIndex < semIndex) {
- // we have all three items in the proper sequence
- primaryType = rawdata.substring(0, slashIndex).
- trim().toLowerCase(Locale.ENGLISH);
- subType = rawdata.substring(slashIndex + 1,
- semIndex).trim().toLowerCase(Locale.ENGLISH);
- parameters = new
-MimeTypeParameterList(rawdata.substring(semIndex));
- } else {
- // we have a ';' lexically before a '/' which means we have a primary type
- // & a parameter list but no sub type
- throw new MimeTypeParseException("Unable to find a sub type.");
- }
-
- // now validate the primary and sub types
-
- // check to see if primary is valid
- if(!isValidToken(primaryType)) {
- throw new MimeTypeParseException("Primary type is invalid.");
- }
-
- // check to see if sub is valid
- if(!isValidToken(subType)) {
- throw new MimeTypeParseException("Sub type is invalid.");
- }
- }
-
- /**
- * Retrieve the primary type of this object.
- */
- public String getPrimaryType() {
- return primaryType;
- }
-
- /**
- * Retrieve the sub type of this object.
- */
- public String getSubType() {
- return subType;
- }
-
- /**
- * Retrieve a copy of this object's parameter list.
- */
- public MimeTypeParameterList getParameters() {
- return (MimeTypeParameterList)parameters.clone();
- }
-
- /**
- * Retrieve the value associated with the given name, or null if there
- * is no current association.
- */
- public String getParameter(String name) {
- return parameters.get(name);
- }
-
- /**
- * Set the value to be associated with the given name, replacing
- * any previous association.
- *
- * @throw IllegalArgumentException if parameter or value is illegal
- */
- public void setParameter(String name, String value) {
- parameters.set(name, value);
- }
-
- /**
- * Remove any value associated with the given name.
- *
- * @throw IllegalArgumentException if parameter may not be deleted
- */
- public void removeParameter(String name) {
- parameters.remove(name);
- }
-
- /**
- * Return the String representation of this object.
- */
- public String toString() {
- return getBaseType() + parameters.toString();
- }
-
- /**
- * Return a String representation of this object
- * without the parameter list.
- */
- public String getBaseType() {
- return primaryType + "/" + subType;
- }
-
- /**
- * Returns <code>true</code> if the primary type and the
- * subtype of this object are the same as the specified
- * <code>type</code>; otherwise returns <code>false</code>.
- *
- * @param type the type to compare to <code>this</code>'s type
- * @return <code>true</code> if the primary type and the
- * subtype of this object are the same as the
- * specified <code>type</code>; otherwise returns
- * <code>false</code>
- */
- public boolean match(MimeType type) {
- if (type == null)
- return false;
- return primaryType.equals(type.getPrimaryType())
- && (subType.equals("*")
- || type.getSubType().equals("*")
- || (subType.equals(type.getSubType())));
- }
-
- /**
- * Returns <code>true</code> if the primary type and the
- * subtype of this object are the same as the content type
- * described in <code>rawdata</code>; otherwise returns
- * <code>false</code>.
- *
- * @param rawdata the raw data to be examined
- * @return <code>true</code> if the primary type and the
- * subtype of this object are the same as the content type
- * described in <code>rawdata</code>; otherwise returns
- * <code>false</code>; if <code>rawdata</code> is
- * <code>null</code>, returns <code>false</code>
- */
- public boolean match(String rawdata) throws MimeTypeParseException {
- if (rawdata == null)
- return false;
- return match(new MimeType(rawdata));
- }
-
- /**
- * The object implements the writeExternal method to save its contents
- * by calling the methods of DataOutput for its primitive values or
- * calling the writeObject method of ObjectOutput for objects, strings
- * and arrays.
- * @exception IOException Includes any I/O exceptions that may occur
- */
- public void writeExternal(ObjectOutput out) throws IOException {
- String s = toString(); // contains ASCII chars only
- // one-to-one correspondence between ASCII char and byte in UTF string
- if (s.length() <= 65535) { // 65535 is max length of UTF string
- out.writeUTF(s);
- } else {
- out.writeByte(0);
- out.writeByte(0);
- out.writeInt(s.length());
- out.write(s.getBytes());
- }
- }
-
- /**
- * The object implements the readExternal method to restore its
- * contents by calling the methods of DataInput for primitive
- * types and readObject for objects, strings and arrays. The
- * readExternal method must read the values in the same sequence
- * and with the same types as were written by writeExternal.
- * @exception ClassNotFoundException If the class for an object being
- * restored cannot be found.
- */
- public void readExternal(ObjectInput in) throws IOException,
-ClassNotFoundException {
- String s = in.readUTF();
- if (s == null || s.length() == 0) { // long mime type
- byte[] ba = new byte[in.readInt()];
- in.readFully(ba);
- s = new String(ba);
- }
- try {
- parse(s);
- } catch(MimeTypeParseException e) {
- throw new IOException(e.toString());
- }
- }
-
- /**
- * Returns a clone of this object.
- * @return a clone of this object
- */
-
- public Object clone() {
- MimeType newObj = null;
- try {
- newObj = (MimeType)super.clone();
- } catch (CloneNotSupportedException cannotHappen) {
- }
- newObj.parameters = (MimeTypeParameterList)parameters.clone();
- return newObj;
- }
-
- private String primaryType;
- private String subType;
- private MimeTypeParameterList parameters;
-
- // below here be scary parsing related things
-
- /**
- * Determines whether or not a given character belongs to a legal token.
- */
- private static boolean isTokenChar(char c) {
- return ((c > 040) && (c < 0177)) && (TSPECIALS.indexOf(c) < 0);
- }
-
- /**
- * Determines whether or not a given string is a legal token.
- *
- * @throws NullPointerException if <code>s</code> is null
- */
- private boolean isValidToken(String s) {
- int len = s.length();
- if(len > 0) {
- for (int i = 0; i < len; ++i) {
- char c = s.charAt(i);
- if (!isTokenChar(c)) {
- return false;
- }
- }
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * A string that holds all the special chars.
- */
-
- private static final String TSPECIALS = "()<>@,;:\\\"/[]?=";
-
-} // class MimeType
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/MimeTypeParameterList.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,404 +0,0 @@
-/*
- * Copyright (c) 1997, 2013, 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 java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-
-/**
- * An object that encapsulates the parameter list of a MimeType
- * as defined in RFC 2045 and 2046.
- *
- * @author jeff.dunn@eng.sun.com
- */
-class MimeTypeParameterList implements Cloneable {
-
- /**
- * Default constructor.
- */
- public MimeTypeParameterList() {
- parameters = new Hashtable<>();
- }
-
- public MimeTypeParameterList(String rawdata)
- throws MimeTypeParseException
- {
- parameters = new Hashtable<>();
-
- // now parse rawdata
- parse(rawdata);
- }
-
- public int hashCode() {
- int code = Integer.MAX_VALUE/45; // "random" value for empty lists
- String paramName = null;
- Enumeration<String> enum_ = this.getNames();
-
- while (enum_.hasMoreElements()) {
- paramName = enum_.nextElement();
- code += paramName.hashCode();
- code += this.get(paramName).hashCode();
- }
-
- return code;
- } // hashCode()
-
- /**
- * Two parameter lists are considered equal if they have exactly
- * the same set of parameter names and associated values. The
- * order of the parameters is not considered.
- */
- public boolean equals(Object thatObject) {
- //System.out.println("MimeTypeParameterList.equals("+this+","+thatObject+")");
- if (!(thatObject instanceof MimeTypeParameterList)) {
- return false;
- }
- MimeTypeParameterList that = (MimeTypeParameterList)thatObject;
- if (this.size() != that.size()) {
- return false;
- }
- String name = null;
- String thisValue = null;
- String thatValue = null;
- Set<Map.Entry<String, String>> entries = parameters.entrySet();
- Iterator<Map.Entry<String, String>> iterator = entries.iterator();
- Map.Entry<String, String> entry = null;
- while (iterator.hasNext()) {
- entry = iterator.next();
- name = entry.getKey();
- thisValue = entry.getValue();
- thatValue = that.parameters.get(name);
- if ((thisValue == null) || (thatValue == null)) {
- // both null -> equal, only one null -> not equal
- if (thisValue != thatValue) {
- return false;
- }
- } else if (!thisValue.equals(thatValue)) {
- return false;
- }
- } // while iterator
-
- return true;
- } // equals()
-
- /**
- * A routine for parsing the parameter list out of a String.
- */
- protected void parse(String rawdata) throws MimeTypeParseException {
- int length = rawdata.length();
- if(length > 0) {
- int currentIndex = skipWhiteSpace(rawdata, 0);
- int lastIndex = 0;
-
- if(currentIndex < length) {
- char currentChar = rawdata.charAt(currentIndex);
- while ((currentIndex < length) && (currentChar == ';')) {
- String name;
- String value;
- boolean foundit;
-
- // eat the ';'
- ++currentIndex;
-
- // now parse the parameter name
-
- // skip whitespace
- currentIndex = skipWhiteSpace(rawdata, currentIndex);
-
- if(currentIndex < length) {
- // find the end of the token char run
- lastIndex = currentIndex;
- currentChar = rawdata.charAt(currentIndex);
- while((currentIndex < length) && isTokenChar(currentChar)) {
- ++currentIndex;
- currentChar = rawdata.charAt(currentIndex);
- }
- name = rawdata.substring(lastIndex, currentIndex).toLowerCase();
-
- // now parse the '=' that separates the name from the value
-
- // skip whitespace
- currentIndex = skipWhiteSpace(rawdata, currentIndex);
-
- if((currentIndex < length) && (rawdata.charAt(currentIndex) == '=')) {
- // eat it and parse the parameter value
- ++currentIndex;
-
- // skip whitespace
- currentIndex = skipWhiteSpace(rawdata, currentIndex);
-
- if(currentIndex < length) {
- // now find out whether or not we have a quoted value
- currentChar = rawdata.charAt(currentIndex);
- if(currentChar == '"') {
- // yup it's quoted so eat it and capture the quoted string
- ++currentIndex;
- lastIndex = currentIndex;
-
- if(currentIndex < length) {
- // find the next unescaped quote
- foundit = false;
- while((currentIndex < length) && !foundit) {
- currentChar = rawdata.charAt(currentIndex);
- if(currentChar == '\\') {
- // found an escape sequence so pass this and the next character
- currentIndex += 2;
- } else if(currentChar == '"') {
- // found it!
- foundit = true;
- } else {
- ++currentIndex;
- }
- }
- if(currentChar == '"') {
- value = unquote(rawdata.substring(lastIndex, currentIndex));
- // eat the quote
- ++currentIndex;
- } else {
- throw new MimeTypeParseException("Encountered unterminated quoted parameter value.");
- }
- } else {
- throw new MimeTypeParseException("Encountered unterminated quoted parameter value.");
- }
- } else if(isTokenChar(currentChar)) {
- // nope it's an ordinary token so it ends with a non-token char
- lastIndex = currentIndex;
- foundit = false;
- while((currentIndex < length) && !foundit) {
- currentChar = rawdata.charAt(currentIndex);
-
- if(isTokenChar(currentChar)) {
- ++currentIndex;
- } else {
- foundit = true;
- }
- }
- value = rawdata.substring(lastIndex, currentIndex);
- } else {
- // it ain't a value
- throw new MimeTypeParseException("Unexpected character encountered at index " + currentIndex);
- }
-
- // now put the data into the hashtable
- parameters.put(name, value);
- } else {
- throw new MimeTypeParseException("Couldn't find a value for parameter named " + name);
- }
- } else {
- throw new MimeTypeParseException("Couldn't find the '=' that separates a parameter name from its value.");
- }
- } else {
- throw new MimeTypeParseException("Couldn't find parameter name");
- }
-
- // setup the next iteration
- currentIndex = skipWhiteSpace(rawdata, currentIndex);
- if(currentIndex < length) {
- currentChar = rawdata.charAt(currentIndex);
- }
- }
- if(currentIndex < length) {
- throw new MimeTypeParseException("More characters encountered in input than expected.");
- }
- }
- }
- }
-
- /**
- * return the number of name-value pairs in this list.
- */
- public int size() {
- return parameters.size();
- }
-
- /**
- * Determine whether or not this list is empty.
- */
- public boolean isEmpty() {
- return parameters.isEmpty();
- }
-
- /**
- * Retrieve the value associated with the given name, or null if there
- * is no current association.
- */
- public String get(String name) {
- return parameters.get(name.trim().toLowerCase());
- }
-
- /**
- * Set the value to be associated with the given name, replacing
- * any previous association.
- */
- public void set(String name, String value) {
- parameters.put(name.trim().toLowerCase(), value);
- }
-
- /**
- * Remove any value associated with the given name.
- */
- public void remove(String name) {
- parameters.remove(name.trim().toLowerCase());
- }
-
- /**
- * Retrieve an enumeration of all the names in this list.
- */
- public Enumeration<String> getNames() {
- return parameters.keys();
- }
-
- public String toString() {
- // Heuristic: 8 characters per field
- StringBuilder buffer = new StringBuilder(parameters.size() * 16);
-
- Enumeration<String> keys = parameters.keys();
- while(keys.hasMoreElements())
- {
- buffer.append("; ");
-
- String key = keys.nextElement();
- buffer.append(key);
- buffer.append('=');
- buffer.append(quote(parameters.get(key)));
- }
-
- return buffer.toString();
- }
-
- /**
- * @return a clone of this object
- */
- @SuppressWarnings("unchecked") // Cast from clone
- public Object clone() {
- MimeTypeParameterList newObj = null;
- try {
- newObj = (MimeTypeParameterList)super.clone();
- } catch (CloneNotSupportedException cannotHappen) {
- }
- newObj.parameters = (Hashtable<String, String>)parameters.clone();
- return newObj;
- }
-
- private Hashtable<String, String> parameters;
-
- // below here be scary parsing related things
-
- /**
- * Determine whether or not a given character belongs to a legal token.
- */
- private static boolean isTokenChar(char c) {
- return ((c > 040) && (c < 0177)) && (TSPECIALS.indexOf(c) < 0);
- }
-
- /**
- * return the index of the first non white space character in
- * rawdata at or after index i.
- */
- private static int skipWhiteSpace(String rawdata, int i) {
- int length = rawdata.length();
- if (i < length) {
- char c = rawdata.charAt(i);
- while ((i < length) && Character.isWhitespace(c)) {
- ++i;
- c = rawdata.charAt(i);
- }
- }
-
- return i;
- }
-
- /**
- * A routine that knows how and when to quote and escape the given value.
- */
- private static String quote(String value) {
- boolean needsQuotes = false;
-
- // check to see if we actually have to quote this thing
- int length = value.length();
- for(int i = 0; (i < length) && !needsQuotes; ++i) {
- needsQuotes = !isTokenChar(value.charAt(i));
- }
-
- if(needsQuotes) {
- StringBuilder buffer = new StringBuilder((int)(length * 1.5));
-
- // add the initial quote
- buffer.append('"');
-
- // add the properly escaped text
- for(int i = 0; i < length; ++i) {
- char c = value.charAt(i);
- if((c == '\\') || (c == '"')) {
- buffer.append('\\');
- }
- buffer.append(c);
- }
-
- // add the closing quote
- buffer.append('"');
-
- return buffer.toString();
- }
- else
- {
- return value;
- }
- }
-
- /**
- * A routine that knows how to strip the quotes and escape sequences from the given value.
- */
- private static String unquote(String value) {
- int valueLength = value.length();
- StringBuilder buffer = new StringBuilder(valueLength);
-
- boolean escaped = false;
- for(int i = 0; i < valueLength; ++i) {
- char currentChar = value.charAt(i);
- if(!escaped && (currentChar != '\\')) {
- buffer.append(currentChar);
- } else if(escaped) {
- buffer.append(currentChar);
- escaped = false;
- } else {
- escaped = true;
- }
- }
-
- return buffer.toString();
- }
-
- /**
- * A string that holds all the special chars.
- */
- private static final String TSPECIALS = "()<>@,;:\\\"/[]?=";
-
-}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/MimeTypeParseException.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 1997, 2006, 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;
-
-
-/**
- * A class to encapsulate MimeType parsing related exceptions
- *
- * @serial exclude
- * @since 1.3
- */
-public class MimeTypeParseException extends Exception {
-
- // use serialVersionUID from JDK 1.2.2 for interoperability
- private static final long serialVersionUID = -5604407764691570741L;
-
- /**
- * Constructs a MimeTypeParseException with no specified detail message.
- */
- public MimeTypeParseException() {
- super();
- }
-
- /**
- * Constructs a MimeTypeParseException with the specified detail message.
- *
- * @param s the detail message.
- */
- public MimeTypeParseException(String s) {
- super(s);
- }
-} // class MimeTypeParseException
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/StringSelection.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +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 java.io.*;
-
-
-/**
- * A <code>Transferable</code> which implements the capability required
- * to transfer a <code>String</code>.
- *
- * This <code>Transferable</code> properly supports
- * <code>DataFlavor.stringFlavor</code>
- * and all equivalent flavors. Support for
- * <code>DataFlavor.plainTextFlavor</code>
- * and all equivalent flavors is <b>deprecated</b>. No other
- * <code>DataFlavor</code>s are supported.
- *
- * @see java.awt.datatransfer.DataFlavor#stringFlavor
- * @see java.awt.datatransfer.DataFlavor#plainTextFlavor
- */
-public class StringSelection implements Transferable, ClipboardOwner {
-
- private static final int STRING = 0;
- private static final int PLAIN_TEXT = 1;
-
- @SuppressWarnings("deprecation")
- private static final DataFlavor[] flavors = {
- DataFlavor.stringFlavor,
- DataFlavor.plainTextFlavor // deprecated
- };
-
- private String data;
-
- /**
- * Creates a <code>Transferable</code> capable of transferring
- * the specified <code>String</code>.
- * @param data the string to be transferred
- */
- public StringSelection(String data) {
- this.data = data;
- }
-
- /**
- * Returns an array of flavors in which this <code>Transferable</code>
- * can provide the data. <code>DataFlavor.stringFlavor</code>
- * is properly supported.
- * Support for <code>DataFlavor.plainTextFlavor</code> is
- * <b>deprecated</b>.
- *
- * @return an array of length two, whose elements are <code>DataFlavor.
- * stringFlavor</code> and <code>DataFlavor.plainTextFlavor</code>
- */
- public DataFlavor[] getTransferDataFlavors() {
- // returning flavors itself would allow client code to modify
- // our internal behavior
- return flavors.clone();
- }
-
- /**
- * Returns whether the requested flavor is supported by this
- * <code>Transferable</code>.
- *
- * @param flavor the requested flavor for the data
- * @return true if <code>flavor</code> is equal to
- * <code>DataFlavor.stringFlavor</code> or
- * <code>DataFlavor.plainTextFlavor</code>; false if <code>flavor</code>
- * is not one of the above flavors
- * @throws NullPointerException if flavor is <code>null</code>
- */
- public boolean isDataFlavorSupported(DataFlavor flavor) {
- // JCK Test StringSelection0003: if 'flavor' is null, throw NPE
- for (int i = 0; i < flavors.length; i++) {
- if (flavor.equals(flavors[i])) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns the <code>Transferable</code>'s data in the requested
- * <code>DataFlavor</code> if possible. If the desired flavor is
- * <code>DataFlavor.stringFlavor</code>, or an equivalent flavor,
- * the <code>String</code> representing the selection is
- * returned. If the desired flavor is
- * <code>DataFlavor.plainTextFlavor</code>,
- * or an equivalent flavor, a <code>Reader</code> is returned.
- * <b>Note:</b> The behavior of this method for
- * <code>DataFlavor.plainTextFlavor</code>
- * and equivalent <code>DataFlavor</code>s is inconsistent with the
- * definition of <code>DataFlavor.plainTextFlavor</code>.
- *
- * @param flavor the requested flavor for the data
- * @return the data in the requested flavor, as outlined above
- * @throws UnsupportedFlavorException if the requested data flavor is
- * not equivalent to either <code>DataFlavor.stringFlavor</code>
- * or <code>DataFlavor.plainTextFlavor</code>
- * @throws IOException if an IOException occurs while retrieving the data.
- * By default, StringSelection never throws this exception, but a
- * subclass may.
- * @throws NullPointerException if flavor is <code>null</code>
- * @see java.io.Reader
- */
- public Object getTransferData(DataFlavor flavor)
- throws UnsupportedFlavorException, IOException
- {
- // JCK Test StringSelection0007: if 'flavor' is null, throw NPE
- if (flavor.equals(flavors[STRING])) {
- return (Object)data;
- } else if (flavor.equals(flavors[PLAIN_TEXT])) {
- return new StringReader(data == null ? "" : data);
- } else {
- throw new UnsupportedFlavorException(flavor);
- }
- }
-
- public void lostOwnership(Clipboard clipboard, Transferable contents) {
- }
-}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/SystemFlavorMap.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1094 +0,0 @@
-/*
- * Copyright (c) 1997, 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.datatransfer.DesktopDatatransferService;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.ref.SoftReference;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * The SystemFlavorMap is a configurable map between "natives" (Strings), which
- * correspond to platform-specific data formats, and "flavors" (DataFlavors),
- * which correspond to platform-independent MIME types. This mapping is used
- * by the data transfer subsystem to transfer data between Java and native
- * applications, and between Java applications in separate VMs.
- *
- * @since 1.2
- */
-public final class SystemFlavorMap implements FlavorMap, FlavorTable {
-
- /**
- * Constant prefix used to tag Java types converted to native platform
- * type.
- */
- private static String JavaMIME = "JAVA_DATAFLAVOR:";
-
- private static final Object FLAVOR_MAP_KEY = new Object();
-
- /**
- * The list of valid, decoded text flavor representation classes, in order
- * from best to worst.
- */
- private static final String[] UNICODE_TEXT_CLASSES = {
- "java.io.Reader", "java.lang.String", "java.nio.CharBuffer", "\"[C\""
- };
-
- /**
- * The list of valid, encoded text flavor representation classes, in order
- * from best to worst.
- */
- private static final String[] ENCODED_TEXT_CLASSES = {
- "java.io.InputStream", "java.nio.ByteBuffer", "\"[B\""
- };
-
- /**
- * A String representing text/plain MIME type.
- */
- private static final String TEXT_PLAIN_BASE_TYPE = "text/plain";
-
- /**
- * A String representing text/html MIME type.
- */
- private static final String HTML_TEXT_BASE_TYPE = "text/html";
-
- /**
- * Maps native Strings to Lists of DataFlavors (or base type Strings for
- * text DataFlavors).
- * Do not use the field directly, use getNativeToFlavor() instead.
- */
- private final Map<String, LinkedHashSet<DataFlavor>> nativeToFlavor = new HashMap<>();
-
- /**
- * Accessor to nativeToFlavor map. Since we use lazy initialization we must
- * use this accessor instead of direct access to the field which may not be
- * initialized yet. This method will initialize the field if needed.
- *
- * @return nativeToFlavor
- */
- private Map<String, LinkedHashSet<DataFlavor>> getNativeToFlavor() {
- if (!isMapInitialized) {
- initSystemFlavorMap();
- }
- return nativeToFlavor;
- }
-
- /**
- * Maps DataFlavors (or base type Strings for text DataFlavors) to Lists of
- * native Strings.
- * Do not use the field directly, use getFlavorToNative() instead.
- */
- private final Map<DataFlavor, LinkedHashSet<String>> flavorToNative = new HashMap<>();
-
- /**
- * Accessor to flavorToNative map. Since we use lazy initialization we must
- * use this accessor instead of direct access to the field which may not be
- * initialized yet. This method will initialize the field if needed.
- *
- * @return flavorToNative
- */
- private synchronized Map<DataFlavor, LinkedHashSet<String>> getFlavorToNative() {
- if (!isMapInitialized) {
- initSystemFlavorMap();
- }
- return flavorToNative;
- }
-
- /**
- * Maps a text DataFlavor primary mime-type to the native. Used only to store
- * standard mappings registered in the flavormap.properties
- * Do not use this field directly, use getTextTypeToNative() instead.
- */
- private Map<String, LinkedHashSet<String>> textTypeToNative = new HashMap<>();
-
- /**
- * Shows if the object has been initialized.
- */
- private boolean isMapInitialized = false;
-
- /**
- * An accessor to textTypeToNative map. Since we use lazy initialization we
- * must use this accessor instead of direct access to the field which may not
- * be initialized yet. This method will initialize the field if needed.
- *
- * @return textTypeToNative
- */
- private synchronized Map<String, LinkedHashSet<String>> getTextTypeToNative() {
- if (!isMapInitialized) {
- initSystemFlavorMap();
- // From this point the map should not be modified
- textTypeToNative = Collections.unmodifiableMap(textTypeToNative);
- }
- return textTypeToNative;
- }
-
- /**
- * Caches the result of getNativesForFlavor(). Maps DataFlavors to
- * SoftReferences which reference LinkedHashSet of String natives.
- */
- private final SoftCache<DataFlavor, String> nativesForFlavorCache = new SoftCache<>();
-
- /**
- * Caches the result getFlavorsForNative(). Maps String natives to
- * SoftReferences which reference LinkedHashSet of DataFlavors.
- */
- private final SoftCache<String, DataFlavor> flavorsForNativeCache = new SoftCache<>();
-
- /**
- * Dynamic mapping generation used for text mappings should not be applied
- * to the DataFlavors and String natives for which the mappings have been
- * explicitly specified with setFlavorsForNative() or
- * setNativesForFlavor(). This keeps all such keys.
- */
- private Set<Object> disabledMappingGenerationKeys = new HashSet<>();
-
- /**
- * Returns the default FlavorMap for this thread's ClassLoader.
- *
- * @return the default FlavorMap for this thread's ClassLoader
- */
- public static FlavorMap getDefaultFlavorMap() {
- return DataFlavorUtil.getDesktopService().getFlavorMap(SystemFlavorMap::new);
- }
-
- private SystemFlavorMap() {
- }
-
- /**
- * Initializes a SystemFlavorMap by reading flavormap.properties
- * For thread-safety must be called under lock on this.
- */
- private void initSystemFlavorMap() {
- if (isMapInitialized) {
- return;
- }
- isMapInitialized = true;
-
- InputStream is = SystemFlavorMap.class.getResourceAsStream("/sun/datatransfer/resources/flavormap.properties");
- if (is == null) {
- throw new InternalError("Default flavor mapping not found");
- }
-
- try (InputStreamReader isr = new InputStreamReader(is);
- BufferedReader reader = new BufferedReader(isr)) {
- String line;
- while ((line = reader.readLine()) != null) {
- line = line.trim();
- if (line.startsWith("#") || line.isEmpty()) continue;
- while (line.endsWith("\\")) {
- line = line.substring(0, line.length() - 1) + reader.readLine().trim();
- }
- int delimiterPosition = line.indexOf('=');
- String key = line.substring(0, delimiterPosition).replaceAll("\\ ", " ");
- String[] values = line.substring(delimiterPosition + 1, line.length()).split(",");
- for (String value : values) {
- try {
- value = loadConvert(value);
- MimeType mime = new MimeType(value);
- if ("text".equals(mime.getPrimaryType())) {
- String charset = mime.getParameter("charset");
- if (DataFlavorUtil.doesSubtypeSupportCharset(mime.getSubType(), charset))
- {
- // We need to store the charset and eoln
- // parameters, if any, so that the
- // DataTransferer will have this information
- // for conversion into the native format.
- DesktopDatatransferService desktopService =
- DataFlavorUtil.getDesktopService();
- if (desktopService.isDesktopPresent()) {
- desktopService.registerTextFlavorProperties(
- key, charset,
- mime.getParameter("eoln"),
- mime.getParameter("terminators"));
- }
- }
-
- // But don't store any of these parameters in the
- // DataFlavor itself for any text natives (even
- // non-charset ones). The SystemFlavorMap will
- // synthesize the appropriate mappings later.
- mime.removeParameter("charset");
- mime.removeParameter("class");
- mime.removeParameter("eoln");
- mime.removeParameter("terminators");
- value = mime.toString();
- }
- } catch (MimeTypeParseException e) {
- e.printStackTrace();
- continue;
- }
-
- DataFlavor flavor;
- try {
- flavor = new DataFlavor(value);
- } catch (Exception e) {
- try {
- flavor = new DataFlavor(value, null);
- } catch (Exception ee) {
- ee.printStackTrace();
- continue;
- }
- }
-
- final LinkedHashSet<DataFlavor> dfs = new LinkedHashSet<>();
- dfs.add(flavor);
-
- if ("text".equals(flavor.getPrimaryType())) {
- dfs.addAll(convertMimeTypeToDataFlavors(value));
- store(flavor.mimeType.getBaseType(), key, getTextTypeToNative());
- }
-
- for (DataFlavor df : dfs) {
- store(df, key, getFlavorToNative());
- store(key, df, getNativeToFlavor());
- }
- }
- }
- } catch (IOException e) {
- throw new InternalError("Error reading default flavor mapping", e);
- }
- }
-
- // Copied from java.util.Properties
- private static String loadConvert(String theString) {
- char aChar;
- int len = theString.length();
- StringBuilder outBuffer = new StringBuilder(len);
-
- for (int x = 0; x < len; ) {
- aChar = theString.charAt(x++);
- if (aChar == '\\') {
- aChar = theString.charAt(x++);
- if (aChar == 'u') {
- // Read the xxxx
- int value = 0;
- for (int i = 0; i < 4; i++) {
- aChar = theString.charAt(x++);
- switch (aChar) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9': {
- value = (value << 4) + aChar - '0';
- break;
- }
- case 'a': case 'b': case 'c':
- case 'd': case 'e': case 'f': {
- value = (value << 4) + 10 + aChar - 'a';
- break;
- }
- case 'A': case 'B': case 'C':
- case 'D': case 'E': case 'F': {
- value = (value << 4) + 10 + aChar - 'A';
- break;
- }
- default: {
- throw new IllegalArgumentException(
- "Malformed \\uxxxx encoding.");
- }
- }
- }
- outBuffer.append((char)value);
- } else {
- if (aChar == 't') {
- aChar = '\t';
- } else if (aChar == 'r') {
- aChar = '\r';
- } else if (aChar == 'n') {
- aChar = '\n';
- } else if (aChar == 'f') {
- aChar = '\f';
- }
- outBuffer.append(aChar);
- }
- } else {
- outBuffer.append(aChar);
- }
- }
- return outBuffer.toString();
- }
-
- /**
- * Stores the listed object under the specified hash key in map. Unlike a
- * standard map, the listed object will not replace any object already at
- * the appropriate Map location, but rather will be appended to a List
- * stored in that location.
- */
- private <H, L> void store(H hashed, L listed, Map<H, LinkedHashSet<L>> map) {
- LinkedHashSet<L> list = map.get(hashed);
- if (list == null) {
- list = new LinkedHashSet<>(1);
- map.put(hashed, list);
- }
- if (!list.contains(listed)) {
- list.add(listed);
- }
- }
-
- /**
- * Semantically equivalent to 'nativeToFlavor.get(nat)'. This method
- * handles the case where 'nat' is not found in 'nativeToFlavor'. In that
- * case, a new DataFlavor is synthesized, stored, and returned, if and
- * only if the specified native is encoded as a Java MIME type.
- */
- private LinkedHashSet<DataFlavor> nativeToFlavorLookup(String nat) {
- LinkedHashSet<DataFlavor> flavors = getNativeToFlavor().get(nat);
-
- if (nat != null && !disabledMappingGenerationKeys.contains(nat)) {
- DesktopDatatransferService desktopService = DataFlavorUtil.getDesktopService();
- if (desktopService.isDesktopPresent()) {
- LinkedHashSet<DataFlavor> platformFlavors =
- desktopService.getPlatformMappingsForNative(nat);
- if (!platformFlavors.isEmpty()) {
- if (flavors != null) {
- // Prepending the platform-specific mappings ensures
- // that the flavors added with
- // addFlavorForUnencodedNative() are at the end of
- // list.
- platformFlavors.addAll(flavors);
- }
- flavors = platformFlavors;
- }
- }
- }
-
- if (flavors == null && isJavaMIMEType(nat)) {
- String decoded = decodeJavaMIMEType(nat);
- DataFlavor flavor = null;
-
- try {
- flavor = new DataFlavor(decoded);
- } catch (Exception e) {
- System.err.println("Exception \"" + e.getClass().getName() +
- ": " + e.getMessage() +
- "\"while constructing DataFlavor for: " +
- decoded);
- }
-
- if (flavor != null) {
- flavors = new LinkedHashSet<>(1);
- getNativeToFlavor().put(nat, flavors);
- flavors.add(flavor);
- flavorsForNativeCache.remove(nat);
-
- LinkedHashSet<String> natives = getFlavorToNative().get(flavor);
- if (natives == null) {
- natives = new LinkedHashSet<>(1);
- getFlavorToNative().put(flavor, natives);
- }
- natives.add(nat);
- nativesForFlavorCache.remove(flavor);
- }
- }
-
- return (flavors != null) ? flavors : new LinkedHashSet<>(0);
- }
-
- /**
- * Semantically equivalent to 'flavorToNative.get(flav)'. This method
- * handles the case where 'flav' is not found in 'flavorToNative' depending
- * on the value of passes 'synthesize' parameter. If 'synthesize' is
- * SYNTHESIZE_IF_NOT_FOUND a native is synthesized, stored, and returned by
- * encoding the DataFlavor's MIME type. Otherwise an empty List is returned
- * and 'flavorToNative' remains unaffected.
- */
- private LinkedHashSet<String> flavorToNativeLookup(final DataFlavor flav,
- final boolean synthesize) {
-
- LinkedHashSet<String> natives = getFlavorToNative().get(flav);
-
- if (flav != null && !disabledMappingGenerationKeys.contains(flav)) {
- DesktopDatatransferService desktopService = DataFlavorUtil.getDesktopService();
- if (desktopService.isDesktopPresent()) {
- LinkedHashSet<String> platformNatives =
- desktopService.getPlatformMappingsForFlavor(flav);
- if (!platformNatives.isEmpty()) {
- if (natives != null) {
- // Prepend the platform-specific mappings to ensure
- // that the natives added with
- // addUnencodedNativeForFlavor() are at the end of
- // list.
- platformNatives.addAll(natives);
- }
- natives = platformNatives;
- }
- }
- }
-
- if (natives == null) {
- if (synthesize) {
- String encoded = encodeDataFlavor(flav);
- natives = new LinkedHashSet<>(1);
- getFlavorToNative().put(flav, natives);
- natives.add(encoded);
-
- LinkedHashSet<DataFlavor> flavors = getNativeToFlavor().get(encoded);
- if (flavors == null) {
- flavors = new LinkedHashSet<>(1);
- getNativeToFlavor().put(encoded, flavors);
- }
- flavors.add(flav);
-
- nativesForFlavorCache.remove(flav);
- flavorsForNativeCache.remove(encoded);
- } else {
- natives = new LinkedHashSet<>(0);
- }
- }
-
- return new LinkedHashSet<>(natives);
- }
-
- /**
- * Returns a <code>List</code> of <code>String</code> natives to which the
- * specified <code>DataFlavor</code> can be translated by the data transfer
- * subsystem. The <code>List</code> will be sorted from best native to
- * worst. That is, the first native will best reflect data in the specified
- * flavor to the underlying native platform.
- * <p>
- * If the specified <code>DataFlavor</code> is previously unknown to the
- * data transfer subsystem and the data transfer subsystem is unable to
- * translate this <code>DataFlavor</code> to any existing native, then
- * invoking this method will establish a
- * mapping in both directions between the specified <code>DataFlavor</code>
- * and an encoded version of its MIME type as its native.
- *
- * @param flav the <code>DataFlavor</code> whose corresponding natives
- * should be returned. If <code>null</code> is specified, all
- * natives currently known to the data transfer subsystem are
- * returned in a non-deterministic order.
- * @return a <code>java.util.List</code> of <code>java.lang.String</code>
- * objects which are platform-specific representations of platform-
- * specific data formats
- *
- * @see #encodeDataFlavor
- * @since 1.4
- */
- @Override
- public synchronized List<String> getNativesForFlavor(DataFlavor flav) {
- LinkedHashSet<String> retval = nativesForFlavorCache.check(flav);
- if (retval != null) {
- return new ArrayList<>(retval);
- }
-
- if (flav == null) {
- retval = new LinkedHashSet<>(getNativeToFlavor().keySet());
- } else if (disabledMappingGenerationKeys.contains(flav)) {
- // In this case we shouldn't synthesize a native for this flavor,
- // since its mappings were explicitly specified.
- retval = flavorToNativeLookup(flav, false);
- } else if (DataFlavorUtil.isFlavorCharsetTextType(flav)) {
- retval = new LinkedHashSet<>(0);
-
- // For text/* flavors, flavor-to-native mappings specified in
- // flavormap.properties are stored per flavor's base type.
- if ("text".equals(flav.getPrimaryType())) {
- LinkedHashSet<String> textTypeNatives =
- getTextTypeToNative().get(flav.mimeType.getBaseType());
- if (textTypeNatives != null) {
- retval.addAll(textTypeNatives);
- }
- }
-
- // Also include text/plain natives, but don't duplicate Strings
- LinkedHashSet<String> textTypeNatives =
- getTextTypeToNative().get(TEXT_PLAIN_BASE_TYPE);
- if (textTypeNatives != null) {
- retval.addAll(textTypeNatives);
- }
-
- if (retval.isEmpty()) {
- retval = flavorToNativeLookup(flav, true);
- } else {
- // In this branch it is guaranteed that natives explicitly
- // listed for flav's MIME type were added with
- // addUnencodedNativeForFlavor(), so they have lower priority.
- retval.addAll(flavorToNativeLookup(flav, false));
- }
- } else if (DataFlavorUtil.isFlavorNoncharsetTextType(flav)) {
- retval = getTextTypeToNative().get(flav.mimeType.getBaseType());
-
- if (retval == null || retval.isEmpty()) {
- retval = flavorToNativeLookup(flav, true);
- } else {
- // In this branch it is guaranteed that natives explicitly
- // listed for flav's MIME type were added with
- // addUnencodedNativeForFlavor(), so they have lower priority.
- retval.addAll(flavorToNativeLookup(flav, false));
- }
- } else {
- retval = flavorToNativeLookup(flav, true);
- }
-
- nativesForFlavorCache.put(flav, retval);
- // Create a copy, because client code can modify the returned list.
- return new ArrayList<>(retval);
- }
-
- /**
- * Returns a <code>List</code> of <code>DataFlavor</code>s to which the
- * specified <code>String</code> native can be translated by the data
- * transfer subsystem. The <code>List</code> will be sorted from best
- * <code>DataFlavor</code> to worst. That is, the first
- * <code>DataFlavor</code> will best reflect data in the specified
- * native to a Java application.
- * <p>
- * If the specified native is previously unknown to the data transfer
- * subsystem, and that native has been properly encoded, then invoking this
- * method will establish a mapping in both directions between the specified
- * native and a <code>DataFlavor</code> whose MIME type is a decoded
- * version of the native.
- * <p>
- * If the specified native is not a properly encoded native and the
- * mappings for this native have not been altered with
- * <code>setFlavorsForNative</code>, then the contents of the
- * <code>List</code> is platform dependent, but <code>null</code>
- * cannot be returned.
- *
- * @param nat the native whose corresponding <code>DataFlavor</code>s
- * should be returned. If <code>null</code> is specified, all
- * <code>DataFlavor</code>s currently known to the data transfer
- * subsystem are returned in a non-deterministic order.
- * @return a <code>java.util.List</code> of <code>DataFlavor</code>
- * objects into which platform-specific data in the specified,
- * platform-specific native can be translated
- *
- * @see #encodeJavaMIMEType
- * @since 1.4
- */
- @Override
- public synchronized List<DataFlavor> getFlavorsForNative(String nat) {
- LinkedHashSet<DataFlavor> returnValue = flavorsForNativeCache.check(nat);
- if (returnValue != null) {
- return new ArrayList<>(returnValue);
- } else {
- returnValue = new LinkedHashSet<>();
- }
-
- if (nat == null) {
- for (String n : getNativesForFlavor(null)) {
- returnValue.addAll(getFlavorsForNative(n));
- }
- } else {
- final LinkedHashSet<DataFlavor> flavors = nativeToFlavorLookup(nat);
- if (disabledMappingGenerationKeys.contains(nat)) {
- return new ArrayList<>(flavors);
- }
-
- final LinkedHashSet<DataFlavor> flavorsWithSynthesized =
- nativeToFlavorLookup(nat);
-
- for (DataFlavor df : flavorsWithSynthesized) {
- returnValue.add(df);
- if ("text".equals(df.getPrimaryType())) {
- String baseType = df.mimeType.getBaseType();
- returnValue.addAll(convertMimeTypeToDataFlavors(baseType));
- }
- }
- }
- flavorsForNativeCache.put(nat, returnValue);
- return new ArrayList<>(returnValue);
- }
-
- @SuppressWarnings("deprecation")
- private static Set<DataFlavor> convertMimeTypeToDataFlavors(
- final String baseType) {
-
- final Set<DataFlavor> returnValue = new LinkedHashSet<>();
-
- String subType = null;
-
- try {
- final MimeType mimeType = new MimeType(baseType);
- subType = mimeType.getSubType();
- } catch (MimeTypeParseException mtpe) {
- // Cannot happen, since we checked all mappings
- // on load from flavormap.properties.
- }
-
- if (DataFlavorUtil.doesSubtypeSupportCharset(subType, null)) {
- if (TEXT_PLAIN_BASE_TYPE.equals(baseType))
- {
- returnValue.add(DataFlavor.stringFlavor);
- }
-
- for (String unicodeClassName : UNICODE_TEXT_CLASSES) {
- final String mimeType = baseType + ";charset=Unicode;class=" +
- unicodeClassName;
-
- final LinkedHashSet<String> mimeTypes =
- handleHtmlMimeTypes(baseType, mimeType);
- for (String mt : mimeTypes) {
- DataFlavor toAdd = null;
- try {
- toAdd = new DataFlavor(mt);
- } catch (ClassNotFoundException cannotHappen) {
- }
- returnValue.add(toAdd);
- }
- }
-
- for (String charset : DataFlavorUtil.standardEncodings()) {
-
- for (String encodedTextClass : ENCODED_TEXT_CLASSES) {
- final String mimeType =
- baseType + ";charset=" + charset +
- ";class=" + encodedTextClass;
-
- final LinkedHashSet<String> mimeTypes =
- handleHtmlMimeTypes(baseType, mimeType);
-
- for (String mt : mimeTypes) {
-
- DataFlavor df = null;
-
- try {
- df = new DataFlavor(mt);
- // Check for equality to plainTextFlavor so
- // that we can ensure that the exact charset of
- // plainTextFlavor, not the canonical charset
- // or another equivalent charset with a
- // different name, is used.
- if (df.equals(DataFlavor.plainTextFlavor)) {
- df = DataFlavor.plainTextFlavor;
- }
- } catch (ClassNotFoundException cannotHappen) {
- }
-
- returnValue.add(df);
- }
- }
- }
-
- if (TEXT_PLAIN_BASE_TYPE.equals(baseType))
- {
- returnValue.add(DataFlavor.plainTextFlavor);
- }
- } else {
- // Non-charset text natives should be treated as
- // opaque, 8-bit data in any of its various
- // representations.
- for (String encodedTextClassName : ENCODED_TEXT_CLASSES) {
- DataFlavor toAdd = null;
- try {
- toAdd = new DataFlavor(baseType +
- ";class=" + encodedTextClassName);
- } catch (ClassNotFoundException cannotHappen) {
- }
- returnValue.add(toAdd);
- }
- }
- return returnValue;
- }
-
- private static final String [] htmlDocumentTypes =
- new String [] {"all", "selection", "fragment"};
-
- private static LinkedHashSet<String> handleHtmlMimeTypes(String baseType,
- String mimeType) {
-
- LinkedHashSet<String> returnValues = new LinkedHashSet<>();
-
- if (HTML_TEXT_BASE_TYPE.equals(baseType)) {
- for (String documentType : htmlDocumentTypes) {
- returnValues.add(mimeType + ";document=" + documentType);
- }
- } else {
- returnValues.add(mimeType);
- }
-
- return returnValues;
- }
-
- /**
- * Returns a <code>Map</code> of the specified <code>DataFlavor</code>s to
- * their most preferred <code>String</code> native. Each native value will
- * be the same as the first native in the List returned by
- * <code>getNativesForFlavor</code> for the specified flavor.
- * <p>
- * If a specified <code>DataFlavor</code> is previously unknown to the
- * data transfer subsystem, then invoking this method will establish a
- * mapping in both directions between the specified <code>DataFlavor</code>
- * and an encoded version of its MIME type as its native.
- *
- * @param flavors an array of <code>DataFlavor</code>s which will be the
- * key set of the returned <code>Map</code>. If <code>null</code> is
- * specified, a mapping of all <code>DataFlavor</code>s known to the
- * data transfer subsystem to their most preferred
- * <code>String</code> natives will be returned.
- * @return a <code>java.util.Map</code> of <code>DataFlavor</code>s to
- * <code>String</code> natives
- *
- * @see #getNativesForFlavor
- * @see #encodeDataFlavor
- */
- @Override
- public synchronized Map<DataFlavor,String> getNativesForFlavors(DataFlavor[] flavors)
- {
- // Use getNativesForFlavor to generate extra natives for text flavors
- // and stringFlavor
-
- if (flavors == null) {
- List<DataFlavor> flavor_list = getFlavorsForNative(null);
- flavors = new DataFlavor[flavor_list.size()];
- flavor_list.toArray(flavors);
- }
-
- Map<DataFlavor, String> retval = new HashMap<>(flavors.length, 1.0f);
- for (DataFlavor flavor : flavors) {
- List<String> natives = getNativesForFlavor(flavor);
- String nat = (natives.isEmpty()) ? null : natives.get(0);
- retval.put(flavor, nat);
- }
-
- return retval;
- }
-
- /**
- * Returns a <code>Map</code> of the specified <code>String</code> natives
- * to their most preferred <code>DataFlavor</code>. Each
- * <code>DataFlavor</code> value will be the same as the first
- * <code>DataFlavor</code> in the List returned by
- * <code>getFlavorsForNative</code> for the specified native.
- * <p>
- * If a specified native is previously unknown to the data transfer
- * subsystem, and that native has been properly encoded, then invoking this
- * method will establish a mapping in both directions between the specified
- * native and a <code>DataFlavor</code> whose MIME type is a decoded
- * version of the native.
- *
- * @param natives an array of <code>String</code>s which will be the
- * key set of the returned <code>Map</code>. If <code>null</code> is
- * specified, a mapping of all supported <code>String</code> natives
- * to their most preferred <code>DataFlavor</code>s will be
- * returned.
- * @return a <code>java.util.Map</code> of <code>String</code> natives to
- * <code>DataFlavor</code>s
- *
- * @see #getFlavorsForNative
- * @see #encodeJavaMIMEType
- */
- @Override
- public synchronized Map<String,DataFlavor> getFlavorsForNatives(String[] natives)
- {
- // Use getFlavorsForNative to generate extra flavors for text natives
- if (natives == null) {
- List<String> nativesList = getNativesForFlavor(null);
- natives = new String[nativesList.size()];
- nativesList.toArray(natives);
- }
-
- Map<String, DataFlavor> retval = new HashMap<>(natives.length, 1.0f);
- for (String aNative : natives) {
- List<DataFlavor> flavors = getFlavorsForNative(aNative);
- DataFlavor flav = (flavors.isEmpty())? null : flavors.get(0);
- retval.put(aNative, flav);
- }
- return retval;
- }
-
- /**
- * Adds a mapping from the specified <code>DataFlavor</code> (and all
- * <code>DataFlavor</code>s equal to the specified <code>DataFlavor</code>)
- * to the specified <code>String</code> native.
- * Unlike <code>getNativesForFlavor</code>, the mapping will only be
- * established in one direction, and the native will not be encoded. To
- * establish a two-way mapping, call
- * <code>addFlavorForUnencodedNative</code> as well. The new mapping will
- * be of lower priority than any existing mapping.
- * This method has no effect if a mapping from the specified or equal
- * <code>DataFlavor</code> to the specified <code>String</code> native
- * already exists.
- *
- * @param flav the <code>DataFlavor</code> key for the mapping
- * @param nat the <code>String</code> native value for the mapping
- * @throws NullPointerException if flav or nat is <code>null</code>
- *
- * @see #addFlavorForUnencodedNative
- * @since 1.4
- */
- public synchronized void addUnencodedNativeForFlavor(DataFlavor flav,
- String nat) {
- Objects.requireNonNull(nat, "Null native not permitted");
- Objects.requireNonNull(flav, "Null flavor not permitted");
-
- LinkedHashSet<String> natives = getFlavorToNative().get(flav);
- if (natives == null) {
- natives = new LinkedHashSet<>(1);
- getFlavorToNative().put(flav, natives);
- }
- natives.add(nat);
- nativesForFlavorCache.remove(flav);
- }
-
- /**
- * Discards the current mappings for the specified <code>DataFlavor</code>
- * and all <code>DataFlavor</code>s equal to the specified
- * <code>DataFlavor</code>, and creates new mappings to the
- * specified <code>String</code> natives.
- * Unlike <code>getNativesForFlavor</code>, the mappings will only be
- * established in one direction, and the natives will not be encoded. To
- * establish two-way mappings, call <code>setFlavorsForNative</code>
- * as well. The first native in the array will represent the highest
- * priority mapping. Subsequent natives will represent mappings of
- * decreasing priority.
- * <p>
- * If the array contains several elements that reference equal
- * <code>String</code> natives, this method will establish new mappings
- * for the first of those elements and ignore the rest of them.
- * <p>
- * It is recommended that client code not reset mappings established by the
- * data transfer subsystem. This method should only be used for
- * application-level mappings.
- *
- * @param flav the <code>DataFlavor</code> key for the mappings
- * @param natives the <code>String</code> native values for the mappings
- * @throws NullPointerException if flav or natives is <code>null</code>
- * or if natives contains <code>null</code> elements
- *
- * @see #setFlavorsForNative
- * @since 1.4
- */
- public synchronized void setNativesForFlavor(DataFlavor flav,
- String[] natives) {
- Objects.requireNonNull(natives, "Null natives not permitted");
- Objects.requireNonNull(flav, "Null flavors not permitted");
-
- getFlavorToNative().remove(flav);
- for (String aNative : natives) {
- addUnencodedNativeForFlavor(flav, aNative);
- }
- disabledMappingGenerationKeys.add(flav);
- nativesForFlavorCache.remove(flav);
- }
-
- /**
- * Adds a mapping from a single <code>String</code> native to a single
- * <code>DataFlavor</code>. Unlike <code>getFlavorsForNative</code>, the
- * mapping will only be established in one direction, and the native will
- * not be encoded. To establish a two-way mapping, call
- * <code>addUnencodedNativeForFlavor</code> as well. The new mapping will
- * be of lower priority than any existing mapping.
- * This method has no effect if a mapping from the specified
- * <code>String</code> native to the specified or equal
- * <code>DataFlavor</code> already exists.
- *
- * @param nat the <code>String</code> native key for the mapping
- * @param flav the <code>DataFlavor</code> value for the mapping
- * @throws NullPointerException if nat or flav is <code>null</code>
- *
- * @see #addUnencodedNativeForFlavor
- * @since 1.4
- */
- public synchronized void addFlavorForUnencodedNative(String nat,
- DataFlavor flav) {
- Objects.requireNonNull(nat, "Null native not permitted");
- Objects.requireNonNull(flav, "Null flavor not permitted");
-
- LinkedHashSet<DataFlavor> flavors = getNativeToFlavor().get(nat);
- if (flavors == null) {
- flavors = new LinkedHashSet<>(1);
- getNativeToFlavor().put(nat, flavors);
- }
- flavors.add(flav);
- flavorsForNativeCache.remove(nat);
- }
-
- /**
- * Discards the current mappings for the specified <code>String</code>
- * native, and creates new mappings to the specified
- * <code>DataFlavor</code>s. Unlike <code>getFlavorsForNative</code>, the
- * mappings will only be established in one direction, and the natives need
- * not be encoded. To establish two-way mappings, call
- * <code>setNativesForFlavor</code> as well. The first
- * <code>DataFlavor</code> in the array will represent the highest priority
- * mapping. Subsequent <code>DataFlavor</code>s will represent mappings of
- * decreasing priority.
- * <p>
- * If the array contains several elements that reference equal
- * <code>DataFlavor</code>s, this method will establish new mappings
- * for the first of those elements and ignore the rest of them.
- * <p>
- * It is recommended that client code not reset mappings established by the
- * data transfer subsystem. This method should only be used for
- * application-level mappings.
- *
- * @param nat the <code>String</code> native key for the mappings
- * @param flavors the <code>DataFlavor</code> values for the mappings
- * @throws NullPointerException if nat or flavors is <code>null</code>
- * or if flavors contains <code>null</code> elements
- *
- * @see #setNativesForFlavor
- * @since 1.4
- */
- public synchronized void setFlavorsForNative(String nat,
- DataFlavor[] flavors) {
- Objects.requireNonNull(nat, "Null native not permitted");
- Objects.requireNonNull(flavors, "Null flavors not permitted");
-
- getNativeToFlavor().remove(nat);
- for (DataFlavor flavor : flavors) {
- addFlavorForUnencodedNative(nat, flavor);
- }
- disabledMappingGenerationKeys.add(nat);
- flavorsForNativeCache.remove(nat);
- }
-
- /**
- * Encodes a MIME type for use as a <code>String</code> native. The format
- * of an encoded representation of a MIME type is implementation-dependent.
- * The only restrictions are:
- * <ul>
- * <li>The encoded representation is <code>null</code> if and only if the
- * MIME type <code>String</code> is <code>null</code>.</li>
- * <li>The encoded representations for two non-<code>null</code> MIME type
- * <code>String</code>s are equal if and only if these <code>String</code>s
- * are equal according to <code>String.equals(Object)</code>.</li>
- * </ul>
- * <p>
- * The reference implementation of this method returns the specified MIME
- * type <code>String</code> prefixed with <code>JAVA_DATAFLAVOR:</code>.
- *
- * @param mimeType the MIME type to encode
- * @return the encoded <code>String</code>, or <code>null</code> if
- * mimeType is <code>null</code>
- */
- public static String encodeJavaMIMEType(String mimeType) {
- return (mimeType != null)
- ? JavaMIME + mimeType
- : null;
- }
-
- /**
- * Encodes a <code>DataFlavor</code> for use as a <code>String</code>
- * native. The format of an encoded <code>DataFlavor</code> is
- * implementation-dependent. The only restrictions are:
- * <ul>
- * <li>The encoded representation is <code>null</code> if and only if the
- * specified <code>DataFlavor</code> is <code>null</code> or its MIME type
- * <code>String</code> is <code>null</code>.</li>
- * <li>The encoded representations for two non-<code>null</code>
- * <code>DataFlavor</code>s with non-<code>null</code> MIME type
- * <code>String</code>s are equal if and only if the MIME type
- * <code>String</code>s of these <code>DataFlavor</code>s are equal
- * according to <code>String.equals(Object)</code>.</li>
- * </ul>
- * <p>
- * The reference implementation of this method returns the MIME type
- * <code>String</code> of the specified <code>DataFlavor</code> prefixed
- * with <code>JAVA_DATAFLAVOR:</code>.
- *
- * @param flav the <code>DataFlavor</code> to encode
- * @return the encoded <code>String</code>, or <code>null</code> if
- * flav is <code>null</code> or has a <code>null</code> MIME type
- */
- public static String encodeDataFlavor(DataFlavor flav) {
- return (flav != null)
- ? SystemFlavorMap.encodeJavaMIMEType(flav.getMimeType())
- : null;
- }
-
- /**
- * Returns whether the specified <code>String</code> is an encoded Java
- * MIME type.
- *
- * @param str the <code>String</code> to test
- * @return <code>true</code> if the <code>String</code> is encoded;
- * <code>false</code> otherwise
- */
- public static boolean isJavaMIMEType(String str) {
- return (str != null && str.startsWith(JavaMIME, 0));
- }
-
- /**
- * Decodes a <code>String</code> native for use as a Java MIME type.
- *
- * @param nat the <code>String</code> to decode
- * @return the decoded Java MIME type, or <code>null</code> if nat is not
- * an encoded <code>String</code> native
- */
- public static String decodeJavaMIMEType(String nat) {
- return (isJavaMIMEType(nat))
- ? nat.substring(JavaMIME.length(), nat.length()).trim()
- : null;
- }
-
- /**
- * Decodes a <code>String</code> native for use as a
- * <code>DataFlavor</code>.
- *
- * @param nat the <code>String</code> to decode
- * @return the decoded <code>DataFlavor</code>, or <code>null</code> if
- * nat is not an encoded <code>String</code> native
- * @throws ClassNotFoundException if the class of the data flavor
- * is not loaded
- */
- public static DataFlavor decodeDataFlavor(String nat)
- throws ClassNotFoundException
- {
- String retval_str = SystemFlavorMap.decodeJavaMIMEType(nat);
- return (retval_str != null)
- ? new DataFlavor(retval_str)
- : null;
- }
-
- private static final class SoftCache<K, V> {
- Map<K, SoftReference<LinkedHashSet<V>>> cache;
-
- public void put(K key, LinkedHashSet<V> value) {
- if (cache == null) {
- cache = new HashMap<>(1);
- }
- cache.put(key, new SoftReference<>(value));
- }
-
- public void remove(K key) {
- if (cache == null) return;
- cache.remove(null);
- cache.remove(key);
- }
-
- public LinkedHashSet<V> check(K key) {
- if (cache == null) return null;
- SoftReference<LinkedHashSet<V>> ref = cache.get(key);
- if (ref != null) {
- return ref.get();
- }
- return null;
- }
- }
-}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/Transferable.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +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 java.io.IOException;
-
-/**
- * Defines the interface for classes that can be used to provide data
- * for a transfer operation.
- * <p>
- * For information on using data transfer with Swing, see
- * <a href="http://docs.oracle.com/javase/tutorial/uiswing/dnd/index.html">
- * How to Use Drag and Drop and Data Transfer</a>,
- * a section in <em>The Java Tutorial</em>, for more information.
- *
- * @author Amy Fowler
- */
-
-public interface Transferable {
-
- /**
- * Returns an array of DataFlavor objects indicating the flavors the data
- * can be provided in. The array should be ordered according to preference
- * for providing the data (from most richly descriptive to least descriptive).
- * @return an array of data flavors in which this data can be transferred
- */
- public DataFlavor[] getTransferDataFlavors();
-
- /**
- * Returns whether or not the specified data flavor is supported for
- * this object.
- * @param flavor the requested flavor for the data
- * @return boolean indicating whether or not the data flavor is supported
- */
- public boolean isDataFlavorSupported(DataFlavor flavor);
-
- /**
- * Returns an object which represents the data to be transferred. The class
- * of the object returned is defined by the representation class of the flavor.
- *
- * @param flavor the requested flavor for the data
- * @return an object which represents the data to be transferred
- * @see DataFlavor#getRepresentationClass
- * @exception IOException if the data is no longer available
- * in the requested flavor.
- * @exception UnsupportedFlavorException if the requested data flavor is
- * not supported.
- */
- public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException;
-
-}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/UnsupportedFlavorException.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1996, 2000, 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;
-
-/**
- * Signals that the requested data is not supported in this flavor.
- * @see Transferable#getTransferData
- *
- * @author Amy Fowler
- */
-public class UnsupportedFlavorException extends Exception {
-
- /*
- * JDK 1.1 serialVersionUID
- */
- private static final long serialVersionUID = 5383814944251665601L;
-
- /**
- * Constructs an UnsupportedFlavorException.
- *
- * @param flavor the flavor object which caused the exception. May
- * be <code>null</code>.
- */
- public UnsupportedFlavorException(DataFlavor flavor) {
- super((flavor != null) ? flavor.getHumanPresentableName() : null);
- }
-}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/package.html Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-<!--
- Copyright (c) 1998, 2013, 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.
--->
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head><title></title></head>
-<body bgcolor="white">
-
-Provides interfaces and classes for transferring data
-between and within applications. It defines the notion of a
-"transferable" object, which is an object capable of being
-transferred between or within applications. An object identifies
-itself as being transferable by implementing the Transferable
-interface.
-<p>
-It also provides a clipboard mechanism, which is an object that
-temporarily holds a transferable object that can be transferred
-between or within an application. The clipboard is typically used
-for copy and paste operations. Although it is possible to create
-a clipboard to use within an application, most applications will
-use the system clipboard to ensure the data can be transferred
-across applications running on the platform.
-
-<!--
-<h2>Package Specification</h2>
-
-##### FILL IN ANY SPECS NEEDED BY JAVA COMPATIBILITY KIT #####
-<ul>
- <li><a href="">##### REFER TO ANY FRAMEMAKER SPECIFICATION HERE #####</a>
-</ul>
-
-<h2>Related Documentation</h2>
-
-For overviews, tutorials, examples, guides, and tool documentation, please see:
-<ul>
- <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
-</ul>
--->
-
-@since 1.1
-</body>
-</html>
--- a/jdk/src/java.desktop/share/classes/sun/datatransfer/DataFlavorUtil.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,841 +0,0 @@
-/*
- * Copyright (c) 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 sun.datatransfer;
-
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.FlavorMap;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.StandardCharsets;
-import java.nio.charset.UnsupportedCharsetException;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.ServiceLoader;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.function.Supplier;
-
-
-/**
- * Utility class with different datatransfer helper functions
- *
- * @see 1.9
- */
-public class DataFlavorUtil {
-
- private DataFlavorUtil() {
- // Avoid instantiation
- }
-
- private static Comparator<String> getCharsetComparator() {
- return CharsetComparator.INSTANCE;
- }
-
- public static Comparator<DataFlavor> getDataFlavorComparator() {
- return DataFlavorComparator.INSTANCE;
- }
-
- public static Comparator<Long> getIndexOrderComparator(Map<Long, Integer> indexMap) {
- return new IndexOrderComparator(indexMap);
- }
-
- public static Comparator<DataFlavor> getTextFlavorComparator() {
- return TextFlavorComparator.INSTANCE;
- }
-
- /**
- * Tracks whether a particular text/* MIME type supports the charset
- * parameter. The Map is initialized with all of the standard MIME types
- * listed in the DataFlavor.selectBestTextFlavor method comment. Additional
- * entries may be added during the life of the JRE for text/<other> types.
- */
- private static final Map<String, Boolean> textMIMESubtypeCharsetSupport;
-
- static {
- Map<String, Boolean> tempMap = new HashMap<>(17);
- tempMap.put("sgml", Boolean.TRUE);
- tempMap.put("xml", Boolean.TRUE);
- tempMap.put("html", Boolean.TRUE);
- tempMap.put("enriched", Boolean.TRUE);
- tempMap.put("richtext", Boolean.TRUE);
- tempMap.put("uri-list", Boolean.TRUE);
- tempMap.put("directory", Boolean.TRUE);
- tempMap.put("css", Boolean.TRUE);
- tempMap.put("calendar", Boolean.TRUE);
- tempMap.put("plain", Boolean.TRUE);
- tempMap.put("rtf", Boolean.FALSE);
- tempMap.put("tab-separated-values", Boolean.FALSE);
- tempMap.put("t140", Boolean.FALSE);
- tempMap.put("rfc822-headers", Boolean.FALSE);
- tempMap.put("parityfec", Boolean.FALSE);
- textMIMESubtypeCharsetSupport = Collections.synchronizedMap(tempMap);
- }
-
- /**
- * Lazy initialization of Standard Encodings.
- */
- private static class StandardEncodingsHolder {
- private static final SortedSet<String> standardEncodings = load();
-
- private static SortedSet<String> load() {
- final SortedSet<String> tempSet = new TreeSet<>(getCharsetComparator().reversed());
- tempSet.add("US-ASCII");
- tempSet.add("ISO-8859-1");
- tempSet.add("UTF-8");
- tempSet.add("UTF-16BE");
- tempSet.add("UTF-16LE");
- tempSet.add("UTF-16");
- tempSet.add(Charset.defaultCharset().name());
- return Collections.unmodifiableSortedSet(tempSet);
- }
- }
-
- /**
- * Returns a {@code SortedSet} of Strings which are a total order of the standard
- * character sets supported by the JRE. The ordering follows the same principles as
- * {@link java.awt.datatransfer.DataFlavor#selectBestTextFlavor(java.awt.datatransfer.DataFlavor[])}.
- * So as to avoid loading all available character converters, optional, non-standard,
- * character sets are not included.
- */
- public static Set<String> standardEncodings() {
- return StandardEncodingsHolder.standardEncodings;
- }
-
- /**
- * Converts an arbitrary text encoding to its canonical name.
- */
- public static String canonicalName(String encoding) {
- if (encoding == null) {
- return null;
- }
- try {
- return Charset.forName(encoding).name();
- } catch (IllegalCharsetNameException icne) {
- return encoding;
- } catch (UnsupportedCharsetException uce) {
- return encoding;
- }
- }
-
- /**
- * Tests only whether the flavor's MIME type supports the charset
- * parameter. Must only be called for flavors with a primary type of
- * "text".
- */
- public static boolean doesSubtypeSupportCharset(DataFlavor flavor) {
- String subType = flavor.getSubType();
- if (subType == null) {
- return false;
- }
-
- Boolean support = textMIMESubtypeCharsetSupport.get(subType);
-
- if (support != null) {
- return support;
- }
-
- boolean ret_val = (flavor.getParameter("charset") != null);
- textMIMESubtypeCharsetSupport.put(subType, ret_val);
- return ret_val;
- }
- public static boolean doesSubtypeSupportCharset(String subType,
- String charset)
- {
- Boolean support = textMIMESubtypeCharsetSupport.get(subType);
-
- if (support != null) {
- return support;
- }
-
- boolean ret_val = (charset != null);
- textMIMESubtypeCharsetSupport.put(subType, ret_val);
- return ret_val;
- }
-
-
- /**
- * Returns whether this flavor is a text type which supports the
- * 'charset' parameter.
- */
- public static boolean isFlavorCharsetTextType(DataFlavor flavor) {
- // Although stringFlavor doesn't actually support the charset
- // parameter (because its primary MIME type is not "text"), it should
- // be treated as though it does. stringFlavor is semantically
- // equivalent to "text/plain" data.
- if (DataFlavor.stringFlavor.equals(flavor)) {
- return true;
- }
-
- if (!"text".equals(flavor.getPrimaryType()) ||
- !doesSubtypeSupportCharset(flavor))
- {
- return false;
- }
-
- Class<?> rep_class = flavor.getRepresentationClass();
-
- if (flavor.isRepresentationClassReader() ||
- String.class.equals(rep_class) ||
- flavor.isRepresentationClassCharBuffer() ||
- char[].class.equals(rep_class))
- {
- return true;
- }
-
- if (!(flavor.isRepresentationClassInputStream() ||
- flavor.isRepresentationClassByteBuffer() ||
- byte[].class.equals(rep_class))) {
- return false;
- }
-
- String charset = flavor.getParameter("charset");
-
- // null equals default encoding which is always supported
- return (charset == null) || isEncodingSupported(charset);
- }
-
- /**
- * Returns whether this flavor is a text type which does not support the
- * 'charset' parameter.
- */
- public static boolean isFlavorNoncharsetTextType(DataFlavor flavor) {
- if (!"text".equals(flavor.getPrimaryType()) || doesSubtypeSupportCharset(flavor)) {
- return false;
- }
-
- return (flavor.isRepresentationClassInputStream() ||
- flavor.isRepresentationClassByteBuffer() ||
- byte[].class.equals(flavor.getRepresentationClass()));
- }
-
- /**
- * If the specified flavor is a text flavor which supports the "charset"
- * parameter, then this method returns that parameter, or the default
- * charset if no such parameter was specified at construction. For non-
- * text DataFlavors, and for non-charset text flavors, this method returns
- * null.
- */
- public static String getTextCharset(DataFlavor flavor) {
- if (!isFlavorCharsetTextType(flavor)) {
- return null;
- }
-
- String encoding = flavor.getParameter("charset");
-
- return (encoding != null) ? encoding : Charset.defaultCharset().name();
- }
-
- /**
- * Determines whether this JRE can both encode and decode text in the
- * specified encoding.
- */
- private static boolean isEncodingSupported(String encoding) {
- if (encoding == null) {
- return false;
- }
- try {
- return Charset.isSupported(encoding);
- } catch (IllegalCharsetNameException icne) {
- return false;
- }
- }
-
- /**
- * Helper method to compare two objects by their Integer indices in the
- * given map. If the map doesn't contain an entry for either of the
- * objects, the fallback index will be used for the object instead.
- *
- * @param indexMap the map which maps objects into Integer indexes.
- * @param obj1 the first object to be compared.
- * @param obj2 the second object to be compared.
- * @param fallbackIndex the Integer to be used as a fallback index.
- * @return a negative integer, zero, or a positive integer as the
- * first object is mapped to a less, equal to, or greater
- * index than the second.
- */
- static <T> int compareIndices(Map<T, Integer> indexMap,
- T obj1, T obj2,
- Integer fallbackIndex) {
- Integer index1 = indexMap.getOrDefault(obj1, fallbackIndex);
- Integer index2 = indexMap.getOrDefault(obj2, fallbackIndex);
- return index1.compareTo(index2);
- }
-
- /**
- * An IndexedComparator which compares two String charsets. The comparison
- * follows the rules outlined in DataFlavor.selectBestTextFlavor. In order
- * to ensure that non-Unicode, non-ASCII, non-default charsets are sorted
- * in alphabetical order, charsets are not automatically converted to their
- * canonical forms.
- */
- private static class CharsetComparator implements Comparator<String> {
- static final CharsetComparator INSTANCE = new CharsetComparator();
-
- private static final Map<String, Integer> charsets;
-
- private static final Integer DEFAULT_CHARSET_INDEX = 2;
- private static final Integer OTHER_CHARSET_INDEX = 1;
- private static final Integer WORST_CHARSET_INDEX = 0;
- private static final Integer UNSUPPORTED_CHARSET_INDEX = Integer.MIN_VALUE;
-
- private static final String UNSUPPORTED_CHARSET = "UNSUPPORTED";
-
- static {
- Map<String, Integer> charsetsMap = new HashMap<>(8, 1.0f);
-
- // we prefer Unicode charsets
- charsetsMap.put(canonicalName("UTF-16LE"), 4);
- charsetsMap.put(canonicalName("UTF-16BE"), 5);
- charsetsMap.put(canonicalName("UTF-8"), 6);
- charsetsMap.put(canonicalName("UTF-16"), 7);
-
- // US-ASCII is the worst charset supported
- charsetsMap.put(canonicalName("US-ASCII"), WORST_CHARSET_INDEX);
-
- charsetsMap.putIfAbsent(Charset.defaultCharset().name(), DEFAULT_CHARSET_INDEX);
-
- charsetsMap.put(UNSUPPORTED_CHARSET, UNSUPPORTED_CHARSET_INDEX);
-
- charsets = Collections.unmodifiableMap(charsetsMap);
- }
-
- /**
- * Compares charsets. Returns a negative integer, zero, or a positive
- * integer as the first charset is worse than, equal to, or better than
- * the second.
- * <p>
- * Charsets are ordered according to the following rules:
- * <ul>
- * <li>All unsupported charsets are equal.
- * <li>Any unsupported charset is worse than any supported charset.
- * <li>Unicode charsets, such as "UTF-16", "UTF-8", "UTF-16BE" and
- * "UTF-16LE", are considered best.
- * <li>After them, platform default charset is selected.
- * <li>"US-ASCII" is the worst of supported charsets.
- * <li>For all other supported charsets, the lexicographically less
- * one is considered the better.
- * </ul>
- *
- * @param charset1 the first charset to be compared
- * @param charset2 the second charset to be compared.
- * @return a negative integer, zero, or a positive integer as the
- * first argument is worse, equal to, or better than the
- * second.
- */
- public int compare(String charset1, String charset2) {
- charset1 = getEncoding(charset1);
- charset2 = getEncoding(charset2);
-
- int comp = compareIndices(charsets, charset1, charset2, OTHER_CHARSET_INDEX);
-
- if (comp == 0) {
- return charset2.compareTo(charset1);
- }
-
- return comp;
- }
-
- /**
- * Returns encoding for the specified charset according to the
- * following rules:
- * <ul>
- * <li>If the charset is <code>null</code>, then <code>null</code> will
- * be returned.
- * <li>Iff the charset specifies an encoding unsupported by this JRE,
- * <code>UNSUPPORTED_CHARSET</code> will be returned.
- * <li>If the charset specifies an alias name, the corresponding
- * canonical name will be returned iff the charset is a known
- * Unicode, ASCII, or default charset.
- * </ul>
- *
- * @param charset the charset.
- * @return an encoding for this charset.
- */
- static String getEncoding(String charset) {
- if (charset == null) {
- return null;
- } else if (!isEncodingSupported(charset)) {
- return UNSUPPORTED_CHARSET;
- } else {
- // Only convert to canonical form if the charset is one
- // of the charsets explicitly listed in the known charsets
- // map. This will happen only for Unicode, ASCII, or default
- // charsets.
- String canonicalName = canonicalName(charset);
- return (charsets.containsKey(canonicalName))
- ? canonicalName
- : charset;
- }
- }
- }
-
- /**
- * An IndexedComparator which compares two DataFlavors. For text flavors,
- * the comparison follows the rules outlined in
- * DataFlavor.selectBestTextFlavor. For non-text flavors, unknown
- * application MIME types are preferred, followed by known
- * application/x-java-* MIME types. Unknown application types are preferred
- * because if the user provides his own data flavor, it will likely be the
- * most descriptive one. For flavors which are otherwise equal, the
- * flavors' string representation are compared in the alphabetical order.
- */
- private static class DataFlavorComparator implements Comparator<DataFlavor> {
-
- static final DataFlavorComparator INSTANCE = new DataFlavorComparator();
-
- private static final Map<String, Integer> exactTypes;
- private static final Map<String, Integer> primaryTypes;
- private static final Map<Class<?>, Integer> nonTextRepresentations;
- private static final Map<String, Integer> textTypes;
- private static final Map<Class<?>, Integer> decodedTextRepresentations;
- private static final Map<Class<?>, Integer> encodedTextRepresentations;
-
- private static final Integer UNKNOWN_OBJECT_LOSES = Integer.MIN_VALUE;
- private static final Integer UNKNOWN_OBJECT_WINS = Integer.MAX_VALUE;
-
- static {
- {
- Map<String, Integer> exactTypesMap = new HashMap<>(4, 1.0f);
-
- // application/x-java-* MIME types
- exactTypesMap.put("application/x-java-file-list", 0);
- exactTypesMap.put("application/x-java-serialized-object", 1);
- exactTypesMap.put("application/x-java-jvm-local-objectref", 2);
- exactTypesMap.put("application/x-java-remote-object", 3);
-
- exactTypes = Collections.unmodifiableMap(exactTypesMap);
- }
-
- {
- Map<String, Integer> primaryTypesMap = new HashMap<>(1, 1.0f);
-
- primaryTypesMap.put("application", 0);
-
- primaryTypes = Collections.unmodifiableMap(primaryTypesMap);
- }
-
- {
- Map<Class<?>, Integer> nonTextRepresentationsMap = new HashMap<>(3, 1.0f);
-
- nonTextRepresentationsMap.put(java.io.InputStream.class, 0);
- nonTextRepresentationsMap.put(java.io.Serializable.class, 1);
-
- nonTextRepresentationsMap.put(RMI.remoteClass(), 2);
-
- nonTextRepresentations = Collections.unmodifiableMap(nonTextRepresentationsMap);
- }
-
- {
- Map<String, Integer> textTypesMap = new HashMap<>(16, 1.0f);
-
- // plain text
- textTypesMap.put("text/plain", 0);
-
- // stringFlavor
- textTypesMap.put("application/x-java-serialized-object", 1);
-
- // misc
- textTypesMap.put("text/calendar", 2);
- textTypesMap.put("text/css", 3);
- textTypesMap.put("text/directory", 4);
- textTypesMap.put("text/parityfec", 5);
- textTypesMap.put("text/rfc822-headers", 6);
- textTypesMap.put("text/t140", 7);
- textTypesMap.put("text/tab-separated-values", 8);
- textTypesMap.put("text/uri-list", 9);
-
- // enriched
- textTypesMap.put("text/richtext", 10);
- textTypesMap.put("text/enriched", 11);
- textTypesMap.put("text/rtf", 12);
-
- // markup
- textTypesMap.put("text/html", 13);
- textTypesMap.put("text/xml", 14);
- textTypesMap.put("text/sgml", 15);
-
- textTypes = Collections.unmodifiableMap(textTypesMap);
- }
-
- {
- Map<Class<?>, Integer> decodedTextRepresentationsMap = new HashMap<>(4, 1.0f);
-
- decodedTextRepresentationsMap.put(char[].class, 0);
- decodedTextRepresentationsMap.put(CharBuffer.class, 1);
- decodedTextRepresentationsMap.put(String.class, 2);
- decodedTextRepresentationsMap.put(Reader.class, 3);
-
- decodedTextRepresentations =
- Collections.unmodifiableMap(decodedTextRepresentationsMap);
- }
-
- {
- Map<Class<?>, Integer> encodedTextRepresentationsMap = new HashMap<>(3, 1.0f);
-
- encodedTextRepresentationsMap.put(byte[].class, 0);
- encodedTextRepresentationsMap.put(ByteBuffer.class, 1);
- encodedTextRepresentationsMap.put(InputStream.class, 2);
-
- encodedTextRepresentations =
- Collections.unmodifiableMap(encodedTextRepresentationsMap);
- }
- }
-
-
- public int compare(DataFlavor flavor1, DataFlavor flavor2) {
- if (flavor1.equals(flavor2)) {
- return 0;
- }
-
- int comp;
-
- String primaryType1 = flavor1.getPrimaryType();
- String subType1 = flavor1.getSubType();
- String mimeType1 = primaryType1 + "/" + subType1;
- Class<?> class1 = flavor1.getRepresentationClass();
-
- String primaryType2 = flavor2.getPrimaryType();
- String subType2 = flavor2.getSubType();
- String mimeType2 = primaryType2 + "/" + subType2;
- Class<?> class2 = flavor2.getRepresentationClass();
-
- if (flavor1.isFlavorTextType() && flavor2.isFlavorTextType()) {
- // First, compare MIME types
- comp = compareIndices(textTypes, mimeType1, mimeType2, UNKNOWN_OBJECT_LOSES);
- if (comp != 0) {
- return comp;
- }
-
- // Only need to test one flavor because they both have the
- // same MIME type. Also don't need to worry about accidentally
- // passing stringFlavor because either
- // 1. Both flavors are stringFlavor, in which case the
- // equality test at the top of the function succeeded.
- // 2. Only one flavor is stringFlavor, in which case the MIME
- // type comparison returned a non-zero value.
- if (doesSubtypeSupportCharset(flavor1)) {
- // Next, prefer the decoded text representations of Reader,
- // String, CharBuffer, and [C, in that order.
- comp = compareIndices(decodedTextRepresentations, class1,
- class2, UNKNOWN_OBJECT_LOSES);
- if (comp != 0) {
- return comp;
- }
-
- // Next, compare charsets
- comp = CharsetComparator.INSTANCE.compare(getTextCharset(flavor1),
- getTextCharset(flavor2));
- if (comp != 0) {
- return comp;
- }
- }
-
- // Finally, prefer the encoded text representations of
- // InputStream, ByteBuffer, and [B, in that order.
- comp = compareIndices(encodedTextRepresentations, class1,
- class2, UNKNOWN_OBJECT_LOSES);
- if (comp != 0) {
- return comp;
- }
- } else {
- // First, prefer application types.
- comp = compareIndices(primaryTypes, primaryType1, primaryType2,
- UNKNOWN_OBJECT_LOSES);
- if (comp != 0) {
- return comp;
- }
-
- // Next prefer text types
- if (flavor1.isFlavorTextType()) {
- return 1;
- }
-
- if (flavor2.isFlavorTextType()) {
- return -1;
- }
-
- // Next, look for application/x-java-* types. Prefer unknown
- // MIME types because if the user provides his own data flavor,
- // it will likely be the most descriptive one.
- comp = compareIndices(exactTypes, mimeType1, mimeType2,
- UNKNOWN_OBJECT_WINS);
- if (comp != 0) {
- return comp;
- }
-
- // Finally, prefer the representation classes of Remote,
- // Serializable, and InputStream, in that order.
- comp = compareIndices(nonTextRepresentations, class1, class2,
- UNKNOWN_OBJECT_LOSES);
- if (comp != 0) {
- return comp;
- }
- }
-
- // The flavours are not equal but still not distinguishable.
- // Compare String representations in alphabetical order
- return flavor1.getMimeType().compareTo(flavor2.getMimeType());
- }
- }
-
- /*
- * Given the Map that maps objects to Integer indices and a boolean value,
- * this Comparator imposes a direct or reverse order on set of objects.
- * <p>
- * If the specified boolean value is SELECT_BEST, the Comparator imposes the
- * direct index-based order: an object A is greater than an object B if and
- * only if the index of A is greater than the index of B. An object that
- * doesn't have an associated index is less or equal than any other object.
- * <p>
- * If the specified boolean value is SELECT_WORST, the Comparator imposes the
- * reverse index-based order: an object A is greater than an object B if and
- * only if A is less than B with the direct index-based order.
- */
- private static class IndexOrderComparator implements Comparator<Long> {
- private final Map<Long, Integer> indexMap;
- private static final Integer FALLBACK_INDEX = Integer.MIN_VALUE;
-
- public IndexOrderComparator(Map<Long, Integer> indexMap) {
- this.indexMap = indexMap;
- }
-
- public int compare(Long obj1, Long obj2) {
- return compareIndices(indexMap, obj1, obj2, FALLBACK_INDEX);
- }
- }
-
- private static class TextFlavorComparator extends DataFlavorComparator {
-
- static final TextFlavorComparator INSTANCE = new TextFlavorComparator();
- /**
- * Compares two <code>DataFlavor</code> objects. Returns a negative
- * integer, zero, or a positive integer as the first
- * <code>DataFlavor</code> is worse than, equal to, or better than the
- * second.
- * <p>
- * <code>DataFlavor</code>s are ordered according to the rules outlined
- * for <code>selectBestTextFlavor</code>.
- *
- * @param flavor1 the first <code>DataFlavor</code> to be compared
- * @param flavor2 the second <code>DataFlavor</code> to be compared
- * @return a negative integer, zero, or a positive integer as the first
- * argument is worse, equal to, or better than the second
- * @throws ClassCastException if either of the arguments is not an
- * instance of <code>DataFlavor</code>
- * @throws NullPointerException if either of the arguments is
- * <code>null</code>
- *
- * @see java.awt.datatransfer.DataFlavor#selectBestTextFlavor
- */
- public int compare(DataFlavor flavor1, DataFlavor flavor2) {
- if (flavor1.isFlavorTextType()) {
- if (flavor2.isFlavorTextType()) {
- return super.compare(flavor1, flavor2);
- } else {
- return 1;
- }
- } else if (flavor2.isFlavorTextType()) {
- return -1;
- } else {
- return 0;
- }
- }
- }
-
- /**
- * A fallback implementation of {@link sun.datatransfer.DesktopDatatransferService}
- * used if there is no desktop.
- */
- private static final class DefaultDesktopDatatransferService implements DesktopDatatransferService {
- static final DesktopDatatransferService INSTANCE = getDesktopService();
-
- private static DesktopDatatransferService getDesktopService() {
- ServiceLoader<DesktopDatatransferService> loader =
- ServiceLoader.load(DesktopDatatransferService.class, null);
- Iterator<DesktopDatatransferService> iterator = loader.iterator();
- if (iterator.hasNext()) {
- return iterator.next();
- } else {
- return new DefaultDesktopDatatransferService();
- }
- }
-
- /**
- * System singleton FlavorTable.
- * Only used if there is no desktop
- * to provide an appropriate FlavorMap.
- */
- private volatile FlavorMap flavorMap;
-
- @Override
- public void invokeOnEventThread(Runnable r) {
- r.run();
- }
-
- @Override
- public String getDefaultUnicodeEncoding() {
- return StandardCharsets.UTF_8.name();
- }
-
- @Override
- public FlavorMap getFlavorMap(Supplier<FlavorMap> supplier) {
- FlavorMap map = flavorMap;
- if (map == null) {
- synchronized (this) {
- map = flavorMap;
- if (map == null) {
- flavorMap = map = supplier.get();
- }
- }
- }
- return map;
- }
-
- @Override
- public boolean isDesktopPresent() {
- return false;
- }
-
- @Override
- public LinkedHashSet<DataFlavor> getPlatformMappingsForNative(String nat) {
- return new LinkedHashSet<>();
- }
-
- @Override
- public LinkedHashSet<String> getPlatformMappingsForFlavor(DataFlavor df) {
- return new LinkedHashSet<>();
- }
-
- @Override
- public void registerTextFlavorProperties(String nat, String charset,
- String eoln, String terminators) {
- // Not needed if desktop module is absent
- }
- }
-
- public static DesktopDatatransferService getDesktopService() {
- return DefaultDesktopDatatransferService.INSTANCE;
- }
-
- /**
- * A class that provides access to java.rmi.Remote and java.rmi.MarshalledObject
- * without creating a static dependency.
- */
- public static class RMI {
- private static final Class<?> remoteClass = getClass("java.rmi.Remote");
- private static final Class<?> marshallObjectClass = getClass("java.rmi.MarshalledObject");
- private static final Constructor<?> marshallCtor = getConstructor(marshallObjectClass, Object.class);
- private static final Method marshallGet = getMethod(marshallObjectClass, "get");
-
- private static Class<?> getClass(String name) {
- try {
- return Class.forName(name, true, null);
- } catch (ClassNotFoundException e) {
- return null;
- }
- }
-
- private static Constructor<?> getConstructor(Class<?> c, Class<?>... types) {
- try {
- return (c == null) ? null : c.getDeclaredConstructor(types);
- } catch (NoSuchMethodException x) {
- throw new AssertionError(x);
- }
- }
-
- private static Method getMethod(Class<?> c, String name, Class<?>... types) {
- try {
- return (c == null) ? null : c.getMethod(name, types);
- } catch (NoSuchMethodException e) {
- throw new AssertionError(e);
- }
- }
-
- /**
- * Returns java.rmi.Remote.class if RMI is present; otherwise {@code null}.
- */
- static Class<?> remoteClass() {
- return remoteClass;
- }
-
- /**
- * Returns {@code true} if the given class is java.rmi.Remote.
- */
- public static boolean isRemote(Class<?> c) {
- return (remoteClass != null) && remoteClass.isAssignableFrom(c);
- }
-
- /**
- * Returns a new MarshalledObject containing the serialized representation
- * of the given object.
- */
- public static Object newMarshalledObject(Object obj) throws IOException {
- try {
- return marshallCtor == null ? null : marshallCtor.newInstance(obj);
- } catch (InstantiationException | IllegalAccessException x) {
- throw new AssertionError(x);
- } catch (InvocationTargetException x) {
- Throwable cause = x.getCause();
- if (cause instanceof IOException)
- throw (IOException) cause;
- throw new AssertionError(x);
- }
- }
-
- /**
- * Returns a new copy of the contained marshalled object.
- */
- public static Object getMarshalledObject(Object obj)
- throws IOException, ClassNotFoundException {
- try {
- return marshallGet == null ? null : marshallGet.invoke(obj);
- } catch (IllegalAccessException x) {
- throw new AssertionError(x);
- } catch (InvocationTargetException x) {
- Throwable cause = x.getCause();
- if (cause instanceof IOException)
- throw (IOException) cause;
- if (cause instanceof ClassNotFoundException)
- throw (ClassNotFoundException) cause;
- throw new AssertionError(x);
- }
- }
-
- }
-}
--- a/jdk/src/java.desktop/share/classes/sun/datatransfer/DesktopDatatransferService.java Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 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 sun.datatransfer;
-
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.FlavorMap;
-import java.util.LinkedHashSet;
-import java.util.function.Supplier;
-
-/**
- * Contains services which desktop provides to the datatransfer system
- * to enrich it's functionality
- *
- * @author Petr Pchelko
- * @since 1.9
- */
-public interface DesktopDatatransferService {
-
- /**
- * If desktop is present - invokes a {@code Runnable} on
- * the event dispatch thread. Otherwise invokes a {@code run()}
- * method directly.
- *
- * @param r a {@code Runnable} to invoke
- */
- void invokeOnEventThread(Runnable r);
-
- /**
- * Get a platform-dependent default unicode encoding to use in
- * datatransfer system.
- *
- * @return default unicode encoding
- */
- String getDefaultUnicodeEncoding();
-
- /**
- * Takes an appropriate {@code FlavorMap} from the desktop.
- * If no appropriate table is found - uses a provided supplier to
- * instantiate a table. If the desktop is absent - creates and returns
- * a system singleton.
- *
- * @param supplier a constructor that should be used to create a new instance of
- * the {@code FlavorMap}
- * @return a {@code FlavorMap}
- */
- FlavorMap getFlavorMap(Supplier<FlavorMap> supplier);
-
- /**
- * Checks if desktop is present
- *
- * @return {@code true} is the desktop is present
- */
- boolean isDesktopPresent();
-
- /**
- * Returns platform-specific mappings for the specified native format.
- * If there are no platform-specific mappings for this native, the method
- * returns an empty {@code Set}
- *
- * @param nat a native format to return flavors for
- * @return set of platform-specific mappings for a native format
- */
- LinkedHashSet<DataFlavor> getPlatformMappingsForNative(String nat);
-
- /**
- * Returns platform-specific mappings for the specified flavor.
- * If there are no platform-specific mappings for this flavor, the method
- * returns an empty {@code Set}
- *
- * @param df {@code DataFlavor} to return mappings for
- * @return set of platform-specific mappings for a {@code DataFlavor}
- */
- LinkedHashSet<String> getPlatformMappingsForFlavor(DataFlavor df);
-
- /**
- * This method is called for text flavor mappings established while parsing
- * the default flavor mappings file. It stores the "eoln" and "terminators"
- * parameters which are not officially part of the MIME type. They are
- * MIME parameters specific to the flavormap.properties file format.
- */
- void registerTextFlavorProperties(String nat, String charset,
- String eoln, String terminators);
-}
--- a/jdk/src/java.desktop/unix/classes/sun/datatransfer/resources/flavormap.properties Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# This properties file is used to initialize the default
-# java.awt.datatransfer.SystemFlavorMap. It contains the X11 platform-specific,
-# default mappings between common X11 selection atoms and platform-independent
-# MIME type strings, which will be converted into
-# java.awt.datatransfer.DataFlavors.
-#
-# The standard format is:
-#
-# <native>=<MIME type>,<MIME type>, ...
-#
-# <native> should be a string identifier that the native platform will
-# recognize as a valid data format. <MIME type> should specify both a MIME
-# primary type and a MIME subtype separated by a '/'. The MIME type may include
-# parameters, where each parameter is a key/value pair separated by '=', and
-# where each parameter to the MIME type is separated by a ';'.
-#
-# Because SystemFlavorMap implements FlavorTable, developers are free to
-# duplicate DataFlavor values and set multiple values for a single native by
-# separating them with ",". If a mapping contains a duplicate key or value,
-# earlier mappings which included this key or value will be preferred.
-#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", and which support the charset parameter, should specify the exact
-# format in which the native platform expects the data. The "charset"
-# parameter specifies the char to byte encoding, the "eoln" parameter
-# specifies the end-of-line marker, and the "terminators" parameter specifies
-# the number of terminating NUL bytes. Note that "eoln" and "terminators"
-# are not standardized MIME type parameters. They are specific to this file
-# format ONLY. They will not appear in any of the DataFlavors returned by the
-# SystemFlavorMap at the Java level.
-#
-# If the "charset" parameter is omitted, or has zero length, the platform
-# default encoding is assumed. If the "eoln" parameter is omitted, or has
-# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
-# or has a value less than zero, zero is assumed.
-#
-# Upon initialization, the data transfer subsystem will record the specified
-# details of the native text format, but the default SystemFlavorMap will
-# present a large set of synthesized DataFlavors which map, in both
-# directions, to the native. After receiving data from the application in one
-# of the synthetic DataFlavors, the data transfer subsystem will transform
-# the data stream into the format specified in this file before passing the
-# transformed stream to the native system.
-#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", but which do not support the charset parameter, will be treated as
-# opaque, 8-bit data. They will not undergo any transformation process, and
-# any "charset", "eoln", or "terminators" parameters specified in this file
-# will be ignored.
-#
-# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
-# text flavors which support the charset parameter.
-
-UTF8_STRING=text/plain;charset=UTF-8;eoln="\n";terminators=0
-
-# The COMPOUND_TEXT support for inter-client text transfer is disabled by
-# default. The reason is that many native applications prefer this format over
-# other native text formats, but are unable to decode the textual data in this
-# format properly. This results in java-to-native text transfer failures.
-# To enable the COMPOUND_TEXT support for this JRE installation uncomment
-# the line below.
-
-# COMPOUND_TEXT=text/plain;charset=x-compound-text;eoln="\n";terminators=0
-
-TEXT=text/plain;eoln="\n";terminators=0
-STRING=text/plain;charset=iso8859-1;eoln="\n";terminators=0
-FILE_NAME=application/x-java-file-list;class=java.util.List
-text/uri-list=application/x-java-file-list;class=java.util.List
-PNG=image/x-java-image;class=java.awt.Image
-JFIF=image/x-java-image;class=java.awt.Image
--- a/jdk/src/java.desktop/windows/classes/sun/datatransfer/resources/flavormap.properties Fri Jan 16 19:11:10 2015 +0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-#
-# This properties file is used to initialize the default
-# java.awt.datatransfer.SystemFlavorMap. It contains the Win32 platform-
-# specific, default mappings between common Win32 Clipboard atoms and platform-
-# independent MIME type strings, which will be converted into
-# java.awt.datatransfer.DataFlavors.
-#
-# The standard format is:
-#
-# <native>=<MIME type>,<MIME type>, ...
-#
-# <native> should be a string identifier that the native platform will
-# recognize as a valid data format. <MIME type> should specify both a MIME
-# primary type and a MIME subtype separated by a '/'. The MIME type may include
-# parameters, where each parameter is a key/value pair separated by '=', and
-# where each parameter to the MIME type is separated by a ';'.
-#
-# Because SystemFlavorMap implements FlavorTable, developers are free to
-# duplicate DataFlavor values and set multiple values for a single native by
-# separating them with ",". If a mapping contains a duplicate key or value,
-# earlier mappings which included this key or value will be preferred.#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", and which support the charset parameter, should specify the exact
-# format in which the native platform expects the data. The "charset"
-# parameter specifies the char to byte encoding, the "eoln" parameter
-# specifies the end-of-line marker, and the "terminators" parameter specifies
-# the number of terminating NUL bytes. Note that "eoln" and "terminators"
-# are not standardized MIME type parameters. They are specific to this file
-# format ONLY. They will not appear in any of the DataFlavors returned by the
-# SystemFlavorMap at the Java level.
-#
-# If the "charset" parameter is omitted, or has zero length, the platform
-# default encoding is assumed. If the "eoln" parameter is omitted, or has
-# zero length, "\n" is assumed. If the "terminators" parameter is omitted,
-# or has a value less than zero, zero is assumed.
-#
-# Upon initialization, the data transfer subsystem will record the specified
-# details of the native text format, but the default SystemFlavorMap will
-# present a large set of synthesized DataFlavors which map, in both
-# directions, to the native. After receiving data from the application in one
-# of the synthetic DataFlavors, the data transfer subsystem will transform
-# the data stream into the format specified in this file before passing the
-# transformed stream to the native system.
-#
-# Mappings whose values specify DataFlavors with primary MIME types of
-# "text", but which do not support the charset parameter, will be treated as
-# opaque, 8-bit data. They will not undergo any transformation process, and
-# any "charset", "eoln", or "terminators" parameters specified in this file
-# will be ignored.
-#
-# See java.awt.datatransfer.DataFlavor.selectBestTextFlavor for a list of
-# text flavors which support the charset parameter.
-
-UNICODE\ TEXT=text/plain;charset=utf-16le;eoln="\r\n";terminators=2
-TEXT=text/plain;eoln="\r\n";terminators=1
-HTML\ Format=text/html;charset=utf-8;eoln="\r\n";terminators=1
-Rich\ Text\ Format=text/rtf
-HDROP=application/x-java-file-list;class=java.util.List
-PNG=image/x-java-image;class=java.awt.Image
-JFIF=image/x-java-image;class=java.awt.Image
-DIB=image/x-java-image;class=java.awt.Image
-ENHMETAFILE=image/x-java-image;class=java.awt.Image
-METAFILEPICT=image/x-java-image;class=java.awt.Image
-LOCALE=application/x-java-text-encoding;class="[B"
-UniformResourceLocator=application/x-java-url;class=java.net.URL,\
- text/uri-list;eoln="\r\n";terminators=1,\
- text/plain;eoln="\r\n";terminators=1
-FileGroupDescriptorW=application/x-java-file-list;class=java.util.List
-FileGroupDescriptor=application/x-java-file-list;class=java.util.List