001    package com.hammurapi.util.concurrent;
002    
003    import java.util.concurrent.Callable;
004    
005    /**
006     * Callable which callInternal() method is invoked only once. 
007     * @author Pavel Vlasov
008     *
009     * @param <T>
010     */
011    public 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    }