1
2
3
4 package gboat2.base.core.util;
5
6 import gboat2.base.bridge.exception.DefaultGboatNestedException;
7
8 import java.util.Collections;
9 import java.util.HashMap;
10 import java.util.Iterator;
11 import java.util.LinkedList;
12 import java.util.List;
13 import java.util.Map;
14
15 import org.osgi.framework.Bundle;
16 import org.osgi.framework.BundleEvent;
17 import org.osgi.framework.BundleListener;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
21 import org.springframework.context.ApplicationContext;
22 import org.springframework.context.ApplicationContextAware;
23 import org.springframework.context.support.AbstractRefreshableApplicationContext;
24 import org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext;
25 import org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext;
26
27
28
29
30
31
32
33
34
35 public final class SpringContextUtil implements ApplicationContextAware, BundleListener {
36
37 private static Logger logger = LoggerFactory.getLogger(SpringContextUtil.class);
38
39 private static SpringContextUtil context;
40
41 private SpringContextUtil() {
42 }
43
44 public synchronized static SpringContextUtil getInstance() {
45 if (context == null) {
46 context = new SpringContextUtil();
47 }
48 return context;
49 }
50
51 private static final List<OsgiBundleXmlApplicationContext> servletContexts = Collections
52 .synchronizedList(new LinkedList<OsgiBundleXmlApplicationContext>());
53
54 public final void setApplicationContext(ApplicationContext context) {
55 synchronized (servletContexts) {
56 logger.debug("add " + context + " to SpringContextUtil");
57 List<OsgiBundleXmlApplicationContext> toRemoved = new LinkedList<OsgiBundleXmlApplicationContext>();
58 if (context instanceof OsgiBundleXmlApplicationContext) {
59
60 OsgiBundleXmlApplicationContext bundleContext = (OsgiBundleXmlApplicationContext) context;
61 for (OsgiBundleXmlApplicationContext ctx : servletContexts) {
62 if (ctx.getBundle().getSymbolicName().equals(bundleContext.getBundle().getSymbolicName())) {
63 logger.debug(bundleContext + " is already in SpringContextUtil");
64 toRemoved.add(ctx);
65 }
66 }
67 for (OsgiBundleXmlApplicationContext ctx : toRemoved) {
68 logger.debug("remove " + ctx);
69 servletContexts.remove(ctx);
70 }
71 servletContexts.add(bundleContext);
72 }
73 }
74 }
75
76 private OsgiBundleXmlApplicationContext getContextOfBundle(Bundle bundle) {
77 synchronized (servletContexts) {
78 for (OsgiBundleXmlApplicationContext context : servletContexts) {
79 if (context.getBundle().getSymbolicName().equals(bundle.getSymbolicName())) {
80 return context;
81 }
82 }
83 }
84
85 return null;
86 }
87
88
89
90
91
92
93 private boolean refreshApplicationContext(AbstractDelegatedExecutionApplicationContext context) {
94 Bundle bundle = context.getBundle();
95 if (bundle.getState() != Bundle.ACTIVE)
96 return false;
97
98 logger.debug("refresh Bundle [] 的 Spring ApplicationContext: {}", bundle.getSymbolicName(), context);
99 context.refresh();
100 return true;
101 }
102
103
104
105
106
107
108
109 public List<Object> getBeansOfType(Class<?> className, Bundle bundle) {
110 logger.debug("try to find bean of " + className + " in " + bundle.getSymbolicName() + " ...");
111 List<Object> beans = new LinkedList<Object>();
112 OsgiBundleXmlApplicationContext context = getContextOfBundle(bundle);
113 if (context != null) {
114 Map<String, Object> map = new HashMap<String, Object>();
115 try {
116 @SuppressWarnings("unchecked")
117 Map<String, Object> beansOfType = (Map<String, Object>)context.getBeansOfType(className);
118 map = beansOfType;
119 } catch (NoSuchBeanDefinitionException e) {
120 } catch (IllegalStateException e) {
121 if (context instanceof OsgiBundleXmlApplicationContext) {
122 if (context.getBundle().getState() == Bundle.ACTIVE) {
123 logger.debug("refresh " + context);
124 context.refresh();
125 try {
126 @SuppressWarnings("unchecked")
127 Map<String, Object> beansOfType = (Map<String, Object>)context.getBeansOfType(className);
128 map = beansOfType;
129 } catch (NoSuchBeanDefinitionException ignore) {
130 }
131 }
132 }
133 }
134 if (!map.isEmpty()) {
135 Iterator<String> it = map.keySet().iterator();
136 String name;
137 while (it.hasNext()) {
138 name = it.next();
139 beans.add(map.get(name));
140 }
141 }
142 } else {
143 throw new DefaultGboatNestedException("Can't find ApplicationContext for " + bundle.getSymbolicName());
144 }
145 logger.debug("find : " + beans);
146 return beans;
147 }
148
149 public Object getBeanOfType(Class<?> className, Bundle bundle) {
150 List<Object> objs = getBeansOfType(className, bundle);
151 if(objs.size()==1){
152 return objs.get(0);
153 }else if(objs.size()>1){
154 throw new DefaultGboatNestedException("more than one object of class["+className+"] in "+bundle.getSymbolicName());
155 }else{
156 return null;
157 }
158 }
159
160 public Object getBeanOfId(String id) {
161 logger.debug("try to find bean with id " + id);
162 synchronized (servletContexts) {
163 Object bean;
164 for (ApplicationContext context : servletContexts) {
165 try {
166 bean = context.getBean(id);
167 if (bean != null) {
168 logger.debug("find : " + bean);
169 return bean;
170 }
171 } catch (NoSuchBeanDefinitionException e) {
172 continue;
173 } catch (IllegalStateException e) {
174 if (context instanceof OsgiBundleXmlApplicationContext) {
175 if (((OsgiBundleXmlApplicationContext) context).getBundle().getState() == Bundle.ACTIVE) {
176 logger.debug("refresh " + context);
177 ((AbstractRefreshableApplicationContext) context).refresh();
178 try {
179 bean = context.getBean(id);
180 if (bean != null) {
181 logger.debug("find : " + bean);
182 return bean;
183 }
184 } catch (NoSuchBeanDefinitionException ignore) {
185 continue;
186 }
187 }
188 }
189 }
190 }
191 return null;
192 }
193 }
194
195 public Object getBeanOfId(String id, Bundle bundle) {
196 logger.debug("try to find bean with id " + id + " in bundle[" + bundle.getSymbolicName() + "]");
197 Object bean;
198 OsgiBundleXmlApplicationContext context = getContextOfBundle(bundle);
199 if (context != null) {
200 try {
201 bean = context.getBean(id);
202 if (bean != null) {
203 logger.debug("find : " + bean);
204 return bean;
205 }
206 } catch (NoSuchBeanDefinitionException e) {
207 } catch (IllegalStateException e) {
208 if (context instanceof OsgiBundleXmlApplicationContext) {
209 if (((OsgiBundleXmlApplicationContext) context).getBundle().getState() == Bundle.ACTIVE) {
210 logger.debug("refresh " + context);
211 ((AbstractRefreshableApplicationContext) context).refresh();
212 try {
213 bean = context.getBean(id);
214 if (bean != null) {
215 logger.debug("find : " + bean);
216 return bean;
217 }
218 } catch (NoSuchBeanDefinitionException ignore) {
219 }
220 }
221 }
222 }
223 }
224 return null;
225 }
226
227 public <T> T getBeanOfId(String id, Bundle bundle, Class<T> requiredType) {
228 logger.debug("try to find bean with id " + id + " in bundle[" + bundle.getSymbolicName() + "]");
229 T bean = null;
230 OsgiBundleXmlApplicationContext context = getContextOfBundle(bundle);
231 if (context == null)
232 return null;
233
234 try {
235 bean = context.getBean(id, requiredType);
236 } catch (IllegalStateException e) {
237 if (refreshApplicationContext(context)) {
238 bean = context.getBean(id, requiredType);
239 }
240 }
241 return bean;
242 }
243
244 @Override
245 public void bundleChanged(BundleEvent event) {
246 if (event.getBundle().getState() == Bundle.RESOLVED) {
247 OsgiBundleXmlApplicationContext bundleContext = getContextOfBundle(event.getBundle());
248 if (bundleContext != null) {
249 synchronized (servletContexts) {
250 servletContexts.remove(bundleContext);
251 }
252 }
253 }
254 }
255 }