1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.dbcp2.datasources;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.IOException;
21 import java.io.ObjectInputStream;
22 import java.time.Duration;
23 import java.util.ArrayList;
24 import java.util.Hashtable;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Properties;
28 import java.util.concurrent.ConcurrentHashMap;
29
30 import javax.naming.Context;
31 import javax.naming.Name;
32 import javax.naming.RefAddr;
33 import javax.naming.Reference;
34 import javax.naming.spi.ObjectFactory;
35
36 import org.apache.commons.dbcp2.ListException;
37 import org.apache.commons.dbcp2.Utils;
38
39
40
41
42
43
44 abstract class InstanceKeyDataSourceFactory implements ObjectFactory {
45
46 private static final Map<String, InstanceKeyDataSource> INSTANCE_MAP = new ConcurrentHashMap<>();
47
48
49
50
51
52
53
54
55
56
57 public static void closeAll() throws ListException {
58
59 final List<Throwable> exceptionList = new ArrayList<>(INSTANCE_MAP.size());
60 INSTANCE_MAP.entrySet().forEach(entry -> {
61
62 if (entry != null) {
63 @SuppressWarnings("resource")
64 final InstanceKeyDataSource value = entry.getValue();
65 Utils.close(value, exceptionList::add);
66 }
67 });
68 INSTANCE_MAP.clear();
69 if (!exceptionList.isEmpty()) {
70 throw new ListException("Could not close all InstanceKeyDataSource instances.", exceptionList);
71 }
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 protected static final Object deserialize(final byte[] data) throws IOException, ClassNotFoundException {
88 ObjectInputStream in = null;
89 try {
90 in = new ObjectInputStream(new ByteArrayInputStream(data));
91 return in.readObject();
92 } finally {
93 Utils.closeQuietly(in);
94 }
95 }
96
97 static synchronized String registerNewInstance(final InstanceKeyDataSource ds) {
98 int max = 0;
99 for (final String s : INSTANCE_MAP.keySet()) {
100 if (s != null) {
101 try {
102 max = Math.max(max, Integer.parseInt(s));
103 } catch (final NumberFormatException ignored) {
104
105 }
106 }
107 }
108 final String instanceKey = String.valueOf(max + 1);
109
110
111 INSTANCE_MAP.put(instanceKey, ds);
112 return instanceKey;
113 }
114
115 static void removeInstance(final String key) {
116 if (key != null) {
117 INSTANCE_MAP.remove(key);
118 }
119 }
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 protected abstract InstanceKeyDataSource getNewInstance(Reference ref) throws IOException, ClassNotFoundException;
135
136
137
138
139 @Override
140 public Object getObjectInstance(final Object refObj, final Name name, final Context context,
141 final Hashtable<?, ?> env) throws IOException, ClassNotFoundException {
142
143
144 Object obj = null;
145 if (refObj instanceof Reference) {
146 final Reference ref = (Reference) refObj;
147 if (isCorrectClass(ref.getClassName())) {
148 final RefAddr refAddr = ref.get("instanceKey");
149 if (refAddr != null && refAddr.getContent() != null) {
150
151 obj = INSTANCE_MAP.get(refAddr.getContent());
152 } else {
153
154
155
156 String key = null;
157 if (name != null) {
158 key = name.toString();
159 obj = INSTANCE_MAP.get(key);
160 }
161 if (obj == null) {
162 final InstanceKeyDataSource ds = getNewInstance(ref);
163 setCommonProperties(ref, ds);
164 obj = ds;
165 if (key != null) {
166 INSTANCE_MAP.put(key, ds);
167 }
168 }
169 }
170 }
171 }
172 return obj;
173 }
174
175
176
177
178
179
180
181
182
183 protected abstract boolean isCorrectClass(String className);
184
185 boolean parseBoolean(final RefAddr refAddr) {
186 return Boolean.parseBoolean(toString(refAddr));
187 }
188
189 int parseInt(final RefAddr refAddr) {
190 return Integer.parseInt(toString(refAddr));
191 }
192
193 long parseLong(final RefAddr refAddr) {
194 return Long.parseLong(toString(refAddr));
195 }
196
197 private void setCommonProperties(final Reference ref, final InstanceKeyDataSource ikds)
198 throws IOException, ClassNotFoundException {
199
200 RefAddr refAddr = ref.get("dataSourceName");
201 if (refAddr != null && refAddr.getContent() != null) {
202 ikds.setDataSourceName(toString(refAddr));
203 }
204
205 refAddr = ref.get("description");
206 if (refAddr != null && refAddr.getContent() != null) {
207 ikds.setDescription(toString(refAddr));
208 }
209
210 refAddr = ref.get("jndiEnvironment");
211 if (refAddr != null && refAddr.getContent() != null) {
212 final byte[] serialized = (byte[]) refAddr.getContent();
213 ikds.setJndiEnvironment((Properties) deserialize(serialized));
214 }
215
216 refAddr = ref.get("loginTimeout");
217 if (refAddr != null && refAddr.getContent() != null) {
218 ikds.setLoginTimeout(Duration.ofSeconds(parseInt(refAddr)));
219 }
220
221
222 refAddr = ref.get("blockWhenExhausted");
223 if (refAddr != null && refAddr.getContent() != null) {
224 ikds.setDefaultBlockWhenExhausted(parseBoolean(refAddr));
225 }
226
227 refAddr = ref.get("evictionPolicyClassName");
228 if (refAddr != null && refAddr.getContent() != null) {
229 ikds.setDefaultEvictionPolicyClassName(toString(refAddr));
230 }
231
232
233 refAddr = ref.get("lifo");
234 if (refAddr != null && refAddr.getContent() != null) {
235 ikds.setDefaultLifo(parseBoolean(refAddr));
236 }
237
238 refAddr = ref.get("maxIdlePerKey");
239 if (refAddr != null && refAddr.getContent() != null) {
240 ikds.setDefaultMaxIdle(parseInt(refAddr));
241 }
242
243 refAddr = ref.get("maxTotalPerKey");
244 if (refAddr != null && refAddr.getContent() != null) {
245 ikds.setDefaultMaxTotal(parseInt(refAddr));
246 }
247
248 refAddr = ref.get("maxWaitMillis");
249 if (refAddr != null && refAddr.getContent() != null) {
250 ikds.setDefaultMaxWait(Duration.ofMillis(parseLong(refAddr)));
251 }
252
253 refAddr = ref.get("minEvictableIdleTimeMillis");
254 if (refAddr != null && refAddr.getContent() != null) {
255 ikds.setDefaultMinEvictableIdle(Duration.ofMillis(parseLong(refAddr)));
256 }
257
258 refAddr = ref.get("minIdlePerKey");
259 if (refAddr != null && refAddr.getContent() != null) {
260 ikds.setDefaultMinIdle(parseInt(refAddr));
261 }
262
263 refAddr = ref.get("numTestsPerEvictionRun");
264 if (refAddr != null && refAddr.getContent() != null) {
265 ikds.setDefaultNumTestsPerEvictionRun(parseInt(refAddr));
266 }
267
268 refAddr = ref.get("softMinEvictableIdleTimeMillis");
269 if (refAddr != null && refAddr.getContent() != null) {
270 ikds.setDefaultSoftMinEvictableIdle(Duration.ofMillis(parseLong(refAddr)));
271 }
272
273 refAddr = ref.get("testOnCreate");
274 if (refAddr != null && refAddr.getContent() != null) {
275 ikds.setDefaultTestOnCreate(parseBoolean(refAddr));
276 }
277
278 refAddr = ref.get("testOnBorrow");
279 if (refAddr != null && refAddr.getContent() != null) {
280 ikds.setDefaultTestOnBorrow(parseBoolean(refAddr));
281 }
282
283 refAddr = ref.get("testOnReturn");
284 if (refAddr != null && refAddr.getContent() != null) {
285 ikds.setDefaultTestOnReturn(parseBoolean(refAddr));
286 }
287
288 refAddr = ref.get("testWhileIdle");
289 if (refAddr != null && refAddr.getContent() != null) {
290 ikds.setDefaultTestWhileIdle(parseBoolean(refAddr));
291 }
292
293 refAddr = ref.get("timeBetweenEvictionRunsMillis");
294 if (refAddr != null && refAddr.getContent() != null) {
295 ikds.setDefaultDurationBetweenEvictionRuns(Duration.ofMillis(parseLong(refAddr)));
296 }
297
298
299
300 refAddr = ref.get("validationQuery");
301 if (refAddr != null && refAddr.getContent() != null) {
302 ikds.setValidationQuery(toString(refAddr));
303 }
304
305 refAddr = ref.get("validationQueryTimeout");
306 if (refAddr != null && refAddr.getContent() != null) {
307 ikds.setValidationQueryTimeout(Duration.ofSeconds(parseInt(refAddr)));
308 }
309
310 refAddr = ref.get("rollbackAfterValidation");
311 if (refAddr != null && refAddr.getContent() != null) {
312 ikds.setRollbackAfterValidation(parseBoolean(refAddr));
313 }
314
315 refAddr = ref.get("maxConnLifetimeMillis");
316 if (refAddr != null && refAddr.getContent() != null) {
317 ikds.setMaxConnLifetime(Duration.ofMillis(parseLong(refAddr)));
318 }
319
320
321
322 refAddr = ref.get("defaultAutoCommit");
323 if (refAddr != null && refAddr.getContent() != null) {
324 ikds.setDefaultAutoCommit(Boolean.valueOf(toString(refAddr)));
325 }
326
327 refAddr = ref.get("defaultTransactionIsolation");
328 if (refAddr != null && refAddr.getContent() != null) {
329 ikds.setDefaultTransactionIsolation(parseInt(refAddr));
330 }
331
332 refAddr = ref.get("defaultReadOnly");
333 if (refAddr != null && refAddr.getContent() != null) {
334 ikds.setDefaultReadOnly(Boolean.valueOf(toString(refAddr)));
335 }
336 }
337
338 String toString(final RefAddr refAddr) {
339 return refAddr.getContent().toString();
340 }
341 }