src/share/classes/sun/awt/datatransfer/DataTransferer.java
Print this page
*** 59,81 ****
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.*;
! import sun.util.logging.PlatformLogger;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import java.awt.image.BufferedImage;
--- 59,79 ----
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.*;
! import sun.datatransfer.DataFlavorUtil;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import java.awt.image.BufferedImage;
*** 133,171 ****
* </pre>
*/
public static final DataFlavor javaTextEncodingFlavor;
/**
- * Lazy initialization of Standard Encodings.
- */
- private static class StandardEncodingsHolder {
- private static final SortedSet<String> standardEncodings = load();
-
- private static SortedSet<String> load() {
- final Comparator<String> comparator =
- new CharsetComparator(IndexedComparator.SELECT_WORST);
- final SortedSet<String> tempSet = new TreeSet<>(comparator);
- tempSet.add("US-ASCII");
- tempSet.add("ISO-8859-1");
- tempSet.add("UTF-8");
- tempSet.add("UTF-16BE");
- tempSet.add("UTF-16LE");
- tempSet.add("UTF-16");
- tempSet.add(Charset.defaultCharset().name());
- return Collections.unmodifiableSortedSet(tempSet);
- }
- }
-
- /**
- * Tracks whether a particular text/* MIME type supports the charset
- * parameter. The Map is initialized with all of the standard MIME types
- * listed in the DataFlavor.selectBestTextFlavor method comment. Additional
- * entries may be added during the life of the JRE for text/<other> types.
- */
- private static final Map<String, Boolean> textMIMESubtypeCharsetSupport;
-
- /**
* A collection of all natives listed in flavormap.properties with
* a primary MIME type of "text".
*/
private static final Set<Long> textNatives =
Collections.synchronizedSet(new HashSet<>());
--- 131,140 ----
*** 191,227 ****
/**
* The key used to store pending data conversion requests for an AppContext.
*/
private static final String DATA_CONVERTER_KEY = "DATA_CONVERTER_KEY";
- private static final PlatformLogger dtLog = PlatformLogger.getLogger("sun.awt.datatransfer.DataTransfer");
-
static {
DataFlavor tJavaTextEncodingFlavor = null;
try {
tJavaTextEncodingFlavor = new DataFlavor("application/x-java-text-encoding;class=\"[B\"");
} catch (ClassNotFoundException cannotHappen) {
}
javaTextEncodingFlavor = tJavaTextEncodingFlavor;
-
- Map<String, Boolean> tempMap = new HashMap<>(17);
- tempMap.put("sgml", Boolean.TRUE);
- tempMap.put("xml", Boolean.TRUE);
- tempMap.put("html", Boolean.TRUE);
- tempMap.put("enriched", Boolean.TRUE);
- tempMap.put("richtext", Boolean.TRUE);
- tempMap.put("uri-list", Boolean.TRUE);
- tempMap.put("directory", Boolean.TRUE);
- tempMap.put("css", Boolean.TRUE);
- tempMap.put("calendar", Boolean.TRUE);
- tempMap.put("plain", Boolean.TRUE);
- tempMap.put("rtf", Boolean.FALSE);
- tempMap.put("tab-separated-values", Boolean.FALSE);
- tempMap.put("t140", Boolean.FALSE);
- tempMap.put("rfc822-headers", Boolean.FALSE);
- tempMap.put("parityfec", Boolean.FALSE);
- textMIMESubtypeCharsetSupport = Collections.synchronizedMap(tempMap);
}
/**
* The accessor method for the singleton DataTransferer instance. Note
* that in a headless environment, there may be no DataTransferer instance;
--- 160,176 ----
*** 230,404 ****
public static synchronized DataTransferer getInstance() {
return ((SunToolkit) Toolkit.getDefaultToolkit()).getDataTransferer();
}
/**
- * Converts an arbitrary text encoding to its canonical name.
- */
- public static String canonicalName(String encoding) {
- if (encoding == null) {
- return null;
- }
- try {
- return Charset.forName(encoding).name();
- } catch (IllegalCharsetNameException icne) {
- return encoding;
- } catch (UnsupportedCharsetException uce) {
- return encoding;
- }
- }
-
- /**
- * If the specified flavor is a text flavor which supports the "charset"
- * parameter, then this method returns that parameter, or the default
- * charset if no such parameter was specified at construction. For non-
- * text DataFlavors, and for non-charset text flavors, this method returns
- * null.
- */
- public static String getTextCharset(DataFlavor flavor) {
- if (!isFlavorCharsetTextType(flavor)) {
- return null;
- }
-
- String encoding = flavor.getParameter("charset");
-
- return (encoding != null) ? encoding : Charset.defaultCharset().name();
- }
-
- /**
- * Tests only whether the flavor's MIME type supports the charset
- * parameter. Must only be called for flavors with a primary type of
- * "text".
- */
- public static boolean doesSubtypeSupportCharset(DataFlavor flavor) {
- if (dtLog.isLoggable(PlatformLogger.Level.FINE)) {
- if (!"text".equals(flavor.getPrimaryType())) {
- dtLog.fine("Assertion (\"text\".equals(flavor.getPrimaryType())) failed");
- }
- }
-
- String subType = flavor.getSubType();
- if (subType == null) {
- return false;
- }
-
- Boolean support = textMIMESubtypeCharsetSupport.get(subType);
-
- if (support != null) {
- return support;
- }
-
- boolean ret_val = (flavor.getParameter("charset") != null);
- textMIMESubtypeCharsetSupport.put(subType, ret_val);
- return ret_val;
- }
- public static boolean doesSubtypeSupportCharset(String subType,
- String charset)
- {
- Boolean support = textMIMESubtypeCharsetSupport.get(subType);
-
- if (support != null) {
- return support;
- }
-
- boolean ret_val = (charset != null);
- textMIMESubtypeCharsetSupport.put(subType, ret_val);
- return ret_val;
- }
-
- /**
- * Returns whether this flavor is a text type which supports the
- * 'charset' parameter.
- */
- public static boolean isFlavorCharsetTextType(DataFlavor flavor) {
- // Although stringFlavor doesn't actually support the charset
- // parameter (because its primary MIME type is not "text"), it should
- // be treated as though it does. stringFlavor is semantically
- // equivalent to "text/plain" data.
- if (DataFlavor.stringFlavor.equals(flavor)) {
- return true;
- }
-
- if (!"text".equals(flavor.getPrimaryType()) ||
- !doesSubtypeSupportCharset(flavor))
- {
- return false;
- }
-
- Class<?> rep_class = flavor.getRepresentationClass();
-
- if (flavor.isRepresentationClassReader() ||
- String.class.equals(rep_class) ||
- flavor.isRepresentationClassCharBuffer() ||
- char[].class.equals(rep_class))
- {
- return true;
- }
-
- if (!(flavor.isRepresentationClassInputStream() ||
- flavor.isRepresentationClassByteBuffer() ||
- byte[].class.equals(rep_class))) {
- return false;
- }
-
- String charset = flavor.getParameter("charset");
-
- return (charset != null)
- ? DataTransferer.isEncodingSupported(charset)
- : true; // null equals default encoding which is always supported
- }
-
- /**
- * Returns whether this flavor is a text type which does not support the
- * 'charset' parameter.
- */
- public static boolean isFlavorNoncharsetTextType(DataFlavor flavor) {
- if (!"text".equals(flavor.getPrimaryType()) ||
- doesSubtypeSupportCharset(flavor))
- {
- return false;
- }
-
- return (flavor.isRepresentationClassInputStream() ||
- flavor.isRepresentationClassByteBuffer() ||
- byte[].class.equals(flavor.getRepresentationClass()));
- }
-
- /**
- * Determines whether this JRE can both encode and decode text in the
- * specified encoding.
- */
- private static boolean isEncodingSupported(String encoding) {
- if (encoding == null) {
- return false;
- }
- try {
- return Charset.isSupported(encoding);
- } catch (IllegalCharsetNameException icne) {
- return false;
- }
- }
-
- /**
- * Returns {@code true} if the given type is a java.rmi.Remote.
- */
- public static boolean isRemote(Class<?> type) {
- return RMI.isRemote(type);
- }
-
- /**
- * Returns an Iterator which traverses a SortedSet of Strings which are
- * a total order of the standard character sets supported by the JRE. The
- * ordering follows the same principles as DataFlavor.selectBestTextFlavor.
- * So as to avoid loading all available character converters, optional,
- * non-standard, character sets are not included.
- */
- public static Set <String> standardEncodings() {
- return StandardEncodingsHolder.standardEncodings;
- }
-
- /**
* Converts a FlavorMap to a FlavorTable.
*/
public static FlavorTable adaptFlavorMap(final FlavorMap map) {
if (map instanceof FlavorTable) {
return (FlavorTable)map;
--- 179,188 ----
*** 598,609 ****
formatMap.putAll(textPlainMap);
indexMap.putAll(textPlainIndexMap);
// Sort the map keys according to the formats preference order.
! Comparator<Long> comparator =
! new IndexOrderComparator(indexMap, IndexedComparator.SELECT_WORST);
SortedMap<Long, DataFlavor> sortedMap = new TreeMap<>(comparator);
sortedMap.putAll(formatMap);
return sortedMap;
}
--- 382,392 ----
formatMap.putAll(textPlainMap);
indexMap.putAll(textPlainIndexMap);
// Sort the map keys according to the formats preference order.
! Comparator<Long> comparator = DataFlavorUtil.getIndexOrderComparator(indexMap).reversed();
SortedMap<Long, DataFlavor> sortedMap = new TreeMap<>(comparator);
sortedMap.putAll(formatMap);
return sortedMap;
}
*** 970,991 ****
// Source data is a String. Search-and-replace EOLN. Encode into the
// target format. Append terminating NUL bytes.
if (stringSelectionHack ||
(String.class.equals(flavor.getRepresentationClass()) &&
! isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
String str = removeSuspectedData(flavor, contents, (String)obj);
return translateTransferableString(
str,
format);
// Source data is a Reader. Convert to a String and recur. In the
// future, we may want to rewrite this so that we encode on demand.
} else if (flavor.isRepresentationClassReader()) {
! if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
throw new IOException
("cannot transfer non-text data as Reader");
}
StringBuilder buf = new StringBuilder();
--- 753,774 ----
// Source data is a String. Search-and-replace EOLN. Encode into the
// target format. Append terminating NUL bytes.
if (stringSelectionHack ||
(String.class.equals(flavor.getRepresentationClass()) &&
! DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
String str = removeSuspectedData(flavor, contents, (String)obj);
return translateTransferableString(
str,
format);
// Source data is a Reader. Convert to a String and recur. In the
// future, we may want to rewrite this so that we encode on demand.
} else if (flavor.isRepresentationClassReader()) {
! if (!(DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
throw new IOException
("cannot transfer non-text data as Reader");
}
StringBuilder buf = new StringBuilder();
*** 1000,1010 ****
buf.toString(),
format);
// Source data is a CharBuffer. Convert to a String and recur.
} else if (flavor.isRepresentationClassCharBuffer()) {
! if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
throw new IOException
("cannot transfer non-text data as CharBuffer");
}
CharBuffer buffer = (CharBuffer)obj;
--- 783,793 ----
buf.toString(),
format);
// Source data is a CharBuffer. Convert to a String and recur.
} else if (flavor.isRepresentationClassCharBuffer()) {
! if (!(DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
throw new IOException
("cannot transfer non-text data as CharBuffer");
}
CharBuffer buffer = (CharBuffer)obj;
*** 1016,1026 ****
new String(chars),
format);
// Source data is a char array. Convert to a String and recur.
} else if (char[].class.equals(flavor.getRepresentationClass())) {
! if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
throw new IOException
("cannot transfer non-text data as char array");
}
return translateTransferableString(
--- 799,809 ----
new String(chars),
format);
// Source data is a char array. Convert to a String and recur.
} else if (char[].class.equals(flavor.getRepresentationClass())) {
! if (!(DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
throw new IOException
("cannot transfer non-text data as char array");
}
return translateTransferableString(
*** 1034,1045 ****
ByteBuffer buffer = (ByteBuffer)obj;
int size = buffer.remaining();
byte[] bytes = new byte[size];
buffer.get(bytes, 0, size);
! if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
! String sourceEncoding = DataTransferer.getTextCharset(flavor);
return translateTransferableString(
new String(bytes, sourceEncoding),
format);
} else {
return bytes;
--- 817,828 ----
ByteBuffer buffer = (ByteBuffer)obj;
int size = buffer.remaining();
byte[] bytes = new byte[size];
buffer.get(bytes, 0, size);
! if (DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
! String sourceEncoding = DataFlavorUtil.getTextCharset(flavor);
return translateTransferableString(
new String(bytes, sourceEncoding),
format);
} else {
return bytes;
*** 1049,1060 ****
// the array. For text flavors, decode back to a String and recur to
// reencode according to the requested format.
} else if (byte[].class.equals(flavor.getRepresentationClass())) {
byte[] bytes = (byte[])obj;
! if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
! String sourceEncoding = DataTransferer.getTextCharset(flavor);
return translateTransferableString(
new String(bytes, sourceEncoding),
format);
} else {
return bytes;
--- 832,843 ----
// the array. For text flavors, decode back to a String and recur to
// reencode according to the requested format.
} else if (byte[].class.equals(flavor.getRepresentationClass())) {
byte[] bytes = (byte[])obj;
! if (DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
! String sourceEncoding = DataFlavorUtil.getTextCharset(flavor);
return translateTransferableString(
new String(bytes, sourceEncoding),
format);
} else {
return bytes;
*** 1153,1179 ****
bos.write(tmp, 0, aValue);
}
} while (!eof);
}
! 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);
! theByteArray = convertObjectToBytes(mo);
// Source data is Serializable
} else if (flavor.isRepresentationClassSerializable()) {
theByteArray = convertObjectToBytes(obj);
--- 936,959 ----
bos.write(tmp, 0, aValue);
}
} while (!eof);
}
! if (DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
byte[] bytes = bos.toByteArray();
! String sourceEncoding = DataFlavorUtil.getTextCharset(flavor);
return translateTransferableString(
new String(bytes, sourceEncoding),
format);
}
theByteArray = bos.toByteArray();
}
// Source data is an RMI object
} else if (flavor.isRepresentationClassRemote()) {
! theByteArray = convertObjectToBytes(DataFlavorUtil.RMI.newMarshalledObject(obj));
// Source data is Serializable
} else if (flavor.isRepresentationClassSerializable()) {
theByteArray = convertObjectToBytes(obj);
*** 1385,1395 ****
}
// 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)) {
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
--- 1165,1175 ----
}
// Target data is a String. Strip terminating NUL bytes. Decode bytes
// into characters. Search-and-replace EOLN.
} else if (String.class.equals(flavor.getRepresentationClass()) &&
! DataFlavorUtil.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
*** 1399,1422 ****
theObject = translateStream(bais,
flavor, format, localeTransferable);
}
// 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");
}
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 (char[].class.equals(flavor.getRepresentationClass())) {
! if (!(isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
throw new IOException
("cannot transfer non-text data as char array");
}
theObject = translateBytesToString(
--- 1179,1201 ----
theObject = translateStream(bais,
flavor, format, localeTransferable);
}
// Target data is a CharBuffer. Recur to obtain String and wrap.
} else if (flavor.isRepresentationClassCharBuffer()) {
! if (!(DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
! throw new IOException("cannot transfer non-text data as CharBuffer");
}
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 (char[].class.equals(flavor.getRepresentationClass())) {
! if (!(DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format))) {
throw new IOException
("cannot transfer non-text data as char array");
}
theObject = translateBytesToString(
*** 1425,1438 ****
// 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 = translateBytesToString(
bytes, format, localeTransferable).getBytes(
! DataTransferer.getTextCharset(flavor)
);
}
ByteBuffer buffer = ByteBuffer.wrap(bytes);
theObject = constructFlavoredObject(buffer, flavor, ByteBuffer.class);
--- 1204,1217 ----
// 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 (DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
bytes = translateBytesToString(
bytes, format, localeTransferable).getBytes(
! DataFlavorUtil.getTextCharset(flavor)
);
}
ByteBuffer buffer = ByteBuffer.wrap(bytes);
theObject = constructFlavoredObject(buffer, flavor, ByteBuffer.class);
*** 1440,1453 ****
// 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 (byte[].class.equals(flavor.getRepresentationClass())) {
! if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
theObject = translateBytesToString(
bytes, format, localeTransferable
! ).getBytes(DataTransferer.getTextCharset(flavor));
} else {
theObject = bytes;
}
// Target data is an InputStream. For arbitrary flavors, just return
--- 1219,1232 ----
// 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 (byte[].class.equals(flavor.getRepresentationClass())) {
! if (DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
theObject = translateBytesToString(
bytes, format, localeTransferable
! ).getBytes(DataFlavorUtil.getTextCharset(flavor));
} else {
theObject = bytes;
}
// Target data is an InputStream. For arbitrary flavors, just return
*** 1460,1472 ****
theObject = translateStream(bais, flavor, format, localeTransferable);
}
} else if (flavor.isRepresentationClassRemote()) {
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
! ObjectInputStream ois = new ObjectInputStream(bais))
! {
! theObject = RMI.getMarshalledObject(ois.readObject());
} catch (Exception e) {
throw new IOException(e.getMessage());
}
// Target data is Serializable
--- 1239,1251 ----
theObject = translateStream(bais, flavor, format, localeTransferable);
}
} else if (flavor.isRepresentationClassRemote()) {
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
! ObjectInputStream ois = new ObjectInputStream(bais)) {
!
! theObject = DataFlavorUtil.RMI.getMarshalledObject(ois.readObject());
} catch (Exception e) {
throw new IOException(e.getMessage());
}
// Target data is Serializable
*** 1527,1537 ****
theObject = 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 translateBytesToString(inputStreamToByteArray(str),
format, localeTransferable);
// Special hack to maintain backwards-compatibility with the brokenness
--- 1306,1316 ----
theObject = 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()) &&
! DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
return translateBytesToString(inputStreamToByteArray(str),
format, localeTransferable);
// Special hack to maintain backwards-compatibility with the brokenness
*** 1552,1591 ****
// 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 a byte array
} else if (byte[].class.equals(flavor.getRepresentationClass())) {
! if(isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
theObject = translateBytesToString(inputStreamToByteArray(str), format, localeTransferable)
! .getBytes(DataTransferer.getTextCharset(flavor));
} else {
theObject = inputStreamToByteArray(str);
}
// 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()) {
--- 1331,1367 ----
// 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 (!(DataFlavorUtil.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 = DataFlavorUtil.getTextCharset(DataFlavor.plainTextFlavor);
Reader reader = new InputStreamReader(is, unicode);
theObject = constructFlavoredObject(reader, flavor, Reader.class);
// Target data is a byte array
} else if (byte[].class.equals(flavor.getRepresentationClass())) {
! if (DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
theObject = translateBytesToString(inputStreamToByteArray(str), format, localeTransferable)
! .getBytes(DataFlavorUtil.getTextCharset(flavor));
} else {
theObject = inputStreamToByteArray(str);
}
// Target data is an RMI object
} else if (flavor.isRepresentationClassRemote()) {
! try (ObjectInputStream ois = new ObjectInputStream(str)) {
! theObject = DataFlavorUtil.RMI.getMarshalledObject(ois.readObject());
! } catch (Exception e) {
throw new IOException(e.getMessage());
}
// Target data is Serializable
} else if (flavor.isRepresentationClassSerializable()) {
*** 1619,1631 ****
*/
private Object translateStreamToInputStream
(InputStream str, DataFlavor flavor, long format,
Transferable localeTransferable) throws IOException
{
! if (isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
str = new ReencodingInputStream
! (str, format, DataTransferer.getTextCharset(flavor),
localeTransferable);
}
return constructFlavoredObject(str, flavor, InputStream.class);
}
--- 1395,1407 ----
*/
private Object translateStreamToInputStream
(InputStream str, DataFlavor flavor, long format,
Transferable localeTransferable) throws IOException
{
! if (DataFlavorUtil.isFlavorCharsetTextType(flavor) && isTextFormat(format)) {
str = new ReencodingInputStream
! (str, format, DataFlavorUtil.getTextCharset(flavor),
localeTransferable);
}
return constructFlavoredObject(str, flavor, InputStream.class);
}
*** 1863,1874 ****
*/
protected Image standardImageBytesToImage(
byte[] bytes, String mimeType) throws IOException
{
! Iterator<ImageReader> readerIterator =
! ImageIO.getImageReadersByMIMEType(mimeType);
if (!readerIterator.hasNext()) {
throw new IOException("No registered service provider can decode " +
" an image from " + mimeType);
}
--- 1639,1649 ----
*/
protected Image standardImageBytesToImage(
byte[] bytes, String mimeType) throws IOException
{
! Iterator<ImageReader> readerIterator = ImageIO.getImageReadersByMIMEType(mimeType);
if (!readerIterator.hasNext()) {
throw new IOException("No registered service provider can decode " +
" an image from " + mimeType);
}
*** 1917,1928 ****
*/
protected byte[] imageToStandardBytes(Image image, String mimeType)
throws IOException {
IOException originalIOE = null;
! Iterator<ImageWriter> writerIterator =
! ImageIO.getImageWritersByMIMEType(mimeType);
if (!writerIterator.hasNext()) {
throw new IOException("No registered service provider can encode " +
" an image to " + mimeType);
}
--- 1692,1702 ----
*/
protected byte[] imageToStandardBytes(Image image, String mimeType)
throws IOException {
IOException originalIOE = null;
! Iterator<ImageWriter> writerIterator = ImageIO.getImageWritersByMIMEType(mimeType);
if (!writerIterator.hasNext()) {
throw new IOException("No registered service provider can encode " +
" an image to " + mimeType);
}
*** 1977,1988 ****
byte[] imageToStandardBytesImpl(RenderedImage renderedImage,
String mimeType)
throws IOException {
! Iterator<ImageWriter> writerIterator =
! ImageIO.getImageWritersByMIMEType(mimeType);
ImageTypeSpecifier typeSpecifier =
new ImageTypeSpecifier(renderedImage);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
--- 1751,1761 ----
byte[] imageToStandardBytesImpl(RenderedImage renderedImage,
String mimeType)
throws IOException {
! Iterator<ImageWriter> writerIterator = ImageIO.getImageWritersByMIMEType(mimeType);
ImageTypeSpecifier typeSpecifier =
new ImageTypeSpecifier(renderedImage);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
*** 2161,2172 ****
getToolkitThreadBlockedHandler().unlock();
}
}
}
! public abstract ToolkitThreadBlockedHandler
! getToolkitThreadBlockedHandler();
/**
* Helper function to reduce a Map with Long keys to a long array.
* <p>
* The map keys are sorted according to the native formats preference
--- 1934,1944 ----
getToolkitThreadBlockedHandler().unlock();
}
}
}
! public abstract ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler();
/**
* Helper function to reduce a Map with Long keys to a long array.
* <p>
* The map keys are sorted according to the native formats preference
*** 2187,2198 ****
* The array will be sorted according to <code>DataFlavorComparator</code>.
*/
public static DataFlavor[] setToSortedDataFlavorArray(Set<DataFlavor> flavorsSet) {
DataFlavor[] flavors = new DataFlavor[flavorsSet.size()];
flavorsSet.toArray(flavors);
! final Comparator<DataFlavor> comparator =
! new DataFlavorComparator(IndexedComparator.SELECT_WORST);
Arrays.sort(flavors, comparator);
return flavors;
}
/**
--- 1959,1969 ----
* The array will be sorted according to <code>DataFlavorComparator</code>.
*/
public static DataFlavor[] setToSortedDataFlavorArray(Set<DataFlavor> flavorsSet) {
DataFlavor[] flavors = new DataFlavor[flavorsSet.size()];
flavorsSet.toArray(flavors);
! final Comparator<DataFlavor> comparator = DataFlavorUtil.getDataFlavorComparator().reversed();
Arrays.sort(flavors, comparator);
return flavors;
}
/**
*** 2228,2748 ****
* returns an empty <code>List</code>.
*/
public LinkedHashSet<String> getPlatformMappingsForFlavor(DataFlavor df) {
return new LinkedHashSet<>();
}
-
- /**
- * A Comparator which includes a helper function for comparing two Objects
- * which are likely to be keys in the specified Map.
- */
- public abstract static class IndexedComparator<T> implements Comparator<T> {
-
- /**
- * The best Object (e.g., DataFlavor) will be the last in sequence.
- */
- public static final boolean SELECT_BEST = true;
-
- /**
- * The best Object (e.g., DataFlavor) will be the first in sequence.
- */
- public static final boolean SELECT_WORST = false;
-
- final boolean order;
-
- public IndexedComparator(boolean order) {
- this.order = order;
- }
-
- /**
- * Helper method to compare two objects by their Integer indices in the
- * given map. If the map doesn't contain an entry for either of the
- * objects, the fallback index will be used for the object instead.
- *
- * @param indexMap the map which maps objects into Integer indexes.
- * @param obj1 the first object to be compared.
- * @param obj2 the second object to be compared.
- * @param fallbackIndex the Integer to be used as a fallback index.
- * @return a negative integer, zero, or a positive integer as the
- * first object is mapped to a less, equal to, or greater
- * index than the second.
- */
- static <T> int compareIndices(Map<T, Integer> indexMap,
- T obj1, T obj2,
- Integer fallbackIndex) {
- Integer index1 = indexMap.getOrDefault(obj1, fallbackIndex);
- Integer index2 = indexMap.getOrDefault(obj2, fallbackIndex);
- return index1.compareTo(index2);
- }
- }
-
- /**
- * An IndexedComparator which compares two String charsets. The comparison
- * follows the rules outlined in DataFlavor.selectBestTextFlavor. In order
- * to ensure that non-Unicode, non-ASCII, non-default charsets are sorted
- * in alphabetical order, charsets are not automatically converted to their
- * canonical forms.
- */
- public static class CharsetComparator extends IndexedComparator<String> {
- private static final Map<String, Integer> charsets;
-
- private static final Integer DEFAULT_CHARSET_INDEX = 2;
- private static final Integer OTHER_CHARSET_INDEX = 1;
- private static final Integer WORST_CHARSET_INDEX = 0;
- private static final Integer UNSUPPORTED_CHARSET_INDEX = Integer.MIN_VALUE;
-
- private static final String UNSUPPORTED_CHARSET = "UNSUPPORTED";
-
- static {
- Map<String, Integer> charsetsMap = new HashMap<>(8, 1.0f);
-
- // we prefer Unicode charsets
- charsetsMap.put(canonicalName("UTF-16LE"), 4);
- charsetsMap.put(canonicalName("UTF-16BE"), 5);
- charsetsMap.put(canonicalName("UTF-8"), 6);
- charsetsMap.put(canonicalName("UTF-16"), 7);
-
- // US-ASCII is the worst charset supported
- charsetsMap.put(canonicalName("US-ASCII"), WORST_CHARSET_INDEX);
-
- charsetsMap.putIfAbsent(Charset.defaultCharset().name(), DEFAULT_CHARSET_INDEX);
-
- charsetsMap.put(UNSUPPORTED_CHARSET, UNSUPPORTED_CHARSET_INDEX);
-
- charsets = Collections.unmodifiableMap(charsetsMap);
- }
-
- public CharsetComparator(boolean order) {
- super(order);
- }
-
- /**
- * Compares two String objects. Returns a negative integer, zero,
- * or a positive integer as the first charset is worse than, equal to,
- * or better than the second.
- *
- * @param obj1 the first charset to be compared
- * @param obj2 the second charset to be compared
- * @return a negative integer, zero, or a positive integer as the
- * first argument is worse, equal to, or better than the
- * second.
- * @throws ClassCastException if either of the arguments is not
- * instance of String
- * @throws NullPointerException if either of the arguments is
- * <code>null</code>.
- */
- public int compare(String obj1, String obj2) {
- if (order == SELECT_BEST) {
- return compareCharsets(obj1, obj2);
- } else {
- return compareCharsets(obj2, obj1);
- }
- }
-
- /**
- * Compares charsets. Returns a negative integer, zero, or a positive
- * integer as the first charset is worse than, equal to, or better than
- * the second.
- * <p>
- * Charsets are ordered according to the following rules:
- * <ul>
- * <li>All unsupported charsets are equal.
- * <li>Any unsupported charset is worse than any supported charset.
- * <li>Unicode charsets, such as "UTF-16", "UTF-8", "UTF-16BE" and
- * "UTF-16LE", are considered best.
- * <li>After them, platform default charset is selected.
- * <li>"US-ASCII" is the worst of supported charsets.
- * <li>For all other supported charsets, the lexicographically less
- * one is considered the better.
- * </ul>
- *
- * @param charset1 the first charset to be compared
- * @param charset2 the second charset to be compared.
- * @return a negative integer, zero, or a positive integer as the
- * first argument is worse, equal to, or better than the
- * second.
- */
- int compareCharsets(String charset1, String charset2) {
- charset1 = getEncoding(charset1);
- charset2 = getEncoding(charset2);
-
- int comp = compareIndices(charsets, charset1, charset2,
- OTHER_CHARSET_INDEX);
-
- if (comp == 0) {
- return charset2.compareTo(charset1);
- }
-
- return comp;
- }
-
- /**
- * Returns encoding for the specified charset according to the
- * following rules:
- * <ul>
- * <li>If the charset is <code>null</code>, then <code>null</code> will
- * be returned.
- * <li>Iff the charset specifies an encoding unsupported by this JRE,
- * <code>UNSUPPORTED_CHARSET</code> will be returned.
- * <li>If the charset specifies an alias name, the corresponding
- * canonical name will be returned iff the charset is a known
- * Unicode, ASCII, or default charset.
- * </ul>
- *
- * @param charset the charset.
- * @return an encoding for this charset.
- */
- static String getEncoding(String charset) {
- if (charset == null) {
- return null;
- } else if (!DataTransferer.isEncodingSupported(charset)) {
- return UNSUPPORTED_CHARSET;
- } else {
- // Only convert to canonical form if the charset is one
- // of the charsets explicitly listed in the known charsets
- // map. This will happen only for Unicode, ASCII, or default
- // charsets.
- String canonicalName = DataTransferer.canonicalName(charset);
- return (charsets.containsKey(canonicalName))
- ? canonicalName
- : charset;
- }
- }
- }
-
- /**
- * An IndexedComparator which compares two DataFlavors. For text flavors,
- * the comparison follows the rules outlined in
- * DataFlavor.selectBestTextFlavor. For non-text flavors, unknown
- * application MIME types are preferred, followed by known
- * application/x-java-* MIME types. Unknown application types are preferred
- * because if the user provides his own data flavor, it will likely be the
- * most descriptive one. For flavors which are otherwise equal, the
- * flavors' string representation are compared in the alphabetical order.
- */
- public static class DataFlavorComparator extends IndexedComparator<DataFlavor> {
-
- private final CharsetComparator charsetComparator;
-
- private static final Map<String, Integer> exactTypes;
- private static final Map<String, Integer> primaryTypes;
- private static final Map<Class<?>, Integer> nonTextRepresentations;
- private static final Map<String, Integer> textTypes;
- private static final Map<Class<?>, Integer> decodedTextRepresentations;
- private static final Map<Class<?>, Integer> encodedTextRepresentations;
-
- private static final Integer UNKNOWN_OBJECT_LOSES = Integer.MIN_VALUE;
- private static final Integer UNKNOWN_OBJECT_WINS = Integer.MAX_VALUE;
-
- static {
- {
- Map<String, Integer> exactTypesMap = new HashMap<>(4, 1.0f);
-
- // application/x-java-* MIME types
- exactTypesMap.put("application/x-java-file-list", 0);
- exactTypesMap.put("application/x-java-serialized-object", 1);
- exactTypesMap.put("application/x-java-jvm-local-objectref", 2);
- exactTypesMap.put("application/x-java-remote-object", 3);
-
- exactTypes = Collections.unmodifiableMap(exactTypesMap);
- }
-
- {
- Map<String, Integer> primaryTypesMap = new HashMap<>(1, 1.0f);
-
- primaryTypesMap.put("application", 0);
-
- primaryTypes = Collections.unmodifiableMap(primaryTypesMap);
- }
-
- {
- Map<Class<?>, Integer> nonTextRepresentationsMap = new HashMap<>(3, 1.0f);
-
- nonTextRepresentationsMap.put(java.io.InputStream.class, 0);
- nonTextRepresentationsMap.put(java.io.Serializable.class, 1);
-
- Class<?> remoteClass = RMI.remoteClass();
- if (remoteClass != null) {
- nonTextRepresentationsMap.put(remoteClass, 2);
- }
-
- nonTextRepresentations = Collections.unmodifiableMap(nonTextRepresentationsMap);
- }
-
- {
- Map<String, Integer> textTypesMap = new HashMap<>(16, 1.0f);
-
- // plain text
- textTypesMap.put("text/plain", 0);
-
- // stringFlavor
- textTypesMap.put("application/x-java-serialized-object", 1);
-
- // misc
- textTypesMap.put("text/calendar", 2);
- textTypesMap.put("text/css", 3);
- textTypesMap.put("text/directory", 4);
- textTypesMap.put("text/parityfec", 5);
- textTypesMap.put("text/rfc822-headers", 6);
- textTypesMap.put("text/t140", 7);
- textTypesMap.put("text/tab-separated-values", 8);
- textTypesMap.put("text/uri-list", 9);
-
- // enriched
- textTypesMap.put("text/richtext", 10);
- textTypesMap.put("text/enriched", 11);
- textTypesMap.put("text/rtf", 12);
-
- // markup
- textTypesMap.put("text/html", 13);
- textTypesMap.put("text/xml", 14);
- textTypesMap.put("text/sgml", 15);
-
- textTypes = Collections.unmodifiableMap(textTypesMap);
- }
-
- {
- Map<Class<?>, Integer> decodedTextRepresentationsMap = new HashMap<>(4, 1.0f);
-
- decodedTextRepresentationsMap.put(char[].class, 0);
- decodedTextRepresentationsMap.put(CharBuffer.class, 1);
- decodedTextRepresentationsMap.put(String.class, 2);
- decodedTextRepresentationsMap.put(Reader.class, 3);
-
- decodedTextRepresentations =
- Collections.unmodifiableMap(decodedTextRepresentationsMap);
- }
-
- {
- Map<Class<?>, Integer> encodedTextRepresentationsMap = new HashMap<>(3, 1.0f);
-
- encodedTextRepresentationsMap.put(byte[].class, 0);
- encodedTextRepresentationsMap.put(ByteBuffer.class, 1);
- encodedTextRepresentationsMap.put(InputStream.class, 2);
-
- encodedTextRepresentations =
- Collections.unmodifiableMap(encodedTextRepresentationsMap);
- }
- }
-
- public DataFlavorComparator() {
- this(SELECT_BEST);
- }
-
- public DataFlavorComparator(boolean order) {
- super(order);
-
- charsetComparator = new CharsetComparator(order);
- }
-
- public int compare(DataFlavor obj1, DataFlavor obj2) {
- DataFlavor flavor1 = order == SELECT_BEST ? obj1 : obj2;
- DataFlavor flavor2 = order == SELECT_BEST ? obj2 : obj1;
-
- if (flavor1.equals(flavor2)) {
- return 0;
- }
-
- int comp = 0;
-
- String primaryType1 = flavor1.getPrimaryType();
- String subType1 = flavor1.getSubType();
- String mimeType1 = primaryType1 + "/" + subType1;
- Class<?> class1 = flavor1.getRepresentationClass();
-
- String primaryType2 = flavor2.getPrimaryType();
- String subType2 = flavor2.getSubType();
- String mimeType2 = primaryType2 + "/" + subType2;
- Class<?> class2 = flavor2.getRepresentationClass();
-
- if (flavor1.isFlavorTextType() && flavor2.isFlavorTextType()) {
- // First, compare MIME types
- comp = compareIndices(textTypes, mimeType1, mimeType2,
- UNKNOWN_OBJECT_LOSES);
- if (comp != 0) {
- return comp;
- }
-
- // Only need to test one flavor because they both have the
- // same MIME type. Also don't need to worry about accidentally
- // passing stringFlavor because either
- // 1. Both flavors are stringFlavor, in which case the
- // equality test at the top of the function succeeded.
- // 2. Only one flavor is stringFlavor, in which case the MIME
- // type comparison returned a non-zero value.
- if (doesSubtypeSupportCharset(flavor1)) {
- // Next, prefer the decoded text representations of Reader,
- // String, CharBuffer, and [C, in that order.
- comp = compareIndices(decodedTextRepresentations, class1,
- class2, UNKNOWN_OBJECT_LOSES);
- if (comp != 0) {
- return comp;
- }
-
- // Next, compare charsets
- comp = charsetComparator.compareCharsets
- (DataTransferer.getTextCharset(flavor1),
- DataTransferer.getTextCharset(flavor2));
- if (comp != 0) {
- return comp;
- }
- }
-
- // Finally, prefer the encoded text representations of
- // InputStream, ByteBuffer, and [B, in that order.
- comp = compareIndices(encodedTextRepresentations, class1,
- class2, UNKNOWN_OBJECT_LOSES);
- if (comp != 0) {
- return comp;
- }
- } else {
- // First, prefer application types.
- comp = compareIndices(primaryTypes, primaryType1, primaryType2,
- UNKNOWN_OBJECT_LOSES);
- if (comp != 0) {
- return comp;
- }
-
- // Next, look for application/x-java-* types. Prefer unknown
- // MIME types because if the user provides his own data flavor,
- // it will likely be the most descriptive one.
- comp = compareIndices(exactTypes, mimeType1, mimeType2,
- UNKNOWN_OBJECT_WINS);
- if (comp != 0) {
- return comp;
- }
-
- // Finally, prefer the representation classes of Remote,
- // Serializable, and InputStream, in that order.
- comp = compareIndices(nonTextRepresentations, class1, class2,
- UNKNOWN_OBJECT_LOSES);
- if (comp != 0) {
- return comp;
- }
- }
-
- // The flavours are not equal but still not distinguishable.
- // Compare String representations in alphabetical order
- return flavor1.getMimeType().compareTo(flavor2.getMimeType());
- }
- }
-
- /*
- * Given the Map that maps objects to Integer indices and a boolean value,
- * this Comparator imposes a direct or reverse order on set of objects.
- * <p>
- * If the specified boolean value is SELECT_BEST, the Comparator imposes the
- * direct index-based order: an object A is greater than an object B if and
- * only if the index of A is greater than the index of B. An object that
- * doesn't have an associated index is less or equal than any other object.
- * <p>
- * If the specified boolean value is SELECT_WORST, the Comparator imposes the
- * reverse index-based order: an object A is greater than an object B if and
- * only if A is less than B with the direct index-based order.
- */
- public static class IndexOrderComparator extends IndexedComparator<Long> {
- private final Map<Long, Integer> indexMap;
- private static final Integer FALLBACK_INDEX = Integer.MIN_VALUE;
-
- public IndexOrderComparator(Map<Long, Integer> indexMap, boolean order) {
- super(order);
- this.indexMap = indexMap;
- }
-
- public int compare(Long obj1, Long obj2) {
- if (order == SELECT_WORST) {
- return -compareIndices(indexMap, obj1, obj2, FALLBACK_INDEX);
- } else {
- return compareIndices(indexMap, obj1, obj2, FALLBACK_INDEX);
- }
- }
- }
-
- /**
- * A class that provides access to java.rmi.Remote and java.rmi.MarshalledObject
- * without creating a static dependency.
- */
- private static class RMI {
- private static final Class<?> remoteClass = getClass("java.rmi.Remote");
- private static final Class<?> marshallObjectClass =
- getClass("java.rmi.MarshalledObject");
- private static final Constructor<?> marshallCtor =
- getConstructor(marshallObjectClass, Object.class);
- private static final Method marshallGet =
- getMethod(marshallObjectClass, "get");
-
- private static Class<?> getClass(String name) {
- try {
- return Class.forName(name, true, null);
- } catch (ClassNotFoundException e) {
- return null;
- }
- }
-
- private static Constructor<?> getConstructor(Class<?> c, Class<?>... types) {
- try {
- return (c == null) ? null : c.getDeclaredConstructor(types);
- } catch (NoSuchMethodException x) {
- throw new AssertionError(x);
- }
- }
-
- private static Method getMethod(Class<?> c, String name, Class<?>... types) {
- try {
- return (c == null) ? null : c.getMethod(name, types);
- } catch (NoSuchMethodException e) {
- throw new AssertionError(e);
- }
- }
-
- /**
- * Returns {@code true} if the given class is java.rmi.Remote.
- */
- static boolean isRemote(Class<?> c) {
- return (remoteClass == null) ? false : remoteClass.isAssignableFrom(c);
- }
-
- /**
- * Returns java.rmi.Remote.class if RMI is present; otherwise {@code null}.
- */
- static Class<?> remoteClass() {
- return remoteClass;
- }
-
- /**
- * Returns a new MarshalledObject containing the serialized representation
- * of the given object.
- */
- static Object newMarshalledObject(Object obj) throws IOException {
- try {
- return marshallCtor.newInstance(obj);
- } catch (InstantiationException | IllegalAccessException x) {
- throw new AssertionError(x);
- } catch (InvocationTargetException x) {
- Throwable cause = x.getCause();
- if (cause instanceof IOException)
- throw (IOException)cause;
- throw new AssertionError(x);
- }
- }
-
- /**
- * Returns a new copy of the contained marshalled object.
- */
- static Object getMarshalledObject(Object obj)
- throws IOException, ClassNotFoundException
- {
- try {
- return marshallGet.invoke(obj);
- } catch (IllegalAccessException x) {
- throw new AssertionError(x);
- } catch (InvocationTargetException x) {
- Throwable cause = x.getCause();
- if (cause instanceof IOException)
- throw (IOException)cause;
- if (cause instanceof ClassNotFoundException)
- throw (ClassNotFoundException)cause;
- throw new AssertionError(x);
- }
- }
- }
}
--- 1999,2004 ----