CONTENTS | PREV | NEXT | Drag and Drop |
In the case where a valid drop occurs, the DropTargetListener's drop() method is responsible for undertaking the transfer of the data associated with the gesture. The DropTargetDropEvent provides a means to obtain a Transferable object that represent that data object(s) to be transferred.From the drop() method, the DropTargetListener shall initially either rejectDrop() (immediately returning thereafter) or acceptDrop() specifying the selected operation from those returned by getSourceActions().
Subsequent to an acceptDrop(), but not before, getTransferable() may be invoked, and any data transfers performed via the returned Transferable's getTransferData() method. Finally, once the destination of the drop has completed the transfer(s) of the objects from the source it shall signal the success, or immediate failure, of the transfer(s) via an invocation of DropTargetContext.ropComplete().
Upon returning from the DropTargetContext.dropComplete() method the Transferable and DragSourceContext instances are no longer guaranteed to be valid and all references to them shall be discarded by the recipient to allow them to be subsequently garbage collected.
When using the ACTION_REFERENCE operation the source and destination should take care to agree upon the object and the associated semantics of the transfer. Typically in intra-JVM transfers a live object reference would be passed between source and destination, but in the case of inter-JVM transfers, or transfers between native and Java applications, live object references do not make sense, so some other `reference' type should be exchanged such as a URI for example. Both the DragSource and DropTarget can detect if the transfer is intra-JVM or not.
All the target DnD platforms represent their transfer data types using a similar mechanism, however the representations do differ. The Java platform uses MIME types encapsulated within a DataFlavor to represent its data types. Unfortunately in order to permit the transfer of data between Java and platform native applications the existence of these platform names need to be exposed, thus a mechanism is required in order to create an extensible (platform independent) mapping between these platform dependent type names, their representations, and the Java MIME based DataFlavors.The implementation will provide a mechanism to externally specify a mapping between platform native data types (strings) and MIME types (strings) used to construct DataFlavors. This external mapping will be used by the underlying platform specific implementation code in order to expose the appropriate DataFlavors (MIME types), exported by the source, to the destination, via the underlying platform DnD mechanisms.
Both the DragSource and DropTarget classes provide access for the underlying system to map platform dependent names to and from DataFlavors.
public interface java.awt.datatransfer.FlavorMap { java.util.Map getNativesForFlavors(DataFlavor[] dfs); java.util.Map getFlavorsForNatives(String[] natives); }
The getNativesForFlavors() method takes an array of DataFlavors and returns a Map object containing zero or more keys of type DataFlavor, from the actual parameter dfs, with associated values of type String, which correspond to the platform dependent type name for that MIME type.The getFlavorsForNatives() method takes an array of String types and returns a Map object containing zero or more keys of type String, from the actual parameter natives, with associated values of type DataFlavor, which correspond to the platform independent type for that platform dependent type name.
The Map object returned by both methods may be mutable but is not required to be.
If NULL is passed to either of these methods they should return their current map of all keys and values known to the implementation at the time of the call.
For example on Win32 the Clipboard Format Name for simple text is "CF_TEXT" (actually it is the integer 1) and on Motif it is the X11 Atom named "STRING", the MIME type one may use to represent this would be "text/plain charset=us-ascii". Therefore a platform portable FlavorMap would map between these names; CF_TEXT on win32 and STRING on Motif/X11.
Typically, as implemented in the SystemFlavorMap these mappings are held in an external persistent configuration format (a properties file or URL) and are loaded from the platform to configure the FlavorMap appropriately for a given platform.
The SystemFlavorMap class is provided to implement a simple, platform configurable mechanism for specifying a system-wide set of common mappings, and is defined as follows:
public class java.awt.datatransfer.SystemFlavorMap implements FlavorMap { public static FlavorMap getSystemFlavorMap(); public synchronized Map getNativesForFlavors(DataFlavor[] dfs); public synchronized Map getFlavorsForNatives(String[] natives); public static String encodeJavaMIMEType(DataFlavor df); public static String encodeJavaMimeType(java.util.mime.MimeType mime); public static boolean isEncodedJavaMimeType(String mimeStr); public static DataFlavor createFlavorFromEncodedJavaMimeType(String ejmts); public static java.util.mime.MimeType createMimeTypeFromEncodedJavaMimeType( String ejmts ); }
The SystemFlavorMap class provides a simple implementation, using a properties file (see java.awt.Properties), of a persistent platform FlavorMap. Using the value of the AWT property "AWT.flavorMapFileURL" (see Toolkit.getProperty()) or the default file location of System.getProperty("java.home") + File.separator + "lib" + File.separator + "flavormap.properties", this class creates the appropriate Maps from the properties found therein.In addition the class provides several static convenience functions used to encode and decode Java MimeTypes to and from a platform dependent namespace. The syntax of the properties file is:
{ <platform_type_name> `=' <IETF_MIME_RFC_conformant_specification> <nl> } *
The default implementations of DragSource and DropTarget return the SystemFlavorMap from their getFlavorMap() method, unless they have been provided with an overriding implementation.
Since one of the primary goals of this API is to allow Drag and Drop of data between Java and native applications this has some significant consequences upon the method and mechanism of the actual data encoding and exchange when data is passed across the boundary of the Java Virtual Machine.Since one of the participants in such an exchange may be a native application, and thus has no knowledge of the Java type system, the Drag and Drop system cannot just exchange a Java object reference since the other participant may have no knowledge of, or capability to manipulate such a type.
When any exchange occurs, it can only do so, regardless of the implementation of the participants, if and only if both participants are agreed upon a familiar data type and encoding. Thus, sadly the burden of the exchange is born mostly by the participants themselves.
What this means in practical terms is that for "native" data formats, such as platform dependent image, document, or other "Content-Types" the encoding and decoding of their associated external data format is the responsibility of the source and destination of the transfer.
The Drag and Drop system shall expose the external representation of such "native" data types across the boundary of the Java Virtual Machine as encapsulated within a java.io.InputStream or a subclass thereof.
This means that any DataFlavor with a representation class that extends java.io.InputStream can be transferred, and will be exposed for transfer, across the Java Virtual Machine boundary.
To implement the exchange of such a native data type, a developer would define a DataFlavor with a MIME "Content-Type" that describes the nature of the "native" data type, with a representation class that extends a java.io.InputStream class that encodes the data encapsulated into a stream of bytes.
In particular such InputStream subclasses shall implement the following semantics:
Provision of this constructor by a subclass of java.io.InputStream will allow the Drag and Drop system (associated with the DropTarget) to automatically re-construct an instance of the representation class specified by the requested DataFlavor, and initialize it with an InputStream containing the encapsulated data formatted according to the expectations of that subclass. Once initialized this instance is returned to the caller of the Transferable.getTransferData() method, thus allowing the caller to subsequently re-read and interpret the formatted content of the data stream transferred.
Provision of this method (or inheriting a superclasses implementation) enables the Drag and Drop system (associated with the DragSource) to automatically extract an encoded stream of the encapsulated data from the Transferable, thus enabling the transfer of the data across the JVM boundary as a simple byte stream to the requestor of the particular DataFlavor.
A typical subject of a Drag and Drop transfer is a list of one or more platform dependent filenames. In order to ease the programming task of developers either producing or consuming such lists the Drag and Drop system treats them as a special case.If a DataFlavor is specified with a MIME "Content-Type" of application/x-java-file-list;class=java.util.List the Drag and Drop system will expect the list elements to be a homogeneous list of objects of type java.io.File. Thus a source shall, if supporting the transfer of a list of files, construct such a List of File objects when such a DataFlavor is requested, and a recipient shall expect such a List of File objects if it requests such a valid DataFlavor from it's source. This special case provides a simple mechanism for the transfer of lists of files between source and target.
It is possible to Drag and Drop object references between JVMs' by using the facilities of the RMI mechanism. The Drag and Drop system will automatically arrange for the transfer of any object reference that adheres to these requirements:
(the MIME "Content-Type" can be any suitable, arbitrary type or application/x-java-remote-object)(effectively the object implementation class transferred should be extended from java.rmi.server.UnicastRemoteObject since the RMI system implements some required initialization, without which the transfer will not complete properly).
If these conditions are met, then if an appropriate DataFlavor is requested, then the object returned to the requestor (if it is in a difference JVM from the source) will be an RMI reference to an instance of the Remote object subinterface specified as the representation class of the DataFlavor.