1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.pool2.impl;
18
19 import java.lang.reflect.ParameterizedType;
20 import java.lang.reflect.Type;
21 import java.lang.reflect.TypeVariable;
22 import java.time.Duration;
23 import java.time.Instant;
24 import java.time.temporal.ChronoUnit;
25 import java.util.Objects;
26 import java.util.concurrent.TimeUnit;
27
28 import org.apache.commons.pool2.PooledObjectFactory;
29
30
31
32
33
34
35 class PoolImplUtils {
36
37
38
39
40
41
42
43
44 @SuppressWarnings("rawtypes")
45 static Class<?> getFactoryType(final Class<? extends PooledObjectFactory> factoryClass) {
46 final Class<PooledObjectFactory> type = PooledObjectFactory.class;
47 final Object genericType = getGenericType(type, factoryClass);
48 if (genericType instanceof Integer) {
49
50
51
52
53 final ParameterizedType pi = getParameterizedType(type, factoryClass);
54 if (pi != null) {
55 final Type[] bounds = ((TypeVariable) pi.getActualTypeArguments()[((Integer) genericType).intValue()])
56 .getBounds();
57 if (bounds != null && bounds.length > 0) {
58 final Type bound0 = bounds[0];
59 if (bound0 instanceof Class) {
60 return (Class<?>) bound0;
61 }
62 }
63 }
64
65 return Object.class;
66 }
67 return (Class<?>) genericType;
68 }
69
70
71
72
73
74
75
76
77
78
79 private static <T> Object getGenericType(final Class<T> type, final Class<? extends T> clazz) {
80 if (type == null || clazz == null) {
81
82 return null;
83 }
84
85
86 final ParameterizedType pi = getParameterizedType(type, clazz);
87 if (pi != null) {
88 return getTypeParameter(clazz, pi.getActualTypeArguments()[0]);
89 }
90
91
92 @SuppressWarnings("unchecked")
93 final Class<? extends T> superClass = (Class<? extends T>) clazz.getSuperclass();
94
95 final Object result = getGenericType(type, superClass);
96 if (result instanceof Class<?>) {
97
98 return result;
99 }
100 if (result instanceof Integer) {
101
102
103 final ParameterizedType superClassType = (ParameterizedType) clazz.getGenericSuperclass();
104 return getTypeParameter(clazz, superClassType.getActualTypeArguments()[((Integer) result).intValue()]);
105 }
106
107 return null;
108 }
109
110
111
112
113
114
115
116
117
118 private static <T> ParameterizedType getParameterizedType(final Class<T> type, final Class<? extends T> clazz) {
119 for (final Type iface : clazz.getGenericInterfaces()) {
120
121 if (iface instanceof ParameterizedType) {
122 final ParameterizedType pi = (ParameterizedType) iface;
123
124 if (pi.getRawType() instanceof Class && type.isAssignableFrom((Class<?>) pi.getRawType())) {
125 return pi;
126 }
127 }
128 }
129 return null;
130 }
131
132
133
134
135
136
137
138
139
140
141
142 private static Object getTypeParameter(final Class<?> clazz, final Type argType) {
143 if (argType instanceof Class<?>) {
144 return argType;
145 }
146 final TypeVariable<?>[] tvs = clazz.getTypeParameters();
147 for (int i = 0; i < tvs.length; i++) {
148 if (tvs[i].equals(argType)) {
149 return Integer.valueOf(i);
150 }
151 }
152 return null;
153 }
154
155 static boolean isPositive(final Duration delay) {
156 return delay != null && !delay.isNegative() && !delay.isZero();
157 }
158
159
160
161
162
163
164
165
166
167 static Instant max(final Instant a, final Instant b) {
168 return a.compareTo(b) > 0 ? a : b;
169 }
170
171
172
173
174
175
176
177
178
179 static Instant min(final Instant a, final Instant b) {
180 return a.compareTo(b) < 0 ? a : b;
181 }
182
183
184
185
186
187
188
189
190 static Duration nonNull(final Duration value, final Duration defaultValue) {
191 return value != null ? value : Objects.requireNonNull(defaultValue, "defaultValue");
192 }
193
194
195
196
197
198
199
200 static ChronoUnit toChronoUnit(final TimeUnit timeUnit) {
201
202 switch (Objects.requireNonNull(timeUnit)) {
203 case NANOSECONDS:
204 return ChronoUnit.NANOS;
205 case MICROSECONDS:
206 return ChronoUnit.MICROS;
207 case MILLISECONDS:
208 return ChronoUnit.MILLIS;
209 case SECONDS:
210 return ChronoUnit.SECONDS;
211 case MINUTES:
212 return ChronoUnit.MINUTES;
213 case HOURS:
214 return ChronoUnit.HOURS;
215 case DAYS:
216 return ChronoUnit.DAYS;
217 default:
218 throw new IllegalArgumentException(timeUnit.toString());
219 }
220 }
221
222
223
224
225
226
227
228
229 static Duration toDuration(final long amount, final TimeUnit timeUnit) {
230 return Duration.of(amount, PoolImplUtils.toChronoUnit(timeUnit));
231 }
232
233 }