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:
052: /**
053: *
054: * Contains methods to search and wait Frame.
055: * A FrameWaiter is a utility class used to look or wait for Frames.
056: * It contains methods to search for a Frame among the currently
057: * showing Frames as well as methods that wait for a Frame to show
058: * within an allotted time period.
059: *
060: * <BR><BR>Timeouts used: <BR>
061: * FrameWaiter.WaitFrameTimeout - time to wait frame displayed. <BR>
062: * FrameWaiter.AfterFrameTimeout - time to sleep after frame has been displayed. <BR>
063: *
064: * @see org.netbeans.jemmy.Timeouts
065: *
066: * @author Alexandre Iline (alexandre.iline@sun.com)
067: */
068:
069: public class FrameWaiter extends WindowWaiter implements Timeoutable,
070: Outputable {
071:
072: private final static long WAIT_TIME = 60000;
073: private final static long AFTER_WAIT_TIME = 0;
074:
075: private Timeouts timeouts;
076: private TestOut output;
077:
078: /**
079: * Constructor.
080: */
081: public FrameWaiter() {
082: super ();
083: setTimeouts(JemmyProperties.getProperties().getTimeouts());
084: setOutput(JemmyProperties.getProperties().getOutput());
085: }
086:
087: /**
088: * Searches for a Frame.
089: * Search among the currently showing Frames for one that meets the search
090: * criteria applied by the <code>ComponentChooser</code> parameter.
091: * @param cc A component chooser used to define and apply the search criteria.
092: * @return a reference to the first Frame that is showing and that
093: * meets the search criteria. If no such Frame can be found, a
094: * <code>null</code> reference is returned.
095: */
096: public static Frame getFrame(ComponentChooser cc) {
097: return ((Frame) WindowWaiter.getWindow(new FrameSubChooser(cc)));
098: }
099:
100: /**
101: * Searches for a Frame.
102: * The search proceeds among the currently showing Frames for the
103: * <code>index+1</code>'th Frame that meets the criteria defined and
104: * applied by the <code>ComonentChooser</code> parameter.
105: * @param cc A component chooser used to define and apply the search criteria.
106: * @param index The ordinal index of the Frame in the set of currently displayed
107: * Frames. The first index is 0.
108: * @return a reference to the <code>index+1</code>'th Frame that is showing
109: * and that meets the search criteria. If there are fewer than
110: * <code>index+1</code> Frames, a <code>null</code> reference is returned.
111: */
112: public static Frame getFrame(ComponentChooser cc, int index) {
113: return ((Frame) WindowWaiter.getWindow(new FrameSubChooser(cc),
114: index));
115: }
116:
117: /**
118: * Searches for a Frame by title.
119: * The search proceeds among the currently showing Frames for the first
120: * with a suitable title.
121: * @param title Frame title or subtitle.
122: * @param ce If <code>true</code> and the search is case sensitive, then a
123: * match occurs when the <code>title</code> argument is a substring of a
124: * Frame title. If <code>false</code> and the search is case sensitive,
125: * then the <code>title</code> argument and the Frame title must be the same.
126: * If <code>true</code> and the search is case insensitive, then a match occurs
127: * when the <code>title</code> argument is a substring of the Frame title after
128: * changing both to upper case. If <code>false</code> and the search is case
129: * insensitive, then a match occurs when the <code>title</code> argument is a
130: * substring of the Frame title after changing both to upper case.
131: * @param cc If <code>true</code> the search is case sensitive; otherwise, the
132: * search is case insensitive.
133: * @return a reference to the first Frame that is showing and that has a
134: * suitable title. If no such Frame can be found, a <code>null</code>
135: * reference is returned.
136: */
137: public static Frame getFrame(String title, boolean ce, boolean cc) {
138: return ((Frame) WindowWaiter.getWindow(new FrameByTitleChooser(
139: title, ce, cc)));
140: }
141:
142: /**
143: * Searches for a Frame by title.
144: * The search is for the <code>index+1</code>'th Frame among the currently
145: * showing Frames that possess a suitable title.
146: *
147: * @param title Frame title or subtitle.
148: * @param ce If <code>true</code> and the search is case sensitive, then a
149: * match occurs when the <code>title</code> argument is a substring of a
150: * Frame title. If <code>false</code> and the search is case sensitive,
151: * then the <code>title</code> argument and the Frame title must be the same.
152: * If <code>true</code> and the search is case insensitive, then a match occurs
153: * when the <code>title</code> argument is a substring of the Frame title after
154: * changing both to upper case. If <code>false</code> and the search is case
155: * insensitive, then a match occurs when the <code>title</code> argument is a
156: * substring of the Frame title after changing both to upper case.
157: * @param cc If <code>true</code> the search is case sensitive; otherwise, the
158: * search is case insensitive.
159: * @param index The ordinal index of the Frame in the set of currently displayed
160: * Frames. The first index is 0.
161: * @return a reference to the <code>index+1</code>'th Frame that is showing
162: * and that has a suitable title. If there are fewer than
163: * <code>index+1</code> Frames, a <code>null</code> reference is returned.
164: */
165: public static Frame getFrame(String title, boolean ce, boolean cc,
166: int index) {
167: return ((Frame) WindowWaiter.getWindow(new FrameByTitleChooser(
168: title, ce, cc), index));
169: }
170:
171: static {
172: Timeouts.initDefault("FrameWaiter.WaitFrameTimeout", WAIT_TIME);
173: Timeouts.initDefault("FrameWaiter.AfterFrameTimeout",
174: AFTER_WAIT_TIME);
175: }
176:
177: /**
178: * Defines current timeouts.
179: * @param timeouts A collection of timeout assignments.
180: * @see org.netbeans.jemmy.Timeoutable
181: * @see org.netbeans.jemmy.Timeouts
182: * @see #getTimeouts
183: */
184: public void setTimeouts(Timeouts timeouts) {
185: this .timeouts = timeouts;
186: Timeouts times = timeouts.cloneThis();
187: times.setTimeout("WindowWaiter.WaitWindowTimeout", timeouts
188: .getTimeout("FrameWaiter.WaitFrameTimeout"));
189: times.setTimeout("WindowWaiter.AfterWindowTimeout", timeouts
190: .getTimeout("FrameWaiter.AfterFrameTimeout"));
191: super .setTimeouts(times);
192: }
193:
194: /**
195: * Return current timeouts.
196: * @return the collection of current timeout assignments.
197: * @see org.netbeans.jemmy.Timeoutable
198: * @see org.netbeans.jemmy.Timeouts
199: * @see #setTimeouts
200: */
201: public Timeouts getTimeouts() {
202: return (timeouts);
203: }
204:
205: /**
206: * Defines print output streams or writers.
207: * @param output Identify the streams or writers used for print output.
208: * @see org.netbeans.jemmy.Outputable
209: * @see org.netbeans.jemmy.TestOut
210: * @see #getOutput
211: */
212: public void setOutput(TestOut output) {
213: this .output = output;
214: super .setOutput(output);
215: }
216:
217: /**
218: * Returns print output streams or writers.
219: * @return an object that contains references to objects for
220: * printing to output and err streams.
221: * @see org.netbeans.jemmy.Outputable
222: * @see org.netbeans.jemmy.TestOut
223: * @see #setOutput
224: */
225: public TestOut getOutput() {
226: return (output);
227: }
228:
229: /**
230: * Waits for a Frame to show.
231: * Wait for the <code>index+1</code>'th Frame that meets the criteria
232: * defined and applied by the <code>ComonentChooser</code> parameter to
233: * show up.
234: *
235: * @param ch A component chooser used to define and apply the search criteria.
236: * @param index The ordinal index of the Frame in the set of currently displayed
237: * Frames. The first index is 0.
238: * @return a reference to the <code>index+1</code>'th Frame that shows
239: * and that meets the search criteria. If fewer than
240: * <code>index+1</code> Frames show up in the allotted time period then
241: * a <code>null</code> reference is returned.
242: * @throws TimeoutExpiredException
243: * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object)
244: * @exception InterruptedException
245: */
246: public Frame waitFrame(ComponentChooser ch, int index)
247: throws InterruptedException {
248: setTimeouts(timeouts);
249: return ((Frame) waitWindow(new FrameSubChooser(ch), index));
250: }
251:
252: /**
253: * Waits for a Frame to show.
254: * Wait for a Frame that meets the search criteria applied by the
255: * <code>ComponentChooser</code> parameter to show up.
256: *
257: * @param ch A component chooser used to define and apply the search criteria.
258: * @return a reference to the first Frame that shows and that
259: * meets the search criteria. If no such Frame can be found within the
260: * time period allotted, a <code>null</code> reference is returned.
261: * @throws TimeoutExpiredException
262: * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object)
263: * @exception InterruptedException
264: */
265: public Frame waitFrame(ComponentChooser ch)
266: throws InterruptedException {
267: return (waitFrame(ch, 0));
268: }
269:
270: /**
271: * Waits for a Frame to show.
272: * Wait for the <code>index+1</code>'th Frame to show with a suitable title.
273: *
274: * @param title Frame title or subtitle.
275: * @param compareExactly If <code>true</code> and the search is case sensitive, then a
276: * match occurs when the <code>title</code> argument is a substring of a
277: * Frame title. If <code>false</code> and the search is case sensitive,
278: * then the <code>title</code> argument and the Frame title must be the same.
279: * If <code>true</code> and the search is case insensitive, then a match occurs
280: * when the <code>title</code> argument is a substring of the Frame title after
281: * changing both to upper case. If <code>false</code> and the search is case
282: * insensitive, then a match occurs when the <code>title</code> argument is a
283: * substring of the Frame title after changing both to upper case.
284: * @param compareCaseSensitive If <code>true</code> the search is case sensitive;
285: * otherwise, the search is case insensitive.
286: * @param index The ordinal index of the Frame in the set of currently displayed
287: * Frames with the proper window ownership and a suitable title. The
288: * first index is 0.
289: * @return a reference to the <code>index+1</code>'th Frame to show and that has a
290: * suitable title. If no such Frame can be found within the time period
291: * allotted, a <code>null</code> reference is returned.
292: * @throws TimeoutExpiredException
293: * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object)
294: * @exception InterruptedException
295: */
296: public Frame waitFrame(String title, boolean compareExactly,
297: boolean compareCaseSensitive, int index)
298: throws InterruptedException {
299: return (waitFrame(new FrameByTitleChooser(title,
300: compareExactly, compareCaseSensitive), index));
301: }
302:
303: /**
304: * Waits for a Frame to show.
305: * Wait for the first Frame to show with a suitable title.
306: *
307: * @param title Frame title or subtitle.
308: * @param compareExactly If <code>true</code> and the search is case sensitive, then a
309: * match occurs when the <code>title</code> argument is a substring of a
310: * Frame title. If <code>false</code> and the search is case sensitive,
311: * then the <code>title</code> argument and the Frame title must be the same.
312: * If <code>true</code> and the search is case insensitive, then a match occurs
313: * when the <code>title</code> argument is a substring of the Frame title after
314: * changing both to upper case. If <code>false</code> and the search is case
315: * insensitive, then a match occurs when the <code>title</code> argument is a
316: * substring of the Frame title after changing both to upper case.
317: * @param compareCaseSensitive If <code>true</code> the search is case sensitive;
318: * otherwise, the search is case insensitive.
319: * @return a reference to the first Frame to show and that has a
320: * suitable title. If no such Frame can be found within the time period
321: * allotted, a <code>null</code> reference is returned.
322: * @throws TimeoutExpiredException
323: * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object)
324: * @exception InterruptedException
325: */
326: public Frame waitFrame(String title, boolean compareExactly,
327: boolean compareCaseSensitive) throws InterruptedException {
328: return (waitFrame(title, compareExactly, compareCaseSensitive,
329: 0));
330: }
331:
332: /**
333: * @see Waiter#getWaitingStartedMessage()
334: */
335: protected String getWaitingStartedMessage() {
336: return ("Start to wait frame \""
337: + getComponentChooser().getDescription() + "\" opened");
338: }
339:
340: /**
341: * Overrides WindowWaiter.getTimeoutExpiredMessage.
342: * Returns the timeout expired message value.
343: * @param timeSpent Time spent for waiting
344: * @return a message tring
345: * @see Waiter#getTimeoutExpiredMessage(long)
346: */
347: protected String getTimeoutExpiredMessage(long timeSpent) {
348: return ("Frame \"" + getComponentChooser().getDescription()
349: + "\" has not been opened in "
350: + (new Long(timeSpent)).toString() + " milliseconds");
351: }
352:
353: /**
354: * Overrides WindowWaiter.getActionProducedMessage.
355: * Returns the action produced message value.
356: * @param timeSpent Time spent for waiting.
357: * @param result A message string.
358: * @return a message tring
359: * @see Waiter#getActionProducedMessage(long, Object)
360: */
361: protected String getActionProducedMessage(long timeSpent,
362: final Object result) {
363: String resultToString = null;
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 ("Frame \"" + getComponentChooser().getDescription()
377: + "\" has been opened in "
378: + (new Long(timeSpent)).toString() + " milliseconds"
379: + "\n " + resultToString);
380: }
381:
382: /**
383: * @see Waiter#getGoldenWaitingStartedMessage()
384: */
385: protected String getGoldenWaitingStartedMessage() {
386: return ("Start to wait frame \""
387: + getComponentChooser().getDescription() + "\" opened");
388: }
389:
390: /**
391: * @see Waiter#getGoldenTimeoutExpiredMessage()
392: */
393: protected String getGoldenTimeoutExpiredMessage() {
394: return ("Frame \"" + getComponentChooser().getDescription() + "\" has not been opened");
395: }
396:
397: /**
398: * @see Waiter#getGoldenActionProducedMessage()
399: */
400: protected String getGoldenActionProducedMessage() {
401: return ("Frame \"" + getComponentChooser().getDescription() + "\" has been opened");
402: }
403:
404: private static class FrameSubChooser implements ComponentChooser {
405: private ComponentChooser chooser;
406:
407: public FrameSubChooser(ComponentChooser c) {
408: super ();
409: chooser = c;
410: }
411:
412: public boolean checkComponent(Component comp) {
413: if (comp instanceof Frame) {
414: return (comp.isShowing() && comp.isVisible() && chooser
415: .checkComponent(comp));
416: } else {
417: return (false);
418: }
419: }
420:
421: public String getDescription() {
422: return (chooser.getDescription());
423: }
424: }
425:
426: private static class FrameByTitleChooser implements
427: ComponentChooser {
428: String title;
429: boolean compareExactly;
430: boolean compareCaseSensitive;
431:
432: public FrameByTitleChooser(String t, boolean ce, boolean cc) {
433: super ();
434: title = t;
435: compareExactly = ce;
436: compareCaseSensitive = cc;
437: }
438:
439: public boolean checkComponent(Component comp) {
440: if (comp instanceof Frame) {
441: if (((Frame) comp).isShowing() && comp.isVisible()
442: && ((Frame) comp).getTitle() != null) {
443: String titleToComp = ((Frame) comp).getTitle();
444: String contextToComp = title;
445: if (compareCaseSensitive) {
446: titleToComp = titleToComp.toUpperCase();
447: contextToComp = contextToComp.toUpperCase();
448: }
449: if (compareExactly) {
450: return (titleToComp.equals(contextToComp));
451: } else {
452: return (titleToComp.indexOf(contextToComp) != -1);
453: }
454: }
455: }
456: return (false);
457: }
458:
459: public String getDescription() {
460: return (title);
461: }
462: }
463:
464: }
|