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 }