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 String id = StringUtils.leftPad(Thread.currentThread().getId() + "", 2);
147 String name = Thread.currentThread().getName();
148 logger.debug("id: " + id + " name: " + name + " ctx=" + ctx.getClass().getSimpleName() + "@" + Integer.toHexString(ctx.hashCode()));
149 ctx.refresh();
150 SpringUtils.debugQuietly(ctx);
151 } finally {
152 SpringUtils.closeQuietly(ctx);
153 }
154 }
155
156 @Override
157 public void load(String location, Map<String, Object> contextBeans, PropertySource<?> propertySource) {
158
159 Assert.hasText(location, "location is null");
160
161
162 SpringContext context = new SpringContext();
163 context.setLocations(Arrays.asList(location));
164 context.setPropertySourceContext(new PropertySourceContext(PropertySourceUtils.asList(propertySource)));
165
166
167 context.setContextBeans(CollectionUtils.toEmptyMap(contextBeans));
168
169
170 load(context);
171 }
172
173 @Override
174 public void load(Class<?> annotatedClass) {
175 load(annotatedClass, (String) null, (Object) null);
176 }
177
178 @Override
179 public void load(String location) {
180 load(location, (String) null, (Object) null);
181 }
182
183
184
185
186 protected void addMetaInfo(AnnotationConfigApplicationContext ctx, SpringContext sc) {
187 if (!StringUtils.isBlank(sc.getId())) {
188 ctx.setId(sc.getId());
189 }
190 if (!StringUtils.isBlank(sc.getDisplayName())) {
191 ctx.setDisplayName(sc.getDisplayName());
192 }
193 }
194
195
196
197
198 protected void addMetaInfo(ClassPathXmlApplicationContext ctx, SpringContext sc) {
199 if (!StringUtils.isBlank(sc.getId())) {
200 ctx.setId(sc.getId());
201 }
202 if (!StringUtils.isBlank(sc.getDisplayName())) {
203 ctx.setDisplayName(sc.getDisplayName());
204 }
205 }
206
207 protected AbstractApplicationContext getAnnotationContext(SpringContext context, ConfigurableApplicationContext parent) {
208 AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
209 if (parent != null) {
210 ctx.setParent(parent);
211 } else {
212 addMetaInfo(ctx, context);
213 }
214 for (Class<?> annotatedClass : context.getAnnotatedClasses()) {
215 ctx.register(annotatedClass);
216 }
217 return ctx;
218 }
219
220 protected void setActiveProfiles(ConfigurableApplicationContext applicationContext, List<String> activeProfiles) {
221 if (!CollectionUtils.isEmpty(activeProfiles)) {
222 ConfigurableEnvironment env = applicationContext.getEnvironment();
223 env.setActiveProfiles(CollectionUtils.toStringArray(activeProfiles));
224 }
225 }
226
227 protected void setDefaultProfiles(ConfigurableApplicationContext applicationContext, List<String> defaultProfiles) {
228 if (!CollectionUtils.isEmpty(defaultProfiles)) {
229 ConfigurableEnvironment env = applicationContext.getEnvironment();
230 env.setDefaultProfiles(CollectionUtils.toStringArray(defaultProfiles));
231 }
232 }
233
234 protected void addPropertySources(SpringContext context, ConfigurableApplicationContext applicationContext) {
235 PropertySourceContext psc = context.getPropertySourceContext();
236 if (psc == null) {
237 return;
238 }
239 ConfigurableEnvironment env = applicationContext.getEnvironment();
240 if (psc.isRemoveExistingSources()) {
241 logger.debug("Removing all existing property sources");
242 PropertySourceUtils.removeAllPropertySources(env);
243 }
244
245 if (CollectionUtils.isEmpty(psc.getSources())) {
246 return;
247 }
248 List<PropertySource<?>> propertySources = psc.getSources();
249 MutablePropertySources sources = env.getPropertySources();
250 if (psc.isLastOneInWins()) {
251 Collections.reverse(propertySources);
252 }
253 PropertySourceAddPriority priority = psc.getPriority();
254 for (PropertySource<?> propertySource : propertySources) {
255 Object[] args = { propertySource.getName(), propertySource.getClass().getName(), priority };
256 logger.debug("Adding property source - [{}] -> [{}] Priority=[{}]", args);
257 switch (priority) {
258 case FIRST:
259 sources.addFirst(propertySource);
260 break;
261 case LAST:
262 sources.addLast(propertySource);
263 break;
264 default:
265 throw new IllegalStateException(priority + " is an unknown priority");
266 }
267 }
268 }
269
270
271
272
273 protected List<String> getConvertedLocations(List<String> locations) {
274 List<String> converted = new ArrayList<String>();
275 for (String location : locations) {
276 if (LocationUtils.isExistingFile(location)) {
277 File file = new File(location);
278
279 String url = LocationUtils.getCanonicalURLString(file);
280 converted.add(url);
281 } else {
282 converted.add(location);
283 }
284 }
285 return converted;
286 }
287
288 @Deprecated
289 @Override
290 public void load(Class<?> annotatedClass, String beanName, Object bean, PropertySource<?> propertySource) {
291 load(annotatedClass, CollectionUtils.toEmptyMap(beanName, bean), propertySource);
292 }
293
294 @Deprecated
295 @Override
296 public void load(Class<?> annotatedClass, String beanName, Object bean) {
297 load(annotatedClass, beanName, bean, null);
298 }
299
300 @Deprecated
301 @Override
302 public void load(String location, String beanName, Object bean, PropertySource<?> propertySource) {
303 load(location, CollectionUtils.toEmptyMap(beanName, bean), propertySource);
304 }
305
306 @Deprecated
307 @Override
308 public void load(String location, String beanName, Object bean) {
309 load(location, beanName, bean, null);
310 }
311
312 }