001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.core;
043:
044: import java.awt.Toolkit;
045: import java.awt.datatransfer.Clipboard;
046: import java.awt.datatransfer.ClipboardOwner;
047: import java.awt.datatransfer.DataFlavor;
048: import java.awt.datatransfer.StringSelection;
049: import java.awt.datatransfer.Transferable;
050: import java.awt.datatransfer.UnsupportedFlavorException;
051: import java.io.IOException;
052: import java.io.PrintStream;
053: import java.lang.reflect.InvocationTargetException;
054: import java.util.Date;
055: import java.util.logging.Level;
056: import java.util.logging.Logger;
057: import javax.swing.SwingUtilities;
058: import org.netbeans.junit.AssertionFailedErrorException;
059: import org.netbeans.junit.MockServices;
060: import org.netbeans.junit.NbTestCase;
061: import org.openide.util.Lookup;
062: import org.openide.util.datatransfer.ClipboardEvent;
063: import org.openide.util.datatransfer.ClipboardListener;
064: import org.openide.util.datatransfer.ExClipboard;
065: import org.openide.util.datatransfer.ExTransferable;
066: import org.openide.util.datatransfer.TransferListener;
067:
068: /** Test NbClipboard, in "native" mode (e.g. Windows).
069: * @author Jesse Glick
070: * @see "#30923"
071: */
072: public class NbClipboardNativeTest extends NbTestCase implements
073: ClipboardListener {
074: private NbClipboard ec;
075: private int listenerCalls;
076: private Logger LOG;
077:
078: public NbClipboardNativeTest(String name) {
079: super (name);
080: }
081:
082: protected void setUp() throws Exception {
083: MockServices.setServices();
084: LOG = Logger.getLogger("TEST-" + getName());
085:
086: class EmptyTrans implements Transferable, ClipboardOwner {
087: public DataFlavor[] getTransferDataFlavors() {
088: return new DataFlavor[0];
089: }
090:
091: public boolean isDataFlavorSupported(DataFlavor flavor) {
092: return false;
093: }
094:
095: public Object getTransferData(DataFlavor flavor)
096: throws UnsupportedFlavorException, IOException {
097: throw new IOException("Nothing here");
098: }
099:
100: public void lostOwnership(Clipboard clipboard,
101: Transferable contents) {
102: }
103: }
104:
105: super .setUp();
106:
107: LOG.info("Setting up");
108:
109: //System.setProperty("org.netbeans.core.NbClipboard", "-5");
110: System.setProperty("netbeans.slow.system.clipboard.hack",
111: String.valueOf(slowClipboardHack()));
112: this .ec = new NbClipboard();
113:
114: LOG.info("Clipboard created");
115:
116: EmptyTrans et = new EmptyTrans();
117: Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
118: et, et);
119:
120: waitFinished(this .ec);
121:
122: LOG.info("system clipboard content changed");
123:
124: this .ec.addClipboardListener(this );
125:
126: LOG.info("Listener added");
127: }
128:
129: protected void tearDown() throws Exception {
130: super .tearDown();
131: if (ec != null) {
132: this .ec.removeClipboardListener(this );
133: }
134:
135: waitFinished(ec);
136: }
137:
138: protected boolean slowClipboardHack() {
139: return false;
140: }
141:
142: public void testGetClipboardWorks() throws Exception {
143: class Get implements ClipboardListener {
144: Transferable in;
145:
146: public void clipboardChanged(ClipboardEvent ev) {
147: in = ec.getContents(this );
148: }
149: }
150:
151: Get get = new Get();
152: ec.addClipboardListener(get);
153:
154: StringSelection ss = new StringSelection("x");
155: ec.setContents(ss, ss);
156:
157: assertEquals("Inside is the right one", ss
158: .getTransferData(DataFlavor.stringFlavor), get.in
159: .getTransferData(DataFlavor.stringFlavor));
160: }
161:
162: public void testWhenCallingGetContentsItChecksSystemClipboardFirstTimeAfterActivation()
163: throws Exception {
164: assertEquals("No changes yet", 0, listenerCalls);
165:
166: Clipboard sc = Toolkit.getDefaultToolkit().getSystemClipboard();
167: StringSelection ss = new StringSelection("oldvalue");
168: sc.setContents(ss, ss);
169:
170: // just simulate initial switch to NetBeans main window
171: ec.activateWindowHack(true);
172: waitFinished(ec);
173:
174: if (listenerCalls == 0) {
175: fail("We need at least one call: " + listenerCalls);
176: }
177: listenerCalls = 0;
178:
179: StringSelection s2 = new StringSelection("data2");
180: sc.setContents(s2, s2);
181:
182: waitFinished(ec);
183:
184: if (slowClipboardHack()) {
185: assertEquals("No change notified", 0, listenerCalls);
186: }
187:
188: // we need to wait longer time than the value in NbClipboard
189: Thread.sleep(200);
190:
191: Transferable t = this .ec.getContents(this );
192: assertTrue("String flavor is there", t
193: .isDataFlavorSupported(DataFlavor.stringFlavor));
194:
195: String s = (String) t.getTransferData(DataFlavor.stringFlavor);
196: assertEquals(
197: "The getContents rechecked the system clipboard first time after window activated",
198: "data2", s);
199:
200: sc.setContents(ss, ss);
201:
202: t = this .ec.getContents(this );
203: s = (String) t.getTransferData(DataFlavor.stringFlavor);
204: if (slowClipboardHack()) {
205: assertEquals(
206: "The getContents rechecked the clipboard just for the first time, not now, so the content is the same",
207: "data2", s);
208:
209: ec.activateWindowHack(true);
210: Thread.sleep(200);
211:
212: t = this .ec.getContents(this );
213: s = (String) t.getTransferData(DataFlavor.stringFlavor);
214: assertEquals("The WINDOW_ACTIVATED rechecks the clipboard",
215: "oldvalue", s);
216: } else {
217: assertEquals(
218: "without slow hack it gets the value immediatelly",
219: "oldvalue", s);
220: }
221: }
222:
223: public void testClipboard() throws Exception {
224: MockServices.setServices(Cnv.class);
225: Clipboard c = Lookup.getDefault().lookup(Clipboard.class);
226: ExClipboard ec = Lookup.getDefault().lookup(ExClipboard.class);
227: assertEquals("Clipboard == ExClipboard", c, ec);
228: assertNotNull(Lookup.getDefault().lookup(
229: ExClipboard.Convertor.class));
230: assertEquals(Cnv.class, Lookup.getDefault().lookup(
231: ExClipboard.Convertor.class).getClass());
232: c.setContents(
233: new ExTransferable.Single(DataFlavor.stringFlavor) {
234: protected Object getData() throws IOException,
235: UnsupportedFlavorException {
236: return "17";
237: }
238: }, null);
239: Transferable t = c.getContents(null);
240: assertTrue("still supports stringFlavor", t
241: .isDataFlavorSupported(DataFlavor.stringFlavor));
242: assertEquals("correct string in clipboard", "17", t
243: .getTransferData(DataFlavor.stringFlavor));
244: assertTrue("support Integer too", t
245: .isDataFlavorSupported(MYFLAV));
246: assertEquals("correct Integer", new Integer(17), t
247: .getTransferData(MYFLAV));
248: }
249:
250: private static final DataFlavor MYFLAV = new DataFlavor(
251: "text/x-integer", "Integer"); // data: java.lang.Integer
252:
253: public static final class Cnv implements ExClipboard.Convertor {
254: public Transferable convert(Transferable t) {
255: Logger.getAnonymousLogger().info("converting...");
256: if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
257: final ExTransferable t2 = ExTransferable.create(t);
258: if (t2.isDataFlavorSupported(DataFlavor.stringFlavor)
259: && !t2.isDataFlavorSupported(MYFLAV)) {
260: t2.put(new ExTransferable.Single(MYFLAV) {
261: protected Object getData() throws IOException,
262: UnsupportedFlavorException {
263: String s = (String) t2
264: .getTransferData(DataFlavor.stringFlavor);
265: try {
266: return new Integer(s);
267: } catch (NumberFormatException nfe) {
268: throw new IOException(nfe.toString());
269: }
270: }
271: });
272: }
273: return t2;
274: } else {
275: return t;
276: }
277: }
278: }
279:
280: // #25537
281: public void testOwnershipLostEvent() throws Exception {
282: final int[] holder = new int[] { 0 };
283: ExTransferable transferable = ExTransferable
284: .create(new StringSelection("A"));
285:
286: // listen on ownershipLost
287: transferable.addTransferListener(new TransferListener() {
288: public void accepted(int action) {
289: }
290:
291: public void rejected() {
292: }
293:
294: public void ownershipLost() {
295: holder[0]++;
296: }
297: });
298:
299: Clipboard c = Lookup.getDefault().lookup(Clipboard.class);
300:
301: c.setContents(transferable, null);
302:
303: assertTrue("Still has ownership", holder[0] == 0);
304:
305: c.setContents(new StringSelection("B"), null);
306:
307: assertTrue("Exactly one ownershipLost event have happened.",
308: holder[0] == 1);
309: }
310:
311: public void clipboardChanged(ClipboardEvent ev) {
312: listenerCalls++;
313: LOG.log(Level.INFO, "clipboardChanged: " + listenerCalls,
314: new Exception());
315: }
316:
317: private void waitFinished(NbClipboard ec) {
318: try {
319: ec.waitFinished();
320: SwingUtilities.invokeAndWait(new Runnable() {
321: public void run() {
322: }
323: });
324: ec.waitFinished();
325: SwingUtilities.invokeAndWait(new Runnable() {
326: public void run() {
327: }
328: });
329: } catch (InterruptedException ex) {
330: throw new AssertionFailedErrorException(ex);
331: } catch (InvocationTargetException ex) {
332: throw new AssertionFailedErrorException(ex);
333: }
334: }
335:
336: protected Level logLevel() {
337: return Level.ALL;
338: }
339:
340: }
|