/******************************************************************************* * Copyright (c) 2016 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.browsersim.wait; /** * Common ancestor for waiting classes. Contains abstract * {@link #stopWaiting(WaitCondition)} method that is called in the constructor. * * @author Vlado Pakan * @author Lucia Jelinkova * */ public abstract class AbstractWait { private TimePeriod timeout; private boolean throwTimeoutException = true; /** * Waits till condition is met for default time period. Throws * WaitTimeoutExpiredException after waiting for specified time period * and wait condition is not met. * * @param condition wait condition to met */ public AbstractWait(WaitCondition condition) { this(condition, TimePeriod.NORMAL); } /** * Waits till condition is met for specified timeout period. Throws * WaitTimeoutExpiredException after waiting for specified time period * and wait condition is not met. * * @param condition wait condition to met * @param timePeriod time period to wait */ public AbstractWait(WaitCondition condition, TimePeriod timePeriod) { this(condition, timePeriod, true); } /** * Waits till condition is met for specified timeout period. There is a * possibility to turn on/off throwing a exception. * * @param condition wait condition to met * @param timePeriod time period to wait * @param throwRuntimeException whether exception should be thrown after * expiration of the period * @throws WaitTimeoutExpiredException the wait timeout expired exception */ public AbstractWait(WaitCondition condition, TimePeriod timePeriod, boolean throwRuntimeException) { this(condition, timePeriod, throwRuntimeException, TimePeriod.SHORT); } /** * Waits till condition is met for specified timeout period. There is a * possibility to turn on/off throwing a exception. This constructor also * allows to set custom test period - time elapsed before another execution * of a wait condition is performed. * * @param condition wait condition to met * @param timePeriod time period to wait * @param throwRuntimeException whether exception should be thrown after * expiration of the period * @param testPeriod time to wait before another testing of a wait * condition is performed * @throws WaitTimeoutExpiredException the wait timeout expired exception */ public AbstractWait(WaitCondition condition, TimePeriod timePeriod, boolean throwRuntimeException, TimePeriod testPeriod) { if(condition == null) { throw new IllegalArgumentException("condition can't be null"); } if(timePeriod == null) { throw new IllegalArgumentException("timePeriod can't be null"); } if (testPeriod == null) { throw new IllegalArgumentException("testPeriod cannot be null."); } this.timeout = timePeriod; this.throwTimeoutException = throwRuntimeException; wait(condition, testPeriod); } /** * Condition if the waiting should stop. * * @param condition wait condition to met * @return true if the while loop should continue, false otherwise */ protected abstract boolean stopWaiting(WaitCondition condition); /** * Gets description of specific wait condition. Description should * provide information about nature of wait condition followed by space * character. Purpose of this method is logging. * * @return description of specific wait condition */ protected abstract String description(); private void wait(WaitCondition condition, TimePeriod testPeriod) { long limit; if((Long.MAX_VALUE - System.currentTimeMillis()) / 1000 > getTimeout().getSeconds()){ limit = System.currentTimeMillis() + getTimeout().getSeconds() * 1000; } else { limit = Long.MAX_VALUE; } while (true) { if (stopWaiting(condition)){ break; } if (timeoutExceeded(condition, limit)){ return; } sleep(testPeriod); } } /** * Gets time period of timeout. * * @return time period of timeout */ protected TimePeriod getTimeout() { return timeout; } /** * Finds out whether exception should be thrown is wait condition is not met * after expiration of specified time period. * * @return true if exception should be thrown, false otherwise */ protected boolean throwTimeoutException() { return throwTimeoutException; } /** * Sleeps for specified time period. * * @param timePeriod time period to sleep */ public static void sleep(TimePeriod timePeriod) { try { Thread.sleep(timePeriod.getSeconds() * 1000); } catch (InterruptedException e) { throw new RuntimeException("Sleep interrupted", e); } } private boolean timeoutExceeded(WaitCondition condition, long limit) { if (System.currentTimeMillis() > limit) { if (throwTimeoutException()) { throw new IllegalArgumentException("wait failed"+ condition.errorMessage()); } else { return true; } } return false; } }