jdk/src/solaris/classes/sun/awt/motif/MDataTransferer.java
changeset 1192 715cf9378c53
parent 1051 90cf935adb35
parent 1191 f142c1da78c2
child 1193 41afb8ee8f45
equal deleted inserted replaced
1051:90cf935adb35 1192:715cf9378c53
     1 /*
       
     2  * Copyright 2000-2004 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.awt.motif;
       
    27 
       
    28 import java.awt.Image;
       
    29 
       
    30 import java.awt.datatransfer.DataFlavor;
       
    31 
       
    32 import java.awt.image.BufferedImage;
       
    33 import java.awt.image.ColorModel;
       
    34 import java.awt.image.WritableRaster;
       
    35 
       
    36 import java.io.InputStream;
       
    37 import java.io.IOException;
       
    38 
       
    39 import java.util.ArrayList;
       
    40 import java.util.Iterator;
       
    41 import java.util.List;
       
    42 
       
    43 import javax.imageio.ImageIO;
       
    44 import javax.imageio.ImageTypeSpecifier;
       
    45 import javax.imageio.ImageWriter;
       
    46 import javax.imageio.spi.ImageWriterSpi;
       
    47 
       
    48 import sun.awt.datatransfer.DataTransferer;
       
    49 import sun.awt.datatransfer.ToolkitThreadBlockedHandler;
       
    50 
       
    51 /**
       
    52  * Platform-specific support for the data transfer subsystem.
       
    53  *
       
    54  * @author Roger Brinkley
       
    55  * @author Danila Sinopalnikov
       
    56  *
       
    57  * @since 1.3.1
       
    58  */
       
    59 public class MDataTransferer extends DataTransferer {
       
    60     private static final long FILE_NAME_ATOM;
       
    61     private static final long DT_NET_FILE_ATOM;
       
    62     private static final long PNG_ATOM;
       
    63     private static final long JFIF_ATOM;
       
    64 
       
    65     static {
       
    66         FILE_NAME_ATOM = getAtomForTarget("FILE_NAME");
       
    67         DT_NET_FILE_ATOM = getAtomForTarget("_DT_NETFILE");
       
    68         PNG_ATOM = getAtomForTarget("PNG");
       
    69         JFIF_ATOM = getAtomForTarget("JFIF");
       
    70     }
       
    71 
       
    72     /**
       
    73      * Singleton constructor
       
    74      */
       
    75     private MDataTransferer() {
       
    76     }
       
    77 
       
    78     private static MDataTransferer transferer;
       
    79 
       
    80     static MDataTransferer getInstanceImpl() {
       
    81         if (transferer == null) {
       
    82             synchronized (MDataTransferer.class) {
       
    83                 if (transferer == null) {
       
    84                     transferer = new MDataTransferer();
       
    85                 }
       
    86             }
       
    87         }
       
    88         return transferer;
       
    89     }
       
    90 
       
    91     public String getDefaultUnicodeEncoding() {
       
    92         return "iso-10646-ucs-2";
       
    93     }
       
    94 
       
    95     public boolean isLocaleDependentTextFormat(long format) {
       
    96         return false;
       
    97     }
       
    98 
       
    99     public boolean isTextFormat(long format) {
       
   100         return super.isTextFormat(format)
       
   101             || isMimeFormat(format, "text");
       
   102     }
       
   103 
       
   104     protected String getCharsetForTextFormat(Long lFormat) {
       
   105         long format = lFormat.longValue();
       
   106         if (isMimeFormat(format, "text")) {
       
   107             String nat = getNativeForFormat(format);
       
   108             DataFlavor df = new DataFlavor(nat, null);
       
   109             // Ignore the charset parameter of the MIME type if the subtype
       
   110             // doesn't support charset.
       
   111             if (!DataTransferer.doesSubtypeSupportCharset(df)) {
       
   112                 return null;
       
   113             }
       
   114             String charset = df.getParameter("charset");
       
   115             if (charset != null) {
       
   116                 return charset;
       
   117             }
       
   118         }
       
   119         return super.getCharsetForTextFormat(lFormat);
       
   120     }
       
   121 
       
   122     public boolean isFileFormat(long format) {
       
   123         return format == FILE_NAME_ATOM || format == DT_NET_FILE_ATOM;
       
   124     }
       
   125 
       
   126     public boolean isImageFormat(long format) {
       
   127         return format == PNG_ATOM || format == JFIF_ATOM
       
   128             || isMimeFormat(format, "image");
       
   129     }
       
   130 
       
   131     protected Long getFormatForNativeAsLong(String str) {
       
   132         // Just get the atom. If it has already been retrived
       
   133         // once, we'll get a copy so this should be very fast.
       
   134         long atom = getAtomForTarget(str);
       
   135         if (atom <= 0) {
       
   136             throw new InternalError("Cannot register a target");
       
   137         }
       
   138         return Long.valueOf(atom);
       
   139     }
       
   140 
       
   141     protected String getNativeForFormat(long format) {
       
   142         return getTargetNameForAtom(format);
       
   143     }
       
   144 
       
   145     public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() {
       
   146         return MToolkitThreadBlockedHandler.getToolkitThreadBlockedHandler();
       
   147     }
       
   148 
       
   149     /**
       
   150      * Gets an atom for a format name.
       
   151      */
       
   152     static native long getAtomForTarget(String name);
       
   153 
       
   154     /**
       
   155      * Gets an format name for a given format (atom)
       
   156      */
       
   157     private static native String getTargetNameForAtom(long atom);
       
   158 
       
   159     protected byte[] imageToPlatformBytes(Image image, long format)
       
   160       throws IOException {
       
   161         String mimeType = null;
       
   162         if (format == PNG_ATOM) {
       
   163             mimeType = "image/png";
       
   164         } else if (format == JFIF_ATOM) {
       
   165             mimeType = "image/jpeg";
       
   166         } else {
       
   167             // Check if an image MIME format.
       
   168             try {
       
   169                 String nat = getNativeForFormat(format);
       
   170                 DataFlavor df = new DataFlavor(nat);
       
   171                 String primaryType = df.getPrimaryType();
       
   172                 if ("image".equals(primaryType)) {
       
   173                     mimeType = df.getPrimaryType() + "/" + df.getSubType();
       
   174                 }
       
   175             } catch (Exception e) {
       
   176                 // Not an image MIME format.
       
   177             }
       
   178         }
       
   179         if (mimeType != null) {
       
   180             return imageToStandardBytes(image, mimeType);
       
   181         } else {
       
   182             String nativeFormat = getNativeForFormat(format);
       
   183             throw new IOException("Translation to " + nativeFormat +
       
   184                                   " is not supported.");
       
   185         }
       
   186     }
       
   187 
       
   188     /**
       
   189      * Translates either a byte array or an input stream which contain
       
   190      * platform-specific image data in the given format into an Image.
       
   191      */
       
   192     protected Image platformImageBytesOrStreamToImage(InputStream inputStream,
       
   193                                                       byte[] bytes,
       
   194                                                       long format)
       
   195       throws IOException {
       
   196         String mimeType = null;
       
   197         if (format == PNG_ATOM) {
       
   198             mimeType = "image/png";
       
   199         } else if (format == JFIF_ATOM) {
       
   200             mimeType = "image/jpeg";
       
   201         } else {
       
   202             // Check if an image MIME format.
       
   203             try {
       
   204                 String nat = getNativeForFormat(format);
       
   205                 DataFlavor df = new DataFlavor(nat);
       
   206                 String primaryType = df.getPrimaryType();
       
   207                 if ("image".equals(primaryType)) {
       
   208                     mimeType = df.getPrimaryType() + "/" + df.getSubType();
       
   209                 }
       
   210             } catch (Exception e) {
       
   211                 // Not an image MIME format.
       
   212             }
       
   213         }
       
   214         if (mimeType != null) {
       
   215             return standardImageBytesOrStreamToImage(inputStream, bytes, mimeType);
       
   216         } else {
       
   217             String nativeFormat = getNativeForFormat(format);
       
   218             throw new IOException("Translation from " + nativeFormat +
       
   219                                   " is not supported.");
       
   220         }
       
   221     }
       
   222 
       
   223     /**
       
   224      * Returns true if and only if the name of the specified format Atom
       
   225      * constitutes a valid MIME type with the specified primary type.
       
   226      */
       
   227     private boolean isMimeFormat(long format, String primaryType) {
       
   228         String nat = getNativeForFormat(format);
       
   229 
       
   230         if (nat == null) {
       
   231             return false;
       
   232         }
       
   233 
       
   234         try {
       
   235             DataFlavor df = new DataFlavor(nat);
       
   236             if (primaryType.equals(df.getPrimaryType())) {
       
   237                 return true;
       
   238             }
       
   239         } catch (Exception e) {
       
   240             // Not a MIME format.
       
   241         }
       
   242 
       
   243         return false;
       
   244     }
       
   245 
       
   246     /*
       
   247      * The XDnD protocol prescribes that the Atoms used as targets for data
       
   248      * transfer should have string names that represent the corresponding MIME
       
   249      * types.
       
   250      * To meet this requirement we check if the passed native format constitutes
       
   251      * a valid MIME and return a list of flavors to which the data in this MIME
       
   252      * type can be translated by the Data Transfer subsystem.
       
   253      */
       
   254     public List getPlatformMappingsForNative(String nat) {
       
   255         List flavors = new ArrayList();
       
   256 
       
   257         if (nat == null) {
       
   258             return flavors;
       
   259         }
       
   260 
       
   261         DataFlavor df = null;
       
   262 
       
   263         try {
       
   264             df = new DataFlavor(nat);
       
   265         } catch (Exception e) {
       
   266             // The string doesn't constitute a valid MIME type.
       
   267             return flavors;
       
   268         }
       
   269 
       
   270         Object value = df;
       
   271         final String primaryType = df.getPrimaryType();
       
   272         final String baseType = primaryType + "/" + df.getSubType();
       
   273 
       
   274         // For text formats we map natives to MIME strings instead of data
       
   275         // flavors to enable dynamic text native-to-flavor mapping generation.
       
   276         // See SystemFlavorMap.getFlavorsForNative() for details.
       
   277         if ("text".equals(primaryType)) {
       
   278             value = primaryType + "/" + df.getSubType();
       
   279         } else if ("image".equals(primaryType)) {
       
   280             Iterator readers = ImageIO.getImageReadersByMIMEType(baseType);
       
   281             if (readers.hasNext()) {
       
   282                 flavors.add(DataFlavor.imageFlavor);
       
   283             }
       
   284         }
       
   285 
       
   286         flavors.add(value);
       
   287 
       
   288         return flavors;
       
   289     }
       
   290 
       
   291     private static ImageTypeSpecifier defaultSpecifier = null;
       
   292 
       
   293     private ImageTypeSpecifier getDefaultImageTypeSpecifier() {
       
   294         if (defaultSpecifier == null) {
       
   295             ColorModel model = ColorModel.getRGBdefault();
       
   296             WritableRaster raster =
       
   297                 model.createCompatibleWritableRaster(10, 10);
       
   298 
       
   299             BufferedImage bufferedImage =
       
   300                 new BufferedImage(model, raster, model.isAlphaPremultiplied(),
       
   301                                   null);
       
   302 
       
   303             defaultSpecifier = new ImageTypeSpecifier(bufferedImage);
       
   304         }
       
   305 
       
   306         return defaultSpecifier;
       
   307     }
       
   308 
       
   309     /*
       
   310      * The XDnD protocol prescribes that the Atoms used as targets for data
       
   311      * transfer should have string names that represent the corresponding MIME
       
   312      * types.
       
   313      * To meet this requirement we return a list of formats that represent
       
   314      * MIME types to which the data in this flavor can be translated by the Data
       
   315      * Transfer subsystem.
       
   316      */
       
   317     public List getPlatformMappingsForFlavor(DataFlavor df) {
       
   318         List natives = new ArrayList(1);
       
   319 
       
   320         if (df == null) {
       
   321             return natives;
       
   322         }
       
   323 
       
   324         String charset = df.getParameter("charset");
       
   325         String baseType = df.getPrimaryType() + "/" + df.getSubType();
       
   326         String mimeType = baseType;
       
   327 
       
   328         if (charset != null && DataTransferer.isFlavorCharsetTextType(df)) {
       
   329             mimeType += ";charset=" + charset;
       
   330         }
       
   331 
       
   332         // Add a mapping to the MIME native whenever the representation class
       
   333         // doesn't require translation.
       
   334         if (df.getRepresentationClass() != null &&
       
   335             (df.isRepresentationClassInputStream() ||
       
   336              df.isRepresentationClassByteBuffer() ||
       
   337              byteArrayClass.equals(df.getRepresentationClass()))) {
       
   338             natives.add(mimeType);
       
   339         }
       
   340 
       
   341         if (DataFlavor.imageFlavor.equals(df)) {
       
   342             String[] mimeTypes = ImageIO.getWriterMIMETypes();
       
   343             if (mimeTypes != null) {
       
   344                 for (int i = 0; i < mimeTypes.length; i++) {
       
   345                     Iterator writers =
       
   346                         ImageIO.getImageWritersByMIMEType(mimeTypes[i]);
       
   347 
       
   348                     while (writers.hasNext()) {
       
   349                         ImageWriter imageWriter = (ImageWriter)writers.next();
       
   350                         ImageWriterSpi writerSpi =
       
   351                             imageWriter.getOriginatingProvider();
       
   352 
       
   353                         if (writerSpi != null &&
       
   354                             writerSpi.canEncodeImage(getDefaultImageTypeSpecifier())) {
       
   355                             natives.add(mimeTypes[i]);
       
   356                             break;
       
   357                         }
       
   358                     }
       
   359                 }
       
   360             }
       
   361         } else if (DataTransferer.isFlavorCharsetTextType(df)) {
       
   362             final Iterator iter = DataTransferer.standardEncodings();
       
   363 
       
   364             // stringFlavor is semantically equivalent to the standard
       
   365             // "text/plain" MIME type.
       
   366             if (DataFlavor.stringFlavor.equals(df)) {
       
   367                 baseType = "text/plain";
       
   368             }
       
   369 
       
   370             while (iter.hasNext()) {
       
   371                 String encoding = (String)iter.next();
       
   372                 if (!encoding.equals(charset)) {
       
   373                     natives.add(baseType + ";charset=" + encoding);
       
   374                 }
       
   375             }
       
   376 
       
   377             // Add a MIME format without specified charset.
       
   378             if (!natives.contains(baseType)) {
       
   379                 natives.add(baseType);
       
   380             }
       
   381         }
       
   382 
       
   383         return natives;
       
   384     }
       
   385     protected native String[] dragQueryFile(byte[] bytes);
       
   386 }