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 }