154 * representationClass = java.lang.String
155 * mimeType = "text/plain; charset=Unicode"
156 * </pre>
157 */
158 public static final DataFlavor plainTextStringFlavor;
159
160 /**
161 * The <code>DataFlavor</code> representing a Java text encoding String
162 * encoded in UTF-8, where
163 * <pre>
164 * representationClass = [B
165 * mimeType = "application/x-java-text-encoding"
166 * </pre>
167 */
168 public static final DataFlavor javaTextEncodingFlavor;
169
170 /**
171 * Lazy initialization of Standard Encodings.
172 */
173 private static class StandardEncodingsHolder {
174 private static final SortedSet standardEncodings = load();
175
176 private static SortedSet load() {
177 final Comparator comparator =
178 new CharsetComparator(IndexedComparator.SELECT_WORST);
179 final SortedSet tempSet = new TreeSet(comparator);
180 tempSet.add("US-ASCII");
181 tempSet.add("ISO-8859-1");
182 tempSet.add("UTF-8");
183 tempSet.add("UTF-16BE");
184 tempSet.add("UTF-16LE");
185 tempSet.add("UTF-16");
186 tempSet.add(getDefaultTextCharset());
187 return Collections.unmodifiableSortedSet(tempSet);
188 }
189 }
190
191 /**
192 * Tracks whether a particular text/* MIME type supports the charset
193 * parameter. The Map is initialized with all of the standard MIME types
194 * listed in the DataFlavor.selectBestTextFlavor method comment. Additional
195 * entries may be added during the life of the JRE for text/<other> types.
196 */
197 private static final Map textMIMESubtypeCharsetSupport;
198
199 /**
506 return Charset.isSupported(encoding);
507 } catch (IllegalCharsetNameException icne) {
508 return false;
509 }
510 }
511
512 /**
513 * Returns {@code true} if the given type is a java.rmi.Remote.
514 */
515 public static boolean isRemote(Class<?> type) {
516 return RMI.isRemote(type);
517 }
518
519 /**
520 * Returns an Iterator which traverses a SortedSet of Strings which are
521 * a total order of the standard character sets supported by the JRE. The
522 * ordering follows the same principles as DataFlavor.selectBestTextFlavor.
523 * So as to avoid loading all available character converters, optional,
524 * non-standard, character sets are not included.
525 */
526 public static Iterator standardEncodings() {
527 return StandardEncodingsHolder.standardEncodings.iterator();
528 }
529
530 /**
531 * Converts a FlavorMap to a FlavorTable.
532 */
533 public static FlavorTable adaptFlavorMap(final FlavorMap map) {
534 if (map instanceof FlavorTable) {
535 return (FlavorTable)map;
536 }
537
538 return new FlavorTable() {
539 public Map getNativesForFlavors(DataFlavor[] flavors) {
540 return map.getNativesForFlavors(flavors);
541 }
542 public Map getFlavorsForNatives(String[] natives) {
543 return map.getFlavorsForNatives(natives);
544 }
545 public List getNativesForFlavor(DataFlavor flav) {
546 Map natives =
547 getNativesForFlavors(new DataFlavor[] { flav } );
1046 Integer terminators = (Integer)nativeTerminators.get(lFormat);
1047 if (terminators != null) {
1048 int numTerminators = terminators.intValue();
1049 byte[] terminatedBytes =
1050 new byte[bytes.length + numTerminators];
1051 System.arraycopy(bytes, 0, terminatedBytes, 0, bytes.length);
1052 for (int i = bytes.length; i < terminatedBytes.length; i++) {
1053 terminatedBytes[i] = 0x0;
1054 }
1055 bytes = terminatedBytes;
1056 }
1057 return bytes;
1058 }
1059
1060 /**
1061 * Translating either a byte array or an InputStream into an String.
1062 * Strip terminators and search-and-replace EOLN.
1063 *
1064 * Native to Java string conversion
1065 */
1066 private String translateBytesOrStreamToString(InputStream str, byte[] bytes,
1067 long format,
1068 Transferable localeTransferable)
1069 throws IOException
1070 {
1071 // A String holds all of its data in memory at one time, so
1072 // we can't avoid reading the entire InputStream at this point.
1073 if (bytes == null) {
1074 bytes = inputStreamToByteArray(str);
1075 }
1076 str.close();
1077
1078 Long lFormat = Long.valueOf(format);
1079 String charset = getBestCharsetForTextFormat(lFormat, localeTransferable);
1080
1081 // Locate terminating NUL bytes. Note that if terminators is 0,
1082 // the we never added an entry to nativeTerminators anyway, so
1083 // we'll skip code altogether.
1084
1085 // In other words: we are doing char alignment here basing on suggestion
1086 // that count of zero-'terminators' is a number of bytes in one symbol
1087 // for selected charset (clipboard format). It is not complitly true for
1088 // multibyte coding like UTF-8, but helps understand the procedure.
1089 // "abcde\0" -> "abcde"
1090
1091 String eoln = (String)nativeEOLNs.get(lFormat);
1092 Integer terminators = (Integer)nativeTerminators.get(lFormat);
1093 int count;
1094 if (terminators != null) {
1095 int numTerminators = terminators.intValue();
1096 search:
1199 // Source data is a String. Search-and-replace EOLN. Encode into the
1200 // target format. Append terminating NUL bytes.
1201 if (stringSelectionHack ||
1202 (String.class.equals(flavor.getRepresentationClass()) &&
1203 isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1204
1205 String str = removeSuspectedData(flavor, contents, (String)obj);
1206
1207 return translateTransferableString(
1208 str,
1209 format);
1210
1211 // Source data is a Reader. Convert to a String and recur. In the
1212 // future, we may want to rewrite this so that we encode on demand.
1213 } else if (flavor.isRepresentationClassReader()) {
1214 if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1215 throw new IOException
1216 ("cannot transfer non-text data as Reader");
1217 }
1218
1219 Reader r = (Reader)obj;
1220 StringBuffer buf = new StringBuffer();
1221 int c;
1222 while ((c = r.read()) != -1) {
1223 buf.append((char)c);
1224 }
1225 r.close();
1226
1227 return translateTransferableString(
1228 buf.toString(),
1229 format);
1230
1231 // Source data is a CharBuffer. Convert to a String and recur.
1232 } else if (flavor.isRepresentationClassCharBuffer()) {
1233 if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1234 throw new IOException
1235 ("cannot transfer non-text data as CharBuffer");
1236 }
1237
1238 CharBuffer buffer = (CharBuffer)obj;
1239 int size = buffer.remaining();
1240 char[] chars = new char[size];
1241 buffer.get(chars, 0, size);
1242
1243 return translateTransferableString(
1244 new String(chars),
1245 format);
1287 } else {
1288 return bytes;
1289 }
1290 // Source data is Image
1291 } else if (DataFlavor.imageFlavor.equals(flavor)) {
1292 if (!isImageFormat(format)) {
1293 throw new IOException("Data translation failed: " +
1294 "not an image format");
1295 }
1296
1297 Image image = (Image)obj;
1298 byte[] bytes = imageToPlatformBytes(image, format);
1299
1300 if (bytes == null) {
1301 throw new IOException("Data translation failed: " +
1302 "cannot convert java image to native format");
1303 }
1304 return bytes;
1305 }
1306
1307 ByteArrayOutputStream bos = new ByteArrayOutputStream();
1308
1309 // Target data is a file list. Source data must be a
1310 // java.util.List which contains java.io.File or String instances.
1311 if (isFileFormat(format)) {
1312 if (!DataFlavor.javaFileListFlavor.equals(flavor)) {
1313 throw new IOException("data translation failed");
1314 }
1315
1316 final List list = (List)obj;
1317
1318 final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents);
1319
1320 final ArrayList<String> fileList = castToFiles(list, userProtectionDomain);
1321
1322 bos = convertFileListToBytes(fileList);
1323
1324
1325 // Target data is a URI list. Source data must be a
1326 // java.util.List which contains java.io.File or String instances.
1327 } else if (isURIListFormat(format)) {
1328 if (!DataFlavor.javaFileListFlavor.equals(flavor)) {
1329 throw new IOException("data translation failed");
1330 }
1331 String nat = getNativeForFormat(format);
1332 String targetCharset = null;
1333 if (nat != null) {
1334 try {
1335 targetCharset = new DataFlavor(nat).getParameter("charset");
1336 } catch (ClassNotFoundException cnfe) {
1337 throw new IOException(cnfe);
1338 }
1339 }
1340 if (targetCharset == null) {
1341 targetCharset = "UTF-8";
1342 }
1343 final List list = (List)obj;
1344 final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents);
1345 final ArrayList<String> fileList = castToFiles(list, userProtectionDomain);
1346 final ArrayList<String> uriList = new ArrayList<String>(fileList.size());
1347 for (String fileObject : fileList) {
1348 final URI uri = new File(fileObject).toURI();
1349 // Some implementations are fussy about the number of slashes (file:///path/to/file is best)
1350 try {
1351 uriList.add(new URI(uri.getScheme(), "", uri.getPath(), uri.getFragment()).toString());
1352 } catch (URISyntaxException uriSyntaxException) {
1353 throw new IOException(uriSyntaxException);
1354 }
1355 }
1356
1357 byte[] eoln = "\r\n".getBytes(targetCharset);
1358 for (int i = 0; i < uriList.size(); i++) {
1359 byte[] bytes = uriList.get(i).getBytes(targetCharset);
1360 bos.write(bytes, 0, bytes.length);
1361 bos.write(eoln, 0, eoln.length);
1362 }
1363
1364 // Source data is an InputStream. For arbitrary flavors, just grab the
1365 // bytes and dump them into a byte array. For text flavors, decode back
1366 // to a String and recur to reencode according to the requested format.
1367 } else if (flavor.isRepresentationClassInputStream()) {
1368 InputStream is = (InputStream)obj;
1369 boolean eof = false;
1370 int avail = is.available();
1371 byte[] tmp = new byte[avail > 8192 ? avail : 8192];
1372 do {
1373 int ret;
1374 if (!(eof = (ret = is.read(tmp, 0, tmp.length)) == -1)) {
1375 bos.write(tmp, 0, ret);
1376 }
1377 } while (!eof);
1378 is.close();
1379
1380 if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
1381 byte[] bytes = bos.toByteArray();
1382 bos.close();
1383 String sourceEncoding = DataTransferer.getTextCharset(flavor);
1384 return translateTransferableString(
1385 new String(bytes, sourceEncoding),
1386 format);
1387 }
1388
1389 // Source data is an RMI object
1390 } else if (flavor.isRepresentationClassRemote()) {
1391 Object mo = RMI.newMarshalledObject(obj);
1392 ObjectOutputStream oos = new ObjectOutputStream(bos);
1393 oos.writeObject(mo);
1394 oos.close();
1395
1396 // Source data is Serializable
1397 } else if (flavor.isRepresentationClassSerializable()) {
1398 ObjectOutputStream oos = new ObjectOutputStream(bos);
1399 oos.writeObject(obj);
1400 oos.close();
1401
1402 } else {
1403 throw new IOException("data translation failed");
1404 }
1405
1406 byte[] ret = bos.toByteArray();
1407 bos.close();
1408 return ret;
1409 }
1410
1411 protected abstract ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList) throws IOException;
1412
1413 private String removeSuspectedData(DataFlavor flavor, final Transferable contents, final String str)
1414 throws IOException
1415 {
1416 if (null == System.getSecurityManager()
1417 || !flavor.isMimeTypeEqual("text/uri-list"))
1418 {
1419 return str;
1420 }
1421
1422
1423 String ret_val = "";
1424 final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents);
1425
1426 try {
1427 ret_val = (String) AccessController.doPrivileged(new PrivilegedExceptionAction() {
1428 public Object run() {
1543 }
1544 }
1545 }
1546
1547 for (File deploymentCacheDirectory : deploymentCacheDirectoryList) {
1548 for (File dir = f; dir != null; dir = dir.getParentFile()) {
1549 if (dir.equals(deploymentCacheDirectory)) {
1550 return true;
1551 }
1552 }
1553 }
1554
1555 return false;
1556 }
1557
1558
1559 public Object translateBytes(byte[] bytes, DataFlavor flavor,
1560 long format, Transferable localeTransferable)
1561 throws IOException
1562 {
1563 return translateBytesOrStream(null, bytes, flavor, format,
1564 localeTransferable);
1565 }
1566
1567 public Object translateStream(InputStream str, DataFlavor flavor,
1568 long format, Transferable localeTransferable)
1569 throws IOException
1570 {
1571 return translateBytesOrStream(str, null, flavor, format,
1572 localeTransferable);
1573 }
1574
1575
1576 /**
1577 * Primary translation function for translating either a byte array or
1578 * an InputStream into an Object, given a source format and a target
1579 * DataFlavor.
1580 *
1581 * One of str/bytes is non-null; the other is null.
1582 * The conversion from byte[] to InputStream is cheap, so do that
1583 * immediately if necessary. The opposite conversion is expensive,
1584 * so avoid it if possible.
1585 */
1586 protected Object translateBytesOrStream(InputStream str, byte[] bytes,
1587 DataFlavor flavor, long format,
1588 Transferable localeTransferable)
1589 throws IOException
1590 {
1591
1592 if (str == null) {
1593 str = new ByteArrayInputStream(bytes);
1594 }
1595
1596 // Source data is a file list. Use the dragQueryFile native function to
1597 // do most of the decoding. Then wrap File objects around the String
1598 // filenames and return a List.
1599 if (isFileFormat(format)) {
1600 if (!DataFlavor.javaFileListFlavor.equals(flavor)) {
1601 throw new IOException("data translation failed");
1602 }
1603 if (bytes == null) {
1604 bytes = inputStreamToByteArray(str);
1605 }
1606 String[] filenames = dragQueryFile(bytes);
1607 if (filenames == null) {
1608 str.close();
1609 return null;
1610 }
1611
1612 // Convert the strings to File objects
1613 File[] files = new File[filenames.length];
1614 for (int i = 0; i < filenames.length; i++) {
1615 files[i] = new File(filenames[i]);
1616 }
1617 str.close();
1618
1619 // Turn the list of Files into a List and return
1620 return Arrays.asList(files);
1621
1622 // Source data is a URI list. Convert to DataFlavor.javaFileListFlavor
1623 // where possible.
1624 } else if (isURIListFormat(format) && DataFlavor.javaFileListFlavor.equals(flavor)) {
1625 try {
1626 URI uris[] = dragQueryURIs(str, bytes, format, localeTransferable);
1627 if (uris == null) {
1628 return null;
1629 }
1630 ArrayList files = new ArrayList();
1631 for (URI uri : uris) {
1632 try {
1633 files.add(new File(uri));
1634 } catch (IllegalArgumentException illegalArg) {
1635 // When converting from URIs to less generic files,
1636 // common practice (Wine, SWT) seems to be to
1637 // silently drop the URIs that aren't local files.
1638 }
1639 }
1640 return files;
1641 } finally {
1642 str.close();
1643 }
1644
1645 // Target data is a String. Strip terminating NUL bytes. Decode bytes
1646 // into characters. Search-and-replace EOLN.
1647 } else if (String.class.equals(flavor.getRepresentationClass()) &&
1648 isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
1649
1650 return translateBytesOrStreamToString(
1651 str, bytes,
1652 format, localeTransferable);
1653
1654 // Special hack to maintain backwards-compatibility with the brokenness
1655 // of StringSelection. Return a StringReader instead of an InputStream.
1656 // Recur to obtain String and encapsulate.
1657 } else if (DataFlavor.plainTextFlavor.equals(flavor)) {
1658 return new StringReader(translateBytesOrStreamToString(
1659 str, bytes,
1660 format, localeTransferable));
1661
1662 // Target data is an InputStream. For arbitrary flavors, just return
1663 // the raw bytes. For text flavors, decode to strip terminators and
1664 // search-and-replace EOLN, then reencode according to the requested
1665 // flavor.
1666 } else if (flavor.isRepresentationClassInputStream()) {
1667 return translateBytesOrStreamToInputStream(str, flavor, format,
1668 localeTransferable);
1669
1670 // Target data is a Reader. Obtain data in InputStream format, encoded
1671 // as "Unicode" (utf-16be). Then use an InputStreamReader to decode
1672 // back to chars on demand.
1673 } else if (flavor.isRepresentationClassReader()) {
1674 if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1675 throw new IOException
1676 ("cannot transfer non-text data as Reader");
1677 }
1678
1679 InputStream is = (InputStream)
1680 translateBytesOrStreamToInputStream
1681 (str, DataFlavor.plainTextFlavor, format,
1682 localeTransferable);
1683 String unicode =
1684 DataTransferer.getTextCharset(DataFlavor.plainTextFlavor);
1685 Reader reader = new InputStreamReader(is, unicode);
1686
1687 return constructFlavoredObject(reader, flavor, Reader.class);
1688
1689 // Target data is a CharBuffer. Recur to obtain String and wrap.
1690 } else if (flavor.isRepresentationClassCharBuffer()) {
1691 if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1692 throw new IOException
1693 ("cannot transfer non-text data as CharBuffer");
1694 }
1695
1696 CharBuffer buffer = CharBuffer.wrap(translateBytesOrStreamToString(
1697 str, bytes,
1698 format, localeTransferable));
1699
1700 return constructFlavoredObject(buffer, flavor, CharBuffer.class);
1701
1702 // Target data is a char array. Recur to obtain String and convert to
1703 // char array.
1704 } else if (charArrayClass.equals(flavor.getRepresentationClass())) {
1705 if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1706 throw new IOException
1707 ("cannot transfer non-text data as char array");
1708 }
1709
1710 return translateBytesOrStreamToString(
1711 str, bytes,
1712 format, localeTransferable).toCharArray();
1713
1714 // Target data is a ByteBuffer. For arbitrary flavors, just return
1715 // the raw bytes. For text flavors, convert to a String to strip
1716 // terminators and search-and-replace EOLN, then reencode according to
1717 // the requested flavor.
1718 } else if (flavor.isRepresentationClassByteBuffer()) {
1719 if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
1720 bytes = translateBytesOrStreamToString(
1721 str, bytes,
1722 format, localeTransferable
1723 ).getBytes(
1724 DataTransferer.getTextCharset(flavor)
1725 );
1726 } else {
1727 if (bytes == null) {
1728 bytes = inputStreamToByteArray(str);
1729 }
1730 }
1731
1732 ByteBuffer buffer = ByteBuffer.wrap(bytes);
1733 return constructFlavoredObject(buffer, flavor, ByteBuffer.class);
1734
1735 // Target data is a byte array. For arbitrary flavors, just return
1736 // the raw bytes. For text flavors, convert to a String to strip
1737 // terminators and search-and-replace EOLN, then reencode according to
1738 // the requested flavor.
1739 } else if (byteArrayClass.equals(flavor.getRepresentationClass())) {
1740 if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
1741 return translateBytesOrStreamToString(
1742 str, bytes,
1743 format, localeTransferable
1744 ).getBytes(
1745 DataTransferer.getTextCharset(flavor)
1746 );
1747 } else {
1748 return (bytes != null) ? bytes : inputStreamToByteArray(str);
1749 }
1750
1751 // Target data is an RMI object
1752 } else if (flavor.isRepresentationClassRemote()) {
1753 try {
1754 byte[] ba = inputStreamToByteArray(str);
1755 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(ba));
1756 Object ret = RMI.getMarshalledObject(ois.readObject());
1757 ois.close();
1758 str.close();
1759 return ret;
1760 } catch (Exception e) {
1761 throw new IOException(e.getMessage());
1762 }
1763
1764 // Target data is Serializable
1765 } else if (flavor.isRepresentationClassSerializable()) {
1766 try {
1767 byte[] ba = inputStreamToByteArray(str);
1768 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(ba));
1769 Object ret = ois.readObject();
1770 ois.close();
1771 str.close();
1772 return ret;
1773 } catch (Exception e) {
1774 throw new IOException(e.getMessage());
1775 }
1776
1777 // Target data is Image
1778 } else if (DataFlavor.imageFlavor.equals(flavor)) {
1779 if (!isImageFormat(format)) {
1780 throw new IOException("data translation failed");
1781 }
1782
1783 Image image = platformImageBytesOrStreamToImage(str, bytes, format);
1784 str.close();
1785 return image;
1786 }
1787
1788 throw new IOException("data translation failed");
1789 }
1790
1791 /**
1792 * For arbitrary flavors, just use the raw InputStream. For text flavors,
1793 * ReencodingInputStream will decode and reencode the InputStream on demand
1794 * so that we can strip terminators and search-and-replace EOLN.
1795 */
1796 private Object translateBytesOrStreamToInputStream
1797 (InputStream str, DataFlavor flavor, long format,
1798 Transferable localeTransferable) throws IOException
1799 {
1800 if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
1801 str = new ReencodingInputStream
1802 (str, format, DataTransferer.getTextCharset(flavor),
1803 localeTransferable);
1804 }
1805
1806 return constructFlavoredObject(str, flavor, InputStream.class);
1807 }
1808
1809 /**
1810 * We support representations which are exactly of the specified Class,
1811 * and also arbitrary Objects which have a constructor which takes an
1812 * instance of the Class as its sole parameter.
1813 */
1814 private Object constructFlavoredObject(Object arg, DataFlavor flavor,
1815 Class clazz)
1816 throws IOException
2032 }
2033
2034 if (count == array.length) {
2035 return true;
2036 } else {
2037 wrapped.reset();
2038 return false;
2039 }
2040 }
2041 }
2042
2043 /**
2044 * Decodes a byte array into a set of String filenames.
2045 */
2046 protected abstract String[] dragQueryFile(byte[] bytes);
2047
2048 /**
2049 * Decodes URIs from either a byte array or a stream.
2050 */
2051 protected URI[] dragQueryURIs(InputStream stream,
2052 byte[] bytes,
2053 long format,
2054 Transferable localeTransferable)
2055 throws IOException
2056 {
2057 throw new IOException(
2058 new UnsupportedOperationException("not implemented on this platform"));
2059 }
2060
2061 /**
2062 * Translates either a byte array or an input stream which contain
2063 * platform-specific image data in the given format into an Image.
2064 */
2065 protected abstract Image platformImageBytesOrStreamToImage(InputStream str,
2066 byte[] bytes,
2067 long format)
2068 throws IOException;
2069
2070 /**
2071 * Translates either a byte array or an input stream which contain
2072 * an image data in the given standard format into an Image.
2073 *
2074 * @param mimeType image MIME type, such as: image/png, image/jpeg, image/gif
2075 */
2076 protected Image standardImageBytesOrStreamToImage(InputStream inputStream,
2077 byte[] bytes,
2078 String mimeType)
2079 throws IOException {
2080 if (inputStream == null) {
2081 inputStream = new ByteArrayInputStream(bytes);
2082 }
2083
2084 Iterator readerIterator = ImageIO.getImageReadersByMIMEType(mimeType);
2085
2086 if (!readerIterator.hasNext()) {
2087 throw new IOException("No registered service provider can decode " +
2088 " an image from " + mimeType);
2089 }
2090
2091 IOException ioe = null;
2092
2093 while (readerIterator.hasNext()) {
2094 ImageReader imageReader = (ImageReader)readerIterator.next();
2095 try {
2096 ImageInputStream imageInputStream =
2097 ImageIO.createImageInputStream(inputStream);
2098
2099 try {
2100 ImageReadParam param = imageReader.getDefaultReadParam();
2101 imageReader.setInput(imageInputStream, true, true);
2102 BufferedImage bufferedImage =
2103 imageReader.read(imageReader.getMinIndex(), param);
2104 if (bufferedImage != null) {
2105 return bufferedImage;
2106 }
2107 } finally {
2108 imageInputStream.close();
2109 imageReader.dispose();
2110 }
2111 } catch (IOException e) {
2112 ioe = e;
2113 continue;
2114 }
2115 }
2116
2117 if (ioe == null) {
2407
2408 /**
2409 * Helper function to convert a Set of DataFlavors to a sorted array.
2410 * The array will be sorted according to <code>DataFlavorComparator</code>.
2411 */
2412 public static DataFlavor[] setToSortedDataFlavorArray(Set flavorsSet) {
2413 DataFlavor[] flavors = new DataFlavor[flavorsSet.size()];
2414 flavorsSet.toArray(flavors);
2415 final Comparator comparator =
2416 new DataFlavorComparator(IndexedComparator.SELECT_WORST);
2417 Arrays.sort(flavors, comparator);
2418 return flavors;
2419 }
2420
2421 /**
2422 * Helper function to convert an InputStream to a byte[] array.
2423 */
2424 protected static byte[] inputStreamToByteArray(InputStream str)
2425 throws IOException
2426 {
2427 ByteArrayOutputStream baos = new ByteArrayOutputStream();
2428 int len = 0;
2429 byte[] buf = new byte[8192];
2430
2431 while ((len = str.read(buf)) != -1) {
2432 baos.write(buf, 0, len);
2433 }
2434
2435 return baos.toByteArray();
2436 }
2437
2438 /**
2439 * Returns platform-specific mappings for the specified native.
2440 * If there are no platform-specific mappings for this native, the method
2441 * returns an empty <code>List</code>.
2442 */
2443 public List getPlatformMappingsForNative(String nat) {
2444 return new ArrayList();
2445 }
2446
2447 /**
2448 * Returns platform-specific mappings for the specified flavor.
2449 * If there are no platform-specific mappings for this flavor, the method
2450 * returns an empty <code>List</code>.
2451 */
2452 public List getPlatformMappingsForFlavor(DataFlavor df) {
2453 return new ArrayList();
2454 }
2455
|
154 * representationClass = java.lang.String
155 * mimeType = "text/plain; charset=Unicode"
156 * </pre>
157 */
158 public static final DataFlavor plainTextStringFlavor;
159
160 /**
161 * The <code>DataFlavor</code> representing a Java text encoding String
162 * encoded in UTF-8, where
163 * <pre>
164 * representationClass = [B
165 * mimeType = "application/x-java-text-encoding"
166 * </pre>
167 */
168 public static final DataFlavor javaTextEncodingFlavor;
169
170 /**
171 * Lazy initialization of Standard Encodings.
172 */
173 private static class StandardEncodingsHolder {
174 private static final SortedSet<String> standardEncodings = load();
175
176 private static SortedSet<String> load() {
177 final Comparator comparator =
178 new CharsetComparator(IndexedComparator.SELECT_WORST);
179 final SortedSet<String> tempSet = new TreeSet<String>(comparator);
180 tempSet.add("US-ASCII");
181 tempSet.add("ISO-8859-1");
182 tempSet.add("UTF-8");
183 tempSet.add("UTF-16BE");
184 tempSet.add("UTF-16LE");
185 tempSet.add("UTF-16");
186 tempSet.add(getDefaultTextCharset());
187 return Collections.unmodifiableSortedSet(tempSet);
188 }
189 }
190
191 /**
192 * Tracks whether a particular text/* MIME type supports the charset
193 * parameter. The Map is initialized with all of the standard MIME types
194 * listed in the DataFlavor.selectBestTextFlavor method comment. Additional
195 * entries may be added during the life of the JRE for text/<other> types.
196 */
197 private static final Map textMIMESubtypeCharsetSupport;
198
199 /**
506 return Charset.isSupported(encoding);
507 } catch (IllegalCharsetNameException icne) {
508 return false;
509 }
510 }
511
512 /**
513 * Returns {@code true} if the given type is a java.rmi.Remote.
514 */
515 public static boolean isRemote(Class<?> type) {
516 return RMI.isRemote(type);
517 }
518
519 /**
520 * Returns an Iterator which traverses a SortedSet of Strings which are
521 * a total order of the standard character sets supported by the JRE. The
522 * ordering follows the same principles as DataFlavor.selectBestTextFlavor.
523 * So as to avoid loading all available character converters, optional,
524 * non-standard, character sets are not included.
525 */
526 public static Set <String> standardEncodings() {
527 return StandardEncodingsHolder.standardEncodings;
528 }
529
530 /**
531 * Converts a FlavorMap to a FlavorTable.
532 */
533 public static FlavorTable adaptFlavorMap(final FlavorMap map) {
534 if (map instanceof FlavorTable) {
535 return (FlavorTable)map;
536 }
537
538 return new FlavorTable() {
539 public Map getNativesForFlavors(DataFlavor[] flavors) {
540 return map.getNativesForFlavors(flavors);
541 }
542 public Map getFlavorsForNatives(String[] natives) {
543 return map.getFlavorsForNatives(natives);
544 }
545 public List getNativesForFlavor(DataFlavor flav) {
546 Map natives =
547 getNativesForFlavors(new DataFlavor[] { flav } );
1046 Integer terminators = (Integer)nativeTerminators.get(lFormat);
1047 if (terminators != null) {
1048 int numTerminators = terminators.intValue();
1049 byte[] terminatedBytes =
1050 new byte[bytes.length + numTerminators];
1051 System.arraycopy(bytes, 0, terminatedBytes, 0, bytes.length);
1052 for (int i = bytes.length; i < terminatedBytes.length; i++) {
1053 terminatedBytes[i] = 0x0;
1054 }
1055 bytes = terminatedBytes;
1056 }
1057 return bytes;
1058 }
1059
1060 /**
1061 * Translating either a byte array or an InputStream into an String.
1062 * Strip terminators and search-and-replace EOLN.
1063 *
1064 * Native to Java string conversion
1065 */
1066 private String translateBytesToString(byte[] bytes, long format,
1067 Transferable localeTransferable)
1068 throws IOException
1069 {
1070
1071 Long lFormat = Long.valueOf(format);
1072 String charset = getBestCharsetForTextFormat(lFormat, localeTransferable);
1073
1074 // Locate terminating NUL bytes. Note that if terminators is 0,
1075 // the we never added an entry to nativeTerminators anyway, so
1076 // we'll skip code altogether.
1077
1078 // In other words: we are doing char alignment here basing on suggestion
1079 // that count of zero-'terminators' is a number of bytes in one symbol
1080 // for selected charset (clipboard format). It is not complitly true for
1081 // multibyte coding like UTF-8, but helps understand the procedure.
1082 // "abcde\0" -> "abcde"
1083
1084 String eoln = (String)nativeEOLNs.get(lFormat);
1085 Integer terminators = (Integer)nativeTerminators.get(lFormat);
1086 int count;
1087 if (terminators != null) {
1088 int numTerminators = terminators.intValue();
1089 search:
1192 // Source data is a String. Search-and-replace EOLN. Encode into the
1193 // target format. Append terminating NUL bytes.
1194 if (stringSelectionHack ||
1195 (String.class.equals(flavor.getRepresentationClass()) &&
1196 isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1197
1198 String str = removeSuspectedData(flavor, contents, (String)obj);
1199
1200 return translateTransferableString(
1201 str,
1202 format);
1203
1204 // Source data is a Reader. Convert to a String and recur. In the
1205 // future, we may want to rewrite this so that we encode on demand.
1206 } else if (flavor.isRepresentationClassReader()) {
1207 if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1208 throw new IOException
1209 ("cannot transfer non-text data as Reader");
1210 }
1211
1212 StringBuffer buf = new StringBuffer();
1213 try (Reader r = (Reader)obj) {
1214 int c;
1215 while ((c = r.read()) != -1) {
1216 buf.append((char)c);
1217 }
1218 }
1219
1220 return translateTransferableString(
1221 buf.toString(),
1222 format);
1223
1224 // Source data is a CharBuffer. Convert to a String and recur.
1225 } else if (flavor.isRepresentationClassCharBuffer()) {
1226 if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1227 throw new IOException
1228 ("cannot transfer non-text data as CharBuffer");
1229 }
1230
1231 CharBuffer buffer = (CharBuffer)obj;
1232 int size = buffer.remaining();
1233 char[] chars = new char[size];
1234 buffer.get(chars, 0, size);
1235
1236 return translateTransferableString(
1237 new String(chars),
1238 format);
1280 } else {
1281 return bytes;
1282 }
1283 // Source data is Image
1284 } else if (DataFlavor.imageFlavor.equals(flavor)) {
1285 if (!isImageFormat(format)) {
1286 throw new IOException("Data translation failed: " +
1287 "not an image format");
1288 }
1289
1290 Image image = (Image)obj;
1291 byte[] bytes = imageToPlatformBytes(image, format);
1292
1293 if (bytes == null) {
1294 throw new IOException("Data translation failed: " +
1295 "cannot convert java image to native format");
1296 }
1297 return bytes;
1298 }
1299
1300 byte[] theByteArray = null;
1301
1302 // Target data is a file list. Source data must be a
1303 // java.util.List which contains java.io.File or String instances.
1304 if (isFileFormat(format)) {
1305 if (!DataFlavor.javaFileListFlavor.equals(flavor)) {
1306 throw new IOException("data translation failed");
1307 }
1308
1309 final List list = (List)obj;
1310
1311 final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents);
1312
1313 final ArrayList<String> fileList = castToFiles(list, userProtectionDomain);
1314
1315 try (ByteArrayOutputStream bos = convertFileListToBytes(fileList)) {
1316 theByteArray = bos.toByteArray();
1317 }
1318
1319 // Target data is a URI list. Source data must be a
1320 // java.util.List which contains java.io.File or String instances.
1321 } else if (isURIListFormat(format)) {
1322 if (!DataFlavor.javaFileListFlavor.equals(flavor)) {
1323 throw new IOException("data translation failed");
1324 }
1325 String nat = getNativeForFormat(format);
1326 String targetCharset = null;
1327 if (nat != null) {
1328 try {
1329 targetCharset = new DataFlavor(nat).getParameter("charset");
1330 } catch (ClassNotFoundException cnfe) {
1331 throw new IOException(cnfe);
1332 }
1333 }
1334 if (targetCharset == null) {
1335 targetCharset = "UTF-8";
1336 }
1337 final List list = (List)obj;
1338 final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents);
1339 final ArrayList<String> fileList = castToFiles(list, userProtectionDomain);
1340 final ArrayList<String> uriList = new ArrayList<String>(fileList.size());
1341 for (String fileObject : fileList) {
1342 final URI uri = new File(fileObject).toURI();
1343 // Some implementations are fussy about the number of slashes (file:///path/to/file is best)
1344 try {
1345 uriList.add(new URI(uri.getScheme(), "", uri.getPath(), uri.getFragment()).toString());
1346 } catch (URISyntaxException uriSyntaxException) {
1347 throw new IOException(uriSyntaxException);
1348 }
1349 }
1350
1351 byte[] eoln = "\r\n".getBytes(targetCharset);
1352
1353 try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
1354 for (int i = 0; i < uriList.size(); i++) {
1355 byte[] bytes = uriList.get(i).getBytes(targetCharset);
1356 bos.write(bytes, 0, bytes.length);
1357 bos.write(eoln, 0, eoln.length);
1358 }
1359 theByteArray = bos.toByteArray();
1360 }
1361
1362 // Source data is an InputStream. For arbitrary flavors, just grab the
1363 // bytes and dump them into a byte array. For text flavors, decode back
1364 // to a String and recur to reencode according to the requested format.
1365 } else if (flavor.isRepresentationClassInputStream()) {
1366 try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
1367 try (InputStream is = (InputStream)obj) {
1368 boolean eof = false;
1369 int avail = is.available();
1370 byte[] tmp = new byte[avail > 8192 ? avail : 8192];
1371 do {
1372 int aValue;
1373 if (!(eof = (aValue = is.read(tmp, 0, tmp.length)) == -1)) {
1374 bos.write(tmp, 0, aValue);
1375 }
1376 } while (!eof);
1377 }
1378
1379 if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
1380 byte[] bytes = bos.toByteArray();
1381 String sourceEncoding = DataTransferer.getTextCharset(flavor);
1382 return translateTransferableString(
1383 new String(bytes, sourceEncoding),
1384 format);
1385 }
1386 theByteArray = bos.toByteArray();
1387 }
1388
1389
1390
1391 // Source data is an RMI object
1392 } else if (flavor.isRepresentationClassRemote()) {
1393
1394 Object mo = RMI.newMarshalledObject(obj);
1395 theByteArray = convertObjectToBytes(mo);
1396
1397 // Source data is Serializable
1398 } else if (flavor.isRepresentationClassSerializable()) {
1399
1400 theByteArray = convertObjectToBytes(obj);
1401
1402 } else {
1403 throw new IOException("data translation failed");
1404 }
1405
1406
1407
1408 return theByteArray;
1409 }
1410
1411 private static byte[] convertObjectToBytes(Object object) throws IOException {
1412 try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
1413 ObjectOutputStream oos = new ObjectOutputStream(bos))
1414 {
1415 oos.writeObject(object);
1416 return bos.toByteArray();
1417 }
1418 }
1419
1420 protected abstract ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList) throws IOException;
1421
1422 private String removeSuspectedData(DataFlavor flavor, final Transferable contents, final String str)
1423 throws IOException
1424 {
1425 if (null == System.getSecurityManager()
1426 || !flavor.isMimeTypeEqual("text/uri-list"))
1427 {
1428 return str;
1429 }
1430
1431
1432 String ret_val = "";
1433 final ProtectionDomain userProtectionDomain = getUserProtectionDomain(contents);
1434
1435 try {
1436 ret_val = (String) AccessController.doPrivileged(new PrivilegedExceptionAction() {
1437 public Object run() {
1552 }
1553 }
1554 }
1555
1556 for (File deploymentCacheDirectory : deploymentCacheDirectoryList) {
1557 for (File dir = f; dir != null; dir = dir.getParentFile()) {
1558 if (dir.equals(deploymentCacheDirectory)) {
1559 return true;
1560 }
1561 }
1562 }
1563
1564 return false;
1565 }
1566
1567
1568 public Object translateBytes(byte[] bytes, DataFlavor flavor,
1569 long format, Transferable localeTransferable)
1570 throws IOException
1571 {
1572
1573 Object theObject = null;
1574
1575 // Source data is a file list. Use the dragQueryFile native function to
1576 // do most of the decoding. Then wrap File objects around the String
1577 // filenames and return a List.
1578 if (isFileFormat(format)) {
1579 if (!DataFlavor.javaFileListFlavor.equals(flavor)) {
1580 throw new IOException("data translation failed");
1581 }
1582 String[] filenames = dragQueryFile(bytes);
1583 if (filenames == null) {
1584 return null;
1585 }
1586
1587 // Convert the strings to File objects
1588 File[] files = new File[filenames.length];
1589 for (int i = 0; i < filenames.length; i++) {
1590 files[i] = new File(filenames[i]);
1591 }
1592
1593 // Turn the list of Files into a List and return
1594 theObject = Arrays.asList(files);
1595
1596 // Target data is a String. Strip terminating NUL bytes. Decode bytes
1597 // into characters. Search-and-replace EOLN.
1598 } else if (String.class.equals(flavor.getRepresentationClass()) &&
1599 isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
1600
1601 theObject = translateBytesToString(bytes, format, localeTransferable);
1602
1603 // Target data is a Reader. Obtain data in InputStream format, encoded
1604 // as "Unicode" (utf-16be). Then use an InputStreamReader to decode
1605 // back to chars on demand.
1606 } else if (flavor.isRepresentationClassReader()) {
1607 try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
1608 theObject = translateStream(bais,
1609 flavor, format, localeTransferable);
1610 }
1611 // Target data is a CharBuffer. Recur to obtain String and wrap.
1612 } else if (flavor.isRepresentationClassCharBuffer()) {
1613 if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1614 throw new IOException
1615 ("cannot transfer non-text data as CharBuffer");
1616 }
1617
1618 CharBuffer buffer = CharBuffer.wrap(
1619 translateBytesToString(bytes,format, localeTransferable));
1620
1621 theObject = constructFlavoredObject(buffer, flavor, CharBuffer.class);
1622
1623 // Target data is a char array. Recur to obtain String and convert to
1624 // char array.
1625 } else if (charArrayClass.equals(flavor.getRepresentationClass())) {
1626 if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1627 throw new IOException
1628 ("cannot transfer non-text data as char array");
1629 }
1630
1631 theObject = translateBytesToString(
1632 bytes, format, localeTransferable).toCharArray();
1633
1634 // Target data is a ByteBuffer. For arbitrary flavors, just return
1635 // the raw bytes. For text flavors, convert to a String to strip
1636 // terminators and search-and-replace EOLN, then reencode according to
1637 // the requested flavor.
1638 } else if (flavor.isRepresentationClassByteBuffer()) {
1639 if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
1640 bytes = translateBytesToString(
1641 bytes, format, localeTransferable).getBytes(
1642 DataTransferer.getTextCharset(flavor)
1643 );
1644 }
1645
1646 ByteBuffer buffer = ByteBuffer.wrap(bytes);
1647 theObject = constructFlavoredObject(buffer, flavor, ByteBuffer.class);
1648
1649 // Target data is a byte array. For arbitrary flavors, just return
1650 // the raw bytes. For text flavors, convert to a String to strip
1651 // terminators and search-and-replace EOLN, then reencode according to
1652 // the requested flavor.
1653 } else if (byteArrayClass.equals(flavor.getRepresentationClass())) {
1654 if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
1655 theObject = translateBytesToString(
1656 bytes, format, localeTransferable
1657 ).getBytes(DataTransferer.getTextCharset(flavor));
1658 } else {
1659 theObject = bytes;
1660 }
1661
1662 // Target data is an InputStream. For arbitrary flavors, just return
1663 // the raw bytes. For text flavors, decode to strip terminators and
1664 // search-and-replace EOLN, then reencode according to the requested
1665 // flavor.
1666 } else if (flavor.isRepresentationClassInputStream()) {
1667
1668 try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
1669 theObject = translateStream(bais, flavor, format, localeTransferable);
1670 }
1671
1672 // Target data is Serializable
1673 } else if (flavor.isRepresentationClassSerializable()) {
1674
1675 try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
1676 theObject = translateStream(bais, flavor, format, localeTransferable);
1677 }
1678
1679 // Target data is Image
1680 } else if (DataFlavor.imageFlavor.equals(flavor)) {
1681 if (!isImageFormat(format)) {
1682 throw new IOException("data translation failed");
1683 }
1684
1685 theObject = platformImageBytesToImage(bytes, format);
1686 }
1687
1688 if (theObject == null) {
1689 throw new IOException("data translation failed");
1690 }
1691
1692 return theObject;
1693
1694 }
1695
1696 /**
1697 * Primary translation function for translating
1698 * an InputStream into an Object, given a source format and a target
1699 * DataFlavor.
1700 */
1701 public Object translateStream(InputStream str, DataFlavor flavor,
1702 long format, Transferable localeTransferable)
1703 throws IOException
1704 {
1705
1706 Object theObject = null;
1707 // Source data is a URI list. Convert to DataFlavor.javaFileListFlavor
1708 // where possible.
1709 if (isURIListFormat(format)
1710 && DataFlavor.javaFileListFlavor.equals(flavor))
1711 {
1712
1713 URI uris[] = dragQueryURIs(str, format, localeTransferable);
1714 if (uris == null) {
1715 return null;
1716 }
1717 ArrayList files = new ArrayList();
1718 for (URI uri : uris) {
1719 try {
1720 files.add(new File(uri));
1721 } catch (IllegalArgumentException illegalArg) {
1722 // When converting from URIs to less generic files,
1723 // common practice (Wine, SWT) seems to be to
1724 // silently drop the URIs that aren't local files.
1725 }
1726 }
1727 theObject = files;
1728
1729 // Special hack to maintain backwards-compatibility with the brokenness
1730 // of StringSelection. Return a StringReader instead of an InputStream.
1731 // Recur to obtain String and encapsulate.
1732 } else if (DataFlavor.plainTextFlavor.equals(flavor)) {
1733 theObject = new StringReader(translateBytesToString(
1734 inputStreamToByteArray(str),
1735 format, localeTransferable));
1736
1737 // Target data is an InputStream. For arbitrary flavors, just return
1738 // the raw bytes. For text flavors, decode to strip terminators and
1739 // search-and-replace EOLN, then reencode according to the requested
1740 // flavor.
1741 } else if (flavor.isRepresentationClassInputStream()) {
1742 theObject = translateStreamToInputStream(str, flavor, format,
1743 localeTransferable);
1744
1745 // Target data is a Reader. Obtain data in InputStream format, encoded
1746 // as "Unicode" (utf-16be). Then use an InputStreamReader to decode
1747 // back to chars on demand.
1748 } else if (flavor.isRepresentationClassReader()) {
1749 if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
1750 throw new IOException
1751 ("cannot transfer non-text data as Reader");
1752 }
1753
1754 InputStream is = (InputStream)translateStreamToInputStream(
1755 str, DataFlavor.plainTextFlavor,
1756 format, localeTransferable);
1757
1758 String unicode = DataTransferer.getTextCharset(DataFlavor.plainTextFlavor);
1759
1760 Reader reader = new InputStreamReader(is, unicode);
1761
1762 theObject = constructFlavoredObject(reader, flavor, Reader.class);
1763
1764 // Target data is an RMI object
1765 } else if (flavor.isRepresentationClassRemote()) {
1766
1767 try (ObjectInputStream ois =
1768 new ObjectInputStream(str))
1769 {
1770 theObject = RMI.getMarshalledObject(ois.readObject());
1771 }catch (Exception e) {
1772 throw new IOException(e.getMessage());
1773 }
1774
1775 // Target data is Serializable
1776 } else if (flavor.isRepresentationClassSerializable()) {
1777 try (ObjectInputStream ois =
1778 new ObjectInputStream(str))
1779 {
1780 theObject = ois.readObject();
1781 } catch (Exception e) {
1782 throw new IOException(e.getMessage());
1783 }
1784 }
1785
1786
1787 return theObject;
1788
1789 }
1790
1791 /**
1792 * For arbitrary flavors, just use the raw InputStream. For text flavors,
1793 * ReencodingInputStream will decode and reencode the InputStream on demand
1794 * so that we can strip terminators and search-and-replace EOLN.
1795 */
1796 private Object translateStreamToInputStream
1797 (InputStream str, DataFlavor flavor, long format,
1798 Transferable localeTransferable) throws IOException
1799 {
1800 if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
1801 str = new ReencodingInputStream
1802 (str, format, DataTransferer.getTextCharset(flavor),
1803 localeTransferable);
1804 }
1805
1806 return constructFlavoredObject(str, flavor, InputStream.class);
1807 }
1808
1809 /**
1810 * We support representations which are exactly of the specified Class,
1811 * and also arbitrary Objects which have a constructor which takes an
1812 * instance of the Class as its sole parameter.
1813 */
1814 private Object constructFlavoredObject(Object arg, DataFlavor flavor,
1815 Class clazz)
1816 throws IOException
2032 }
2033
2034 if (count == array.length) {
2035 return true;
2036 } else {
2037 wrapped.reset();
2038 return false;
2039 }
2040 }
2041 }
2042
2043 /**
2044 * Decodes a byte array into a set of String filenames.
2045 */
2046 protected abstract String[] dragQueryFile(byte[] bytes);
2047
2048 /**
2049 * Decodes URIs from either a byte array or a stream.
2050 */
2051 protected URI[] dragQueryURIs(InputStream stream,
2052 long format,
2053 Transferable localeTransferable)
2054 throws IOException
2055 {
2056 throw new IOException(
2057 new UnsupportedOperationException("not implemented on this platform"));
2058 }
2059
2060 /**
2061 * Translates either a byte array or an input stream which contain
2062 * platform-specific image data in the given format into an Image.
2063 */
2064
2065
2066 protected abstract Image platformImageBytesToImage(
2067 byte[] bytes,long format) throws IOException;
2068
2069 /**
2070 * Translates either a byte array or an input stream which contain
2071 * an image data in the given standard format into an Image.
2072 *
2073 * @param mimeType image MIME type, such as: image/png, image/jpeg, image/gif
2074 */
2075 protected Image standardImageBytesToImage(
2076 byte[] bytes, String mimeType) throws IOException
2077 {
2078
2079 Iterator readerIterator = ImageIO.getImageReadersByMIMEType(mimeType);
2080
2081 if (!readerIterator.hasNext()) {
2082 throw new IOException("No registered service provider can decode " +
2083 " an image from " + mimeType);
2084 }
2085
2086 IOException ioe = null;
2087
2088 while (readerIterator.hasNext()) {
2089 ImageReader imageReader = (ImageReader)readerIterator.next();
2090 try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) {
2091 ImageInputStream imageInputStream =
2092 ImageIO.createImageInputStream(bais);
2093
2094 try {
2095 ImageReadParam param = imageReader.getDefaultReadParam();
2096 imageReader.setInput(imageInputStream, true, true);
2097 BufferedImage bufferedImage =
2098 imageReader.read(imageReader.getMinIndex(), param);
2099 if (bufferedImage != null) {
2100 return bufferedImage;
2101 }
2102 } finally {
2103 imageInputStream.close();
2104 imageReader.dispose();
2105 }
2106 } catch (IOException e) {
2107 ioe = e;
2108 continue;
2109 }
2110 }
2111
2112 if (ioe == null) {
2402
2403 /**
2404 * Helper function to convert a Set of DataFlavors to a sorted array.
2405 * The array will be sorted according to <code>DataFlavorComparator</code>.
2406 */
2407 public static DataFlavor[] setToSortedDataFlavorArray(Set flavorsSet) {
2408 DataFlavor[] flavors = new DataFlavor[flavorsSet.size()];
2409 flavorsSet.toArray(flavors);
2410 final Comparator comparator =
2411 new DataFlavorComparator(IndexedComparator.SELECT_WORST);
2412 Arrays.sort(flavors, comparator);
2413 return flavors;
2414 }
2415
2416 /**
2417 * Helper function to convert an InputStream to a byte[] array.
2418 */
2419 protected static byte[] inputStreamToByteArray(InputStream str)
2420 throws IOException
2421 {
2422 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
2423 int len = 0;
2424 byte[] buf = new byte[8192];
2425
2426 while ((len = str.read(buf)) != -1) {
2427 baos.write(buf, 0, len);
2428 }
2429
2430 return baos.toByteArray();
2431 }
2432 }
2433
2434 /**
2435 * Returns platform-specific mappings for the specified native.
2436 * If there are no platform-specific mappings for this native, the method
2437 * returns an empty <code>List</code>.
2438 */
2439 public List getPlatformMappingsForNative(String nat) {
2440 return new ArrayList();
2441 }
2442
2443 /**
2444 * Returns platform-specific mappings for the specified flavor.
2445 * If there are no platform-specific mappings for this flavor, the method
2446 * returns an empty <code>List</code>.
2447 */
2448 public List getPlatformMappingsForFlavor(DataFlavor df) {
2449 return new ArrayList();
2450 }
2451
|