< prev index next >

src/java.desktop/share/classes/sun/awt/datatransfer/DataTransferer.java

Print this page




 107  *
 108  * The concept of "flavors" and "natives" is extended to include "formats",
 109  * which are the numeric values Win32 and X11 use to express particular data
 110  * types. Like FlavorMap, which provides getNativesForFlavors(DataFlavor[]) and
 111  * getFlavorsForNatives(String[]) functions, DataTransferer provides a set
 112  * of getFormatsFor(Transferable|Flavor|Flavors) and
 113  * getFlavorsFor(Format|Formats) functions.
 114  *
 115  * Also provided are functions for translating a Transferable into a byte
 116  * array, given a source DataFlavor and a target format, and for translating
 117  * a byte array or InputStream into an Object, given a source format and
 118  * a target DataFlavor.
 119  *
 120  * @author David Mendenhall
 121  * @author Danila Sinopalnikov
 122  *
 123  * @since 1.3.1
 124  */
 125 public abstract class DataTransferer {
 126     /**
 127      * The <code>DataFlavor</code> representing a Java text encoding String
 128      * encoded in UTF-8, where
 129      * <pre>
 130      *     representationClass = [B
 131      *     mimeType            = "application/x-java-text-encoding"
 132      * </pre>
 133      */
 134     public static final DataFlavor javaTextEncodingFlavor;
 135 
 136     /**
 137      * A collection of all natives listed in flavormap.properties with
 138      * a primary MIME type of "text".
 139      */
 140     private static final Set<Long> textNatives =
 141             Collections.synchronizedSet(new HashSet<>());
 142 
 143     /**
 144      * The native encodings/charsets for the Set of textNatives.
 145      */
 146     private static final Map<Long, String> nativeCharsets =
 147             Collections.synchronizedMap(new HashMap<>());


 306     {
 307         DataFlavor[] flavors = contents.getTransferDataFlavors();
 308         if (flavors == null) {
 309             return Collections.emptySortedMap();
 310         }
 311         return getFormatsForFlavors(flavors, map);
 312     }
 313 
 314     /**
 315      * Returns a Map whose keys are all of the possible formats into which data
 316      * in the specified DataFlavors can be translated. The value of each key
 317      * is the DataFlavor in which the Transferable's data should be requested
 318      * when converting to the format.
 319      * <p>
 320      * The map keys are sorted according to the native formats preference
 321      * order.
 322      *
 323      * @param flavors the data flavors
 324      * @param map the FlavorTable which contains mappings between
 325      *            DataFlavors and data formats
 326      * @throws NullPointerException if flavors or map is <code>null</code>
 327      */
 328     public SortedMap<Long, DataFlavor> getFormatsForFlavors(DataFlavor[] flavors,
 329                                                             FlavorTable map)
 330     {
 331         Map<Long,DataFlavor> formatMap = new HashMap<>(flavors.length);
 332         Map<Long,DataFlavor> textPlainMap = new HashMap<>(flavors.length);
 333         // Maps formats to indices that will be used to sort the formats
 334         // according to the preference order.
 335         // Larger index value corresponds to the more preferable format.
 336         Map<Long, Integer> indexMap = new HashMap<>(flavors.length);
 337         Map<Long, Integer> textPlainIndexMap = new HashMap<>(flavors.length);
 338 
 339         int currentIndex = 0;
 340 
 341         // Iterate backwards so that preferred DataFlavors are used over
 342         // other DataFlavors. (See javadoc for
 343         // Transferable.getTransferDataFlavors.)
 344         for (int i = flavors.length - 1; i >= 0; i--) {
 345             DataFlavor flavor = flavors[i];
 346             if (flavor == null) continue;


 461                 if (mappingSet.contains(new AbstractMap.SimpleEntry<>(lFormat, flavor))) {
 462                     flavorMap.put(flavor, lFormat);
 463                     break;
 464                 }
 465             }
 466         }
 467 
 468         return flavorMap;
 469     }
 470 
 471     /**
 472      * Returns a Set of all DataFlavors for which
 473      * 1) a mapping from at least one of the specified formats exists in the
 474      * specified map and
 475      * 2) the data translation for this mapping can be performed by the data
 476      * transfer subsystem.
 477      *
 478      * @param formats the data formats
 479      * @param map the FlavorTable which contains mappings between
 480      *            DataFlavors and data formats
 481      * @throws NullPointerException if formats or map is <code>null</code>
 482      */
 483     public Set<DataFlavor> getFlavorsForFormatsAsSet(long[] formats, FlavorTable map) {
 484         Set<DataFlavor> flavorSet = new HashSet<>(formats.length);
 485 
 486         for (long format : formats) {
 487             List<DataFlavor> flavors = map.getFlavorsForNative(getNativeForFormat(format));
 488             for (DataFlavor flavor : flavors) {
 489                 // Don't explicitly test for String, since it is just a special
 490                 // case of Serializable
 491                 if (flavor.isFlavorTextType() ||
 492                         flavor.isFlavorJavaFileListType() ||
 493                         DataFlavor.imageFlavor.equals(flavor) ||
 494                         flavor.isRepresentationClassSerializable() ||
 495                         flavor.isRepresentationClassInputStream() ||
 496                         flavor.isRepresentationClassRemote()) {
 497                     flavorSet.add(flavor);
 498                 }
 499             }
 500         }
 501 
 502         return flavorSet;
 503     }
 504 
 505     /**
 506      * Returns an array of all DataFlavors for which
 507      * 1) a mapping from at least one of the specified formats exists in the
 508      * specified map and
 509      * 2) the data translation for this mapping can be performed by the data
 510      * transfer subsystem.
 511      * The array will be sorted according to a
 512      * <code>DataFlavorComparator</code> created with the specified
 513      * map as an argument.
 514      *
 515      * @param formats the data formats
 516      * @param map the FlavorTable which contains mappings between
 517      *            DataFlavors and data formats
 518      * @throws NullPointerException if formats or map is <code>null</code>
 519      */
 520     public DataFlavor[] getFlavorsForFormatsAsArray(long[] formats,
 521                                                     FlavorTable map) {
 522         // getFlavorsForFormatsAsSet() is less expensive than
 523         // getFlavorsForFormats().
 524         return setToSortedDataFlavorArray(getFlavorsForFormatsAsSet(formats, map));
 525     }
 526 
 527     /**
 528      * Looks-up or registers the String native with the native data transfer
 529      * system and returns a long format corresponding to that native.
 530      */
 531     protected abstract Long getFormatForNativeAsLong(String str);
 532 
 533     /**
 534      * Looks-up the String native corresponding to the specified long format in
 535      * the native data transfer system.
 536      */
 537     protected abstract String getNativeForFormat(long format);
 538 


1788                 continue;
1789             }
1790 
1791             imageWriter.dispose();
1792             baos.close();
1793             return baos.toByteArray();
1794         }
1795 
1796         baos.close();
1797 
1798         if (ioe == null) {
1799             ioe = new IOException("Registered service providers failed to encode "
1800                                   + renderedImage + " to " + mimeType);
1801         }
1802 
1803         throw ioe;
1804     }
1805 
1806     /**
1807      * Concatenates the data represented by two objects. Objects can be either
1808      * byte arrays or instances of <code>InputStream</code>. If both arguments
1809      * are byte arrays byte array will be returned. Otherwise an
1810      * <code>InputStream</code> will be returned.
1811      * <p>
1812      * Currently is only called from native code to prepend palette data to
1813      * platform-specific image data during image transfer on Win32.
1814      *
1815      * @param obj1 the first object to be concatenated.
1816      * @param obj2 the second object to be concatenated.
1817      * @return a byte array or an <code>InputStream</code> which represents
1818      *         a logical concatenation of the two arguments.
1819      * @throws NullPointerException is either of the arguments is
1820      *         <code>null</code>
1821      * @throws ClassCastException is either of the arguments is
1822      *         neither byte array nor an instance of <code>InputStream</code>.
1823      */
1824     private Object concatData(Object obj1, Object obj2) {
1825         InputStream str1 = null;
1826         InputStream str2 = null;
1827 
1828         if (obj1 instanceof byte[]) {
1829             byte[] arr1 = (byte[])obj1;
1830             if (obj2 instanceof byte[]) {
1831                 byte[] arr2 = (byte[])obj2;
1832                 byte[] ret = new byte[arr1.length + arr2.length];
1833                 System.arraycopy(arr1, 0, ret, 0, arr1.length);
1834                 System.arraycopy(arr2, 0, ret, arr1.length, arr2.length);
1835                 return ret;
1836             } else {
1837                 str1 = new ByteArrayInputStream(arr1);
1838                 str2 = (InputStream)obj2;
1839             }
1840         } else {
1841             str1 = (InputStream)obj1;
1842             if (obj2 instanceof byte[]) {


1945     public abstract ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler();
1946 
1947     /**
1948      * Helper function to reduce a Map with Long keys to a long array.
1949      * <p>
1950      * The map keys are sorted according to the native formats preference
1951      * order.
1952      */
1953     public static long[] keysToLongArray(SortedMap<Long, ?> map) {
1954         Set<Long> keySet = map.keySet();
1955         long[] retval = new long[keySet.size()];
1956         int i = 0;
1957         for (Iterator<Long> iter = keySet.iterator(); iter.hasNext(); i++) {
1958             retval[i] = iter.next();
1959         }
1960         return retval;
1961     }
1962 
1963     /**
1964      * Helper function to convert a Set of DataFlavors to a sorted array.
1965      * The array will be sorted according to <code>DataFlavorComparator</code>.
1966      */
1967     public static DataFlavor[] setToSortedDataFlavorArray(Set<DataFlavor> flavorsSet) {
1968         DataFlavor[] flavors = new DataFlavor[flavorsSet.size()];
1969         flavorsSet.toArray(flavors);
1970         final Comparator<DataFlavor> comparator = DataFlavorUtil.getDataFlavorComparator().reversed();
1971         Arrays.sort(flavors, comparator);
1972         return flavors;
1973     }
1974 
1975     /**
1976      * Helper function to convert an InputStream to a byte[] array.
1977      */
1978     protected static byte[] inputStreamToByteArray(InputStream str)
1979         throws IOException
1980     {
1981         try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
1982             int len = 0;
1983             byte[] buf = new byte[8192];
1984 
1985             while ((len = str.read(buf)) != -1) {
1986                 baos.write(buf, 0, len);
1987             }
1988 
1989             return baos.toByteArray();
1990         }
1991     }
1992 
1993     /**
1994      * Returns platform-specific mappings for the specified native.
1995      * If there are no platform-specific mappings for this native, the method
1996      * returns an empty <code>List</code>.
1997      */
1998     public LinkedHashSet<DataFlavor> getPlatformMappingsForNative(String nat) {
1999         return new LinkedHashSet<>();
2000     }
2001 
2002     /**
2003      * Returns platform-specific mappings for the specified flavor.
2004      * If there are no platform-specific mappings for this flavor, the method
2005      * returns an empty <code>List</code>.
2006      */
2007     public LinkedHashSet<String> getPlatformMappingsForFlavor(DataFlavor df) {
2008         return new LinkedHashSet<>();
2009     }
2010 }


 107  *
 108  * The concept of "flavors" and "natives" is extended to include "formats",
 109  * which are the numeric values Win32 and X11 use to express particular data
 110  * types. Like FlavorMap, which provides getNativesForFlavors(DataFlavor[]) and
 111  * getFlavorsForNatives(String[]) functions, DataTransferer provides a set
 112  * of getFormatsFor(Transferable|Flavor|Flavors) and
 113  * getFlavorsFor(Format|Formats) functions.
 114  *
 115  * Also provided are functions for translating a Transferable into a byte
 116  * array, given a source DataFlavor and a target format, and for translating
 117  * a byte array or InputStream into an Object, given a source format and
 118  * a target DataFlavor.
 119  *
 120  * @author David Mendenhall
 121  * @author Danila Sinopalnikov
 122  *
 123  * @since 1.3.1
 124  */
 125 public abstract class DataTransferer {
 126     /**
 127      * The {@code DataFlavor} representing a Java text encoding String
 128      * encoded in UTF-8, where
 129      * <pre>
 130      *     representationClass = [B
 131      *     mimeType            = "application/x-java-text-encoding"
 132      * </pre>
 133      */
 134     public static final DataFlavor javaTextEncodingFlavor;
 135 
 136     /**
 137      * A collection of all natives listed in flavormap.properties with
 138      * a primary MIME type of "text".
 139      */
 140     private static final Set<Long> textNatives =
 141             Collections.synchronizedSet(new HashSet<>());
 142 
 143     /**
 144      * The native encodings/charsets for the Set of textNatives.
 145      */
 146     private static final Map<Long, String> nativeCharsets =
 147             Collections.synchronizedMap(new HashMap<>());


 306     {
 307         DataFlavor[] flavors = contents.getTransferDataFlavors();
 308         if (flavors == null) {
 309             return Collections.emptySortedMap();
 310         }
 311         return getFormatsForFlavors(flavors, map);
 312     }
 313 
 314     /**
 315      * Returns a Map whose keys are all of the possible formats into which data
 316      * in the specified DataFlavors can be translated. The value of each key
 317      * is the DataFlavor in which the Transferable's data should be requested
 318      * when converting to the format.
 319      * <p>
 320      * The map keys are sorted according to the native formats preference
 321      * order.
 322      *
 323      * @param flavors the data flavors
 324      * @param map the FlavorTable which contains mappings between
 325      *            DataFlavors and data formats
 326      * @throws NullPointerException if flavors or map is {@code null}
 327      */
 328     public SortedMap<Long, DataFlavor> getFormatsForFlavors(DataFlavor[] flavors,
 329                                                             FlavorTable map)
 330     {
 331         Map<Long,DataFlavor> formatMap = new HashMap<>(flavors.length);
 332         Map<Long,DataFlavor> textPlainMap = new HashMap<>(flavors.length);
 333         // Maps formats to indices that will be used to sort the formats
 334         // according to the preference order.
 335         // Larger index value corresponds to the more preferable format.
 336         Map<Long, Integer> indexMap = new HashMap<>(flavors.length);
 337         Map<Long, Integer> textPlainIndexMap = new HashMap<>(flavors.length);
 338 
 339         int currentIndex = 0;
 340 
 341         // Iterate backwards so that preferred DataFlavors are used over
 342         // other DataFlavors. (See javadoc for
 343         // Transferable.getTransferDataFlavors.)
 344         for (int i = flavors.length - 1; i >= 0; i--) {
 345             DataFlavor flavor = flavors[i];
 346             if (flavor == null) continue;


 461                 if (mappingSet.contains(new AbstractMap.SimpleEntry<>(lFormat, flavor))) {
 462                     flavorMap.put(flavor, lFormat);
 463                     break;
 464                 }
 465             }
 466         }
 467 
 468         return flavorMap;
 469     }
 470 
 471     /**
 472      * Returns a Set of all DataFlavors for which
 473      * 1) a mapping from at least one of the specified formats exists in the
 474      * specified map and
 475      * 2) the data translation for this mapping can be performed by the data
 476      * transfer subsystem.
 477      *
 478      * @param formats the data formats
 479      * @param map the FlavorTable which contains mappings between
 480      *            DataFlavors and data formats
 481      * @throws NullPointerException if formats or map is {@code null}
 482      */
 483     public Set<DataFlavor> getFlavorsForFormatsAsSet(long[] formats, FlavorTable map) {
 484         Set<DataFlavor> flavorSet = new HashSet<>(formats.length);
 485 
 486         for (long format : formats) {
 487             List<DataFlavor> flavors = map.getFlavorsForNative(getNativeForFormat(format));
 488             for (DataFlavor flavor : flavors) {
 489                 // Don't explicitly test for String, since it is just a special
 490                 // case of Serializable
 491                 if (flavor.isFlavorTextType() ||
 492                         flavor.isFlavorJavaFileListType() ||
 493                         DataFlavor.imageFlavor.equals(flavor) ||
 494                         flavor.isRepresentationClassSerializable() ||
 495                         flavor.isRepresentationClassInputStream() ||
 496                         flavor.isRepresentationClassRemote()) {
 497                     flavorSet.add(flavor);
 498                 }
 499             }
 500         }
 501 
 502         return flavorSet;
 503     }
 504 
 505     /**
 506      * Returns an array of all DataFlavors for which
 507      * 1) a mapping from at least one of the specified formats exists in the
 508      * specified map and
 509      * 2) the data translation for this mapping can be performed by the data
 510      * transfer subsystem.
 511      * The array will be sorted according to a
 512      * {@code DataFlavorComparator} created with the specified
 513      * map as an argument.
 514      *
 515      * @param formats the data formats
 516      * @param map the FlavorTable which contains mappings between
 517      *            DataFlavors and data formats
 518      * @throws NullPointerException if formats or map is {@code null}
 519      */
 520     public DataFlavor[] getFlavorsForFormatsAsArray(long[] formats,
 521                                                     FlavorTable map) {
 522         // getFlavorsForFormatsAsSet() is less expensive than
 523         // getFlavorsForFormats().
 524         return setToSortedDataFlavorArray(getFlavorsForFormatsAsSet(formats, map));
 525     }
 526 
 527     /**
 528      * Looks-up or registers the String native with the native data transfer
 529      * system and returns a long format corresponding to that native.
 530      */
 531     protected abstract Long getFormatForNativeAsLong(String str);
 532 
 533     /**
 534      * Looks-up the String native corresponding to the specified long format in
 535      * the native data transfer system.
 536      */
 537     protected abstract String getNativeForFormat(long format);
 538 


1788                 continue;
1789             }
1790 
1791             imageWriter.dispose();
1792             baos.close();
1793             return baos.toByteArray();
1794         }
1795 
1796         baos.close();
1797 
1798         if (ioe == null) {
1799             ioe = new IOException("Registered service providers failed to encode "
1800                                   + renderedImage + " to " + mimeType);
1801         }
1802 
1803         throw ioe;
1804     }
1805 
1806     /**
1807      * Concatenates the data represented by two objects. Objects can be either
1808      * byte arrays or instances of {@code InputStream}. If both arguments
1809      * are byte arrays byte array will be returned. Otherwise an
1810      * {@code InputStream} will be returned.
1811      * <p>
1812      * Currently is only called from native code to prepend palette data to
1813      * platform-specific image data during image transfer on Win32.
1814      *
1815      * @param obj1 the first object to be concatenated.
1816      * @param obj2 the second object to be concatenated.
1817      * @return a byte array or an {@code InputStream} which represents
1818      *         a logical concatenation of the two arguments.
1819      * @throws NullPointerException is either of the arguments is
1820      *         {@code null}
1821      * @throws ClassCastException is either of the arguments is
1822      *         neither byte array nor an instance of {@code InputStream}.
1823      */
1824     private Object concatData(Object obj1, Object obj2) {
1825         InputStream str1 = null;
1826         InputStream str2 = null;
1827 
1828         if (obj1 instanceof byte[]) {
1829             byte[] arr1 = (byte[])obj1;
1830             if (obj2 instanceof byte[]) {
1831                 byte[] arr2 = (byte[])obj2;
1832                 byte[] ret = new byte[arr1.length + arr2.length];
1833                 System.arraycopy(arr1, 0, ret, 0, arr1.length);
1834                 System.arraycopy(arr2, 0, ret, arr1.length, arr2.length);
1835                 return ret;
1836             } else {
1837                 str1 = new ByteArrayInputStream(arr1);
1838                 str2 = (InputStream)obj2;
1839             }
1840         } else {
1841             str1 = (InputStream)obj1;
1842             if (obj2 instanceof byte[]) {


1945     public abstract ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler();
1946 
1947     /**
1948      * Helper function to reduce a Map with Long keys to a long array.
1949      * <p>
1950      * The map keys are sorted according to the native formats preference
1951      * order.
1952      */
1953     public static long[] keysToLongArray(SortedMap<Long, ?> map) {
1954         Set<Long> keySet = map.keySet();
1955         long[] retval = new long[keySet.size()];
1956         int i = 0;
1957         for (Iterator<Long> iter = keySet.iterator(); iter.hasNext(); i++) {
1958             retval[i] = iter.next();
1959         }
1960         return retval;
1961     }
1962 
1963     /**
1964      * Helper function to convert a Set of DataFlavors to a sorted array.
1965      * The array will be sorted according to {@code DataFlavorComparator}.
1966      */
1967     public static DataFlavor[] setToSortedDataFlavorArray(Set<DataFlavor> flavorsSet) {
1968         DataFlavor[] flavors = new DataFlavor[flavorsSet.size()];
1969         flavorsSet.toArray(flavors);
1970         final Comparator<DataFlavor> comparator = DataFlavorUtil.getDataFlavorComparator().reversed();
1971         Arrays.sort(flavors, comparator);
1972         return flavors;
1973     }
1974 
1975     /**
1976      * Helper function to convert an InputStream to a byte[] array.
1977      */
1978     protected static byte[] inputStreamToByteArray(InputStream str)
1979         throws IOException
1980     {
1981         try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
1982             int len = 0;
1983             byte[] buf = new byte[8192];
1984 
1985             while ((len = str.read(buf)) != -1) {
1986                 baos.write(buf, 0, len);
1987             }
1988 
1989             return baos.toByteArray();
1990         }
1991     }
1992 
1993     /**
1994      * Returns platform-specific mappings for the specified native.
1995      * If there are no platform-specific mappings for this native, the method
1996      * returns an empty {@code List}.
1997      */
1998     public LinkedHashSet<DataFlavor> getPlatformMappingsForNative(String nat) {
1999         return new LinkedHashSet<>();
2000     }
2001 
2002     /**
2003      * Returns platform-specific mappings for the specified flavor.
2004      * If there are no platform-specific mappings for this flavor, the method
2005      * returns an empty {@code List}.
2006      */
2007     public LinkedHashSet<String> getPlatformMappingsForFlavor(DataFlavor df) {
2008         return new LinkedHashSet<>();
2009     }
2010 }
< prev index next >