hrider.actions.RunnableAction.java Source code

Java tutorial

Introduction

Here is the source code for hrider.actions.RunnableAction.java

Source

package hrider.actions;

import hrider.io.Log;
import org.apache.commons.lang.time.StopWatch;

/**
 * Copyright (C) 2012 NICE Systems ltd.
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @author Igor Cher
 * @version %I%, %G%
 *          <p/>
 *          This class represents a runnable action.
 */
public class RunnableAction<R> implements Runnable {

    //region Constants
    private final static Log logger = Log.getLogger(RunnableAction.class);
    //endregion

    //region Variables
    private String name;
    private Action<R> action;
    private Thread thread;
    private boolean isRunning;
    private boolean interrupted;
    private R result;
    //endregion

    //region Constructor
    public RunnableAction(String name, Action<R> action) {
        this.name = name;
        this.action = action;
    }
    //endregion

    //region Public Properties
    public R getResult() {
        return result;
    }

    public boolean isCompleted() {
        return !isRunning && !interrupted;
    }

    public boolean isRunning() {
        return isRunning;
    }
    //endregion

    //region Public Methods
    public static <R> RunnableAction<R> run(String name, Action<R> action) {
        RunnableAction<R> runnableAction = new RunnableAction<R>(name, action);
        runnableAction.start();

        return runnableAction;
    }

    public static <R> R runAndWait(String name, Action<R> action, long timeout) {
        RunnableAction<R> runnableAction = new RunnableAction<R>(name, action);
        runnableAction.start();

        runnableAction.waitOrAbort(timeout);
        return runnableAction.result;
    }

    public void start() {
        if (this.thread == null) {
            this.thread = new Thread(this);
            this.thread.setName(this.name);
            this.thread.setDaemon(true);
            this.thread.start();

            this.isRunning = true;

            logger.info("Action '%s' started.", this.name);
        }
    }

    public void abort() {
        if (this.isRunning) {
            this.interrupted = true;

            this.thread.interrupt();
            this.thread = null;
        }
    }

    public void waitUntil(long timeout) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        long localTimeout = timeout / 10;

        while (this.isRunning) {
            try {
                Thread.sleep(localTimeout);

                if (stopWatch.getTime() > timeout) {
                    break;
                }
            } catch (InterruptedException ignore) {
            }
        }

        stopWatch.stop();
    }

    public void waitOrAbort(long timeout) {
        waitUntil(timeout);

        if (this.isRunning) {
            abort();
        }
    }

    @Override
    public void run() {
        try {
            this.result = action.run();
            this.isRunning = false;

            logger.info("Action '%s' completed.", this.name);
        } catch (Exception e) {
            this.isRunning = false;

            if (this.interrupted) {
                logger.info("Action '%s' aborted.", this.name);
            } else {
                logger.info("Action '%s' failed.", this.name);
                this.action.onError(e);
            }
        }
    }
    //endregion
}