blob: 907d264e740a9cb05d9047de12fd4f14b0efe80c [file] [log] [blame]
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.util.Optional;
/**
*
* Runs actions with or without waiting.
*
* <BR><BR>Timeouts used: <BR>
* ActionProducer.MaxActionTime - time action should be finished in. <BR>
*
* @see Action
* @see Timeouts
*
* @author Alexandre Iline (alexandre.iline@oracle.com)
*/
public class ActionProducer<R, P> extends Thread
implements Action<R, P>, Waitable<Optional<R>, P>, Timeoutable {
private final static long ACTION_TIMEOUT = 10000;
private Action<R, P> action;
private boolean needWait = true;
private P parameter;
private boolean finished;
private R result = null;
private Timeouts timeouts;
private Waiter<Optional<R>, P> waiter;
private TestOut output;
private Throwable exception;
/**
* Creates a producer for an action.
*
* @param a Action implementation.
*/
public ActionProducer(Action<R, P> a) {
super();
waiter = new Waiter<>(this);
action = a;
setTimeouts(JemmyProperties.getProperties().getTimeouts());
setOutput(JemmyProperties.getProperties().getOutput());
finished = false;
exception = null;
}
/**
* Creates a producer for an action.
*
* @param a Action implementation.
* @param nw Defines if {@code produceAction} method should wait for
* the end of action.
*/
public ActionProducer(Action<R, P> a, boolean nw) {
super();
waiter = new Waiter<>(this);
action = a;
needWait = nw;
setTimeouts(JemmyProperties.getProperties().getTimeouts());
setOutput(JemmyProperties.getProperties().getOutput());
finished = false;
exception = null;
}
/**
* Creates a producer. {@code produceAction} must be overridden.
*/
protected ActionProducer() {
super();
waiter = new Waiter<>(this);
setTimeouts(JemmyProperties.getProperties().getTimeouts());
setOutput(JemmyProperties.getProperties().getOutput());
finished = false;
exception = null;
}
/**
* Creates a producer. {@code produceAction} must be overridden.
*
* @param nw Defines if {@code produceAction} method should wait for
* the end of action.
*/
protected ActionProducer(boolean nw) {
super();
waiter = new Waiter<>(this);
needWait = nw;
setTimeouts(JemmyProperties.getProperties().getTimeouts());
setOutput(JemmyProperties.getProperties().getOutput());
finished = false;
exception = null;
}
static {
Timeouts.initDefault("ActionProducer.MaxActionTime", ACTION_TIMEOUT);
}
/**
* Set all the time outs used by sleeps or waits used by the launched
* action.
*
* @param ts An object containing timeout information.
* @see org.netbeans.jemmy.Timeouts
* @see org.netbeans.jemmy.Timeoutable
* @see #getTimeouts
*/
@Override
public void setTimeouts(Timeouts ts) {
timeouts = ts;
}
/**
* Get all the time outs used by sleeps or waits used by the launched
* action.
*
* @return an object containing information about timeouts.
* @see org.netbeans.jemmy.Timeouts
* @see org.netbeans.jemmy.Timeoutable
* @see #setTimeouts
*/
@Override
public Timeouts getTimeouts() {
return timeouts;
}
/**
* Identity of the streams or writers used for print output.
*
* @param out An object containing print output assignments for output and
* error streams.
* @see org.netbeans.jemmy.TestOut
* @see org.netbeans.jemmy.Outputable
*/
public void setOutput(TestOut out) {
output = out;
waiter.setOutput(output);
}
/**
* Returns the exception value.
*
* @return a Throwable object representing the exception value
*/
public Throwable getException() {
return exception;
}
/**
* Defines action priority in terms of thread priority. Increase (decrease)
* parameter value to Thread.MIN_PRIORITY(MAX_PRIORITY) in case if it is
* less(more) then it.
*
* @param newPriority New thread priority.
*/
public void setActionPriority(int newPriority) {
int priority;
if (newPriority < Thread.MIN_PRIORITY) {
priority = MIN_PRIORITY;
} else if (newPriority > Thread.MAX_PRIORITY) {
priority = MAX_PRIORITY;
} else {
priority = newPriority;
}
try {
setPriority(priority);
} catch (IllegalArgumentException | SecurityException e) {
e.printStackTrace();
}
}
/**
* Get the result of a launched action.
*
* @return a launched action's result. without waiting in case if
* {@code getFinished()}
* @see #getFinished()
*/
public R getResult() {
return result;
}
/**
* Check if a launched action has finished.
*
* @return {@code true} if the launched action has completed, either
* normally or with an exception; {@code false} otherwise.
*/
public boolean getFinished() {
synchronized (this) {
return finished;
}
}
/**
* Does nothing; the method should be overridden by inheritors.
*
* @param obj An object used to modify execution. This might be a
* {@code java.lang.String[]} that lists a test's command line
* arguments.
* @return An object - result of the action.
* @see org.netbeans.jemmy.Action
*/
@Override
public R launch(P obj) {
return null;
}
/**
* @return this {@code ActionProducer}'s description.
* @see Action
*/
@Override
public String getDescription() {
if (action != null) {
return action.getDescription();
} else {
return "Unknown action";
}
}
/**
* Starts execution. Uses ActionProducer.MaxActionTime timeout.
*
* @param obj Parameter to be passed into action's
* {@code launch(Object)} method. This parameter might be a
* {@code java.lang.String[]} that lists a test's command line
* arguments.
* @param actionTimeOrigin is used for timeout reporting, if non-null.
* @return {@code launch(Object)} result.
* @throws TimeoutExpiredException
* @exception InterruptedException
*/
public R produceAction(P obj, String actionTimeOrigin) throws InterruptedException {
parameter = obj;
synchronized (this) {
finished = false;
}
start();
if (needWait) {
waiter.setTimeoutsToCloneOf(timeouts, "ActionProducer.MaxActionTime", actionTimeOrigin);
try {
waiter.waitAction(null);
} catch (TimeoutExpiredException e) {
output.printError("Timeout for \"" + getDescription()
+ "\" action has been expired. Thread has been interrupted.");
interrupt();
throw (e);
}
}
return result;
}
/**
* Launch an action in a separate thread of execution. When the action
* finishes, record that fact. If the action finishes normally, store it's
* result. Use {@code getFinished()} and {@code getResult} to
* answer questions about test completion and return value, respectively.
*
* @see #getFinished()
* @see #getResult()
* @see java.lang.Runnable
*/
@Override
public final void run() {
result = null;
try {
result = launchAction(parameter);
} catch (Throwable e) {
exception = e;
}
synchronized (this) {
finished = true;
}
}
/**
* Inquire for a reference to the object returned by a launched action.
*
* @param obj Not used.
* @return the result returned when a launched action finishes normally.
* @see org.netbeans.jemmy.Waitable
*/
@Override
public final Optional<R> actionProduced(P obj) {
synchronized (this) {
if (finished) {
return Optional.ofNullable(result);
} else {
return null;
}
}
}
/**
* Launch some action. Pass the action parameters and get it's return value,
* too.
*
* @param obj Parameter used to configure the execution of whatever this
* {@code ActionProducer} puts into execution.
* @return the return value of the action.
*/
private R launchAction(P obj) {
if (action != null) {
return action.launch(obj);
} else {
return launch(obj);
}
}
@Override
public String toString() {
return "ActionProducer{" + "action=" + action + ", needWait=" + needWait + ", parameter=" + parameter + ", finished=" + finished + ", result=" + result + ", exception=" + exception + '}';
}
}