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