1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.kuali.common.util.service;
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.List;
23  
24  import org.apache.commons.lang3.StringUtils;
25  import org.kuali.common.util.Assert;
26  import org.kuali.common.util.CollectionUtils;
27  import org.kuali.common.util.LocationUtils;
28  import org.kuali.common.util.spring.SpringUtils;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  import org.springframework.context.ApplicationContext;
32  import org.springframework.context.ConfigurableApplicationContext;
33  import org.springframework.context.annotation.AnnotationConfigApplicationContext;
34  import org.springframework.context.support.ClassPathXmlApplicationContext;
35  import org.springframework.core.env.ConfigurableEnvironment;
36  import org.springframework.core.env.MutablePropertySources;
37  import org.springframework.core.env.PropertySource;
38  
39  public class DefaultSpringService implements SpringService {
40  
41  	private static final Logger logger = LoggerFactory.getLogger(DefaultSpringService.class);
42  
43  	@Override
44  	public void load(Class<?> annotatedClass) {
45  		load(annotatedClass, null, null);
46  	}
47  
48  	@Override
49  	public void load(Class<?> annotatedClass, String beanName, Object bean, PropertySource<?> propertySource) {
50  		
51  		Assert.notNull(annotatedClass, "annotatedClass is null");
52  
53  		
54  		SpringContext context = new SpringContext();
55  		context.setAnnotatedClasses(CollectionUtils.asList(annotatedClass));
56  		context.setPropertySourceContext(new PropertySourceContext(SpringUtils.asList(propertySource)));
57  
58  		
59  		context.setBeanNames(CollectionUtils.toEmptyList(beanName));
60  		context.setBeans(CollectionUtils.toEmptyList(bean));
61  
62  		
63  		load(context);
64  	}
65  
66  	@Override
67  	public void load(Class<?> annotatedClass, String beanName, Object bean) {
68  		load(annotatedClass, beanName, bean, null);
69  	}
70  
71  	@Override
72  	public void load(String location) {
73  		load(location, null, null);
74  	}
75  
76  	@Override
77  	public void load(String location, String beanName, Object bean, PropertySource<?> propertySource) {
78  		
79  		Assert.hasText(location, "location is null");
80  
81  		
82  		SpringContext context = new SpringContext();
83  		context.setLocations(Arrays.asList(location));
84  		context.setPropertySourceContext(new PropertySourceContext(SpringUtils.asList(propertySource)));
85  
86  		
87  		context.setBeanNames(CollectionUtils.toEmptyList(beanName));
88  		context.setBeans(CollectionUtils.toEmptyList(bean));
89  
90  		
91  		load(context);
92  	}
93  
94  	@Override
95  	public void load(String location, String beanName, Object bean) {
96  		load(location, beanName, bean, null);
97  	}
98  
99  	@Override
100 	public void load(SpringContext context) {
101 
102 		
103 		context.setBeanNames(CollectionUtils.toEmptyList(context.getBeanNames()));
104 		context.setBeans(CollectionUtils.toEmptyList(context.getBeans()));
105 		context.setAnnotatedClasses(CollectionUtils.toEmptyList(context.getAnnotatedClasses()));
106 		context.setLocations(CollectionUtils.toEmptyList(context.getLocations()));
107 
108 		
109 		boolean empty = CollectionUtils.isEmpty(context.getLocations()) && CollectionUtils.isEmpty(context.getAnnotatedClasses());
110 		Assert.isFalse(empty, "Both locations and annotatedClasses are empty");
111 
112 		
113 		Assert.isTrue(context.getBeanNames().size() == context.getBeans().size());
114 
115 		
116 		SpringUtils.validateExists(context.getLocations());
117 
118 		
119 		List<String> convertedLocations = getConvertedLocations(context.getLocations());
120 
121 		
122 		String[] locationsArray = CollectionUtils.toStringArray(convertedLocations);
123 
124 		ConfigurableApplicationContext parent = null;
125 		ClassPathXmlApplicationContext xmlChild = null;
126 		AnnotationConfigApplicationContext annotationChild = null;
127 		try {
128 			if (isParentContextRequired(context)) {
129 				
130 				parent = SpringUtils.getContextWithPreRegisteredBeans(context.getId(), context.getDisplayName(), context.getBeanNames(), context.getBeans());
131 			}
132 
133 			if (!CollectionUtils.isEmpty(context.getAnnotatedClasses())) {
134 				
135 				annotationChild = getAnnotationContext(context, parent);
136 				
137 				addPropertySources(context, annotationChild);
138 
139 			}
140 
141 			if (!CollectionUtils.isEmpty(context.getLocations())) {
142 				
143 				xmlChild = new ClassPathXmlApplicationContext(locationsArray, false, parent);
144 				if (parent == null) {
145 					addMetaInfo(xmlChild, context);
146 				}
147 				
148 				addPropertySources(context, xmlChild);
149 			}
150 
151 			
152 			SpringUtils.refreshQuietly(annotationChild);
153 			SpringUtils.refreshQuietly(xmlChild);
154 			debugQuietly(parent, annotationChild, xmlChild);
155 		} finally {
156 			
157 			
158 			
159 			
160 		}
161 	}
162 
163 	protected void debugQuietly(ApplicationContext parent, ApplicationContext child1, ApplicationContext child2) {
164 		if (!logger.isDebugEnabled()) {
165 			return;
166 		}
167 		if (parent != null) {
168 			SpringUtils.debug(parent);
169 		} else {
170 			if (child1 != null) {
171 				SpringUtils.debug(child1);
172 			}
173 			if (child2 != null) {
174 				SpringUtils.debug(child2);
175 			}
176 		}
177 	}
178 
179 	
180 
181 
182 	protected void addMetaInfo(AnnotationConfigApplicationContext ctx, SpringContext sc) {
183 		if (!StringUtils.isBlank(sc.getId())) {
184 			ctx.setId(sc.getId());
185 		}
186 		if (!StringUtils.isBlank(sc.getDisplayName())) {
187 			ctx.setDisplayName(sc.getDisplayName());
188 		}
189 	}
190 
191 	
192 
193 
194 	protected void addMetaInfo(ClassPathXmlApplicationContext ctx, SpringContext sc) {
195 		if (!StringUtils.isBlank(sc.getId())) {
196 			ctx.setId(sc.getId());
197 		}
198 		if (!StringUtils.isBlank(sc.getDisplayName())) {
199 			ctx.setDisplayName(sc.getDisplayName());
200 		}
201 	}
202 
203 	protected AnnotationConfigApplicationContext getAnnotationContext(SpringContext context, ConfigurableApplicationContext parent) {
204 		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
205 		if (parent != null) {
206 			ctx.setParent(parent);
207 		} else {
208 			addMetaInfo(ctx, context);
209 		}
210 		for (Class<?> annotatedClass : context.getAnnotatedClasses()) {
211 			ctx.register(annotatedClass);
212 		}
213 		return ctx;
214 	}
215 
216 	protected void addPropertySources(SpringContext context, ConfigurableApplicationContext applicationContext) {
217 		PropertySourceContext psc = context.getPropertySourceContext();
218 		ConfigurableEnvironment env = applicationContext.getEnvironment();
219 		if (psc.isRemoveExistingSources()) {
220 			logger.debug("Removing all existing property sources");
221 			SpringUtils.removeAllPropertySources(env);
222 		}
223 
224 		if (CollectionUtils.isEmpty(psc.getSources())) {
225 			return;
226 		}
227 		List<PropertySource<?>> propertySources = psc.getSources();
228 		MutablePropertySources sources = env.getPropertySources();
229 		if (psc.isLastOneInWins()) {
230 			Collections.reverse(propertySources);
231 		}
232 		PropertySourceAddPriority priority = psc.getPriority();
233 		for (PropertySource<?> propertySource : propertySources) {
234 			Object[] args = { propertySource.getName(), propertySource.getClass().getName(), priority };
235 			logger.debug("Adding property source - [{}] -> [{}] Priority=[{}]", args);
236 			switch (priority) {
237 			case FIRST:
238 				sources.addFirst(propertySource);
239 				break;
240 			case LAST:
241 				sources.addLast(propertySource);
242 				break;
243 			default:
244 				throw new IllegalStateException(priority + " is an unknown priority");
245 			}
246 		}
247 	}
248 
249 	
250 
251 
252 	protected boolean isParentContextRequired(SpringContext context) {
253 		if (!CollectionUtils.isEmpty(context.getBeanNames())) {
254 			return true;
255 		} else if (!CollectionUtils.isEmpty(context.getBeans())) {
256 			return true;
257 		} else {
258 			return false;
259 		}
260 	}
261 
262 	
263 
264 
265 	protected List<String> getConvertedLocations(List<String> locations) {
266 		List<String> converted = new ArrayList<String>();
267 		for (String location : locations) {
268 			if (LocationUtils.isExistingFile(location)) {
269 				File file = new File(location);
270 				
271 				String url = LocationUtils.getCanonicalURLString(file);
272 				converted.add(url);
273 			} else {
274 				converted.add(location);
275 			}
276 		}
277 		return converted;
278 	}
279 
280 }