1 /*
   2  * Copyright (c) 1996, 2007, Oracle and/or its affiliates. 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.awt.windows;
  27 
  28 import java.awt.datatransfer.DataFlavor;
  29 import java.awt.datatransfer.Transferable;
  30 import java.awt.datatransfer.UnsupportedFlavorException;
  31 
  32 import java.io.IOException;
  33 
  34 import java.util.Iterator;
  35 import java.util.Map;
  36 
  37 import sun.awt.datatransfer.SunClipboard;
  38 import sun.awt.datatransfer.DataTransferer;
  39 
  40 
  41 /**
  42  * A class which interfaces with the Windows clipboard in order to support
  43  * data transfer via Clipboard operations. Most of the work is provided by
  44  * sun.awt.datatransfer.DataTransferer.
  45  *
  46  * @author Tom Ball
  47  * @author David Mendenhall
  48  * @author Danila Sinopalnikov
  49  * @author Alexander Gerasimov
  50  *
  51  * @since JDK1.1
  52  */
  53 public class WClipboard extends SunClipboard {
  54 
  55     private boolean isClipboardViewerRegistered;
  56 
  57     public WClipboard() {
  58         super("System");
  59     }
  60 
  61     public long getID() {
  62         return 0;
  63     }
  64 
  65     protected void setContentsNative(Transferable contents) {
  66 
  67         // Don't use delayed Clipboard rendering for the Transferable's data.
  68         // If we did that, we would call Transferable.getTransferData on
  69         // the Toolkit thread, which is a security hole.
  70         //
  71         // Get all of the target formats into which the Transferable can be
  72         // translated. Then, for each format, translate the data and post
  73         // it to the Clipboard.
  74         Map formatMap = WDataTransferer.getInstance().
  75             getFormatsForTransferable(contents, flavorMap);
  76 
  77         openClipboard(this);
  78 
  79         try {
  80             for (Iterator iter = formatMap.keySet().iterator();
  81                  iter.hasNext(); ) {
  82                 Long lFormat = (Long)iter.next();
  83                 long format = lFormat.longValue();
  84                 DataFlavor flavor = (DataFlavor)formatMap.get(lFormat);
  85 
  86                 try {
  87                     byte[] bytes = WDataTransferer.getInstance().
  88                         translateTransferable(contents, flavor, format);
  89                     publishClipboardData(format, bytes);
  90                 } catch (IOException e) {
  91                     // Fix 4696186: don't print exception if data with
  92                     // javaJVMLocalObjectMimeType failed to serialize.
  93                     // May remove this if-check when 5078787 is fixed.
  94                     if (!(flavor.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType) &&
  95                           e instanceof java.io.NotSerializableException)) {
  96                         e.printStackTrace();
  97                     }
  98                 }
  99             }
 100         } finally {
 101             closeClipboard();
 102         }
 103     }
 104 
 105     private void lostSelectionOwnershipImpl() {
 106         lostOwnershipImpl();
 107     }
 108 
 109     /**
 110      * Currently delayed data rendering is not used for the Windows clipboard,
 111      * so there is no native context to clear.
 112      */
 113     protected void clearNativeContext() {}
 114 
 115     /**
 116      * Call the Win32 OpenClipboard function. If newOwner is non-null,
 117      * we also call EmptyClipboard and take ownership.
 118      *
 119      * @throws IllegalStateException if the clipboard has not been opened
 120      */
 121     public native void openClipboard(SunClipboard newOwner) throws IllegalStateException;
 122     /**
 123      * Call the Win32 CloseClipboard function if we have clipboard ownership,
 124      * does nothing if we have not ownership.
 125      */
 126     public native void closeClipboard();
 127     /**
 128      * Call the Win32 SetClipboardData function.
 129      */
 130     private native void publishClipboardData(long format, byte[] bytes);
 131 
 132     private static native void init();
 133     static {
 134         init();
 135     }
 136 
 137     protected native long[] getClipboardFormats();
 138     protected native byte[] getClipboardData(long format) throws IOException;
 139 
 140     protected void registerClipboardViewerChecked() {
 141         if (!isClipboardViewerRegistered) {
 142             registerClipboardViewer();
 143             isClipboardViewerRegistered = true;
 144         }
 145     }
 146 
 147     private native void registerClipboardViewer();
 148 
 149     /**
 150      * The clipboard viewer (it's the toolkit window) is not unregistered
 151      * until the toolkit window disposing since MSDN suggests removing
 152      * the window from the clipboard viewer chain just before it is destroyed.
 153      */
 154     protected void unregisterClipboardViewerChecked() {}
 155 
 156     /**
 157      * Upcall from native code.
 158      */
 159     private void handleContentsChanged() {
 160         if (!areFlavorListenersRegistered()) {
 161             return;
 162         }
 163 
 164         long[] formats = null;
 165         try {
 166             openClipboard(null);
 167             formats = getClipboardFormats();
 168         } catch (IllegalStateException exc) {
 169             // do nothing to handle the exception, call checkChange(null)
 170         } finally {
 171             closeClipboard();
 172         }
 173         checkChange(formats);
 174     }
 175 
 176     /**
 177      * The clipboard must be opened.
 178      *
 179      * @since 1.5
 180      */
 181     protected Transferable createLocaleTransferable(long[] formats) throws IOException {
 182         boolean found = false;
 183         for (int i = 0; i < formats.length; i++) {
 184             if (formats[i] == WDataTransferer.CF_LOCALE) {
 185                 found = true;
 186                 break;
 187             }
 188         }
 189         if (!found) {
 190             return null;
 191         }
 192 
 193         byte[] localeData = null;
 194         try {
 195             localeData = getClipboardData(WDataTransferer.CF_LOCALE);
 196         } catch (IOException ioexc) {
 197             return null;
 198         }
 199 
 200         final byte[] localeDataFinal = localeData;
 201 
 202         return new Transferable() {
 203                 public DataFlavor[] getTransferDataFlavors() {
 204                     return new DataFlavor[] { DataTransferer.javaTextEncodingFlavor };
 205                 }
 206                 public boolean isDataFlavorSupported(DataFlavor flavor) {
 207                     return flavor.equals(DataTransferer.javaTextEncodingFlavor);
 208                 }
 209                 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
 210                     if (isDataFlavorSupported(flavor)) {
 211                         return localeDataFinal;
 212                     }
 213                     throw new UnsupportedFlavorException(flavor);
 214                 }
 215             };
 216     }
 217 
 218 }