001    package org.kuali.common.util.spring;
002    
003    import java.util.ArrayList;
004    import java.util.Collections;
005    import java.util.Iterator;
006    import java.util.List;
007    import java.util.Properties;
008    
009    import org.kuali.common.util.Assert;
010    import org.kuali.common.util.PropertyUtils;
011    import org.slf4j.Logger;
012    import org.slf4j.LoggerFactory;
013    import org.springframework.core.env.ConfigurableEnvironment;
014    import org.springframework.core.env.EnumerablePropertySource;
015    import org.springframework.core.env.Environment;
016    import org.springframework.core.env.MutablePropertySources;
017    import org.springframework.core.env.PropertiesPropertySource;
018    import org.springframework.core.env.PropertySource;
019    
020    public class SpringUtils {
021    
022            private static final Logger logger = LoggerFactory.getLogger(SpringUtils.class);
023    
024            public static void showPropertySources(ConfigurableEnvironment env) {
025                    List<PropertySource<?>> propertySources = getPropertySources(env);
026                    for (PropertySource<?> propertySource : propertySources) {
027                            String name = propertySource.getName();
028                            String impl = propertySource.getClass().getName();
029                            String source = propertySource.getSource().getClass().getName();
030                            Object[] args = { name, impl, source };
031                            logger.info("Name: {}  Impl: [{}]  Source: [{}]", args);
032                    }
033            }
034    
035            /**
036             * Get a fully resolved property value from the environment. If the property is not found or contains unresolvable placeholders an exception is thrown.
037             */
038            public static String getProperty(Environment env, String key) {
039                    String value = env.getRequiredProperty(key);
040                    return env.resolveRequiredPlaceholders(value);
041            }
042    
043            /**
044             * Examine <code>ConfigurableEnvironment</code> for <code>PropertySource</code>'s that extend <code>EnumerablePropertySource</code> and aggregate them into a single
045             * <code>Properties</code> object
046             */
047            public static Properties getAllEnumerableProperties(ConfigurableEnvironment env) {
048    
049                    // Extract the list of PropertySources from the environment
050                    List<PropertySource<?>> sources = getPropertySources(env);
051    
052                    // Convert the list of PropertySource's to a list of Properties objects
053                    List<Properties> propertiesList = convertEnumerablePropertySources(sources);
054    
055                    // Spring provides PropertySource objects ordered from highest priority to lowest priority
056                    // We reverse the order here so we can iterate though the list of Properties objects using
057                    // properties.putAll() as a simple "last one in wins" strategy to make sure the highest priority
058                    // property value always wins
059                    Collections.reverse(propertiesList);
060    
061                    // Combine them into a single Properties object
062                    return PropertyUtils.combine(propertiesList);
063            }
064    
065            /**
066             * Remove any existing property sources and add one property source backed by the properties passed in
067             */
068            public static void reconfigurePropertySources(ConfigurableEnvironment env, String name, Properties properties) {
069                    // Remove all existing property sources
070                    removeAllPropertySources(env);
071    
072                    // MutablePropertySources allow us to manipulate the list of property sources
073                    MutablePropertySources mps = env.getPropertySources();
074    
075                    // Make sure there are no existing property sources
076                    Assert.isTrue(mps.size() == 0);
077    
078                    // Create a property source backed by the properties object passed in
079                    PropertiesPropertySource pps = new PropertiesPropertySource(name, properties);
080    
081                    // Add it to the environment
082                    mps.addFirst(pps);
083            }
084    
085            /**
086             * Remove any existing property sources
087             */
088            public static void removeAllPropertySources(ConfigurableEnvironment env) {
089                    MutablePropertySources mps = env.getPropertySources();
090                    List<PropertySource<?>> sources = getPropertySources(env);
091                    for (PropertySource<?> source : sources) {
092                            String name = source.getName();
093                            mps.remove(name);
094                    }
095            }
096    
097            /**
098             * Get all PropertySource objects from the environment as a List.
099             */
100            public static List<PropertySource<?>> getPropertySources(ConfigurableEnvironment env) {
101                    MutablePropertySources mps = env.getPropertySources();
102                    List<PropertySource<?>> sources = new ArrayList<PropertySource<?>>();
103                    Iterator<PropertySource<?>> itr = mps.iterator();
104                    while (itr.hasNext()) {
105                            PropertySource<?> source = itr.next();
106                            sources.add(source);
107                    }
108                    return sources;
109            }
110    
111            /**
112             * Convert any PropertySources that extend EnumerablePropertySource into Properties object's
113             */
114            public static List<Properties> convertEnumerablePropertySources(List<PropertySource<?>> sources) {
115                    List<Properties> list = new ArrayList<Properties>();
116                    // Extract property values from the sources and place them in a Properties object
117                    for (PropertySource<?> source : sources) {
118                            logger.debug("Adding [{}]", source.getName());
119                            if (source instanceof EnumerablePropertySource) {
120                                    EnumerablePropertySource<?> eps = (EnumerablePropertySource<?>) source;
121                                    Properties sourceProperties = convert(eps);
122                                    list.add(sourceProperties);
123                            } else {
124                                    logger.warn("Unable to obtain properties from property source [{}] -> [{}]", source.getName(), source.getClass().getName());
125                            }
126                    }
127                    return list;
128            }
129    
130            /**
131             * Convert an EnumerablePropertySource into a Properties object.
132             */
133            public static Properties convert(EnumerablePropertySource<?> source) {
134                    Properties properties = new Properties();
135                    String[] names = source.getPropertyNames();
136                    for (String name : names) {
137                            Object object = source.getProperty(name);
138                            if (object != null) {
139                                    String value = object.toString();
140                                    properties.setProperty(name, value);
141                            } else {
142                                    logger.warn("Property [{}] is null", name);
143                            }
144                    }
145                    return properties;
146            }
147    
148    }