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 }