KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > util > actions > CallbackSystemActionTest


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.openide.util.actions;
21
22 import java.awt.event.ActionEvent JavaDoc;
23 import java.beans.PropertyChangeEvent JavaDoc;
24 import java.beans.PropertyChangeListener JavaDoc;
25 import java.io.PrintWriter JavaDoc;
26 import java.io.StringWriter JavaDoc;
27 import java.lang.ref.Reference JavaDoc;
28 import java.lang.ref.WeakReference JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.logging.Level JavaDoc;
32 import java.util.logging.Logger JavaDoc;
33 import javax.swing.AbstractAction JavaDoc;
34 import javax.swing.Action JavaDoc;
35 import javax.swing.ActionMap JavaDoc;
36 import javax.swing.text.DefaultEditorKit JavaDoc;
37 import org.netbeans.junit.NbTestCase;
38 import org.openide.util.HelpCtx;
39 import org.openide.util.Lookup;
40 import org.openide.util.actions.ActionPerformer;
41 import org.openide.util.actions.CallbackSystemAction;
42 import org.openide.util.actions.SystemAction;
43 import org.openide.util.lookup.Lookups;
44
45 /** Test CallbackSystemAction: changing performer, focus tracking.
46  * @author Jesse Glick
47  */

48 public class CallbackSystemActionTest extends NbTestCase {
49     private Logger JavaDoc LOG;
50     
51     
52     public CallbackSystemActionTest(String JavaDoc name) {
53         super(name);
54     }
55     
56     protected void setUp() throws Exception JavaDoc {
57         LOG = Logger.getLogger("TEST-" + getName());
58         
59         LOG.info("setUp");
60     }
61     
62     protected void tearDown() throws Exception JavaDoc {
63         LOG.info("tearDown");
64         super.tearDown();
65         LOG.info("tearDown super finished");
66         SimpleCallbackAction.waitInstancesZero(LOG);
67         LOG.info("waiting for zero instances done");
68     }
69
70     protected Level JavaDoc logLevel() {
71         return Level.FINE;
72     }
73
74     protected int timeOut() {
75         return 5000;
76     }
77     
78     protected boolean runInEQ() {
79         return true;
80     }
81     
82     public void testPropertyChangeListenersDetachedAtFinalizeIssue58100() throws Exception JavaDoc {
83         
84         class MyAction extends AbstractAction JavaDoc
85                 implements ActionPerformer {
86             public void actionPerformed(ActionEvent JavaDoc ev) {
87             }
88             public void performAction(SystemAction a) {
89             }
90         }
91         MyAction action = new MyAction();
92         ActionMap JavaDoc map = new ActionMap JavaDoc();
93         CallbackSystemAction systemaction = (CallbackSystemAction)SystemAction.get(SimpleCallbackAction.class);
94         map.put(systemaction.getActionMapKey(), action);
95         Lookup context = Lookups.singleton(map);
96         Action JavaDoc delegateaction = systemaction.createContextAwareInstance(context);
97         
98         assertTrue("Action is expected to have a PropertyChangeListener attached", action.getPropertyChangeListeners().length > 0);
99         
100         Reference JavaDoc actionref = new WeakReference JavaDoc(systemaction);
101         systemaction = null;
102         delegateaction = null;
103         assertGC("CallbackSystemAction is supposed to be GCed", actionref);
104         
105         assertEquals("Action is expected to have no PropertyChangeListener attached", 0, action.getPropertyChangeListeners().length);
106     }
107     
108     public void testSurviveFocusChangeInTheNewWay() throws Exception JavaDoc {
109         doSurviveFocusChangeInTheNewWay(false);
110     }
111     
112     public void testSurviveFocusChangeInTheNewWayEvenActionIsGCed() throws Exception JavaDoc {
113         doSurviveFocusChangeInTheNewWay(true);
114     }
115     
116     private void doSurviveFocusChangeInTheNewWay(boolean doGC) throws Exception JavaDoc {
117         class MyAction extends AbstractAction JavaDoc {
118             public int cntEnabled;
119             public int cntPerformed;
120             
121             public boolean isEnabled() {
122                 cntEnabled++;
123                 return true;
124             }
125             
126             public void actionPerformed(ActionEvent JavaDoc ev) {
127                 cntPerformed++;
128             }
129         }
130         MyAction myAction = new MyAction();
131         
132         ActionMap JavaDoc other = new ActionMap JavaDoc();
133         ActionMap JavaDoc tc = new ActionMap JavaDoc();
134         SurviveFocusChgCallbackAction a = (SurviveFocusChgCallbackAction)SurviveFocusChgCallbackAction.get(SurviveFocusChgCallbackAction.class);
135         tc.put(a.getActionMapKey(), myAction);
136         
137         ActionsInfraHid.setActionMap(other);
138         try {
139             assertFalse("Disabled on other component", a.isEnabled());
140             ActionsInfraHid.setActionMap(tc);
141             assertTrue("MyAction is enabled", a.isEnabled());
142             assertEquals("isEnabled called once", 1, myAction.cntEnabled);
143             
144             if (doGC) {
145                 WeakReference JavaDoc ref = new WeakReference JavaDoc(a);
146                 a = null;
147                 assertGC("Action can disappear", ref);
148                 a = (SurviveFocusChgCallbackAction)SurviveFocusChgCallbackAction.get(SurviveFocusChgCallbackAction.class);
149             }
150             
151             ActionsInfraHid.setActionMap(other);
152             assertTrue("Still enabled", a.isEnabled());
153             assertEquals("isEnabled called still only once (now it is called twice)", 2, myAction.cntEnabled);
154         } finally {
155             ActionsInfraHid.setActionMap(null);
156         }
157         
158         WeakReference JavaDoc ref = new WeakReference JavaDoc(a);
159         WeakReference JavaDoc ref2 = new WeakReference JavaDoc(myAction);
160         WeakReference JavaDoc ref3 = new WeakReference JavaDoc(tc);
161         a = null;
162         myAction = null;
163         tc = null;
164         assertGC("We are able to clear global action", ref);
165         assertGC("Even our action", ref2);
166         assertGC("Even our component", ref3);
167     }
168     
169     /** Make sure that the performer system works and controls enablement.
170      */

171     public void testPerformer() throws Exception JavaDoc {
172         CallbackSystemAction a = (CallbackSystemAction)SystemAction.get(SimpleCallbackAction.class);
173         assertFalse(a.isEnabled());
174         Performer p = new Performer();
175         assertEquals(0, p.count);
176         a.setActionPerformer(p);
177         assertTrue(a.isEnabled());
178         a.actionPerformed(null);
179         assertEquals(1, p.count);
180         a.setActionPerformer(null);
181         assertFalse(a.isEnabled());
182     }
183     
184     /** Make sure that focus changes turn on or off actions as appropriate.
185      */

186     public void testFocusChanges() throws Exception JavaDoc {
187         helperTestFocusChanges();
188         // CallbackSystemAction keeps a listener separately from the action,
189
// so make sure the actions still work after collected and recreated.
190
// Note that similar code fails to work in NodeActionTest because the
191
// GC will not complete, so if the GC assert here starts to fail, it is
192
// OK to comment out the GC, its assert, and the second call to
193
// helperTestFocusChanges().
194
SimpleCallbackAction.waitInstancesZero(LOG);
195         helperTestFocusChanges();
196     }
197     private void helperTestFocusChanges() throws Exception JavaDoc {
198         ActionMap JavaDoc t1 = new ActionMap JavaDoc();
199         ActionMap JavaDoc t2 = new ActionMap JavaDoc();
200         ActionsInfraHid.setActionMap(t1);
201         try {
202             LOG.info("helperTestFocusChanges1");
203             CallbackSystemAction a1 = (CallbackSystemAction)SystemAction.get(SurviveFocusChgCallbackAction.class);
204             assertTrue(a1.getSurviveFocusChange());
205             LOG.info("helperTestFocusChanges2");
206             CallbackSystemAction a2 = (CallbackSystemAction)SystemAction.get(SimpleCallbackAction.class);
207             assertFalse(a2.getSurviveFocusChange());
208             LOG.info("helperTestFocusChanges3");
209             CallbackSystemAction a3 = (CallbackSystemAction)SystemAction.get(DoesNotSurviveFocusChgCallbackAction.class);
210             assertFalse(a3.getSurviveFocusChange());
211             Performer p = new Performer();
212             LOG.info("helperTestFocusChanges4");
213             a1.setActionPerformer(p);
214             a2.setActionPerformer(p);
215             a3.setActionPerformer(p);
216             LOG.info("helperTestFocusChanges5");
217             assertTrue(a1.isEnabled());
218             assertTrue(a2.isEnabled());
219             assertTrue(a3.isEnabled());
220             LOG.info("helperTestFocusChanges6");
221             ActionsInfraHid.setActionMap(t2);
222             LOG.info("helperTestFocusChanges7");
223             assertTrue(a1.isEnabled());
224             LOG.info("helperTestFocusChanges8");
225             assertEquals(p, a1.getActionPerformer());
226             assertFalse(a2.isEnabled());
227             LOG.info("helperTestFocusChanges9");
228             assertEquals(null, a2.getActionPerformer());
229             assertFalse(a3.isEnabled());
230             LOG.info("helperTestFocusChanges10");
231             assertEquals(null, a3.getActionPerformer());
232         } finally {
233             LOG.info("helperTestFocusChanges - finally");
234             ActionsInfraHid.setActionMap(null);
235             LOG.info("helperTestFocusChanges - done");
236         }
237         LOG.info("helperTestFocusChanges - done successfully");
238     }
239     
240     public void testGlobalChanges() throws Exception JavaDoc {
241         class MyAction extends AbstractAction JavaDoc {
242             public int cntEnabled;
243             public int cntPerformed;
244             
245             public boolean isEnabled() {
246                 cntEnabled++;
247                 return true;
248             }
249             
250             public void actionPerformed(ActionEvent JavaDoc ev) {
251                 cntPerformed++;
252             }
253         }
254         MyAction myAction = new MyAction();
255         
256         ActionMap JavaDoc tc = new ActionMap JavaDoc();
257         tc.put(DefaultEditorKit.copyAction, myAction);
258         CopyAction a = (CopyAction)CopyAction.get(CopyAction.class);
259         
260         ActionsInfraHid.setActionMap(tc);
261         try {
262             assertTrue("MyAction is enabled", a.isEnabled());
263             assertEquals("isEnabled called once", 1, myAction.cntEnabled);
264             a.setActionPerformer(null);
265             assertEquals("An enabled is currentlly called again", 2, myAction.cntEnabled);
266         } finally {
267             ActionsInfraHid.setActionMap(null);
268         }
269     }
270     private static final class CopyAction extends CallbackSystemAction {
271         public Object JavaDoc getActionMapKey() {
272             return DefaultEditorKit.copyAction;
273         }
274         public String JavaDoc getName() {
275             return "Copy";
276         }
277         public HelpCtx getHelpCtx() {
278             return null;
279         }
280         protected boolean asynchronous() {
281             return false;
282         }
283     }
284     
285     /** Action performer that counts invocations. */
286     public static final class Performer implements ActionPerformer {
287         public int count = 0;
288         public void performAction(SystemAction action) {
289             count++;
290         }
291     }
292     
293     /** Simple callback action. */
294     public static final class SimpleCallbackAction extends CallbackSystemAction {
295         public String JavaDoc getName() {
296             return "SimpleCallbackAction";
297         }
298         public HelpCtx getHelpCtx() {
299             return null;
300         }
301         
302         private static ArrayList JavaDoc INSTANCES_WHO = new ArrayList JavaDoc();
303         private static Object JavaDoc INSTANCES_LOCK = new Object JavaDoc();
304         public static int INSTANCES = 0;
305         
306         public static void waitInstancesZero(Logger JavaDoc l) throws InterruptedException JavaDoc {
307             for (int i = 0; i < 10; i++) {
308                 synchronized (INSTANCES_LOCK) {
309                     if (INSTANCES == 0) return;
310                     
311                     l.warning("instances still there: " + INSTANCES);
312                 }
313                 
314                 ActionsInfraHid.doGC();
315                 
316                 synchronized (INSTANCES_LOCK) {
317                     l.warning("after GC, do wait");
318                     
319                     INSTANCES_LOCK.wait(1000);
320                     l.warning("after waiting");
321                 }
322             }
323             failInstances("Instances are not zero");
324         }
325         
326         private static void failInstances(String JavaDoc msg) {
327             StringWriter JavaDoc w = new StringWriter JavaDoc();
328             PrintWriter JavaDoc pw = new PrintWriter JavaDoc(w);
329             pw.println(msg + ": " + INSTANCES);
330             for (Iterator JavaDoc it = INSTANCES_WHO.iterator(); it.hasNext();) {
331                 Exception JavaDoc elem = (Exception JavaDoc) it.next();
332                 elem.printStackTrace(pw);
333             }
334             pw.close();
335             fail(w.toString());
336         }
337         
338         public SimpleCallbackAction() {
339             synchronized (INSTANCES_LOCK) {
340                 INSTANCES++;
341                 INSTANCES_LOCK.notifyAll();
342                 INSTANCES_WHO.add(new Exception JavaDoc("Incremented to " + INSTANCES));
343                 
344                 if (INSTANCES == 2) {
345                     failInstances("Incremented to two. That is bad");
346                 }
347             }
348         }
349         protected boolean clearSharedData() {
350             synchronized (INSTANCES_LOCK) {
351                 INSTANCES--;
352                 INSTANCES_LOCK.notifyAll();
353                 INSTANCES_WHO.add(new Exception JavaDoc("Decremented to " + INSTANCES));
354             }
355             return super.clearSharedData();
356         }
357         protected boolean asynchronous() {
358             return false;
359         }
360     }
361     
362     /** Similar but survives focus changes. */
363     public static final class SurviveFocusChgCallbackAction extends CallbackSystemAction {
364         protected void initialize() {
365             super.initialize();
366             setSurviveFocusChange(true);
367         }
368         public String JavaDoc getName() {
369             return "SurviveFocusChgCallbackAction";
370         }
371         public HelpCtx getHelpCtx() {
372             return null;
373         }
374         protected boolean asynchronous() {
375             return false;
376         }
377     }
378     
379     /** Similar but does not; should behave like SimpleCallbackAction (it just sets the flag explicitly). */
380     public static final class DoesNotSurviveFocusChgCallbackAction extends CallbackSystemAction {
381         protected void initialize() {
382             super.initialize();
383             setSurviveFocusChange(false);
384         }
385         public String JavaDoc getName() {
386             return "SurviveFocusChgCallbackAction";
387         }
388         public HelpCtx getHelpCtx() {
389             return null;
390         }
391         protected boolean asynchronous() {
392             return false;
393         }
394     }
395     
396     
397     
398     
399     //
400
// Set of tests for ActionMap and context
401
//
402

403     public void testLookupOfStateInActionMap() throws Exception JavaDoc {
404         class MyAction extends AbstractAction JavaDoc
405                 implements ActionPerformer {
406             int actionPerformed;
407             int performAction;
408             
409             public void actionPerformed(ActionEvent JavaDoc ev) {
410                 actionPerformed++;
411             }
412             
413             public void performAction(SystemAction a) {
414                 performAction++;
415             }
416         }
417         MyAction action = new MyAction();
418         
419         ActionMap JavaDoc map = new ActionMap JavaDoc();
420         CallbackSystemAction system = (CallbackSystemAction)SystemAction.get(SurviveFocusChgCallbackAction.class);
421         system.setActionPerformer(null);
422         map.put(system.getActionMapKey(), action);
423         
424         
425         
426         Action JavaDoc clone;
427         
428         
429         //
430
// Without action map
431
//
432

433         clone = system.createContextAwareInstance(Lookup.EMPTY);
434         
435         assertTrue("Action should not be enabled if no callback provided", !clone.isEnabled());
436         
437         system.setActionPerformer(action);
438         assertTrue("Is enabled, because it has a performer", clone.isEnabled());
439         system.setActionPerformer(null);
440         assertTrue("Is disabled, because the performer has been unregistered", !clone.isEnabled());
441         
442         //
443
// test with actionmap
444
//
445
action.setEnabled(false);
446         
447         Lookup context = Lookups.singleton(map);
448         clone = system.createContextAwareInstance(context);
449         
450         CntListener listener = new CntListener();
451         clone.addPropertyChangeListener(listener);
452         
453         assertTrue("Not enabled now", !clone.isEnabled());
454         action.setEnabled(true);
455         assertTrue("Clone is enabled because the action in ActionMap is", clone.isEnabled());
456         listener.assertCnt("One change expected", 1);
457         
458         system.setActionPerformer(action);
459         clone.actionPerformed(new ActionEvent JavaDoc(this, 0, ""));
460         assertEquals("MyAction.actionPerformed invoked", 1, action.actionPerformed);
461         assertEquals("MyAction.performAction is not invoked", 0, action.performAction);
462         
463         
464         action.setEnabled(false);
465         assertTrue("Clone is disabled because the action in ActionMap is", !clone.isEnabled());
466         listener.assertCnt("Another change expected", 1);
467         
468         clone.actionPerformed(new ActionEvent JavaDoc(this, 0, ""));
469         assertEquals("MyAction.actionPerformed invoked again", 2, action.actionPerformed);
470         assertEquals("MyAction.performAction is not invoked, remains 0", 0, action.performAction);
471         
472     }
473     
474     private static final class CntListener extends Object JavaDoc
475             implements PropertyChangeListener JavaDoc {
476         private int cnt;
477         
478         public void propertyChange(PropertyChangeEvent JavaDoc evt) {
479             cnt++;
480         }
481         
482         public void assertCnt(String JavaDoc msg, int count) {
483             assertEquals(msg, count, this.cnt);
484             this.cnt = 0;
485         }
486     } // end of CntListener
487

488 }
489
Popular Tags