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}