7075105: WIN: Provide a way to format HTML on drop
authordenis
Wed, 27 Mar 2013 16:19:51 +0400
changeset 16705 1caaa379eded
parent 16471 33bca48c948b
child 16706 4b243017cd27
7075105: WIN: Provide a way to format HTML on drop Reviewed-by: uta, serb
jdk/src/macosx/classes/sun/lwawt/macosx/CDataTransferer.java
jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java
jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java
jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java
jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java
jdk/src/solaris/classes/sun/awt/X11/XDataTransferer.java
jdk/src/windows/classes/sun/awt/windows/WDataTransferer.java
jdk/test/java/awt/datatransfer/HTMLDataFlavors/HTMLDataFlavorTest.java
jdk/test/java/awt/datatransfer/HTMLDataFlavors/HtmlTransferable.java
jdk/test/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.html
jdk/test/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.java
jdk/test/java/awt/datatransfer/HTMLDataFlavors/PutAllHtmlFlavorsOnClipboard.java
jdk/test/java/awt/datatransfer/HTMLDataFlavors/PutOnlyAllHtmlFlavorOnClipboard.java
jdk/test/java/awt/datatransfer/HTMLDataFlavors/PutSelectionAndFragmentHtmlFlavorsOnClipboard.java
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CDataTransferer.java	Fri Mar 22 19:56:20 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CDataTransferer.java	Wed Mar 27 16:19:51 2013 +0400
@@ -174,7 +174,7 @@
                 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 @@
     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.
      */
-    protected Image platformImageBytesOrStreamToImage(InputStream stream, byte[] bytes, long format) throws IOException {
-        byte[] imageData = bytes;
-
-        if (imageData == null)
-            imageData = inputStreamToByteArray(stream);
-
-        return getImageForByteStream(imageData);
+    protected Image platformImageBytesToImage(byte[] bytes, long format)
+        throws IOException
+    {
+        return getImageForByteStream(bytes);
     }
 
     private native Image getImageForByteStream(byte[] bytes);
--- a/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java	Fri Mar 22 19:56:20 2013 +0400
+++ b/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java	Wed Mar 27 16:19:51 2013 +0400
@@ -25,7 +25,6 @@
 
 package java.awt.datatransfer;
 
-import java.awt.Toolkit;
 import java.io.*;
 import java.nio.*;
 import java.util.*;
@@ -162,6 +161,18 @@
         }
     }
 
+    /*
+     * 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,
      * where:
@@ -246,6 +257,46 @@
     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
      * provided only for the purpose of supporting the
      * <code>Externalizable</code> interface.  It is not
@@ -949,24 +1000,35 @@
                 return false;
             }
 
-            if ("text".equals(getPrimaryType()) &&
-                DataTransferer.doesSubtypeSupportCharset(this) &&
-                representationClass != null &&
-                !(isRepresentationClassReader() ||
-                  String.class.equals(representationClass) ||
-                  isRepresentationClassCharBuffer() ||
-                  DataTransferer.charArrayClass.equals(representationClass)))
-            {
-                String thisCharset =
-                    DataTransferer.canonicalName(getParameter("charset"));
-                String thatCharset =
-                    DataTransferer.canonicalName(that.getParameter("charset"));
-                if (thisCharset == null) {
-                    if (thatCharset != null) {
-                        return false;
+            if ("text".equals(getPrimaryType())) {
+                if (DataTransferer.doesSubtypeSupportCharset(this) &&
+                    representationClass != null &&
+                    !(isRepresentationClassReader() ||
+                        String.class.equals(representationClass) ||
+                        isRepresentationClassCharBuffer() ||
+                        DataTransferer.charArrayClass.equals(representationClass)))
+                {
+                    String thisCharset =
+                        DataTransferer.canonicalName(getParameter("charset"));
+                    String thatCharset =
+                        DataTransferer.canonicalName(that.getParameter("charset"));
+                    if (thisCharset == null) {
+                        if (thatCharset != null) {
+                            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;
                     }
                 }
--- a/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java	Fri Mar 22 19:56:20 2013 +0400
+++ b/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java	Wed Mar 27 16:19:51 2013 +0400
@@ -41,7 +41,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedList;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -101,6 +101,11 @@
     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
      * a native should be synthesized, stored, and returned by encoding the
      * DataFlavor's MIME type in case if the DataFlavor is not found in
@@ -113,7 +118,7 @@
      * text DataFlavors).
      * 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
@@ -122,7 +127,7 @@
      *
      * @return nativeToFlavor
      */
-    private Map getNativeToFlavor() {
+    private Map<String, List<DataFlavor>> getNativeToFlavor() {
         if (!isMapInitialized) {
             initSystemFlavorMap();
         }
@@ -134,7 +139,7 @@
      * native Strings.
      * 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
@@ -421,14 +426,17 @@
                         }
                     }
 
-                    // For text/* flavors, store mappings in separate maps to
-                    // enable dynamic mapping generation at a run-time.
+                    final LinkedHashSet<DataFlavor> dfs = new LinkedHashSet<>();
+
+                    dfs.add(flavor);
+
                     if ("text".equals(flavor.getPrimaryType())) {
-                        store(value, key, getFlavorToNative());
-                        store(key, value, getNativeToFlavor());
-                    } else {
-                        store(flavor, key, getFlavorToNative());
-                        store(key, flavor, getNativeToFlavor());
+                        dfs.addAll(convertMimeTypeToDataFlavors(value));
+                    }
+
+                    for (DataFlavor df : dfs) {
+                        store(df, key, getFlavorToNative());
+                        store(key, df, getNativeToFlavor());
                     }
                 }
             }
@@ -530,7 +538,7 @@
      * only if the specified native is encoded as a Java MIME type.
      */
     private List nativeToFlavorLookup(String nat) {
-        List flavors = (List)getNativeToFlavor().get(nat);
+        List<DataFlavor> flavors = getNativeToFlavor().get(nat);
 
         if (nat != null && !disabledMappingGenerationKeys.contains(nat)) {
             DataTransferer transferer = DataTransferer.getInstance();
@@ -625,7 +633,7 @@
                 getNativesForFlavorCache.remove(flav);
                 getNativesForFlavorCache.remove(null);
 
-                List flavors = (List)getNativeToFlavor().get(encoded);
+                List<DataFlavor> flavors = getNativeToFlavor().get(encoded);
                 if (flavors == null) {
                     flavors = new ArrayList(1);
                     getNativeToFlavor().put(encoded, flavors);
@@ -681,7 +689,7 @@
         }
 
         if (flav == null) {
-            retval = new ArrayList(getNativeToFlavor().keySet());
+            retval = new ArrayList<String>(getNativeToFlavor().keySet());
         } else if (disabledMappingGenerationKeys.contains(flav)) {
             // In this case we shouldn't synthesize a native for this flavor,
             // since its mappings were explicitly specified.
@@ -809,140 +817,162 @@
             }
         }
 
-        LinkedList retval = new LinkedList();
+        final LinkedHashSet <DataFlavor> returnValue =
+            new LinkedHashSet<>();
 
         if (nat == null) {
-            List natives = getNativesForFlavor(null);
-            HashSet dups = new HashSet(natives.size());
+            final List<String> natives = getNativesForFlavor(null);
 
-            for (Iterator natives_iter = natives.iterator();
-                 natives_iter.hasNext(); )
+            for (String n : natives)
             {
-                List flavors =
-                    getFlavorsForNative((String)natives_iter.next());
-                for (Iterator flavors_iter = flavors.iterator();
-                     flavors_iter.hasNext(); )
+                final List<DataFlavor> flavors = getFlavorsForNative(n);
+
+                for (DataFlavor df : flavors)
                 {
-                    Object flavor = flavors_iter.next();
-                    if (dups.add(flavor)) {
-                        retval.add(flavor);
-                    }
+                    returnValue.add(df);
                 }
             }
         } else {
-            List flavors = nativeToFlavorLookup(nat);
+
+            final List<DataFlavor> flavors = nativeToFlavorLookup(nat);
 
             if (disabledMappingGenerationKeys.contains(nat)) {
                 return flavors;
             }
 
-            HashSet dups = new HashSet(flavors.size());
-
-            List flavorsAndbaseTypes = nativeToFlavorLookup(nat);
-
-            for (Iterator flavorsAndbaseTypes_iter =
-                     flavorsAndbaseTypes.iterator();
-                 flavorsAndbaseTypes_iter.hasNext(); )
-            {
-                Object value = flavorsAndbaseTypes_iter.next();
-                if (value instanceof String) {
-                    String baseType = (String)value;
-                    String subType = null;
-                    try {
-                        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) &&
-                            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 =
-                                 DataTransferer.standardEncodings();
-                             charset_iter.hasNext(); )
-                        {
-                            String charset = (String)charset_iter.next();
+            final List<DataFlavor> flavorsAndBaseTypes =
+                nativeToFlavorLookup(nat);
 
-                            for (int i = 0; i < ENCODED_TEXT_CLASSES.length;
-                                 i++)
-                            {
-                                DataFlavor toAdd = null;
-                                try {
-                                    toAdd = new DataFlavor
-                                        (baseType + ";charset=" + charset +
-                                         ";class=" + ENCODED_TEXT_CLASSES[i]);
-                                } catch (ClassNotFoundException cannotHappen) {
-                                }
-
-                                // 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 (toAdd.equals(DataFlavor.plainTextFlavor)) {
-                                    toAdd = DataFlavor.plainTextFlavor;
-                                }
-
-                                if (dups.add(toAdd)) {
-                                    retval.add(toAdd);
-                                }
-                            }
-                        }
-
-                        if (TEXT_PLAIN_BASE_TYPE.equals(baseType) &&
-                            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)) {
-                                retval.add(toAdd);
-                            }
-                        }
-                    }
-                } else {
-                    DataFlavor flavor = (DataFlavor)value;
-                    if (dups.add(flavor)) {
-                        retval.add(flavor);
+            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();
                     }
                 }
             }
+
+        }
+
+        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);
         }
 
-        ArrayList arrayList = new ArrayList(retval);
-        getFlavorsForNativeCache.put(nat, new SoftReference(arrayList));
-        return (List)arrayList.clone();
+        if (DataTransferer.doesSubtypeSupportCharset(subType, null)) {
+            if (TEXT_PLAIN_BASE_TYPE.equals(baseType))
+            {
+                returnValue.add(DataFlavor.stringFlavor);
+            }
+
+            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 {
+                        toAdd = new DataFlavor(mt);
+                    } catch (ClassNotFoundException cannotHappen) {
+                    }
+                    returnValue.add(toAdd);
+                }
+            }
+
+            for (String charset : DataTransferer.standardEncodings()) {
+
+                for (String encodedTextClass : ENCODED_TEXT_CLASSES) {
+                    final String mimeType =
+                            baseType + ";charset=" + charset +
+                            ";class=" + encodedTextClass;
+
+                    final LinkedHashSet<String> mimeTypes =
+                        handleHtmlMimeTypes(baseType, mimeType);
+
+                    for (String mt : mimeTypes) {
+
+                        DataFlavor df = null;
+
+                        try {
+                            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) {
+                        }
+
+                        returnValue.add(df);
+                    }
+                }
+            }
+
+            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;
+    }
+
+    private static final String [] htmlDocumntTypes =
+        new String [] {"all", "selection", "fragment"};
+
+    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;
     }
 
     /**
--- a/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java	Fri Mar 22 19:56:20 2013 +0400
+++ b/jdk/src/share/classes/sun/awt/datatransfer/DataTransferer.java	Wed Mar 27 16:19:51 2013 +0400
@@ -171,12 +171,12 @@
      * Lazy initialization of Standard Encodings.
      */
     private static class StandardEncodingsHolder {
-        private static final SortedSet standardEncodings = load();
-
-        private static SortedSet load() {
+        private static final SortedSet<String> standardEncodings = load();
+
+        private static SortedSet<String> load() {
             final Comparator comparator =
                     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("ISO-8859-1");
             tempSet.add("UTF-8");
@@ -523,8 +523,8 @@
      * So as to avoid loading all available character converters, optional,
      * non-standard, character sets are not included.
      */
-    public static Iterator standardEncodings() {
-        return StandardEncodingsHolder.standardEncodings.iterator();
+    public static Set <String> standardEncodings() {
+        return StandardEncodingsHolder.standardEncodings;
     }
 
     /**
@@ -1068,17 +1068,10 @@
      *
      * Native to Java string conversion
      */
-    private String translateBytesOrStreamToString(InputStream str,  byte[] bytes,
-                                                    long format,
-                                                    Transferable localeTransferable)
+    private String translateBytesToString(byte[] bytes, long format,
+                                          Transferable localeTransferable)
             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);
         String charset = getBestCharsetForTextFormat(lFormat, localeTransferable);
@@ -1221,13 +1214,13 @@
                     ("cannot transfer non-text data as Reader");
             }
 
-            Reader r = (Reader)obj;
             StringBuffer buf = new StringBuffer();
-            int c;
-            while ((c = r.read()) != -1) {
-                buf.append((char)c);
+            try (Reader r = (Reader)obj) {
+                int c;
+                while ((c = r.read()) != -1) {
+                    buf.append((char)c);
+                }
             }
-            r.close();
 
             return translateTransferableString(
                 buf.toString(),
@@ -1309,7 +1302,7 @@
             return bytes;
         }
 
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        byte[] theByteArray = null;
 
         // Target data is a file list. Source data must be a
         // java.util.List which contains java.io.File or String instances.
@@ -1324,8 +1317,9 @@
 
             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
         // java.util.List which contains java.io.File or String instances.
@@ -1360,57 +1354,72 @@
               }
 
             byte[] eoln = "\r\n".getBytes(targetCharset);
-            for (int i = 0; i < uriList.size(); i++) {
-                byte[] bytes = uriList.get(i).getBytes(targetCharset);
-                bos.write(bytes, 0, bytes.length);
-                bos.write(eoln, 0, eoln.length);
+
+            try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
+                for (int i = 0; i < uriList.size(); i++) {
+                    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
         // 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.
         } else if (flavor.isRepresentationClassInputStream()) {
-            InputStream is = (InputStream)obj;
-            boolean eof = false;
-            int avail = is.available();
-            byte[] tmp = new byte[avail > 8192 ? avail : 8192];
-            do {
-                int ret;
-                if (!(eof = (ret = is.read(tmp, 0, tmp.length)) == -1)) {
-                    bos.write(tmp, 0, ret);
+            try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
+                try (InputStream is = (InputStream)obj) {
+                    boolean eof = false;
+                    int avail = is.available();
+                    byte[] tmp = new byte[avail > 8192 ? avail : 8192];
+                    do {
+                        int aValue;
+                        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)) {
-                byte[] bytes = bos.toByteArray();
-                bos.close();
-                String sourceEncoding = DataTransferer.getTextCharset(flavor);
-                return translateTransferableString(
-                    new String(bytes, sourceEncoding),
-                    format);
+
+                if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
+                    byte[] bytes = bos.toByteArray();
+                    String sourceEncoding = DataTransferer.getTextCharset(flavor);
+                    return translateTransferableString(
+                               new String(bytes, sourceEncoding),
+                               format);
+                }
+                theByteArray = bos.toByteArray();
             }
 
+
+
         // Source data is an RMI object
         } else if (flavor.isRepresentationClassRemote()) {
+
             Object mo = RMI.newMarshalledObject(obj);
-            ObjectOutputStream oos = new ObjectOutputStream(bos);
-            oos.writeObject(mo);
-            oos.close();
-
-        // Source data is Serializable
+            theByteArray = convertObjectToBytes(mo);
+
+            // Source data is Serializable
         } else if (flavor.isRepresentationClassSerializable()) {
-            ObjectOutputStream oos = new ObjectOutputStream(bos);
-            oos.writeObject(obj);
-            oos.close();
+
+            theByteArray = convertObjectToBytes(obj);
 
         } else {
             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;
@@ -1565,38 +1574,8 @@
                                  long format, Transferable localeTransferable)
         throws IOException
     {
-        return translateBytesOrStream(null, bytes, flavor, format,
-                                      localeTransferable);
-    }
-
-    public Object translateStream(InputStream str, DataFlavor flavor,
-                                  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);
-        }
+
+        Object theObject = null;
 
         // Source data is a file list. Use the dragQueryFile native function to
         // do most of the decoding. Then wrap File objects around the String
@@ -1605,12 +1584,8 @@
             if (!DataFlavor.javaFileListFlavor.equals(flavor)) {
                 throw new IOException("data translation failed");
             }
-            if (bytes == null) {
-                bytes = inputStreamToByteArray(str);
-            }
             String[] filenames = dragQueryFile(bytes);
             if (filenames == null) {
-                str.close();
                 return null;
             }
 
@@ -1619,178 +1594,203 @@
             for (int i = 0; i < filenames.length; i++) {
                 files[i] = new File(filenames[i]);
             }
-            str.close();
 
             // Turn the list of Files into a List and return
-            return Arrays.asList(files);
-
-        // Source data is a URI list. Convert to DataFlavor.javaFileListFlavor
-        // where possible.
-        } 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.
+            theObject = Arrays.asList(files);
+
+            // Target data is a String. Strip terminating NUL bytes. Decode bytes
+            // into characters. Search-and-replace EOLN.
         } else if (String.class.equals(flavor.getRepresentationClass()) &&
-                   isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
-
-            return translateBytesOrStreamToString(
-                str, bytes,
-                format, localeTransferable);
-
-        // 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)) {
-            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.
+                       isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
+
+            theObject = translateBytesToString(bytes, 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");
+            try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
+                theObject = translateStream(bais,
+                        flavor, format, localeTransferable);
             }
-
-            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.
+            // Target data is a CharBuffer. Recur to obtain String and wrap.
         } else if (flavor.isRepresentationClassCharBuffer()) {
             if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
                 throw new IOException
-                    ("cannot transfer non-text data as CharBuffer");
+                          ("cannot transfer non-text data as CharBuffer");
             }
 
-            CharBuffer buffer = CharBuffer.wrap(translateBytesOrStreamToString(
-                str, bytes,
-                format, localeTransferable));
-
-            return constructFlavoredObject(buffer, flavor, CharBuffer.class);
-
-        // Target data is a char array. Recur to obtain String and convert to
-        // char array.
+            CharBuffer buffer = CharBuffer.wrap(
+                translateBytesToString(bytes,format, localeTransferable));
+
+            theObject = constructFlavoredObject(buffer, flavor, CharBuffer.class);
+
+            // Target data is a char array. Recur to obtain String and convert to
+            // char array.
         } else if (charArrayClass.equals(flavor.getRepresentationClass())) {
             if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
                 throw new IOException
-                    ("cannot transfer non-text data as char array");
+                          ("cannot transfer non-text data as char array");
             }
 
-            return translateBytesOrStreamToString(
-                    str, bytes,
-                    format, localeTransferable).toCharArray();
-
-        // Target data is a ByteBuffer. For arbitrary flavors, just return
-        // the raw bytes. For text flavors, convert to a String to strip
-        // terminators and search-and-replace EOLN, then reencode according to
-        // the requested flavor.
+            theObject = translateBytesToString(
+                bytes, format, localeTransferable).toCharArray();
+
+            // Target data is a ByteBuffer. For arbitrary flavors, just return
+            // the raw bytes. For text flavors, convert to a String to strip
+            // terminators and search-and-replace EOLN, then reencode according to
+            // the requested flavor.
         } else if (flavor.isRepresentationClassByteBuffer()) {
             if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
-                bytes = translateBytesOrStreamToString(
-                    str, bytes,
-                    format, localeTransferable
-                ).getBytes(
-                    DataTransferer.getTextCharset(flavor)
-                );
-            } else {
-                if (bytes == null) {
-                    bytes = inputStreamToByteArray(str);
-                }
+                bytes = translateBytesToString(
+                    bytes, format, localeTransferable).getBytes(
+                        DataTransferer.getTextCharset(flavor)
+                    );
             }
 
             ByteBuffer buffer = ByteBuffer.wrap(bytes);
-            return constructFlavoredObject(buffer, flavor, ByteBuffer.class);
-
-        // Target data is a byte array. For arbitrary flavors, just return
-        // the raw bytes. For text flavors, convert to a String to strip
-        // terminators and search-and-replace EOLN, then reencode according to
-        // the requested flavor.
+            theObject = constructFlavoredObject(buffer, flavor, ByteBuffer.class);
+
+            // Target data is a byte array. For arbitrary flavors, just return
+            // the raw bytes. For text flavors, convert to a String to strip
+            // terminators and search-and-replace EOLN, then reencode according to
+            // the requested flavor.
         } else if (byteArrayClass.equals(flavor.getRepresentationClass())) {
             if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
-                return translateBytesOrStreamToString(
-                    str, bytes,
-                    format, localeTransferable
-                ).getBytes(
-                    DataTransferer.getTextCharset(flavor)
-                );
+                theObject = translateBytesToString(
+                    bytes, format, localeTransferable
+                ).getBytes(DataTransferer.getTextCharset(flavor));
             } else {
-                return (bytes != null) ? bytes : inputStreamToByteArray(str);
+                theObject = bytes;
             }
 
-        // Target data is an RMI object
-        } else if (flavor.isRepresentationClassRemote()) {
-            try {
-                byte[] ba = inputStreamToByteArray(str);
-                ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(ba));
-                Object ret = RMI.getMarshalledObject(ois.readObject());
-                ois.close();
-                str.close();
-                return ret;
-            } catch (Exception e) {
-                throw new IOException(e.getMessage());
+            // 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()) {
+
+            try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
+                theObject = translateStream(bais, flavor, format, localeTransferable);
             }
 
-        // Target data is Serializable
+            // Target data is Serializable
         } else if (flavor.isRepresentationClassSerializable()) {
-            try {
-                byte[] ba = inputStreamToByteArray(str);
-                ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(ba));
-                Object ret = ois.readObject();
-                ois.close();
-                str.close();
-                return ret;
-            } catch (Exception e) {
-                throw new IOException(e.getMessage());
+
+            try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
+                theObject = translateStream(bais, flavor, format, localeTransferable);
             }
 
-        // Target data is Image
+            // Target data is Image
         } else if (DataFlavor.imageFlavor.equals(flavor)) {
             if (!isImageFormat(format)) {
                 throw new IOException("data translation failed");
             }
 
-            Image image = platformImageBytesOrStreamToImage(str, bytes, format);
-            str.close();
-            return image;
+            theObject = platformImageBytesToImage(bytes, format);
+        }
+
+        if (theObject == null) {
+            throw new IOException("data translation failed");
         }
 
-        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());
+            }
+        }
+
+
+        return theObject;
+
     }
 
     /**
@@ -1798,7 +1798,7 @@
      * ReencodingInputStream will decode and reencode the InputStream on demand
      * so that we can strip terminators and search-and-replace EOLN.
      */
-    private Object translateBytesOrStreamToInputStream
+    private Object translateStreamToInputStream
         (InputStream str, DataFlavor flavor, long format,
          Transferable localeTransferable) throws IOException
     {
@@ -2054,7 +2054,6 @@
      * Decodes URIs from either a byte array or a stream.
      */
     protected URI[] dragQueryURIs(InputStream stream,
-                                  byte[] bytes,
                                   long format,
                                   Transferable localeTransferable)
       throws IOException
@@ -2067,10 +2066,10 @@
      * Translates either a byte array or an input stream which contain
      * platform-specific image data in the given format into an Image.
      */
-    protected abstract Image platformImageBytesOrStreamToImage(InputStream str,
-                                                               byte[] bytes,
-                                                               long format)
-      throws IOException;
+
+
+    protected abstract Image platformImageBytesToImage(
+        byte[] bytes,long format) throws IOException;
 
     /**
      * Translates either a byte array or an input stream which contain
@@ -2078,13 +2077,9 @@
      *
      * @param mimeType image MIME type, such as: image/png, image/jpeg, image/gif
      */
-    protected Image standardImageBytesOrStreamToImage(InputStream inputStream,
-                                                      byte[] bytes,
-                                                      String mimeType)
-      throws IOException {
-        if (inputStream == null) {
-            inputStream = new ByteArrayInputStream(bytes);
-        }
+    protected Image standardImageBytesToImage(
+        byte[] bytes, String mimeType) throws IOException
+    {
 
         Iterator readerIterator = ImageIO.getImageReadersByMIMEType(mimeType);
 
@@ -2097,9 +2092,9 @@
 
         while (readerIterator.hasNext()) {
             ImageReader imageReader = (ImageReader)readerIterator.next();
-            try {
+            try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
                 ImageInputStream imageInputStream =
-                    ImageIO.createImageInputStream(inputStream);
+                    ImageIO.createImageInputStream(bais);
 
                 try {
                     ImageReadParam param = imageReader.getDefaultReadParam();
@@ -2456,15 +2451,16 @@
     protected static byte[] inputStreamToByteArray(InputStream str)
         throws IOException
     {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        int len = 0;
-        byte[] buf = new byte[8192];
-
-        while ((len = str.read(buf)) != -1) {
-            baos.write(buf, 0, len);
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            int len = 0;
+            byte[] buf = new byte[8192];
+
+            while ((len = str.read(buf)) != -1) {
+                baos.write(buf, 0, len);
+            }
+
+            return baos.toByteArray();
         }
-
-        return baos.toByteArray();
     }
 
     /**
--- a/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java	Fri Mar 22 19:56:20 2013 +0400
+++ b/jdk/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java	Wed Mar 27 16:19:51 2013 +0400
@@ -57,7 +57,6 @@
 import sun.awt.SunToolkit;
 import sun.awt.datatransfer.DataTransferer;
 import sun.awt.datatransfer.ToolkitThreadBlockedHandler;
-import sun.security.util.SecurityConstants;
 
 /**
  * <p>
@@ -260,6 +259,7 @@
         }
 
         final long format = lFormat.longValue();
+
         Object ret = getNativeData(format);
 
         if (ret instanceof byte[]) {
@@ -270,11 +270,14 @@
                 throw new InvalidDnDOperationException(e.getMessage());
             }
         } else if (ret instanceof InputStream) {
+            InputStream inputStream = (InputStream)ret;
             try {
                 return DataTransferer.getInstance().
-                    translateStream((InputStream)ret, df, format, this);
+                    translateStream(inputStream, df, format, this);
             } catch (IOException e) {
                 throw new InvalidDnDOperationException(e.getMessage());
+            } finally {
+                inputStream.close();
             }
         } else {
             throw new IOException("no native data was transfered");
--- a/jdk/src/solaris/classes/sun/awt/X11/XDataTransferer.java	Fri Mar 22 19:56:20 2013 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XDataTransferer.java	Wed Mar 27 16:19:51 2013 +0400
@@ -212,10 +212,9 @@
      * Translates either a byte array or an input stream which contain
      * platform-specific image data in the given format into an Image.
      */
-    protected Image platformImageBytesOrStreamToImage(InputStream inputStream,
-                                                      byte[] bytes,
-                                                      long format)
-      throws IOException {
+    protected Image platformImageBytesToImage(
+        byte[] bytes, long format) throws IOException
+    {
         String mimeType = null;
         if (format == PNG_ATOM.getAtom()) {
             mimeType = "image/png";
@@ -235,7 +234,7 @@
             }
         }
         if (mimeType != null) {
-            return standardImageBytesOrStreamToImage(inputStream, bytes, mimeType);
+            return standardImageBytesToImage(bytes, mimeType);
         } else {
             String nativeFormat = getNativeForFormat(format);
             throw new IOException("Translation from " + nativeFormat +
@@ -330,8 +329,8 @@
      * 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.
      */
-    public List getPlatformMappingsForNative(String nat) {
-        List flavors = new ArrayList();
+    public List <DataFlavor> getPlatformMappingsForNative(String nat) {
+        List <DataFlavor> flavors = new ArrayList();
 
         if (nat == null) {
             return flavors;
@@ -346,16 +345,14 @@
             return flavors;
         }
 
-        Object value = df;
+        DataFlavor value = df;
         final String primaryType = df.getPrimaryType();
         final String baseType = primaryType + "/" + df.getSubType();
 
         // For text formats we map natives to MIME strings instead of data
         // flavors to enable dynamic text native-to-flavor mapping generation.
         // See SystemFlavorMap.getFlavorsForNative() for details.
-        if ("text".equals(primaryType)) {
-            value = primaryType + "/" + df.getSubType();
-        } else if ("image".equals(primaryType)) {
+        if ("image".equals(primaryType)) {
             Iterator readers = ImageIO.getImageReadersByMIMEType(baseType);
             if (readers.hasNext()) {
                 flavors.add(DataFlavor.imageFlavor);
@@ -438,16 +435,13 @@
                 }
             }
         } else if (DataTransferer.isFlavorCharsetTextType(df)) {
-            final Iterator iter = DataTransferer.standardEncodings();
-
             // stringFlavor is semantically equivalent to the standard
             // "text/plain" MIME type.
             if (DataFlavor.stringFlavor.equals(df)) {
                 baseType = "text/plain";
             }
 
-            while (iter.hasNext()) {
-                String encoding = (String)iter.next();
+            for (String encoding : DataTransferer.standardEncodings()) {
                 if (!encoding.equals(charset)) {
                     natives.add(baseType + ";charset=" + encoding);
                 }
--- a/jdk/src/windows/classes/sun/awt/windows/WDataTransferer.java	Fri Mar 22 19:56:20 2013 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/WDataTransferer.java	Wed Mar 27 16:19:51 2013 +0400
@@ -87,35 +87,35 @@
  */
 public class WDataTransferer extends DataTransferer {
     private static final String[] predefinedClipboardNames = {
-        "",
-        "TEXT",
-        "BITMAP",
-        "METAFILEPICT",
-        "SYLK",
-        "DIF",
-        "TIFF",
-        "OEM TEXT",
-        "DIB",
-        "PALETTE",
-        "PENDATA",
-        "RIFF",
-        "WAVE",
-        "UNICODE TEXT",
-        "ENHMETAFILE",
-        "HDROP",
-        "LOCALE",
-        "DIBV5"
+            "",
+            "TEXT",
+            "BITMAP",
+            "METAFILEPICT",
+            "SYLK",
+            "DIF",
+            "TIFF",
+            "OEM TEXT",
+            "DIB",
+            "PALETTE",
+            "PENDATA",
+            "RIFF",
+            "WAVE",
+            "UNICODE TEXT",
+            "ENHMETAFILE",
+            "HDROP",
+            "LOCALE",
+            "DIBV5"
     };
 
     private static final Map <String, Long> predefinedClipboardNameMap;
     static {
         Map <String,Long> tempMap =
-            new HashMap <> (predefinedClipboardNames.length, 1.0f);
+                new HashMap <> (predefinedClipboardNames.length, 1.0f);
         for (int i = 1; i < predefinedClipboardNames.length; i++) {
             tempMap.put(predefinedClipboardNames[i], Long.valueOf(i));
         }
         predefinedClipboardNameMap =
-            Collections.synchronizedMap(tempMap);
+                Collections.synchronizedMap(tempMap);
     }
 
     /**
@@ -138,18 +138,18 @@
     //CF_FILECONTENTS supported as mandatory associated clipboard
 
     private static final Long L_CF_LOCALE =
-      predefinedClipboardNameMap.get(predefinedClipboardNames[CF_LOCALE]);
+            predefinedClipboardNameMap.get(predefinedClipboardNames[CF_LOCALE]);
 
     private static final DirectColorModel directColorModel =
-        new DirectColorModel(24,
-                             0x00FF0000,  /* red mask   */
-                             0x0000FF00,  /* green mask */
-                             0x000000FF); /* blue mask  */
+            new DirectColorModel(24,
+                    0x00FF0000,  /* red mask   */
+                    0x0000FF00,  /* green mask */
+                    0x000000FF); /* blue mask  */
 
     private static final int[] bandmasks = new int[] {
-        directColorModel.getRedMask(),
-        directColorModel.getGreenMask(),
-        directColorModel.getBlueMask() };
+            directColorModel.getRedMask(),
+            directColorModel.getGreenMask(),
+            directColorModel.getBlueMask() };
 
     /**
      * Singleton constructor
@@ -171,10 +171,10 @@
     }
 
     public SortedMap <Long, DataFlavor> getFormatsForFlavors(
-        DataFlavor[] flavors, FlavorTable map)
+            DataFlavor[] flavors, FlavorTable map)
     {
         SortedMap <Long, DataFlavor> retval =
-            super.getFormatsForFlavors(flavors, map);
+                super.getFormatsForFlavors(flavors, map);
 
         // The Win32 native code does not support exporting LOCALE data, nor
         // should it.
@@ -191,32 +191,60 @@
                                         DataFlavor flavor,
                                         long format) throws IOException
     {
-        byte[] bytes = super.translateTransferable(contents, flavor, format);
-
+        byte[] bytes = null;
         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;
     }
 
-    protected Object translateBytesOrStream(InputStream str, byte[] bytes,
-                                            DataFlavor flavor, long format,
-                                            Transferable localeTransferable)
+    // The stream is closed as a closable object
+    public Object translateStream(InputStream str,
+                                 DataFlavor flavor, long format,
+                                 Transferable localeTransferable)
         throws IOException
     {
         if (format == CF_HTML && flavor.isFlavorTextType()) {
-            if (str == null) {
-                str = new ByteArrayInputStream(bytes);
-                bytes = null;
-            }
+            str = new HTMLCodec(str,
+                                 EHTMLReadMode.getEHTMLReadMode(flavor));
+
+        }
+        return super.translateStream(str, flavor, format,
+                                        localeTransferable);
 
-            str = new HTMLCodec(str,  EHTMLReadMode.HTML_READ_SELECTION);
-        }
+    }
+
+    public Object translateBytes(byte[] bytes, DataFlavor flavor, long format,
+        Transferable localeTransferable) throws IOException
+    {
+
 
         if (format == CF_FILEGROUPDESCRIPTORA || format == CF_FILEGROUPDESCRIPTORW) {
-            if (null != str ) {
-                str.close();
-            }
             if (bytes == null || !DataFlavor.javaFileListFlavor.equals(flavor)) {
                 throw new IOException("data translation failed");
             }
@@ -238,28 +266,24 @@
         }
 
         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();
             if (localeTransferable != null && localeTransferable.
-                isDataFlavorSupported(javaTextEncodingFlavor))
+                                                                    isDataFlavorSupported(javaTextEncodingFlavor))
             {
                 try {
                     charset = new String((byte[])localeTransferable.
-                                   getTransferData(javaTextEncodingFlavor),
-                                   "UTF-8");
+                        getTransferData(javaTextEncodingFlavor), "UTF-8");
                 } catch (UnsupportedFlavorException cannotHappen) {
                 }
             }
             return new URL(new String(bytes, charset));
         }
 
-        return super.translateBytesOrStream(str, bytes, flavor, format,
-                                            localeTransferable);
+        return super.translateBytes(bytes , flavor, format,
+                                        localeTransferable);
+
     }
 
     public boolean isLocaleDependentTextFormat(long format) {
@@ -280,18 +304,18 @@
 
     protected String getNativeForFormat(long format) {
         return (format < predefinedClipboardNames.length)
-            ? predefinedClipboardNames[(int)format]
-            : getClipboardFormatName(format);
+                ? predefinedClipboardNames[(int)format]
+                : getClipboardFormatName(format);
     }
 
     private final ToolkitThreadBlockedHandler handler =
-        new WToolkitThreadBlockedHandler();
+            new WToolkitThreadBlockedHandler();
 
     public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() {
         return handler;
     }
 
-   /**
+    /**
      * Calls the Win32 RegisterClipboardFormat function to register
      * a non-standard format.
      */
@@ -305,12 +329,12 @@
 
     public boolean isImageFormat(long format) {
         return format == CF_DIB || format == CF_ENHMETAFILE ||
-               format == CF_METAFILEPICT || format == CF_PNG ||
-               format == CF_JFIF;
+                format == CF_METAFILEPICT || format == CF_PNG ||
+                format == CF_JFIF;
     }
 
     protected byte[] imageToPlatformBytes(Image image, long format)
-      throws IOException {
+            throws IOException {
         String mimeType = null;
         if (format == CF_PNG) {
             mimeType = "image/png";
@@ -352,11 +376,11 @@
         int[] nBits = {8, 8, 8};
         int[] bOffs = {2, 1, 0};
         ColorModel colorModel =
-            new ComponentColorModel(cs, nBits, false, false,
-                                    Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
+                new ComponentColorModel(cs, nBits, false, false,
+                        Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
         WritableRaster raster =
-            Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height,
-                                           width * 3 + pad, 3, bOffs, null);
+                Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height,
+                        width * 3 + pad, 3, bOffs, null);
 
         BufferedImage bimage = new BufferedImage(colorModel, raster, false, null);
 
@@ -364,7 +388,7 @@
         // top-down DIBs.
         // So we flip the image vertically and create a bottom-up DIB.
         AffineTransform imageFlipTransform =
-            new AffineTransform(1, 0, 0, -1, 0, height);
+                new AffineTransform(1, 0, 0, -1, 0, height);
 
         Graphics2D g2d = bimage.createGraphics();
 
@@ -383,7 +407,7 @@
     private static final byte [] UNICODE_NULL_TERMINATOR =  new byte [] {0,0};
 
     protected ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList)
-        throws IOException
+            throws IOException
     {
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
 
@@ -407,10 +431,10 @@
         return bos;
     }
 
-   /**
-    * Returns a byte array which contains data special for the given format
-    * and for the given image data.
-    */
+    /**
+     * Returns a byte array which contains data special for the given format
+     * and for the given image data.
+     */
     private native byte[] imageDataToPlatformImageBytes(byte[] imageData,
                                                         int width, int height,
                                                         long format);
@@ -419,10 +443,8 @@
      * Translates either a byte array or an input stream which contain
      * platform-specific image data in the given format into an Image.
      */
-    protected Image platformImageBytesOrStreamToImage(InputStream str,
-                                                      byte[] bytes,
-                                                      long format)
-      throws IOException {
+    protected Image platformImageBytesToImage(byte[] bytes, long format)
+            throws IOException {
         String mimeType = null;
         if (format == CF_PNG) {
             mimeType = "image/png";
@@ -430,11 +452,7 @@
             mimeType = "image/jpeg";
         }
         if (mimeType != null) {
-            return standardImageBytesOrStreamToImage(str, bytes, mimeType);
-        }
-
-        if (bytes == null) {
-            bytes = inputStreamToByteArray(str);
+            return standardImageBytesToImage(bytes, mimeType);
         }
 
         int[] imageData = platformImageBytesToImageData(bytes, format);
@@ -448,8 +466,8 @@
 
         DataBufferInt buffer = new DataBufferInt(imageData, len);
         WritableRaster raster = Raster.createPackedRaster(buffer, width,
-                                                          height, width,
-                                                          bandmasks, null);
+                height, width,
+                bandmasks, null);
 
         return new BufferedImage(directColorModel, raster, false, null);
     }
@@ -462,13 +480,13 @@
      */
     private native int[] platformImageBytesToImageData(byte[] bytes,
                                                        long format)
-      throws IOException;
+            throws IOException;
 
     protected native String[] dragQueryFile(byte[] bytes);
 }
 
 final class WToolkitThreadBlockedHandler extends Mutex
-                       implements ToolkitThreadBlockedHandler {
+        implements ToolkitThreadBlockedHandler {
 
     public void enter() {
         if (!isOwned()) {
@@ -492,7 +510,22 @@
 enum EHTMLReadMode {
     HTML_READ_ALL,
     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 @@
                     htmlSuffix = "</BODY>" + htmlSuffix;
                 };
             };
-            htmlPrefix = htmlPrefix + START_FRAGMENT_CMT;
-            htmlSuffix = END_FRAGMENT_CMT + htmlSuffix;
         }
 
         String stBaseUrl = DEF_SOURCE_URL;
         int nStartHTML =
-            VERSION.length() + VERSION_NUM.length() + EOLN.length()
-            + START_HTML.length() + PADDED_WIDTH + EOLN.length()
-            + END_HTML.length() + PADDED_WIDTH + EOLN.length()
-            + START_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
-            + END_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
-            + SOURCE_URL.length() + stBaseUrl.length() + EOLN.length()
-            ;
+                VERSION.length() + VERSION_NUM.length() + EOLN.length()
+                        + START_HTML.length() + PADDED_WIDTH + EOLN.length()
+                        + END_HTML.length() + PADDED_WIDTH + EOLN.length()
+                        + START_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
+                        + END_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
+                        + SOURCE_URL.length() + stBaseUrl.length() + EOLN.length()
+                ;
         int nStartFragment = nStartHTML + htmlPrefix.length();
         int nEndFragment = nStartFragment + bytes.length - 1;
         int nEndHTML = nEndFragment + htmlSuffix.length();
 
         StringBuilder header = new StringBuilder(
-            nStartFragment
-            + START_FRAGMENT_CMT.length()
+                nStartFragment
+                        + START_FRAGMENT_CMT.length()
         );
         //header
         header.append(VERSION);
@@ -639,14 +670,14 @@
         }
 
         byte[] retval = new byte[headerBytes.length + bytes.length +
-                                 trailerBytes.length];
+                trailerBytes.length];
 
         System.arraycopy(headerBytes, 0, retval, 0, headerBytes.length);
         System.arraycopy(bytes, 0, retval, headerBytes.length,
-                       bytes.length - 1);
+                bytes.length - 1);
         System.arraycopy(trailerBytes, 0, retval,
-                         headerBytes.length + bytes.length - 1,
-                         trailerBytes.length);
+                headerBytes.length + bytes.length - 1,
+                trailerBytes.length);
         retval[retval.length-1] = 0;
 
         return retval;
@@ -659,7 +690,7 @@
     private boolean descriptionParsed = 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;
 
     // CharToByteUTF8.getMaxBytesPerChar returns 3, so we should not buffer
@@ -667,30 +698,30 @@
     public static final int CHAR_BUFFER_LEN = BYTE_BUFFER_LEN / 3;
 
     private static final String FAILURE_MSG =
-        "Unable to parse HTML description: ";
+            "Unable to parse HTML description: ";
     private static final String INVALID_MSG =
-        " invalid";
+            " invalid";
 
     //HTML header mapping:
     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
-                   iFragStart,// StartFragment -- shift in array jast after <!--StartFragment-->
-                   iFragEnd,  // EndFragment -- shift in array before start <!--EndFragment-->
-                   iSelStart, // StartSelection -- shift in array of the first char in copied selection
-                   iSelEnd;   // EndSelection -- shift in array of the last char in copied selection
+            iHTMLEnd,  // EndHTML -- shift in array of last byte for HTML syntax analysis
+            iFragStart,// StartFragment -- shift in array jast after <!--StartFragment-->
+            iFragEnd,  // EndFragment -- shift in array before start <!--EndFragment-->
+            iSelStart, // StartSelection -- shift in array of the first 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 stVersion; // Version -- current supported version
 
     //Stream reader markers:
     private long iStartOffset,
-                 iEndOffset,
-                 iReadCount;
+            iEndOffset,
+            iReadCount;
 
     private EHTMLReadMode readMode;
 
     public HTMLCodec(
-        InputStream _bytestream,
-        EHTMLReadMode _readMode) throws IOException
+            InputStream _bytestream,
+            EHTMLReadMode _readMode) throws IOException
     {
         bufferedStream = new BufferedInputStream(_bytestream, BYTE_BUFFER_LEN);
         readMode = _readMode;
@@ -723,31 +754,31 @@
         // initialization of array offset pointers
         // to the same "uninitialized" state.
         iHTMLEnd =
-            iHTMLStart =
-                iFragEnd =
-                    iFragStart =
-                        iSelEnd =
-                            iSelStart = -1;
+                iHTMLStart =
+                        iFragEnd =
+                                iFragStart =
+                                        iSelEnd =
+                                                iSelStart = -1;
 
         bufferedStream.mark(BYTE_BUFFER_LEN);
         String astEntries[] = new String[] {
-            //common
-            VERSION,
-            START_HTML,
-            END_HTML,
-            START_FRAGMENT,
-            END_FRAGMENT,
-            //ver 1.0
-            START_SELECTION,
-            END_SELECTION,
-            SOURCE_URL
+                //common
+                VERSION,
+                START_HTML,
+                END_HTML,
+                START_FRAGMENT,
+                END_FRAGMENT,
+                //ver 1.0
+                START_SELECTION,
+                END_SELECTION,
+                SOURCE_URL
         };
         BufferedReader bufferedReader = new BufferedReader(
-            new InputStreamReader(
-                bufferedStream,
-                ENCODING
-            ),
-            CHAR_BUFFER_LEN
+                new InputStreamReader(
+                        bufferedStream,
+                        ENCODING
+                ),
+                CHAR_BUFFER_LEN
         );
         long iHeadSize = 0;
         long iCRSize = EOLN.length();
@@ -769,30 +800,30 @@
                 if( null!=stValue ) {
                     try{
                         switch( iEntry ){
-                        case 0:
-                            stVersion = stValue;
-                            break;
-                        case 1:
-                            iHTMLStart = Integer.parseInt(stValue);
-                            break;
-                        case 2:
-                            iHTMLEnd = Integer.parseInt(stValue);
-                            break;
-                        case 3:
-                            iFragStart = Integer.parseInt(stValue);
-                            break;
-                        case 4:
-                            iFragEnd = Integer.parseInt(stValue);
-                            break;
-                        case 5:
-                            iSelStart = Integer.parseInt(stValue);
-                            break;
-                        case 6:
-                            iSelEnd = Integer.parseInt(stValue);
-                            break;
-                        case 7:
-                            stBaseURL = stValue;
-                            break;
+                            case 0:
+                                stVersion = stValue;
+                                break;
+                            case 1:
+                                iHTMLStart = Integer.parseInt(stValue);
+                                break;
+                            case 2:
+                                iHTMLEnd = Integer.parseInt(stValue);
+                                break;
+                            case 3:
+                                iFragStart = Integer.parseInt(stValue);
+                                break;
+                            case 4:
+                                iFragEnd = Integer.parseInt(stValue);
+                                break;
+                            case 5:
+                                iSelStart = Integer.parseInt(stValue);
+                                break;
+                            case 6:
+                                iSelEnd = Integer.parseInt(stValue);
+                                break;
+                            case 7:
+                                stBaseURL = stValue;
+                                break;
                         };
                     } catch ( NumberFormatException e ) {
                         throw new IOException(FAILURE_MSG + astEntries[iEntry]+ " value " + e + INVALID_MSG);
@@ -816,19 +847,19 @@
 
         //one of possible modes
         switch( readMode ){
-        case HTML_READ_ALL:
-            iStartOffset = iHTMLStart;
-            iEndOffset = iHTMLEnd;
-            break;
-        case HTML_READ_FRAGMENT:
-            iStartOffset = iFragStart;
-            iEndOffset = iFragEnd;
-            break;
-        case HTML_READ_SELECTION:
-        default:
-            iStartOffset = iSelStart;
-            iEndOffset = iSelEnd;
-            break;
+            case HTML_READ_ALL:
+                iStartOffset = iHTMLStart;
+                iEndOffset = iHTMLEnd;
+                break;
+            case HTML_READ_FRAGMENT:
+                iStartOffset = iFragStart;
+                iEndOffset = iFragEnd;
+                break;
+            case HTML_READ_SELECTION:
+            default:
+                iStartOffset = iSelStart;
+                iEndOffset = iSelEnd;
+                break;
         }
 
         bufferedStream.reset();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/datatransfer/HTMLDataFlavors/HTMLDataFlavorTest.java	Wed Mar 27 16:19:51 2013 +0400
@@ -0,0 +1,188 @@
+/*
+ * 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.");
+
+
+            }
+        }
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/datatransfer/HTMLDataFlavors/HtmlTransferable.java	Wed Mar 27 16:19:51 2013 +0400
@@ -0,0 +1,113 @@
+/*
+ * 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);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.html	Wed Mar 27 16:19:51 2013 +0400
@@ -0,0 +1,20 @@
+<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>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.java	Wed Mar 27 16:19:51 2013 +0400
@@ -0,0 +1,292 @@
+/*
+ * 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/datatransfer/HTMLDataFlavors/PutAllHtmlFlavorsOnClipboard.java	Wed Mar 27 16:19:51 2013 +0400
@@ -0,0 +1,34 @@
+/*
+ * 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");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/datatransfer/HTMLDataFlavors/PutOnlyAllHtmlFlavorOnClipboard.java	Wed Mar 27 16:19:51 2013 +0400
@@ -0,0 +1,35 @@
+/*
+ * 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");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/datatransfer/HTMLDataFlavors/PutSelectionAndFragmentHtmlFlavorsOnClipboard.java	Wed Mar 27 16:19:51 2013 +0400
@@ -0,0 +1,34 @@
+/*
+ * 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);
+    }
+}