JDK-4258903 : Transferring text via DnD and Clipboard is too difficult
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.2.0,1.2.2,1.3.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS:
    generic,solaris_2.5.1,windows_95,windows_nt generic,solaris_2.5.1,windows_95,windows_nt
  • CPU: generic,x86
  • Submitted: 1999-08-02
  • Updated: 2000-11-29
  • Resolved: 2000-11-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.0 betaFixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Description
A Transferrable object MUST implement the plain-text data flavor or drop will fail mostly silently under windows (It DOES return to the DragSourceListener that the drop failed, but gives no indicationas  to why.)  This is probablyt due to a failure within the Windows OS drag and drop routines under these conditions,as the OS requires plain-text for drag-and-drop objects.

=====
This description is not true. See the evaluation for more details.
david.mendenhall@eng 2000-08-02

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin-beta FIXED IN: merlin-beta INTEGRATED IN: merlin-beta
14-06-2004

EVALUATION Not exactly. As of kestrel, the Transferable must support one of the following: Win95/98: text/plain;charset=ascii;class=java.io.InputStream WinNT/2000: text/plain;charset=unicode;class=java.io.InputStream text/plain;charset=ascii;class=java.io.InputStream Solaris/Linux: text/plain;charset=iso8859-1;class=java.io.InputStream text/plain;charset=unknown;class=java.io.InputStream test/plain;charset=X11-COMPOUND_TEXT;class=java.io.InputStream Several of these choices are poor. 'unicode' should be replaced with 'utf-16le'. 'unknown' and 'ascii' should be removed altogether. However, the real solution is to eliminate the 1-to-1 native-to-flavor and flavor-to-native mappings so that a Transferable need not support a whole bunch of DataFlavors in order to work across platforms. david.mendenhall@eng 2000-08-02 From dpm Mon Nov 13 10:44:00 2000 Date: Mon, 13 Nov 2000 10:44:00 -0800 (PST) From: David Mendenhall <dpm@jdc> Subject: 4258903 : Transferring text via DnD and Clipboard is too difficult To: jdk-change@eng, jck-ccc@eng Cc: awt-core@eng X-Mailer: dtmail 1.3.0 @(#)CDE Version 1.4 SunOS 5.8 sun4u sparc Mime-Version: 1.0 Content-Type: TEXT/plain; charset=us-ascii Content-MD5: HaajO9aRn8CQ7dIbUG5AEg== Content-Length: 26679 Release: merlin Problem: (BugID 4258903) Transferring text via DnD and Clipboard is too difficult Currently, the only way for an application to transfer text successfully is for that application's Transferables to support a set of DataFlavors which can be transformed into at least one native format on every platform for which the application will be deployed. However, because a native format can only have one unique DataFlavor mapped to it, it is very difficult, if not impossible, for an application to determine what that set is. The unique mappings vary across platforms, and are not part of the specification, even for JRE implementations for a particular platform. Developers could canvas the most popular JREs on their target platforms, but this is a wearisome process, and still does not provide true WORA. In addition, there is no technical reason why, if the JRE supports both the text flavor which the Transferable offers, and the target text format for the platform, that the data transfer subsystem could not do an implicit conversion between these two formats. If such implicit conversions were allowed, then developers' Transferables would only need to support one DataFlavor to achieve transferable text for all JREs on all platforms. We propose that the SDK adopt a set of APIs that will permit the implementation of such an implicit text conversion subsystem. Currently, the primary impediment to this implementation is the java.awt.datatransfer.FlavorMap interface, and its corresponding jre/lib/flavormap.properties file, both of which insist on a 1-to-1 mapping, in both directions, between native formats and DataFlavors. The relaxation of such a restriction would permit us to rewrite the SystemFlavorMap class so that it provides a rich set of synthetic DataFlavors, all of which map to the same native. Finally, applications need a way to register new flavor-to-native and native-to-flavor mappings at runtime. The current system allows specific site customizations of the JRE for new mappings, but this is inadequate for web-deployed applications. For example, if the web- deployed Java application 'Foo' is designed to interact with the native application 'Bar', it may need to transfer data in the native BAR format. 'Foo' understands the BAR format at the byte level, including endianness, and is willing to generate that byte stream without any help from the data transfer subsystem. Nevertheless, there is no way to tell the subsystem that, say, data in the flavor application/x-bar-data should pass through unaltered to the native system as BAR data. The SystemFlavorMap does support the registration of new natives, but these natives are tagged with a special prefix which prevents the native system from recognizing them. Thus, this registration process cannot be used between Java and native applications, but instead, only between Java applications in separate VMs. Requesters: Drag & Drop (David Mendenhall) Proposed API change: Summary: We have relaxed the 1-to-1 restriction of SystemFlavorMap by creating a new interface, ManyToManyFlavorMap, and implementing that interface in SystemFlavorMap. We have also changed the format of the flavormap.properties file to allow for duplicate native keys or duplicate DataFlavor values. For text natives, flavormap.properties now specifies the exact format of the byte stream which the native platform expects. In addition to the existing charset parameter, parameters were added for the end-of-line identifier and the number of terminating NUL bytes. After parsing and storing this information, the SystemFlavorMap then synthesizes an entire set of DataFlavors which map to the native: For all text/*, where * is any subtype except "plain": text/*; charset=Unicode; class=java.io.Reader text/*; charset=Unicode; class=java.lang.String text/*; charset=Unicode; class=[C And for each encoding supported by the JRE: text/*; charset=<encoding>; class=java.io.InputStream text/*; charset=<encoding>; class=[B Then, for all text/*, including text/plain: application/x-java-serialized-object; class=java.lang.String text/plain; charset=Unicode; class=java.io.Reader text/plain; charset=Unicode; class=java.lang.String text/plain; charset=Unicode; class=[C And for each encoding supported by the JRE: text/plain; charset=<encoding>; class=java.io.InputStream text/plain; charset=<encoding>; class=[B When the data transfer subsystem receives data in one of the synthetic DataFlavors, it will transform that data to the format specified in the flavormap.properties file. In order to support this change fully, Reader, String, [C, and [B needed to be elevated to the same order as InputStream for text flavors in the existing API. But since Reader, String, and [C are representations independent of charset -- "Unicode" is just a placeholder -- specifications which mentioned the charset parameter, such as DataFlavor.equals(DataFlavor) and DataFlavor.selectBestTextFlavor(DataFlavor[]), had to be revised as well. DataFlavor.isRepresentationClassReader and DataFlavor.isFlavorTextType were added mainly for completeness with respect to the existing API. Finally, four methods were added to SystemFlavorMap to permit the runtime registration by a specific application of new flavor-to-native and native-to-flavor mappings. These new methods do not append a prefix to the native String, so they can be used to establish communication between Java and native applications. Details: New interface java.awt.datatransfer.ManyToManyFlavorMap: /** * 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. ManyToManyFlavorMaps need not * be symmetric, but typically are. * * @author David Mendenhall * @version %I%, %G% * * @since 1.4 */ public interface ManyToManyFlavorMap 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. * * @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>ManyToManyFlavorMap</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 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. * * @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>ManyToManyFlavorMap</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 getFlavorsForNative(String nat); } Revised existing class java.awt.datatransfer.SystemFlavorMap: /** * 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. * * @version %I%, %G% * @since 1.2 */ public final class SystemFlavorMap implements FlavorMap, ManyToManyFlavorMap { /** * 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, 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 */ public List getNativesForFlavor(DataFlavor flav); /** * 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. * * @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 */ public List getFlavorsForNative(String nat); /** * Registers a mapping from a single <code>DataFlavor</code> to a single * <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>registerFlavorForUnencodedNative</code> as well. * * @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 #registerFlavorForUnencodedNative */ public void registerUnencodedNativeForFlavor(DataFlavor flav, String nat); /** * Discards the current mappings for 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>replaceFlavorsForNative</code> * as well. * <p> * It is recommended that client code not replace 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 nat the <code>String</code> native values for the mappings * @throws NullPointerException if flav or natives is <code>null</code> * * @see #replaceFlavorsForNative */ public void replaceNativesForFlavor(DataFlavor flav, String[] natives); /** * Registers 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>registerUnencodedNativeForFlavor</code> as well. * * @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 #registerUnencodedNativeForFlavor */ public void registerFlavorForUnencodedNative(String nat, DataFlavor flav); /** * 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-wa
11-06-2004

WORK AROUND Create a Transferable which supports both text/plain;charset=ascii;class=java.io.InputStream, and text/plain;charset=iso8859-1;class=java.io.InputStream. This will work on Win95/98/NT/2000, Solaris, and Linux. Unfortunately, this is not a satisfactory solution if you want to transfer non-ASCII text.
11-06-2004

EVALUATION y mappings, call * <code>replaceNativesForFlavor</code> as well. * <p> * It is recommended that client code not replace 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 flav the <code>DataFlavor</code> values for the mappings * @throws NullPointerException if nat or flavors is <code>null</code> * * @see #replaceNativesForFlavor */ public void replaceFlavorsForNative(String nat, DataFlavor[] flavors); } Revised existing class java.awt.datatransfer.DataFlavor: /** * 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: * "text/&lt;other&gt;", "text/plain", * "application/x-java-serialized-object", "text/calendar", "text/css", * "text/directory", "text/rfc822-header", "text/tab-separated-values", * "text/uri-list", "text/richtext", "text/enriched", "text/rtf", * "text/html", "text/xml", "text/sgml". 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, they will * then be sorted by their representation classes in the following order: * &lt;all others&gt;, <code>[C</code>, <code>java.lang.String</code>, * <code>java.io.Reader</code>. * <p> * If two or more flavors share the best representation class, and that * representation is one of the three explicitly listed, then one of those * flavors will be chosen non-deterministically. If, however, no flavor has * one of the three 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: * &lt;all others&gt;, <code>[B</code>, <code>java.io.InputStream</code>. * <p> * If two or more flavors share the best representation class, or if no * flavor has one of the two 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 availableFlavors is * null, has zero length, or contains no text flavors */ public static final DataFlavor selectBestTextFlavor( DataFlavor[] availableFlavors); /** * 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>[C</code>, <code>java.io.InputStream</code>, and <code>[B</code>. * * @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 five 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> 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 */ public Reader getReaderForText(Transferable transferable) throws UnsupportedFlavorException, IOException; /** * Tests an arbitrary <code>Object</code> to this <code>DataFlavor</code> * for equality. 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" and the * representation class is not <code>java.io.Reader</code>, * <code>java.lang.String</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. * * @param that 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 */ public boolean equals(Object o); /** * Tests a <code>DataFlavor</code> to this <code>DataFlavor</code> for * equality. 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" and the * representation class is not <code>java.io.Reader</code>, * <code>java.lang.String</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. * * @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 */ public boolean equals(DataFlavor that); /** * Tests a <code>DataFlavor</code> to this <code>DataFlavor</code> for * equality. 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" and the * representation class is not <code>java.io.Reader</code>, * <code>java.lang.String</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. * * @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 */ public boolean match(DataFlavor that); /** * Returns whether the representation class for this * <code>DataFlavor</code> is <code>java.io.Reader</code> or a subclass * thereof. */ public boolean isRepresentationClassReader(); /** * 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. If this * flavor's primary MIME type is "text", this flavor's representation must * be <code>java.io.Reader</code>, <code>java.lang.String</code>, * <code>[C</code>, <code>java.io.InputStream</code>, or <code>[B</code>. * If the representation is <code>java.io.InputStream</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. * * @return <code>true</code> if this <code>DataFlavor</code> is a valid * text flavor as described above; <code>false</code> otherwise */ public boolean isFlavorTextType(); Revised format for jre/lib/flavormap.properties: On Win32: # 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. On Solaris/Linux: # 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. Continuing, on all platforms: # These default mappings may be augmented by specifying the # # AWT.DnD.flavorMapFileURL # # property in the appropriate awt.properties file. The specified properties URL # will be loaded into the SystemFlavorMap. # # The standard format is: # # <native>=<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 ManyToManyFlavorMap, developers are free # to duplicate both native keys and DataFlavor values. # # Mappings whose values specify DataFlavors with primary MIME types of "text" # 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. # # If the "charset" parameter is omitted, the platform default encoding is # assumed. If the "eoln" parameter is omitted, "\n" is assumed. If the # "terminators" parameter is omitted, 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. API reviewed and approved by: Final API reviewed by Danila Sinopalnikov. Early design approval by Roger Brinkley (Sun) and Jens Alfke (Apple). The concepts, but not the design, of this API change were first approved by Mark Reinhold, Graham Hamilton, and Bill Shannon on 15 Nov 1999. Implementation: - Engineer who made (or will make) the changes: David Mendenhall - Date at which changes will be complete: 17 Nov 2000 - Number of lines of new or modified code: + Java: 300 new, 100 revised + Native: None. - Code reviewed (or will be reviewed) by: Danila Sinopalnikov Risk assessment: Low to moderate. We are changing a large part of the text data transfer subsystem, and there is always risk in making such a change. However, at this point, this code is well-understood, and we have a set of extensive test suites for locating and identifying regressions. SQE (product testing) impact: SQE has already committed to test development for this API change. This work is being done under umbrella RFE 4289847: Clipboard/DataTransfer/FlavorMap/SystemFlavorMap Fixes and Enhancements JCK (compatibility testing) impact: TBD Doc impact: javadoc changes only. Localization impact: None. Internationalization impact: Text transfer in international locales will be greatly simplified by this change. Security impact: None. Legal impact: None. david.mendenhall@east 2000-11-13 Approved with minor modifications on 21Nov2000. david.mendenhall@east 2000-11-27
13-11-2000