1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.common.util.spring;
17
18 import java.io.File;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.Comparator;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Properties;
27
28 import org.codehaus.plexus.util.StringUtils;
29 import org.jasypt.util.text.TextEncryptor;
30 import org.kuali.common.util.Assert;
31 import org.kuali.common.util.CollectionUtils;
32 import org.kuali.common.util.EncUtils;
33 import org.kuali.common.util.EncryptionStrength;
34 import org.kuali.common.util.FormatUtils;
35 import org.kuali.common.util.LocationUtils;
36 import org.kuali.common.util.LoggerLevel;
37 import org.kuali.common.util.LoggerUtils;
38 import org.kuali.common.util.Project;
39 import org.kuali.common.util.ProjectUtils;
40 import org.kuali.common.util.PropertyUtils;
41 import org.kuali.common.util.ReflectionUtils;
42 import org.kuali.common.util.Str;
43 import org.kuali.common.util.execute.Executable;
44 import org.kuali.common.util.execute.SpringExecutable;
45 import org.kuali.common.util.property.Constants;
46 import org.kuali.common.util.property.ProjectProperties;
47 import org.kuali.common.util.property.processor.ResolvePlaceholdersProcessor;
48 import org.kuali.common.util.service.DefaultSpringService;
49 import org.kuali.common.util.service.PropertySourceContext;
50 import org.kuali.common.util.service.SpringContext;
51 import org.kuali.common.util.service.SpringService;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54 import org.springframework.beans.factory.BeanFactoryUtils;
55 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
56 import org.springframework.context.ApplicationContext;
57 import org.springframework.context.ConfigurableApplicationContext;
58 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
59 import org.springframework.context.support.ClassPathXmlApplicationContext;
60 import org.springframework.context.support.GenericXmlApplicationContext;
61 import org.springframework.core.env.ConfigurableEnvironment;
62 import org.springframework.core.env.EnumerablePropertySource;
63 import org.springframework.core.env.Environment;
64 import org.springframework.core.env.MutablePropertySources;
65 import org.springframework.core.env.PropertiesPropertySource;
66 import org.springframework.core.env.PropertySource;
67 import org.springframework.util.PropertyPlaceholderHelper;
68
69 public class SpringUtils {
70
71 private static final Logger logger = LoggerFactory.getLogger(SpringUtils.class);
72
73
74 private static final PropertyPlaceholderHelper HELPER = new PropertyPlaceholderHelper("${", "}", ":", false);
75
76
77
78
79 public static <T> T getInstance(Environment env, String key, String defaultValue) {
80 String className = getProperty(env, key, defaultValue);
81 return ReflectionUtils.newInstance(className);
82 }
83
84 public static List<String> getListFromCSV(Environment env, String key, String defaultValue) {
85 String csv = SpringUtils.getProperty(env, key, defaultValue);
86 return CollectionUtils.getTrimmedListFromCSV(csv);
87 }
88
89 public static List<PropertySource<?>> getPropertySources(SpringService service, Class<?> annotatedClass, String mavenPropertiesBeanName, Properties mavenProperties) {
90 ConfigurableApplicationContext parent = getContextWithPreRegisteredBean(mavenPropertiesBeanName, mavenProperties);
91 AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
92 child.setParent(parent);
93 child.register(annotatedClass);
94 child.refresh();
95 return SpringUtils.getPropertySources(child);
96 }
97
98 public static List<PropertySource<?>> getPropertySources(SpringService service, String location, String mavenPropertiesBeanName, Properties mavenProperties) {
99 String[] locationsArray = { location };
100 ConfigurableApplicationContext parent = getContextWithPreRegisteredBean(mavenPropertiesBeanName, mavenProperties);
101 ConfigurableApplicationContext child = new ClassPathXmlApplicationContext(locationsArray, parent);
102 return SpringUtils.getPropertySources(child);
103 }
104
105 public static Executable getSpringExecutable(Environment env, boolean skip, PropertySource<?> ps, List<Class<?>> annotatedClasses) {
106
107
108
109
110 PropertySourceContext psc = new PropertySourceContext(ps, true);
111
112
113 SpringContext context = new SpringContext();
114 context.setAnnotatedClasses(annotatedClasses);
115 context.setPropertySourceContext(psc);
116
117
118 SpringExecutable se = new SpringExecutable();
119 se.setService(new DefaultSpringService());
120 se.setContext(context);
121 se.setSkip(skip);
122 return se;
123 }
124
125 public static int getInteger(Environment env, String key) {
126 String value = getProperty(env, key);
127 return Integer.parseInt(value);
128 }
129
130 public static int getInteger(Environment env, String key, int defaultValue) {
131 String value = getProperty(env, key, Integer.toString(defaultValue));
132 return Integer.parseInt(value);
133 }
134
135 public static long getLong(Environment env, String key) {
136 String value = getProperty(env, key);
137 return Long.parseLong(value);
138 }
139
140 public static long getLong(Environment env, String key, long defaultValue) {
141 String value = getProperty(env, key, Long.toString(defaultValue));
142 return Long.parseLong(value);
143 }
144
145 public static double getDouble(Environment env, String key) {
146 String value = getProperty(env, key);
147 return Double.parseDouble(value);
148 }
149
150 public static double getDouble(Environment env, String key, double defaultValue) {
151 String value = getProperty(env, key, Double.toString(defaultValue));
152 return Double.parseDouble(value);
153 }
154
155
156
157
158
159
160 public static long getMillis(Environment env, String key, String defaultValue) {
161 String value = getProperty(env, key, defaultValue);
162 return FormatUtils.getMillis(value);
163 }
164
165
166
167
168
169
170 public static long getBytes(Environment env, String key, String defaultValue) {
171 String value = getProperty(env, key, defaultValue);
172 return FormatUtils.getBytes(value);
173 }
174
175
176
177
178
179
180 public static long getBytes(Environment env, String key) {
181 String value = getProperty(env, key);
182 return FormatUtils.getBytes(value);
183 }
184
185 public static File getFile(Environment env, String key) {
186 String value = getProperty(env, key);
187 return new File(value);
188 }
189
190 public static boolean getBoolean(Environment env, String key, boolean defaultValue) {
191 String value = getProperty(env, key, Boolean.toString(defaultValue));
192 return Boolean.parseBoolean(value);
193 }
194
195 public static boolean getBoolean(Environment env, String key) {
196 String value = getProperty(env, key);
197 return Boolean.parseBoolean(value);
198 }
199
200 public static PropertySource<?> getGlobalPropertySource(String name, List<ProjectProperties> pps) {
201
202 Properties source = PropertyUtils.load(pps);
203
204
205 Properties globalSource = PropertyUtils.getGlobalProperties(source);
206
207
208 prepareContextProperties(globalSource);
209
210
211 return new PropertiesPropertySource(name, globalSource);
212 }
213
214 public static PropertySource<?> getPropertySource(String name, List<ProjectProperties> pps) {
215
216 Properties source = PropertyUtils.load(pps);
217
218
219 prepareContextProperties(source);
220
221
222 return new PropertiesPropertySource(name, source);
223 }
224
225 public static String getRequiredResolvedProperty(Properties properties, String key) {
226 return getRequiredResolvedProperty(properties, key, null);
227 }
228
229 public static String getRequiredResolvedProperty(Properties properties, String key, String defaultValue) {
230 String value = properties.getProperty(key);
231 value = StringUtils.isBlank(value) ? defaultValue : value;
232 if (StringUtils.isBlank(value)) {
233 throw new IllegalArgumentException("[" + key + "] is not set");
234 } else {
235 return HELPER.replacePlaceholders(value, properties);
236 }
237 }
238
239
240
241
242
243
244
245
246 public static void prepareContextProperties(Properties properties) {
247
248
249 properties.putAll(PropertyUtils.getGlobalProperties());
250
251
252 decrypt(properties);
253
254
255 resolve(properties);
256 }
257
258 public static void resolve(Properties properties) {
259
260 boolean resolve = new Boolean(getRequiredResolvedProperty(properties, "properties.resolve", "true"));
261 if (resolve) {
262 ResolvePlaceholdersProcessor rpp = new ResolvePlaceholdersProcessor();
263 rpp.setHelper(HELPER);
264 rpp.process(properties);
265 }
266 }
267
268 public static void decrypt(Properties properties) {
269
270 boolean decrypt = new Boolean(getRequiredResolvedProperty(properties, "properties.decrypt", "false"));
271 if (decrypt) {
272
273 String password = getRequiredResolvedProperty(properties, "properties.enc.password");
274
275
276 String defaultStrength = EncryptionStrength.BASIC.name();
277 String strength = getRequiredResolvedProperty(properties, "properties.enc.strength", defaultStrength);
278 EncryptionStrength es = EncryptionStrength.valueOf(strength);
279 TextEncryptor decryptor = EncUtils.getTextEncryptor(es, password);
280 PropertyUtils.decrypt(properties, decryptor);
281 }
282 }
283
284
285
286
287
288
289
290
291 public static String getDefaultPropertyContextLocation(String gav) {
292 Assert.hasText(gav, "gav has no text");
293 Project p = ProjectUtils.getProject(gav);
294 return "classpath:" + Str.getPath(p.getGroupId()) + "/" + p.getArtifactId() + "-properties-context.xml";
295 }
296
297
298
299
300 public static void validateExists(List<String> locations) {
301 StringBuilder sb = new StringBuilder();
302 for (String location : locations) {
303 if (!LocationUtils.exists(location)) {
304 sb.append("Location [" + location + "] does not exist\n");
305 }
306 }
307 if (sb.length() > 0) {
308 throw new IllegalArgumentException(sb.toString());
309 }
310 }
311
312 public static ConfigurableApplicationContext getContextWithPreRegisteredBeans(String id, String displayName, List<String> beanNames, List<Object> beans) {
313 Assert.isTrue(beanNames.size() == beans.size());
314 GenericXmlApplicationContext appContext = new GenericXmlApplicationContext();
315 if (!StringUtils.isBlank(id)) {
316 appContext.setId(id);
317 }
318 if (!StringUtils.isBlank(displayName)) {
319 appContext.setDisplayName(displayName);
320 }
321 appContext.refresh();
322 ConfigurableListableBeanFactory factory = appContext.getBeanFactory();
323 for (int i = 0; i < beanNames.size(); i++) {
324 String beanName = beanNames.get(i);
325 Object bean = beans.get(i);
326 logger.debug("Registering bean - [{}] -> [{}]", beanName, bean.getClass().getName());
327 factory.registerSingleton(beanName, bean);
328 }
329 return appContext;
330 }
331
332 public static ConfigurableApplicationContext getContextWithPreRegisteredBeans(List<String> beanNames, List<Object> beans) {
333 return getContextWithPreRegisteredBeans(null, null, beanNames, beans);
334 }
335
336
337
338
339 public static void refreshQuietly(ConfigurableApplicationContext context) {
340 if (context != null) {
341 context.refresh();
342 }
343 }
344
345
346
347
348 public static void closeQuietly(ConfigurableApplicationContext context) {
349 if (context != null) {
350 context.close();
351 }
352 }
353
354 public static ConfigurableApplicationContext getContextWithPreRegisteredBean(String beanName, Object bean) {
355 return getContextWithPreRegisteredBeans(Arrays.asList(beanName), Arrays.asList(bean));
356 }
357
358 public static List<PropertySource<?>> getPropertySources(Class<?> annotatedClass) {
359 ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(annotatedClass);
360 return extractPropertySourcesAndClose(context);
361 }
362
363 public static List<PropertySource<?>> extractPropertySourcesAndClose(ConfigurableApplicationContext context) {
364
365 List<PropertySource<?>> sources = getPropertySources(context);
366
367
368 closeQuietly(context);
369
370
371 return sources;
372 }
373
374
375
376
377 public static List<PropertySource<?>> getPropertySources(String location) {
378 ConfigurableApplicationContext context = new GenericXmlApplicationContext(location);
379 return extractPropertySourcesAndClose(context);
380 }
381
382
383
384
385 public static List<PropertySource<?>> getPropertySources(ConfigurableApplicationContext context) {
386
387 return getPropertySources(context, new PropertySourceNameComparator());
388 }
389
390 public static <T> Map<String, T> getAllBeans(List<String> locations, Class<T> type) {
391 String[] locationsArray = locations.toArray(new String[locations.size()]);
392 ConfigurableApplicationContext ctx = new GenericXmlApplicationContext(locationsArray);
393 Map<String, T> map = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, type);
394 ctx.close();
395 return map;
396 }
397
398 public static <T> Map<String, T> getAllBeans(String location, Class<T> type) {
399 ConfigurableApplicationContext ctx = new GenericXmlApplicationContext(location);
400 Map<String, T> map = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, type);
401 ctx.close();
402 return map;
403 }
404
405 public static <T> Map<String, T> getAllBeans(ConfigurableApplicationContext ctx, Class<T> type) {
406 return BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, type);
407 }
408
409
410
411
412 public static List<PropertySource<?>> getPropertySources(ConfigurableApplicationContext context, Comparator<PropertySource<?>> comparator) {
413
414 @SuppressWarnings("rawtypes")
415 Map<String, PropertySource> map = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, PropertySource.class);
416
417
418 List<PropertySource<?>> list = new ArrayList<PropertySource<?>>();
419 for (PropertySource<?> source : map.values()) {
420 list.add(source);
421 }
422
423
424 Collections.sort(list, comparator);
425
426
427 return list;
428 }
429
430
431
432
433 public static List<PropertySource<?>> asList(PropertySource<?>... sources) {
434 List<PropertySource<?>> list = new ArrayList<PropertySource<?>>();
435 if (sources == null) {
436 return list;
437 }
438 for (PropertySource<?> element : sources) {
439 if (element != null) {
440 list.add(element);
441 }
442 }
443 return list;
444 }
445
446 public static void debug(ApplicationContext ctx) {
447 logger.debug("------------------------ Spring Context ------------------------------");
448 logger.debug("Id: [{}]", ctx.getId());
449 logger.debug("Display Name: [{}]", ctx.getDisplayName());
450 logger.debug("Application Name: [{}]", ctx.getApplicationName());
451 logger.debug("----------------------------------------------------------------------");
452 List<String> names = Arrays.asList(BeanFactoryUtils.beanNamesIncludingAncestors(ctx));
453 List<String> columns = Arrays.asList("Name", "Type", "Hashcode");
454 List<Object[]> rows = new ArrayList<Object[]>();
455 Collections.sort(names);
456 for (String name : names) {
457 Object bean = ctx.getBean(name);
458 String instance = (bean == null) ? Constants.NULL : bean.getClass().getSimpleName();
459 String hashcode = (bean == null) ? Constants.NULL : Integer.toHexString(bean.hashCode());
460 Object[] row = { name, instance, hashcode };
461 rows.add(row);
462 }
463 LoggerUtils.logTable(columns, rows, LoggerLevel.DEBUG, logger, true);
464 logger.debug("----------------------------------------------------------------------");
465 }
466
467 public static void showPropertySources(List<PropertySource<?>> propertySources) {
468 List<String> columns = Arrays.asList("Name", "Impl", "Source");
469 List<Object[]> rows = new ArrayList<Object[]>();
470 for (PropertySource<?> propertySource : propertySources) {
471 String name = propertySource.getName();
472 String impl = propertySource.getClass().getName();
473 String source = propertySource.getSource().getClass().getName();
474 Object[] row = { name, impl, source };
475 rows.add(row);
476 }
477 LoggerUtils.logTable(columns, rows, LoggerLevel.INFO, logger, true);
478 }
479
480 public static void showPropertySources(ConfigurableEnvironment env) {
481 showPropertySources(getPropertySources(env));
482 }
483
484
485
486
487 public static String getProperty(Environment env, String key) {
488 String value = env.getRequiredProperty(key);
489 return env.resolveRequiredPlaceholders(value);
490 }
491
492
493
494
495 public static boolean exists(Environment env, String key) {
496 return env.getProperty(key) != null;
497 }
498
499
500
501
502
503 public static String getProperty(Environment env, String key, String defaultValue) {
504 if (defaultValue == null) {
505
506 return getProperty(env, key);
507 } else {
508
509 String value = env.getProperty(key);
510 if (value == null) {
511
512 return env.resolveRequiredPlaceholders(defaultValue);
513 } else {
514
515 return env.resolveRequiredPlaceholders(value);
516 }
517 }
518 }
519
520
521
522
523
524 public static Properties getAllEnumerableProperties(ConfigurableEnvironment env) {
525
526
527 List<PropertySource<?>> sources = getPropertySources(env);
528
529
530
531 Collections.reverse(sources);
532
533
534 PropertySourceConversionResult result = convertEnumerablePropertySources(sources);
535
536
537 return PropertyUtils.combine(result.getPropertiesList());
538 }
539
540
541
542
543 public static void reconfigurePropertySources(ConfigurableEnvironment env, String name, Properties properties) {
544
545 removeAllPropertySources(env);
546
547
548 MutablePropertySources mps = env.getPropertySources();
549
550
551 Assert.isTrue(mps.size() == 0);
552
553
554 PropertiesPropertySource pps = new PropertiesPropertySource(name, properties);
555
556
557 mps.addFirst(pps);
558 }
559
560
561
562
563 public static void removeAllPropertySources(ConfigurableEnvironment env) {
564 MutablePropertySources mps = env.getPropertySources();
565 List<PropertySource<?>> sources = getPropertySources(env);
566 for (PropertySource<?> source : sources) {
567 String name = source.getName();
568 mps.remove(name);
569 }
570 }
571
572
573
574
575 public static List<PropertySource<?>> getPropertySources(ConfigurableEnvironment env) {
576 MutablePropertySources mps = env.getPropertySources();
577 List<PropertySource<?>> sources = new ArrayList<PropertySource<?>>();
578 Iterator<PropertySource<?>> itr = mps.iterator();
579 while (itr.hasNext()) {
580 PropertySource<?> source = itr.next();
581 sources.add(source);
582 }
583 return sources;
584 }
585
586
587
588
589 public static PropertySourceConversionResult convertEnumerablePropertySources(List<PropertySource<?>> sources) {
590 PropertySourceConversionResult result = new PropertySourceConversionResult();
591 List<Properties> list = new ArrayList<Properties>();
592 List<PropertySource<?>> converted = new ArrayList<PropertySource<?>>();
593 List<PropertySource<?>> skipped = new ArrayList<PropertySource<?>>();
594
595 for (PropertySource<?> source : sources) {
596 logger.debug("Adding [{}]", source.getName());
597 if (source instanceof EnumerablePropertySource) {
598 EnumerablePropertySource<?> eps = (EnumerablePropertySource<?>) source;
599 Properties sourceProperties = convert(eps);
600 list.add(sourceProperties);
601 converted.add(source);
602 } else {
603 logger.debug("Unable to obtain properties from property source [{}] -> [{}]", source.getName(), source.getClass().getName());
604 skipped.add(source);
605 }
606 }
607 result.setConverted(converted);
608 result.setSkipped(skipped);
609 result.setPropertiesList(list);
610 return result;
611 }
612
613
614
615
616 public static Properties convert(EnumerablePropertySource<?> source) {
617 Properties properties = new Properties();
618 String[] names = source.getPropertyNames();
619 for (String name : names) {
620 Object object = source.getProperty(name);
621 if (object != null) {
622 String value = object.toString();
623 properties.setProperty(name, value);
624 } else {
625 logger.warn("Property [{}] is null", name);
626 }
627 }
628 return properties;
629 }
630
631
632
633
634 public static boolean isTrue(Environment env, String property) {
635 String value = env.getProperty(property);
636 if (StringUtils.isBlank(value)) {
637 return false;
638 } else {
639 return new Boolean(value);
640 }
641 }
642
643 }