001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.lang3.concurrent;
018    
019    import java.util.concurrent.ExecutionException;
020    import java.util.concurrent.Future;
021    import java.util.concurrent.TimeUnit;
022    
023    /**
024     * <p>
025     * An utility class providing functionality related to the {@code
026     * java.util.concurrent} package.
027     * </p>
028     *
029     * @author Apache Software Foundation
030     * @version $Id: ConcurrentUtils.java 929189 2010-03-30 16:49:22Z oheger $
031     */
032    public class ConcurrentUtils {
033    
034        /**
035         * Private constructor so that no instances can be created. This class
036         * contains only static utility methods.
037         */
038        private ConcurrentUtils() {
039        }
040    
041        /**
042         * Inspects the cause of the specified {@code ExecutionException} and
043         * creates a {@code ConcurrentException} with the checked cause if
044         * necessary. This method performs the following checks on the cause of the
045         * passed in exception:
046         * <ul>
047         * <li>If the passed in exception is <b>null</b> or the cause is
048         * <b>null</b>, this method returns <b>null</b>.</li>
049         * <li>If the cause is a runtime exception, it is directly thrown.</li>
050         * <li>If the cause is an error, it is directly thrown, too.</li>
051         * <li>In any other case the cause is a checked exception. The method then
052         * creates a {@link ConcurrentException}, initializes it with the cause, and
053         * returns it.</li>
054         * </ul>
055         *
056         * @param ex the exception to be processed
057         * @return a {@code ConcurrentException} with the checked cause
058         */
059        public static ConcurrentException extractCause(ExecutionException ex) {
060            if (ex == null || ex.getCause() == null) {
061                return null;
062            }
063    
064            throwCause(ex);
065            return new ConcurrentException(ex.getMessage(), ex.getCause());
066        }
067    
068        /**
069         * Inspects the cause of the specified {@code ExecutionException} and
070         * creates a {@code ConcurrentRuntimeException} with the checked cause if
071         * necessary. This method works exactly like
072         * {@link #extractCause(ExecutionException)}. The only difference is that
073         * the cause of the specified {@code ExecutionException} is extracted as a
074         * runtime exception. This is an alternative for client code that does not
075         * want to deal with checked exceptions.
076         *
077         * @param ex the exception to be processed
078         * @return a {@code ConcurrentRuntimeException} with the checked cause
079         */
080        public static ConcurrentRuntimeException extractCauseUnchecked(
081                ExecutionException ex) {
082            if (ex == null || ex.getCause() == null) {
083                return null;
084            }
085    
086            throwCause(ex);
087            return new ConcurrentRuntimeException(ex.getMessage(), ex.getCause());
088        }
089    
090        /**
091         * Handles the specified {@code ExecutionException}. This method calls
092         * {@link #extractCause(ExecutionException)} for obtaining the cause of the
093         * exception - which might already cause an unchecked exception or an error
094         * being thrown. If the cause is a checked exception however, it is wrapped
095         * in a {@code ConcurrentException}, which is thrown. If the passed in
096         * exception is <b>null</b> or has no cause, the method simply returns
097         * without throwing an exception.
098         *
099         * @param ex the exception to be handled
100         * @throws ConcurrentException if the cause of the {@code
101         * ExecutionException} is a checked exception
102         */
103        public static void handleCause(ExecutionException ex)
104                throws ConcurrentException {
105            ConcurrentException cex = extractCause(ex);
106    
107            if (cex != null) {
108                throw cex;
109            }
110        }
111    
112        /**
113         * Handles the specified {@code ExecutionException} and transforms it into a
114         * runtime exception. This method works exactly like
115         * {@link #handleCause(ExecutionException)}, but instead of a
116         * {@link ConcurrentException} it throws a
117         * {@link ConcurrentRuntimeException}. This is an alternative for client
118         * code that does not want to deal with checked exceptions.
119         *
120         * @param ex the exception to be handled
121         * @throws ConcurrentRuntimeException if the cause of the {@code
122         * ExecutionException} is a checked exception; this exception is then
123         * wrapped in the thrown runtime exception
124         */
125        public static void handleCauseUnchecked(ExecutionException ex) {
126            ConcurrentRuntimeException crex = extractCauseUnchecked(ex);
127    
128            if (crex != null) {
129                throw crex;
130            }
131        }
132    
133        /**
134         * Tests whether the specified {@code Throwable} is a checked exception. If
135         * not, an exception is thrown.
136         *
137         * @param ex the {@code Throwable} to check
138         * @return a flag whether the passed in exception is a checked exception
139         * @throws IllegalArgumentException if the {@code Throwable} is not a
140         * checked exception
141         */
142        static Throwable checkedException(Throwable ex) {
143            if (ex != null && !(ex instanceof RuntimeException)
144                    && !(ex instanceof Error)) {
145                return ex;
146            } else {
147                throw new IllegalArgumentException("Not a checked exception: " + ex);
148            }
149        }
150    
151        /**
152         * Tests whether the cause of the specified {@code ExecutionException}
153         * should be thrown and does it if necessary.
154         *
155         * @param ex the exception in question
156         */
157        private static void throwCause(ExecutionException ex) {
158            if (ex.getCause() instanceof RuntimeException) {
159                throw (RuntimeException) ex.getCause();
160            }
161    
162            if (ex.getCause() instanceof Error) {
163                throw (Error) ex.getCause();
164            }
165        }
166    
167        //-----------------------------------------------------------------------
168        /**
169         * Invokes the specified {@code ConcurrentInitializer} and returns the
170         * object produced by the initializer. This method just invokes the {@code
171         * get()} method of the given {@code ConcurrentInitializer}. It is
172         * <b>null</b>-safe: if the argument is <b>null</b>, result is also
173         * <b>null</b>.
174         *
175         * @param <T> the type of the object produced by the initializer
176         * @param initializer the {@code ConcurrentInitializer} to be invoked
177         * @return the object managed by the {@code ConcurrentInitializer}
178         * @throws ConcurrentException if the {@code ConcurrentInitializer} throws
179         * an exception
180         */
181        public static <T> T initialize(ConcurrentInitializer<T> initializer)
182                throws ConcurrentException {
183            return (initializer != null) ? initializer.get() : null;
184        }
185    
186        /**
187         * Invokes the specified {@code ConcurrentInitializer} and transforms
188         * occurring exceptions to runtime exceptions. This method works like
189         * {@link #initialize(ConcurrentInitializer)}, but if the {@code
190         * ConcurrentInitializer} throws a {@link ConcurrentException}, it is
191         * caught, and the cause is wrapped in a {@link ConcurrentRuntimeException}.
192         * So client code does not have to deal with checked exceptions.
193         *
194         * @param <T> the type of the object produced by the initializer
195         * @param initializer the {@code ConcurrentInitializer} to be invoked
196         * @return the object managed by the {@code ConcurrentInitializer}
197         * @throws ConcurrentRuntimeException if the initializer throws an exception
198         */
199        public static <T> T initializeUnchecked(ConcurrentInitializer<T> initializer) {
200            try {
201                return initialize(initializer);
202            } catch (ConcurrentException cex) {
203                throw new ConcurrentRuntimeException(cex.getCause());
204            }
205        }
206    
207        //-----------------------------------------------------------------------
208        /**
209         * <p>
210         * Gets an implementation of <code>Future</code> that is immediately done
211         * and returns the specified constant value.
212         * </p>
213         * <p>
214         * This can be useful to return a simple constant immediately from the
215         * concurrent processing, perhaps as part of avoiding nulls.
216         * A constant future can also be useful in testing.
217         * </p>
218         *
219         * @param value  the constant value to return, may be null
220         * @return an instance of Future that will return the value, never null
221         */
222        public static <T> Future<T> constantFuture(T value) {
223            return new ConstantFuture<T>(value);
224        }
225    
226        static final class ConstantFuture<T> implements Future<T> {
227            /** The constant value. */
228            private final T value;
229    
230            ConstantFuture(T value) {
231                this.value = value;
232            }
233    
234            public boolean isDone() {
235                return true;
236            }
237    
238            public T get() {
239                return value;
240            }
241    
242            public T get(long timeout, TimeUnit unit) {
243                return value;
244            }
245    
246            public boolean isCancelled() {
247                return false;
248            }
249    
250            public boolean cancel(boolean mayInterruptIfRunning) {
251                return false;
252            }
253        }
254    
255    }