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