FrameWaiter.java revision 13978:1993af50385d
1/* 2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23package org.netbeans.jemmy; 24 25import java.awt.Component; 26import java.awt.Frame; 27 28/** 29 * 30 * Contains methods to search and wait Frame. A FrameWaiter is a utility class 31 * used to look or wait for Frames. It contains methods to search for a Frame 32 * among the currently showing Frames as well as methods that wait for a Frame 33 * to show within an allotted time period. 34 * 35 * <BR><BR>Timeouts used: <BR> 36 * FrameWaiter.WaitFrameTimeout - time to wait frame displayed. <BR> 37 * FrameWaiter.AfterFrameTimeout - time to sleep after frame has been displayed. 38 * <BR> 39 * 40 * @see org.netbeans.jemmy.Timeouts 41 * 42 * @author Alexandre Iline (alexandre.iline@oracle.com) 43 */ 44public class FrameWaiter extends WindowWaiter implements Timeoutable, Outputable { 45 46 private final static long WAIT_TIME = 60000; 47 private final static long AFTER_WAIT_TIME = 0; 48 49 private Timeouts timeouts; 50 private TestOut output; 51 52 /** 53 * Constructor. 54 */ 55 public FrameWaiter() { 56 super(); 57 setTimeouts(JemmyProperties.getProperties().getTimeouts()); 58 setOutput(JemmyProperties.getProperties().getOutput()); 59 } 60 61 /** 62 * Searches for a Frame. Search among the currently showing Frames for one 63 * that meets the search criteria applied by the 64 * {@code ComponentChooser} parameter. 65 * 66 * @param cc A component chooser used to define and apply the search 67 * criteria. 68 * @return a reference to the first Frame that is showing and that meets the 69 * search criteria. If no such Frame can be found, a {@code null} 70 * reference is returned. 71 */ 72 public static Frame getFrame(ComponentChooser cc) { 73 return (Frame) WindowWaiter.getWindow(new FrameSubChooser(cc)); 74 } 75 76 /** 77 * Searches for a Frame. The search proceeds among the currently showing 78 * Frames for the {@code index+1}'th Frame that meets the criteria 79 * defined and applied by the {@code ComonentChooser} parameter. 80 * 81 * @param cc A component chooser used to define and apply the search 82 * criteria. 83 * @param index The ordinal index of the Frame in the set of currently 84 * displayed Frames. The first index is 0. 85 * @return a reference to the {@code index+1}'th Frame that is showing 86 * and that meets the search criteria. If there are fewer than 87 * {@code index+1} Frames, a {@code null} reference is returned. 88 */ 89 public static Frame getFrame(ComponentChooser cc, int index) { 90 return (Frame) WindowWaiter.getWindow(new FrameSubChooser(cc), index); 91 } 92 93 /** 94 * Searches for a Frame by title. The search proceeds among the currently 95 * showing Frames for the first with a suitable title. 96 * 97 * @param title Frame title or subtitle. 98 * @param ce If {@code true} and the search is case sensitive, then a 99 * match occurs when the {@code title} argument is a substring of a 100 * Frame title. If {@code false} and the search is case sensitive, then 101 * the {@code title} argument and the Frame title must be the same. If 102 * {@code true} and the search is case insensitive, then a match occurs 103 * when the {@code title} argument is a substring of the Frame title 104 * after changing both to upper case. If {@code false} and the search 105 * is case insensitive, then a match occurs when the {@code title} 106 * argument is a substring of the Frame title after changing both to upper 107 * case. 108 * @param cc If {@code true} the search is case sensitive; otherwise, 109 * the search is case insensitive. 110 * @return a reference to the first Frame that is showing and that has a 111 * suitable title. If no such Frame can be found, a {@code null} 112 * reference is returned. 113 */ 114 public static Frame getFrame(String title, boolean ce, boolean cc) { 115 return (Frame) WindowWaiter.getWindow(new FrameByTitleChooser(title, ce, cc)); 116 } 117 118 /** 119 * Searches for a Frame by title. The search is for the 120 * {@code index+1}'th Frame among the currently showing Frames that 121 * possess a suitable title. 122 * 123 * @param title Frame title or subtitle. 124 * @param ce If {@code true} and the search is case sensitive, then a 125 * match occurs when the {@code title} argument is a substring of a 126 * Frame title. If {@code false} and the search is case sensitive, then 127 * the {@code title} argument and the Frame title must be the same. If 128 * {@code true} and the search is case insensitive, then a match occurs 129 * when the {@code title} argument is a substring of the Frame title 130 * after changing both to upper case. If {@code false} and the search 131 * is case insensitive, then a match occurs when the {@code title} 132 * argument is a substring of the Frame title after changing both to upper 133 * case. 134 * @param cc If {@code true} the search is case sensitive; otherwise, 135 * the search is case insensitive. 136 * @param index The ordinal index of the Frame in the set of currently 137 * displayed Frames. The first index is 0. 138 * @return a reference to the {@code index+1}'th Frame that is showing 139 * and that has a suitable title. If there are fewer than 140 * {@code index+1} Frames, a {@code null} reference is returned. 141 */ 142 public static Frame getFrame(String title, boolean ce, boolean cc, int index) { 143 return (Frame) WindowWaiter.getWindow(new FrameByTitleChooser(title, ce, cc), index); 144 } 145 146 static { 147 Timeouts.initDefault("FrameWaiter.WaitFrameTimeout", WAIT_TIME); 148 Timeouts.initDefault("FrameWaiter.AfterFrameTimeout", AFTER_WAIT_TIME); 149 } 150 151 /** 152 * Defines current timeouts. 153 * 154 * @param timeouts A collection of timeout assignments. 155 * @see org.netbeans.jemmy.Timeoutable 156 * @see org.netbeans.jemmy.Timeouts 157 * @see #getTimeouts 158 */ 159 @Override 160 public void setTimeouts(Timeouts timeouts) { 161 this.timeouts = timeouts; 162 Timeouts times = timeouts.cloneThis(); 163 times.setTimeout("WindowWaiter.WaitWindowTimeout", 164 timeouts.getTimeout("FrameWaiter.WaitFrameTimeout")); 165 times.setTimeout("WindowWaiter.AfterWindowTimeout", 166 timeouts.getTimeout("FrameWaiter.AfterFrameTimeout")); 167 super.setTimeouts(times); 168 } 169 170 /** 171 * Return current timeouts. 172 * 173 * @return the collection of current timeout assignments. 174 * @see org.netbeans.jemmy.Timeoutable 175 * @see org.netbeans.jemmy.Timeouts 176 * @see #setTimeouts 177 */ 178 @Override 179 public Timeouts getTimeouts() { 180 return timeouts; 181 } 182 183 /** 184 * Defines print output streams or writers. 185 * 186 * @param output Identify the streams or writers used for print output. 187 * @see org.netbeans.jemmy.Outputable 188 * @see org.netbeans.jemmy.TestOut 189 * @see #getOutput 190 */ 191 @Override 192 public void setOutput(TestOut output) { 193 this.output = output; 194 super.setOutput(output); 195 } 196 197 /** 198 * Returns print output streams or writers. 199 * 200 * @return an object that contains references to objects for printing to 201 * output and err streams. 202 * @see org.netbeans.jemmy.Outputable 203 * @see org.netbeans.jemmy.TestOut 204 * @see #setOutput 205 */ 206 @Override 207 public TestOut getOutput() { 208 return output; 209 } 210 211 /** 212 * Waits for a Frame to show. Wait for the {@code index+1}'th Frame 213 * that meets the criteria defined and applied by the 214 * {@code ComonentChooser} parameter to show up. 215 * 216 * @param ch A component chooser used to define and apply the search 217 * criteria. 218 * @param index The ordinal index of the Frame in the set of currently 219 * displayed Frames. The first index is 0. 220 * @return a reference to the {@code index+1}'th Frame that shows and 221 * that meets the search criteria. If fewer than {@code index+1} Frames 222 * show up in the allotted time period then a {@code null} reference is 223 * returned. 224 * @throws TimeoutExpiredException 225 * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object) 226 * @exception InterruptedException 227 */ 228 public Frame waitFrame(ComponentChooser ch, int index) 229 throws InterruptedException { 230 setTimeouts(timeouts); 231 return (Frame) waitWindow(new FrameSubChooser(ch), index); 232 } 233 234 /** 235 * Waits for a Frame to show. Wait for a Frame that meets the search 236 * criteria applied by the {@code ComponentChooser} parameter to show 237 * up. 238 * 239 * @param ch A component chooser used to define and apply the search 240 * criteria. 241 * @return a reference to the first Frame that shows and that meets the 242 * search criteria. If no such Frame can be found within the time period 243 * allotted, a {@code null} reference is returned. 244 * @throws TimeoutExpiredException 245 * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object) 246 * @exception InterruptedException 247 */ 248 public Frame waitFrame(ComponentChooser ch) 249 throws InterruptedException { 250 return waitFrame(ch, 0); 251 } 252 253 /** 254 * Waits for a Frame to show. Wait for the {@code index+1}'th Frame to 255 * show with a suitable title. 256 * 257 * @param title Frame title or subtitle. 258 * @param compareExactly If {@code true} and the search is case 259 * sensitive, then a match occurs when the {@code title} argument is a 260 * substring of a Frame title. If {@code false} and the search is case 261 * sensitive, then the {@code title} argument and the Frame title must 262 * be the same. If {@code true} and the search is case insensitive, 263 * then a match occurs when the {@code title} argument is a substring 264 * of the Frame title after changing both to upper case. If 265 * {@code false} and the search is case insensitive, then a match 266 * occurs when the {@code title} argument is a substring of the Frame 267 * title after changing both to upper case. 268 * @param compareCaseSensitive If {@code true} the search is case 269 * sensitive; otherwise, the search is case insensitive. 270 * @param index The ordinal index of the Frame in the set of currently 271 * displayed Frames with the proper window ownership and a suitable title. 272 * The first index is 0. 273 * @return a reference to the {@code index+1}'th Frame to show and that 274 * has a suitable title. If no such Frame can be found within the time 275 * period allotted, a {@code null} reference is returned. 276 * @throws TimeoutExpiredException 277 * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object) 278 * @exception InterruptedException 279 */ 280 public Frame waitFrame(String title, boolean compareExactly, boolean compareCaseSensitive, int index) 281 throws InterruptedException { 282 return waitFrame(new FrameByTitleChooser(title, compareExactly, compareCaseSensitive), index); 283 } 284 285 /** 286 * Waits for a Frame to show. Wait for the first Frame to show with a 287 * suitable title. 288 * 289 * @param title Frame title or subtitle. 290 * @param compareExactly If {@code true} and the search is case 291 * sensitive, then a match occurs when the {@code title} argument is a 292 * substring of a Frame title. If {@code false} and the search is case 293 * sensitive, then the {@code title} argument and the Frame title must 294 * be the same. If {@code true} and the search is case insensitive, 295 * then a match occurs when the {@code title} argument is a substring 296 * of the Frame title after changing both to upper case. If 297 * {@code false} and the search is case insensitive, then a match 298 * occurs when the {@code title} argument is a substring of the Frame 299 * title after changing both to upper case. 300 * @param compareCaseSensitive If {@code true} the search is case 301 * sensitive; otherwise, the search is case insensitive. 302 * @return a reference to the first Frame to show and that has a suitable 303 * title. If no such Frame can be found within the time period allotted, a 304 * {@code null} reference is returned. 305 * @throws TimeoutExpiredException 306 * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object) 307 * @exception InterruptedException 308 */ 309 public Frame waitFrame(String title, boolean compareExactly, boolean compareCaseSensitive) 310 throws InterruptedException { 311 return waitFrame(title, compareExactly, compareCaseSensitive, 0); 312 } 313 314 /** 315 * @see Waiter#getWaitingStartedMessage() 316 */ 317 @Override 318 protected String getWaitingStartedMessage() { 319 return "Start to wait frame \"" + getComponentChooser().getDescription() + "\" opened"; 320 } 321 322 /** 323 * Overrides WindowWaiter.getTimeoutExpiredMessage. Returns the timeout 324 * expired message value. 325 * 326 * @param timeSpent Time spent for waiting 327 * @return a message tring 328 * @see Waiter#getTimeoutExpiredMessage(long) 329 */ 330 @Override 331 protected String getTimeoutExpiredMessage(long timeSpent) { 332 return ("Frame \"" + getComponentChooser().getDescription() + "\" has not been opened in " 333 + timeSpent + " milliseconds"); 334 } 335 336 /** 337 * Overrides WindowWaiter.getActionProducedMessage. Returns the action 338 * produced message value. 339 * 340 * @param timeSpent Time spent for waiting. 341 * @param result A message string. 342 * @return a message tring 343 * @see Waiter#getActionProducedMessage(long, Object) 344 */ 345 @Override 346 protected String getActionProducedMessage(long timeSpent, final Object result) { 347 String resultToString = null; 348 if (result instanceof Component) { 349 // run toString in dispatch thread 350 resultToString = new QueueTool().invokeSmoothly( 351 new QueueTool.QueueAction<String>("result.toString()") { 352 @Override 353 public String launch() { 354 return result.toString(); 355 } 356 } 357 ); 358 } else { 359 resultToString = result.toString(); 360 } 361 return ("Frame \"" + getComponentChooser().getDescription() + "\" has been opened in " 362 + timeSpent + " milliseconds" 363 + "\n " + resultToString); 364 } 365 366 /** 367 * @see Waiter#getGoldenWaitingStartedMessage() 368 */ 369 @Override 370 protected String getGoldenWaitingStartedMessage() { 371 return "Start to wait frame \"" + getComponentChooser().getDescription() + "\" opened"; 372 } 373 374 /** 375 * @see Waiter#getGoldenTimeoutExpiredMessage() 376 */ 377 @Override 378 protected String getGoldenTimeoutExpiredMessage() { 379 return "Frame \"" + getComponentChooser().getDescription() + "\" has not been opened"; 380 } 381 382 /** 383 * @see Waiter#getGoldenActionProducedMessage() 384 */ 385 @Override 386 protected String getGoldenActionProducedMessage() { 387 return "Frame \"" + getComponentChooser().getDescription() + "\" has been opened"; 388 } 389 390 private static class FrameSubChooser implements ComponentChooser { 391 392 private ComponentChooser chooser; 393 394 public FrameSubChooser(ComponentChooser c) { 395 super(); 396 chooser = c; 397 } 398 399 @Override 400 public boolean checkComponent(Component comp) { 401 if (comp instanceof Frame) { 402 return ((FIND_INVISIBLE_WINDOWS || (comp.isShowing() && comp.isVisible())) 403 && chooser.checkComponent(comp)); 404 } else { 405 return false; 406 } 407 } 408 409 @Override 410 public String getDescription() { 411 return chooser.getDescription(); 412 } 413 414 @Override 415 public String toString() { 416 return "FrameSubChooser{" + "chooser=" + chooser + '}'; 417 } 418 } 419 420 private static class FrameByTitleChooser implements ComponentChooser { 421 422 String title; 423 boolean compareExactly; 424 boolean compareCaseSensitive; 425 426 public FrameByTitleChooser(String t, boolean ce, boolean cc) { 427 super(); 428 title = t; 429 compareExactly = ce; 430 compareCaseSensitive = cc; 431 } 432 433 @Override 434 public boolean checkComponent(Component comp) { 435 if (comp instanceof Frame) { 436 if ((FIND_INVISIBLE_WINDOWS || (comp.isShowing() && comp.isVisible())) 437 && ((Frame) comp).getTitle() != null) { 438 String titleToComp = ((Frame) comp).getTitle(); 439 String contextToComp = title; 440 if (compareCaseSensitive) { 441 titleToComp = titleToComp.toUpperCase(); 442 contextToComp = contextToComp.toUpperCase(); 443 } 444 if (compareExactly) { 445 return titleToComp.equals(contextToComp); 446 } else { 447 return titleToComp.contains(contextToComp); 448 } 449 } 450 } 451 return false; 452 } 453 454 @Override 455 public String getDescription() { 456 return title; 457 } 458 459 @Override 460 public String toString() { 461 return "FrameByTitleChooser{" + "title=" + title + ", compareExactly=" + compareExactly + ", compareCaseSensitive=" + compareCaseSensitive + '}'; 462 } 463 } 464 465} 466