1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.castor.core.util;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.net.URL;
23 import java.text.MessageFormat;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Properties;
29
30 import org.apache.commons.lang3.StringUtils;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33
34
35
36
37
38
39
40
41 public abstract class AbstractProperties {
42
43
44
45
46 private static final String USER_PROPERTIES_SYSTEM_PROPERTY =
47 "org.castor.user.properties.location";
48
49
50
51
52
53 private static final Log LOG = LogFactory.getLog(AbstractProperties.class);
54
55
56
57
58 private final ClassLoader _applicationClassLoader;
59
60
61
62
63
64 private final ClassLoader _domainClassLoader;
65
66
67
68
69 private final AbstractProperties _parent;
70
71 private final Map<Object, Object> _map = new HashMap<>();
72
73
74
75
76
77 protected AbstractProperties() {
78 this(null, null);
79 }
80
81
82
83
84
85
86
87 protected AbstractProperties(final ClassLoader app, final ClassLoader domain) {
88 _applicationClassLoader = (app != null) ? app : getClass().getClassLoader();
89 _domainClassLoader = (domain != null) ? domain : getClass().getClassLoader();
90
91 _parent = null;
92 }
93
94
95
96
97
98
99
100 protected AbstractProperties(final AbstractProperties parent) {
101 _applicationClassLoader = parent.getApplicationClassLoader();
102 _domainClassLoader = parent.getDomainClassLoader();
103
104 _parent = parent;
105 }
106
107
108
109
110
111
112 public final ClassLoader getApplicationClassLoader() {
113 return _applicationClassLoader;
114 }
115
116
117
118
119
120
121
122 public final ClassLoader getDomainClassLoader() {
123 return _domainClassLoader;
124 }
125
126
127
128
129
130
131
132
133
134
135 protected void loadDefaultProperties(final String path, final String filename) {
136 Properties properties = new Properties();
137
138
139 boolean inCastorJar = loadFromClassPath(properties, path + filename);
140
141
142
143 boolean inJavaLibDir = loadFromJavaHome(properties, filename);
144
145
146 if (!inCastorJar && !inJavaLibDir) {
147 throw new PropertiesException("Failed to load properties: " + filename);
148 }
149
150 _map.putAll(properties);
151 }
152
153
154
155
156
157
158
159
160
161
162 protected void loadUserProperties(final String filename) {
163 Properties properties = new Properties();
164
165
166 boolean userPropertiesLoaded = loadFromClassPath(properties, "/" + filename);
167
168
169
170 if (!userPropertiesLoaded) {
171 userPropertiesLoaded = loadFromWorkingDirectory(properties, filename);
172 }
173
174 if (!userPropertiesLoaded) {
175 String property = System.getProperty(USER_PROPERTIES_SYSTEM_PROPERTY);
176 if (property != null && property.length() > 0) {
177 File file = new File(property);
178 if (file.exists()) {
179 LOG.info("Loading custom Castor properties from " + file.getAbsolutePath());
180 userPropertiesLoaded = loadFromFile(properties, file);
181 } else {
182 LOG.warn(file.getAbsolutePath() + " is not a valid file.");
183 }
184 }
185 }
186
187 _map.putAll(properties);
188 }
189
190
191
192
193
194
195
196
197 private boolean loadFromClassPath(final Properties properties, final String filename) {
198 InputStream classPathStream = null;
199 try {
200 URL url = getClass().getResource(filename);
201 if (url != null) {
202 classPathStream = url.openStream();
203 properties.load(classPathStream);
204
205 if (LOG.isDebugEnabled()) {
206 LOG.debug("Properties loaded from classpath: " + filename);
207 }
208
209 return true;
210 }
211 return false;
212 } catch (Exception ex) {
213 LOG.warn("Failed to load properties from classpath: " + filename, ex);
214 return false;
215 } finally {
216 if (classPathStream != null) {
217 try {
218 classPathStream.close();
219 } catch (IOException e) {
220 LOG.warn("Failed to close properties from classpath: " + filename);
221 }
222 }
223 }
224 }
225
226
227
228
229
230
231
232
233
234 private boolean loadFromJavaHome(final Properties properties, final String filename) {
235 try {
236 String javaHome = System.getProperty("java.home");
237 if (javaHome == null) {
238 return false;
239 }
240 return loadFromFile(properties, new File(new File(javaHome, "lib"), filename));
241 } catch (SecurityException ex) {
242 LOG.warn("Security policy prevented access to system property 'java.home'.", ex);
243 return false;
244 }
245 }
246
247
248
249
250
251
252
253
254
255 private boolean loadFromWorkingDirectory(final Properties properties, final String filename) {
256 return loadFromFile(properties, new File(filename));
257 }
258
259
260
261
262
263
264
265
266 private boolean loadFromFile(final Properties properties, final File file) {
267 try {
268 if (file.exists() && file.canRead()) {
269 try (InputStream fileStream = new FileInputStream(file)) {
270 properties.load(fileStream);
271 }
272
273 if (LOG.isDebugEnabled()) {
274 LOG.debug("Properties file loaded: " + file);
275 }
276
277 return true;
278 }
279 return false;
280 } catch (SecurityException ex) {
281 LOG.warn("Security policy prevented access to properties file: " + file, ex);
282 return false;
283 } catch (Exception ex) {
284 LOG.warn("Failed to load properties file: " + file, ex);
285 return false;
286 }
287 }
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304 public final synchronized Object put(final String key, final Object value) {
305 if (value == null) {
306 throw new NullPointerException();
307 }
308 return _map.put(key, value);
309 }
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324 public final synchronized Object remove(final String key) {
325 return _map.remove(key);
326 }
327
328
329
330
331
332
333
334
335
336
337
338 protected synchronized Object get(final String key) {
339 Object value = _map.get(key);
340 if ((value == null) && (_parent != null)) {
341 value = _parent.get(key);
342 }
343 return value;
344 }
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359 public final Boolean getBoolean(final String key) {
360 Object objectValue = get(key);
361
362 if (objectValue == null) {
363 return null;
364 } else if (objectValue instanceof Boolean) {
365 return (Boolean) objectValue;
366 } else if (objectValue instanceof String) {
367 String stringValue = (String) objectValue;
368 if ("true".equalsIgnoreCase(stringValue)) {
369 return Boolean.TRUE;
370 } else if ("false".equalsIgnoreCase(stringValue)) {
371 return Boolean.FALSE;
372 }
373 }
374
375 Object[] args = new Object[] {key, objectValue};
376 String msg = "Properties value can not be converted to boolean: {0}={1}";
377 throw new PropertiesException(MessageFormat.format(msg, args));
378 }
379
380
381
382
383
384
385
386
387
388
389
390
391
392 public final boolean getBoolean(final String key, final boolean defaultValue) {
393 Object objectValue = get(key);
394
395 if (objectValue instanceof Boolean) {
396 return ((Boolean) objectValue).booleanValue();
397 } else if (objectValue instanceof String) {
398 String stringValue = (String) objectValue;
399 if ("true".equalsIgnoreCase(stringValue)) {
400 return true;
401 } else if ("false".equalsIgnoreCase(stringValue)) {
402 return false;
403 }
404 }
405
406 return defaultValue;
407 }
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422 public final Integer getInteger(final String key) {
423 Object objectValue = get(key);
424
425 if (objectValue == null) {
426 return null;
427 } else if (objectValue instanceof Integer) {
428 return (Integer) objectValue;
429 } else if (objectValue instanceof String) {
430 try {
431 return Integer.valueOf((String) objectValue);
432 } catch (NumberFormatException ex) {
433 Object[] args = new Object[] {key, objectValue};
434 String msg = "Properties value can not be converted to int: {0}={1}";
435 throw new PropertiesException(MessageFormat.format(msg, args), ex);
436 }
437 }
438
439 Object[] args = new Object[] {key, objectValue};
440 String msg = "Properties value can not be converted to int: {0}={1}";
441 throw new PropertiesException(MessageFormat.format(msg, args));
442 }
443
444
445
446
447
448
449
450
451
452
453
454
455
456 public final int getInteger(final String key, final int defaultValue) {
457 Object objectValue = get(key);
458
459 if (objectValue instanceof Integer) {
460 return ((Integer) objectValue).intValue();
461 } else if (objectValue instanceof String) {
462 String stringValue = (String) objectValue;
463 try {
464 return Integer.parseInt(stringValue);
465 } catch (NumberFormatException ex) {
466 return defaultValue;
467 }
468 }
469
470 return defaultValue;
471 }
472
473
474
475
476
477
478
479
480
481
482
483 public final String getString(final String key) {
484 Object objectValue = get(key);
485
486 if (objectValue == null) {
487 return null;
488 } else if (objectValue instanceof String) {
489 return (String) objectValue;
490 }
491
492 Object[] args = new Object[] {key, objectValue};
493 String msg = "Properties value is not a string: {0}={1}";
494 throw new PropertiesException(MessageFormat.format(msg, args));
495 }
496
497
498
499
500
501
502
503
504
505
506
507
508 public final String getString(final String key, final String defaultValue) {
509 Object objectValue = get(key);
510
511 if ((objectValue instanceof String) && !"".equals(objectValue)) {
512 return (String) objectValue;
513 }
514
515 return defaultValue;
516 }
517
518
519
520
521
522
523
524
525
526
527
528
529
530 public final String[] getStringArray(final String key) {
531 Object objectValue = get(key);
532
533 if (objectValue == null) {
534 return null;
535 } else if (objectValue instanceof String[]) {
536 return (String[]) objectValue;
537 } else if (objectValue instanceof String) {
538 return StringUtils.split((String) objectValue, ',');
539 }
540
541 Object[] args = new Object[] {key, objectValue};
542 String msg = "Properties value is not a String[]: {0}={1}";
543 throw new PropertiesException(MessageFormat.format(msg, args));
544 }
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559 public final Class getClass(final String key, final ClassLoader loader) {
560 Object objectValue = get(key);
561
562 if (objectValue == null) {
563 return null;
564 } else if (objectValue instanceof Class) {
565 return (Class) objectValue;
566 } else if (objectValue instanceof String) {
567 String classname = (String) objectValue;
568 try {
569 return loader.loadClass(classname);
570 } catch (ClassNotFoundException ex) {
571 Object[] args = new Object[] {key, classname};
572 String msg = "Could not find class of properties value: {0}={1}";
573 throw new PropertiesException(MessageFormat.format(msg, args), ex);
574 }
575 }
576
577 Object[] args = new Object[] {key, objectValue};
578 String msg = "Properties value is not a Class: {0}={1}";
579 throw new PropertiesException(MessageFormat.format(msg, args));
580 }
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596 public final Class[] getClassArray(final String key, final ClassLoader loader) {
597 Object objectValue = get(key);
598
599 if (objectValue == null) {
600 return null;
601 } else if (objectValue instanceof Class[]) {
602 return (Class[]) objectValue;
603 } else if (objectValue instanceof String) {
604 String[] classnames = StringUtils.split((String) objectValue, ',');
605 Class[] classes = new Class[classnames.length];
606 for (int i = 0; i < classnames.length; i++) {
607 try {
608 classes[i] = loader.loadClass(classnames[i]);
609 } catch (ClassNotFoundException ex) {
610 Object[] args = new Object[] {key, Integer.valueOf(i), classnames[i]};
611 String msg = "Could not find class of properties value: {0}[{1}]={2}";
612 throw new PropertiesException(MessageFormat.format(msg, args), ex);
613 }
614 }
615 return classes;
616 }
617
618 Object[] args = new Object[] {key, objectValue};
619 String msg = "Properties value is not a Class[]: {0}={1}";
620 throw new PropertiesException(MessageFormat.format(msg, args));
621 }
622
623
624
625
626
627
628
629
630
631
632
633 public final Object getObject(final String key) {
634 return get(key);
635 }
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652 public final Object[] getObjectArray(final String key, final ClassLoader loader) {
653 Object objectValue = get(key);
654
655 if (objectValue == null) {
656 return null;
657 } else if (objectValue instanceof Object[]) {
658 return (Object[]) objectValue;
659 } else if (objectValue instanceof String) {
660 List<Object> objects = new ArrayList<>();
661 String[] classnames = StringUtils.split((String) objectValue, ',');
662 for (int i = 0; i < classnames.length; i++) {
663 String classname = classnames[i];
664 try {
665 if ((classname != null) && !"".equals(classname.trim())) {
666 classname = classname.trim();
667 objects.add(loader.loadClass(classname).newInstance());
668 }
669 } catch (ClassNotFoundException ex) {
670 Object[] args = new Object[] {key, Integer.valueOf(i), classname};
671 String msg = "Could not find configured class: {0}[{1}]={2}";
672 throw new PropertiesException(MessageFormat.format(msg, args), ex);
673 } catch (IllegalAccessException ex) {
674 Object[] args = new Object[] {key, Integer.valueOf(i), classname};
675 String msg = "Could not instantiate configured class: {0}[{1}]={2}";
676 throw new PropertiesException(MessageFormat.format(msg, args), ex);
677 } catch (InstantiationException ex) {
678 Object[] args = new Object[] {key, Integer.valueOf(i), classname};
679 String msg = "Could not instantiate configured class: {0}[{1}]={2}";
680 throw new PropertiesException(MessageFormat.format(msg, args), ex);
681 } catch (ExceptionInInitializerError ex) {
682 Object[] args = new Object[] {key, Integer.valueOf(i), classname};
683 String msg = "Could not instantiate configured class: {0}[{1}]={2}";
684 throw new PropertiesException(MessageFormat.format(msg, args), ex);
685 } catch (SecurityException ex) {
686 Object[] args = new Object[] {key, Integer.valueOf(i), classname};
687 String msg = "Could not instantiate configured class: {0}[{1}]={2}";
688 throw new PropertiesException(MessageFormat.format(msg, args), ex);
689 }
690 }
691 return objects.toArray();
692 }
693
694 Object[] args = new Object[] {key, objectValue};
695 String msg = "Properties value is not an Object[]: {0}={1}";
696 throw new PropertiesException(MessageFormat.format(msg, args));
697 }
698
699 }