• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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