--- a/jdk/make/copy/Copy-java.base.gmk Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/make/copy/Copy-java.base.gmk Wed Jan 28 08:14:18 2015 -0800
@@ -60,16 +60,28 @@
endif
################################################################################
-# Copy msvcrXX.dll on windows
+# Copy the microsoft runtime libraries on windows
+ifeq ($(OPENJDK_TARGET_OS), windows)
-ifeq ($(OPENJDK_TARGET_OS), windows)
- MSVCR_TARGET := $(LIB_DST_DIR)/$(notdir $(MSVCR_DLL))
# Chmod to avoid permission issues if bundles are unpacked on unix platforms.
- $(MSVCR_TARGET): $(MSVCR_DLL)
- $(call install-file)
+ define copy-and-chmod
+ $(install-file)
$(CHMOD) a+rx $@
+ endef
- TARGETS += $(MSVCR_TARGET)
+ # Use separate macro calls in case the source files are not in the same
+ # directory.
+ $(eval $(call SetupCopyFiles,COPY_MSVCR, \
+ DEST := $(LIB_DST_DIR), \
+ FILES := $(MSVCR_DLL), \
+ MACRO := copy-and-chmod))
+
+ $(eval $(call SetupCopyFiles,COPY_MSVCP, \
+ DEST := $(LIB_DST_DIR), \
+ FILES := $(MSVCP_DLL), \
+ MACRO := copy-and-chmod))
+
+ TARGETS += $(COPY_MSVCR) $(COPY_MSVCP)
endif
################################################################################
--- a/jdk/make/lib/CoreLibraries.gmk Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/make/lib/CoreLibraries.gmk Wed Jan 28 08:14:18 2015 -0800
@@ -271,6 +271,11 @@
# Staticically link with c runtime on windows.
LIBJLI_CFLAGS := $(filter-out -MD, $(LIBJLI_CFLAGS))
LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)
+ # Supply the name of the C runtime lib.
+ LIBJLI_CFLAGS += -DMSVCR_DLL_NAME='"$(notdir $(MSVCR_DLL))"'
+ ifneq ($(MSVCP_DLL), )
+ LIBJLI_CFLAGS += -DMSVCP_DLL_NAME='"$(notdir $(MSVCP_DLL))"'
+ endif
else
LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)/jli
endif
--- a/jdk/make/src/classes/build/tools/module/boot.modules Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/make/src/classes/build/tools/module/boot.modules Wed Jan 28 08:14:18 2015 -0800
@@ -1,4 +1,5 @@
java.base
+java.datatransfer
java.desktop
java.activation
java.annotations.common
--- a/jdk/src/java.base/windows/native/libjli/java_md.c Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.base/windows/native/libjli/java_md.c Wed Jan 28 08:14:18 2015 -0800
@@ -265,26 +265,17 @@
* assumed to be present in the "JRE path" directory. If it is not found
* there (or "JRE path" fails to resolve), skip the explicit load and let
* nature take its course, which is likely to be a failure to execute.
- * This is clearly completely specific to the exact compiler version
- * which isn't very nice, but its hardly the only place.
- * No attempt to look for compiler versions in between 2003 and 2010
- * as we aren't supporting building with those.
+ * The makefiles will provide the correct lib contained in quotes in the
+ * macro MSVCR_DLL_NAME.
*/
-#ifdef _MSC_VER
-#if _MSC_VER < 1400
-#define CRT_DLL "msvcr71.dll"
-#endif
-#if _MSC_VER >= 1600
-#define CRT_DLL "msvcr100.dll"
-#endif
-#ifdef CRT_DLL
+#ifdef MSVCR_DLL_NAME
if (GetJREPath(crtpath, MAXPATHLEN)) {
if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") +
- JLI_StrLen(CRT_DLL) >= MAXPATHLEN) {
+ JLI_StrLen(MSVCR_DLL_NAME) >= MAXPATHLEN) {
JLI_ReportErrorMessage(JRE_ERROR11);
return JNI_FALSE;
}
- (void)JLI_StrCat(crtpath, "\\bin\\" CRT_DLL); /* Add crt dll */
+ (void)JLI_StrCat(crtpath, "\\bin\\" MSVCR_DLL_NAME); /* Add crt dll */
JLI_TraceLauncher("CRT path is %s\n", crtpath);
if (_access(crtpath, 0) == 0) {
if (LoadLibrary(crtpath) == 0) {
@@ -293,8 +284,24 @@
}
}
}
-#endif /* CRT_DLL */
-#endif /* _MSC_VER */
+#endif /* MSVCR_DLL_NAME */
+#ifdef MSVCP_DLL_NAME
+ if (GetJREPath(crtpath, MAXPATHLEN)) {
+ if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") +
+ JLI_StrLen(MSVCP_DLL_NAME) >= MAXPATHLEN) {
+ JLI_ReportErrorMessage(JRE_ERROR11);
+ return JNI_FALSE;
+ }
+ (void)JLI_StrCat(crtpath, "\\bin\\" MSVCP_DLL_NAME); /* Add prt dll */
+ JLI_TraceLauncher("PRT path is %s\n", crtpath);
+ if (_access(crtpath, 0) == 0) {
+ if (LoadLibrary(crtpath) == 0) {
+ JLI_ReportErrorMessage(DLL_ERROR4, crtpath);
+ return JNI_FALSE;
+ }
+ }
+ }
+#endif /* MSVCP_DLL_NAME */
loaded = 1;
}
return JNI_TRUE;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.datatransfer/macosx/classes/sun/datatransfer/resources/flavormap.properties Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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 Wed Jan 28 08:14:18 2015 -0800
@@ -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/com/apple/laf/AquaBorder.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaBorder.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -68,8 +68,9 @@
painter.state.set(size);
}
+ @Override
public Insets getBorderInsets(final Component c) {
- return sizeVariant.margins;
+ return (Insets) sizeVariant.margins.clone();
}
protected AquaBorder deriveBorderForSize(final Size size) {
@@ -130,8 +131,10 @@
return (focusable != null && focusable instanceof JComponent && ((JComponent)focusable).hasFocus());
}
+ @Override
public boolean isBorderOpaque() { return false; }
+ @Override
public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int w, final int h) {
painter.paint(g, c, x, y, w, h);
}
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxUI.java Wed Jan 28 08:14:18 2015 -0800
@@ -275,7 +275,7 @@
actionMap.put("aquaSelectNext", highlightNextAction);
actionMap.put("aquaSelectPrevious", highlightPreviousAction);
- actionMap.put("aquaEnterPressed", triggerSelectionAction);
+ actionMap.put("enterPressed", triggerSelectionAction);
actionMap.put("aquaSpacePressed", toggleSelectionAction);
actionMap.put("aquaSelectHome", highlightFirstAction);
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -1098,8 +1098,15 @@
super(f);
}
- public Component getTableCellRendererComponent(final JTable list, final Object value, final boolean isSelected, final boolean cellHasFocus, final int index, final int col) {
- super.getTableCellRendererComponent(list, value, isSelected, false, index, col); // No focus border, thanks
+ public Component getTableCellRendererComponent(final JTable list,
+ final Object value,
+ final boolean isSelected,
+ final boolean cellHasFocus,
+ final int index,
+ final int col) {
+ super.getTableCellRendererComponent(list, value, isSelected, false,
+ index,
+ col); // No focus border, thanks
final File file = (File)value;
final JFileChooser fc = getFileChooser();
setText(fc.getName(file));
@@ -1115,8 +1122,14 @@
super(f);
}
- public Component getTableCellRendererComponent(final JTable list, final Object value, final boolean isSelected, final boolean cellHasFocus, final int index, final int col) {
- super.getTableCellRendererComponent(list, value, isSelected, false, index, col);
+ public Component getTableCellRendererComponent(final JTable list,
+ final Object value,
+ final boolean isSelected,
+ final boolean cellHasFocus,
+ final int index,
+ final int col) {
+ super.getTableCellRendererComponent(list, value, isSelected, false,
+ index, col);
final File file = (File)fFileList.getValueAt(index, 0);
setEnabled(isSelectableInList(file));
final DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT);
@@ -1132,14 +1145,17 @@
}
}
+ @Override
public Dimension getPreferredSize(final JComponent c) {
- return PREF_SIZE;
+ return new Dimension(PREF_WIDTH, PREF_HEIGHT);
}
+ @Override
public Dimension getMinimumSize(final JComponent c) {
- return MIN_SIZE;
+ return new Dimension(MIN_WIDTH, MIN_HEIGHT);
}
+ @Override
public Dimension getMaximumSize(final JComponent c) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
@@ -1819,12 +1835,8 @@
private static final int PREF_WIDTH = 550;
private static final int PREF_HEIGHT = 400;
- private static final Dimension PREF_SIZE = new Dimension(PREF_WIDTH, PREF_HEIGHT);
-
private static final int MIN_WIDTH = 400;
private static final int MIN_HEIGHT = 250;
- private static final Dimension MIN_SIZE = new Dimension(MIN_WIDTH, MIN_HEIGHT);
-
private static final int LIST_MIN_WIDTH = 400;
private static final int LIST_MIN_HEIGHT = 100;
private static final Dimension LIST_MIN_SIZE = new Dimension(LIST_MIN_WIDTH, LIST_MIN_HEIGHT);
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaKeyBindings.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaKeyBindings.java Wed Jan 28 08:14:18 2015 -0800
@@ -214,7 +214,7 @@
"PAGE_DOWN", "aquaSelectPageDown",
"HOME", "aquaSelectHome",
"END", "aquaSelectEnd",
- "ENTER", "aquaEnterPressed",
+ "ENTER", "enterPressed",
"UP", "aquaSelectPrevious",
"KP_UP", "aquaSelectPrevious",
"DOWN", "aquaSelectNext",
--- a/jdk/src/java.desktop/macosx/classes/sun/datatransfer/resources/flavormap.properties Wed Jan 28 04:56:00 2015 -0800
+++ /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/macosx/classes/sun/font/CFont.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/font/CFont.java Wed Jan 28 08:14:18 2015 -0800
@@ -77,14 +77,72 @@
}
private static native long createNativeFont(final String nativeFontName,
- final int style,
- final boolean isFakeItalic);
+ final int style);
private static native void disposeNativeFont(final long nativeFontPtr);
private boolean isFakeItalic;
private String nativeFontName;
private long nativeFontPtr;
+ private native float getWidthNative(final long nativeFontPtr);
+ private native float getWeightNative(final long nativeFontPtr);
+
+ private int fontWidth = -1;
+ private int fontWeight = -1;
+
+ @Override
+ public int getWidth() {
+ if (fontWidth == -1) {
+ // Apple use a range of -1 -> +1, where 0.0 is normal
+ // OpenType uses a % range from 50% -> 200% where 100% is normal
+ // and maps these onto the integer values 1->9.
+ // Since that is what Font2D.getWidth() expects, remap to that.
+ float fw = getWidthNative(getNativeFontPtr());
+ if (fw == 0.0) { // short cut the common case
+ fontWidth = Font2D.FWIDTH_NORMAL;
+ return fontWidth;
+ }
+ fw += 1.0; fw *= 100.0;
+ if (fw <= 50.0) {
+ fontWidth = 1;
+ } else if (fw <= 62.5) {
+ fontWidth = 2;
+ } else if (fw <= 75.0) {
+ fontWidth = 3;
+ } else if (fw <= 87.5) {
+ fontWidth = 4;
+ } else if (fw <= 100.0) {
+ fontWidth = 5;
+ } else if (fw <= 112.5) {
+ fontWidth = 6;
+ } else if (fw <= 125.0) {
+ fontWidth = 7;
+ } else if (fw <= 150.0) {
+ fontWidth = 8;
+ } else {
+ fontWidth = 9;
+ }
+ }
+ return fontWidth;
+ }
+
+ @Override
+ public int getWeight() {
+ if (fontWeight == -1) {
+ // Apple use a range of -1 -> +1, where 0 is medium/regular
+ // Map this on to the OpenType range of 100->900 where
+ // 500 is medium/regular.
+ // We'll actually map to 0->1000 but that's close enough.
+ float fw = getWeightNative(getNativeFontPtr());
+ if (fw == 0) {
+ return Font2D.FWEIGHT_NORMAL;
+ }
+ fw += 1.0; fw *= 500;
+ fontWeight = (int)fw;
+ }
+ return fontWeight;
+ }
+
// this constructor is called from CFontWrapper.m
public CFont(String name) {
this(name, name);
@@ -94,10 +152,11 @@
handle = new Font2DHandle(this);
fullName = name;
familyName = inFamilyName;
- nativeFontName = inFamilyName;
+ nativeFontName = fullName;
setStyle();
}
+ /* Called from CFontManager too */
public CFont(CFont other, String logicalFamilyName) {
handle = new Font2DHandle(this);
fullName = logicalFamilyName;
@@ -109,6 +168,7 @@
public CFont createItalicVariant() {
CFont font = new CFont(this, familyName);
+ font.nativeFontName = fullName;
font.fullName =
fullName + (style == Font.BOLD ? "" : "-") + "Italic-Derived";
font.style |= Font.ITALIC;
@@ -118,7 +178,7 @@
protected synchronized long getNativeFontPtr() {
if (nativeFontPtr == 0L) {
- nativeFontPtr = createNativeFont(nativeFontName, style, isFakeItalic);
+ nativeFontPtr = createNativeFont(nativeFontName, style);
}
return nativeFontPtr;
}
--- a/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java Wed Jan 28 08:14:18 2015 -0800
@@ -252,13 +252,42 @@
final CFont font = new CFont(fontName, fontFamilyName);
registerGenericFont(font);
+ }
- if ((font.getStyle() & Font.ITALIC) == 0) {
- registerGenericFont(font.createItalicVariant(), true);
+ void registerItalicDerived() {
+ FontFamily[] famArr = FontFamily.getAllFontFamilies();
+ for (int i=0; i<famArr.length; i++) {
+ FontFamily family = famArr[i];
+
+ Font2D f2dPlain = family.getFont(Font.PLAIN);
+ if (f2dPlain != null && !(f2dPlain instanceof CFont)) continue;
+ Font2D f2dBold = family.getFont(Font.BOLD);
+ if (f2dBold != null && !(f2dBold instanceof CFont)) continue;
+ Font2D f2dItalic = family.getFont(Font.ITALIC);
+ if (f2dItalic != null && !(f2dItalic instanceof CFont)) continue;
+ Font2D f2dBoldItalic = family.getFont(Font.BOLD|Font.ITALIC);
+ if (f2dBoldItalic != null && !(f2dBoldItalic instanceof CFont)) continue;
+
+ CFont plain = (CFont)f2dPlain;
+ CFont bold = (CFont)f2dBold;
+ CFont italic = (CFont)f2dItalic;
+ CFont boldItalic = (CFont)f2dBoldItalic;
+
+ if (bold == null) bold = plain;
+ if (plain == null && bold == null) continue;
+ if (italic != null && boldItalic != null) continue;
+ if (plain != null && italic == null) {
+ registerGenericFont(plain.createItalicVariant(), true);
+ }
+ if (bold != null && boldItalic == null) {
+ registerGenericFont(bold.createItalicVariant(), true);
+ }
}
}
Object waitForFontsToBeLoaded = new Object();
+ private boolean loadedAllFonts = false;
+
public void loadFonts()
{
synchronized(waitForFontsToBeLoaded)
@@ -267,7 +296,11 @@
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Object>() {
public Object run() {
- loadNativeFonts();
+ if (!loadedAllFonts) {
+ loadNativeFonts();
+ registerItalicDerived();
+ loadedAllFonts = true;
+ }
return null;
}
}
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m Wed Jan 28 08:14:18 2015 -0800
@@ -890,9 +890,9 @@
// text, or 'text in progress'. We also need to send the event if we get an insert text out of the blue!
// (i.e., when the user uses the Character palette or Inkwell), or when the string to insert is a complex
// Unicode value.
- NSUInteger utf8Length = [aString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+ NSUInteger utf16Length = [aString lengthOfBytesUsingEncoding:NSUTF16StringEncoding];
- if ([self hasMarkedText] || !fProcessingKeystroke || (utf8Length > 1)) {
+ if ([self hasMarkedText] || !fProcessingKeystroke || (utf16Length > 2)) {
JNIEnv *env = [ThreadUtilities getJNIEnv];
static JNF_MEMBER_CACHE(jm_selectPreviousGlyph, jc_CInputMethod, "selectPreviousGlyph", "()V");
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m Wed Jan 28 08:14:18 2015 -0800
@@ -35,15 +35,11 @@
#import "AWTStrike.h"
#import "CoreTextSupport.h"
-
-#define DEBUG
-
@implementation AWTFont
-- (id) initWithFont:(NSFont *)font isFakeItalic:(BOOL)isFakeItalic {
+- (id) initWithFont:(NSFont *)font {
self = [super init];
if (self) {
- fIsFakeItalic = isFakeItalic;
fFont = [font retain];
fNativeCGFont = CTFontCopyGraphicsFont((CTFontRef)font, NULL);
}
@@ -72,7 +68,6 @@
+ (AWTFont *) awtFontForName:(NSString *)name
style:(int)style
- isFakeItalic:(BOOL)isFakeItalic
{
// create font with family & size
NSFont *nsFont = [NSFont fontWithName:name size:1.0];
@@ -95,7 +90,7 @@
nsFont = [[NSFontManager sharedFontManager] convertFont:nsFont toHaveTrait:NSBoldFontMask];
}
- return [[[AWTFont alloc] initWithFont:nsFont isFakeItalic:isFakeItalic] autorelease];
+ return [[[AWTFont alloc] initWithFont:nsFont] autorelease];
}
+ (NSFont *) nsFontForJavaFont:(jobject)javaFont env:(JNIEnv *)env {
@@ -354,7 +349,7 @@
JNIEXPORT jlong JNICALL
Java_sun_font_CFont_createNativeFont
(JNIEnv *env, jclass clazz,
- jstring nativeFontName, jint style, jboolean isFakeItalic)
+ jstring nativeFontName, jint style)
{
AWTFont *awtFont = nil;
@@ -362,8 +357,7 @@
awtFont =
[AWTFont awtFontForName:JNFJavaToNSString(env, nativeFontName)
- style:style
- isFakeItalic:isFakeItalic]; // autoreleased
+ style:style]; // autoreleased
if (awtFont) {
CFRetain(awtFont); // GC
@@ -376,6 +370,52 @@
/*
* Class: sun_font_CFont
+ * Method: getWidthNative
+ * Signature: (J)F
+ */
+JNIEXPORT jfloat JNICALL
+Java_sun_font_CFont_getWidthNative
+ (JNIEnv *env, jobject cfont, jlong awtFontPtr)
+{
+ float widthVal;
+JNF_COCOA_ENTER(env);
+
+ AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
+ NSFont* nsFont = awtFont->fFont;
+ NSFontDescriptor *fontDescriptor = nsFont.fontDescriptor;
+ NSDictionary *fontTraits = [fontDescriptor objectForKey : NSFontTraitsAttribute];
+ NSNumber *width = [fontTraits objectForKey : NSFontWidthTrait];
+ widthVal = (float)[width floatValue];
+
+JNF_COCOA_EXIT(env);
+ return (jfloat)widthVal;
+}
+
+/*
+ * Class: sun_font_CFont
+ * Method: getWeightNative
+ * Signature: (J)F
+ */
+JNIEXPORT jfloat JNICALL
+Java_sun_font_CFont_getWeightNative
+ (JNIEnv *env, jobject cfont, jlong awtFontPtr)
+{
+ float weightVal;
+JNF_COCOA_ENTER(env);
+
+ AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
+ NSFont* nsFont = awtFont->fFont;
+ NSFontDescriptor *fontDescriptor = nsFont.fontDescriptor;
+ NSDictionary *fontTraits = [fontDescriptor objectForKey : NSFontTraitsAttribute];
+ NSNumber *weight = [fontTraits objectForKey : NSFontWeightTrait];
+ weightVal = (float)[weight floatValue];
+
+JNF_COCOA_EXIT(env);
+ return (jfloat)weightVal;
+}
+
+/*
+ * Class: sun_font_CFont
* Method: disposeNativeFont
* Signature: (J)V
*/
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java Wed Jan 28 08:14:18 2015 -0800
@@ -100,7 +100,8 @@
private static Dimension prefListSize = new Dimension(75, 150);
private static Dimension PREF_SIZE = new Dimension(435, 360);
- private static Dimension MIN_SIZE = new Dimension(200, 300);
+ private static final int MIN_WIDTH = 200;
+ private static final int MIN_HEIGHT = 300;
private static Dimension ZERO_ACC_SIZE = new Dimension(1, 1);
@@ -1052,6 +1053,7 @@
}
}
+ @Override
public Dimension getPreferredSize(JComponent c) {
Dimension prefSize = new Dimension(PREF_SIZE);
JComponent accessory = getFileChooser().getAccessory();
@@ -1067,10 +1069,12 @@
}
}
- public Dimension getMinimumSize(JComponent x) {
- return new Dimension(MIN_SIZE);
+ @Override
+ public Dimension getMinimumSize(JComponent x) {
+ return new Dimension(MIN_WIDTH, MIN_HEIGHT);
}
+ @Override
public Dimension getMaximumSize(JComponent x) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -65,8 +65,8 @@
private static Dimension WITH_ACCELERATOR_PREF_SIZE = new Dimension(650, 450);
private static Dimension PREF_SIZE = new Dimension(350, 450);
- private static Dimension MIN_SIZE = new Dimension(200, 300);
-
+ private static final int MIN_WIDTH = 200;
+ private static final int MIN_HEIGHT = 300;
private static Dimension PREF_ACC_SIZE = new Dimension(10, 10);
private static Dimension ZERO_ACC_SIZE = new Dimension(1, 1);
@@ -628,6 +628,7 @@
return scrollpane;
}
+ @Override
public Dimension getPreferredSize(JComponent c) {
Dimension prefSize =
(getFileChooser().getAccessory() != null) ? WITH_ACCELERATOR_PREF_SIZE : PREF_SIZE;
@@ -640,10 +641,12 @@
}
}
- public Dimension getMinimumSize(JComponent x) {
- return MIN_SIZE;
+ @Override
+ public Dimension getMinimumSize(JComponent x) {
+ return new Dimension(MIN_WIDTH, MIN_HEIGHT);
}
+ @Override
public Dimension getMaximumSize(JComponent x) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java Wed Jan 28 08:14:18 2015 -0800
@@ -93,7 +93,6 @@
private static int MIN_WIDTH = 425;
private static int MIN_HEIGHT = 245;
- private static Dimension MIN_SIZE = new Dimension(MIN_WIDTH, MIN_HEIGHT);
private static int LIST_PREF_WIDTH = 444;
private static int LIST_PREF_HEIGHT = 138;
@@ -642,6 +641,7 @@
* @return a <code>Dimension</code> specifying the preferred
* width and height of the file chooser
*/
+ @Override
public Dimension getPreferredSize(JComponent c) {
int prefWidth = PREF_SIZE.width;
Dimension d = c.getLayout().preferredLayoutSize(c);
@@ -660,8 +660,9 @@
* @return a <code>Dimension</code> specifying the minimum
* width and height of the file chooser
*/
+ @Override
public Dimension getMinimumSize(JComponent c) {
- return MIN_SIZE;
+ return new Dimension(MIN_WIDTH, MIN_HEIGHT);
}
/**
@@ -671,6 +672,7 @@
* @return a <code>Dimension</code> specifying the maximum
* width and height of the file chooser
*/
+ @Override
public Dimension getMaximumSize(JComponent c) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
--- a/jdk/src/java.desktop/share/classes/java/awt/Component.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -1690,15 +1690,6 @@
/* do nothing */
}
- /*
- * Delete references from LightweightDispatcher of a heavyweight parent
- */
- void clearLightweightDispatcherOnRemove(Component removedComponent) {
- if (parent != null) {
- parent.clearLightweightDispatcherOnRemove(removedComponent);
- }
- }
-
/**
* @deprecated As of JDK version 1.1,
* replaced by <code>setVisible(boolean)</code>.
@@ -6242,7 +6233,7 @@
/**
* Indicates whether a class or its superclasses override coalesceEvents.
* Must be called with lock on coalesceMap and privileged.
- * @see checkCoalsecing
+ * @see checkCoalescing
*/
private static boolean isCoalesceEventsOverriden(Class<?> clazz) {
assert Thread.holdsLock(coalesceMap);
@@ -7083,8 +7074,6 @@
}
synchronized (getTreeLock()) {
- clearLightweightDispatcherOnRemove(this);
-
if (isFocusOwner() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) {
transferFocus(true);
}
--- a/jdk/src/java.desktop/share/classes/java/awt/Container.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/Container.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -41,6 +41,7 @@
import java.io.PrintStream;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.util.EventListener;
@@ -3321,16 +3322,6 @@
}
}
- @Override
- void clearLightweightDispatcherOnRemove(Component removedComponent) {
- if (dispatcher != null) {
- dispatcher.removeReferences(removedComponent);
- } else {
- //It is a Lightweight Container, should clear parent`s Dispatcher
- super.clearLightweightDispatcherOnRemove(removedComponent);
- }
- }
-
final Container getTraversalRoot() {
if (isFocusCycleRoot()) {
return findTraversalRoot();
@@ -4431,7 +4422,9 @@
LightweightDispatcher(Container nativeContainer) {
this.nativeContainer = nativeContainer;
- mouseEventTarget = null;
+ mouseEventTarget = new WeakReference<>(null);
+ targetLastEntered = new WeakReference<>(null);
+ targetLastEnteredDT = new WeakReference<>(null);
eventMask = 0;
}
@@ -4442,9 +4435,9 @@
void dispose() {
//System.out.println("Disposing lw dispatcher");
stopListeningForOtherDrags();
- mouseEventTarget = null;
- targetLastEntered = null;
- targetLastEnteredDT = null;
+ mouseEventTarget.clear();
+ targetLastEntered.clear();
+ targetLastEnteredDT.clear();
}
/**
@@ -4531,65 +4524,62 @@
trackMouseEnterExit(mouseOver, e);
- // 4508327 : MOUSE_CLICKED should only go to the recipient of
- // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
- // MOUSE_CLICKED.
- if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
- mouseEventTarget = (mouseOver != nativeContainer) ? mouseOver: null;
- isCleaned = false;
+ Component met = mouseEventTarget.get();
+ // 4508327 : MOUSE_CLICKED should only go to the recipient of
+ // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
+ // MOUSE_CLICKED.
+ if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
+ met = (mouseOver != nativeContainer) ? mouseOver : null;
+ mouseEventTarget = new WeakReference<>(met);
}
- if (mouseEventTarget != null) {
+ if (met != null) {
switch (id) {
- case MouseEvent.MOUSE_ENTERED:
- case MouseEvent.MOUSE_EXITED:
- break;
- case MouseEvent.MOUSE_PRESSED:
- retargetMouseEvent(mouseEventTarget, id, e);
- break;
- case MouseEvent.MOUSE_RELEASED:
- retargetMouseEvent(mouseEventTarget, id, e);
- break;
- case MouseEvent.MOUSE_CLICKED:
- // 4508327: MOUSE_CLICKED should never be dispatched to a Component
- // other than that which received the MOUSE_PRESSED event. If the
- // mouse is now over a different Component, don't dispatch the event.
- // The previous fix for a similar problem was associated with bug
- // 4155217.
- if (mouseOver == mouseEventTarget) {
- retargetMouseEvent(mouseOver, id, e);
- }
- break;
- case MouseEvent.MOUSE_MOVED:
- retargetMouseEvent(mouseEventTarget, id, e);
- break;
- case MouseEvent.MOUSE_DRAGGED:
- if (isMouseGrab(e)) {
- retargetMouseEvent(mouseEventTarget, id, e);
- }
- break;
- case MouseEvent.MOUSE_WHEEL:
- // This may send it somewhere that doesn't have MouseWheelEvents
- // enabled. In this case, Component.dispatchEventImpl() will
- // retarget the event to a parent that DOES have the events enabled.
- if (eventLog.isLoggable(PlatformLogger.Level.FINEST) && (mouseOver != null)) {
- eventLog.finest("retargeting mouse wheel to " +
+ case MouseEvent.MOUSE_ENTERED:
+ case MouseEvent.MOUSE_EXITED:
+ break;
+ case MouseEvent.MOUSE_PRESSED:
+ retargetMouseEvent(met, id, e);
+ break;
+ case MouseEvent.MOUSE_RELEASED:
+ retargetMouseEvent(met, id, e);
+ break;
+ case MouseEvent.MOUSE_CLICKED:
+ // 4508327: MOUSE_CLICKED should never be dispatched to a Component
+ // other than that which received the MOUSE_PRESSED event. If the
+ // mouse is now over a different Component, don't dispatch the event.
+ // The previous fix for a similar problem was associated with bug
+ // 4155217.
+ if (mouseOver == met) {
+ retargetMouseEvent(mouseOver, id, e);
+ }
+ break;
+ case MouseEvent.MOUSE_MOVED:
+ retargetMouseEvent(met, id, e);
+ break;
+ case MouseEvent.MOUSE_DRAGGED:
+ if (isMouseGrab(e)) {
+ retargetMouseEvent(met, id, e);
+ }
+ break;
+ case MouseEvent.MOUSE_WHEEL:
+ // This may send it somewhere that doesn't have MouseWheelEvents
+ // enabled. In this case, Component.dispatchEventImpl() will
+ // retarget the event to a parent that DOES have the events enabled.
+ if (eventLog.isLoggable(PlatformLogger.Level.FINEST) && (mouseOver != null)) {
+ eventLog.finest("retargeting mouse wheel to " +
mouseOver.getName() + ", " +
mouseOver.getClass());
- }
- retargetMouseEvent(mouseOver, id, e);
- break;
+ }
+ retargetMouseEvent(mouseOver, id, e);
+ break;
}
- //Consuming of wheel events is implemented in "retargetMouseEvent".
- if (id != MouseEvent.MOUSE_WHEEL) {
- e.consume();
+ //Consuming of wheel events is implemented in "retargetMouseEvent".
+ if (id != MouseEvent.MOUSE_WHEEL) {
+ e.consume();
+ }
}
- } else if (isCleaned && id != MouseEvent.MOUSE_WHEEL) {
- //After mouseEventTarget was removed and cleaned should consume all events
- //until new mouseEventTarget is found
- e.consume();
- }
- return e.isConsumed();
+ return e.isConsumed();
}
private boolean processDropTargetEvent(SunDropTargetEvent e) {
@@ -4652,9 +4642,10 @@
} else if (id == MouseEvent.MOUSE_EXITED) {
isMouseDTInNativeContainer = false;
}
- targetLastEnteredDT = retargetMouseEnterExit(targetOver, e,
- targetLastEnteredDT,
+ Component tle = retargetMouseEnterExit(targetOver, e,
+ targetLastEnteredDT.get(),
isMouseDTInNativeContainer);
+ targetLastEnteredDT = new WeakReference<>(tle);
}
/*
@@ -4680,9 +4671,10 @@
isMouseInNativeContainer = false;
stopListeningForOtherDrags();
}
- targetLastEntered = retargetMouseEnterExit(targetOver, e,
- targetLastEntered,
+ Component tle = retargetMouseEnterExit(targetOver, e,
+ targetLastEntered.get(),
isMouseInNativeContainer);
+ targetLastEntered = new WeakReference<>(tle);
}
private Component retargetMouseEnterExit(Component targetOver, MouseEvent e,
@@ -4944,22 +4936,17 @@
* is null, there are currently no events being forwarded to
* a subcomponent.
*/
- private transient Component mouseEventTarget;
+ private transient WeakReference<Component> mouseEventTarget;
/**
* The last component entered by the {@code MouseEvent}.
*/
- private transient Component targetLastEntered;
+ private transient WeakReference<Component> targetLastEntered;
/**
* The last component entered by the {@code SunDropTargetEvent}.
*/
- private transient Component targetLastEnteredDT;
-
- /**
- * Indicates whether {@code mouseEventTarget} was removed and nulled
- */
- private transient boolean isCleaned;
+ private transient WeakReference<Component> targetLastEnteredDT;
/**
* Is the mouse over the native container.
@@ -5000,17 +4987,4 @@
AWTEvent.MOUSE_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK |
AWTEvent.MOUSE_WHEEL_EVENT_MASK;
-
- void removeReferences(Component removedComponent) {
- if (mouseEventTarget == removedComponent) {
- isCleaned = true;
- mouseEventTarget = null;
- }
- if (targetLastEntered == removedComponent) {
- targetLastEntered = null;
- }
- if (targetLastEnteredDT == removedComponent) {
- targetLastEnteredDT = null;
- }
- }
}
--- a/jdk/src/java.desktop/share/classes/java/awt/EventQueue.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/EventQueue.java Wed Jan 28 08:14:18 2015 -0800
@@ -182,7 +182,14 @@
private FwDispatcher fwDispatcher;
- private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue");
+ private static volatile PlatformLogger eventLog;
+
+ private static final PlatformLogger getEventLog() {
+ if(eventLog == null) {
+ eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue");
+ }
+ return eventLog;
+ }
static {
AWTAccessor.setEventQueueAccessor(
@@ -762,8 +769,8 @@
dispatchThread.stopDispatching();
}
} else {
- if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
- eventLog.fine("Unable to dispatch event: " + event);
+ if (getEventLog().isLoggable(PlatformLogger.Level.FINE)) {
+ getEventLog().fine("Unable to dispatch event: " + event);
}
}
}
@@ -860,8 +867,8 @@
* @since 1.2
*/
public void push(EventQueue newEventQueue) {
- if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
- eventLog.fine("EventQueue.push(" + newEventQueue + ")");
+ if (getEventLog().isLoggable(PlatformLogger.Level.FINE)) {
+ getEventLog().fine("EventQueue.push(" + newEventQueue + ")");
}
pushPopLock.lock();
@@ -886,8 +893,8 @@
// Use getNextEventPrivate() as it doesn't call flushPendingEvents()
newEventQueue.postEventPrivate(topQueue.getNextEventPrivate());
} catch (InterruptedException ie) {
- if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
- eventLog.fine("Interrupted push", ie);
+ if (getEventLog().isLoggable(PlatformLogger.Level.FINE)) {
+ getEventLog().fine("Interrupted push", ie);
}
}
}
@@ -925,8 +932,8 @@
* @since 1.2
*/
protected void pop() throws EmptyStackException {
- if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
- eventLog.fine("EventQueue.pop(" + this + ")");
+ if (getEventLog().isLoggable(PlatformLogger.Level.FINE)) {
+ getEventLog().fine("EventQueue.pop(" + this + ")");
}
pushPopLock.lock();
@@ -948,8 +955,8 @@
try {
prevQueue.postEventPrivate(topQueue.getNextEventPrivate());
} catch (InterruptedException ie) {
- if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
- eventLog.fine("Interrupted pop", ie);
+ if (getEventLog().isLoggable(PlatformLogger.Level.FINE)) {
+ getEventLog().fine("Interrupted pop", ie);
}
}
}
--- a/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/MenuBar.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -181,7 +181,7 @@
* removed from the menu bar, and replaced with the specified menu.
* @param m the menu to be set as the help menu
*/
- public void setHelpMenu(Menu m) {
+ public void setHelpMenu(final Menu m) {
synchronized (getTreeLock()) {
if (helpMenu == m) {
return;
@@ -189,11 +189,11 @@
if (helpMenu != null) {
remove(helpMenu);
}
- if (m.parent != this) {
- add(m);
- }
helpMenu = m;
if (m != null) {
+ if (m.parent != this) {
+ add(m);
+ }
m.isHelpMenu = true;
m.parent = this;
MenuBarPeer peer = (MenuBarPeer)this.peer;
@@ -242,7 +242,7 @@
* @param index the position of the menu to be removed.
* @see java.awt.MenuBar#add(java.awt.Menu)
*/
- public void remove(int index) {
+ public void remove(final int index) {
synchronized (getTreeLock()) {
Menu m = getMenu(index);
menus.removeElementAt(index);
@@ -252,6 +252,10 @@
m.parent = null;
peer.delMenu(index);
}
+ if (helpMenu == m) {
+ helpMenu = null;
+ m.isHelpMenu = false;
+ }
}
}
--- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/Clipboard.java Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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/java/awt/image/BufferedImage.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/image/BufferedImage.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -25,26 +25,23 @@
package java.awt.image;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.Point;
+import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
-import java.awt.Graphics2D;
-import java.awt.GraphicsConfiguration;
-import java.awt.GraphicsEnvironment;
-import java.awt.ImageCapabilities;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.Point2D;
-import java.awt.Point;
-import java.awt.Rectangle;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Hashtable;
+import java.util.Set;
import java.util.Vector;
+import sun.awt.image.ByteComponentRaster;
import sun.awt.image.BytePackedRaster;
-import sun.awt.image.ShortComponentRaster;
-import sun.awt.image.ByteComponentRaster;
import sun.awt.image.IntegerComponentRaster;
import sun.awt.image.OffScreenImageSource;
+import sun.awt.image.ShortComponentRaster;
/**
*
@@ -68,18 +65,14 @@
* @see Raster
* @see WritableRaster
*/
-
public class BufferedImage extends java.awt.Image
implements WritableRenderedImage, Transparency
{
- int imageType = TYPE_CUSTOM;
- ColorModel colorModel;
- WritableRaster raster;
- OffScreenImageSource osis;
- Hashtable<?, ?> properties;
-
- boolean isAlphaPremultiplied;// If true, alpha has been premultiplied in
- // color channels
+ private int imageType = TYPE_CUSTOM;
+ private ColorModel colorModel;
+ private final WritableRaster raster;
+ private OffScreenImageSource osis;
+ private Hashtable<String, Object> properties;
/**
* Image Type Constants
@@ -328,8 +321,8 @@
0x000000ff, // Blue
0x0 // Alpha
);
- raster = colorModel.createCompatibleWritableRaster(width,
- height);
+ raster = colorModel.createCompatibleWritableRaster(width,
+ height);
}
break;
@@ -355,9 +348,8 @@
true, // Alpha Premultiplied
DataBuffer.TYPE_INT
);
-
- raster = colorModel.createCompatibleWritableRaster(width,
- height);
+ raster = colorModel.createCompatibleWritableRaster(width,
+ height);
}
break;
@@ -368,8 +360,8 @@
0x0000ff00, // Green
0x00ff0000 // Blue
);
- raster = colorModel.createCompatibleWritableRaster(width,
- height);
+ raster = colorModel.createCompatibleWritableRaster(width,
+ height);
}
break;
@@ -642,7 +634,14 @@
colorModel = cm;
this.raster = raster;
- this.properties = properties;
+ if (properties != null && !properties.isEmpty()) {
+ this.properties = new Hashtable<>();
+ for (final Object key : properties.keySet()) {
+ if (key instanceof String) {
+ this.properties.put((String) key, properties.get(key));
+ }
+ }
+ }
int numBands = raster.getNumBands();
boolean isAlphaPre = cm.isAlphaPremultiplied();
final boolean isStandard = isStandard(cm, raster);
@@ -1272,7 +1271,11 @@
* or <code>null</code> if no property names are recognized.
*/
public String[] getPropertyNames() {
- return null;
+ if (properties == null || properties.isEmpty()) {
+ return null;
+ }
+ final Set<String> keys = properties.keySet();
+ return keys.toArray(new String[keys.size()]);
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/AbstractButton.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/AbstractButton.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -2215,10 +2215,7 @@
*/
public boolean imageUpdate(Image img, int infoflags,
int x, int y, int w, int h) {
- Icon iconDisplayed = getIcon();
- if (iconDisplayed == null) {
- return false;
- }
+ Icon iconDisplayed = null;
if (!model.isEnabled()) {
if (model.isSelected()) {
@@ -2238,7 +2235,12 @@
iconDisplayed = getSelectedIcon();
}
- if (!SwingUtilities.doesIconReferenceImage(iconDisplayed, img)) {
+ if (iconDisplayed == null) {
+ iconDisplayed = getIcon();
+ }
+
+ if (iconDisplayed == null
+ || !SwingUtilities.doesIconReferenceImage(iconDisplayed, img)) {
// We don't know about this image, disable the notification so
// we don't keep repainting.
return false;
--- a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -27,22 +27,15 @@
import java.util.HashSet;
import java.util.Hashtable;
-import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Vector;
import java.util.EventListener;
import java.util.Set;
-import java.util.Map;
-import java.util.HashMap;
import java.awt.*;
import java.awt.event.*;
-import java.awt.image.VolatileImage;
-import java.awt.Graphics2D;
import java.awt.peer.LightweightPeer;
-import java.awt.dnd.DropTarget;
-import java.awt.font.FontRenderContext;
import java.beans.PropertyChangeListener;
import java.beans.VetoableChangeListener;
import java.beans.VetoableChangeSupport;
@@ -1868,7 +1861,7 @@
/**
* Overrides <code>Container.getAlignmentY</code> to return
- * the horizontal alignment.
+ * the vertical alignment.
*
* @return the value of the <code>alignmentY</code> property
* @see #setAlignmentY
@@ -1882,9 +1875,9 @@
}
/**
- * Sets the horizontal alignment.
+ * Sets the vertical alignment.
*
- * @param alignmentY the new horizontal alignment
+ * @param alignmentY the new vertical alignment
* @see #getAlignmentY
* @beaninfo
* description: The preferred vertical alignment of the component.
@@ -1897,7 +1890,7 @@
/**
* Overrides <code>Container.getAlignmentX</code> to return
- * the vertical alignment.
+ * the horizontal alignment.
*
* @return the value of the <code>alignmentX</code> property
* @see #setAlignmentX
@@ -1911,9 +1904,9 @@
}
/**
- * Sets the vertical alignment.
+ * Sets the horizontal alignment.
*
- * @param alignmentX the new vertical alignment
+ * @param alignmentX the new horizontal alignment
* @see #getAlignmentX
* @beaninfo
* description: The preferred horizontal alignment of the component.
--- a/jdk/src/java.desktop/share/classes/javax/swing/JFormattedTextField.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JFormattedTextField.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -30,7 +30,6 @@
import java.io.*;
import java.text.*;
import java.util.*;
-import javax.swing.UIManager;
import javax.swing.event.*;
import javax.swing.plaf.UIResource;
import javax.swing.text.*;
@@ -151,7 +150,7 @@
* will be created to handle formatting of numbers:
* <pre>
* JFormattedTextField tf = new JFormattedTextField();
- * tf.setValue(new Number(100));
+ * tf.setValue(100);
* </pre>
* <p>
* <strong>Warning:</strong> As the <code>AbstractFormatter</code> will
--- a/jdk/src/java.desktop/share/classes/javax/swing/JTextArea.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JTextArea.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -493,7 +493,6 @@
* @exception IllegalArgumentException if part of the range is an
* invalid position in the model
* @see #insert
- * @see #replaceRange
*/
public void replaceRange(String str, int start, int end) {
if (end < start) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDesktopPaneUI.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDesktopPaneUI.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -36,10 +36,9 @@
import java.awt.Graphics;
import java.awt.KeyboardFocusManager;
import java.awt.*;
-import java.util.Vector;
+
import sun.swing.DefaultLookup;
import sun.swing.UIAction;
-import sun.awt.AppContext;
/**
* Basic L&F for a desktop.
@@ -49,9 +48,6 @@
public class BasicDesktopPaneUI extends DesktopPaneUI {
// Old actions forward to an instance of this.
private static final Actions SHARED_ACTION = new Actions();
- private static Dimension minSize = new Dimension(0,0);
- private static Dimension maxSize = new Dimension(Integer.MAX_VALUE,
- Integer.MAX_VALUE);
private Handler handler;
private PropertyChangeListener pcl;
@@ -304,13 +300,19 @@
public void paint(Graphics g, JComponent c) {}
- public Dimension getPreferredSize(JComponent c) {return null;}
+ @Override
+ public Dimension getPreferredSize(JComponent c) {
+ return null;
+ }
+ @Override
public Dimension getMinimumSize(JComponent c) {
- return minSize;
- }
- public Dimension getMaximumSize(JComponent c){
- return maxSize;
+ return new Dimension(0, 0);
+ }
+
+ @Override
+ public Dimension getMaximumSize(JComponent c) {
+ return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
/**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -92,8 +92,6 @@
private static int MIN_WIDTH = 500;
private static int MIN_HEIGHT = 326;
- private static Dimension MIN_SIZE = new Dimension(MIN_WIDTH, MIN_HEIGHT);
-
private static int LIST_PREF_WIDTH = 405;
private static int LIST_PREF_HEIGHT = 135;
private static Dimension LIST_PREF_SIZE = new Dimension(LIST_PREF_WIDTH, LIST_PREF_HEIGHT);
@@ -615,6 +613,7 @@
* @return a <code>Dimension</code> specifying the preferred
* width and height of the file chooser
*/
+ @Override
public Dimension getPreferredSize(JComponent c) {
int prefWidth = PREF_SIZE.width;
Dimension d = c.getLayout().preferredLayoutSize(c);
@@ -633,8 +632,9 @@
* @return a <code>Dimension</code> specifying the minimum
* width and height of the file chooser
*/
+ @Override
public Dimension getMinimumSize(JComponent c) {
- return MIN_SIZE;
+ return new Dimension(MIN_WIDTH, MIN_HEIGHT);
}
/**
@@ -644,6 +644,7 @@
* @return a <code>Dimension</code> specifying the maximum
* width and height of the file chooser
*/
+ @Override
public Dimension getMaximumSize(JComponent c) {
return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
@@ -654,7 +655,8 @@
} else {
JFileChooser fc = getFileChooser();
if ((fc.isDirectorySelectionEnabled() && !fc.isFileSelectionEnabled()) ||
- (fc.isDirectorySelectionEnabled() && fc.isFileSelectionEnabled() && fc.getFileSystemView().isFileSystemRoot(file))) {
+ (fc.isDirectorySelectionEnabled() && fc.isFileSelectionEnabled()
+ && fc.getFileSystemView().isFileSystemRoot(file))) {
return file.getPath();
} else {
return file.getName();
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/GapContent.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/GapContent.java Wed Jan 28 08:14:18 2015 -0800
@@ -710,8 +710,9 @@
* @param length the length >= 0
* @return the set of instances
*/
- protected Vector<UndoPosRef> getPositionsInRange(Vector<UndoPosRef> v,
- int offset, int length) {
+ @SuppressWarnings({"rawtypes", "unchecked"}) // UndoPosRef type cannot be exposed
+ protected Vector getPositionsInRange(Vector v,
+ int offset, int length) {
int endOffset = offset + length;
int startIndex;
int endIndex;
@@ -758,7 +759,8 @@
*
* @param positions the UndoPosRef instances to reset
*/
- protected void updateUndoPositions(Vector<UndoPosRef> positions, int offset,
+ @SuppressWarnings("rawtypes") // UndoPosRef type cannot be exposed
+ protected void updateUndoPositions(Vector positions, int offset,
int length) {
// Find the indexs of the end points.
int endOffset = offset + length;
@@ -775,7 +777,7 @@
// Reset the location of the refenences.
for(int counter = positions.size() - 1; counter >= 0; counter--) {
- UndoPosRef ref = positions.elementAt(counter);
+ UndoPosRef ref = (UndoPosRef) positions.elementAt(counter);
ref.resetLocation(endOffset, g1);
}
// We have to resort the marks in the range startIndex to endIndex.
@@ -902,7 +904,8 @@
protected String string;
/** An array of instances of UndoPosRef for the Positions in the
* range that was removed, valid after undo. */
- protected Vector<UndoPosRef> posRefs;
+ @SuppressWarnings("rawtypes") // UndoPosRef type cannot be exposed
+ protected Vector posRefs;
} // GapContent.InsertUndo
@@ -911,6 +914,7 @@
*/
@SuppressWarnings("serial") // JDK-implementation class
class RemoveUndo extends AbstractUndoableEdit {
+ @SuppressWarnings("unchecked")
protected RemoveUndo(int offset, String string) {
super();
this.offset = offset;
@@ -934,6 +938,7 @@
}
}
+ @SuppressWarnings("unchecked")
public void redo() throws CannotRedoException {
super.redo();
try {
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/StringContent.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/StringContent.java Wed Jan 28 08:14:18 2015 -0800
@@ -271,11 +271,12 @@
* @param length the length >= 0
* @return the set of instances
*/
- protected Vector<UndoPosRef> getPositionsInRange(Vector<UndoPosRef> v, int offset,
- int length) {
+ @SuppressWarnings({"rawtypes", "unchecked"}) // UndoPosRef type cannot be exposed
+ protected Vector getPositionsInRange(Vector v, int offset,
+ int length) {
int n = marks.size();
int end = offset + length;
- Vector<UndoPosRef> placeIn = (v == null) ? new Vector<>() : v;
+ Vector placeIn = (v == null) ? new Vector() : v;
for (int i = 0; i < n; i++) {
PosRec mark = marks.elementAt(i);
if (mark.unused) {
@@ -298,9 +299,10 @@
*
* @param positions the positions of the instances
*/
- protected void updateUndoPositions(Vector<UndoPosRef> positions) {
+ @SuppressWarnings("rawtypes") // UndoPosRef type cannot be exposed
+ protected void updateUndoPositions(Vector positions) {
for(int counter = positions.size() - 1; counter >= 0; counter--) {
- UndoPosRef ref = positions.elementAt(counter);
+ UndoPosRef ref = (UndoPosRef) positions.elementAt(counter);
// Check if the Position is still valid.
if(ref.rec.unused) {
positions.removeElementAt(counter);
@@ -437,7 +439,8 @@
protected String string;
// An array of instances of UndoPosRef for the Positions in the
// range that was removed, valid after undo.
- protected Vector<UndoPosRef> posRefs;
+ @SuppressWarnings("rawtypes") // UndoPosRef type cannot be exposed
+ protected Vector posRefs;
}
@@ -445,6 +448,7 @@
* UndoableEdit created for removes.
*/
class RemoveUndo extends AbstractUndoableEdit {
+ @SuppressWarnings("unchecked")
protected RemoveUndo(int offset, String string) {
super();
this.offset = offset;
@@ -471,6 +475,7 @@
}
}
+ @SuppressWarnings("unchecked")
public void redo() throws CannotRedoException {
super.redo();
try {
--- a/jdk/src/java.desktop/share/classes/sun/datatransfer/DataFlavorUtil.java Wed Jan 28 04:56:00 2015 -0800
+++ /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 Wed Jan 28 04:56:00 2015 -0800
+++ /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/share/classes/sun/font/Font2D.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/font/Font2D.java Wed Jan 28 08:14:18 2015 -0800
@@ -157,6 +157,21 @@
}
}
+ public static final int FWIDTH_NORMAL = 5; // OS/2 usWidthClass
+ public static final int FWEIGHT_NORMAL = 400; // OS/2 usWeightClass
+ public static final int FWEIGHT_BOLD = 700; // OS/2 usWeightClass
+
+ public int getWidth() {
+ return FWIDTH_NORMAL;
+ }
+
+ public int getWeight() {
+ if ((style & Font.BOLD) !=0) {
+ return FWEIGHT_BOLD;
+ } else {
+ return FWEIGHT_NORMAL;
+ }
+ }
int getRank() {
return fontRank;
--- a/jdk/src/java.desktop/share/classes/sun/font/FontFamily.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/font/FontFamily.java Wed Jan 28 08:14:18 2015 -0800
@@ -27,6 +27,7 @@
import java.io.File;
import java.awt.Font;
+import java.util.Collection;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Locale;
@@ -134,7 +135,98 @@
return java.util.Objects.equals(newDir, existDir);
}
+ /*
+ * We want a family to be of the same width and prefer medium/normal width.
+ * Once we find a particular width we accept more of the same width
+ * until we find one closer to normal when we 'evict' all existing fonts.
+ * So once we see a 'normal' width font we evict all members that are not
+ * normal width and then accept only new ones that are normal width.
+ *
+ * Once a font passes the width test we subject it to the weight test.
+ * For Plain we target the weight the closest that is <= NORMAL (400)
+ * For Bold we target the weight that is closest to BOLD (700).
+ *
+ * In the future, rather than discarding these fonts, we should
+ * extend the family to include these so lookups on these properties
+ * can locate them, as presently they will only be located by full name
+ * based lookup.
+ */
+
+ private int familyWidth = 0;
+ private boolean preferredWidth(Font2D font) {
+
+ int newWidth = font.getWidth();
+
+ if (familyWidth == 0) {
+ familyWidth = newWidth;
+ return true;
+ }
+
+ if (newWidth == familyWidth) {
+ return true;
+ }
+
+ if (Math.abs(Font2D.FWIDTH_NORMAL - newWidth) <
+ Math.abs(Font2D.FWIDTH_NORMAL - familyWidth))
+ {
+ if (FontUtilities.debugFonts()) {
+ FontUtilities.getLogger().info(
+ "Found more preferred width. New width = " + newWidth +
+ " Old width = " + familyWidth + " in font " + font +
+ " nulling out fonts plain: " + plain + " bold: " + bold +
+ " italic: " + italic + " bolditalic: " + bolditalic);
+ }
+ familyWidth = newWidth;
+ plain = bold = italic = bolditalic = null;
+ return true;
+ } else if (FontUtilities.debugFonts()) {
+ FontUtilities.getLogger().info(
+ "Family rejecting font " + font +
+ " of less preferred width " + newWidth);
+ }
+ return false;
+ }
+
+ private boolean closerWeight(Font2D currFont, Font2D font, int style) {
+ if (familyWidth != font.getWidth()) {
+ return false;
+ }
+
+ if (currFont == null) {
+ return true;
+ }
+
+ if (FontUtilities.debugFonts()) {
+ FontUtilities.getLogger().info(
+ "New weight for style " + style + ". Curr.font=" + currFont +
+ " New font="+font+" Curr.weight="+ + currFont.getWeight()+
+ " New weight="+font.getWeight());
+ }
+
+ int newWeight = font.getWeight();
+ switch (style) {
+ case Font.PLAIN:
+ case Font.ITALIC:
+ return (newWeight <= Font2D.FWEIGHT_NORMAL &&
+ newWeight > currFont.getWeight());
+
+ case Font.BOLD:
+ case Font.BOLD|Font.ITALIC:
+ return (Math.abs(newWeight - Font2D.FWEIGHT_BOLD) <
+ Math.abs(currFont.getWeight() - Font2D.FWEIGHT_BOLD));
+
+ default:
+ return false;
+ }
+ }
+
public void setFont(Font2D font, int style) {
+
+ if (FontUtilities.isLogging()) {
+ FontUtilities.getLogger().info(
+ "Request to add " + font + " with style " + style +
+ " to family " + this);
+ }
/* Allow a lower-rank font only if its a file font
* from the exact same source as any previous font.
*/
@@ -152,19 +244,27 @@
switch (style) {
case Font.PLAIN:
- plain = font;
+ if (preferredWidth(font) && closerWeight(plain, font, style)) {
+ plain = font;
+ }
break;
case Font.BOLD:
- bold = font;
+ if (preferredWidth(font) && closerWeight(bold, font, style)) {
+ bold = font;
+ }
break;
case Font.ITALIC:
- italic = font;
+ if (preferredWidth(font) && closerWeight(italic, font, style)) {
+ italic = font;
+ }
break;
case Font.BOLD|Font.ITALIC:
- bolditalic = font;
+ if (preferredWidth(font) && closerWeight(bolditalic, font, style)) {
+ bolditalic = font;
+ }
break;
default:
@@ -316,6 +416,11 @@
return allLocaleNames.get(name.toLowerCase());
}
+ public static FontFamily[] getAllFontFamilies() {
+ Collection<FontFamily> families = familyNameMap.values();
+ return families.toArray(new FontFamily[0]);
+ }
+
public String toString() {
return
"Font family: " + familyName +
--- a/jdk/src/java.desktop/share/classes/sun/font/TrueTypeFont.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/share/classes/sun/font/TrueTypeFont.java Wed Jan 28 08:14:18 2015 -0800
@@ -963,6 +963,18 @@
setStyle(getTableBuffer(os_2Tag));
}
+ private int fontWidth = 0;
+ @Override
+ public int getWidth() {
+ return (fontWidth > 0) ? fontWidth : super.getWidth();
+ }
+
+ private int fontWeight = 0;
+ @Override
+ public int getWeight() {
+ return (fontWeight > 0) ? fontWeight : super.getWeight();
+ }
+
/* TrueTypeFont can use the fsSelection fields of OS/2 table
* to determine the style. In the unlikely case that doesn't exist,
* can use macStyle in the 'head' table but simpler to
@@ -978,8 +990,15 @@
private static final int fsSelectionBoldBit = 0x00020;
private static final int fsSelectionRegularBit = 0x00040;
private void setStyle(ByteBuffer os_2Table) {
+ if (os_2Table == null) {
+ return;
+ }
+ if (os_2Table.capacity() >= 8) {
+ fontWeight = os_2Table.getChar(4) & 0xffff;
+ fontWidth = os_2Table.getChar(6) & 0xffff;
+ }
/* fsSelection is unsigned short at buffer offset 62 */
- if (os_2Table == null || os_2Table.capacity() < 64) {
+ if (os_2Table.capacity() < 64) {
super.setStyle();
return;
}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XAWTFormatter.java Wed Jan 28 04:56:00 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +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 sun.awt.X11;
-
-import java.util.logging.*;
-import java.text.*;
-import java.util.*;
-import java.io.*;
-
-/**
- * Formatter class providing ANSI output. Based on java.util.logging.SimpleFormatter sources.
- */
-
-public class XAWTFormatter extends java.util.logging.Formatter {
- Date dat = new Date();
- private final static String format = "{0,date} {0,time}";
- private MessageFormat formatter;
-
- private Object args[] = new Object[1];
-
- // Line separator string. This is the value of the line.separator
- // property at the moment that the SimpleFormatter was created.
- private String lineSeparator = System.lineSeparator();
-
- boolean displayFullRecord = false;
- boolean useANSI = false;
- boolean showDate = true;
- boolean showLevel = true;
- boolean swapMethodClass = false;
- public XAWTFormatter() {
- displayFullRecord = "true".equals(LogManager.getLogManager().getProperty("XAWTFormatter.displayFullRecord"));
- useANSI = "true".equals(LogManager.getLogManager().getProperty("XAWTFormatter.useANSI"));
- showDate = !"false".equals(LogManager.getLogManager().getProperty("XAWTFormatter.showDate"));
- showLevel = !"false".equals(LogManager.getLogManager().getProperty("XAWTFormatter.showLevel"));
- swapMethodClass = "true".equals(LogManager.getLogManager().getProperty("XAWTFormatter.swapMethodClass"));
- }
-
- /**
- * Format the given LogRecord.
- * @param record the log record to be formatted.
- * @return a formatted log record
- */
- public synchronized String format(LogRecord record) {
- StringBuffer sb = new StringBuffer();
- if (useANSI) {
- Level lev = record.getLevel();
- if (Level.FINEST.equals(lev)) {
- sb.append("[36m");
- } else if (Level.FINER.equals(lev)) {
- sb.append("[32m");
- } else if (Level.FINE.equals(lev)) {
- sb.append("[34m");
- }
- }
- if (displayFullRecord) {
- if (showDate) {
- // Minimize memory allocations here.
- dat.setTime(record.getMillis());
- args[0] = dat;
- StringBuffer text = new StringBuffer();
- if (formatter == null) {
- formatter = new MessageFormat(format);
- }
- formatter.format(args, text, null);
- sb.append(text);
- sb.append(" ");
- } else {
- sb.append(" ");
- }
- if (swapMethodClass) {
- if (record.getSourceMethodName() != null) {
- sb.append(" [35m");
- sb.append(record.getSourceMethodName());
- sb.append("[30m ");
- }
- if (record.getSourceClassName() != null) {
- sb.append(record.getSourceClassName());
- } else {
- sb.append(record.getLoggerName());
- }
- } else {
- if (record.getSourceClassName() != null) {
- sb.append(record.getSourceClassName());
- } else {
- sb.append(record.getLoggerName());
- }
- if (record.getSourceMethodName() != null) {
- sb.append(" [35m");
- sb.append(record.getSourceMethodName());
- sb.append("[30m");
- }
- }
- sb.append(lineSeparator);
- }
- if (useANSI) {
- Level lev = record.getLevel();
- if (Level.FINEST.equals(lev)) {
- sb.append("[36m");
- } else if (Level.FINER.equals(lev)) {
- sb.append("[32m");
- } else if (Level.FINE.equals(lev)) {
- sb.append("[34m");
- }
- }
- if (showLevel) {
- sb.append(record.getLevel().getLocalizedName());
- sb.append(": ");
- }
- String message = formatMessage(record);
- sb.append(message);
- sb.append(lineSeparator);
- if (record.getThrown() != null) {
- try {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- record.getThrown().printStackTrace(pw);
- pw.close();
- sb.append(sw.toString());
- } catch (Exception ex) {
- }
- }
- if (useANSI) {
- sb.append("[30m");
- }
- return sb.toString();
- }
-}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbeddedFrame.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbeddedFrame.java Wed Jan 28 08:14:18 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -25,15 +25,17 @@
package sun.awt.X11;
+import java.awt.AWTKeyStroke;
+import java.awt.Toolkit;
+
import sun.awt.EmbeddedFrame;
-import java.awt.*;
-import java.awt.AWTKeyStroke;
-import java.util.logging.Logger;
+import sun.util.logging.PlatformLogger;
@SuppressWarnings("serial") // JDK-implementation class
public class XEmbeddedFrame extends EmbeddedFrame {
- private static final Logger log = Logger.getLogger(XEmbeddedFrame.class.getName());
+ private static final PlatformLogger log =
+ PlatformLogger.getLogger(XEmbeddedFrame.class.getName());
long handle;
public XEmbeddedFrame() {
--- a/jdk/src/java.desktop/unix/classes/sun/datatransfer/resources/flavormap.properties Wed Jan 28 04:56:00 2015 -0800
+++ /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/unix/classes/sun/font/FcFontConfiguration.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/src/java.desktop/unix/classes/sun/font/FcFontConfiguration.java Wed Jan 28 08:14:18 2015 -0800
@@ -180,7 +180,7 @@
String[] componentFaceNames = cfi[idx].getComponentFaceNames();
FontDescriptor[] ret = new FontDescriptor[componentFaceNames.length];
for (int i = 0; i < componentFaceNames.length; i++) {
- ret[i] = new FontDescriptor(componentFaceNames[i], StandardCharsets.UTF_8.newEncoder(), new int[0]);
+ ret[i] = new FontDescriptor(componentFaceNames[i], StandardCharsets.ISO_8859_1.newEncoder(), new int[0]);
}
return ret;
--- a/jdk/src/java.desktop/windows/classes/sun/datatransfer/resources/flavormap.properties Wed Jan 28 04:56:00 2015 -0800
+++ /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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Color/LoadProfileWithSM.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+import java.awt.color.*;
+
+/*
+ * @test
+ * @bug 8058969
+ * @summary test standard profiles loads with SecurityManager installed.
+ * @run main/othervm LoadProfileWithSM
+ */
+
+public class LoadProfileWithSM {
+
+ public static void main(String[] args) {
+ System.setSecurityManager(new SecurityManager());
+ ICC_Profile profile =
+ ((ICC_ColorSpace)(ColorSpace.getInstance(
+ ColorSpace.CS_GRAY))).getProfile();
+ /* request profile data in order to force profile loading */
+ profile.getData();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Color/LoadStandardProfilesTest.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8039271
+ * @summary test all standard profiles load correctly.
+ */
+
+import java.awt.color.ICC_Profile;
+
+public class LoadStandardProfilesTest {
+
+ public static void main(String args[]) {
+ try {
+ ICC_Profile sRGB = ICC_Profile.getInstance("sRGB.pf");
+ ICC_Profile gray = ICC_Profile.getInstance("GRAY.pf");
+ ICC_Profile pycc = ICC_Profile.getInstance("PYCC.pf");
+ ICC_Profile ciexyz = ICC_Profile.getInstance("CIEXYZ.pf");
+ ICC_Profile linearRGB = ICC_Profile.getInstance("LINEAR_RGB.pf");
+
+ if (sRGB == null ||
+ gray == null ||
+ pycc == null ||
+ ciexyz == null ||
+ linearRGB == null)
+ {
+ throw new RuntimeException("null profile.");
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Component/DimensionEncapsulation/DimensionEncapsulation.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Checkbox;
+import java.awt.Choice;
+import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.FileDialog;
+import java.awt.Frame;
+import java.awt.Label;
+import java.awt.List;
+import java.awt.Panel;
+import java.awt.ScrollPane;
+import java.awt.Scrollbar;
+import java.awt.TextArea;
+import java.awt.TextField;
+import java.awt.Window;
+import java.util.ArrayList;
+import java.util.Objects;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JColorChooser;
+import javax.swing.JDesktopPane;
+import javax.swing.JDialog;
+import javax.swing.JEditorPane;
+import javax.swing.JFileChooser;
+import javax.swing.JFormattedTextField;
+import javax.swing.JFrame;
+import javax.swing.JInternalFrame;
+import javax.swing.JLabel;
+import javax.swing.JLayeredPane;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPasswordField;
+import javax.swing.JPopupMenu;
+import javax.swing.JProgressBar;
+import javax.swing.JRadioButton;
+import javax.swing.JRadioButtonMenuItem;
+import javax.swing.JRootPane;
+import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
+import javax.swing.JSlider;
+import javax.swing.JSpinner;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.JTextPane;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+import javax.swing.JTree;
+import javax.swing.JViewport;
+import javax.swing.JWindow;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UIManager.LookAndFeelInfo;
+import javax.swing.UnsupportedLookAndFeelException;
+import javax.swing.table.JTableHeader;
+
+import static javax.swing.UIManager.getInstalledLookAndFeels;
+
+/**
+ * @test
+ * @bug 6459798
+ * @author Sergey Bylokhov
+ */
+public final class DimensionEncapsulation implements Runnable {
+
+ java.util.List<Component> failures = new ArrayList<>();
+
+ public static void main(final String[] args) throws Exception {
+ for (final LookAndFeelInfo laf : getInstalledLookAndFeels()) {
+ SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf));
+ SwingUtilities.invokeAndWait(new DimensionEncapsulation());
+ }
+ }
+
+ @Override
+ public void run() {
+ runTest(new Panel());
+ runTest(new Button());
+ runTest(new Checkbox());
+ runTest(new Canvas());
+ runTest(new Choice());
+ runTest(new Label());
+ runTest(new Scrollbar());
+ runTest(new TextArea());
+ runTest(new TextField());
+ runTest(new Dialog(new JFrame()));
+ runTest(new Frame());
+ runTest(new Window(new JFrame()));
+ runTest(new FileDialog(new JFrame()));
+ runTest(new List());
+ runTest(new ScrollPane());
+ runTest(new JFrame());
+ runTest(new JDialog(new JFrame()));
+ runTest(new JWindow(new JFrame()));
+ runTest(new JLabel("hi"));
+ runTest(new JMenu());
+ runTest(new JTree());
+ runTest(new JTable());
+ runTest(new JMenuItem());
+ runTest(new JCheckBoxMenuItem());
+ runTest(new JToggleButton());
+ runTest(new JSpinner());
+ runTest(new JSlider());
+ runTest(Box.createVerticalBox());
+ runTest(Box.createHorizontalBox());
+ runTest(new JTextField());
+ runTest(new JTextArea());
+ runTest(new JTextPane());
+ runTest(new JPasswordField());
+ runTest(new JFormattedTextField());
+ runTest(new JEditorPane());
+ runTest(new JButton());
+ runTest(new JColorChooser());
+ runTest(new JFileChooser());
+ runTest(new JCheckBox());
+ runTest(new JInternalFrame());
+ runTest(new JDesktopPane());
+ runTest(new JTableHeader());
+ runTest(new JLayeredPane());
+ runTest(new JRootPane());
+ runTest(new JMenuBar());
+ runTest(new JOptionPane());
+ runTest(new JRadioButton());
+ runTest(new JRadioButtonMenuItem());
+ runTest(new JPopupMenu());
+ //runTest(new JScrollBar()); --> don't test defines max and min in
+ // terms of preferred
+ runTest(new JScrollPane());
+ runTest(new JViewport());
+ runTest(new JSplitPane());
+ runTest(new JTabbedPane());
+ runTest(new JToolBar());
+ runTest(new JSeparator());
+ runTest(new JProgressBar());
+ if (!failures.isEmpty()) {
+ System.out.println("These classes failed");
+ for (final Component failure : failures) {
+ System.out.println(failure.getClass());
+ }
+ throw new RuntimeException("Test failed");
+ }
+ }
+
+ public void runTest(final Component c) {
+ try {
+ test(c);
+ c.setMinimumSize(new Dimension(100, 10));
+ c.setMaximumSize(new Dimension(200, 20));
+ c.setPreferredSize(new Dimension(300, 30));
+ test(c);
+ } catch (final Throwable ignored) {
+ failures.add(c);
+ }
+ }
+
+ public void test(final Component component) {
+ final Dimension psize = component.getPreferredSize();
+ psize.width += 200;
+ if (Objects.equals(psize, component.getPreferredSize())) {
+ throw new RuntimeException("PreferredSize is wrong");
+ }
+ final Dimension msize = component.getMaximumSize();
+ msize.width += 200;
+ if (Objects.equals(msize, component.getMaximumSize())) {
+ throw new RuntimeException("MaximumSize is wrong");
+ }
+ final Dimension misize = component.getMinimumSize();
+ misize.width += 200;
+ if (Objects.equals(misize, component.getMinimumSize())) {
+ throw new RuntimeException("MinimumSize is wrong");
+ }
+ }
+
+ private static void setLookAndFeel(final LookAndFeelInfo laf) {
+ try {
+ UIManager.setLookAndFeel(laf.getClassName());
+ System.out.println("LookAndFeel: " + laf.getClassName());
+ } catch (ClassNotFoundException | InstantiationException |
+ UnsupportedLookAndFeelException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Component/InsetsEncapsulation/InsetsEncapsulation.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.awt.Component;
+import java.awt.Insets;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JColorChooser;
+import javax.swing.JComponent;
+import javax.swing.JDesktopPane;
+import javax.swing.JEditorPane;
+import javax.swing.JFileChooser;
+import javax.swing.JFormattedTextField;
+import javax.swing.JInternalFrame;
+import javax.swing.JLabel;
+import javax.swing.JLayeredPane;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPasswordField;
+import javax.swing.JPopupMenu;
+import javax.swing.JProgressBar;
+import javax.swing.JRadioButton;
+import javax.swing.JRadioButtonMenuItem;
+import javax.swing.JRootPane;
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
+import javax.swing.JSlider;
+import javax.swing.JSpinner;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.JTextPane;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+import javax.swing.JTree;
+import javax.swing.JViewport;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+import javax.swing.table.JTableHeader;
+
+import static javax.swing.UIManager.LookAndFeelInfo;
+import static javax.swing.UIManager.getInstalledLookAndFeels;
+
+/**
+ * @test
+ * @bug 6459800
+ * @author Sergey Bylokhov
+ */
+public final class InsetsEncapsulation implements Runnable {
+
+ private final Collection<Component> failures = new ArrayList<>();
+
+ public static void main(final String[] args) throws Exception {
+ for (final LookAndFeelInfo laf : getInstalledLookAndFeels()) {
+ SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf));
+ SwingUtilities.invokeAndWait(new InsetsEncapsulation());
+ }
+ }
+
+ @Override
+ public void run() {
+ runTest(new JLabel("hi"));
+ runTest(new JMenu());
+ runTest(new JTree());
+ runTest(new JTable());
+ runTest(new JMenuItem());
+ runTest(new JCheckBoxMenuItem());
+ runTest(new JToggleButton());
+ runTest(new JSpinner());
+ runTest(new JSlider());
+ runTest(Box.createVerticalBox());
+ runTest(Box.createHorizontalBox());
+ runTest(new JTextField());
+ runTest(new JTextArea());
+ runTest(new JTextPane());
+ runTest(new JPasswordField());
+ runTest(new JFormattedTextField());
+ runTest(new JEditorPane());
+ runTest(new JButton());
+ runTest(new JColorChooser());
+ runTest(new JFileChooser());
+ runTest(new JCheckBox());
+ runTest(new JInternalFrame());
+ runTest(new JDesktopPane());
+ runTest(new JTableHeader());
+ runTest(new JLayeredPane());
+ runTest(new JRootPane());
+ runTest(new JMenuBar());
+ runTest(new JOptionPane());
+ runTest(new JRadioButton());
+ runTest(new JRadioButtonMenuItem());
+ runTest(new JPopupMenu());
+ runTest(new JScrollBar());
+ runTest(new JScrollPane());
+ runTest(new JViewport());
+ runTest(new JSplitPane());
+ runTest(new JTabbedPane());
+ runTest(new JToolBar());
+ runTest(new JSeparator());
+ runTest(new JProgressBar());
+ if (!failures.isEmpty()) {
+ System.out.println("These classes failed");
+ for (final Component failure : failures) {
+ System.out.println(failure.getClass());
+ }
+ throw new RuntimeException("Test failed");
+ }
+ }
+
+ void runTest(final JComponent component) {
+ try {
+ test(component);
+ } catch (final Throwable ignored) {
+ failures.add(component);
+ }
+ }
+
+ void test(final JComponent component) {
+ final Insets p = component.getInsets();
+ p.top += 3;
+ if (p.equals(component.getInsets())) {
+ throw new RuntimeException("Insets altered by altering Insets!");
+ }
+ }
+
+ private static void setLookAndFeel(final LookAndFeelInfo laf) {
+ try {
+ UIManager.setLookAndFeel(laf.getClassName());
+ System.out.println("LookAndFeel: " + laf.getClassName());
+ } catch (ClassNotFoundException | InstantiationException |
+ UnsupportedLookAndFeelException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FontClass/HelvLtOblTest.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8064833
+ * @summary Test correct font is obtained via famil+style
+ * @run main HelvLtOblTest
+ */
+
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.RenderingHints;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.image.BufferedImage;
+
+public class HelvLtOblTest extends JComponent {
+
+ static Font helvFont = null;
+
+ static int[] codes = { 0x23, 0x4a, 0x48, 0x3, 0x4a, 0x55, 0x42, 0x4d,
+ 0x4a, 0x44, 0x3,
+ 0x53, 0x46, 0x45, 0x3, 0x55, 0x46, 0x59, 0x55, };
+
+ static String str = "Big italic red text";
+
+ public static void main(String[] args) throws Exception {
+ String os = System.getProperty("os.name");
+ if (!os.startsWith("Mac")) {
+ return;
+ }
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ Font[] fonts = ge.getAllFonts();
+ for (int i=0; i<fonts.length; i++) {
+ if (fonts[i].getPSName().equals("Helvetica-LightOblique")) {
+ helvFont = fonts[i];
+ break;
+ }
+ }
+ if (helvFont == null) {
+ return;
+ }
+ final HelvLtOblTest test = new HelvLtOblTest();
+ SwingUtilities.invokeLater(() -> {
+ JFrame f = new JFrame();
+ f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ f.add("Center", test);
+ f.pack();
+ f.setVisible(true);
+ });
+ test.compareImages();
+ }
+
+ public Dimension getPreferredSize() {
+ return new Dimension(400,400);
+ }
+
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ Graphics2D g2 = (Graphics2D)g;
+ FontRenderContext frc = new FontRenderContext(null, true, true);
+ Font f = helvFont.deriveFont(Font.PLAIN, 40);
+ System.out.println("font = " +f.getFontName());
+ GlyphVector gv = f.createGlyphVector(frc, codes);
+ g.setFont(f);
+ g.setColor(Color.white);
+ g.fillRect(0,0,400,400);
+ g.setColor(Color.black);
+ g2.drawGlyphVector(gv, 5,200);
+ g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
+ RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+ g2.drawString(str, 5, 250);
+ }
+
+ void compareImages() {
+ BufferedImage bi0 = drawText(false);
+ BufferedImage bi1 = drawText(true);
+ compare(bi0, bi1);
+ }
+
+ BufferedImage drawText(boolean doGV) {
+ int w = 400;
+ int h = 50;
+ BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = bi.createGraphics();
+ g.setColor(Color.white);
+ g.fillRect(0,0,w,h);
+ g.setColor(Color.black);
+ Font f = helvFont.deriveFont(Font.PLAIN, 40);
+ g.setFont(f);
+ int x = 5;
+ int y = h - 10;
+ if (doGV) {
+ FontRenderContext frc = new FontRenderContext(null, true, true);
+ GlyphVector gv = f.createGlyphVector(frc, codes);
+ g.drawGlyphVector(gv, 5, y);
+ } else {
+ g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
+ RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+ g.drawString(str, x, y);
+ }
+ return bi;
+ }
+
+ // Need to allow for minimal rounding error, so allow each component
+ // to differ by 1.
+ void compare(BufferedImage bi0, BufferedImage bi1) {
+ int wid = bi0.getWidth();
+ int hgt = bi0.getHeight();
+ for (int x=0; x<wid; x++) {
+ for (int y=0; y<hgt; y++) {
+ int rgb0 = bi0.getRGB(x, y);
+ int rgb1 = bi1.getRGB(x, y);
+ if (rgb0 == rgb1) continue;
+ int r0 = (rgb0 & 0xff0000) >> 16;
+ int r1 = (rgb1 & 0xff0000) >> 16;
+ int rdiff = r0-r1; if (rdiff<0) rdiff = -rdiff;
+ int g0 = (rgb0 & 0x00ff00) >> 8;
+ int g1 = (rgb1 & 0x00ff00) >> 8;
+ int gdiff = g0-g1; if (gdiff<0) gdiff = -gdiff;
+ int b0 = (rgb0 & 0x0000ff);
+ int b1 = (rgb1 & 0x0000ff);
+ int bdiff = b0-b1; if (bdiff<0) bdiff = -bdiff;
+ if (rdiff > 1 || gdiff > 1 || bdiff > 1) {
+ throw new RuntimeException(
+ "Images differ at x=" + x + " y="+ y + " " +
+ Integer.toHexString(rgb0) + " vs " +
+ Integer.toHexString(rgb1));
+ }
+ }
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FullScreen/NonExistentDisplayModeTest/NonExistentDisplayModeTest.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2006, 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.
+ *
+ * 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.
+ */
+
+import java.awt.DisplayMode;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.util.ArrayList;
+import java.util.Random;
+
+import static java.awt.DisplayMode.REFRESH_RATE_UNKNOWN;
+
+/**
+ * @test
+ * @bug 6430607
+ * @summary Test that we throw an exception for incorrect display modes
+ * @author Dmitri.Trembovetski@Sun.COM area=FullScreen
+ * @run main/othervm NonExistentDisplayModeTest
+ * @run main/othervm -Dsun.java2d.noddraw=true NonExistentDisplayModeTest
+ * @run main/othervm -Dsun.java2d.opengl=true NonExistentDisplayModeTest
+ */
+public class NonExistentDisplayModeTest {
+
+ public static void main(String[] args) {
+ new NonExistentDisplayModeTest().start();
+ }
+
+ private void start() {
+ Frame f = new Frame("Testing, please wait..");
+ f.pack();
+ GraphicsDevice gd = f.getGraphicsConfiguration().getDevice();
+ if (!gd.isFullScreenSupported()) {
+ System.out.println("Exclusive FS mode not supported, test passed.");
+ f.dispose();
+ return;
+ }
+
+ gd.setFullScreenWindow(f);
+ if (!gd.isDisplayChangeSupported()) {
+ System.out.println("DisplayMode change not supported, test passed.");
+ f.dispose();
+ return;
+ }
+
+ DisplayMode dms[] = gd.getDisplayModes();
+ ArrayList<DisplayMode> dmList = new ArrayList<DisplayMode>(dms.length);
+ for (DisplayMode dm : dms) {
+ dmList.add(dm);
+ }
+
+ ArrayList<DisplayMode> nonExistentDms = createNonExistentDMList(dmList);
+
+ for (DisplayMode dm : nonExistentDms) {
+ boolean exThrown = false;
+ try {
+ System.out.printf("Testing mode: (%4dx%4d) depth=%3d rate=%d\n",
+ dm.getWidth(), dm.getHeight(),
+ dm.getBitDepth(), dm.getRefreshRate());
+ gd.setDisplayMode(dm);
+ } catch (IllegalArgumentException e) {
+ exThrown = true;
+ }
+ if (!exThrown) {
+ gd.setFullScreenWindow(null);
+ f.dispose();
+ throw new
+ RuntimeException("Failed: No exception thrown for dm "+dm);
+ }
+ }
+ gd.setFullScreenWindow(null);
+ f.dispose();
+ System.out.println("Test passed.");
+ }
+
+ private static final Random rnd = new Random();
+ private ArrayList<DisplayMode>
+ createNonExistentDMList(ArrayList<DisplayMode> dmList)
+ {
+ ArrayList<DisplayMode> newList =
+ new ArrayList<DisplayMode>(dmList.size());
+ // vary one parameter at a time
+ int param = 0;
+ for (DisplayMode dm : dmList) {
+ param = ++param % 3;
+ switch (param) {
+ case 0: {
+ DisplayMode newDM = deriveSize(dm);
+ if (!dmList.contains(newDM)) {
+ newList.add(newDM);
+ }
+ break;
+ }
+ case 1: {
+ DisplayMode newDM = deriveDepth(dm);
+ if (!dmList.contains(newDM)) {
+ newList.add(newDM);
+ }
+ break;
+ }
+ case 2: {
+ if (dm.getRefreshRate() != REFRESH_RATE_UNKNOWN) {
+ DisplayMode newDM = deriveRR(dm);
+ if (!dmList.contains(newDM)) {
+ newList.add(newDM);
+ }
+ }
+ break;
+ }
+ }
+ }
+ return newList;
+ }
+
+ private static DisplayMode deriveSize(DisplayMode dm) {
+ int w = dm.getWidth() / 7;
+ int h = dm.getHeight() / 3;
+ return new DisplayMode(w, h, dm.getBitDepth(), dm.getRefreshRate());
+ }
+ private static DisplayMode deriveRR(DisplayMode dm) {
+ return new DisplayMode(dm.getWidth(), dm.getHeight(),
+ dm.getBitDepth(), 777);
+ }
+ private static DisplayMode deriveDepth(DisplayMode dm) {
+ int depth;
+ if (dm.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI) {
+ depth = 77;
+ } else {
+ depth = DisplayMode.BIT_DEPTH_MULTI;
+ }
+ return new DisplayMode(dm.getWidth(), dm.getHeight(),
+ depth, dm.getRefreshRate());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/MenuBar/RemoveHelpMenu/RemoveHelpMenu.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.awt.Frame;
+import java.awt.Menu;
+import java.awt.MenuBar;
+
+/**
+ * @test
+ * @bug 6475361
+ * @author Sergey Bylokhov
+ */
+public final class RemoveHelpMenu {
+
+ public static void main(final String[] args) {
+ final Frame frame = new Frame("RemoveHelpMenu Test");
+ try {
+ frame.pack();
+ // peer exists
+ test1(getMenuBar(frame));
+ test2(getMenuBar(frame));
+ test3(getMenuBar(frame));
+ test4(getMenuBar(frame));
+ } finally {
+ frame.dispose();
+ }
+ // peer is null
+ test1(getMenuBar(frame));
+ test2(getMenuBar(frame));
+ test3(getMenuBar(frame));
+ test4(getMenuBar(frame));
+ }
+
+ private static MenuBar getMenuBar(final Frame frame) {
+ final MenuBar menuBar = new MenuBar();
+ frame.setMenuBar(menuBar);
+ return menuBar;
+ }
+
+ private static void checkHelpMenu(final Menu menu, final boolean expected) {
+ final boolean actual = menu.toString().contains("isHelpMenu=true");
+ if (actual != expected) {
+ throw new RuntimeException("Incorrect menu type");
+ }
+ }
+
+ private static void checkMenuCount(final MenuBar bar, final int expected) {
+ final int actual = bar.getMenuCount();
+ if (actual != expected) {
+ throw new RuntimeException("Incorrect menus count");
+ }
+ }
+
+ private static void checkCurrentMenu(final MenuBar bar, final Menu menu) {
+ if (bar.getHelpMenu() != menu) {
+ throw new RuntimeException("Wrong HelpMenu");
+ }
+ }
+
+ private static void test1(final MenuBar menuBar) {
+ checkCurrentMenu(menuBar, null);
+ checkMenuCount(menuBar, 0);
+ }
+
+ private static void test2(final MenuBar menuBar) {
+ final Menu helpMenu = new Menu("Help Menu");
+ menuBar.setHelpMenu(helpMenu);
+ checkCurrentMenu(menuBar, helpMenu);
+ checkMenuCount(menuBar, 1);
+ checkHelpMenu(helpMenu, true);
+
+ menuBar.remove(helpMenu);
+ checkCurrentMenu(menuBar, null);
+ checkMenuCount(menuBar, 0);
+ checkHelpMenu(helpMenu, false);
+ }
+
+ private static void test3(final MenuBar menuBar) {
+ final Menu helpMenu1 = new Menu("Help Menu1");
+ final Menu helpMenu2 = new Menu("Help Menu2");
+ menuBar.setHelpMenu(helpMenu1);
+ checkCurrentMenu(menuBar, helpMenu1);
+ checkMenuCount(menuBar, 1);
+ checkHelpMenu(helpMenu1, true);
+ checkHelpMenu(helpMenu2, false);
+
+ menuBar.setHelpMenu(helpMenu2);
+ checkCurrentMenu(menuBar, helpMenu2);
+ checkMenuCount(menuBar, 1);
+ checkHelpMenu(helpMenu1, false);
+ checkHelpMenu(helpMenu2, true);
+
+ menuBar.remove(helpMenu2);
+ checkCurrentMenu(menuBar, null);
+ checkMenuCount(menuBar, 0);
+ checkHelpMenu(helpMenu1, false);
+ checkHelpMenu(helpMenu2, false);
+ }
+
+ private static void test4(final MenuBar menuBar) {
+ final Menu helpMenu = new Menu("Help Menu");
+ menuBar.setHelpMenu(helpMenu);
+ checkCurrentMenu(menuBar, helpMenu);
+ checkMenuCount(menuBar, 1);
+ checkHelpMenu(helpMenu, true);
+
+ menuBar.setHelpMenu(null);
+ checkCurrentMenu(menuBar, null);
+ checkMenuCount(menuBar, 0);
+ checkHelpMenu(helpMenu, false);
+ }
+}
\ No newline at end of file
--- a/jdk/test/java/awt/Mixing/HWDisappear.java Wed Jan 28 04:56:00 2015 -0800
+++ b/jdk/test/java/awt/Mixing/HWDisappear.java Wed Jan 28 08:14:18 2015 -0800
@@ -40,6 +40,7 @@
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
+import javax.swing.plaf.metal.MetalLookAndFeel;
import test.java.awt.regtesthelpers.Util;
public class HWDisappear
@@ -109,7 +110,7 @@
// Click on the button.
Point bLoc = b.getLocationOnScreen();
- robot.mouseMove(bLoc.x + b.getWidth() / 2, bLoc.y + 5);
+ robot.mouseMove(bLoc.x + b.getWidth() / 2, bLoc.y + b.getHeight() / 2);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
@@ -148,8 +149,9 @@
// instantiated in the same VM. Being static (and using
// static vars), it aint gonna work. Not worrying about
// it for now.
- public static void main( String args[] ) throws InterruptedException
+ public static void main( String args[] ) throws Exception
{
+ UIManager.setLookAndFeel(new MetalLookAndFeel());
mainThread = Thread.currentThread();
try
{
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Mouse/RemovedComponentMouseListener/RemovedComponentMouseListener.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8061636
+ * @summary fix for 7079254 changes behavior of MouseListener, MouseMotionListener
+ * @library ../../regtesthelpers
+ * @build Util
+ * @author Alexander Zvegintsev
+ * @run main RemovedComponentMouseListener
+ */
+
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import javax.swing.*;
+import test.java.awt.regtesthelpers.Util;
+
+public class RemovedComponentMouseListener extends JFrame {
+
+ static boolean mouseReleasedReceived;
+ static JButton button;
+
+ public RemovedComponentMouseListener() {
+ JPanel panel = new JPanel();
+ JPanel buttonPanel = new JPanel();
+ button = new JButton("Button");
+
+ setSize(300, 300);
+
+ buttonPanel.add(button);
+ panel.add(buttonPanel);
+ setContentPane(panel);
+
+ button.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ buttonPanel.remove(button);
+ panel.add(button);
+ button.revalidate();
+ button.repaint();
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ mouseReleasedReceived = true;
+ }
+ });
+
+ setVisible(true);
+ }
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(() -> {
+ new RemovedComponentMouseListener();
+ });
+
+ Robot r = Util.createRobot();
+ r.setAutoDelay(100);
+ r.waitForIdle();
+ Util.pointOnComp(button, r);
+
+ r.waitForIdle();
+ r.mousePress(InputEvent.BUTTON1_MASK);
+ r.waitForIdle();
+ r.mouseRelease(InputEvent.BUTTON1_MASK);
+ r.waitForIdle();
+ if (!mouseReleasedReceived) {
+ throw new RuntimeException("mouseReleased event was not received");
+ }
+ }
+}
--- a/jdk/test/java/awt/color/LoadProfileWithSM.java Wed Jan 28 04:56:00 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +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.
- *
- * 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.
- */
-
-import java.awt.color.*;
-
-/*
- * @test
- * @bug 8058969
- * @summary test standard profiles loads with SecurityManager installed.
- * @run main/othervm LoadProfileWithSM
- */
-
-public class LoadProfileWithSM {
-
- public static void main(String[] args) {
- System.setSecurityManager(new SecurityManager());
- ICC_Profile profile =
- ((ICC_ColorSpace)(ColorSpace.getInstance(
- ColorSpace.CS_GRAY))).getProfile();
- /* request profile data in order to force profile loading */
- profile.getData();
- }
-}
--- a/jdk/test/java/awt/color/LoadStandardProfilesTest.java Wed Jan 28 04:56:00 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +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.
- *
- * 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.
- */
-
-/*
- * @test
- * @bug 8039271
- * @summary test all standard profiles load correctly.
- */
-
-import java.awt.color.ICC_Profile;
-
-public class LoadStandardProfilesTest {
-
- public static void main(String args[]) {
- try {
- ICC_Profile sRGB = ICC_Profile.getInstance("sRGB.pf");
- ICC_Profile gray = ICC_Profile.getInstance("GRAY.pf");
- ICC_Profile pycc = ICC_Profile.getInstance("PYCC.pf");
- ICC_Profile ciexyz = ICC_Profile.getInstance("CIEXYZ.pf");
- ICC_Profile linearRGB = ICC_Profile.getInstance("LINEAR_RGB.pf");
-
- if (sRGB == null ||
- gray == null ||
- pycc == null ||
- ciexyz == null ||
- linearRGB == null)
- {
- throw new RuntimeException("null profile.");
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/KeyEvent/AltCharAcceleratorTest/AltCharAcceleratorTest.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/*
+@test
+@bug 8068283
+@summary Checks that <Alt>+Char accelerators work when pressed in a text component
+@author Anton Nashatyrev
+@run main AltCharAcceleratorTest
+*/
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class AltCharAcceleratorTest {
+
+ boolean action1 = false;
+ boolean action2 = false;
+
+ CountDownLatch focusLatch = new CountDownLatch(1);
+ CountDownLatch actionLatch = new CountDownLatch(2);
+
+ public AltCharAcceleratorTest() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ JFrame f = new JFrame("frame");
+ final JTextField t = new JTextField();
+ JMenuBar mb = new JMenuBar();
+ JMenu m1 = new JMenu("File");
+ JMenuItem i1 = new JMenuItem("Save");
+ JMenuItem i2 = new JMenuItem("Load");
+
+ i1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.ALT_MASK));
+ i2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.ALT_MASK));
+
+ i1.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ System.out.println("Action1!");
+ action1 = true;
+ actionLatch.countDown();
+ }
+ });
+
+ i2.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ System.out.println("Action2!");
+ action2 = true;
+ actionLatch.countDown();
+ }
+ });
+
+ t.addFocusListener(new FocusAdapter() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ System.out.println("Focused!");
+ focusLatch.countDown();
+ }
+ });
+
+ t.setColumns(10);
+ t.requestFocusInWindow();
+
+ f.setJMenuBar(mb);
+ mb.add(m1);
+ m1.add(i1);
+ m1.add(i2);
+
+ f.setLayout(new FlowLayout());
+ f.add(t);
+ f.setSize(200, 200);
+
+ f.setVisible(true);
+ }
+ });
+ }
+
+ void test() throws Exception {
+ ((SunToolkit) Toolkit.getDefaultToolkit()).realSync();
+
+ focusLatch.await(5, TimeUnit.SECONDS);
+
+ Robot robot = new Robot();
+ robot.setAutoDelay(100);
+
+ robot.keyPress(KeyEvent.VK_ALT);
+ robot.keyPress(KeyEvent.VK_T);
+ robot.keyRelease(KeyEvent.VK_T);
+ robot.keyRelease(KeyEvent.VK_ALT);
+
+ robot.keyPress(KeyEvent.VK_ALT);
+ robot.keyPress(KeyEvent.VK_F);
+ robot.keyRelease(KeyEvent.VK_F);
+ robot.keyRelease(KeyEvent.VK_ALT);
+
+ actionLatch.await(5, TimeUnit.SECONDS);
+
+ if (!action1 || !action2) {
+ throw new RuntimeException("Actions not performed");
+ }
+
+ System.out.println("Passed.");
+ }
+
+ public static void main(String[] args) throws Exception {
+ AltCharAcceleratorTest t = new AltCharAcceleratorTest();
+ t.test();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/BufferedImage/GetPropertyNames.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.util.Properties;
+
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
+
+/**
+ * @test
+ * @bug 8066132
+ * @author Sergey Bylokhov
+ */
+public final class GetPropertyNames {
+
+ static BufferedImage defaultProps = new BufferedImage(1, 1, TYPE_INT_ARGB);
+
+ public static void main(final String[] args) {
+ // default result is null
+ if (defaultProps.getPropertyNames() != null) {
+ throw new RuntimeException("PropertyNames should be null");
+ }
+ // for null properties result is null
+ final BufferedImage emptyProps = getBufferedImage(null);
+ if (emptyProps.getPropertyNames() != null) {
+ throw new RuntimeException("PropertyNames should be null");
+ }
+ // for empty properties result is null
+ final BufferedImage nullProps = getBufferedImage(new Properties());
+ if (nullProps.getPropertyNames() != null) {
+ throw new RuntimeException("PropertyNames should be null");
+ }
+ // for non-string keys result is null
+ final Properties properties = new Properties();
+ properties.put(1, 1);
+ properties.put(2, 2);
+ properties.put(3, 3);
+ final BufferedImage nonStringProps = getBufferedImage(properties);
+ if (nonStringProps.getPropertyNames() != null) {
+ throw new RuntimeException("PropertyNames should be null");
+ }
+ // for string keys result is not null
+ properties.clear();
+ properties.setProperty("1", "1");
+ properties.setProperty("2", "2");
+ validate(getBufferedImage(properties), 2);
+ // for the mix of strings and objects result is not null
+ properties.clear();
+ properties.put(1, 1);
+ properties.put(2, 2);
+ properties.put(3, 3);
+ properties.setProperty("key1", "value1");
+ properties.setProperty("key2", "value2");
+ final BufferedImage mixProps = getBufferedImage(properties);
+ validate(mixProps, 2);
+ if (!"value1".equals(mixProps.getProperty("key1"))
+ || !"value2".equals(mixProps.getProperty("key2"))) {
+ throw new RuntimeException("Wrong key-value pair");
+ }
+ }
+
+
+ private static BufferedImage getBufferedImage(final Properties properties) {
+ return new BufferedImage(defaultProps.getColorModel(),
+ defaultProps.getRaster(),
+ defaultProps.isAlphaPremultiplied(),
+ properties);
+ }
+
+ private static void validate(final BufferedImage bi, final int expected) {
+ final String[] names = bi.getPropertyNames();
+ if (names.length != expected) {
+ throw new RuntimeException("Wrong number of names");
+ }
+ for (final String name : names) {
+ final Object property = bi.getProperty(name);
+ if (property == Image.UndefinedProperty || property == null) {
+ throw new RuntimeException("Unexpected property");
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/print/PrintSEUmlauts/PrintSEUmlauts.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+import java.awt.Graphics;
+import java.awt.GraphicsEnvironment;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import javax.print.DocFlavor;
+import javax.print.DocPrintJob;
+import javax.print.SimpleDoc;
+import javax.print.StreamPrintService;
+import javax.print.StreamPrintServiceFactory;
+import javax.print.attribute.HashDocAttributeSet;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.event.PrintJobAdapter;
+import javax.print.event.PrintJobEvent;
+
+/*
+ * @test
+ * @bug 8067364
+ * @summary Printing to Postscript doesn't support dieresis
+ * @build PrintSEUmlauts
+ * @run main/othervm PrintSEUmlauts
+ */
+public class PrintSEUmlauts implements Printable {
+
+ public static void main(String[] args) throws Exception {
+
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+
+ DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
+ String mime = DocFlavor.BYTE_ARRAY.POSTSCRIPT.getMimeType();
+
+ StreamPrintServiceFactory[] factories =
+ StreamPrintServiceFactory.
+ lookupStreamPrintServiceFactories(flavor, mime);
+ if (factories.length == 0) {
+ System.out.println("No print service found.");
+ return;
+ }
+
+ FileOutputStream output = new FileOutputStream("out.ps");
+ StreamPrintService service = factories[0].getPrintService(output);
+
+ SimpleDoc doc =
+ new SimpleDoc(new PrintSEUmlauts(),
+ DocFlavor.SERVICE_FORMATTED.PRINTABLE,
+ new HashDocAttributeSet());
+ DocPrintJob job = service.createPrintJob();
+ job.addPrintJobListener(new PrintJobAdapter() {
+ @Override
+ public void printJobCompleted(PrintJobEvent pje) {
+ testPrintAndExit();
+ }
+ });
+
+ job.print(doc, new HashPrintRequestAttributeSet());
+ }
+
+ private static final boolean DEBUG = false;
+ private static void testPrintAndExit() {
+ String expected = "<e4> 7.44 100.0 100.0 S";
+ String content = "";
+
+ File file = new File("out.ps");
+ if (!DEBUG) {
+ file.deleteOnExit();
+ }
+
+ try (FileInputStream stream = new FileInputStream(file)) {
+ byte[] data = new byte[(int) file.length()];
+ stream.read(data);
+ content = new String(data, StandardCharsets.ISO_8859_1);
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+
+ if (!content.contains(expected)) {
+ System.err.println("FAIL");
+ if (DEBUG) {
+ System.err.println("printing content");
+ System.err.println(content);
+ }
+ throw new RuntimeException("Expected <e4> to represent 'ä' but not found!");
+ }
+ System.err.println("SUCCESS");
+ }
+
+ public int print(Graphics g, PageFormat pf, int pg) {
+ if (pg > 0) return NO_SUCH_PAGE;
+ g.drawString("ä", 100, 100);
+ return PAGE_EXISTS;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/AbstractButton/AnimatedIcon/AnimatedIcon.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+import java.awt.image.BufferedImage;
+import java.awt.image.ImageObserver;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.SwingUtilities;
+
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
+
+/**
+ * @test
+ * @bug 6573305
+ * @summary Animated icon should animate when the JButton is pressed.
+ * @author Sergey Bylokhov
+ */
+public final class AnimatedIcon {
+
+ public static void main(final String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(() -> {
+ final BufferedImage bi = new BufferedImage(1, 1, TYPE_INT_RGB);
+ final ImageIcon icon = new ImageIcon(bi);
+ final JButton button = new JButton(icon);
+ // Default icon is set => imageUpdate should return true for it
+ isAnimated(bi, button);
+ button.getModel().setPressed(true);
+ button.getModel().setArmed(true);
+ isAnimated(bi, button);
+ button.getModel().setPressed(false);
+ button.getModel().setArmed(false);
+ button.getModel().setSelected(true);
+ isAnimated(bi, button);
+ button.getModel().setSelected(false);
+ button.getModel().setRollover(true);
+ button.setRolloverEnabled(true);
+ isAnimated(bi, button);
+ button.getModel().setSelected(true);
+ isAnimated(bi, button);
+ // Default icon is not set => imageUpdate should return true for
+ // other icons if any
+ button.setIcon(null);
+ button.setPressedIcon(icon);
+ button.getModel().setPressed(true);
+ button.getModel().setArmed(true);
+ isAnimated(bi, button);
+ });
+ }
+
+ private static void isAnimated(BufferedImage bi, JButton button) {
+ if (!button.imageUpdate(bi, ImageObserver.SOMEBITS, 0, 0, 1, 1)) {
+ throw new RuntimeException();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTabbedPane/4209065/bug4209065.html Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,35 @@
+<!--
+ Copyright (c) 1999, 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.
+
+ 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.
+-->
+
+<Html>
+<Body>
+<!--
+<H1>Test</H1>
+<Center>
+<APPLET code="bug4209065.class" WIDTH = 600 HEIGHT = 400>
+</APPLET>
+</Center>
+-->
+
+</Body>
+</Html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTabbedPane/4209065/bug4209065.java Wed Jan 28 08:14:18 2015 -0800
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999, 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.
+ *
+ * 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.
+ */
+
+import java.awt.EventQueue;
+import java.lang.reflect.InvocationTargetException;
+
+import javax.swing.JApplet;
+import javax.swing.JLabel;
+import javax.swing.JTabbedPane;
+
+/**
+ * @test
+ * @bug 4209065
+ * @author Georges Saab
+ * @run applet/manual=yesno bug4209065.html
+ */
+public final class bug4209065 extends JApplet {
+
+ @Override
+ public void init() {
+ try {
+ EventQueue.invokeAndWait(this::createTabbedPane);
+ } catch (InterruptedException | InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void createTabbedPane() {
+ JTabbedPane tp = new JTabbedPane();
+ getContentPane().add(tp);
+ String text = "<html><center>If the style of the text on the tabs matches"
+ + "<br>the descriptions, press <em><b>PASS</b></em></center></html>";
+ tp.addTab("<html><center><font size=+3>big</font></center></html>", new JLabel(text));
+ tp.addTab("<html><center><font color=red>red</font></center></html>", new JLabel(text));
+ tp.addTab("<html><center><em><b>Bold Italic!</b></em></center></html>", new JLabel(text));
+ }
+}