1 /* 2 * Copyright (c) 2016 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 package org.mockito.internal.util; 6 7 import org.mockito.internal.creation.instance.InstantiationException; 8 9 import java.lang.reflect.Method; 10 11 /** 12 * Helper class to work with features that were introduced in Java versions after 1.5. 13 * This class uses reflection in most places to avoid coupling with a newer JDK. 14 */ 15 public final class JavaEightUtil { 16 17 // No need for volatile, these optionals are already safe singletons. 18 private static Object emptyOptional; 19 private static Object emptyOptionalDouble; 20 private static Object emptyOptionalInt; 21 private static Object emptyOptionalLong; 22 JavaEightUtil()23 private JavaEightUtil() { 24 // utility class 25 } 26 27 /** 28 * Creates an empty Optional using reflection to stay backwards-compatible with older JDKs. 29 * 30 * @return an empty Optional. 31 */ emptyOptional()32 public static Object emptyOptional() { 33 // no need for double-checked locking 34 if (emptyOptional != null) { 35 return emptyOptional; 36 } 37 38 return emptyOptional = invokeNullaryFactoryMethod("java.util.Optional", "empty"); 39 } 40 41 42 /** 43 * Creates an empty OptionalDouble using reflection to stay backwards-compatible with older JDKs. 44 * 45 * @return an empty OptionalDouble. 46 */ emptyOptionalDouble()47 public static Object emptyOptionalDouble() { 48 // no need for double-checked locking 49 if (emptyOptionalDouble != null) { 50 return emptyOptionalDouble; 51 } 52 53 return emptyOptionalDouble = invokeNullaryFactoryMethod("java.util.OptionalDouble", "empty"); 54 } 55 56 /** 57 * Creates an empty OptionalInt using reflection to stay backwards-compatible with older JDKs. 58 * 59 * @return an empty OptionalInt. 60 */ emptyOptionalInt()61 public static Object emptyOptionalInt() { 62 // no need for double-checked locking 63 if (emptyOptionalInt != null) { 64 return emptyOptionalInt; 65 } 66 67 return emptyOptionalInt = invokeNullaryFactoryMethod("java.util.OptionalInt", "empty"); 68 } 69 70 /** 71 * Creates an empty OptionalLong using reflection to stay backwards-compatible with older JDKs. 72 * 73 * @return an empty OptionalLong. 74 */ emptyOptionalLong()75 public static Object emptyOptionalLong() { 76 // no need for double-checked locking 77 if (emptyOptionalLong != null) { 78 return emptyOptionalLong; 79 } 80 81 return emptyOptionalLong = invokeNullaryFactoryMethod("java.util.OptionalLong", "empty"); 82 } 83 84 /** 85 * Creates an empty Stream using reflection to stay backwards-compatible with older JDKs. 86 * 87 * @return an empty Stream. 88 */ emptyStream()89 public static Object emptyStream() { 90 // note: the empty stream can not be stored as a singleton. 91 return invokeNullaryFactoryMethod("java.util.stream.Stream", "empty"); 92 } 93 94 /** 95 * Creates an empty DoubleStream using reflection to stay backwards-compatible with older JDKs. 96 * 97 * @return an empty DoubleStream. 98 */ emptyDoubleStream()99 public static Object emptyDoubleStream() { 100 // note: the empty stream can not be stored as a singleton. 101 return invokeNullaryFactoryMethod("java.util.stream.DoubleStream", "empty"); 102 } 103 104 /** 105 * Creates an empty IntStream using reflection to stay backwards-compatible with older JDKs. 106 * 107 * @return an empty IntStream. 108 */ emptyIntStream()109 public static Object emptyIntStream() { 110 // note: the empty stream can not be stored as a singleton. 111 return invokeNullaryFactoryMethod("java.util.stream.IntStream", "empty"); 112 } 113 114 /** 115 * Creates an empty LongStream using reflection to stay backwards-compatible with older JDKs. 116 * 117 * @return an empty LongStream. 118 */ emptyLongStream()119 public static Object emptyLongStream() { 120 // note: the empty stream can not be stored as a singleton. 121 return invokeNullaryFactoryMethod("java.util.stream.LongStream", "empty"); 122 } 123 124 /** 125 * Invokes a nullary static factory method using reflection to stay backwards-compatible with older JDKs. 126 * 127 * @param fqcn The fully qualified class name of the type to be produced. 128 * @param methodName The name of the factory method. 129 * @return the object produced. 130 */ invokeNullaryFactoryMethod(final String fqcn, final String methodName)131 private static Object invokeNullaryFactoryMethod(final String fqcn, final String methodName) { 132 try { 133 final Class<?> type = Class.forName(fqcn); 134 final Method method = type.getMethod(methodName); 135 136 return method.invoke(null); 137 // any exception is really unexpected since the type name has 138 // already been verified 139 } catch (final Exception e) { 140 throw new InstantiationException( 141 String.format("Could not create %s#%s(): %s", fqcn, methodName, e), e); 142 } 143 } 144 } 145