Line 0
Link Here
|
|
|
1 |
/* |
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
3 |
* |
4 |
* Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. |
5 |
* |
6 |
* Oracle and Java are registered trademarks of Oracle and/or its affiliates. |
7 |
* Other names may be trademarks of their respective owners. |
8 |
* |
9 |
* The contents of this file are subject to the terms of either the GNU |
10 |
* General Public License Version 2 only ("GPL") or the Common |
11 |
* Development and Distribution License("CDDL") (collectively, the |
12 |
* "License"). You may not use this file except in compliance with the |
13 |
* License. You can obtain a copy of the License at |
14 |
* http://www.netbeans.org/cddl-gplv2.html |
15 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the |
16 |
* specific language governing permissions and limitations under the |
17 |
* License. When distributing the software, include this License Header |
18 |
* Notice in each file and include the License file at |
19 |
* nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this |
20 |
* particular file as subject to the "Classpath" exception as provided |
21 |
* by Oracle in the GPL Version 2 section of the License file that |
22 |
* accompanied this code. If applicable, add the following below the |
23 |
* License Header, with the fields enclosed by brackets [] replaced by |
24 |
* your own identifying information: |
25 |
* "Portions Copyrighted [year] [name of copyright owner]" |
26 |
* |
27 |
* Contributor(s): |
28 |
* |
29 |
* The Original Software is NetBeans. |
30 |
* Portions Copyrighted 2007 Sun Microsystems, Inc. |
31 |
*/ |
32 |
package org.openide.text; |
33 |
|
34 |
import java.awt.GraphicsEnvironment; |
35 |
import java.beans.PropertyChangeEvent; |
36 |
import java.beans.PropertyChangeListener; |
37 |
import java.io.ByteArrayOutputStream; |
38 |
import java.io.InputStream; |
39 |
import java.lang.ref.WeakReference; |
40 |
import java.util.Arrays; |
41 |
import java.util.concurrent.atomic.AtomicBoolean; |
42 |
import javax.swing.SwingUtilities; |
43 |
import javax.swing.text.Document; |
44 |
import javax.swing.text.EditorKit; |
45 |
import junit.framework.Test; |
46 |
import junit.framework.TestSuite; |
47 |
import org.netbeans.junit.MockServices; |
48 |
import org.netbeans.junit.NbTestCase; |
49 |
import org.openide.DialogDescriptor; |
50 |
import org.openide.DialogDisplayer; |
51 |
import org.openide.NotifyDescriptor; |
52 |
import org.openide.cookies.EditorCookie; |
53 |
import org.openide.util.Lookup; |
54 |
import org.openide.util.lookup.AbstractLookup; |
55 |
import org.openide.util.lookup.InstanceContent; |
56 |
import org.openide.windows.CloneableOpenSupport; |
57 |
import org.openide.windows.CloneableOpenSupportRedirector; |
58 |
|
59 |
/** |
60 |
* based on functionality from CloneableEditorSupportRedirectorTest |
61 |
* @author Vladimir Voskresensky |
62 |
*/ |
63 |
public class CloneableEditorSupportCOSRedirectorTest extends NbTestCase |
64 |
implements CloneableEditorSupport.Env { |
65 |
|
66 |
public static Test suite() { |
67 |
return GraphicsEnvironment.isHeadless() ? new TestSuite() : new TestSuite(CloneableEditorSupportCOSRedirectorTest.class); |
68 |
} |
69 |
|
70 |
static { |
71 |
System.setProperty("org.openide.windows.DummyWindowManager.VISIBLE", "false"); |
72 |
} |
73 |
/** the content of lookup of support */ |
74 |
private InstanceContent ic; |
75 |
private Redirector red; |
76 |
private DialogDisplayer dd; |
77 |
|
78 |
|
79 |
// Env variables |
80 |
private final StringBuilder content; |
81 |
private boolean modified = false; |
82 |
private final java.util.Date date = new java.util.Date (); |
83 |
private java.util.List<PropertyChangeListener> propL = new java.util.ArrayList<PropertyChangeListener>(); |
84 |
private java.beans.VetoableChangeListener vetoL; |
85 |
|
86 |
|
87 |
|
88 |
public CloneableEditorSupportCOSRedirectorTest(String testName) { |
89 |
super(testName); |
90 |
this.content = new StringBuilder(""); |
91 |
} |
92 |
|
93 |
public CloneableEditorSupportCOSRedirectorTest(StringBuilder content) { |
94 |
super(""); |
95 |
this.content = content; |
96 |
} |
97 |
|
98 |
protected void setUp () { |
99 |
ic = new InstanceContent (); |
100 |
CES support = new CES (this, new AbstractLookup(ic)); |
101 |
|
102 |
MockServices.setServices(Redirector.class, DD.class); |
103 |
red = Lookup.getDefault().lookup(Redirector.class); |
104 |
assertNotNull(red); |
105 |
dd = Lookup.getDefault().lookup(DD.class); |
106 |
assertNotNull(dd); |
107 |
|
108 |
CloneableEditorSupportCOSRedirectorTest t = new CloneableEditorSupportCOSRedirectorTest(this.content); |
109 |
red.master = support; |
110 |
InstanceContent slave = new InstanceContent(); |
111 |
red.slave = new CES(t, new AbstractLookup (slave)); |
112 |
slave.add(red.master); |
113 |
} |
114 |
|
115 |
@Override |
116 |
protected void tearDown() throws Exception { |
117 |
super.tearDown(); |
118 |
red.master.close(); |
119 |
red.slave.close(); |
120 |
content.delete(0, content.length()); |
121 |
} |
122 |
|
123 |
public void testSameDocument() throws Exception { |
124 |
red.master.open(); |
125 |
red.slave.open(); |
126 |
javax.swing.text.Document doc = red.slave.openDocument (); |
127 |
assertNotNull (doc); |
128 |
|
129 |
assertSame(doc, red.master.getDocument()); |
130 |
|
131 |
String s = doc.getText (0, doc.getLength ()); |
132 |
assertEquals ("Same text as in the stream", content.toString(), s); |
133 |
|
134 |
assertFalse ("No redo", red.slave.getUndoRedo ().canRedo ()); |
135 |
assertFalse ("No undo", red.slave.getUndoRedo ().canUndo ()); |
136 |
} |
137 |
|
138 |
public void testLineLookupIsPropagated () throws Exception { |
139 |
content.append("Line1\nLine2\n"); |
140 |
red.master.open(); |
141 |
red.slave.open(); |
142 |
Integer template = new Integer (1); |
143 |
ic.add (template); // put anything into the lookup |
144 |
|
145 |
// in order to set.getLines() work correctly, the document has to be loaded |
146 |
red.master.openDocument(); |
147 |
|
148 |
Line.Set set = red.master.getLineSet(); |
149 |
assertSame("Same lines", set, red.slave.getLineSet()); |
150 |
java.util.List list = set.getLines(); |
151 |
assertEquals ("Three lines", 3, list.size ()); |
152 |
|
153 |
Line l = (Line)list.get (0); |
154 |
Integer i = l.getLookup ().lookup (Integer.class); |
155 |
assertEquals ("The original integer", template, i); |
156 |
ic.remove (template); |
157 |
i = l.getLookup ().lookup (Integer.class); |
158 |
assertNull ("Lookup is dynamic, so now there is nothing", i); |
159 |
} |
160 |
|
161 |
|
162 |
public void testGetInputStream () throws Exception { |
163 |
content.append("goes\nto\nInputStream"); |
164 |
red.master.open(); |
165 |
red.slave.open(); |
166 |
String added = "added before\n"; |
167 |
javax.swing.text.Document doc = red.master.openDocument (); |
168 |
assertNotNull (doc); |
169 |
|
170 |
// modify the document |
171 |
doc.insertString(0, added, null); |
172 |
compareStreamWithString(red.master.getInputStream(), added + content); |
173 |
compareStreamWithString(red.slave.getInputStream(), added + content); |
174 |
} |
175 |
|
176 |
public void testGetInputStreamWhenClosed () throws Exception { |
177 |
content.append("basic\ncontent"); |
178 |
red.master.open(); |
179 |
red.slave.open(); |
180 |
compareStreamWithString(red.master.getInputStream(), content); |
181 |
compareStreamWithString(red.slave.getInputStream(), content); |
182 |
// we should be doing this with the document still closed |
183 |
assertNull("The document is supposed to be still closed", red.master.getDocument ()); |
184 |
} |
185 |
|
186 |
public void testDocumentCanBeGarbageCollectedWhenClosed () throws Exception { |
187 |
content.append("Ahoj\nMyDoc"); |
188 |
red.master.open(); |
189 |
red.slave.open(); |
190 |
javax.swing.text.Document doc = red.master.openDocument (); |
191 |
assertNotNull (doc); |
192 |
|
193 |
assertTrue ("Document is loaded", red.master.isDocumentLoaded ()); |
194 |
assertTrue ("Document is loaded", red.slave.isDocumentLoaded ()); |
195 |
assertTrue ("Can be closed without problems", red.slave.close ()); |
196 |
assertFalse ("Document is not loaded", red.master.isDocumentLoaded ()); |
197 |
assertFalse ("Document is not loaded", red.slave.isDocumentLoaded ()); |
198 |
|
199 |
WeakReference<?> ref = new WeakReference<Document>(doc); |
200 |
doc = null; |
201 |
|
202 |
assertGC ("Document can dissapear", ref); |
203 |
} |
204 |
|
205 |
/** |
206 |
* Tests that the wrapEditorComponent() method returns the passed |
207 |
* parameter (doesn't wrap the passed component in some additional UI). |
208 |
*/ |
209 |
public void testWrapEditorComponent() { |
210 |
javax.swing.JPanel panel = new javax.swing.JPanel(); |
211 |
assertSame(red.master.wrapEditorComponent(panel), panel); |
212 |
assertSame(red.slave.wrapEditorComponent(panel), panel); |
213 |
} |
214 |
|
215 |
public void testAfterOpenOfSlaveThereArePanesAndEvent() throws Exception { |
216 |
red.master.open(); |
217 |
final AtomicBoolean wasNonEmtpyOpenedPanesEvent = new AtomicBoolean(false); |
218 |
final AtomicBoolean emtpyPanes = new AtomicBoolean(false); |
219 |
final AtomicBoolean nonEmtpyPanes = new AtomicBoolean(false); |
220 |
|
221 |
PropertyChangeListener l = new PropertyChangeListener() { |
222 |
|
223 |
@Override |
224 |
public void propertyChange(PropertyChangeEvent evt) { |
225 |
if (EditorCookie.Observable.PROP_OPENED_PANES.equals(evt.getPropertyName())) { |
226 |
wasNonEmtpyOpenedPanesEvent.set(red.slave.getOpenedPanes() != null); |
227 |
} |
228 |
} |
229 |
|
230 |
}; |
231 |
red.slave.addPropertyChangeListener(l); |
232 |
|
233 |
class Check implements Runnable { |
234 |
@Override |
235 |
public void run() { |
236 |
// editor not yet opened, attach listener and open from there |
237 |
emtpyPanes.set(red.slave.getOpenedPanes() == null); |
238 |
red.slave.open(); |
239 |
nonEmtpyPanes.set(red.slave.getOpenedPanes() != null); |
240 |
} |
241 |
} |
242 |
Check check = new Check(); |
243 |
|
244 |
SwingUtilities.invokeAndWait(check); |
245 |
red.slave.removePropertyChangeListener(l); |
246 |
assertTrue("No panes are open before red.slave.open", emtpyPanes.get()); |
247 |
assertTrue("Some panes are now open after red.slave.open", nonEmtpyPanes.get()); |
248 |
assertTrue("PROP_OPENED_PANES event was not fired", wasNonEmtpyOpenedPanesEvent.get()); |
249 |
} |
250 |
|
251 |
public void testGetEditorKit() { |
252 |
EditorKit kit = CloneableEditorSupport.getEditorKit("text/plain"); |
253 |
assertNotNull("EditorKit should never be null", kit); |
254 |
// There shouldn't be any EK registered and we should get the default one |
255 |
assertEquals("Wrong default EditorKit", "org.openide.text.CloneableEditorSupport$PlainEditorKit", kit.getClass().getName()); |
256 |
} |
257 |
|
258 |
private void compareStreamWithString(InputStream is, CharSequence s) throws Exception{ |
259 |
int i; |
260 |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
261 |
while ((i = is.read()) != -1) { |
262 |
baos.write(i); |
263 |
} |
264 |
byte b1[] = baos.toByteArray(); |
265 |
byte b2[] = s.toString().getBytes(); |
266 |
assertTrue("Same bytes as would result from the string: " + s, Arrays.equals(b1, b2)); |
267 |
} |
268 |
|
269 |
// |
270 |
// Implementation of the CloneableEditorred.master.Env |
271 |
// |
272 |
|
273 |
public synchronized void addPropertyChangeListener(java.beans.PropertyChangeListener l) { |
274 |
propL.add (l); |
275 |
} |
276 |
public synchronized void removePropertyChangeListener(java.beans.PropertyChangeListener l) { |
277 |
propL.remove (l); |
278 |
} |
279 |
|
280 |
public synchronized void addVetoableChangeListener(java.beans.VetoableChangeListener l) { |
281 |
assertNull ("This is the first veto listener", vetoL); |
282 |
vetoL = l; |
283 |
} |
284 |
public void removeVetoableChangeListener(java.beans.VetoableChangeListener l) { |
285 |
assertEquals ("Removing the right veto one", vetoL, l); |
286 |
vetoL = null; |
287 |
} |
288 |
|
289 |
public org.openide.windows.CloneableOpenSupport findCloneableOpenSupport() { |
290 |
return red.master; |
291 |
} |
292 |
|
293 |
public String getMimeType() { |
294 |
return "text/plain"; |
295 |
} |
296 |
|
297 |
public java.util.Date getTime() { |
298 |
return date; |
299 |
} |
300 |
|
301 |
public java.io.InputStream inputStream() throws java.io.IOException { |
302 |
return new java.io.ByteArrayInputStream (content.toString().getBytes ()); |
303 |
} |
304 |
public java.io.OutputStream outputStream() throws java.io.IOException { |
305 |
class ContentStream extends java.io.ByteArrayOutputStream { |
306 |
public void close () throws java.io.IOException { |
307 |
super.close (); |
308 |
content.append(new String (toByteArray ())); |
309 |
} |
310 |
} |
311 |
|
312 |
return new ContentStream (); |
313 |
} |
314 |
|
315 |
public boolean isValid() { |
316 |
return true; |
317 |
} |
318 |
|
319 |
public boolean isModified() { |
320 |
return modified; |
321 |
} |
322 |
|
323 |
public void markModified() throws java.io.IOException { |
324 |
modified = true; |
325 |
} |
326 |
|
327 |
public void unmarkModified() { |
328 |
modified = false; |
329 |
} |
330 |
|
331 |
/** Implementation of the CES */ |
332 |
private static final class CES extends CloneableEditorSupport { |
333 |
public CES (Env env, Lookup l) { |
334 |
super (env, l); |
335 |
} |
336 |
|
337 |
@Override |
338 |
protected boolean asynchronousOpen() { |
339 |
return true; |
340 |
} |
341 |
|
342 |
protected String messageName() { |
343 |
return "Name"; |
344 |
} |
345 |
|
346 |
protected String messageOpened() { |
347 |
return "Opened"; |
348 |
} |
349 |
|
350 |
protected String messageOpening() { |
351 |
return "Opening"; |
352 |
} |
353 |
|
354 |
protected String messageSave() { |
355 |
return "Save"; |
356 |
} |
357 |
|
358 |
protected String messageToolTip() { |
359 |
return "ToolTip"; |
360 |
} |
361 |
|
362 |
} |
363 |
|
364 |
|
365 |
public static final class Redirector extends CloneableOpenSupportRedirector { |
366 |
CES master; |
367 |
CES slave; |
368 |
|
369 |
@Override |
370 |
protected CloneableOpenSupport redirect(CloneableOpenSupport.Env env) { |
371 |
if (env == slave.cesEnv()) { |
372 |
return master; |
373 |
} |
374 |
return null; |
375 |
} |
376 |
|
377 |
@Override |
378 |
protected void opened(CloneableOpenSupport.Env env) { |
379 |
} |
380 |
|
381 |
@Override |
382 |
protected void closed(CloneableOpenSupport.Env env) { |
383 |
} |
384 |
} |
385 |
/** |
386 |
* Our own dialog displayer when modified CES is closed we agree to close it. |
387 |
*/ |
388 |
public static final class DD extends DialogDisplayer { |
389 |
|
390 |
public static Object[] options; |
391 |
public static Object toReturn; |
392 |
public static boolean disableTest; |
393 |
|
394 |
public java.awt.Dialog createDialog(DialogDescriptor descriptor) { |
395 |
throw new IllegalStateException("Not implemented"); |
396 |
} |
397 |
|
398 |
public Object notify(NotifyDescriptor descriptor) { |
399 |
return NotifyDescriptor.CLOSED_OPTION; |
400 |
} |
401 |
} // end of DD |
402 |
} |