提交 ccedcb80 编写于 作者: D denis

7075105: WIN: Provide a way to format HTML on drop

Reviewed-by: uta, serb
上级 33efe959
...@@ -174,7 +174,7 @@ public class CDataTransferer extends DataTransferer { ...@@ -174,7 +174,7 @@ public class CDataTransferer extends DataTransferer {
bytes = Normalizer.normalize(new String(bytes, "UTF8"), Form.NFC).getBytes("UTF8"); bytes = Normalizer.normalize(new String(bytes, "UTF8"), Form.NFC).getBytes("UTF8");
} }
return super.translateBytesOrStream(stream, bytes, flavor, format, transferable); return super.translateBytes(bytes, flavor, format, transferable);
} }
...@@ -257,16 +257,13 @@ public class CDataTransferer extends DataTransferer { ...@@ -257,16 +257,13 @@ public class CDataTransferer extends DataTransferer {
private native byte[] imageDataToPlatformImageBytes(int[] rData, int nW, int nH); private native byte[] imageDataToPlatformImageBytes(int[] rData, int nW, int nH);
/** /**
* Translates either a byte array or an input stream which contain * Translates a byte array which contains
* platform-specific image data in the given format into an Image. * platform-specific image data in the given format into an Image.
*/ */
protected Image platformImageBytesOrStreamToImage(InputStream stream, byte[] bytes, long format) throws IOException { protected Image platformImageBytesToImage(byte[] bytes, long format)
byte[] imageData = bytes; throws IOException
{
if (imageData == null) return getImageForByteStream(bytes);
imageData = inputStreamToByteArray(stream);
return getImageForByteStream(imageData);
} }
private native Image getImageForByteStream(byte[] bytes); private native Image getImageForByteStream(byte[] bytes);
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
package java.awt.datatransfer; package java.awt.datatransfer;
import java.awt.Toolkit;
import java.io.*; import java.io.*;
import java.nio.*; import java.nio.*;
import java.util.*; import java.util.*;
...@@ -162,6 +161,18 @@ public class DataFlavor implements Externalizable, Cloneable { ...@@ -162,6 +161,18 @@ public class DataFlavor implements Externalizable, Cloneable {
} }
} }
/*
* 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, * The <code>DataFlavor</code> representing a Java Unicode String class,
* where: * where:
...@@ -245,6 +256,46 @@ public class DataFlavor implements Externalizable, Cloneable { ...@@ -245,6 +256,46 @@ public class DataFlavor implements Externalizable, Cloneable {
*/ */
public static final String javaRemoteObjectMimeType = "application/x-java-remote-object"; 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 * Constructs a new <code>DataFlavor</code>. This constructor is
* provided only for the purpose of supporting the * provided only for the purpose of supporting the
...@@ -949,24 +1000,35 @@ public class DataFlavor implements Externalizable, Cloneable { ...@@ -949,24 +1000,35 @@ public class DataFlavor implements Externalizable, Cloneable {
return false; return false;
} }
if ("text".equals(getPrimaryType()) && if ("text".equals(getPrimaryType())) {
DataTransferer.doesSubtypeSupportCharset(this) && if (DataTransferer.doesSubtypeSupportCharset(this) &&
representationClass != null && representationClass != null &&
!(isRepresentationClassReader() || !(isRepresentationClassReader() ||
String.class.equals(representationClass) || String.class.equals(representationClass) ||
isRepresentationClassCharBuffer() || isRepresentationClassCharBuffer() ||
DataTransferer.charArrayClass.equals(representationClass))) DataTransferer.charArrayClass.equals(representationClass)))
{ {
String thisCharset = String thisCharset =
DataTransferer.canonicalName(getParameter("charset")); DataTransferer.canonicalName(getParameter("charset"));
String thatCharset = String thatCharset =
DataTransferer.canonicalName(that.getParameter("charset")); DataTransferer.canonicalName(that.getParameter("charset"));
if (thisCharset == null) { if (thisCharset == null) {
if (thatCharset != null) { if (thatCharset != null) {
return false; return false;
}
} else {
if (!thisCharset.equals(thatCharset)) {
return false;
}
} }
} else { }
if (!thisCharset.equals(thatCharset)) {
if ("html".equals(getSubType()) &&
this.getParameter("document") != null )
{
if (!this.getParameter("document").
equals(that.getParameter("document")))
{
return false; return false;
} }
} }
......
...@@ -41,7 +41,7 @@ import java.util.ArrayList; ...@@ -41,7 +41,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -100,6 +100,11 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { ...@@ -100,6 +100,11 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
*/ */
private static final String TEXT_PLAIN_BASE_TYPE = "text/plain"; 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";
/** /**
* This constant is passed to flavorToNativeLookup() to indicate that a * This constant is passed to flavorToNativeLookup() to indicate that a
* a native should be synthesized, stored, and returned by encoding the * a native should be synthesized, stored, and returned by encoding the
...@@ -113,7 +118,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { ...@@ -113,7 +118,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
* text DataFlavors). * text DataFlavors).
* Do not use the field directly, use getNativeToFlavor() instead. * Do not use the field directly, use getNativeToFlavor() instead.
*/ */
private Map nativeToFlavor = new HashMap(); private final Map<String, List<DataFlavor>> nativeToFlavor = new HashMap<>();
/** /**
* Accessor to nativeToFlavor map. Since we use lazy initialization we must * Accessor to nativeToFlavor map. Since we use lazy initialization we must
...@@ -122,7 +127,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { ...@@ -122,7 +127,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
* *
* @return nativeToFlavor * @return nativeToFlavor
*/ */
private Map getNativeToFlavor() { private Map<String, List<DataFlavor>> getNativeToFlavor() {
if (!isMapInitialized) { if (!isMapInitialized) {
initSystemFlavorMap(); initSystemFlavorMap();
} }
...@@ -134,7 +139,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { ...@@ -134,7 +139,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
* native Strings. * native Strings.
* Do not use the field directly, use getFlavorToNative() instead. * Do not use the field directly, use getFlavorToNative() instead.
*/ */
private Map flavorToNative = new HashMap(); private final Map flavorToNative = new HashMap();
/** /**
* Accessor to flavorToNative map. Since we use lazy initialization we must * Accessor to flavorToNative map. Since we use lazy initialization we must
...@@ -421,14 +426,17 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { ...@@ -421,14 +426,17 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
} }
} }
// For text/* flavors, store mappings in separate maps to final LinkedHashSet<DataFlavor> dfs = new LinkedHashSet<>();
// enable dynamic mapping generation at a run-time.
dfs.add(flavor);
if ("text".equals(flavor.getPrimaryType())) { if ("text".equals(flavor.getPrimaryType())) {
store(value, key, getFlavorToNative()); dfs.addAll(convertMimeTypeToDataFlavors(value));
store(key, value, getNativeToFlavor()); }
} else {
store(flavor, key, getFlavorToNative()); for (DataFlavor df : dfs) {
store(key, flavor, getNativeToFlavor()); store(df, key, getFlavorToNative());
store(key, df, getNativeToFlavor());
} }
} }
} }
...@@ -530,7 +538,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { ...@@ -530,7 +538,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
* only if the specified native is encoded as a Java MIME type. * only if the specified native is encoded as a Java MIME type.
*/ */
private List nativeToFlavorLookup(String nat) { private List nativeToFlavorLookup(String nat) {
List flavors = (List)getNativeToFlavor().get(nat); List<DataFlavor> flavors = getNativeToFlavor().get(nat);
if (nat != null && !disabledMappingGenerationKeys.contains(nat)) { if (nat != null && !disabledMappingGenerationKeys.contains(nat)) {
DataTransferer transferer = DataTransferer.getInstance(); DataTransferer transferer = DataTransferer.getInstance();
...@@ -625,7 +633,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { ...@@ -625,7 +633,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
getNativesForFlavorCache.remove(flav); getNativesForFlavorCache.remove(flav);
getNativesForFlavorCache.remove(null); getNativesForFlavorCache.remove(null);
List flavors = (List)getNativeToFlavor().get(encoded); List<DataFlavor> flavors = getNativeToFlavor().get(encoded);
if (flavors == null) { if (flavors == null) {
flavors = new ArrayList(1); flavors = new ArrayList(1);
getNativeToFlavor().put(encoded, flavors); getNativeToFlavor().put(encoded, flavors);
...@@ -681,7 +689,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { ...@@ -681,7 +689,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
} }
if (flav == null) { if (flav == null) {
retval = new ArrayList(getNativeToFlavor().keySet()); retval = new ArrayList<String>(getNativeToFlavor().keySet());
} else if (disabledMappingGenerationKeys.contains(flav)) { } else if (disabledMappingGenerationKeys.contains(flav)) {
// In this case we shouldn't synthesize a native for this flavor, // In this case we shouldn't synthesize a native for this flavor,
// since its mappings were explicitly specified. // since its mappings were explicitly specified.
...@@ -809,140 +817,162 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { ...@@ -809,140 +817,162 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable {
} }
} }
LinkedList retval = new LinkedList(); final LinkedHashSet <DataFlavor> returnValue =
new LinkedHashSet<>();
if (nat == null) { if (nat == null) {
List natives = getNativesForFlavor(null); final List<String> natives = getNativesForFlavor(null);
HashSet dups = new HashSet(natives.size());
for (Iterator natives_iter = natives.iterator(); for (String n : natives)
natives_iter.hasNext(); )
{ {
List flavors = final List<DataFlavor> flavors = getFlavorsForNative(n);
getFlavorsForNative((String)natives_iter.next());
for (Iterator flavors_iter = flavors.iterator(); for (DataFlavor df : flavors)
flavors_iter.hasNext(); )
{ {
Object flavor = flavors_iter.next(); returnValue.add(df);
if (dups.add(flavor)) {
retval.add(flavor);
}
} }
} }
} else { } else {
List flavors = nativeToFlavorLookup(nat);
final List<DataFlavor> flavors = nativeToFlavorLookup(nat);
if (disabledMappingGenerationKeys.contains(nat)) { if (disabledMappingGenerationKeys.contains(nat)) {
return flavors; return flavors;
} }
HashSet dups = new HashSet(flavors.size()); final List<DataFlavor> flavorsAndBaseTypes =
nativeToFlavorLookup(nat);
List flavorsAndbaseTypes = nativeToFlavorLookup(nat); for (DataFlavor df : flavorsAndBaseTypes) {
returnValue.add(df);
if ("text".equals(df.getPrimaryType())) {
try {
returnValue.addAll(
convertMimeTypeToDataFlavors(
new MimeType(df.getMimeType()
).getBaseType()));
} catch (MimeTypeParseException e) {
e.printStackTrace();
}
}
}
for (Iterator flavorsAndbaseTypes_iter = }
flavorsAndbaseTypes.iterator();
flavorsAndbaseTypes_iter.hasNext(); ) final ArrayList arrayList = new ArrayList(returnValue);
getFlavorsForNativeCache.put(nat, new SoftReference(arrayList));
return (List)arrayList.clone();
}
private static LinkedHashSet<DataFlavor> convertMimeTypeToDataFlavors(
final String baseType) {
final LinkedHashSet<DataFlavor> returnValue =
new LinkedHashSet<DataFlavor>();
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.
assert(false);
}
if (DataTransferer.doesSubtypeSupportCharset(subType, null)) {
if (TEXT_PLAIN_BASE_TYPE.equals(baseType))
{ {
Object value = flavorsAndbaseTypes_iter.next(); returnValue.add(DataFlavor.stringFlavor);
if (value instanceof String) { }
String baseType = (String)value;
String subType = null; 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 { try {
MimeType mimeType = new MimeType(baseType); toAdd = new DataFlavor(mt);
subType = mimeType.getSubType(); } catch (ClassNotFoundException cannotHappen) {
} catch (MimeTypeParseException mtpe) {
// Cannot happen, since we checked all mappings
// on load from flavormap.properties.
assert(false);
} }
if (DataTransferer.doesSubtypeSupportCharset(subType, returnValue.add(toAdd);
null)) { }
if (TEXT_PLAIN_BASE_TYPE.equals(baseType) && }
dups.add(DataFlavor.stringFlavor))
{
retval.add(DataFlavor.stringFlavor);
}
for (int i = 0; i < UNICODE_TEXT_CLASSES.length; i++) {
DataFlavor toAdd = null;
try {
toAdd = new DataFlavor
(baseType + ";charset=Unicode;class=" +
UNICODE_TEXT_CLASSES[i]);
} catch (ClassNotFoundException cannotHappen) {
}
if (dups.add(toAdd)) {
retval.add(toAdd);
}
}
for (Iterator charset_iter = for (String charset : DataTransferer.standardEncodings()) {
DataTransferer.standardEncodings();
charset_iter.hasNext(); )
{
String charset = (String)charset_iter.next();
for (int i = 0; i < ENCODED_TEXT_CLASSES.length; for (String encodedTextClass : ENCODED_TEXT_CLASSES) {
i++) final String mimeType =
{ baseType + ";charset=" + charset +
DataFlavor toAdd = null; ";class=" + encodedTextClass;
try {
toAdd = new DataFlavor
(baseType + ";charset=" + charset +
";class=" + ENCODED_TEXT_CLASSES[i]);
} catch (ClassNotFoundException cannotHappen) {
}
// Check for equality to plainTextFlavor so final LinkedHashSet<String> mimeTypes =
// that we can ensure that the exact charset of handleHtmlMimeTypes(baseType, mimeType);
// plainTextFlavor, not the canonical charset
// or another equivalent charset with a
// different name, is used.
if (toAdd.equals(DataFlavor.plainTextFlavor)) {
toAdd = DataFlavor.plainTextFlavor;
}
if (dups.add(toAdd)) { for (String mt : mimeTypes) {
retval.add(toAdd);
}
}
}
if (TEXT_PLAIN_BASE_TYPE.equals(baseType) && DataFlavor df = null;
dups.add(DataFlavor.plainTextFlavor))
{
retval.add(DataFlavor.plainTextFlavor);
}
} else {
// Non-charset text natives should be treated as
// opaque, 8-bit data in any of its various
// representations.
for (int i = 0; i < ENCODED_TEXT_CLASSES.length; i++) {
DataFlavor toAdd = null;
try {
toAdd = new DataFlavor(baseType +
";class=" + ENCODED_TEXT_CLASSES[i]);
} catch (ClassNotFoundException cannotHappen) {
}
if (dups.add(toAdd)) { try {
retval.add(toAdd); 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) {
} }
}
} else { returnValue.add(df);
DataFlavor flavor = (DataFlavor)value;
if (dups.add(flavor)) {
retval.add(flavor);
} }
} }
} }
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;
}
ArrayList arrayList = new ArrayList(retval); private static final String [] htmlDocumntTypes =
getFlavorsForNativeCache.put(nat, new SoftReference(arrayList)); new String [] {"all", "selection", "fragment"};
return (List)arrayList.clone();
private static LinkedHashSet<String> handleHtmlMimeTypes(
String baseType, String mimeType) {
LinkedHashSet<String> returnValues = new LinkedHashSet<>();
if (HTML_TEXT_BASE_TYPE.equals(baseType)) {
for (String documentType : htmlDocumntTypes) {
returnValues.add(mimeType + ";document=" + documentType);
}
} else {
returnValues.add(mimeType);
}
return returnValues;
} }
/** /**
......
...@@ -57,7 +57,6 @@ import sun.awt.AppContext; ...@@ -57,7 +57,6 @@ import sun.awt.AppContext;
import sun.awt.SunToolkit; import sun.awt.SunToolkit;
import sun.awt.datatransfer.DataTransferer; import sun.awt.datatransfer.DataTransferer;
import sun.awt.datatransfer.ToolkitThreadBlockedHandler; import sun.awt.datatransfer.ToolkitThreadBlockedHandler;
import sun.security.util.SecurityConstants;
/** /**
* <p> * <p>
...@@ -260,6 +259,7 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, ...@@ -260,6 +259,7 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer,
} }
final long format = lFormat.longValue(); final long format = lFormat.longValue();
Object ret = getNativeData(format); Object ret = getNativeData(format);
if (ret instanceof byte[]) { if (ret instanceof byte[]) {
...@@ -270,11 +270,14 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, ...@@ -270,11 +270,14 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer,
throw new InvalidDnDOperationException(e.getMessage()); throw new InvalidDnDOperationException(e.getMessage());
} }
} else if (ret instanceof InputStream) { } else if (ret instanceof InputStream) {
InputStream inputStream = (InputStream)ret;
try { try {
return DataTransferer.getInstance(). return DataTransferer.getInstance().
translateStream((InputStream)ret, df, format, this); translateStream(inputStream, df, format, this);
} catch (IOException e) { } catch (IOException e) {
throw new InvalidDnDOperationException(e.getMessage()); throw new InvalidDnDOperationException(e.getMessage());
} finally {
inputStream.close();
} }
} else { } else {
throw new IOException("no native data was transfered"); throw new IOException("no native data was transfered");
......
...@@ -212,10 +212,9 @@ public class XDataTransferer extends DataTransferer { ...@@ -212,10 +212,9 @@ public class XDataTransferer extends DataTransferer {
* Translates either a byte array or an input stream which contain * Translates either a byte array or an input stream which contain
* platform-specific image data in the given format into an Image. * platform-specific image data in the given format into an Image.
*/ */
protected Image platformImageBytesOrStreamToImage(InputStream inputStream, protected Image platformImageBytesToImage(
byte[] bytes, byte[] bytes, long format) throws IOException
long format) {
throws IOException {
String mimeType = null; String mimeType = null;
if (format == PNG_ATOM.getAtom()) { if (format == PNG_ATOM.getAtom()) {
mimeType = "image/png"; mimeType = "image/png";
...@@ -235,7 +234,7 @@ public class XDataTransferer extends DataTransferer { ...@@ -235,7 +234,7 @@ public class XDataTransferer extends DataTransferer {
} }
} }
if (mimeType != null) { if (mimeType != null) {
return standardImageBytesOrStreamToImage(inputStream, bytes, mimeType); return standardImageBytesToImage(bytes, mimeType);
} else { } else {
String nativeFormat = getNativeForFormat(format); String nativeFormat = getNativeForFormat(format);
throw new IOException("Translation from " + nativeFormat + throw new IOException("Translation from " + nativeFormat +
...@@ -330,8 +329,8 @@ public class XDataTransferer extends DataTransferer { ...@@ -330,8 +329,8 @@ public class XDataTransferer extends DataTransferer {
* a valid MIME and return a list of flavors to which the data in this MIME * a valid MIME and return a list of flavors to which the data in this MIME
* type can be translated by the Data Transfer subsystem. * type can be translated by the Data Transfer subsystem.
*/ */
public List getPlatformMappingsForNative(String nat) { public List <DataFlavor> getPlatformMappingsForNative(String nat) {
List flavors = new ArrayList(); List <DataFlavor> flavors = new ArrayList();
if (nat == null) { if (nat == null) {
return flavors; return flavors;
...@@ -346,16 +345,14 @@ public class XDataTransferer extends DataTransferer { ...@@ -346,16 +345,14 @@ public class XDataTransferer extends DataTransferer {
return flavors; return flavors;
} }
Object value = df; DataFlavor value = df;
final String primaryType = df.getPrimaryType(); final String primaryType = df.getPrimaryType();
final String baseType = primaryType + "/" + df.getSubType(); final String baseType = primaryType + "/" + df.getSubType();
// For text formats we map natives to MIME strings instead of data // For text formats we map natives to MIME strings instead of data
// flavors to enable dynamic text native-to-flavor mapping generation. // flavors to enable dynamic text native-to-flavor mapping generation.
// See SystemFlavorMap.getFlavorsForNative() for details. // See SystemFlavorMap.getFlavorsForNative() for details.
if ("text".equals(primaryType)) { if ("image".equals(primaryType)) {
value = primaryType + "/" + df.getSubType();
} else if ("image".equals(primaryType)) {
Iterator readers = ImageIO.getImageReadersByMIMEType(baseType); Iterator readers = ImageIO.getImageReadersByMIMEType(baseType);
if (readers.hasNext()) { if (readers.hasNext()) {
flavors.add(DataFlavor.imageFlavor); flavors.add(DataFlavor.imageFlavor);
...@@ -438,16 +435,13 @@ public class XDataTransferer extends DataTransferer { ...@@ -438,16 +435,13 @@ public class XDataTransferer extends DataTransferer {
} }
} }
} else if (DataTransferer.isFlavorCharsetTextType(df)) { } else if (DataTransferer.isFlavorCharsetTextType(df)) {
final Iterator iter = DataTransferer.standardEncodings();
// stringFlavor is semantically equivalent to the standard // stringFlavor is semantically equivalent to the standard
// "text/plain" MIME type. // "text/plain" MIME type.
if (DataFlavor.stringFlavor.equals(df)) { if (DataFlavor.stringFlavor.equals(df)) {
baseType = "text/plain"; baseType = "text/plain";
} }
while (iter.hasNext()) { for (String encoding : DataTransferer.standardEncodings()) {
String encoding = (String)iter.next();
if (!encoding.equals(charset)) { if (!encoding.equals(charset)) {
natives.add(baseType + ";charset=" + encoding); natives.add(baseType + ";charset=" + encoding);
} }
......
/*
* Copyright (c) 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.
*
* 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 7075105
@summary WIN: Provide a way to format HTML on drop
@author Denis Fokin: area=datatransfer
@build HtmlTransferable PutAllHtmlFlavorsOnClipboard
@build PutOnlyAllHtmlFlavorOnClipboard PutSelectionAndFragmentHtmlFlavorsOnClipboard
@run main HTMLDataFlavorTest
*/
import java.awt.*;
import java.awt.datatransfer.*;
import java.io.*;
import java.util.HashMap;
public class HTMLDataFlavorTest {
private static HashMap<DataFlavor, String> dataFlavors = new HashMap<DataFlavor, String>();
public static void main(String[] args) throws IOException, UnsupportedFlavorException {
dataFlavors.put(DataFlavor.allHtmlFlavor, HtmlTransferable.ALL_HTML_AS_STRING);
dataFlavors.put(DataFlavor.fragmentHtmlFlavor, HtmlTransferable.FRAGMENT_HTML_AS_STRING);
dataFlavors.put(DataFlavor.selectionHtmlFlavor, HtmlTransferable.SELECTION_HTML_AS_STRING);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
resetClipboardContent(clipboard);
// 1. Put all three html flavors on clipboard.
// Get the data within the same JVM
// Expect that the resulted html is the selection
// wrapped in all three types
clipboard.setContents(new HtmlTransferable(HtmlTransferable.htmlDataFlavors),null);
// Test local transfer
testClipboardContent(clipboard, HtmlTransferable.htmlDataFlavors);
resetClipboardContent(clipboard);
// 2. Put only DataFlavor.allHtmlFlavor on clipboard.
// Expect that the resulted html is the all
// wrapped in all three types
putHtmlInAnotherProcess("PutOnlyAllHtmlFlavorOnClipboard");
for (DataFlavor df : HtmlTransferable.htmlDataFlavors) {
if (!clipboard.isDataFlavorAvailable(df)) {
throw new RuntimeException("The data should be available.");
}
}
if (!clipboard.getData(DataFlavor.allHtmlFlavor).toString().
equals(dataFlavors.get(DataFlavor.allHtmlFlavor).toString()))
{
throw new RuntimeException("DataFlavor.allHtmlFlavor data " +
"should be identical to the data put on the source side.");
}
resetClipboardContent(clipboard);
// 3. Put all three html flavors on clipboard.
// Expect that the resulted html is the selection
// wrapped in all three types
putHtmlInAnotherProcess("PutAllHtmlFlavorsOnClipboard");
for (DataFlavor df : HtmlTransferable.htmlDataFlavors) {
if (!clipboard.isDataFlavorAvailable(df)) {
throw new RuntimeException("The data should be available.");
}
}
if (!clipboard.getData(DataFlavor.selectionHtmlFlavor).toString().
equals(dataFlavors.get(DataFlavor.selectionHtmlFlavor)))
{
throw new RuntimeException("DataFlavor.allHtmlFlavor data " +
"should be identical to the data put on the source side.");
}
}
private static void resetClipboardContent(Clipboard clipboard) {
clipboard.setContents(
new StringSelection("The data is used to empty the clipboard content"
),null);
}
private static void putHtmlInAnotherProcess(String putterCommand) {
try {
String command = System.getProperty("java.home") + "/bin/java -cp " +
System.getProperty("test.classes", ".") + " " +
putterCommand;
System.out.println("Execute process : " + command);
Process p = Runtime.getRuntime().exec(command);
try {
p.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("The data has been set remotely");
try (BufferedReader stdstr = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String s;
while ((s = stdstr.readLine()) != null) {
s = stdstr.readLine();
System.out.println(s);
}
}
try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()))) {
String s;
while ((s = br.readLine()) != null) {
s = br.readLine();
System.err.println(s);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void testClipboardContent(Clipboard clipboard,
DataFlavor [] expectedDataFlavors)
throws UnsupportedFlavorException, IOException {
for (DataFlavor df : clipboard.getAvailableDataFlavors()) {
System.out.println("available df: " + df.getMimeType());
}
for (DataFlavor df : expectedDataFlavors) {
if (!clipboard.isDataFlavorAvailable(df)) {
throw new RuntimeException("The data should be available.");
}
System.out.println("Checking \"" + df.getParameter("document") + "\" for correspondence");
if (!dataFlavors.get(df).toString().equals(clipboard.getData(df).toString())) {
System.err.println("Expected data: " + dataFlavors.get(df).toString());
System.err.println("Actual data: " + clipboard.getData(df).toString());
throw new RuntimeException("An html flavor with parameter \"" +
df.getParameter("document") + "\" does not correspond to the transferred data.");
}
}
}
}
/*
* Copyright (c) 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.
*
* 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.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
/**
* A transferable that mimic ie html data
*/
class HtmlTransferable implements Transferable {
final static String SOURCE_HTML = "<html><head><title>Simple html content</title></head>" +
"<body><ol><li>Dasha</li><li>Masha</li><li>Lida</li></ol></body></html>";
// Data identical to ie output for the next html without end of lines,
// that is gotten by java system clipboard
// <html>
// <head>
// <title>Simple html content</title>
// </head>
// <body>
// <ol>
// <li>Dasha</li>
// <li>Masha</li>
// <li>Lida</li>
// </ol>
// </body>
// </html>
final static String ALL_HTML_AS_STRING = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n" +
"\n" +
"<HTML><HEAD><TITLE>Simple html content</TITLE></HEAD>\n" +
"\n" +
"<BODY>\n" +
"\n" +
"<OL><!--StartFragment--><LI>Masha\n" +
"<LI>Lida</LI><!--EndFragment--></OL>\n" +
"</BODY>\n" +
"</HTML>";
final static String FRAGMENT_HTML_AS_STRING = "<LI>Masha\n" +
"<LI>Lida</LI>";
final static String SELECTION_HTML_AS_STRING = "<LI>Masha" +
"<LI>Lida</LI>";
private DataFlavor[] supportedDataFlavors;
final static DataFlavor[] htmlDataFlavors = new DataFlavor [] {
DataFlavor.allHtmlFlavor,
DataFlavor.fragmentHtmlFlavor,
DataFlavor.selectionHtmlFlavor
};
@Override
public DataFlavor[] getTransferDataFlavors() {
return supportedDataFlavors;
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
for (DataFlavor supportedDataFlavor : supportedDataFlavors) {
if (supportedDataFlavor.equals(flavor)) {
return true;
}
}
return false;
}
HtmlTransferable(DataFlavor[] supportedDataFlavors) {
this.supportedDataFlavors = supportedDataFlavors;
}
@Override
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
if (isDataFlavorSupported(flavor)) {
if (flavor.equals(DataFlavor.allHtmlFlavor)) {
return ALL_HTML_AS_STRING;
} else if (flavor.equals(DataFlavor.fragmentHtmlFlavor)) {
return FRAGMENT_HTML_AS_STRING;
} else if (flavor.equals(DataFlavor.selectionHtmlFlavor)) {
return SELECTION_HTML_AS_STRING;
}
}
throw new UnsupportedFlavorException(flavor);
}
}
<html>
<!--
@test
@bug 7075105
@summary WIN: Provide a way to format HTML on drop
@author Denis Fokin area=datatransfer
@run applet/manual=yesno ManualHTMLDataFlavorTest.html
-->
<head>
<title>ManualHTMLDataFlavorTest</title>
</head>
<body>
<h1>ManualHTMLDataFlavorTest<br>Bug ID: 7075105</h1>
<p> See the dialog box (usually in upper left corner) for instructions</p>
<APPLET CODE="ManualHTMLDataFlavorTest.class" WIDTH=200 HEIGHT=200></APPLET>
</body>
</html>
/*
* Copyright (c) 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.
*
* 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 7075105
@summary WIN: Provide a way to format HTML on drop
@author Denis Fokin: area=datatransfer
@run applet/manual=yesno ManualHTMLDataFlavorTest
*/
import java.applet.Applet;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.*;
import java.io.IOException;
public class ManualHTMLDataFlavorTest extends Applet {
class DropPane extends Panel implements DropTargetListener {
DropPane() {
requestFocus();
setBackground(Color.red);
setDropTarget(new DropTarget(this, DnDConstants.ACTION_COPY, this));
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200,200);
}
@Override
public void dragEnter(DropTargetDragEvent dtde) {
dtde.acceptDrag(DnDConstants.ACTION_COPY);
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
dtde.acceptDrag(DnDConstants.ACTION_COPY);
}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {
dtde.acceptDrag(DnDConstants.ACTION_COPY);
}
@Override
public void dragExit(DropTargetEvent dte) {}
@Override
public void drop(DropTargetDropEvent dtde) {
if (!dtde.isDataFlavorSupported(DataFlavor.allHtmlFlavor)) {
Sysout.println("DataFlavor.allHtmlFlavor is not present in the system clipboard");
dtde.rejectDrop();
return;
} else if (!dtde.isDataFlavorSupported(DataFlavor.fragmentHtmlFlavor)) {
Sysout.println("DataFlavor.fragmentHtmlFlavor is not present in the system clipboard");
dtde.rejectDrop();
return;
} else if (!dtde.isDataFlavorSupported(DataFlavor.selectionHtmlFlavor)) {
Sysout.println("DataFlavor.selectionHtmlFlavor is not present in the system clipboard");
dtde.rejectDrop();
return;
}
dtde.acceptDrop(DnDConstants.ACTION_COPY);
Transferable t = dtde.getTransferable();
try {
Sysout.println("ALL:");
Sysout.println(t.getTransferData(DataFlavor.allHtmlFlavor).toString());
Sysout.println("FRAGMENT:");
Sysout.println(t.getTransferData(DataFlavor.fragmentHtmlFlavor).toString());
Sysout.println("SELECTION:");
Sysout.println(t.getTransferData(DataFlavor.selectionHtmlFlavor).toString());
} catch (UnsupportedFlavorException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void init() {
String[] instructions =
{
"1) The test contains a drop-aware panel with a red background",
"2) Open some page in a browser, select some text",
" Drag and drop it on the red panel",
" IMPORTANT NOTE: the page should be stored locally.",
" otherwise for instance iexplore can prohibit drag and drop from",
" the browser to other applications because of",
" the protected mode restrictions.",
"3) Check the data in the output area of this dialog",
"5) The output should not contain information that any of",
" flavors is not present in the system clipboard",
"6) The output should contain data in three different formats",
" provided by the system clipboard",
" - Data after the \"ALL:\" marker should include the data",
" from the the \"SELECTION:\" marker",
" - Data after the \"FRAGMENT\" marker should include the data",
" from the \"SELECTION:\" marker and may be some closing",
" tags could be added to the mark-up",
" - Data after the \"SELECTION:\" marker should correspond",
" to the data selected in the browser",
"7) If the above requirements are met, the test is passed"
};
add(new DropPane());
Sysout.createDialogWithInstructions( instructions );
new ManualHTMLDataFlavorTest();
}
public void start ()
{
setSize (200,200);
setVisible(true);
validate();
}// start()
}
/* Place other classes related to the test after this line */
/****************************************************
Standard Test Machinery
DO NOT modify anything below -- it's a standard
chunk of code whose purpose is to make user
interaction uniform, and thereby make it simpler
to read and understand someone else's test.
****************************************************/
/**
This is part of the standard test machinery.
It creates a dialog (with the instructions), and is the interface
for sending text messages to the user.
To print the instructions, send an array of strings to Sysout.createDialog
WithInstructions method. Put one line of instructions per array entry.
To display a message for the tester to see, simply call Sysout.println
with the string to be displayed.
This mimics System.out.println but works within the test harness as well
as standalone.
*/
class Sysout
{
private static TestDialog dialog;
public static void createDialogWithInstructions( String[] instructions )
{
dialog = new TestDialog( new Frame(), "Instructions" );
dialog.printInstructions( instructions );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void createDialog( )
{
dialog = new TestDialog( new Frame(), "Instructions" );
String[] defInstr = { "Instructions will appear here. ", "" } ;
dialog.printInstructions( defInstr );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void printInstructions( String[] instructions )
{
dialog.printInstructions( instructions );
}
public static void println( String messageIn )
{
dialog.displayMessage( messageIn );
}
}// Sysout class
/**
This is part of the standard test machinery. It provides a place for the
test instructions to be displayed, and a place for interactive messages
to the user to be displayed.
To have the test instructions displayed, see Sysout.
To have a message to the user be displayed, see Sysout.
Do not call anything in this dialog directly.
*/
class TestDialog extends Dialog
{
TextArea instructionsText;
TextArea messageText;
int maxStringLength = 80;
//DO NOT call this directly, go through Sysout
public TestDialog( Frame frame, String name )
{
super( frame, name );
int scrollBoth = TextArea.SCROLLBARS_BOTH;
instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
add( "North", instructionsText );
messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
add("Center", messageText);
pack();
setVisible(true);
}// TestDialog()
//DO NOT call this directly, go through Sysout
public void printInstructions( String[] instructions )
{
//Clear out any current instructions
instructionsText.setText( "" );
//Go down array of instruction strings
String printStr, remainingStr;
for( int i=0; i < instructions.length; i++ )
{
//chop up each into pieces maxSringLength long
remainingStr = instructions[ i ];
while( remainingStr.length() > 0 )
{
//if longer than max then chop off first max chars to print
if( remainingStr.length() >= maxStringLength )
{
//Try to chop on a word boundary
int posOfSpace = remainingStr.
lastIndexOf( ' ', maxStringLength - 1 );
if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
printStr = remainingStr.substring( 0, posOfSpace + 1 );
remainingStr = remainingStr.substring( posOfSpace + 1 );
}
//else just print
else
{
printStr = remainingStr;
remainingStr = "";
}
instructionsText.append( printStr + "\n" );
}// while
}// for
}//printInstructions()
//DO NOT call this directly, go through Sysout
public void displayMessage( String messageIn )
{
messageText.append( messageIn + "\n" );
System.out.println(messageIn);
}
}// TestDialog class
/*
* Copyright (c) 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.
*
* 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.*;
public class PutAllHtmlFlavorsOnClipboard {
public static void main(String[] args) {
System.out.println("PutAllHtmlFlavorsOnClipboard has been started.");
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
new HtmlTransferable(HtmlTransferable.htmlDataFlavors), null);
System.out.println("Data has been put on clipboard in a separate process");
}
}
/*
* Copyright (c) 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.
*
* 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.*;
import java.awt.datatransfer.DataFlavor;
public class PutOnlyAllHtmlFlavorOnClipboard {
public static void main(String[] args) {
System.out.println("PutOnlyAllHtmlFlavorOnClipboard has been started.");
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
new HtmlTransferable(new DataFlavor[]{DataFlavor.allHtmlFlavor}), null);
System.out.println("Data has been put on clipboard in a separate process");
}
}
/*
* Copyright (c) 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.
*
* 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.*;
import java.awt.datatransfer.DataFlavor;
public class PutSelectionAndFragmentHtmlFlavorsOnClipboard {
public static void main(String[] args) {
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
new HtmlTransferable(new DataFlavor[]{DataFlavor.selectionHtmlFlavor,
DataFlavor.fragmentHtmlFlavor}), null);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册