提交 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;
} }
/** /**
......
...@@ -171,12 +171,12 @@ public abstract class DataTransferer { ...@@ -171,12 +171,12 @@ public abstract class DataTransferer {
* Lazy initialization of Standard Encodings. * Lazy initialization of Standard Encodings.
*/ */
private static class StandardEncodingsHolder { private static class StandardEncodingsHolder {
private static final SortedSet standardEncodings = load(); private static final SortedSet<String> standardEncodings = load();
private static SortedSet load() { private static SortedSet<String> load() {
final Comparator comparator = final Comparator comparator =
new CharsetComparator(IndexedComparator.SELECT_WORST); new CharsetComparator(IndexedComparator.SELECT_WORST);
final SortedSet tempSet = new TreeSet(comparator); final SortedSet<String> tempSet = new TreeSet<String>(comparator);
tempSet.add("US-ASCII"); tempSet.add("US-ASCII");
tempSet.add("ISO-8859-1"); tempSet.add("ISO-8859-1");
tempSet.add("UTF-8"); tempSet.add("UTF-8");
...@@ -523,8 +523,8 @@ public abstract class DataTransferer { ...@@ -523,8 +523,8 @@ public abstract class DataTransferer {
* So as to avoid loading all available character converters, optional, * So as to avoid loading all available character converters, optional,
* non-standard, character sets are not included. * non-standard, character sets are not included.
*/ */
public static Iterator standardEncodings() { public static Set <String> standardEncodings() {
return StandardEncodingsHolder.standardEncodings.iterator(); return StandardEncodingsHolder.standardEncodings;
} }
/** /**
...@@ -1068,17 +1068,10 @@ public abstract class DataTransferer { ...@@ -1068,17 +1068,10 @@ public abstract class DataTransferer {
* *
* Native to Java string conversion * Native to Java string conversion
*/ */
private String translateBytesOrStreamToString(InputStream str, byte[] bytes, private String translateBytesToString(byte[] bytes, long format,
long format, Transferable localeTransferable)
Transferable localeTransferable)
throws IOException throws IOException
{ {
// A String holds all of its data in memory at one time, so
// we can't avoid reading the entire InputStream at this point.
if (bytes == null) {
bytes = inputStreamToByteArray(str);
}
str.close();
Long lFormat = Long.valueOf(format); Long lFormat = Long.valueOf(format);
String charset = getBestCharsetForTextFormat(lFormat, localeTransferable); String charset = getBestCharsetForTextFormat(lFormat, localeTransferable);
...@@ -1221,13 +1214,13 @@ search: ...@@ -1221,13 +1214,13 @@ search:
("cannot transfer non-text data as Reader"); ("cannot transfer non-text data as Reader");
} }
Reader r = (Reader)obj;
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
int c; try (Reader r = (Reader)obj) {
while ((c = r.read()) != -1) { int c;
buf.append((char)c); while ((c = r.read()) != -1) {
buf.append((char)c);
}
} }
r.close();
return translateTransferableString( return translateTransferableString(
buf.toString(), buf.toString(),
...@@ -1309,7 +1302,7 @@ search: ...@@ -1309,7 +1302,7 @@ search:
return bytes; return bytes;
} }
ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] theByteArray = null;
// Target data is a file list. Source data must be a // Target data is a file list. Source data must be a
// java.util.List which contains java.io.File or String instances. // java.util.List which contains java.io.File or String instances.
...@@ -1324,8 +1317,9 @@ search: ...@@ -1324,8 +1317,9 @@ search:
final ArrayList<String> fileList = castToFiles(list, userProtectionDomain); final ArrayList<String> fileList = castToFiles(list, userProtectionDomain);
bos = convertFileListToBytes(fileList); try (ByteArrayOutputStream bos = convertFileListToBytes(fileList)) {
theByteArray = bos.toByteArray();
}
// Target data is a URI list. Source data must be a // Target data is a URI list. Source data must be a
// java.util.List which contains java.io.File or String instances. // java.util.List which contains java.io.File or String instances.
...@@ -1360,57 +1354,72 @@ search: ...@@ -1360,57 +1354,72 @@ search:
} }
byte[] eoln = "\r\n".getBytes(targetCharset); byte[] eoln = "\r\n".getBytes(targetCharset);
for (int i = 0; i < uriList.size(); i++) {
byte[] bytes = uriList.get(i).getBytes(targetCharset); try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
bos.write(bytes, 0, bytes.length); for (int i = 0; i < uriList.size(); i++) {
bos.write(eoln, 0, eoln.length); byte[] bytes = uriList.get(i).getBytes(targetCharset);
bos.write(bytes, 0, bytes.length);
bos.write(eoln, 0, eoln.length);
}
theByteArray = bos.toByteArray();
} }
// Source data is an InputStream. For arbitrary flavors, just grab the // Source data is an InputStream. For arbitrary flavors, just grab the
// bytes and dump them into a byte array. For text flavors, decode back // bytes and dump them into a byte array. For text flavors, decode back
// to a String and recur to reencode according to the requested format. // to a String and recur to reencode according to the requested format.
} else if (flavor.isRepresentationClassInputStream()) { } else if (flavor.isRepresentationClassInputStream()) {
InputStream is = (InputStream)obj; try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
boolean eof = false; try (InputStream is = (InputStream)obj) {
int avail = is.available(); boolean eof = false;
byte[] tmp = new byte[avail > 8192 ? avail : 8192]; int avail = is.available();
do { byte[] tmp = new byte[avail > 8192 ? avail : 8192];
int ret; do {
if (!(eof = (ret = is.read(tmp, 0, tmp.length)) == -1)) { int aValue;
bos.write(tmp, 0, ret); if (!(eof = (aValue = is.read(tmp, 0, tmp.length)) == -1)) {
bos.write(tmp, 0, aValue);
}
} while (!eof);
} }
} while (!eof);
is.close();
if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) { if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
byte[] bytes = bos.toByteArray(); byte[] bytes = bos.toByteArray();
bos.close(); String sourceEncoding = DataTransferer.getTextCharset(flavor);
String sourceEncoding = DataTransferer.getTextCharset(flavor); return translateTransferableString(
return translateTransferableString( new String(bytes, sourceEncoding),
new String(bytes, sourceEncoding), format);
format); }
theByteArray = bos.toByteArray();
} }
// Source data is an RMI object // Source data is an RMI object
} else if (flavor.isRepresentationClassRemote()) { } else if (flavor.isRepresentationClassRemote()) {
Object mo = RMI.newMarshalledObject(obj); Object mo = RMI.newMarshalledObject(obj);
ObjectOutputStream oos = new ObjectOutputStream(bos); theByteArray = convertObjectToBytes(mo);
oos.writeObject(mo);
oos.close();
// Source data is Serializable // Source data is Serializable
} else if (flavor.isRepresentationClassSerializable()) { } else if (flavor.isRepresentationClassSerializable()) {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj); theByteArray = convertObjectToBytes(obj);
oos.close();
} else { } else {
throw new IOException("data translation failed"); throw new IOException("data translation failed");
} }
byte[] ret = bos.toByteArray();
bos.close();
return ret; return theByteArray;
}
private static byte[] convertObjectToBytes(Object object) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos))
{
oos.writeObject(object);
return bos.toByteArray();
}
} }
protected abstract ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList) throws IOException; protected abstract ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList) throws IOException;
...@@ -1565,38 +1574,8 @@ search: ...@@ -1565,38 +1574,8 @@ search:
long format, Transferable localeTransferable) long format, Transferable localeTransferable)
throws IOException throws IOException
{ {
return translateBytesOrStream(null, bytes, flavor, format,
localeTransferable);
}
public Object translateStream(InputStream str, DataFlavor flavor, Object theObject = null;
long format, Transferable localeTransferable)
throws IOException
{
return translateBytesOrStream(str, null, flavor, format,
localeTransferable);
}
/**
* Primary translation function for translating either a byte array or
* an InputStream into an Object, given a source format and a target
* DataFlavor.
*
* One of str/bytes is non-null; the other is null.
* The conversion from byte[] to InputStream is cheap, so do that
* immediately if necessary. The opposite conversion is expensive,
* so avoid it if possible.
*/
protected Object translateBytesOrStream(InputStream str, byte[] bytes,
DataFlavor flavor, long format,
Transferable localeTransferable)
throws IOException
{
if (str == null) {
str = new ByteArrayInputStream(bytes);
}
// Source data is a file list. Use the dragQueryFile native function to // Source data is a file list. Use the dragQueryFile native function to
// do most of the decoding. Then wrap File objects around the String // do most of the decoding. Then wrap File objects around the String
...@@ -1605,12 +1584,8 @@ search: ...@@ -1605,12 +1584,8 @@ search:
if (!DataFlavor.javaFileListFlavor.equals(flavor)) { if (!DataFlavor.javaFileListFlavor.equals(flavor)) {
throw new IOException("data translation failed"); throw new IOException("data translation failed");
} }
if (bytes == null) {
bytes = inputStreamToByteArray(str);
}
String[] filenames = dragQueryFile(bytes); String[] filenames = dragQueryFile(bytes);
if (filenames == null) { if (filenames == null) {
str.close();
return null; return null;
} }
...@@ -1619,178 +1594,203 @@ search: ...@@ -1619,178 +1594,203 @@ search:
for (int i = 0; i < filenames.length; i++) { for (int i = 0; i < filenames.length; i++) {
files[i] = new File(filenames[i]); files[i] = new File(filenames[i]);
} }
str.close();
// Turn the list of Files into a List and return // Turn the list of Files into a List and return
return Arrays.asList(files); theObject = Arrays.asList(files);
// Source data is a URI list. Convert to DataFlavor.javaFileListFlavor // Target data is a String. Strip terminating NUL bytes. Decode bytes
// where possible. // into characters. Search-and-replace EOLN.
} else if (isURIListFormat(format) && DataFlavor.javaFileListFlavor.equals(flavor)) {
try {
URI uris[] = dragQueryURIs(str, bytes, format, localeTransferable);
if (uris == null) {
return null;
}
ArrayList files = new ArrayList();
for (URI uri : uris) {
try {
files.add(new File(uri));
} catch (IllegalArgumentException illegalArg) {
// When converting from URIs to less generic files,
// common practice (Wine, SWT) seems to be to
// silently drop the URIs that aren't local files.
}
}
return files;
} finally {
str.close();
}
// Target data is a String. Strip terminating NUL bytes. Decode bytes
// into characters. Search-and-replace EOLN.
} else if (String.class.equals(flavor.getRepresentationClass()) && } else if (String.class.equals(flavor.getRepresentationClass()) &&
isFlavorCharsetTextType(flavor) && isTextFormat(format)) { isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
return translateBytesOrStreamToString( theObject = translateBytesToString(bytes, format, localeTransferable);
str, bytes,
format, localeTransferable);
// Special hack to maintain backwards-compatibility with the brokenness // Target data is a Reader. Obtain data in InputStream format, encoded
// of StringSelection. Return a StringReader instead of an InputStream. // as "Unicode" (utf-16be). Then use an InputStreamReader to decode
// Recur to obtain String and encapsulate. // back to chars on demand.
} else if (DataFlavor.plainTextFlavor.equals(flavor)) {
return new StringReader(translateBytesOrStreamToString(
str, bytes,
format, localeTransferable));
// Target data is an InputStream. For arbitrary flavors, just return
// the raw bytes. For text flavors, decode to strip terminators and
// search-and-replace EOLN, then reencode according to the requested
// flavor.
} else if (flavor.isRepresentationClassInputStream()) {
return translateBytesOrStreamToInputStream(str, flavor, format,
localeTransferable);
// Target data is a Reader. Obtain data in InputStream format, encoded
// as "Unicode" (utf-16be). Then use an InputStreamReader to decode
// back to chars on demand.
} else if (flavor.isRepresentationClassReader()) { } else if (flavor.isRepresentationClassReader()) {
if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) { try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
throw new IOException theObject = translateStream(bais,
("cannot transfer non-text data as Reader"); flavor, format, localeTransferable);
} }
// Target data is a CharBuffer. Recur to obtain String and wrap.
InputStream is = (InputStream)
translateBytesOrStreamToInputStream
(str, DataFlavor.plainTextFlavor, format,
localeTransferable);
String unicode =
DataTransferer.getTextCharset(DataFlavor.plainTextFlavor);
Reader reader = new InputStreamReader(is, unicode);
return constructFlavoredObject(reader, flavor, Reader.class);
// Target data is a CharBuffer. Recur to obtain String and wrap.
} else if (flavor.isRepresentationClassCharBuffer()) { } else if (flavor.isRepresentationClassCharBuffer()) {
if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) { if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
throw new IOException throw new IOException
("cannot transfer non-text data as CharBuffer"); ("cannot transfer non-text data as CharBuffer");
} }
CharBuffer buffer = CharBuffer.wrap(translateBytesOrStreamToString( CharBuffer buffer = CharBuffer.wrap(
str, bytes, translateBytesToString(bytes,format, localeTransferable));
format, localeTransferable));
return constructFlavoredObject(buffer, flavor, CharBuffer.class); theObject = constructFlavoredObject(buffer, flavor, CharBuffer.class);
// Target data is a char array. Recur to obtain String and convert to // Target data is a char array. Recur to obtain String and convert to
// char array. // char array.
} else if (charArrayClass.equals(flavor.getRepresentationClass())) { } else if (charArrayClass.equals(flavor.getRepresentationClass())) {
if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) { if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
throw new IOException throw new IOException
("cannot transfer non-text data as char array"); ("cannot transfer non-text data as char array");
} }
return translateBytesOrStreamToString( theObject = translateBytesToString(
str, bytes, bytes, format, localeTransferable).toCharArray();
format, localeTransferable).toCharArray();
// Target data is a ByteBuffer. For arbitrary flavors, just return // Target data is a ByteBuffer. For arbitrary flavors, just return
// the raw bytes. For text flavors, convert to a String to strip // the raw bytes. For text flavors, convert to a String to strip
// terminators and search-and-replace EOLN, then reencode according to // terminators and search-and-replace EOLN, then reencode according to
// the requested flavor. // the requested flavor.
} else if (flavor.isRepresentationClassByteBuffer()) { } else if (flavor.isRepresentationClassByteBuffer()) {
if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) { if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
bytes = translateBytesOrStreamToString( bytes = translateBytesToString(
str, bytes, bytes, format, localeTransferable).getBytes(
format, localeTransferable DataTransferer.getTextCharset(flavor)
).getBytes( );
DataTransferer.getTextCharset(flavor)
);
} else {
if (bytes == null) {
bytes = inputStreamToByteArray(str);
}
} }
ByteBuffer buffer = ByteBuffer.wrap(bytes); ByteBuffer buffer = ByteBuffer.wrap(bytes);
return constructFlavoredObject(buffer, flavor, ByteBuffer.class); theObject = constructFlavoredObject(buffer, flavor, ByteBuffer.class);
// Target data is a byte array. For arbitrary flavors, just return // Target data is a byte array. For arbitrary flavors, just return
// the raw bytes. For text flavors, convert to a String to strip // the raw bytes. For text flavors, convert to a String to strip
// terminators and search-and-replace EOLN, then reencode according to // terminators and search-and-replace EOLN, then reencode according to
// the requested flavor. // the requested flavor.
} else if (byteArrayClass.equals(flavor.getRepresentationClass())) { } else if (byteArrayClass.equals(flavor.getRepresentationClass())) {
if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) { if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
return translateBytesOrStreamToString( theObject = translateBytesToString(
str, bytes, bytes, format, localeTransferable
format, localeTransferable ).getBytes(DataTransferer.getTextCharset(flavor));
).getBytes(
DataTransferer.getTextCharset(flavor)
);
} else { } else {
return (bytes != null) ? bytes : inputStreamToByteArray(str); theObject = bytes;
} }
// Target data is an RMI object // Target data is an InputStream. For arbitrary flavors, just return
} else if (flavor.isRepresentationClassRemote()) { // the raw bytes. For text flavors, decode to strip terminators and
try { // search-and-replace EOLN, then reencode according to the requested
byte[] ba = inputStreamToByteArray(str); // flavor.
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(ba)); } else if (flavor.isRepresentationClassInputStream()) {
Object ret = RMI.getMarshalledObject(ois.readObject());
ois.close(); try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
str.close(); theObject = translateStream(bais, flavor, format, localeTransferable);
return ret;
} catch (Exception e) {
throw new IOException(e.getMessage());
} }
// Target data is Serializable // Target data is Serializable
} else if (flavor.isRepresentationClassSerializable()) { } else if (flavor.isRepresentationClassSerializable()) {
try {
byte[] ba = inputStreamToByteArray(str); try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(ba)); theObject = translateStream(bais, flavor, format, localeTransferable);
Object ret = ois.readObject();
ois.close();
str.close();
return ret;
} catch (Exception e) {
throw new IOException(e.getMessage());
} }
// Target data is Image // Target data is Image
} else if (DataFlavor.imageFlavor.equals(flavor)) { } else if (DataFlavor.imageFlavor.equals(flavor)) {
if (!isImageFormat(format)) { if (!isImageFormat(format)) {
throw new IOException("data translation failed"); throw new IOException("data translation failed");
} }
Image image = platformImageBytesOrStreamToImage(str, bytes, format); theObject = platformImageBytesToImage(bytes, format);
str.close(); }
return image;
if (theObject == null) {
throw new IOException("data translation failed");
}
return theObject;
}
/**
* Primary translation function for translating
* an InputStream into an Object, given a source format and a target
* DataFlavor.
*/
public Object translateStream(InputStream str, DataFlavor flavor,
long format, Transferable localeTransferable)
throws IOException
{
Object theObject = null;
// Source data is a URI list. Convert to DataFlavor.javaFileListFlavor
// where possible.
if (isURIListFormat(format)
&& DataFlavor.javaFileListFlavor.equals(flavor))
{
URI uris[] = dragQueryURIs(str, format, localeTransferable);
if (uris == null) {
return null;
}
ArrayList files = new ArrayList();
for (URI uri : uris) {
try {
files.add(new File(uri));
} catch (IllegalArgumentException illegalArg) {
// When converting from URIs to less generic files,
// common practice (Wine, SWT) seems to be to
// silently drop the URIs that aren't local files.
}
}
theObject = files;
// Special hack to maintain backwards-compatibility with the brokenness
// of StringSelection. Return a StringReader instead of an InputStream.
// Recur to obtain String and encapsulate.
} else if (DataFlavor.plainTextFlavor.equals(flavor)) {
theObject = new StringReader(translateBytesToString(
inputStreamToByteArray(str),
format, localeTransferable));
// Target data is an InputStream. For arbitrary flavors, just return
// the raw bytes. For text flavors, decode to strip terminators and
// search-and-replace EOLN, then reencode according to the requested
// flavor.
} else if (flavor.isRepresentationClassInputStream()) {
theObject = translateStreamToInputStream(str, flavor, format,
localeTransferable);
// Target data is a Reader. Obtain data in InputStream format, encoded
// as "Unicode" (utf-16be). Then use an InputStreamReader to decode
// back to chars on demand.
} else if (flavor.isRepresentationClassReader()) {
if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
throw new IOException
("cannot transfer non-text data as Reader");
}
InputStream is = (InputStream)translateStreamToInputStream(
str, DataFlavor.plainTextFlavor,
format, localeTransferable);
String unicode = DataTransferer.getTextCharset(DataFlavor.plainTextFlavor);
Reader reader = new InputStreamReader(is, unicode);
theObject = constructFlavoredObject(reader, flavor, Reader.class);
// Target data is an RMI object
} else if (flavor.isRepresentationClassRemote()) {
try (ObjectInputStream ois =
new ObjectInputStream(str))
{
theObject = RMI.getMarshalledObject(ois.readObject());
}catch (Exception e) {
throw new IOException(e.getMessage());
}
// Target data is Serializable
} else if (flavor.isRepresentationClassSerializable()) {
try (ObjectInputStream ois =
new ObjectInputStream(str))
{
theObject = ois.readObject();
} catch (Exception e) {
throw new IOException(e.getMessage());
}
} }
throw new IOException("data translation failed");
return theObject;
} }
/** /**
...@@ -1798,7 +1798,7 @@ search: ...@@ -1798,7 +1798,7 @@ search:
* ReencodingInputStream will decode and reencode the InputStream on demand * ReencodingInputStream will decode and reencode the InputStream on demand
* so that we can strip terminators and search-and-replace EOLN. * so that we can strip terminators and search-and-replace EOLN.
*/ */
private Object translateBytesOrStreamToInputStream private Object translateStreamToInputStream
(InputStream str, DataFlavor flavor, long format, (InputStream str, DataFlavor flavor, long format,
Transferable localeTransferable) throws IOException Transferable localeTransferable) throws IOException
{ {
...@@ -2054,7 +2054,6 @@ search: ...@@ -2054,7 +2054,6 @@ search:
* Decodes URIs from either a byte array or a stream. * Decodes URIs from either a byte array or a stream.
*/ */
protected URI[] dragQueryURIs(InputStream stream, protected URI[] dragQueryURIs(InputStream stream,
byte[] bytes,
long format, long format,
Transferable localeTransferable) Transferable localeTransferable)
throws IOException throws IOException
...@@ -2067,10 +2066,10 @@ search: ...@@ -2067,10 +2066,10 @@ search:
* 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 abstract Image platformImageBytesOrStreamToImage(InputStream str,
byte[] bytes,
long format) protected abstract Image platformImageBytesToImage(
throws IOException; byte[] bytes,long format) throws IOException;
/** /**
* Translates either a byte array or an input stream which contain * Translates either a byte array or an input stream which contain
...@@ -2078,13 +2077,9 @@ search: ...@@ -2078,13 +2077,9 @@ search:
* *
* @param mimeType image MIME type, such as: image/png, image/jpeg, image/gif * @param mimeType image MIME type, such as: image/png, image/jpeg, image/gif
*/ */
protected Image standardImageBytesOrStreamToImage(InputStream inputStream, protected Image standardImageBytesToImage(
byte[] bytes, byte[] bytes, String mimeType) throws IOException
String mimeType) {
throws IOException {
if (inputStream == null) {
inputStream = new ByteArrayInputStream(bytes);
}
Iterator readerIterator = ImageIO.getImageReadersByMIMEType(mimeType); Iterator readerIterator = ImageIO.getImageReadersByMIMEType(mimeType);
...@@ -2097,9 +2092,9 @@ search: ...@@ -2097,9 +2092,9 @@ search:
while (readerIterator.hasNext()) { while (readerIterator.hasNext()) {
ImageReader imageReader = (ImageReader)readerIterator.next(); ImageReader imageReader = (ImageReader)readerIterator.next();
try { try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
ImageInputStream imageInputStream = ImageInputStream imageInputStream =
ImageIO.createImageInputStream(inputStream); ImageIO.createImageInputStream(bais);
try { try {
ImageReadParam param = imageReader.getDefaultReadParam(); ImageReadParam param = imageReader.getDefaultReadParam();
...@@ -2456,15 +2451,16 @@ search: ...@@ -2456,15 +2451,16 @@ search:
protected static byte[] inputStreamToByteArray(InputStream str) protected static byte[] inputStreamToByteArray(InputStream str)
throws IOException throws IOException
{ {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
int len = 0; int len = 0;
byte[] buf = new byte[8192]; byte[] buf = new byte[8192];
while ((len = str.read(buf)) != -1) { while ((len = str.read(buf)) != -1) {
baos.write(buf, 0, len); baos.write(buf, 0, len);
} }
return baos.toByteArray(); return baos.toByteArray();
}
} }
/** /**
......
...@@ -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);
} }
......
...@@ -87,35 +87,35 @@ import java.io.ByteArrayOutputStream; ...@@ -87,35 +87,35 @@ import java.io.ByteArrayOutputStream;
*/ */
public class WDataTransferer extends DataTransferer { public class WDataTransferer extends DataTransferer {
private static final String[] predefinedClipboardNames = { private static final String[] predefinedClipboardNames = {
"", "",
"TEXT", "TEXT",
"BITMAP", "BITMAP",
"METAFILEPICT", "METAFILEPICT",
"SYLK", "SYLK",
"DIF", "DIF",
"TIFF", "TIFF",
"OEM TEXT", "OEM TEXT",
"DIB", "DIB",
"PALETTE", "PALETTE",
"PENDATA", "PENDATA",
"RIFF", "RIFF",
"WAVE", "WAVE",
"UNICODE TEXT", "UNICODE TEXT",
"ENHMETAFILE", "ENHMETAFILE",
"HDROP", "HDROP",
"LOCALE", "LOCALE",
"DIBV5" "DIBV5"
}; };
private static final Map <String, Long> predefinedClipboardNameMap; private static final Map <String, Long> predefinedClipboardNameMap;
static { static {
Map <String,Long> tempMap = Map <String,Long> tempMap =
new HashMap <> (predefinedClipboardNames.length, 1.0f); new HashMap <> (predefinedClipboardNames.length, 1.0f);
for (int i = 1; i < predefinedClipboardNames.length; i++) { for (int i = 1; i < predefinedClipboardNames.length; i++) {
tempMap.put(predefinedClipboardNames[i], Long.valueOf(i)); tempMap.put(predefinedClipboardNames[i], Long.valueOf(i));
} }
predefinedClipboardNameMap = predefinedClipboardNameMap =
Collections.synchronizedMap(tempMap); Collections.synchronizedMap(tempMap);
} }
/** /**
...@@ -138,18 +138,18 @@ public class WDataTransferer extends DataTransferer { ...@@ -138,18 +138,18 @@ public class WDataTransferer extends DataTransferer {
//CF_FILECONTENTS supported as mandatory associated clipboard //CF_FILECONTENTS supported as mandatory associated clipboard
private static final Long L_CF_LOCALE = private static final Long L_CF_LOCALE =
predefinedClipboardNameMap.get(predefinedClipboardNames[CF_LOCALE]); predefinedClipboardNameMap.get(predefinedClipboardNames[CF_LOCALE]);
private static final DirectColorModel directColorModel = private static final DirectColorModel directColorModel =
new DirectColorModel(24, new DirectColorModel(24,
0x00FF0000, /* red mask */ 0x00FF0000, /* red mask */
0x0000FF00, /* green mask */ 0x0000FF00, /* green mask */
0x000000FF); /* blue mask */ 0x000000FF); /* blue mask */
private static final int[] bandmasks = new int[] { private static final int[] bandmasks = new int[] {
directColorModel.getRedMask(), directColorModel.getRedMask(),
directColorModel.getGreenMask(), directColorModel.getGreenMask(),
directColorModel.getBlueMask() }; directColorModel.getBlueMask() };
/** /**
* Singleton constructor * Singleton constructor
...@@ -171,10 +171,10 @@ public class WDataTransferer extends DataTransferer { ...@@ -171,10 +171,10 @@ public class WDataTransferer extends DataTransferer {
} }
public SortedMap <Long, DataFlavor> getFormatsForFlavors( public SortedMap <Long, DataFlavor> getFormatsForFlavors(
DataFlavor[] flavors, FlavorTable map) DataFlavor[] flavors, FlavorTable map)
{ {
SortedMap <Long, DataFlavor> retval = SortedMap <Long, DataFlavor> retval =
super.getFormatsForFlavors(flavors, map); super.getFormatsForFlavors(flavors, map);
// The Win32 native code does not support exporting LOCALE data, nor // The Win32 native code does not support exporting LOCALE data, nor
// should it. // should it.
...@@ -191,32 +191,60 @@ public class WDataTransferer extends DataTransferer { ...@@ -191,32 +191,60 @@ public class WDataTransferer extends DataTransferer {
DataFlavor flavor, DataFlavor flavor,
long format) throws IOException long format) throws IOException
{ {
byte[] bytes = super.translateTransferable(contents, flavor, format); byte[] bytes = null;
if (format == CF_HTML) { if (format == CF_HTML) {
bytes = HTMLCodec.convertToHTMLFormat(bytes); if (contents.isDataFlavorSupported(DataFlavor.selectionHtmlFlavor)) {
// if a user provides data represented by
// DataFlavor.selectionHtmlFlavor format, we use this
// type to store the data in the native clipboard
bytes = super.translateTransferable(contents,
DataFlavor.selectionHtmlFlavor,
format);
} else if (contents.isDataFlavorSupported(DataFlavor.allHtmlFlavor)) {
// if we cannot get data represented by the
// DataFlavor.selectionHtmlFlavor format
// but the DataFlavor.allHtmlFlavor format is avialable
// we belive that the user knows how to represent
// the data and how to mark up selection in a
// system specific manner. Therefor, we use this data
bytes = super.translateTransferable(contents,
DataFlavor.allHtmlFlavor,
format);
} else {
// handel other html flavor types, including custom and
// fragment ones
bytes = HTMLCodec.convertToHTMLFormat(bytes);
}
} else {
// we handle non-html types basing on their
// flavors
bytes = super.translateTransferable(contents, flavor, format);
} }
return bytes; return bytes;
} }
protected Object translateBytesOrStream(InputStream str, byte[] bytes, // The stream is closed as a closable object
DataFlavor flavor, long format, public Object translateStream(InputStream str,
Transferable localeTransferable) DataFlavor flavor, long format,
Transferable localeTransferable)
throws IOException throws IOException
{ {
if (format == CF_HTML && flavor.isFlavorTextType()) { if (format == CF_HTML && flavor.isFlavorTextType()) {
if (str == null) { str = new HTMLCodec(str,
str = new ByteArrayInputStream(bytes); EHTMLReadMode.getEHTMLReadMode(flavor));
bytes = null;
}
str = new HTMLCodec(str, EHTMLReadMode.HTML_READ_SELECTION);
} }
return super.translateStream(str, flavor, format,
localeTransferable);
}
public Object translateBytes(byte[] bytes, DataFlavor flavor, long format,
Transferable localeTransferable) throws IOException
{
if (format == CF_FILEGROUPDESCRIPTORA || format == CF_FILEGROUPDESCRIPTORW) { if (format == CF_FILEGROUPDESCRIPTORA || format == CF_FILEGROUPDESCRIPTORW) {
if (null != str ) {
str.close();
}
if (bytes == null || !DataFlavor.javaFileListFlavor.equals(flavor)) { if (bytes == null || !DataFlavor.javaFileListFlavor.equals(flavor)) {
throw new IOException("data translation failed"); throw new IOException("data translation failed");
} }
...@@ -238,28 +266,24 @@ public class WDataTransferer extends DataTransferer { ...@@ -238,28 +266,24 @@ public class WDataTransferer extends DataTransferer {
} }
if (format == CFSTR_INETURL && if (format == CFSTR_INETURL &&
URL.class.equals(flavor.getRepresentationClass())) URL.class.equals(flavor.getRepresentationClass()))
{ {
if (bytes == null) {
bytes = inputStreamToByteArray(str);
str = null;
}
String charset = getDefaultTextCharset(); String charset = getDefaultTextCharset();
if (localeTransferable != null && localeTransferable. if (localeTransferable != null && localeTransferable.
isDataFlavorSupported(javaTextEncodingFlavor)) isDataFlavorSupported(javaTextEncodingFlavor))
{ {
try { try {
charset = new String((byte[])localeTransferable. charset = new String((byte[])localeTransferable.
getTransferData(javaTextEncodingFlavor), getTransferData(javaTextEncodingFlavor), "UTF-8");
"UTF-8");
} catch (UnsupportedFlavorException cannotHappen) { } catch (UnsupportedFlavorException cannotHappen) {
} }
} }
return new URL(new String(bytes, charset)); return new URL(new String(bytes, charset));
} }
return super.translateBytesOrStream(str, bytes, flavor, format, return super.translateBytes(bytes , flavor, format,
localeTransferable); localeTransferable);
} }
public boolean isLocaleDependentTextFormat(long format) { public boolean isLocaleDependentTextFormat(long format) {
...@@ -280,18 +304,18 @@ public class WDataTransferer extends DataTransferer { ...@@ -280,18 +304,18 @@ public class WDataTransferer extends DataTransferer {
protected String getNativeForFormat(long format) { protected String getNativeForFormat(long format) {
return (format < predefinedClipboardNames.length) return (format < predefinedClipboardNames.length)
? predefinedClipboardNames[(int)format] ? predefinedClipboardNames[(int)format]
: getClipboardFormatName(format); : getClipboardFormatName(format);
} }
private final ToolkitThreadBlockedHandler handler = private final ToolkitThreadBlockedHandler handler =
new WToolkitThreadBlockedHandler(); new WToolkitThreadBlockedHandler();
public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() { public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() {
return handler; return handler;
} }
/** /**
* Calls the Win32 RegisterClipboardFormat function to register * Calls the Win32 RegisterClipboardFormat function to register
* a non-standard format. * a non-standard format.
*/ */
...@@ -305,12 +329,12 @@ public class WDataTransferer extends DataTransferer { ...@@ -305,12 +329,12 @@ public class WDataTransferer extends DataTransferer {
public boolean isImageFormat(long format) { public boolean isImageFormat(long format) {
return format == CF_DIB || format == CF_ENHMETAFILE || return format == CF_DIB || format == CF_ENHMETAFILE ||
format == CF_METAFILEPICT || format == CF_PNG || format == CF_METAFILEPICT || format == CF_PNG ||
format == CF_JFIF; format == CF_JFIF;
} }
protected byte[] imageToPlatformBytes(Image image, long format) protected byte[] imageToPlatformBytes(Image image, long format)
throws IOException { throws IOException {
String mimeType = null; String mimeType = null;
if (format == CF_PNG) { if (format == CF_PNG) {
mimeType = "image/png"; mimeType = "image/png";
...@@ -352,11 +376,11 @@ public class WDataTransferer extends DataTransferer { ...@@ -352,11 +376,11 @@ public class WDataTransferer extends DataTransferer {
int[] nBits = {8, 8, 8}; int[] nBits = {8, 8, 8};
int[] bOffs = {2, 1, 0}; int[] bOffs = {2, 1, 0};
ColorModel colorModel = ColorModel colorModel =
new ComponentColorModel(cs, nBits, false, false, new ComponentColorModel(cs, nBits, false, false,
Transparency.OPAQUE, DataBuffer.TYPE_BYTE); Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
WritableRaster raster = WritableRaster raster =
Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height,
width * 3 + pad, 3, bOffs, null); width * 3 + pad, 3, bOffs, null);
BufferedImage bimage = new BufferedImage(colorModel, raster, false, null); BufferedImage bimage = new BufferedImage(colorModel, raster, false, null);
...@@ -364,7 +388,7 @@ public class WDataTransferer extends DataTransferer { ...@@ -364,7 +388,7 @@ public class WDataTransferer extends DataTransferer {
// top-down DIBs. // top-down DIBs.
// So we flip the image vertically and create a bottom-up DIB. // So we flip the image vertically and create a bottom-up DIB.
AffineTransform imageFlipTransform = AffineTransform imageFlipTransform =
new AffineTransform(1, 0, 0, -1, 0, height); new AffineTransform(1, 0, 0, -1, 0, height);
Graphics2D g2d = bimage.createGraphics(); Graphics2D g2d = bimage.createGraphics();
...@@ -383,7 +407,7 @@ public class WDataTransferer extends DataTransferer { ...@@ -383,7 +407,7 @@ public class WDataTransferer extends DataTransferer {
private static final byte [] UNICODE_NULL_TERMINATOR = new byte [] {0,0}; private static final byte [] UNICODE_NULL_TERMINATOR = new byte [] {0,0};
protected ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList) protected ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList)
throws IOException throws IOException
{ {
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
...@@ -407,10 +431,10 @@ public class WDataTransferer extends DataTransferer { ...@@ -407,10 +431,10 @@ public class WDataTransferer extends DataTransferer {
return bos; return bos;
} }
/** /**
* Returns a byte array which contains data special for the given format * Returns a byte array which contains data special for the given format
* and for the given image data. * and for the given image data.
*/ */
private native byte[] imageDataToPlatformImageBytes(byte[] imageData, private native byte[] imageDataToPlatformImageBytes(byte[] imageData,
int width, int height, int width, int height,
long format); long format);
...@@ -419,10 +443,8 @@ public class WDataTransferer extends DataTransferer { ...@@ -419,10 +443,8 @@ public class WDataTransferer 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 str, protected Image platformImageBytesToImage(byte[] bytes, long format)
byte[] bytes, throws IOException {
long format)
throws IOException {
String mimeType = null; String mimeType = null;
if (format == CF_PNG) { if (format == CF_PNG) {
mimeType = "image/png"; mimeType = "image/png";
...@@ -430,11 +452,7 @@ public class WDataTransferer extends DataTransferer { ...@@ -430,11 +452,7 @@ public class WDataTransferer extends DataTransferer {
mimeType = "image/jpeg"; mimeType = "image/jpeg";
} }
if (mimeType != null) { if (mimeType != null) {
return standardImageBytesOrStreamToImage(str, bytes, mimeType); return standardImageBytesToImage(bytes, mimeType);
}
if (bytes == null) {
bytes = inputStreamToByteArray(str);
} }
int[] imageData = platformImageBytesToImageData(bytes, format); int[] imageData = platformImageBytesToImageData(bytes, format);
...@@ -448,8 +466,8 @@ public class WDataTransferer extends DataTransferer { ...@@ -448,8 +466,8 @@ public class WDataTransferer extends DataTransferer {
DataBufferInt buffer = new DataBufferInt(imageData, len); DataBufferInt buffer = new DataBufferInt(imageData, len);
WritableRaster raster = Raster.createPackedRaster(buffer, width, WritableRaster raster = Raster.createPackedRaster(buffer, width,
height, width, height, width,
bandmasks, null); bandmasks, null);
return new BufferedImage(directColorModel, raster, false, null); return new BufferedImage(directColorModel, raster, false, null);
} }
...@@ -462,13 +480,13 @@ public class WDataTransferer extends DataTransferer { ...@@ -462,13 +480,13 @@ public class WDataTransferer extends DataTransferer {
*/ */
private native int[] platformImageBytesToImageData(byte[] bytes, private native int[] platformImageBytesToImageData(byte[] bytes,
long format) long format)
throws IOException; throws IOException;
protected native String[] dragQueryFile(byte[] bytes); protected native String[] dragQueryFile(byte[] bytes);
} }
final class WToolkitThreadBlockedHandler extends Mutex final class WToolkitThreadBlockedHandler extends Mutex
implements ToolkitThreadBlockedHandler { implements ToolkitThreadBlockedHandler {
public void enter() { public void enter() {
if (!isOwned()) { if (!isOwned()) {
...@@ -492,7 +510,22 @@ final class WToolkitThreadBlockedHandler extends Mutex ...@@ -492,7 +510,22 @@ final class WToolkitThreadBlockedHandler extends Mutex
enum EHTMLReadMode { enum EHTMLReadMode {
HTML_READ_ALL, HTML_READ_ALL,
HTML_READ_FRAGMENT, HTML_READ_FRAGMENT,
HTML_READ_SELECTION HTML_READ_SELECTION;
public static EHTMLReadMode getEHTMLReadMode (DataFlavor df) {
EHTMLReadMode mode = HTML_READ_SELECTION;
String parameter = df.getParameter("document");
if ("all".equals(parameter)) {
mode = HTML_READ_ALL;
} else if ("fragment".equals(parameter)) {
mode = HTML_READ_FRAGMENT;
}
return mode;
}
} }
/** /**
...@@ -581,26 +614,24 @@ class HTMLCodec extends InputStream { ...@@ -581,26 +614,24 @@ class HTMLCodec extends InputStream {
htmlSuffix = "</BODY>" + htmlSuffix; htmlSuffix = "</BODY>" + htmlSuffix;
}; };
}; };
htmlPrefix = htmlPrefix + START_FRAGMENT_CMT;
htmlSuffix = END_FRAGMENT_CMT + htmlSuffix;
} }
String stBaseUrl = DEF_SOURCE_URL; String stBaseUrl = DEF_SOURCE_URL;
int nStartHTML = int nStartHTML =
VERSION.length() + VERSION_NUM.length() + EOLN.length() VERSION.length() + VERSION_NUM.length() + EOLN.length()
+ START_HTML.length() + PADDED_WIDTH + EOLN.length() + START_HTML.length() + PADDED_WIDTH + EOLN.length()
+ END_HTML.length() + PADDED_WIDTH + EOLN.length() + END_HTML.length() + PADDED_WIDTH + EOLN.length()
+ START_FRAGMENT.length() + PADDED_WIDTH + EOLN.length() + START_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
+ END_FRAGMENT.length() + PADDED_WIDTH + EOLN.length() + END_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
+ SOURCE_URL.length() + stBaseUrl.length() + EOLN.length() + SOURCE_URL.length() + stBaseUrl.length() + EOLN.length()
; ;
int nStartFragment = nStartHTML + htmlPrefix.length(); int nStartFragment = nStartHTML + htmlPrefix.length();
int nEndFragment = nStartFragment + bytes.length - 1; int nEndFragment = nStartFragment + bytes.length - 1;
int nEndHTML = nEndFragment + htmlSuffix.length(); int nEndHTML = nEndFragment + htmlSuffix.length();
StringBuilder header = new StringBuilder( StringBuilder header = new StringBuilder(
nStartFragment nStartFragment
+ START_FRAGMENT_CMT.length() + START_FRAGMENT_CMT.length()
); );
//header //header
header.append(VERSION); header.append(VERSION);
...@@ -639,14 +670,14 @@ class HTMLCodec extends InputStream { ...@@ -639,14 +670,14 @@ class HTMLCodec extends InputStream {
} }
byte[] retval = new byte[headerBytes.length + bytes.length + byte[] retval = new byte[headerBytes.length + bytes.length +
trailerBytes.length]; trailerBytes.length];
System.arraycopy(headerBytes, 0, retval, 0, headerBytes.length); System.arraycopy(headerBytes, 0, retval, 0, headerBytes.length);
System.arraycopy(bytes, 0, retval, headerBytes.length, System.arraycopy(bytes, 0, retval, headerBytes.length,
bytes.length - 1); bytes.length - 1);
System.arraycopy(trailerBytes, 0, retval, System.arraycopy(trailerBytes, 0, retval,
headerBytes.length + bytes.length - 1, headerBytes.length + bytes.length - 1,
trailerBytes.length); trailerBytes.length);
retval[retval.length-1] = 0; retval[retval.length-1] = 0;
return retval; return retval;
...@@ -659,7 +690,7 @@ class HTMLCodec extends InputStream { ...@@ -659,7 +690,7 @@ class HTMLCodec extends InputStream {
private boolean descriptionParsed = false; private boolean descriptionParsed = false;
private boolean closed = false; private boolean closed = false;
// InputStreamReader uses an 8K buffer. The size is not customizable. // InputStreamReader uses an 8K buffer. The size is not customizable.
public static final int BYTE_BUFFER_LEN = 8192; public static final int BYTE_BUFFER_LEN = 8192;
// CharToByteUTF8.getMaxBytesPerChar returns 3, so we should not buffer // CharToByteUTF8.getMaxBytesPerChar returns 3, so we should not buffer
...@@ -667,30 +698,30 @@ class HTMLCodec extends InputStream { ...@@ -667,30 +698,30 @@ class HTMLCodec extends InputStream {
public static final int CHAR_BUFFER_LEN = BYTE_BUFFER_LEN / 3; public static final int CHAR_BUFFER_LEN = BYTE_BUFFER_LEN / 3;
private static final String FAILURE_MSG = private static final String FAILURE_MSG =
"Unable to parse HTML description: "; "Unable to parse HTML description: ";
private static final String INVALID_MSG = private static final String INVALID_MSG =
" invalid"; " invalid";
//HTML header mapping: //HTML header mapping:
private long iHTMLStart,// StartHTML -- shift in array to the first byte after the header private long iHTMLStart,// StartHTML -- shift in array to the first byte after the header
iHTMLEnd, // EndHTML -- shift in array of last byte for HTML syntax analysis iHTMLEnd, // EndHTML -- shift in array of last byte for HTML syntax analysis
iFragStart,// StartFragment -- shift in array jast after <!--StartFragment--> iFragStart,// StartFragment -- shift in array jast after <!--StartFragment-->
iFragEnd, // EndFragment -- shift in array before start <!--EndFragment--> iFragEnd, // EndFragment -- shift in array before start <!--EndFragment-->
iSelStart, // StartSelection -- shift in array of the first char in copied selection iSelStart, // StartSelection -- shift in array of the first char in copied selection
iSelEnd; // EndSelection -- shift in array of the last char in copied selection iSelEnd; // EndSelection -- shift in array of the last char in copied selection
private String stBaseURL; // SourceURL -- base URL for related referenses private String stBaseURL; // SourceURL -- base URL for related referenses
private String stVersion; // Version -- current supported version private String stVersion; // Version -- current supported version
//Stream reader markers: //Stream reader markers:
private long iStartOffset, private long iStartOffset,
iEndOffset, iEndOffset,
iReadCount; iReadCount;
private EHTMLReadMode readMode; private EHTMLReadMode readMode;
public HTMLCodec( public HTMLCodec(
InputStream _bytestream, InputStream _bytestream,
EHTMLReadMode _readMode) throws IOException EHTMLReadMode _readMode) throws IOException
{ {
bufferedStream = new BufferedInputStream(_bytestream, BYTE_BUFFER_LEN); bufferedStream = new BufferedInputStream(_bytestream, BYTE_BUFFER_LEN);
readMode = _readMode; readMode = _readMode;
...@@ -723,31 +754,31 @@ class HTMLCodec extends InputStream { ...@@ -723,31 +754,31 @@ class HTMLCodec extends InputStream {
// initialization of array offset pointers // initialization of array offset pointers
// to the same "uninitialized" state. // to the same "uninitialized" state.
iHTMLEnd = iHTMLEnd =
iHTMLStart = iHTMLStart =
iFragEnd = iFragEnd =
iFragStart = iFragStart =
iSelEnd = iSelEnd =
iSelStart = -1; iSelStart = -1;
bufferedStream.mark(BYTE_BUFFER_LEN); bufferedStream.mark(BYTE_BUFFER_LEN);
String astEntries[] = new String[] { String astEntries[] = new String[] {
//common //common
VERSION, VERSION,
START_HTML, START_HTML,
END_HTML, END_HTML,
START_FRAGMENT, START_FRAGMENT,
END_FRAGMENT, END_FRAGMENT,
//ver 1.0 //ver 1.0
START_SELECTION, START_SELECTION,
END_SELECTION, END_SELECTION,
SOURCE_URL SOURCE_URL
}; };
BufferedReader bufferedReader = new BufferedReader( BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader( new InputStreamReader(
bufferedStream, bufferedStream,
ENCODING ENCODING
), ),
CHAR_BUFFER_LEN CHAR_BUFFER_LEN
); );
long iHeadSize = 0; long iHeadSize = 0;
long iCRSize = EOLN.length(); long iCRSize = EOLN.length();
...@@ -769,30 +800,30 @@ class HTMLCodec extends InputStream { ...@@ -769,30 +800,30 @@ class HTMLCodec extends InputStream {
if( null!=stValue ) { if( null!=stValue ) {
try{ try{
switch( iEntry ){ switch( iEntry ){
case 0: case 0:
stVersion = stValue; stVersion = stValue;
break; break;
case 1: case 1:
iHTMLStart = Integer.parseInt(stValue); iHTMLStart = Integer.parseInt(stValue);
break; break;
case 2: case 2:
iHTMLEnd = Integer.parseInt(stValue); iHTMLEnd = Integer.parseInt(stValue);
break; break;
case 3: case 3:
iFragStart = Integer.parseInt(stValue); iFragStart = Integer.parseInt(stValue);
break; break;
case 4: case 4:
iFragEnd = Integer.parseInt(stValue); iFragEnd = Integer.parseInt(stValue);
break; break;
case 5: case 5:
iSelStart = Integer.parseInt(stValue); iSelStart = Integer.parseInt(stValue);
break; break;
case 6: case 6:
iSelEnd = Integer.parseInt(stValue); iSelEnd = Integer.parseInt(stValue);
break; break;
case 7: case 7:
stBaseURL = stValue; stBaseURL = stValue;
break; break;
}; };
} catch ( NumberFormatException e ) { } catch ( NumberFormatException e ) {
throw new IOException(FAILURE_MSG + astEntries[iEntry]+ " value " + e + INVALID_MSG); throw new IOException(FAILURE_MSG + astEntries[iEntry]+ " value " + e + INVALID_MSG);
...@@ -816,19 +847,19 @@ class HTMLCodec extends InputStream { ...@@ -816,19 +847,19 @@ class HTMLCodec extends InputStream {
//one of possible modes //one of possible modes
switch( readMode ){ switch( readMode ){
case HTML_READ_ALL: case HTML_READ_ALL:
iStartOffset = iHTMLStart; iStartOffset = iHTMLStart;
iEndOffset = iHTMLEnd; iEndOffset = iHTMLEnd;
break; break;
case HTML_READ_FRAGMENT: case HTML_READ_FRAGMENT:
iStartOffset = iFragStart; iStartOffset = iFragStart;
iEndOffset = iFragEnd; iEndOffset = iFragEnd;
break; break;
case HTML_READ_SELECTION: case HTML_READ_SELECTION:
default: default:
iStartOffset = iSelStart; iStartOffset = iSelStart;
iEndOffset = iSelEnd; iEndOffset = iSelEnd;
break; break;
} }
bufferedStream.reset(); bufferedStream.reset();
......
/*
* 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.
先完成此消息的编辑!
想要评论请 注册