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 */ 017package org.apache.commons.lang3; 018 019import java.io.IOException; 020import java.io.UncheckedIOException; 021import java.lang.reflect.UndeclaredThrowableException; 022 023 024/** This class provides utility functions, and classes for working with the 025 * {@code java.util.function} package, or more generally, with Java 8 026 * lambdas. 027 * More specifically, it attempts to address the fact that lambdas are supposed 028 * not to throw Exceptions, at least not checked Exceptions, aka instances of 029 * {@link Exception}. This enforces the use of constructs like 030 * <pre> 031 * Consumer<java.lang.reflect.Method> consumer = (m) -> { 032 * try { 033 * m.invoke(o, args); 034 * } catch (Throwable t) { 035 * throw Functions.rethrow(t); 036 * } 037 * }; 038 * </pre> 039 * By replacing a {@link java.util.function.Consumer Consumer<O>} with a 040 * {@link FailableConsumer FailableConsumer<O,? extends Throwable>}, this can be 041 * written like follows: 042 * <pre> 043 * Functions.accept((m) -> m.invoke(o,args)); 044 * </pre> 045 * Obviously, the second version is much more concise and the spirit of 046 * Lambda expressions is met better than the second version. 047 */ 048public class Functions { 049 @FunctionalInterface 050 public interface FailableRunnable<T extends Throwable> { 051 /** 052 * Runs the function. 053 * @throws T if the function fails 054 */ 055 void run() throws T; 056 } 057 @FunctionalInterface 058 public interface FailableCallable<O, T extends Throwable> { 059 /** 060 * Calls the callable. 061 * @return The value returned from the callable 062 * @throws T if the callable fails 063 */ 064 O call() throws T; 065 } 066 @FunctionalInterface 067 public interface FailableConsumer<O, T extends Throwable> { 068 /** 069 * Accepts the consumer. 070 * @param pObject the parameter for the consumable to accept 071 * @throws T if the consumer fails 072 */ 073 void accept(O pObject) throws T; 074 } 075 @FunctionalInterface 076 public interface FailableBiConsumer<O1, O2, T extends Throwable> { 077 /** 078 * Accepts the consumer. 079 * @param pObject1 the first parameter for the consumable to accept 080 * @param pObject2 the second parameter for the consumable to accept 081 * @throws T if the consumer fails 082 */ 083 void accept(O1 pObject1, O2 pObject2) throws T; 084 } 085 @FunctionalInterface 086 public interface FailableFunction<I, O, T extends Throwable> { 087 /** 088 * Apply the function. 089 * @param pInput the input for the function 090 * @return the result of the function 091 * @throws T if the function fails 092 */ 093 O apply(I pInput) throws T; 094 } 095 @FunctionalInterface 096 public interface FailableBiFunction<I1, I2, O, T extends Throwable> { 097 /** 098 * Apply the function. 099 * @param pInput1 the first input for the function 100 * @param pInput2 the second input for the function 101 * @return the result of the function 102 * @throws T if the function fails 103 */ 104 O apply(I1 pInput1, I2 pInput2) throws T; 105 } 106 @FunctionalInterface 107 public interface FailablePredicate<O, T extends Throwable> { 108 /** 109 * Test the predicate. 110 * @param pObject the object to test the predicate on 111 * @return the predicate's evaluation 112 * @throws T if the predicate fails 113 */ 114 boolean test(O pObject) throws T; 115 } 116 @FunctionalInterface 117 public interface FailableBiPredicate<O1, O2, T extends Throwable> { 118 /** 119 * Test the predicate. 120 * @param pObject1 the first object to test the predicate on 121 * @param pObject2 the second object to test the predicate on 122 * @return the predicate's evaluation 123 * @throws T if the predicate fails 124 */ 125 boolean test(O1 pObject1, O2 pObject2) throws T; 126 } 127 128 /** 129 * Runs a runnable and rethrows any exception as a {@link RuntimeException}. 130 * @param pRunnable The runnable to run 131 * @param <T> the type of checked exception the runnable may throw 132 */ 133 public static <T extends Throwable> void run(FailableRunnable<T> pRunnable) { 134 try { 135 pRunnable.run(); 136 } catch (Throwable t) { 137 throw rethrow(t); 138 } 139 } 140 141 /** 142 * Calls a callable and rethrows any exception as a {@link RuntimeException}. 143 * @param pCallable the callable to call 144 * @param <O> the return type of the callable 145 * @param <T> the type of checked exception the callable may throw 146 * @return the value returned from the callable 147 */ 148 public static <O, T extends Throwable> O call(FailableCallable<O, T> pCallable) { 149 try { 150 return pCallable.call(); 151 } catch (Throwable t) { 152 throw rethrow(t); 153 } 154 } 155 156 /** 157 * Consumes a consumer and rethrows any exception as a {@link RuntimeException}. 158 * @param pConsumer the consumer to consume 159 * @param pObject the object to consume by <code>pConsumer</code> 160 * @param <O> the type the consumer accepts 161 * @param <T> the type of checked exception the consumer may throw 162 */ 163 public static <O, T extends Throwable> void accept(FailableConsumer<O, T> pConsumer, O pObject) { 164 try { 165 pConsumer.accept(pObject); 166 } catch (Throwable t) { 167 throw rethrow(t); 168 } 169 } 170 171 /** 172 * Consumes a consumer and rethrows any exception as a {@link RuntimeException}. 173 * @param pConsumer the consumer to consume 174 * @param pObject1 the first object to consume by <code>pConsumer</code> 175 * @param pObject2 the second object to consume by <code>pConsumer</code> 176 * @param <O1> the type of the first argument the consumer accepts 177 * @param <O2> the type of the second argument the consumer accepts 178 * @param <T> the type of checked exception the consumer may throw 179 */ 180 public static <O1, O2, T extends Throwable> void accept(FailableBiConsumer<O1, O2, T> pConsumer, O1 pObject1, O2 pObject2) { 181 try { 182 pConsumer.accept(pObject1, pObject2); 183 } catch (Throwable t) { 184 throw rethrow(t); 185 } 186 } 187 188 /** 189 * Applies a function and rethrows any exception as a {@link RuntimeException}. 190 * @param pFunction the function to apply 191 * @param pInput the input to apply <code>pFunction</code> on 192 * @param <I> the type of the argument the function accepts 193 * @param <O> the return type of the function 194 * @param <T> the type of checked exception the function may throw 195 * @return the value returned from the function 196 */ 197 public static <I, O, T extends Throwable> O apply(FailableFunction<I, O, T> pFunction, I pInput) { 198 try { 199 return pFunction.apply(pInput); 200 } catch (Throwable t) { 201 throw rethrow(t); 202 } 203 } 204 205 /** 206 * Applies a function and rethrows any exception as a {@link RuntimeException}. 207 * @param pFunction the function to apply 208 * @param pInput1 the first input to apply <code>pFunction</code> on 209 * @param pInput2 the second input to apply <code>pFunction</code> on 210 * @param <I1> the type of the first argument the function accepts 211 * @param <I2> the type of the second argument the function accepts 212 * @param <O> the return type of the function 213 * @param <T> the type of checked exception the function may throw 214 * @return the value returned from the function 215 */ 216 public static <I1, I2, O, T extends Throwable> O apply(FailableBiFunction<I1, I2, O, T> pFunction, I1 pInput1, I2 pInput2) { 217 try { 218 return pFunction.apply(pInput1, pInput2); 219 } catch (Throwable t) { 220 throw rethrow(t); 221 } 222 } 223 224 /** 225 * Tests a predicate and rethrows any exception as a {@link RuntimeException}. 226 * @param pPredicate the predicate to test 227 * @param pObject the input to test by <code>pPredicate</code> 228 * @param <O> the type of argument the predicate tests 229 * @param <T> the type of checked exception the predicate may throw 230 * @return the boolean value returned by the predicate 231 */ 232 public static <O, T extends Throwable> boolean test(FailablePredicate<O, T> pPredicate, O pObject) { 233 try { 234 return pPredicate.test(pObject); 235 } catch (Throwable t) { 236 throw rethrow(t); 237 } 238 } 239 240 /** 241 * Tests a predicate and rethrows any exception as a {@link RuntimeException}. 242 * @param pPredicate the predicate to test 243 * @param pObject1 the first input to test by <code>pPredicate</code> 244 * @param pObject2 the second input to test by <code>pPredicate</code> 245 * @param <O1> the type of the first argument the predicate tests 246 * @param <O2> the type of the second argument the predicate tests 247 * @param <T> the type of checked exception the predicate may throw 248 * @return the boolean value returned by the predicate 249 */ 250 public static <O1, O2, T extends Throwable> boolean test(FailableBiPredicate<O1, O2, T> pPredicate, O1 pObject1, O2 pObject2) { 251 try { 252 return pPredicate.test(pObject1, pObject2); 253 } catch (Throwable t) { 254 throw rethrow(t); 255 } 256 } 257 258 /** 259 * A simple try-with-resources implementation, that can be used, if your 260 * objects do not implement the {@link AutoCloseable} interface. The method 261 * executes the {@code pAction}. The method guarantees, that <em>all</em> 262 * the {@code pResources} are being executed, in the given order, afterwards, 263 * and regardless of success, or failure. If either the original action, or 264 * any of the resource action fails, then the <em>first</em> failure (aka 265 * {@link Throwable} is rethrown. Example use: 266 * <pre> 267 * final FileInputStream fis = new FileInputStream("my.file"); 268 * Functions.tryWithResources(useInputStream(fis), null, () -> fis.close()); 269 * </pre> 270 * @param pAction The action to execute. This object <em>will</em> always 271 * be invoked. 272 * @param pErrorHandler An optional error handler, which will be invoked finally, 273 * if any error occurred. The error handler will receive the first 274 * error, aka {@link Throwable}. 275 * @param pResources The resource actions to execute. <em>All</em> resource 276 * actions will be invoked, in the given order. A resource action is an 277 * instance of {@link FailableRunnable}, which will be executed. 278 * @see #tryWithResources(FailableRunnable, FailableRunnable...) 279 */ 280 @SafeVarargs 281 public static void tryWithResources(FailableRunnable<? extends Throwable> pAction, 282 FailableConsumer<Throwable, ? extends Throwable> pErrorHandler, 283 FailableRunnable<? extends Throwable>... pResources) { 284 final FailableConsumer<Throwable, ? extends Throwable> errorHandler; 285 if (pErrorHandler == null) { 286 errorHandler = (t) -> rethrow(t); 287 } else { 288 errorHandler = pErrorHandler; 289 } 290 if (pResources != null) { 291 for (FailableRunnable<? extends Throwable> runnable : pResources) { 292 if (runnable == null) { 293 throw new NullPointerException("A resource action must not be null."); 294 } 295 } 296 } 297 Throwable th = null; 298 try { 299 pAction.run(); 300 } catch (Throwable t) { 301 th = t; 302 } 303 if (pResources != null) { 304 for (FailableRunnable<? extends Object> runnable : pResources) { 305 try { 306 runnable.run(); 307 } catch (Throwable t) { 308 if (th == null) { 309 th = t; 310 } 311 } 312 } 313 } 314 if (th != null) { 315 try { 316 errorHandler.accept(th); 317 } catch (Throwable t) { 318 throw rethrow(t); 319 } 320 } 321 } 322 323 /** 324 * A simple try-with-resources implementation, that can be used, if your 325 * objects do not implement the {@link AutoCloseable} interface. The method 326 * executes the {@code pAction}. The method guarantees, that <em>all</em> 327 * the {@code pResources} are being executed, in the given order, afterwards, 328 * and regardless of success, or failure. If either the original action, or 329 * any of the resource action fails, then the <em>first</em> failure (aka 330 * {@link Throwable} is rethrown. Example use: 331 * <pre> 332 * final FileInputStream fis = new FileInputStream("my.file"); 333 * Functions.tryWithResources(useInputStream(fis), () -> fis.close()); 334 * </pre> 335 * @param pAction The action to execute. This object <em>will</em> always 336 * be invoked. 337 * @param pResources The resource actions to execute. <em>All</em> resource 338 * actions will be invoked, in the given order. A resource action is an 339 * instance of {@link FailableRunnable}, which will be executed. 340 * @see #tryWithResources(FailableRunnable, FailableConsumer, FailableRunnable...) 341 */ 342 @SafeVarargs 343 public static void tryWithResources(FailableRunnable<? extends Throwable> pAction, 344 FailableRunnable<? extends Throwable>... pResources) { 345 tryWithResources(pAction, null, pResources); 346 } 347 348 /** 349 * Rethrow a {@link Throwable} as an unchecked exception. 350 * @param pThrowable The throwable to rethrow 351 * @return Never returns anything, this method never terminates normally 352 */ 353 public static RuntimeException rethrow(Throwable pThrowable) { 354 if (pThrowable == null) { 355 throw new NullPointerException("The Throwable must not be null."); 356 } else { 357 if (pThrowable instanceof RuntimeException) { 358 throw (RuntimeException) pThrowable; 359 } else if (pThrowable instanceof Error) { 360 throw (Error) pThrowable; 361 } else if (pThrowable instanceof IOException) { 362 throw new UncheckedIOException((IOException) pThrowable); 363 } else { 364 throw new UndeclaredThrowableException(pThrowable); 365 } 366 } 367 } 368}