3090 lines · 116.7 KB · Java
RawDownload
/* * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.awt.datatransfer; import java.awt.AWTError;import java.awt.EventQueue;import java.awt.Image;import java.awt.Graphics; import java.awt.datatransfer.DataFlavor;import java.awt.datatransfer.FlavorMap;import java.awt.datatransfer.FlavorTable;import java.awt.datatransfer.Transferable;import java.awt.datatransfer.UnsupportedFlavorException; import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.InputStream;import java.io.InputStreamReader;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Reader;import java.io.SequenceInputStream;import java.io.StringReader; import java.net.URI;import java.net.URISyntaxException; import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.nio.charset.Charset;import java.nio.charset.CharsetEncoder;import java.nio.charset.IllegalCharsetNameException;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.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.SortedMap;import java.util.SortedSet;import java.util.Set;import java.util.Stack;import java.util.TreeMap;import java.util.TreeSet; import sun.util.logging.PlatformLogger; import sun.awt.AppContext;import sun.awt.SunToolkit; import java.awt.image.BufferedImage;import java.awt.image.ImageObserver;import java.awt.image.RenderedImage;import java.awt.image.WritableRaster;import java.awt.image.ColorModel; import javax.imageio.ImageIO;import javax.imageio.ImageReader;import javax.imageio.ImageReadParam;import javax.imageio.ImageWriter;import javax.imageio.ImageTypeSpecifier; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageInputStream;import javax.imageio.stream.ImageOutputStream; import sun.awt.image.ImageRepresentation;import sun.awt.image.ToolkitImage; import java.io.FilePermission;  /** * Provides a set of functions to be shared among the DataFlavor class and * platform-specific data transfer implementations. * * The concept of "flavors" and "natives" is extended to include "formats", * which are the numeric values Win32 and X11 use to express particular data * types. Like FlavorMap, which provides getNativesForFlavors(DataFlavor[]) and * getFlavorsForNatives(String[]) functions, DataTransferer provides a set * of getFormatsFor(Transferable|Flavor|Flavors) and * getFlavorsFor(Format|Formats) functions. * * Also provided are functions for translating a Transferable into a byte * array, given a source DataFlavor and a target format, and for translating * a byte array or InputStream into an Object, given a source format and * a target DataFlavor. * * @author David Mendenhall * @author Danila Sinopalnikov * * @since 1.3.1 */public abstract class DataTransferer {     /**     * Cached value of Class.forName("[C");     */    public static final Class charArrayClass;     /**     * Cached value of Class.forName("[B");     */    public static final Class byteArrayClass;     /**     * The <code>DataFlavor</code> representing plain text with Unicode     * encoding, where:     * <pre>     *     representationClass = java.lang.String     *     mimeType            = "text/plain; charset=Unicode"     * </pre>     */    public static final DataFlavor plainTextStringFlavor;     /**     * The <code>DataFlavor</code> representing a Java text encoding String     * encoded in UTF-8, where     * <pre>     *     representationClass = [B     *     mimeType            = "application/x-java-text-encoding"     * </pre>     */    public static final DataFlavor javaTextEncodingFlavor;     /**     * Lazy initialization of Standard Encodings.     */    private static class StandardEncodingsHolder {        private static final SortedSet standardEncodings = load();         private static SortedSet load() {            final Comparator comparator =                    new CharsetComparator(IndexedComparator.SELECT_WORST);            final SortedSet 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(getDefaultTextCharset());            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 textMIMESubtypeCharsetSupport;     /**     * Cache of the platform default encoding as specified in the     * "file.encoding" system property.     */    private static String defaultEncoding;     /**     * A collection of all natives listed in flavormap.properties with     * a primary MIME type of "text".     */    private static final Set textNatives =        Collections.synchronizedSet(new HashSet());     /**     * The native encodings/charsets for the Set of textNatives.     */    private static final Map nativeCharsets =        Collections.synchronizedMap(new HashMap());     /**     * The end-of-line markers for the Set of textNatives.     */    private static final Map nativeEOLNs =        Collections.synchronizedMap(new HashMap());     /**     * The number of terminating NUL bytes for the Set of textNatives.     */    private static final Map nativeTerminators =        Collections.synchronizedMap(new HashMap());     /**     * The key used to store pending data conversion requests for an AppContext.     */    private static final String DATA_CONVERTER_KEY = "DATA_CONVERTER_KEY";     /**     * The singleton DataTransferer instance. It is created during MToolkit     * or WToolkit initialization.     */    private static DataTransferer transferer;     private static final PlatformLogger dtLog = PlatformLogger.getLogger("sun.awt.datatransfer.DataTransfer");     static {        Class tCharArrayClass = null, tByteArrayClass = null;        try {            tCharArrayClass = Class.forName("[C");            tByteArrayClass = Class.forName("[B");        } catch (ClassNotFoundException cannotHappen) {        }        charArrayClass = tCharArrayClass;        byteArrayClass = tByteArrayClass;         DataFlavor tPlainTextStringFlavor = null;        try {            tPlainTextStringFlavor = new DataFlavor                ("text/plain;charset=Unicode;class=java.lang.String");        } catch (ClassNotFoundException cannotHappen) {        }        plainTextStringFlavor = tPlainTextStringFlavor;         DataFlavor tJavaTextEncodingFlavor = null;        try {            tJavaTextEncodingFlavor = new DataFlavor                ("application/x-java-text-encoding;class=\"[B\"");        } catch (ClassNotFoundException cannotHappen) {        }        javaTextEncodingFlavor = tJavaTextEncodingFlavor;         Map 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;     * instead, null will be returned.     */    public static DataTransferer getInstance() {        synchronized (DataTransferer.class) {            if (transferer == null) {                final String name = SunToolkit.getDataTransfererClassName();                if (name != null) {                    PrivilegedAction<DataTransferer> action = new PrivilegedAction<DataTransferer>()                    {                      public DataTransferer run() {                          Class cls = null;                          Method method = null;                          DataTransferer ret = null;                           try {                              cls = Class.forName(name);                          } catch (ClassNotFoundException e) {                              ClassLoader cl = ClassLoader.                                  getSystemClassLoader();                              if (cl != null) {                                  try {                                      cls = cl.loadClass(name);                                  } catch (ClassNotFoundException ee) {                                      ee.printStackTrace();                                      throw new AWTError("DataTransferer not found: " + name);                                  }                              }                          }                          if (cls != null) {                              try {                                  method = cls.getDeclaredMethod("getInstanceImpl");                                  method.setAccessible(true);                              } catch (NoSuchMethodException e) {                                  e.printStackTrace();                                  throw new AWTError("Cannot instantiate DataTransferer: " + name);                              } catch (SecurityException e) {                                  e.printStackTrace();                                  throw new AWTError("Access is denied for DataTransferer: " + name);                              }                          }                          if (method != null) {                              try {                                  ret = (DataTransferer) method.invoke(null);                              } catch (InvocationTargetException e) {                                  e.printStackTrace();                                  throw new AWTError("Cannot instantiate DataTransferer: " + name);                              } catch (IllegalAccessException e) {                                  e.printStackTrace();                                  throw new AWTError("Cannot access DataTransferer: " + name);                              }                          }                          return ret;                      }                    };                    transferer = AccessController.doPrivileged(action);                }            }        }        return transferer;    }     /**     * 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 : getDefaultTextCharset();    }     /**     * Returns the platform's default character encoding.     */    public static String getDefaultTextCharset() {        if (defaultEncoding != null) {            return defaultEncoding;        }        return defaultEncoding = 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.FINE)) {            if (!"text".equals(flavor.getPrimaryType())) {                dtLog.fine("Assertion (\"text\".equals(flavor.getPrimaryType())) failed");            }        }         String subType = flavor.getSubType();        if (subType == null) {            return false;        }         Object support = textMIMESubtypeCharsetSupport.get(subType);         if (support != null) {            return (support == Boolean.TRUE);        }         boolean ret_val = (flavor.getParameter("charset") != null);        textMIMESubtypeCharsetSupport.put            (subType, (ret_val) ? Boolean.TRUE : Boolean.FALSE);        return ret_val;    }    public static boolean doesSubtypeSupportCharset(String subType,                                                    String charset)    {        Object support = textMIMESubtypeCharsetSupport.get(subType);         if (support != null) {            return (support == Boolean.TRUE);        }         boolean ret_val = (charset != null);        textMIMESubtypeCharsetSupport.put            (subType, (ret_val) ? Boolean.TRUE : Boolean.FALSE);        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() ||            DataTransferer.charArrayClass.equals(rep_class))        {            return true;        }         if (!(flavor.isRepresentationClassInputStream() ||              flavor.isRepresentationClassByteBuffer() ||              DataTransferer.byteArrayClass.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() ||                DataTransferer.byteArrayClass.                    equals(flavor.getRepresentationClass()));    }     /**     * Determines whether this JRE can both encode and decode text in the     * specified encoding.     */

Lines 1–500 of 3090.