Source Code Cross Referenced for WindowTracker.java in  » Testing » abbot-1.0.1 » abbot » tester » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » abbot 1.0.1 » abbot.tester 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package abbot.tester;
002:
003:        import java.awt.*;
004:        import java.awt.event.*;
005:        import javax.swing.SwingUtilities;
006:        import java.lang.ref.*;
007:        import java.util.*;
008:
009:        import abbot.Log;
010:        import abbot.util.AWT;
011:        import abbot.util.Properties;
012:        import abbot.util.WeakAWTEventListener;
013:        import abbot.util.NamedTimer;
014:
015:        /** Keep track of all known root windows, and all known showing/hidden/closed
016:         * windows.
017:         */
018:        public class WindowTracker {
019:
020:            private static class Holder {
021:                public static final WindowTracker INSTANCE = new WindowTracker();
022:            }
023:
024:            /** Maps unique event queues to the set of root windows found on each
025:                queue. 
026:             */
027:            private Map contexts = new WeakHashMap();
028:            /** Maps components to their corresponding event queues. */
029:            private Map queues;
030:            private ContextTracker contextTracker;
031:            /** Windows which for which isShowing is true but are not yet ready for
032:                input. */
033:            private Map pendingWindows = new WeakHashMap();
034:            /** Windows which we deem are ready to use.  */
035:            private Map openWindows = new WeakHashMap();
036:            /** Windows which are not visible. */
037:            private Map hiddenWindows = new WeakHashMap();
038:            /** Windows which have sent a WINDOW_CLOSE event. */
039:            private Map closedWindows = new WeakHashMap();
040:            private WindowReadyTracker windowReadyTracker;
041:            private java.awt.Robot robot;
042:            static int WINDOW_READY_DELAY = Properties.getProperty(
043:                    "abbot.window_ready_delay", 10000, 0, 60000);
044:            private Timer windowReadyTimer;
045:
046:            /** Only ever want one of these. */
047:            public static WindowTracker getTracker() {
048:                return Holder.INSTANCE;
049:            }
050:
051:            /** Create an instance of WindowTracker which will track all windows
052:             * coming and going on the current and subsequent app contexts. 
053:             * WARNING: if an applet loads this class, it will only ever see stuff in
054:             * its own app context.
055:             */
056:            WindowTracker() {
057:                contextTracker = new ContextTracker();
058:                windowReadyTracker = new WindowReadyTracker();
059:                // hold the event queue references weakly
060:                // each queue maps to a set of components (actually a weak hash map to
061:                // allow GC of the component keys).
062:                contexts.put(Toolkit.getDefaultToolkit().getSystemEventQueue(),
063:                        new WeakHashMap());
064:                // hold both the component references and the event queues weakly
065:                queues = new WeakHashMap();
066:                // Populate stuff that may already have shown/been hidden
067:                Frame[] frames = Frame.getFrames();
068:                synchronized (openWindows) {
069:                    for (int i = 0; i < frames.length; i++) {
070:                        scanExistingWindows(frames[i]);
071:                    }
072:                }
073:                try {
074:                    robot = new java.awt.Robot();
075:                } catch (AWTException e) {
076:                }
077:                windowReadyTimer = new NamedTimer("Window Ready Timer", true);
078:
079:                long mask = WindowEvent.WINDOW_EVENT_MASK
080:                        | ComponentEvent.COMPONENT_EVENT_MASK;
081:                new WeakAWTEventListener(contextTracker, mask);
082:                mask = InputEvent.MOUSE_MOTION_EVENT_MASK
083:                        | InputEvent.MOUSE_EVENT_MASK
084:                        | InputEvent.PAINT_EVENT_MASK;
085:                new WeakAWTEventListener(windowReadyTracker, mask);
086:            }
087:
088:            private void scanExistingWindows(Window w) {
089:                // Make sure we catch subsequent show/hide events for this window
090:                new WindowWatcher(w);
091:                Window[] windows = w.getOwnedWindows();
092:                for (int i = 0; i < windows.length; i++) {
093:                    scanExistingWindows(windows[i]);
094:                }
095:                openWindows.put(w, Boolean.TRUE);
096:                if (!w.isShowing()) {
097:                    hiddenWindows.put(w, Boolean.TRUE);
098:                }
099:                noteContext(w);
100:            }
101:
102:            /** Returns whether the window is ready to receive OS-level event input.
103:                A window's "isShowing" flag may be set true before the WINDOW_OPENED
104:                event is generated, and even after the WINDOW_OPENED is sent the
105:                window peer is not guaranteed to be ready.
106:             */
107:            public boolean isWindowReady(Window w) {
108:                synchronized (openWindows) {
109:                    if (openWindows.containsKey(w)
110:                            && !hiddenWindows.containsKey(w)) {
111:                        return true;
112:                    }
113:                }
114:                if (robot != null)
115:                    checkWindow(w, robot);
116:                return false;
117:            }
118:
119:            /** Return the event queue corresponding to the given component.  In most
120:                cases, this is the same as
121:                Component.getToolkit().getSystemEventQueue(), but in the case of
122:                applets will bypass the AppContext and provide the real event queue.
123:             */
124:            public EventQueue getQueue(Component c) {
125:                // Components above the applet in the hierarchy may or may not share
126:                // the same context with the applet itself.
127:                while (!(c instanceof  java.applet.Applet)
128:                        && c.getParent() != null)
129:                    c = c.getParent();
130:                synchronized (contexts) {
131:                    WeakReference ref = (WeakReference) queues.get(c);
132:                    EventQueue q = ref != null ? (EventQueue) ref.get() : null;
133:                    if (q == null)
134:                        q = c.getToolkit().getSystemEventQueue();
135:                    return q;
136:                }
137:            }
138:
139:            /** Returns all known event queues. */
140:            public Collection getEventQueues() {
141:                HashSet set = new HashSet();
142:                synchronized (contexts) {
143:                    set.addAll(contexts.keySet());
144:                    Iterator iter = queues.values().iterator();
145:                    while (iter.hasNext()) {
146:                        WeakReference ref = (WeakReference) iter.next();
147:                        EventQueue q = (EventQueue) ref.get();
148:                        if (q != null)
149:                            set.add(q);
150:                    }
151:                }
152:                return set;
153:            }
154:
155:            /** Return all available root Windows.  A root Window is one
156:             * that has a null parent.  Nominally this means a list similar to that
157:             * returned by Frame.getFrames(), but in the case of an Applet may return
158:             * a few Dialogs as well.
159:             */
160:            public Collection getRootWindows() {
161:                Set set = new HashSet();
162:                // Use Frame.getFrames() here in addition to our watched set, just in
163:                // case any of them is missing from our set.
164:                synchronized (contexts) {
165:                    Iterator iter = contexts.keySet().iterator();
166:                    while (iter.hasNext()) {
167:                        EventQueue queue = (EventQueue) iter.next();
168:                        Map map = (Map) contexts.get(queue);
169:                        set.addAll(map.keySet());
170:                    }
171:                }
172:                Frame[] frames = Frame.getFrames();
173:                for (int i = 0; i < frames.length; i++) {
174:                    set.add(frames[i]);
175:                }
176:                //Log.debug(String.valueOf(list.size()) + " total Frames");
177:                return set;
178:            }
179:
180:            /** Provides tracking of window visibility state.  We explicitly add this
181:             * on WINDOW_OPEN and remove it on WINDOW_CLOSE to avoid having to process
182:             * extraneous ComponentEvents.
183:             */
184:            private class WindowWatcher extends WindowAdapter implements 
185:                    ComponentListener {
186:                public WindowWatcher(Window w) {
187:                    w.addComponentListener(this );
188:                    w.addWindowListener(this );
189:                }
190:
191:                public void componentShown(ComponentEvent e) {
192:                    markWindowShowing((Window) e.getSource());
193:                }
194:
195:                public void componentHidden(ComponentEvent e) {
196:                    synchronized (openWindows) {
197:                        //Log.log("Marking " + e.getSource() + " hidden");
198:                        hiddenWindows.put(e.getSource(), Boolean.TRUE);
199:                        pendingWindows.remove(e.getSource());
200:                    }
201:                }
202:
203:                public void windowClosed(WindowEvent e) {
204:                    e.getWindow().removeWindowListener(this );
205:                    e.getWindow().removeComponentListener(this );
206:                }
207:
208:                public void componentResized(ComponentEvent e) {
209:                }
210:
211:                public void componentMoved(ComponentEvent e) {
212:                }
213:            }
214:
215:            /** Whenever we get a window that's on a new event dispatch thread, take
216:             * note of the thread, since it may correspond to a new event queue and
217:             * AppContext. 
218:             */
219:            // FIXME what if it has the same app context? can we check?
220:            private class ContextTracker implements  AWTEventListener {
221:                public void eventDispatched(AWTEvent ev) {
222:
223:                    ComponentEvent event = (ComponentEvent) ev;
224:                    Component comp = event.getComponent();
225:                    // This is our sole means of accessing other app contexts
226:                    // (if running within an applet).  We look for window events
227:                    // beyond OPENED in order to catch windows that have already
228:                    // opened by the time we start listening but which are not
229:                    // in the Frame.getFrames list (i.e. they are on a different
230:                    // context).   Specifically watch for COMPONENT_SHOWN on applets,
231:                    // since we may not get frame events for them.
232:                    if (!(comp instanceof  java.applet.Applet)
233:                            && !(comp instanceof  Window)) {
234:                        return;
235:                    }
236:
237:                    int id = ev.getID();
238:                    if (id == WindowEvent.WINDOW_OPENED) {
239:                        noteOpened(comp);
240:                    } else if (id == WindowEvent.WINDOW_CLOSED) {
241:                        noteClosed(comp);
242:                    } else if (id == WindowEvent.WINDOW_CLOSING) {
243:                        // ignore
244:                    }
245:                    // Take note of all other window events
246:                    else if ((id >= WindowEvent.WINDOW_FIRST && id <= WindowEvent.WINDOW_LAST)
247:                            || id == ComponentEvent.COMPONENT_SHOWN) {
248:                        synchronized (openWindows) {
249:                            if (!getRootWindows().contains(comp)
250:                                    || closedWindows.containsKey(comp)) {
251:                                noteOpened(comp);
252:                            }
253:                        }
254:                    }
255:                    // The context for root-level windows may change between
256:                    // WINDOW_OPENED and subsequent events.
257:                    synchronized (contexts) {
258:                        WeakReference ref = (WeakReference) queues.get(comp);
259:                        if (ref != null
260:                                && !comp.getToolkit().getSystemEventQueue()
261:                                        .equals(ref.get())) {
262:                            noteContext(comp);
263:                        }
264:                    }
265:                }
266:            }
267:
268:            private class WindowReadyTracker implements  AWTEventListener {
269:                public void eventDispatched(AWTEvent e) {
270:                    if (e instanceof  MouseEvent) {
271:                        Component c = (Component) e.getSource();
272:                        Window w = c instanceof  Window ? (Window) c
273:                                : SwingUtilities.getWindowAncestor(c);
274:                        markWindowReady(w);
275:                    }
276:                }
277:            }
278:
279:            private void noteContext(Component comp) {
280:                EventQueue queue = comp.getToolkit().getSystemEventQueue();
281:                synchronized (contexts) {
282:                    Map map = (Map) contexts.get(queue);
283:                    if (map == null) {
284:                        contexts.put(queue, map = new WeakHashMap());
285:                    }
286:                    if (comp instanceof  Window && comp.getParent() == null) {
287:                        map.put(comp, Boolean.TRUE);
288:                    }
289:                    queues.put(comp, new WeakReference(queue));
290:                }
291:            }
292:
293:            private void noteOpened(Component comp) {
294:                //Log.log("Noting " + comp + " opened");
295:                noteContext(comp);
296:                // Attempt to ensure the window is ready for input before recognizing
297:                // it as "open".  There is no Java API for this, so we institute an
298:                // empirically tested delay.
299:                if (comp instanceof  Window) {
300:                    new WindowWatcher((Window) comp);
301:                    markWindowShowing((Window) comp);
302:                    // Native components don't receive events anyway...
303:                    if (comp instanceof  FileDialog) {
304:                        markWindowReady((Window) comp);
305:                    }
306:                }
307:            }
308:
309:            private void noteClosed(Component comp) {
310:                if (comp.getParent() == null) {
311:                    EventQueue queue = comp.getToolkit().getSystemEventQueue();
312:                    synchronized (contexts) {
313:                        Map whm = (Map) contexts.get(queue);
314:                        if (whm != null)
315:                            whm.remove(comp);
316:                        else {
317:                            EventQueue foundQueue = null;
318:                            Iterator iter = contexts.keySet().iterator();
319:                            while (iter.hasNext()) {
320:                                EventQueue q = (EventQueue) iter.next();
321:                                Map map = (Map) contexts.get(q);
322:                                if (map.containsKey(comp)) {
323:                                    foundQueue = q;
324:                                    map.remove(comp);
325:                                }
326:                            }
327:                            if (foundQueue == null) {
328:                                Log.log("Got WINDOW_CLOSED on "
329:                                        + Robot.toString(comp)
330:                                        + " on a previously unseen context: "
331:                                        + queue + "(" + Thread.currentThread()
332:                                        + ")");
333:                            } else {
334:                                Log.log("Window " + Robot.toString(comp)
335:                                        + " sent WINDOW_CLOSED on " + queue
336:                                        + " but sent WINDOW_OPENED on "
337:                                        + foundQueue);
338:                            }
339:                        }
340:                    }
341:                }
342:                synchronized (openWindows) {
343:                    //Log.log("Marking " + comp + " closed");
344:                    openWindows.remove(comp);
345:                    hiddenWindows.remove(comp);
346:                    closedWindows.put(comp, Boolean.TRUE);
347:                    pendingWindows.remove(comp);
348:                }
349:            }
350:
351:            /** Mark the given Window as ready for input.  Indicate whether any
352:             * pending "mark ready" task should be canceled.
353:             */
354:            private void markWindowReady(Window w) {
355:                synchronized (openWindows) {
356:                    // If the window was closed after the check timer started running,
357:                    // it will have canceled the pending ready.
358:                    // Make sure it's still on the pending list before we actually
359:                    // mark it ready.
360:                    if (pendingWindows.containsKey(w)) {
361:                        //Log.log("Noting " + w + " ready");
362:                        closedWindows.remove(w);
363:                        hiddenWindows.remove(w);
364:                        openWindows.put(w, Boolean.TRUE);
365:                        pendingWindows.remove(w);
366:                    }
367:                }
368:            }
369:
370:            /** Indicate a window has set isShowing true and needs to be marked ready
371:                when it is actually ready.
372:             */
373:            private void markWindowShowing(final Window w) {
374:                synchronized (openWindows) {
375:                    // At worst, time out and say the window is ready
376:                    // after the configurable delay
377:                    TimerTask task = new TimerTask() {
378:                        public void run() {
379:                            markWindowReady(w);
380:                        }
381:                    };
382:                    windowReadyTimer.schedule(task, WINDOW_READY_DELAY);
383:                    pendingWindows.put(w, task);
384:                }
385:            }
386:
387:            private static int sign = 1;
388:
389:            /** Actively check whether the given window is ready for input.
390:             * @param robot
391:             * @see #isWindowReady
392:             */
393:            private void checkWindow(final Window w, java.awt.Robot robot) {
394:                // Must avoid frame borders, which are insensitive to mouse
395:                // motion (at least on w32).
396:                final Insets insets = AWT.getInsets(w);
397:                final int width = w.getWidth();
398:                final int height = w.getHeight();
399:                int x = w.getX() + insets.left
400:                        + (width - (insets.left + insets.right)) / 2;
401:                int y = w.getY() + insets.top
402:                        + (height - (insets.top + insets.bottom)) / 2;
403:                if (x != 0 && y != 0) {
404:                    robot.mouseMove(x, y);
405:                    if (width > height)
406:                        robot.mouseMove(x + sign, y);
407:                    else
408:                        robot.mouseMove(x, y + sign);
409:                    sign = -sign;
410:                }
411:                synchronized (openWindows) {
412:                    if (pendingWindows.containsKey(w) && isEmptyFrame(w)) {
413:                        // Force the frame to be large enough to receive events
414:                        SwingUtilities.invokeLater(new Runnable() {
415:                            public void run() {
416:                                int nw = Math.max(width, insets.left
417:                                        + insets.right + 3);
418:                                int nh = Math.max(height, insets.top
419:                                        + insets.bottom + 3);
420:                                w.setSize(nw, nh);
421:                            }
422:                        });
423:                    }
424:                }
425:            }
426:
427:            /** We can't get any motion events on an empty frame. */
428:            private boolean isEmptyFrame(Window w) {
429:                Insets insets = AWT.getInsets(w);
430:                return insets.top + insets.bottom == w.getHeight()
431:                        || insets.left + insets.right == w.getWidth();
432:            }
433:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.