    001package com.hammurapi.common.concurrent;
    002
    003import java.util.concurrent.Callable;
    004
    005/**
    006 * Callable which callInternal() method is invoked only once.
    007 * @author Pavel Vlasov
    008 *
    009 * @param <T>
    010 */
    011public abstract class OneOffCallable<T> implements Callable<T> {
    012
    013        private boolean hasRun;
    014        private Exception exception;
    015        private T result;
    016
    017        public synchronized T call() throws Exception {
    018                if (!hasRun) {
    019                        try {
    020                                result = callInternal();
    021                        } catch (Exception e) {
    022                                exception = e;
    023                        } finally {
    024                                hasRun = true;
    025                        }
    026                }
    027
    028                if (exception!=null) {
    029                        throw exception;
    030                }
    031                return result;
    032        }
    033
    034        /**
    035         * This method is invoked once by the call() method.
    036         * @return
    037         */
    038        protected abstract T callInternal() throws Exception;
    039
    040}