View Javadoc

1   /**
2    * Copyright 2010-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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.Mode;
36  import org.kuali.common.util.Project;
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.config.supplier.PropertiesSupplier;
41  import org.kuali.common.util.execute.Executable;
42  import org.kuali.common.util.nullify.NullUtils;
43  import org.kuali.common.util.property.Constants;
44  import org.kuali.common.util.property.PropertiesContext;
45  import org.slf4j.Logger;
46  import org.slf4j.LoggerFactory;
47  import org.springframework.beans.factory.BeanFactoryUtils;
48  import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
49  import org.springframework.context.ApplicationContext;
50  import org.springframework.context.ConfigurableApplicationContext;
51  import org.springframework.context.annotation.AnnotationConfigApplicationContext;
52  import org.springframework.context.support.ClassPathXmlApplicationContext;
53  import org.springframework.context.support.GenericXmlApplicationContext;
54  import org.springframework.core.env.ConfigurableEnvironment;
55  import org.springframework.core.env.EnumerablePropertySource;
56  import org.springframework.core.env.Environment;
57  import org.springframework.core.env.MutablePropertySources;
58  import org.springframework.core.env.PropertiesPropertySource;
59  import org.springframework.core.env.PropertySource;
60  
61  public class SpringUtils {
62  
63  	private static final Logger logger = LoggerFactory.getLogger(SpringUtils.class);
64  
65  	private static final String GLOBAL_SPRING_PROPERTY_SOURCE_NAME = "springPropertySource";
66  
67  	@Deprecated
68  	public static org.kuali.common.util.service.SpringContext getSpringContext(List<Class<?>> annotatedClasses, org.kuali.common.util.ProjectContext project,
69  			List<org.kuali.common.util.ProjectContext> others) {
70  		// This PropertySource object is backed by a set of properties that has been
71  		// 1 - fully resolved
72  		// 2 - contains all properties needed by Spring
73  		// 3 - contains system/environment properties where system/env properties override loaded properties
74  		PropertySource<?> source = getGlobalPropertySource(project, others);
75  
76  		// Setup a property source context such that our single property source is the only one registered with Spring
77  		// This will make it so our PropertySource is the ONLY thing used to resolve placeholders
78  		org.kuali.common.util.service.PropertySourceContext psc = new org.kuali.common.util.service.PropertySourceContext(source, true);
79  
80  		// Setup a Spring context
81  		org.kuali.common.util.service.SpringContext context = new org.kuali.common.util.service.SpringContext();
82  
83  		// Supply Spring with our PropertySource
84  		context.setPropertySourceContext(psc);
85  
86  		// Supply Spring with java classes containing annotated config
87  		context.setAnnotatedClasses(annotatedClasses);
88  
89  		// Return a Spring context configured with a single property source
90  		return context;
91  	}
92  
93  	@Deprecated
94  	public static org.kuali.common.util.service.SpringContext getSpringContext(Class<?> annotatedClass, org.kuali.common.util.ProjectContext project,
95  			List<org.kuali.common.util.ProjectContext> others) {
96  		return getSpringContext(CollectionUtils.asList(annotatedClass), project, others);
97  	}
98  
99  	/**
100 	 * 
101 	 */
102 	@Deprecated
103 	public static PropertySource<?> getGlobalPropertySource(org.kuali.common.util.ProjectContext project, org.kuali.common.util.ProjectContext other) {
104 		return getGlobalPropertySource(project, Arrays.asList(other));
105 	}
106 
107 	/**
108 	 * 
109 	 */
110 	@Deprecated
111 	public static PropertySource<?> getGlobalPropertySource(org.kuali.common.util.ProjectContext project, List<org.kuali.common.util.ProjectContext> others) {
112 		return getGlobalPropertySource(project, others, null);
113 	}
114 
115 	/**
116 	 * 
117 	 */
118 	@Deprecated
119 	public static PropertySource<?> getGlobalPropertySource(org.kuali.common.util.ProjectContext project, Mode missingLocationsMode) {
120 		return getGlobalPropertySource(project, missingLocationsMode, Collections.<org.kuali.common.util.ProjectContext> emptyList());
121 	}
122 
123 	/**
124 	 * 
125 	 */
126 	@Deprecated
127 	public static PropertySource<?> getGlobalPropertySource(org.kuali.common.util.ProjectContext project, Mode missingLocationsMode, org.kuali.common.util.ProjectContext... others) {
128 		return getGlobalPropertySource(project, missingLocationsMode, Arrays.asList(others));
129 	}
130 
131 	/**
132 	 * 
133 	 */
134 	@Deprecated
135 	public static PropertySource<?> getGlobalPropertySource(org.kuali.common.util.ProjectContext project, Mode missingLocationsMode,
136 			List<org.kuali.common.util.ProjectContext> others) {
137 		org.kuali.common.util.property.ProjectProperties pp = ConfigUtils.getProjectProperties(project);
138 		pp.getPropertiesContext().setMissingLocationsMode(missingLocationsMode);
139 		return getGlobalPropertySource(pp, others, null);
140 	}
141 
142 	@Deprecated
143 	public static PropertySource<?> getGlobalPropertySource(org.kuali.common.util.property.ProjectProperties projectProperties, List<org.kuali.common.util.ProjectContext> others,
144 			Properties properties) {
145 		ConfigUtils.combine(projectProperties, properties);
146 		List<org.kuali.common.util.property.ProjectProperties> otherProjectProperties = ConfigUtils.getProjectProperties(others);
147 		// Get a PropertySource object backed by the properties loaded from the list as well as system/environment properties
148 		return getGlobalPropertySource(projectProperties, otherProjectProperties);
149 	}
150 
151 	/**
152 	 * <code>project</code> needs to be a top level project eg rice-sampleapp, olefs-webapp. <code>others</code> is projects for submodules organized into a list where the last one
153 	 * in wins.
154 	 */
155 	@Deprecated
156 	public static PropertySource<?> getGlobalPropertySource(org.kuali.common.util.ProjectContext project, List<org.kuali.common.util.ProjectContext> others, Properties properties) {
157 
158 		org.kuali.common.util.property.ProjectProperties projectProperties = ConfigUtils.getProjectProperties(project, properties);
159 
160 		List<org.kuali.common.util.property.ProjectProperties> otherProjectProperties = ConfigUtils.getProjectProperties(others);
161 
162 		// Get a PropertySource object backed by the properties loaded from the list as well as system/environment properties
163 		return getGlobalPropertySource(projectProperties, otherProjectProperties);
164 	}
165 
166 	/**
167 	 * <code>project</code> needs to be a top level project eg rice-sampleapp, olefs-webapp. <code>others</code> is projects for submodules organized into a list where the last one
168 	 * in wins.
169 	 */
170 	@Deprecated
171 	public static PropertySource<?> getGlobalPropertySource(org.kuali.common.util.property.ProjectProperties project) {
172 		return getGlobalPropertySource(project, null);
173 	}
174 
175 	/**
176 	 * <code>project</code> needs to be a top level project eg rice-sampleapp, olefs-webapp. <code>others</code> is projects for submodules organized into a list where the last one
177 	 * in wins.
178 	 */
179 	@Deprecated
180 	public static PropertySource<?> getGlobalPropertySource(org.kuali.common.util.property.ProjectProperties project, List<org.kuali.common.util.property.ProjectProperties> others) {
181 		// Property loading uses a "last one in wins" strategy
182 		List<org.kuali.common.util.property.ProjectProperties> list = new ArrayList<org.kuali.common.util.property.ProjectProperties>();
183 
184 		// Add project properties first so they can be used to resolve locations
185 		list.add(project);
186 
187 		if (!CollectionUtils.isEmpty(others)) {
188 			// Load in other project properties
189 			list.addAll(others);
190 
191 			// Add project properties last so they override loaded properties
192 			list.add(project);
193 		}
194 
195 		// Get a PropertySource object backed by the properties loaded from the list as well as system/environment properties
196 		return getGlobalPropertySource(GLOBAL_SPRING_PROPERTY_SOURCE_NAME, list);
197 	}
198 
199 	public static List<String> getIncludes(Environment env, String key, String defaultValue) {
200 		String includes = SpringUtils.getProperty(env, key, defaultValue);
201 		if (NullUtils.isNull(includes) || StringUtils.equals(includes, Constants.WILDCARD)) {
202 			return new ArrayList<String>();
203 		} else {
204 			return CollectionUtils.getTrimmedListFromCSV(includes);
205 		}
206 	}
207 
208 	public static List<String> getIncludes(Environment env, String key) {
209 		return getIncludes(env, key, null);
210 	}
211 
212 	public static List<String> getExcludes(Environment env, String key, String defaultValue) {
213 		String excludes = SpringUtils.getProperty(env, key, defaultValue);
214 		if (NullUtils.isNullOrNone(excludes)) {
215 			return new ArrayList<String>();
216 		} else {
217 			return CollectionUtils.getTrimmedListFromCSV(excludes);
218 		}
219 	}
220 
221 	public static List<String> getExcludes(Environment env, String key) {
222 		return getExcludes(env, key, null);
223 	}
224 
225 	/**
226 	 * Given a property holding the name of a class, return an instance of that class
227 	 */
228 	public static <T> T getInstance(Environment env, String key, Class<T> defaultValue) {
229 		String className = getProperty(env, key, defaultValue.getCanonicalName());
230 		return ReflectionUtils.newInstance(className);
231 	}
232 
233 	/**
234 	 * Given a property holding the name of a class, return an instance of that class
235 	 */
236 	public static <T> T getInstance(Environment env, String key) {
237 		String className = getProperty(env, key, null);
238 		return ReflectionUtils.newInstance(className);
239 	}
240 
241 	public static List<String> getListFromCSV(Environment env, String key, String defaultValue) {
242 		String csv = SpringUtils.getProperty(env, key, defaultValue);
243 		return CollectionUtils.getTrimmedListFromCSV(csv);
244 	}
245 
246 	public static List<String> getListFromCSV(Environment env, String key) {
247 		String csv = SpringUtils.getProperty(env, key);
248 		return CollectionUtils.getTrimmedListFromCSV(csv);
249 	}
250 
251 	/**
252 	 * If the CSV value evaluates to <code>null</code>, <code>"null"</code>, <code>"none"</code> or the empty string, return an empty list.
253 	 */
254 	public static List<String> getNoneSensitiveListFromCSV(Environment env, String key) {
255 		String csv = SpringUtils.getProperty(env, key);
256 		return CollectionUtils.getNoneSensitiveListFromCSV(csv);
257 	}
258 
259 	/**
260 	 * If the CSV value evaluates to <code>null</code>, <code>"null"</code>, <code>"none"</code> or the empty string, return an empty list.
261 	 */
262 	public static List<String> getNoneSensitiveListFromCSV(Environment env, String key, String defaultValue) {
263 		String csv = SpringUtils.getProperty(env, key, defaultValue);
264 		return CollectionUtils.getNoneSensitiveListFromCSV(csv);
265 	}
266 
267 	@Deprecated
268 	public static List<PropertySource<?>> getPropertySources(org.kuali.common.util.service.SpringService service, Class<?> annotatedClass, String propertiesBeanName,
269 			Properties properties) {
270 		return getPropertySources(annotatedClass, propertiesBeanName, properties);
271 	}
272 
273 	/**
274 	 * Scan the annotated class to find the single bean registered in the context that implements <code>PropertySource</code>. If more than one bean is located, throw
275 	 * <code>IllegalStateException</code>.
276 	 */
277 	public static PropertySource<?> getSinglePropertySource(Class<?> annotatedClass) {
278 		return getSinglePropertySource(annotatedClass, null, null);
279 	}
280 
281 	/**
282 	 * Scan the annotated class to find the single bean registered in the context that implements <code>PropertySource</code>. If more than one bean is located, throw
283 	 * <code>IllegalStateException</code>.
284 	 */
285 	public static PropertySource<?> getSinglePropertySource(Class<?> annotatedClass, String propertiesBeanName, Properties properties) {
286 		List<PropertySource<?>> sources = getPropertySources(annotatedClass, propertiesBeanName, properties);
287 		if (sources.size() > 1) {
288 			throw new IllegalStateException("More than one PropertySource was registered in the context");
289 		} else {
290 			return sources.get(0);
291 		}
292 	}
293 
294 	public static List<PropertySource<?>> getPropertySources(Class<?> annotatedClass, String propertiesBeanName, Properties properties) {
295 		return getPropertySources(annotatedClass, propertiesBeanName, properties, null, null);
296 	}
297 
298 	public static void setupProfiles(ConfigurableApplicationContext ctx, List<String> activeProfiles, List<String> defaultProfiles) {
299 		if (!CollectionUtils.isEmpty(activeProfiles)) {
300 			ConfigurableEnvironment env = ctx.getEnvironment();
301 			env.setActiveProfiles(CollectionUtils.toStringArray(activeProfiles));
302 		}
303 		if (!CollectionUtils.isEmpty(defaultProfiles)) {
304 			ConfigurableEnvironment env = ctx.getEnvironment();
305 			env.setDefaultProfiles(CollectionUtils.toStringArray(defaultProfiles));
306 		}
307 	}
308 
309 	public static List<PropertySource<?>> getPropertySources(Class<?> annotatedClass, String propertiesBeanName, Properties properties, List<String> activeProfiles,
310 			List<String> defaultProfiles) {
311 		ConfigurableApplicationContext parent = null;
312 		if (properties == null) {
313 			parent = getConfigurableApplicationContext();
314 		} else {
315 			parent = getContextWithPreRegisteredBean(propertiesBeanName, properties);
316 		}
317 		AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
318 		child.setParent(parent);
319 		setupProfiles(child, activeProfiles, defaultProfiles);
320 		child.register(annotatedClass);
321 		child.refresh();
322 		return getPropertySources(child);
323 	}
324 
325 	@Deprecated
326 	public static List<PropertySource<?>> getPropertySources(org.kuali.common.util.service.SpringService service, String location, String mavenPropertiesBeanName,
327 			Properties mavenProperties) {
328 		return getPropertySources(location, mavenPropertiesBeanName, mavenProperties);
329 	}
330 
331 	public static List<PropertySource<?>> getPropertySources(String location, String propertiesBeanName, Properties properties) {
332 		return getPropertySources(location, propertiesBeanName, properties, null, null);
333 	}
334 
335 	public static List<PropertySource<?>> getPropertySources(String location, String propertiesBeanName, Properties properties, List<String> activeProfiles,
336 			List<String> defaultProfiles) {
337 		String[] locationsArray = { location };
338 		ConfigurableApplicationContext parent = getContextWithPreRegisteredBean(propertiesBeanName, properties);
339 		ConfigurableApplicationContext child = new ClassPathXmlApplicationContext(locationsArray, false, parent);
340 		setupProfiles(child, activeProfiles, defaultProfiles);
341 		child.refresh();
342 		return getPropertySources(child);
343 	}
344 
345 	@Deprecated
346 	public static Executable getSpringExecutable(Environment env, boolean skip, PropertySource<?> ps, List<Class<?>> annotatedClasses) {
347 		/**
348 		 * This line creates a property source containing 100% of the properties needed by Spring to resolve any/all placeholders. It will be the only property source available to
349 		 * Spring so it needs to include system properties and environment variables
350 		 */
351 		org.kuali.common.util.service.PropertySourceContext psc = new org.kuali.common.util.service.PropertySourceContext(ps, true);
352 
353 		// Setup the Spring context
354 		org.kuali.common.util.service.SpringContext context = new org.kuali.common.util.service.SpringContext();
355 		context.setAnnotatedClasses(annotatedClasses);
356 		context.setPropertySourceContext(psc);
357 
358 		// Load the context
359 		org.kuali.common.util.execute.SpringExecutable se = new org.kuali.common.util.execute.SpringExecutable();
360 		se.setService(new org.kuali.common.util.service.DefaultSpringService());
361 		se.setContext(context);
362 		se.setSkip(skip);
363 		return se;
364 	}
365 
366 	public static int getInteger(Environment env, String key) {
367 		String value = getProperty(env, key);
368 		return Integer.parseInt(value);
369 	}
370 
371 	public static int getInteger(Environment env, String key, int defaultValue) {
372 		String value = getProperty(env, key, Integer.toString(defaultValue));
373 		return Integer.parseInt(value);
374 	}
375 
376 	public static long getLong(Environment env, String key) {
377 		String value = getProperty(env, key);
378 		return Long.parseLong(value);
379 	}
380 
381 	public static long getLong(Environment env, String key, long defaultValue) {
382 		String value = getProperty(env, key, Long.toString(defaultValue));
383 		return Long.parseLong(value);
384 	}
385 
386 	public static double getDouble(Environment env, String key) {
387 		String value = getProperty(env, key);
388 		return Double.parseDouble(value);
389 	}
390 
391 	public static double getDouble(Environment env, String key, double defaultValue) {
392 		String value = getProperty(env, key, Double.toString(defaultValue));
393 		return Double.parseDouble(value);
394 	}
395 
396 	/**
397 	 * Parse milliseconds from a time string that ends with a unit of measure. If no unit of measure is provided, milliseconds is assumed. Unit of measure is case insensitive.
398 	 * 
399 	 * @see FormatUtils.getMillis(String time)
400 	 */
401 	public static long getMillis(Environment env, String key, String defaultValue) {
402 		String value = getProperty(env, key, defaultValue);
403 		return FormatUtils.getMillis(value);
404 	}
405 
406 	/**
407 	 * Parse bytes from a size string that ends with a unit of measure. If no unit of measure is provided, bytes is assumed. Unit of measure is case insensitive.
408 	 * 
409 	 * @see FormatUtils.getBytes(String size)
410 	 */
411 	public static int getBytesInteger(Environment env, String key, String defaultValue) {
412 		Long value = getBytes(env, key, defaultValue);
413 		return getValidatedIntValue(value);
414 	}
415 
416 	/**
417 	 * Parse bytes from a size string that ends with a unit of measure. If no unit of measure is provided, bytes is assumed. Unit of measure is case insensitive.
418 	 * 
419 	 * @see FormatUtils.getBytes(String size)
420 	 */
421 	public static int getBytesInteger(Environment env, String key) {
422 		Long value = getBytes(env, key);
423 		return getValidatedIntValue(value);
424 	}
425 
426 	/**
427 	 * Throw IllegalArgumentException if value is outside the range of an Integer, otherwise return the Integer value.
428 	 */
429 	public static int getValidatedIntValue(Long value) {
430 		if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) {
431 			throw new IllegalArgumentException(value + " is outside the range of an integer");
432 		} else {
433 			return value.intValue();
434 		}
435 	}
436 
437 	/**
438 	 * Parse bytes from a size string that ends with a unit of measure. If no unit of measure is provided, bytes is assumed. Unit of measure is case insensitive.
439 	 * 
440 	 * @see FormatUtils.getBytes(String size)
441 	 */
442 	public static long getBytes(Environment env, String key, String defaultValue) {
443 		String value = getProperty(env, key, defaultValue);
444 		return FormatUtils.getBytes(value);
445 	}
446 
447 	/**
448 	 * Parse bytes from a size string that ends with a unit of measure. If no unit of measure is provided, bytes is assumed. Unit of measure is case insensitive.
449 	 * 
450 	 * @see FormatUtils.getBytes(String size)
451 	 */
452 	public static long getBytes(Environment env, String key) {
453 		String value = getProperty(env, key);
454 		return FormatUtils.getBytes(value);
455 	}
456 
457 	public static File getFile(Environment env, String key) {
458 		String value = getProperty(env, key);
459 		return new File(value);
460 	}
461 
462 	public static List<File> getFilesFromCSV(Environment env, String key, String defaultValue) {
463 		List<String> strings = getNoneSensitiveListFromCSV(env, key, defaultValue);
464 		List<File> files = new ArrayList<File>();
465 		for (String string : strings) {
466 			File file = new File(string);
467 			files.add(file);
468 		}
469 		return files;
470 	}
471 
472 	public static List<File> getFilesFromCSV(Environment env, String key) {
473 		return getFilesFromCSV(env, key, null);
474 	}
475 
476 	public static File getFile(Environment env, String key, File defaultValue) {
477 		String value = getProperty(env, key, LocationUtils.getCanonicalPath(defaultValue));
478 		return new File(value);
479 	}
480 
481 	public static boolean getBoolean(Environment env, String key, boolean defaultValue) {
482 		String value = getProperty(env, key, Boolean.toString(defaultValue));
483 		return Boolean.parseBoolean(value);
484 	}
485 
486 	public static boolean getBoolean(Environment env, String key) {
487 		String value = getProperty(env, key);
488 		return Boolean.parseBoolean(value);
489 	}
490 
491 	@Deprecated
492 	public static PropertySource<?> getGlobalPropertySource(String name, List<org.kuali.common.util.property.ProjectProperties> pps) {
493 		// Load them from disk
494 		Properties source = PropertyUtils.load(pps);
495 
496 		// Add in system/environment properties
497 		Properties globalSource = PropertyUtils.getGlobalProperties(source);
498 
499 		logger.debug("Before prepareContextProperties()");
500 		PropertyUtils.debug(globalSource);
501 
502 		// Prepare them so they are ready for use
503 		PropertyUtils.prepareContextProperties(globalSource);
504 
505 		logger.debug("After prepareContextProperties()");
506 		PropertyUtils.debug(globalSource);
507 
508 		// Return a PropertySource backed by the properties
509 		return new PropertiesPropertySource(name, globalSource);
510 	}
511 
512 	public static PropertySource<?> getGlobalPropertySource(Properties properties) {
513 		return new PropertiesPropertySource(GLOBAL_SPRING_PROPERTY_SOURCE_NAME, properties);
514 	}
515 
516 	/**
517 	 * Return a SpringContext that resolves all placeholders from the PropertySource passed in
518 	 */
519 	public static PropertySource<?> getGlobalPropertySource(List<String> locations, String encoding) {
520 		Properties loaded = PropertyUtils.load(locations, encoding);
521 		Properties global = PropertyUtils.getGlobalProperties(loaded);
522 		PropertyUtils.prepareContextProperties(global);
523 		return getGlobalPropertySource(global);
524 	}
525 
526 	/**
527 	 * Return a SpringContext that resolves all placeholders from the list of property locations passed in + System/Environment properties
528 	 */
529 	@Deprecated
530 	public static org.kuali.common.util.service.SpringContext getSinglePropertySourceContext(org.kuali.common.util.ProjectContext context, String location) {
531 		PropertySource<?> source = getGlobalPropertySource(context, location);
532 		return getSinglePropertySourceContext(source);
533 	}
534 
535 	/**
536 	 * Return a SpringExecutable for the project, properties location, and config passed in.
537 	 */
538 	@Deprecated
539 	public static org.kuali.common.util.execute.SpringExecutable getSpringExecutable(org.kuali.common.util.ProjectContext project, String location, List<Class<?>> annotatedClasses) {
540 		org.kuali.common.util.service.SpringContext context = getSinglePropertySourceContext(project, location);
541 		context.setAnnotatedClasses(annotatedClasses);
542 
543 		org.kuali.common.util.execute.SpringExecutable executable = new org.kuali.common.util.execute.SpringExecutable();
544 		executable.setContext(context);
545 		return executable;
546 	}
547 
548 	/**
549 	 * Return a SpringExecutable for the PropertiesSupplier and annotatedClass passed in
550 	 */
551 	@Deprecated
552 	public static org.kuali.common.util.execute.SpringExecutable getSpringExecutable(PropertiesSupplier supplier, Class<?> annotatedClass) {
553 		return getSpringExecutable(supplier, CollectionUtils.asList(annotatedClass));
554 	}
555 
556 	/**
557 	 * Return a SpringExecutable for the PropertiesSupplier and annotatedClasses passed in
558 	 */
559 	@Deprecated
560 	public static org.kuali.common.util.execute.SpringExecutable getSpringExecutable(PropertiesSupplier supplier, List<Class<?>> annotatedClasses) {
561 		Properties properties = supplier.getProperties();
562 		PropertySource<?> source = getGlobalPropertySource(properties);
563 		org.kuali.common.util.service.SpringContext context = getSinglePropertySourceContext(source);
564 		context.setAnnotatedClasses(annotatedClasses);
565 		return new org.kuali.common.util.execute.SpringExecutable(context);
566 	}
567 
568 	/**
569 	 * Return a SpringExecutable for the PropertySource and annotatedClass passed in
570 	 */
571 	@Deprecated
572 	public static org.kuali.common.util.execute.SpringExecutable getSpringExecutable(PropertySource<?> source, Class<?> annotatedClass) {
573 		org.kuali.common.util.service.SpringContext context = getSinglePropertySourceContext(source);
574 		context.setAnnotatedClasses(CollectionUtils.asList(annotatedClass));
575 		return new org.kuali.common.util.execute.SpringExecutable(context);
576 	}
577 
578 	/**
579 	 * Return a SpringExecutable for the project, properties location, and config passed in.
580 	 */
581 	@Deprecated
582 	public static org.kuali.common.util.execute.SpringExecutable getSpringExecutable(org.kuali.common.util.ProjectContext project, String location, Class<?> annotatedClass) {
583 		return getSpringExecutable(project, location, CollectionUtils.asList(annotatedClass));
584 	}
585 
586 	/**
587 	 * Return a SpringExecutable for the project, properties location, and config passed in.
588 	 */
589 	@Deprecated
590 	public static org.kuali.common.util.execute.SpringExecutable getSpringExecutable(Class<?> annotatedClass, String location, org.kuali.common.util.ProjectContext... projects) {
591 		List<org.kuali.common.util.property.ProjectProperties> list = ConfigUtils.getProjectProperties(projects);
592 		org.kuali.common.util.property.ProjectProperties last = list.get(list.size() - 1);
593 		PropertiesContext pc = last.getPropertiesContext();
594 		if (!StringUtils.isBlank(location)) {
595 			List<String> locations = new ArrayList<String>(CollectionUtils.toEmptyList(pc.getLocations()));
596 			locations.add(location);
597 			pc.setLocations(locations);
598 		}
599 		PropertySource<?> source = getGlobalPropertySource(GLOBAL_SPRING_PROPERTY_SOURCE_NAME, list);
600 		org.kuali.common.util.service.SpringContext context = getSinglePropertySourceContext(source);
601 		context.setAnnotatedClasses(CollectionUtils.asList(annotatedClass));
602 		return new org.kuali.common.util.execute.SpringExecutable(context);
603 	}
604 
605 	/**
606 	 * Return a SpringContext that resolves all placeholders from the list of property locations passed in + System/Environment properties
607 	 */
608 	@Deprecated
609 	public static org.kuali.common.util.service.SpringContext getSinglePropertySourceContext(List<String> locations, String encoding) {
610 		PropertySource<?> source = getGlobalPropertySource(locations, encoding);
611 		return getSinglePropertySourceContext(source);
612 	}
613 
614 	/**
615 	 * Return a SpringContext that resolves all placeholders from the PropertySource passed in
616 	 */
617 	@Deprecated
618 	public static org.kuali.common.util.service.SpringContext getSinglePropertySourceContext(PropertySource<?> source) {
619 		// Setup a property source context such that our single property source is the only one registered with Spring
620 		// This will make it so our PropertySource is the ONLY thing used to resolve placeholders
621 		org.kuali.common.util.service.PropertySourceContext psc = new org.kuali.common.util.service.PropertySourceContext(source, true);
622 
623 		// Setup a Spring context
624 		org.kuali.common.util.service.SpringContext context = new org.kuali.common.util.service.SpringContext();
625 
626 		// Supply Spring with our PropertySource
627 		context.setPropertySourceContext(psc);
628 
629 		// Return a Spring context configured with a single property source
630 		return context;
631 	}
632 
633 	@Deprecated
634 	public static PropertySource<?> getGlobalPropertySource(org.kuali.common.util.ProjectContext context, String... locations) {
635 		org.kuali.common.util.property.ProjectProperties pp = ProjectUtils.getProjectProperties(context);
636 		PropertiesContext pc = pp.getPropertiesContext();
637 		List<String> existingLocations = CollectionUtils.toEmptyList(pc.getLocations());
638 		if (locations != null) {
639 			for (String location : locations) {
640 				existingLocations.add(location);
641 			}
642 		}
643 		pc.setLocations(existingLocations);
644 		return getGlobalPropertySource(pp);
645 	}
646 
647 	@Deprecated
648 	public static PropertySource<?> getPropertySource(String name, List<org.kuali.common.util.property.ProjectProperties> pps) {
649 		// Load them from disk
650 		Properties source = PropertyUtils.load(pps);
651 
652 		// Prepare them so they are ready for use
653 		PropertyUtils.prepareContextProperties(source);
654 
655 		// Return a PropertySource backed by the properties
656 		return new PropertiesPropertySource(name, source);
657 	}
658 
659 	/**
660 	 * Converts a GAV into Spring's classpath style notation for the default project properties context.
661 	 * 
662 	 * <pre>
663 	 *  org.kuali.common:kuali-jdbc -> classpath:org/kuali/common/kuali-jdbc/properties-context.xml
664 	 * </pre>
665 	 */
666 	@Deprecated
667 	public static String getDefaultPropertyContextLocation(String gav) {
668 		Assert.hasText(gav, "gav has no text");
669 		Project p = ProjectUtils.getProject(gav);
670 		return ProjectUtils.getClassPathPrefix(p) + "/properties-context.xml";
671 	}
672 
673 	/**
674 	 * Make sure all of the locations actually exist
675 	 */
676 	public static void validateExists(List<String> locations) {
677 		StringBuilder sb = new StringBuilder();
678 		for (String location : locations) {
679 			if (!LocationUtils.exists(location)) {
680 				sb.append("Location [" + location + "] does not exist\n");
681 			}
682 		}
683 		if (sb.length() > 0) {
684 			throw new IllegalArgumentException(sb.toString());
685 		}
686 	}
687 
688 	public static ConfigurableApplicationContext getContextWithPreRegisteredBeans(String id, String displayName, List<String> beanNames, List<Object> beans) {
689 		Assert.isTrue(beanNames.size() == beans.size());
690 		GenericXmlApplicationContext appContext = new GenericXmlApplicationContext();
691 		if (!StringUtils.isBlank(id)) {
692 			appContext.setId(id);
693 		}
694 		if (!StringUtils.isBlank(displayName)) {
695 			appContext.setDisplayName(displayName);
696 		}
697 		appContext.refresh();
698 		ConfigurableListableBeanFactory factory = appContext.getBeanFactory();
699 		for (int i = 0; i < beanNames.size(); i++) {
700 			String beanName = beanNames.get(i);
701 			Object bean = beans.get(i);
702 			logger.debug("Registering bean - [{}] -> [{}]", beanName, bean.getClass().getName());
703 			factory.registerSingleton(beanName, bean);
704 		}
705 		return appContext;
706 	}
707 
708 	public static ConfigurableApplicationContext getConfigurableApplicationContext() {
709 		return new GenericXmlApplicationContext();
710 	}
711 
712 	public static ConfigurableApplicationContext getContextWithPreRegisteredBeans(List<String> beanNames, List<Object> beans) {
713 		return getContextWithPreRegisteredBeans(null, null, beanNames, beans);
714 	}
715 
716 	/**
717 	 * Null safe refresh for a context
718 	 */
719 	public static void refreshQuietly(ConfigurableApplicationContext context) {
720 		if (context != null) {
721 			context.refresh();
722 		}
723 	}
724 
725 	/**
726 	 * Null safe close for a context
727 	 */
728 	public static void closeQuietly(ConfigurableApplicationContext context) {
729 		if (context != null) {
730 			context.close();
731 		}
732 	}
733 
734 	public static ConfigurableApplicationContext getContextWithPreRegisteredBean(String beanName, Object bean) {
735 		return getContextWithPreRegisteredBeans(Arrays.asList(beanName), Arrays.asList(bean));
736 	}
737 
738 	public static List<PropertySource<?>> getPropertySourcesFromAnnotatedClass(String annotatedClassName) {
739 		Class<?> annotatedClass = ReflectionUtils.getClass(annotatedClassName);
740 		return getPropertySources(annotatedClass);
741 	}
742 
743 	public static List<PropertySource<?>> getPropertySources(Class<?> annotatedClass) {
744 		ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(annotatedClass);
745 		return extractPropertySourcesAndClose(context);
746 	}
747 
748 	public static List<PropertySource<?>> extractPropertySourcesAndClose(ConfigurableApplicationContext context) {
749 		// Extract PropertySources (if any)
750 		List<PropertySource<?>> sources = getPropertySources(context);
751 
752 		// Close the context
753 		closeQuietly(context);
754 
755 		// Return the list
756 		return sources;
757 	}
758 
759 	/**
760 	 * Scan the XML Spring context for any beans that implement <code>PropertySource</code>
761 	 */
762 	public static List<PropertySource<?>> getPropertySources(String location) {
763 		ConfigurableApplicationContext context = new GenericXmlApplicationContext(location);
764 		return extractPropertySourcesAndClose(context);
765 	}
766 
767 	/**
768 	 * This method returns a list of any PropertySource objects registered in the indicated context. They are sorted by property source name.
769 	 */
770 	public static List<PropertySource<?>> getPropertySources(ConfigurableApplicationContext context) {
771 		// Sort them by name
772 		return getPropertySources(context, new PropertySourceNameComparator());
773 	}
774 
775 	public static <T> Map<String, T> getAllBeans(List<String> locations, Class<T> type) {
776 		String[] locationsArray = locations.toArray(new String[locations.size()]);
777 		ConfigurableApplicationContext ctx = new GenericXmlApplicationContext(locationsArray);
778 		Map<String, T> map = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, type);
779 		ctx.close();
780 		return map;
781 	}
782 
783 	public static <T> Map<String, T> getAllBeans(String location, Class<T> type) {
784 		ConfigurableApplicationContext ctx = new GenericXmlApplicationContext(location);
785 		Map<String, T> map = BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, type);
786 		ctx.close();
787 		return map;
788 	}
789 
790 	public static <T> Map<String, T> getAllBeans(ConfigurableApplicationContext ctx, Class<T> type) {
791 		return BeanFactoryUtils.beansOfTypeIncludingAncestors(ctx, type);
792 	}
793 
794 	/**
795 	 * This method returns a list of any PropertySource objects registered in the indicated context. The comparator is responsible for putting them in correct order.
796 	 */
797 	public static List<PropertySource<?>> getPropertySources(ConfigurableApplicationContext context, Comparator<PropertySource<?>> comparator) {
798 		// Extract all beans that implement the PropertySource interface
799 		@SuppressWarnings("rawtypes")
800 		Map<String, PropertySource> map = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, PropertySource.class);
801 
802 		// Extract the PropertySource beans into a list
803 		List<PropertySource<?>> list = new ArrayList<PropertySource<?>>();
804 		for (PropertySource<?> source : map.values()) {
805 			list.add(source);
806 		}
807 
808 		// Sort them using the provided comparator
809 		Collections.sort(list, comparator);
810 
811 		// Return the list
812 		return list;
813 	}
814 
815 	/**
816 	 * Null safe method for converting an untyped array of property sources into a list. Never returns null.
817 	 */
818 	public static List<PropertySource<?>> asList(PropertySource<?>... sources) {
819 		List<PropertySource<?>> list = new ArrayList<PropertySource<?>>();
820 		if (sources == null) {
821 			return list;
822 		}
823 		for (PropertySource<?> element : sources) {
824 			if (element != null) {
825 				list.add(element);
826 			}
827 		}
828 		return list;
829 	}
830 
831 	public static void debug(ApplicationContext ctx) {
832 		logger.debug("------------------------ Spring Context ------------------------------");
833 		logger.debug("Id: [{}]", ctx.getId());
834 		logger.debug("Display Name: [{}]", ctx.getDisplayName());
835 		logger.debug("Application Name: [{}]", ctx.getApplicationName());
836 		logger.debug("----------------------------------------------------------------------");
837 		List<String> names = Arrays.asList(BeanFactoryUtils.beanNamesIncludingAncestors(ctx));
838 		List<String> columns = Arrays.asList("Name", "Type", "Hashcode");
839 		List<Object[]> rows = new ArrayList<Object[]>();
840 		Collections.sort(names);
841 		for (String name : names) {
842 			Object bean = ctx.getBean(name);
843 			String instance = (bean == null) ? Constants.NULL : bean.getClass().getSimpleName();
844 			String hashcode = (bean == null) ? Constants.NULL : Integer.toHexString(bean.hashCode());
845 			Object[] row = { name, instance, hashcode };
846 			rows.add(row);
847 		}
848 		LoggerUtils.logTable(columns, rows, LoggerLevel.DEBUG, logger, true);
849 		logger.debug("----------------------------------------------------------------------");
850 	}
851 
852 	public static void showPropertySources(List<PropertySource<?>> propertySources) {
853 		List<String> columns = Arrays.asList("Name", "Impl", "Source");
854 		List<Object[]> rows = new ArrayList<Object[]>();
855 		for (PropertySource<?> propertySource : propertySources) {
856 			String name = propertySource.getName();
857 			String impl = propertySource.getClass().getName();
858 			String source = propertySource.getSource().getClass().getName();
859 			Object[] row = { name, impl, source };
860 			rows.add(row);
861 		}
862 		LoggerUtils.logTable(columns, rows, LoggerLevel.INFO, logger, true);
863 	}
864 
865 	public static void showPropertySources(ConfigurableEnvironment env) {
866 		showPropertySources(getPropertySources(env));
867 	}
868 
869 	/**
870 	 * Get a fully resolved property value from the environment. If the property is not found or contains unresolvable placeholders an exception is thrown.
871 	 */
872 	public static String getProperty(Environment env, String key) {
873 		String value = env.getRequiredProperty(key);
874 		return env.resolveRequiredPlaceholders(value);
875 	}
876 
877 	/**
878 	 * Return true if the environment value for key is not null.
879 	 */
880 	public static boolean exists(Environment env, String key) {
881 		return env.getProperty(key) != null;
882 	}
883 
884 	/**
885 	 * Always return a fully resolved value. Use <code>defaultValue</code> if a value cannot be located in the environment. Throw an exception if the return value contains
886 	 * unresolvable placeholders.
887 	 */
888 	public static String getProperty(Environment env, String key, String defaultValue) {
889 		if (defaultValue == null) {
890 			// No default value supplied, we must be able to locate this property in the environment
891 			return getProperty(env, key);
892 		} else {
893 			// Look up a value from the environment
894 			String value = env.getProperty(key);
895 			if (value == null) {
896 				// Resolve the default value against the environment
897 				return env.resolveRequiredPlaceholders(defaultValue);
898 			} else {
899 				// Resolve the located value against the environment
900 				return env.resolveRequiredPlaceholders(value);
901 			}
902 		}
903 	}
904 
905 	/**
906 	 * Examine <code>ConfigurableEnvironment</code> for <code>PropertySource</code>'s that extend <code>EnumerablePropertySource</code> and aggregate them into a single
907 	 * <code>Properties</code> object
908 	 */
909 	public static Properties getAllEnumerableProperties(ConfigurableEnvironment env) {
910 
911 		// Extract the list of PropertySources from the environment
912 		List<PropertySource<?>> sources = getPropertySources(env);
913 
914 		// Spring provides PropertySource objects ordered from highest priority to lowest priority
915 		// We reverse the order here so things follow the typical "last one in wins" strategy
916 		Collections.reverse(sources);
917 
918 		// Convert the list of PropertySource's to a list of Properties objects
919 		PropertySourceConversionResult result = convertEnumerablePropertySources(sources);
920 
921 		// Combine them into a single Properties object
922 		return PropertyUtils.combine(result.getPropertiesList());
923 	}
924 
925 	/**
926 	 * Remove any existing property sources and add one property source backed by the properties passed in
927 	 */
928 	public static void reconfigurePropertySources(ConfigurableEnvironment env, String name, Properties properties) {
929 		// Remove all existing property sources
930 		removeAllPropertySources(env);
931 
932 		// MutablePropertySources allow us to manipulate the list of property sources
933 		MutablePropertySources mps = env.getPropertySources();
934 
935 		// Make sure there are no existing property sources
936 		Assert.isTrue(mps.size() == 0);
937 
938 		// Create a property source backed by the properties object passed in
939 		PropertiesPropertySource pps = new PropertiesPropertySource(name, properties);
940 
941 		// Add it to the environment
942 		mps.addFirst(pps);
943 	}
944 
945 	/**
946 	 * Remove any existing property sources
947 	 */
948 	public static void removeAllPropertySources(ConfigurableEnvironment env) {
949 		MutablePropertySources mps = env.getPropertySources();
950 		List<PropertySource<?>> sources = getPropertySources(env);
951 		for (PropertySource<?> source : sources) {
952 			String name = source.getName();
953 			mps.remove(name);
954 		}
955 	}
956 
957 	/**
958 	 * Get all PropertySource objects from the environment as a List.
959 	 */
960 	public static List<PropertySource<?>> getPropertySources(ConfigurableEnvironment env) {
961 		MutablePropertySources mps = env.getPropertySources();
962 		List<PropertySource<?>> sources = new ArrayList<PropertySource<?>>();
963 		Iterator<PropertySource<?>> itr = mps.iterator();
964 		while (itr.hasNext()) {
965 			PropertySource<?> source = itr.next();
966 			sources.add(source);
967 		}
968 		return sources;
969 	}
970 
971 	/**
972 	 * Convert any PropertySources that extend EnumerablePropertySource into Properties object's
973 	 */
974 	public static PropertySourceConversionResult convertEnumerablePropertySources(List<PropertySource<?>> sources) {
975 		PropertySourceConversionResult result = new PropertySourceConversionResult();
976 		List<Properties> list = new ArrayList<Properties>();
977 		List<PropertySource<?>> converted = new ArrayList<PropertySource<?>>();
978 		List<PropertySource<?>> skipped = new ArrayList<PropertySource<?>>();
979 		// Extract property values from the sources and place them in a Properties object
980 		for (PropertySource<?> source : sources) {
981 			logger.debug("Adding [{}]", source.getName());
982 			if (source instanceof EnumerablePropertySource) {
983 				EnumerablePropertySource<?> eps = (EnumerablePropertySource<?>) source;
984 				Properties sourceProperties = convert(eps);
985 				list.add(sourceProperties);
986 				converted.add(source);
987 			} else {
988 				logger.debug("Unable to obtain properties from property source [{}] -> [{}]", source.getName(), source.getClass().getName());
989 				skipped.add(source);
990 			}
991 		}
992 		result.setConverted(converted);
993 		result.setSkipped(skipped);
994 		result.setPropertiesList(list);
995 		return result;
996 	}
997 
998 	/**
999 	 * Convert an EnumerablePropertySource into a Properties object.
1000 	 */
1001 	public static Properties convert(EnumerablePropertySource<?> source) {
1002 		Properties properties = new Properties();
1003 		String[] names = source.getPropertyNames();
1004 		for (String name : names) {
1005 			Object object = source.getProperty(name);
1006 			if (object != null) {
1007 				String value = object.toString();
1008 				properties.setProperty(name, value);
1009 			} else {
1010 				logger.warn("Property [{}] is null", name);
1011 			}
1012 		}
1013 		return properties;
1014 	}
1015 
1016 	/**
1017 	 * Return true if, and only if, <code>property</code> is set in the environment and evaluates to true.
1018 	 */
1019 	public static boolean isTrue(Environment env, String property) {
1020 		String value = env.getProperty(property);
1021 		if (StringUtils.isBlank(value)) {
1022 			return false;
1023 		} else {
1024 			return new Boolean(value);
1025 		}
1026 	}
1027 
1028 }