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