/* * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package org.netbeans.jemmy; import java.awt.Component; import java.awt.Frame; /** * * Contains methods to search and wait Frame. A FrameWaiter is a utility class * used to look or wait for Frames. It contains methods to search for a Frame * among the currently showing Frames as well as methods that wait for a Frame * to show within an allotted time period. * * <BR><BR>Timeouts used: <BR> * FrameWaiter.WaitFrameTimeout - time to wait frame displayed. <BR> * FrameWaiter.AfterFrameTimeout - time to sleep after frame has been displayed. * <BR> * * @see org.netbeans.jemmy.Timeouts * * @author Alexandre Iline (alexandre.iline@oracle.com) */ public class FrameWaiter extends WindowWaiter implements Timeoutable, Outputable { private final static long WAIT_TIME = 60000; private final static long AFTER_WAIT_TIME = 0; private Timeouts timeouts; private TestOut output; /** * Constructor. */ public FrameWaiter() { super(); setTimeouts(JemmyProperties.getProperties().getTimeouts()); setOutput(JemmyProperties.getProperties().getOutput()); } /** * Searches for a Frame. Search among the currently showing Frames for one * that meets the search criteria applied by the * {@code ComponentChooser} parameter. * * @param cc A component chooser used to define and apply the search * criteria. * @return a reference to the first Frame that is showing and that meets the * search criteria. If no such Frame can be found, a {@code null} * reference is returned. */ public static Frame getFrame(ComponentChooser cc) { return (Frame) WindowWaiter.getWindow(new FrameSubChooser(cc)); } /** * Searches for a Frame. The search proceeds among the currently showing * Frames for the {@code index+1}'th Frame that meets the criteria * defined and applied by the {@code ComonentChooser} parameter. * * @param cc A component chooser used to define and apply the search * criteria. * @param index The ordinal index of the Frame in the set of currently * displayed Frames. The first index is 0. * @return a reference to the {@code index+1}'th Frame that is showing * and that meets the search criteria. If there are fewer than * {@code index+1} Frames, a {@code null} reference is returned. */ public static Frame getFrame(ComponentChooser cc, int index) { return (Frame) WindowWaiter.getWindow(new FrameSubChooser(cc), index); } /** * Searches for a Frame by title. The search proceeds among the currently * showing Frames for the first with a suitable title. * * @param title Frame title or subtitle. * @param ce If {@code true} and the search is case sensitive, then a * match occurs when the {@code title} argument is a substring of a * Frame title. If {@code false} and the search is case sensitive, then * the {@code title} argument and the Frame title must be the same. If * {@code true} and the search is case insensitive, then a match occurs * when the {@code title} argument is a substring of the Frame title * after changing both to upper case. If {@code false} and the search * is case insensitive, then a match occurs when the {@code title} * argument is a substring of the Frame title after changing both to upper * case. * @param cc If {@code true} the search is case sensitive; otherwise, * the search is case insensitive. * @return a reference to the first Frame that is showing and that has a * suitable title. If no such Frame can be found, a {@code null} * reference is returned. */ public static Frame getFrame(String title, boolean ce, boolean cc) { return (Frame) WindowWaiter.getWindow(new FrameByTitleChooser(title, ce, cc)); } /** * Searches for a Frame by title. The search is for the * {@code index+1}'th Frame among the currently showing Frames that * possess a suitable title. * * @param title Frame title or subtitle. * @param ce If {@code true} and the search is case sensitive, then a * match occurs when the {@code title} argument is a substring of a * Frame title. If {@code false} and the search is case sensitive, then * the {@code title} argument and the Frame title must be the same. If * {@code true} and the search is case insensitive, then a match occurs * when the {@code title} argument is a substring of the Frame title * after changing both to upper case. If {@code false} and the search * is case insensitive, then a match occurs when the {@code title} * argument is a substring of the Frame title after changing both to upper * case. * @param cc If {@code true} the search is case sensitive; otherwise, * the search is case insensitive. * @param index The ordinal index of the Frame in the set of currently * displayed Frames. The first index is 0. * @return a reference to the {@code index+1}'th Frame that is showing * and that has a suitable title. If there are fewer than * {@code index+1} Frames, a {@code null} reference is returned. */ public static Frame getFrame(String title, boolean ce, boolean cc, int index) { return (Frame) WindowWaiter.getWindow(new FrameByTitleChooser(title, ce, cc), index); } static { Timeouts.initDefault("FrameWaiter.WaitFrameTimeout", WAIT_TIME); Timeouts.initDefault("FrameWaiter.AfterFrameTimeout", AFTER_WAIT_TIME); } /** * Defines current timeouts. * * @param timeouts A collection of timeout assignments. * @see org.netbeans.jemmy.Timeoutable * @see org.netbeans.jemmy.Timeouts * @see #getTimeouts */ @Override public void setTimeouts(Timeouts timeouts) { this.timeouts = timeouts; Timeouts times = timeouts.cloneThis(); times.setTimeout("WindowWaiter.WaitWindowTimeout", timeouts.getTimeout("FrameWaiter.WaitFrameTimeout")); times.setTimeout("WindowWaiter.AfterWindowTimeout", timeouts.getTimeout("FrameWaiter.AfterFrameTimeout")); super.setTimeouts(times); } /** * Return current timeouts. * * @return the collection of current timeout assignments. * @see org.netbeans.jemmy.Timeoutable * @see org.netbeans.jemmy.Timeouts * @see #setTimeouts */ @Override public Timeouts getTimeouts() { return timeouts; } /** * Defines print output streams or writers. * * @param output Identify the streams or writers used for print output. * @see org.netbeans.jemmy.Outputable * @see org.netbeans.jemmy.TestOut * @see #getOutput */ @Override public void setOutput(TestOut output) { this.output = output; super.setOutput(output); } /** * Returns print output streams or writers. * * @return an object that contains references to objects for printing to * output and err streams. * @see org.netbeans.jemmy.Outputable * @see org.netbeans.jemmy.TestOut * @see #setOutput */ @Override public TestOut getOutput() { return output; } /** * Waits for a Frame to show. Wait for the {@code index+1}'th Frame * that meets the criteria defined and applied by the * {@code ComonentChooser} parameter to show up. * * @param ch A component chooser used to define and apply the search * criteria. * @param index The ordinal index of the Frame in the set of currently * displayed Frames. The first index is 0. * @return a reference to the {@code index+1}'th Frame that shows and * that meets the search criteria. If fewer than {@code index+1} Frames * show up in the allotted time period then a {@code null} reference is * returned. * @throws TimeoutExpiredException * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object) * @exception InterruptedException */ public Frame waitFrame(ComponentChooser ch, int index) throws InterruptedException { setTimeouts(timeouts); return (Frame) waitWindow(new FrameSubChooser(ch), index); } /** * Waits for a Frame to show. Wait for a Frame that meets the search * criteria applied by the {@code ComponentChooser} parameter to show * up. * * @param ch A component chooser used to define and apply the search * criteria. * @return a reference to the first Frame that shows and that meets the * search criteria. If no such Frame can be found within the time period * allotted, a {@code null} reference is returned. * @throws TimeoutExpiredException * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object) * @exception InterruptedException */ public Frame waitFrame(ComponentChooser ch) throws InterruptedException { return waitFrame(ch, 0); } /** * Waits for a Frame to show. Wait for the {@code index+1}'th Frame to * show with a suitable title. * * @param title Frame title or subtitle. * @param compareExactly If {@code true} and the search is case * sensitive, then a match occurs when the {@code title} argument is a * substring of a Frame title. If {@code false} and the search is case * sensitive, then the {@code title} argument and the Frame title must * be the same. If {@code true} and the search is case insensitive, * then a match occurs when the {@code title} argument is a substring * of the Frame title after changing both to upper case. If * {@code false} and the search is case insensitive, then a match * occurs when the {@code title} argument is a substring of the Frame * title after changing both to upper case. * @param compareCaseSensitive If {@code true} the search is case * sensitive; otherwise, the search is case insensitive. * @param index The ordinal index of the Frame in the set of currently * displayed Frames with the proper window ownership and a suitable title. * The first index is 0. * @return a reference to the {@code index+1}'th Frame to show and that * has a suitable title. If no such Frame can be found within the time * period allotted, a {@code null} reference is returned. * @throws TimeoutExpiredException * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object) * @exception InterruptedException */ public Frame waitFrame(String title, boolean compareExactly, boolean compareCaseSensitive, int index) throws InterruptedException { return waitFrame(new FrameByTitleChooser(title, compareExactly, compareCaseSensitive), index); } /** * Waits for a Frame to show. Wait for the first Frame to show with a * suitable title. * * @param title Frame title or subtitle. * @param compareExactly If {@code true} and the search is case * sensitive, then a match occurs when the {@code title} argument is a * substring of a Frame title. If {@code false} and the search is case * sensitive, then the {@code title} argument and the Frame title must * be the same. If {@code true} and the search is case insensitive, * then a match occurs when the {@code title} argument is a substring * of the Frame title after changing both to upper case. If * {@code false} and the search is case insensitive, then a match * occurs when the {@code title} argument is a substring of the Frame * title after changing both to upper case. * @param compareCaseSensitive If {@code true} the search is case * sensitive; otherwise, the search is case insensitive. * @return a reference to the first Frame to show and that has a suitable * title. If no such Frame can be found within the time period allotted, a * {@code null} reference is returned. * @throws TimeoutExpiredException * @see org.netbeans.jemmy.WindowWaiter#actionProduced(Object) * @exception InterruptedException */ public Frame waitFrame(String title, boolean compareExactly, boolean compareCaseSensitive) throws InterruptedException { return waitFrame(title, compareExactly, compareCaseSensitive, 0); } /** * @see Waiter#getWaitingStartedMessage() */ @Override protected String getWaitingStartedMessage() { return "Start to wait frame \"" + getComponentChooser().getDescription() + "\" opened"; } /** * Overrides WindowWaiter.getTimeoutExpiredMessage. Returns the timeout * expired message value. * * @param timeSpent Time spent for waiting * @return a message tring * @see Waiter#getTimeoutExpiredMessage(long) */ @Override protected String getTimeoutExpiredMessage(long timeSpent) { return ("Frame \"" + getComponentChooser().getDescription() + "\" has not been opened in " + timeSpent + " milliseconds"); } /** * Overrides WindowWaiter.getActionProducedMessage. Returns the action * produced message value. * * @param timeSpent Time spent for waiting. * @param result A message string. * @return a message tring * @see Waiter#getActionProducedMessage(long, Object) */ @Override protected String getActionProducedMessage(long timeSpent, final Object result) { String resultToString = null; if (result instanceof Component) { // run toString in dispatch thread resultToString = new QueueTool().invokeSmoothly( new QueueTool.QueueAction<String>("result.toString()") { @Override public String launch() { return result.toString(); } } ); } else { resultToString = result.toString(); } return ("Frame \"" + getComponentChooser().getDescription() + "\" has been opened in " + timeSpent + " milliseconds" + "\n " + resultToString); } /** * @see Waiter#getGoldenWaitingStartedMessage() */ @Override protected String getGoldenWaitingStartedMessage() { return "Start to wait frame \"" + getComponentChooser().getDescription() + "\" opened"; } /** * @see Waiter#getGoldenTimeoutExpiredMessage() */ @Override protected String getGoldenTimeoutExpiredMessage() { return "Frame \"" + getComponentChooser().getDescription() + "\" has not been opened"; } /** * @see Waiter#getGoldenActionProducedMessage() */ @Override protected String getGoldenActionProducedMessage() { return "Frame \"" + getComponentChooser().getDescription() + "\" has been opened"; } private static class FrameSubChooser implements ComponentChooser { private ComponentChooser chooser; public FrameSubChooser(ComponentChooser c) { super(); chooser = c; } @Override public boolean checkComponent(Component comp) { if (comp instanceof Frame) { return ((FIND_INVISIBLE_WINDOWS || (comp.isShowing() && comp.isVisible())) && chooser.checkComponent(comp)); } else { return false; } } @Override public String getDescription() { return chooser.getDescription(); } @Override public String toString() { return "FrameSubChooser{" + "chooser=" + chooser + '}'; } } private static class FrameByTitleChooser implements ComponentChooser { String title; boolean compareExactly; boolean compareCaseSensitive; public FrameByTitleChooser(String t, boolean ce, boolean cc) { super(); title = t; compareExactly = ce; compareCaseSensitive = cc; } @Override public boolean checkComponent(Component comp) { if (comp instanceof Frame) { if ((FIND_INVISIBLE_WINDOWS || (comp.isShowing() && comp.isVisible())) && ((Frame) comp).getTitle() != null) { String titleToComp = ((Frame) comp).getTitle(); String contextToComp = title; if (compareCaseSensitive) { titleToComp = titleToComp.toUpperCase(); contextToComp = contextToComp.toUpperCase(); } if (compareExactly) { return titleToComp.equals(contextToComp); } else { return titleToComp.contains(contextToComp); } } } return false; } @Override public String getDescription() { return title; } @Override public String toString() { return "FrameByTitleChooser{" + "title=" + title + ", compareExactly=" + compareExactly + ", compareCaseSensitive=" + compareCaseSensitive + '}'; } } }