diff -r 0f955581dc0b src/share/classes/java/awt/datatransfer/DataFlavor.java
--- a/src/share/classes/java/awt/datatransfer/DataFlavor.java Mon Mar 24 06:33:16 2008 -0700
+++ b/src/share/classes/java/awt/datatransfer/DataFlavor.java Sat May 03 12:04:38 2008 +0200
@@ -217,8 +217,29 @@ public class DataFlavor implements Exter
* representation class of java.util.List
is used.
* Each element of the list is required/guaranteed to be of type
* java.io.File
.
+ *
+ * You should generally use javaURIListFlavor instead of this.
*/
public static final DataFlavor javaFileListFlavor = createConstant("application/x-java-file-list;class=java.util.List", null);
+
+ /**
+ * To transfer a list of files and/or URIs to/from Java (and
+ * the underlying platform) a DataFlavor
of this
+ * type/subtype and representation class of
+ * java.util.List
is used. Each element of this
+ * list is required/guaranteed to be of type
+ * java.net.URI
.
+ *
+ * You should use this flavor instead of javaFileListFlavor,
+ * because some platforms provide only URI lists, not file
+ * lists. On these platforms, if and only if all URIs are
+ * files for the transfer in question, you can use/get
+ * javaFileListFlavor in addition to this flavor, for
+ * backward compatibility.
+ *
+ * @since 1.7
+ */
+ public static final DataFlavor javaURIListFlavor = createConstant("application/x-java-uri-list;class=java.util.List", null);
/**
* To transfer a reference to an arbitrary Java object reference that
@@ -1227,6 +1248,20 @@ public class DataFlavor implements Exter
}
+ /**
+ * Returns true if the DataFlavor
specified represents
+ * a list of URI objects.
+ * @return true is the DataFlavor
specified represents
+ * a List of File objects
+ */
+
+ public boolean isFlavorJavaURIListType() {
+ if (mimeType == null || representationClass == null)
+ return false;
+ return java.util.List.class.isAssignableFrom(representationClass) &&
+ mimeType.match(javaURIListFlavor.mimeType);
+ }
+
/**
* Returns whether this DataFlavor
is a valid text flavor for
* this implementation of the Java platform. Only flavors equivalent to
diff -r 0f955581dc0b src/share/classes/sun/awt/datatransfer/DataTransferer.java
--- a/src/share/classes/sun/awt/datatransfer/DataTransferer.java Mon Mar 24 06:33:16 2008 -0700
+++ b/src/share/classes/sun/awt/datatransfer/DataTransferer.java Sat May 03 12:04:38 2008 +0200
@@ -50,6 +50,10 @@ import java.io.Reader;
import java.io.Reader;
import java.io.SequenceInputStream;
import java.io.StringReader;
+
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
@@ -616,6 +620,16 @@ public abstract class DataTransferer {
public abstract boolean isImageFormat(long format);
/**
+ * Determines whether the DataFlavor corresponding to the specified long
+ * format is DataFlavor.javaURIListFlavor.
+ */
+ public boolean isURIListFormat(long format)
+ {
+ // FIXME: make into an abstract method, with a Windows implementation?
+ return false;
+ }
+
+ /**
* Returns a Map whose keys are all of the possible formats into which the
* Transferable's transfer data flavors can be translated. The value of
* each key is the DataFlavor in which the Transferable's data should be
@@ -683,6 +697,7 @@ public abstract class DataTransferer {
// case of Serializable
if (flavor.isFlavorTextType() ||
flavor.isFlavorJavaFileListType() ||
+ flavor.isFlavorJavaURIListType() ||
DataFlavor.imageFlavor.equals(flavor) ||
flavor.isRepresentationClassSerializable() ||
flavor.isRepresentationClassInputStream() ||
@@ -786,6 +801,7 @@ public abstract class DataTransferer {
// case of Serializable
if (flavor.isFlavorTextType() ||
flavor.isFlavorJavaFileListType() ||
+ flavor.isFlavorJavaURIListType() ||
DataFlavor.imageFlavor.equals(flavor) ||
flavor.isRepresentationClassSerializable() ||
flavor.isRepresentationClassInputStream() ||
@@ -862,6 +878,7 @@ public abstract class DataTransferer {
// case of Serializable
if (flavor.isFlavorTextType() ||
flavor.isFlavorJavaFileListType() ||
+ flavor.isFlavorJavaURIListType() ||
DataFlavor.imageFlavor.equals(flavor) ||
flavor.isRepresentationClassSerializable() ||
flavor.isRepresentationClassInputStream() ||
@@ -948,7 +965,7 @@ public abstract class DataTransferer {
* clipboard string encoding/decoding, basing on clipboard
* format and localeTransferable(on decoding, if available)
*/
- private String getBestCharsetForTextFormat(Long lFormat,
+ protected String getBestCharsetForTextFormat(Long lFormat,
Transferable localeTransferable) throws IOException
{
String charset = null;
@@ -971,6 +988,68 @@ public abstract class DataTransferer {
charset = getDefaultTextCharset();
}
return charset;
+ }
+
+ /**
+ * Translate a transferable to a URI list. The default implementation
+ * provides a text/uri-list MIME type in the target encoding.
+ */
+ protected void translateTransferableToURIList(Object obj,
+ long format,
+ ByteArrayOutputStream outStream) throws IOException
+ {
+ String nat = getNativeForFormat(format);
+ String targetCharset = "UTF-8";
+ if (nat != null) {
+ try {
+ if ((targetCharset = new DataFlavor(nat).getParameter("charset")) == null)
+ targetCharset = "UTF-8";
+ } catch (ClassNotFoundException cnfe) {
+ throw new IOException(cnfe);
+ }
+ }
+ final List list = (List)obj;
+ int nItems = 0;
+ for (Object o : list) {
+ if (o instanceof String || o instanceof File ||
+ o instanceof URI)
+ nItems++;
+ }
+ final String[] items = new String[nItems];
+
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws IOException {
+ try {
+ int j = 0;
+ for (Object o : list) {
+ if (o instanceof URI) {
+ items[j++] = ((URI)o).toString();
+ } else if (o instanceof File) {
+ // Many implementations are fussy about the number of slashes
+ items[j++] = new URI("file:///" + ((File)o).getAbsolutePath()).toString();
+ } else if (o instanceof String) {
+ items[j++] = new URI((String)o).toString();
+ }
+ }
+ } catch (URISyntaxException uriSyntaxException) {
+ throw new IOException(uriSyntaxException);
+ }
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException pae) {
+ throw new IOException(pae.getMessage());
+ }
+
+ byte[] bytes = items[0].getBytes(targetCharset);
+ outStream.write(bytes, 0, bytes.length);
+ byte[] eoln = "\r\n".getBytes(targetCharset);
+ for (int i = 1; i < items.length; i++) {
+ outStream.write(eoln, 0, eoln.length);
+ bytes = items[i].getBytes(targetCharset);
+ outStream.write(bytes, 0, bytes.length);
+ }
}
/**
@@ -1279,18 +1358,37 @@ search:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ // Target data is a URI list. Source data must be a
+ // j.u.List of j.i.File, j.l.String, or j.n.URI objects.
+ if (isURIListFormat(format)) {
+ if (!DataFlavor.javaFileListFlavor.equals(flavor) &&
+ !DataFlavor.javaURIListFlavor.equals(flavor)) {
+ throw new IOException("data translation failed");
+ }
+ translateTransferableToURIList(obj, format, bos);
+
// Target data is a file list. Source data must be a
// java.util.List which contains java.io.File or String instances.
- if (isFileFormat(format)) {
+ } else if (isFileFormat(format)) {
if (!DataFlavor.javaFileListFlavor.equals(flavor)) {
throw new IOException("data translation failed");
}
final List list = (List)obj;
int nFiles = 0;
+ final String myHostname = InetAddress.getLocalHost().getHostName();
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
if (o instanceof File || o instanceof String) {
nFiles++;
+ } else if (o instanceof URI) {
+ URI uri = (URI) o;
+ if (uri.getScheme().equals("file")) {
+ String host = uri.getHost();
+ if (host == null || host.equals("localhost") ||
+ host.equals(myHostname)) {
+ nFiles++;
+ }
+ }
}
}
final String[] files = new String[nFiles];
@@ -1300,7 +1398,16 @@ search:
public Object run() throws IOException {
for (int i = 0, j = 0; i < list.size(); i++) {
Object o = list.get(i);
- if (o instanceof File) {
+ if (o instanceof URI) {
+ URI uri = (URI) o;
+ if (uri.getScheme().equals("file")) {
+ String host = uri.getHost();
+ if (host == null || host.equals("localhost") ||
+ host.equals(myHostname)) {
+ files[j++] = new File(uri.getPath()).getCanonicalPath();
+ }
+ }
+ } else if (o instanceof File) {
files[j++] = ((File)o).getCanonicalPath();
} else if (o instanceof String) {
files[j++] = (String)o;
@@ -1403,32 +1510,61 @@ search:
str = new ByteArrayInputStream(bytes);
}
+ // Source data is a URI list. Parse it into List