--- old/modules/javafx.swing/src/main/java/javafx/embed/swing/DataFlavorUtils.java 2018-07-10 15:06:31.040834000 +0530 +++ /dev/null 2018-07-10 15:06:31.000000000 +0530 @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2012, 2017, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package javafx.embed.swing; - -import javafx.scene.input.DataFormat; - -import java.io.ByteArrayOutputStream; -import java.util.Set; -import java.util.Map; -import java.util.List; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Collections; -import java.util.ArrayList; - -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; - -import java.nio.ByteBuffer; - - -final class DataFlavorUtils { - - static String getFxMimeType(final DataFlavor flavor) { - return flavor.getPrimaryType() + "/" + flavor.getSubType(); - } - - static DataFlavor[] getDataFlavors(String[] mimeTypes) { - final ArrayList flavors = - new ArrayList(mimeTypes.length); - for (String mime : mimeTypes) { - DataFlavor flavor = null; - try { - flavor = new DataFlavor(mime); - } catch (ClassNotFoundException | IllegalArgumentException e) { - continue; - } - flavors.add(flavor); - } - return flavors.toArray(new DataFlavor[0]); - } - - static DataFlavor getDataFlavor(final DataFormat format) { - DataFlavor[] flavors = getDataFlavors(format.getIdentifiers().toArray(new String[1])); - - // Well, that's our best guess... - return flavors.length == 0 ? null : flavors[0]; - } - - static String getMimeType(final DataFormat format) { - // Well, that's our best guess... - for (String id : format.getIdentifiers()) return id; - return null; - } - - static DataFormat getDataFormat(final DataFlavor flavor) { - String mimeType = getFxMimeType(flavor); - DataFormat dataFormat = DataFormat.lookupMimeType(mimeType); - if (dataFormat == null) { - dataFormat = new DataFormat(mimeType); // are we ready for this yet? - } - return dataFormat; - } - - /** - * InputStream implementation backed by a ByteBuffer. - * It can handle byte buffers that are backed by arrays - * as well as operating system memory. - */ - private static class ByteBufferInputStream extends InputStream { - private final ByteBuffer bb; - - private ByteBufferInputStream(ByteBuffer bb) { this.bb = bb; } - - @Override public int available() { return bb.remaining(); } - - @Override public int read() throws IOException { - if (!bb.hasRemaining()) return -1; - return bb.get() & 0xFF; // Make sure the value is in [0..255] - } - - @Override public int read(byte[] bytes, int off, int len) throws IOException { - if (!bb.hasRemaining()) return -1; - len = Math.min(len, bb.remaining()); - bb.get(bytes, off, len); - return len; - } - } - - static Object adjustFxData(final DataFlavor flavor, final Object fxData) - throws UnsupportedEncodingException - { - // TBD: Handle more data types!!! - if (fxData instanceof String) { - if (flavor.isRepresentationClassInputStream()) { - final String encoding = flavor.getParameter("charset"); - return new ByteArrayInputStream(encoding != null - ? ((String) fxData).getBytes(encoding) - : ((String) fxData).getBytes()); - } - if (flavor.isRepresentationClassByteBuffer()) { - // ... - } - } - if (fxData instanceof ByteBuffer) { - if (flavor.isRepresentationClassInputStream()) { - return new ByteBufferInputStream((ByteBuffer)fxData); - } - } - return fxData; - } - - static Object adjustSwingData(final DataFlavor flavor, - final String mimeType, - final Object swingData) - { - if (swingData == null) { - return swingData; - } - - if (flavor.isFlavorJavaFileListType()) { - // RT-12663 - final List fileList = (List)swingData; - final String[] paths = new String[fileList.size()]; - int i = 0; - for (File f : fileList) { - paths[i++] = f.getPath(); - } - return paths; - } - DataFormat dataFormat = DataFormat.lookupMimeType(mimeType); - if (DataFormat.PLAIN_TEXT.equals(dataFormat)) { - if (flavor.isFlavorTextType()) { - if (swingData instanceof InputStream) { - InputStream in = (InputStream)swingData; - // TBD: charset - ByteArrayOutputStream out = new ByteArrayOutputStream(); - byte[] bb = new byte[64]; - try { - int len = in.read(bb); - while (len != -1) { - out.write(bb, 0, len); - len = in.read(bb); - } - out.close(); - return new String(out.toByteArray()); - } catch (Exception z) { - // ignore - } - } - } else if (swingData != null) { - return swingData.toString(); - } - } - return swingData; - } - - static Map adjustSwingDataFlavors(final DataFlavor[] flavors) { - // Group data flavors by FX mime type. - final Map> mimeType2Flavors = - new HashMap<>(flavors.length); - for (DataFlavor flavor : flavors) { - final String mimeType = getFxMimeType(flavor); - if (mimeType2Flavors.containsKey(mimeType)) { - final Set mimeTypeFlavors = mimeType2Flavors.get( - mimeType); - try { - mimeTypeFlavors.add(flavor); - } catch (UnsupportedOperationException e) { - // List of data flavors corresponding to FX mime - // type has been finalized already. - } - } else { - Set mimeTypeFlavors = new HashSet(); - - // If this is text data flavor use DataFlavor representing - // a Java Unicode String class. This is what FX expects from - // clipboard. - if (flavor.isFlavorTextType()) { - mimeTypeFlavors.add(DataFlavor.stringFlavor); - mimeTypeFlavors = Collections.unmodifiableSet( - mimeTypeFlavors); - } else { - mimeTypeFlavors.add(flavor); - } - - mimeType2Flavors.put(mimeType, mimeTypeFlavors); - } - } - - // Choose the best data flavor corresponding to the given FX mime type - final Map mimeType2Flavor = new HashMap<>(); - for (String mimeType : mimeType2Flavors.keySet()) { - final DataFlavor[] mimeTypeFlavors = mimeType2Flavors.get(mimeType). - toArray(new DataFlavor[0]); - if (mimeTypeFlavors.length == 1) { - mimeType2Flavor.put(mimeType, mimeTypeFlavors[0]); - } else { - // TBD: something better!!! - mimeType2Flavor.put(mimeType, mimeTypeFlavors[0]); - } - } - - return mimeType2Flavor; - } - - private static Object readData(final Transferable t, final DataFlavor flavor) { - Object obj = null; - try { - obj = t.getTransferData(flavor); - } catch (UnsupportedFlavorException ex) { - // FIXME: report error - ex.printStackTrace(System.err); - } catch (IOException ex) { - // FIXME: report error - ex.printStackTrace(System.err); - } - return obj; - } - - /** - * Returns a Map populated with keys corresponding to all the MIME types - * available in the provided Transferable object. If fetchData is true, - * then the data is fetched as well, otherwise all the values are set to - * null. - */ - static Map readAllData(final Transferable t, - final Map fxMimeType2DataFlavor, - final boolean fetchData) - { - final Map fxMimeType2Data = new HashMap<>(); - for (DataFlavor flavor : t.getTransferDataFlavors()) { - Object obj = fetchData ? readData(t, flavor) : null; - if (obj != null || !fetchData) { - String mimeType = getFxMimeType(flavor); - obj = adjustSwingData(flavor, mimeType, obj); - fxMimeType2Data.put(mimeType, obj); - } - } - for (Map.Entry e: fxMimeType2DataFlavor.entrySet()) { - String mimeType = e.getKey(); - DataFlavor flavor = e.getValue(); - Object obj = fetchData ? readData(t, flavor) : null; - if (obj != null || !fetchData) { - obj = adjustSwingData(flavor, mimeType, obj); - fxMimeType2Data.put(e.getKey(), obj); - } - } - return fxMimeType2Data; - } -} --- /dev/null 2018-07-10 15:06:31.000000000 +0530 +++ new/modules/javafx.swing/src/main/java/com/sun/javafx/embed/swing/DataFlavorUtils.java 2018-07-10 15:06:29.629154800 +0530 @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2012, 2017, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.javafx.embed.swing; + +import javafx.scene.input.DataFormat; + +import java.io.ByteArrayOutputStream; +import java.util.Set; +import java.util.Map; +import java.util.List; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Collections; +import java.util.ArrayList; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import java.nio.ByteBuffer; + + +final class DataFlavorUtils { + + static String getFxMimeType(final DataFlavor flavor) { + return flavor.getPrimaryType() + "/" + flavor.getSubType(); + } + + static DataFlavor[] getDataFlavors(String[] mimeTypes) { + final ArrayList flavors = + new ArrayList(mimeTypes.length); + for (String mime : mimeTypes) { + DataFlavor flavor = null; + try { + flavor = new DataFlavor(mime); + } catch (ClassNotFoundException | IllegalArgumentException e) { + continue; + } + flavors.add(flavor); + } + return flavors.toArray(new DataFlavor[0]); + } + + static DataFlavor getDataFlavor(final DataFormat format) { + DataFlavor[] flavors = getDataFlavors(format.getIdentifiers().toArray(new String[1])); + + // Well, that's our best guess... + return flavors.length == 0 ? null : flavors[0]; + } + + static String getMimeType(final DataFormat format) { + // Well, that's our best guess... + for (String id : format.getIdentifiers()) return id; + return null; + } + + static DataFormat getDataFormat(final DataFlavor flavor) { + String mimeType = getFxMimeType(flavor); + DataFormat dataFormat = DataFormat.lookupMimeType(mimeType); + if (dataFormat == null) { + dataFormat = new DataFormat(mimeType); // are we ready for this yet? + } + return dataFormat; + } + + /** + * InputStream implementation backed by a ByteBuffer. + * It can handle byte buffers that are backed by arrays + * as well as operating system memory. + */ + private static class ByteBufferInputStream extends InputStream { + private final ByteBuffer bb; + + private ByteBufferInputStream(ByteBuffer bb) { this.bb = bb; } + + @Override public int available() { return bb.remaining(); } + + @Override public int read() throws IOException { + if (!bb.hasRemaining()) return -1; + return bb.get() & 0xFF; // Make sure the value is in [0..255] + } + + @Override public int read(byte[] bytes, int off, int len) throws IOException { + if (!bb.hasRemaining()) return -1; + len = Math.min(len, bb.remaining()); + bb.get(bytes, off, len); + return len; + } + } + + static Object adjustFxData(final DataFlavor flavor, final Object fxData) + throws UnsupportedEncodingException + { + // TBD: Handle more data types!!! + if (fxData instanceof String) { + if (flavor.isRepresentationClassInputStream()) { + final String encoding = flavor.getParameter("charset"); + return new ByteArrayInputStream(encoding != null + ? ((String) fxData).getBytes(encoding) + : ((String) fxData).getBytes()); + } + if (flavor.isRepresentationClassByteBuffer()) { + // ... + } + } + if (fxData instanceof ByteBuffer) { + if (flavor.isRepresentationClassInputStream()) { + return new ByteBufferInputStream((ByteBuffer)fxData); + } + } + return fxData; + } + + static Object adjustSwingData(final DataFlavor flavor, + final String mimeType, + final Object swingData) + { + if (swingData == null) { + return swingData; + } + + if (flavor.isFlavorJavaFileListType()) { + // RT-12663 + final List fileList = (List)swingData; + final String[] paths = new String[fileList.size()]; + int i = 0; + for (File f : fileList) { + paths[i++] = f.getPath(); + } + return paths; + } + DataFormat dataFormat = DataFormat.lookupMimeType(mimeType); + if (DataFormat.PLAIN_TEXT.equals(dataFormat)) { + if (flavor.isFlavorTextType()) { + if (swingData instanceof InputStream) { + InputStream in = (InputStream)swingData; + // TBD: charset + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] bb = new byte[64]; + try { + int len = in.read(bb); + while (len != -1) { + out.write(bb, 0, len); + len = in.read(bb); + } + out.close(); + return new String(out.toByteArray()); + } catch (Exception z) { + // ignore + } + } + } else if (swingData != null) { + return swingData.toString(); + } + } + return swingData; + } + + static Map adjustSwingDataFlavors(final DataFlavor[] flavors) { + // Group data flavors by FX mime type. + final Map> mimeType2Flavors = + new HashMap<>(flavors.length); + for (DataFlavor flavor : flavors) { + final String mimeType = getFxMimeType(flavor); + if (mimeType2Flavors.containsKey(mimeType)) { + final Set mimeTypeFlavors = mimeType2Flavors.get( + mimeType); + try { + mimeTypeFlavors.add(flavor); + } catch (UnsupportedOperationException e) { + // List of data flavors corresponding to FX mime + // type has been finalized already. + } + } else { + Set mimeTypeFlavors = new HashSet(); + + // If this is text data flavor use DataFlavor representing + // a Java Unicode String class. This is what FX expects from + // clipboard. + if (flavor.isFlavorTextType()) { + mimeTypeFlavors.add(DataFlavor.stringFlavor); + mimeTypeFlavors = Collections.unmodifiableSet( + mimeTypeFlavors); + } else { + mimeTypeFlavors.add(flavor); + } + + mimeType2Flavors.put(mimeType, mimeTypeFlavors); + } + } + + // Choose the best data flavor corresponding to the given FX mime type + final Map mimeType2Flavor = new HashMap<>(); + for (String mimeType : mimeType2Flavors.keySet()) { + final DataFlavor[] mimeTypeFlavors = mimeType2Flavors.get(mimeType). + toArray(new DataFlavor[0]); + if (mimeTypeFlavors.length == 1) { + mimeType2Flavor.put(mimeType, mimeTypeFlavors[0]); + } else { + // TBD: something better!!! + mimeType2Flavor.put(mimeType, mimeTypeFlavors[0]); + } + } + + return mimeType2Flavor; + } + + private static Object readData(final Transferable t, final DataFlavor flavor) { + Object obj = null; + try { + obj = t.getTransferData(flavor); + } catch (UnsupportedFlavorException ex) { + // FIXME: report error + ex.printStackTrace(System.err); + } catch (IOException ex) { + // FIXME: report error + ex.printStackTrace(System.err); + } + return obj; + } + + /** + * Returns a Map populated with keys corresponding to all the MIME types + * available in the provided Transferable object. If fetchData is true, + * then the data is fetched as well, otherwise all the values are set to + * null. + */ + static Map readAllData(final Transferable t, + final Map fxMimeType2DataFlavor, + final boolean fetchData) + { + final Map fxMimeType2Data = new HashMap<>(); + for (DataFlavor flavor : t.getTransferDataFlavors()) { + Object obj = fetchData ? readData(t, flavor) : null; + if (obj != null || !fetchData) { + String mimeType = getFxMimeType(flavor); + obj = adjustSwingData(flavor, mimeType, obj); + fxMimeType2Data.put(mimeType, obj); + } + } + for (Map.Entry e: fxMimeType2DataFlavor.entrySet()) { + String mimeType = e.getKey(); + DataFlavor flavor = e.getValue(); + Object obj = fetchData ? readData(t, flavor) : null; + if (obj != null || !fetchData) { + obj = adjustSwingData(flavor, mimeType, obj); + fxMimeType2Data.put(e.getKey(), obj); + } + } + return fxMimeType2Data; + } +}