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): Alexandre Iline.
025: *
026: * The Original Software is the Jemmy library.
027: * The Initial Developer of the Original Software is Alexandre Iline.
028: * 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: *
043: * $Id$ $Revision$ $Date$
044: *
045: */
046:
047: package org.netbeans.jemmy;
048:
049: import java.awt.Component;
050: import java.awt.Frame;
051: import java.awt.Window;
052:
053: /**
054: * A WindowWaiter is a utility class used to look or wait for Windows.
055: * It contains methods to search for a Window among the currently
056: * showing Windows as well as methods that wait for a Window to show
057: * within an allotted time period.
058: *
059: * Searches and waits always involve search criteria applied by a
060: * ComponentChooser instance. Searches and waits can both be restricted
061: * to windows owned by a given window.
062: *
063: * <BR>Timeouts used: <BR>
064: * WindowWaiter.WaitWindowTimeout - time to wait window displayed <BR>
065: * WindowWaiter.AfterWindowTimeout - time to sleep after window has been dispayed <BR>
066: *
067: * @see org.netbeans.jemmy.Timeouts
068: *
069: * @author Alexandre Iline (alexandre.iline@sun.com)
070: */
071:
072: public class WindowWaiter extends Waiter implements Timeoutable {
073:
074: private final static long WAIT_TIME = 60000;
075: private final static long AFTER_WAIT_TIME = 0;
076:
077: private ComponentChooser chooser;
078: private Window owner = null;
079: private int index = 0;
080: private Timeouts timeouts;
081:
082: /**
083: * Constructor.
084: */
085: public WindowWaiter() {
086: super ();
087: setTimeouts(JemmyProperties.getProperties().getTimeouts());
088: }
089:
090: /**
091: * Searches for a window.
092: * The search proceeds among the currently showing windows
093: * for the <code>index+1</code>'th window that is both owned by the
094: * <code>java.awt.Window</code> <code>owner</code> and that meets the
095: * criteria defined and applied by the <code>ComponentChooser</code> parameter.
096: * @param owner The owner window of all the windows to be searched.
097: * @param cc A component chooser used to define and apply the search criteria.
098: * @param index The ordinal index of the window in the set of currently displayed
099: * windows with the proper window ownership and a suitable title. The first
100: * index is 0.
101: * @return a reference to the <code>index+1</code>'th window that is showing,
102: * has the proper window ownership, and that meets the search criteria.
103: * If there are fewer than <code>index+1</code> windows, a <code>null</code>
104: * reference is returned.
105: */
106: public static Window getWindow(Window owner, ComponentChooser cc,
107: int index) {
108: return (getAWindow(owner, new IndexChooser(cc, index)));
109: }
110:
111: /**
112: * Searches for a window.
113: * Search among the currently showing windows for the first that is both
114: * owned by the <code>java.awt.Window</code> <code>owner</code> and that
115: * meets the search criteria applied by the <code>ComponentChooser</code>
116: * parameter.
117: * @param owner The owner window of the windows to be searched.
118: * @param cc A component chooser used to define and apply the search criteria.
119: * @return a reference to the first window that is showing, has a proper
120: * owner window, and that meets the search criteria. If no such window
121: * can be found, a <code>null</code> reference is returned.
122: */
123: public static Window getWindow(Window owner, ComponentChooser cc) {
124: return (getWindow(owner, cc, 0));
125: }
126:
127: /**
128: * Searches for a window.
129: * The search proceeds among the currently showing windows for the
130: * <code>index+1</code>'th window that meets the criteria defined and
131: * applied by the <code>ComonentChooser</code> parameter.
132: * @param cc A component chooser used to define and apply the search criteria.
133: * @param index The ordinal index of the window in the set of currently displayed
134: * windows. The first index is 0.
135: * @return a reference to the <code>index+1</code>'th window that is showing
136: * and that meets the search criteria. If there are fewer than
137: * <code>index+1</code> windows, a <code>null</code> reference is returned.
138: */
139: public static Window getWindow(ComponentChooser cc, int index) {
140: return (getAWindow(new IndexChooser(cc, index)));
141: }
142:
143: /**
144: * Searches for a window.
145: * Search among the currently showing windows for one that meets the search
146: * criteria applied by the <code>ComponentChooser</code> parameter.
147: * @param cc A component chooser used to define and apply the search criteria.
148: * @return a reference to the first window that is showing and that
149: * meets the search criteria. If no such window can be found, a
150: * <code>null</code> reference is returned.
151: */
152: public static Window getWindow(ComponentChooser cc) {
153: return (getWindow(cc, 0));
154: }
155:
156: static {
157: Timeouts.initDefault("WindowWaiter.WaitWindowTimeout",
158: WAIT_TIME);
159: Timeouts.initDefault("WindowWaiter.AfterWindowTimeout",
160: AFTER_WAIT_TIME);
161: }
162:
163: /**
164: * Defines current timeouts.
165: * @param timeouts A collection of timeout assignments.
166: * @see org.netbeans.jemmy.Timeoutable
167: * @see org.netbeans.jemmy.Timeouts
168: * @see #getTimeouts
169: */
170: public void setTimeouts(Timeouts timeouts) {
171: this .timeouts = timeouts;
172: Timeouts times = timeouts.cloneThis();
173: times.setTimeout("Waiter.WaitingTime", timeouts
174: .getTimeout("WindowWaiter.WaitWindowTimeout"));
175: times.setTimeout("Waiter.AfterWaitingTime", timeouts
176: .getTimeout("WindowWaiter.AfterWindowTimeout"));
177: super .setTimeouts(times);
178: }
179:
180: /**
181: * Return current timeouts.
182: * @return the collection of current timeout assignments.
183: * @see org.netbeans.jemmy.Timeoutable
184: * @see org.netbeans.jemmy.Timeouts
185: * @see #setTimeouts
186: */
187: public Timeouts getTimeouts() {
188: return (timeouts);
189: }
190:
191: /**
192: * Action producer--get a window.
193: * Get a window. The search uses constraints on window ownership,
194: * ordinal index, and search criteria defined by an instance of
195: * <code>org.netbeans.jemmy.ComponentChooser</code>.
196: * @param obj Not used.
197: * @return the window waited upon. If a window cannot be found
198: * then a <code>null</code> reference is returned.
199: * @see org.netbeans.jemmy.Action
200: */
201: public Object actionProduced(Object obj) {
202: return (WindowWaiter.getWindow(owner, chooser, index));
203: }
204:
205: /**
206: * Waits for a window to show.
207: * Wait for the <code>index+1</code>'th window that meets the criteria
208: * defined and applied by the <code>ComonentChooser</code> parameter to
209: * show up.
210: *
211: * @param ch A component chooser used to define and apply the search criteria.
212: * @param index The ordinal index of the window in the set of currently displayed
213: * windows. The first index is 0.
214: * @return a reference to the <code>index+1</code>'th window that shows
215: * and that meets the search criteria. If fewer than
216: * <code>index+1</code> windows show up in the allotted time period then
217: * a <code>null</code> reference is returned.
218: * @throws TimeoutExpiredException
219: * @see #actionProduced(Object)
220: * @exception InterruptedException
221: */
222: public Window waitWindow(ComponentChooser ch, int index)
223: throws InterruptedException {
224: chooser = ch;
225: owner = null;
226: this .index = index;
227: return (waitWindow());
228: }
229:
230: /**
231: * Waits for a window to show.
232: * Wait for a window that meets the search criteria applied by the
233: * <code>ComponentChooser</code> parameter to show up.
234: *
235: * @param ch A component chooser used to define and apply the search criteria.
236: * @return a reference to the first window that shows and that
237: * meets the search criteria. If no such window can be found within the
238: * time period allotted, a <code>null</code> reference is returned.
239: * @throws TimeoutExpiredException
240: * @see #actionProduced(Object)
241: * @exception InterruptedException
242: */
243: public Window waitWindow(ComponentChooser ch)
244: throws InterruptedException {
245: return (waitWindow(ch, 0));
246: }
247:
248: /**
249: * Waits for a window to show.
250: * Wait for the <code>index+1</code>'th window to show that is both owned by the
251: * <code>java.awt.Window</code> <code>o</code> and that meets the
252: * criteria defined and applied by the <code>ComponentChooser</code> parameter.
253: *
254: * @param o The owner window of all the windows to be searched.
255: * @param ch A component chooser used to define and apply the search criteria.
256: * @param index The ordinal index of the window in the set of currently displayed
257: * windows with the proper window ownership and a suitable title. The first
258: * index is 0.
259: * @return a reference to the <code>index+1</code>'th window to show that
260: * has the proper window ownership, and that meets the search criteria.
261: * If there are fewer than <code>index+1</code> windows, a <code>null</code>
262: * reference is returned.
263: * @throws TimeoutExpiredException
264: * @see #actionProduced(Object)
265: * @exception InterruptedException
266: */
267: public Window waitWindow(Window o, ComponentChooser ch, int index)
268: throws InterruptedException {
269: owner = o;
270: chooser = ch;
271: this .index = index;
272: return ((Window) waitAction(null));
273: }
274:
275: /**
276: * Waits for a window to show.
277: * Wait for the first window to show that is both owned by the
278: * <code>java.awt.Window</code> <code>o</code> and that meets the
279: * criteria defined and applied by the <code>ComponentChooser</code> parameter.
280: *
281: * @param o The owner window of all the windows to be searched.
282: * @param ch A component chooser used to define and apply the search criteria.
283: * @return a reference to the first window to show that
284: * has the proper window ownership, and that meets the search criteria.
285: * If there is no such window, a <code>null</code> reference is returned.
286: * @throws TimeoutExpiredException
287: * @see #actionProduced(Object)
288: * @exception InterruptedException
289: */
290: public Window waitWindow(Window o, ComponentChooser ch)
291: throws InterruptedException {
292: return (waitWindow(o, ch, 0));
293: }
294:
295: public String getDescription() {
296: return (chooser.getDescription());
297: }
298:
299: /**
300: * Method can be used by a subclass to define chooser.
301: * @param ch a chooser specifying searching criteria.
302: * @see #getComponentChooser
303: */
304: protected void setComponentChooser(ComponentChooser ch) {
305: chooser = ch;
306: }
307:
308: /**
309: * Method can be used by a subclass to define chooser.
310: * @return a chooser specifying searching criteria.
311: * @see #setComponentChooser
312: */
313: protected ComponentChooser getComponentChooser() {
314: return (chooser);
315: }
316:
317: /**
318: * Method can be used by a subclass to define window owner.
319: * @param owner Window-owner of the set of windows.
320: * @see #getOwner
321: */
322: protected void setOwner(Window owner) {
323: this .owner = owner;
324: }
325:
326: /**
327: * Method can be used by a subclass to define window owner.
328: * @return Window-owner of the set of windows.
329: * @see #setOwner
330: */
331: protected Window getOwner() {
332: return (owner);
333: }
334:
335: /**
336: * @see org.netbeans.jemmy.Waiter#getWaitingStartedMessage()
337: */
338: protected String getWaitingStartedMessage() {
339: return ("Start to wait window \"" + chooser.getDescription() + "\" opened");
340: }
341:
342: /**
343: * Overrides Waiter.getTimeoutExpiredMessage.
344: * @see org.netbeans.jemmy.Waiter#getTimeoutExpiredMessage(long)
345: * @param timeSpent time from waiting start (milliseconds)
346: * @return a message.
347: */
348: protected String getTimeoutExpiredMessage(long timeSpent) {
349: return ("Window \"" + chooser.getDescription()
350: + "\" has not been opened in "
351: + (new Long(timeSpent)).toString() + " milliseconds");
352: }
353:
354: /**
355: * Overrides Waiter.getActionProducedMessage.
356: * @see org.netbeans.jemmy.Waiter#getActionProducedMessage(long, Object)
357: * @param timeSpent time from waiting start (milliseconds)
358: * @param result result of Waitable.actionproduced method.
359: * @return a message.
360: */
361: protected String getActionProducedMessage(long timeSpent,
362: final Object result) {
363: String resultToString;
364: if (result instanceof Component) {
365: // run toString in dispatch thread
366: resultToString = (String) new QueueTool()
367: .invokeSmoothly(new QueueTool.QueueAction(
368: "result.toString()") {
369: public Object launch() {
370: return result.toString();
371: }
372: });
373: } else {
374: resultToString = result.toString();
375: }
376: return ("Window \"" + chooser.getDescription()
377: + "\" has been opened in "
378: + (new Long(timeSpent)).toString() + " milliseconds"
379: + "\n " + resultToString);
380: }
381:
382: /**
383: * @return a message.
384: * @see org.netbeans.jemmy.Waiter#getGoldenWaitingStartedMessage()
385: */
386: protected String getGoldenWaitingStartedMessage() {
387: return ("Start to wait window \"" + chooser.getDescription() + "\" opened");
388: }
389:
390: /**
391: * @return a message.
392: * @see org.netbeans.jemmy.Waiter#getGoldenTimeoutExpiredMessage()
393: */
394: protected String getGoldenTimeoutExpiredMessage() {
395: return ("Window \"" + chooser.getDescription() + "\" has not been opened");
396: }
397:
398: /**
399: * @return a message.
400: * @see org.netbeans.jemmy.Waiter#getGoldenActionProducedMessage()
401: */
402: protected String getGoldenActionProducedMessage() {
403: return ("Window \"" + chooser.getDescription() + "\" has been opened");
404: }
405:
406: private static Window getAWindow(Window owner, ComponentChooser cc) {
407: if (owner == null) {
408: return (WindowWaiter.getAWindow(cc));
409: } else {
410: Window result = null;
411: Window[] windows = owner.getOwnedWindows();
412: for (int i = 0; i < windows.length; i++) {
413: if (cc.checkComponent(windows[i])) {
414: return (windows[i]);
415: }
416: if ((result = WindowWaiter.getWindow(windows[i], cc)) != null) {
417: return (result);
418: }
419: }
420: return (null);
421: }
422: }
423:
424: private static Window getAWindow(ComponentChooser cc) {
425: Window result = null;
426: Frame[] frames = Frame.getFrames();
427: for (int i = 0; i < frames.length; i++) {
428: if (cc.checkComponent(frames[i])) {
429: return (frames[i]);
430: }
431: if ((result = WindowWaiter.getWindow(frames[i], cc)) != null) {
432: return (result);
433: }
434: }
435: return (null);
436: }
437:
438: private Window waitWindow() throws InterruptedException {
439: return ((Window) waitAction(null));
440: }
441:
442: private Window waitWindow(Window o) throws InterruptedException {
443: owner = o;
444: return ((Window) waitAction(null));
445: }
446:
447: private static class IndexChooser implements ComponentChooser {
448: private int curIndex = 0;
449: private int index;
450: private ComponentChooser chooser;
451:
452: public IndexChooser(ComponentChooser ch, int i) {
453: index = i;
454: chooser = ch;
455: curIndex = 0;
456: }
457:
458: public boolean checkComponent(Component comp) {
459: if (comp.isShowing() && comp.isVisible()
460: && chooser.checkComponent(comp)) {
461: if (curIndex == index) {
462: return (true);
463: }
464: curIndex++;
465: }
466: return (false);
467: }
468:
469: public String getDescription() {
470: return (chooser.getDescription());
471: }
472: }
473: }
|