1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package edu.internet2.middleware.shibboleth.common.config;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.concurrent.locks.Lock;
24 import java.util.concurrent.locks.ReadWriteLock;
25 import java.util.concurrent.locks.ReentrantReadWriteLock;
26
27 import org.opensaml.util.resource.Resource;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import org.springframework.beans.factory.BeanNameAware;
31 import org.springframework.context.ApplicationContext;
32 import org.springframework.context.ApplicationContextAware;
33 import org.springframework.context.support.GenericApplicationContext;
34
35 import edu.internet2.middleware.shibboleth.common.service.Service;
36 import edu.internet2.middleware.shibboleth.common.service.ServiceException;
37
38
39
40
41
42
43
44 public abstract class BaseService implements Service, ApplicationContextAware, BeanNameAware {
45
46
47 private final Logger log = LoggerFactory.getLogger(BaseService.class);
48
49
50 private String serviceName;
51
52
53 private ReentrantReadWriteLock serviceContextRWLock;
54
55
56 private ApplicationContext owningContext;
57
58
59 private GenericApplicationContext serviceContext;
60
61
62 private ArrayList<Resource> serviceConfigurations;
63
64
65 private boolean isInitialized;
66
67
68 private boolean isDestroyed;
69
70
71 public BaseService() {
72 serviceContextRWLock = new ReentrantReadWriteLock(true);
73 isInitialized = false;
74 }
75
76
77 public void destroy() throws ServiceException {
78 Lock writeLock = getReadWriteLock().writeLock();
79 writeLock.lock();
80 isDestroyed = true;
81 serviceContext = null;
82 serviceConfigurations.clear();
83 setInitialized(false);
84 writeLock.unlock();
85 serviceContextRWLock = null;
86 }
87
88
89
90
91
92
93 public ApplicationContext getApplicationContext() {
94 return owningContext;
95 }
96
97
98 public String getId() {
99 return serviceName;
100 }
101
102
103
104
105
106
107 protected ReadWriteLock getReadWriteLock() {
108 return serviceContextRWLock;
109 }
110
111
112
113
114
115
116 public List<Resource> getServiceConfigurations(){
117 return Collections.unmodifiableList(serviceConfigurations);
118 }
119
120
121
122
123
124
125 public ApplicationContext getServiceContext() {
126 return serviceContext;
127 }
128
129
130 public void initialize() throws ServiceException {
131 if (isDestroyed()) {
132 throw new SecurityException(getId() + " service has been destroyed, it may not be initialized.");
133 }
134
135 if (isInitialized()) {
136 return;
137 }
138
139 loadContext();
140 }
141
142
143 public boolean isInitialized() {
144 return isInitialized;
145 }
146
147
148 public boolean isDestroyed() {
149 return isDestroyed;
150 }
151
152
153
154
155
156
157 protected void loadContext() throws ServiceException {
158 log.info("Loading new configuration for service {}", getId());
159
160 if(serviceConfigurations == null || serviceConfigurations.isEmpty()){
161 setInitialized(true);
162 return;
163 }
164
165 GenericApplicationContext newServiceContext = new GenericApplicationContext(getApplicationContext());
166 newServiceContext.setDisplayName("ApplicationContext:" + getId());
167 Lock writeLock = getReadWriteLock().writeLock();
168 writeLock.lock();
169 try {
170 SpringConfigurationUtils.populateRegistry(newServiceContext, getServiceConfigurations());
171 newServiceContext.refresh();
172
173 GenericApplicationContext replacedServiceContext = serviceContext;
174 onNewContextCreated(newServiceContext);
175 setServiceContext(newServiceContext);
176 setInitialized(true);
177 if(replacedServiceContext != null){
178 replacedServiceContext.close();
179 }
180 log.info("{} service loaded new configuration", getId());
181 } catch (Throwable e) {
182
183 setInitialized(false);
184 Throwable rootCause = e;
185 while (rootCause.getCause() != null) {
186 rootCause = rootCause.getCause();
187 }
188 log.error("Configuration was not loaded for " + getId()
189 + " service, error creating components. The root cause of this error was: " +
190 rootCause.getClass().getCanonicalName() + ": " + rootCause.getMessage());
191 log.trace("Full stacktrace is: ", e);
192 throw new ServiceException("Configuration was not loaded for " + getId()
193 + " service, error creating components.", rootCause);
194 }finally{
195 writeLock.unlock();
196 }
197 }
198
199
200
201
202
203
204
205
206
207 protected abstract void onNewContextCreated(ApplicationContext newServiceContext) throws ServiceException;
208
209
210
211
212
213
214 public void setApplicationContext(ApplicationContext applicationContext) {
215 owningContext = applicationContext;
216 }
217
218
219 public void setBeanName(String name) {
220 serviceName = name;
221 }
222
223
224
225
226
227
228 protected void setInitialized(boolean initialized) {
229 isInitialized = initialized;
230 }
231
232
233
234
235
236
237 public void setServiceConfigurations(List<Resource> configurations) {
238 if(isInitialized){
239 throw new IllegalStateException("Service already initialized");
240 }
241 serviceConfigurations = new ArrayList<Resource>(configurations);
242 }
243
244
245
246
247
248
249 protected void setServiceContext(GenericApplicationContext context) {
250 serviceContext = context;
251 }
252 }