1 package org.apache.fulcrum.yaafi.service.reconfiguration;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.InputStream;
24 import java.security.MessageDigest;
25
26 import org.apache.avalon.framework.activity.Disposable;
27 import org.apache.avalon.framework.activity.Initializable;
28 import org.apache.avalon.framework.activity.Startable;
29 import org.apache.avalon.framework.activity.Suspendable;
30 import org.apache.avalon.framework.configuration.Configuration;
31 import org.apache.avalon.framework.configuration.ConfigurationException;
32 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
33 import org.apache.avalon.framework.configuration.Reconfigurable;
34 import org.apache.avalon.framework.context.Context;
35 import org.apache.avalon.framework.context.ContextException;
36 import org.apache.avalon.framework.context.Contextualizable;
37 import org.apache.avalon.framework.logger.AbstractLogEnabled;
38 import org.apache.avalon.framework.service.ServiceException;
39 import org.apache.avalon.framework.service.ServiceManager;
40 import org.apache.avalon.framework.service.Serviceable;
41 import org.apache.fulcrum.yaafi.framework.container.ServiceLifecycleManager;
42
43
44
45
46
47
48
49
50 public class ReconfigurationServiceImpl extends AbstractLogEnabled implements ReconfigurationService, Serviceable,
51 Contextualizable, Reconfigurable, Initializable, Runnable, Startable, Disposable {
52
53 private int interval;
54
55
56 private boolean terminateNow;
57
58
59 private Thread workerThread;
60
61
62 private ServiceManager serviceManager;
63
64
65 private File applicationDir;
66
67
68 private ReconfigurationEntry[] reconfigurationEntryList;
69
70
71 private ServiceLifecycleManager serviceLifecycleManager;
72
73
74
75
76
77
78
79
80 public ReconfigurationServiceImpl() {
81 this.terminateNow = false;
82 }
83
84
85
86
87 public void service(ServiceManager manager) throws ServiceException {
88 this.serviceManager = manager;
89 this.serviceLifecycleManager = (ServiceLifecycleManager) manager;
90 }
91
92
93
94
95 public void contextualize(Context context) throws ContextException {
96 this.applicationDir = (File) context.get("urn:avalon:home");
97 }
98
99
100
101
102 public void configure(Configuration configuration) throws ConfigurationException {
103
104
105 this.interval = Math.max(configuration.getAttributeAsInteger("interval", 5000), 1000);
106
107 this.getLogger().debug("Monitoring the resources every " + this.interval + " ms");
108
109
110
111
112 Configuration services = null;
113 Configuration[] serviceEntries = null;
114 Configuration[] entryList = configuration.getChildren("entry");
115
116 String location = null;
117 String serviceName = null;
118 String[] serviceNameList = null;
119 ReconfigurationEntry reconfigurationEntry = null;
120 ReconfigurationEntry[] list = new ReconfigurationEntry[entryList.length];
121 int listIndex = 0;
122 for (Configuration entry : entryList) {
123 location = entry.getChild("location").getValue();
124 services = entry.getChild("services", false);
125
126 this.getLogger().debug("Adding the following resource to monitor : " + location);
127
128 if (services != null) {
129 serviceEntries = services.getChildren("service");
130 serviceNameList = new String[serviceEntries.length];
131
132 for (int j = 0; j < serviceEntries.length; j++) {
133 serviceName = serviceEntries[j].getAttribute("name");
134 serviceNameList[j] = serviceName;
135 }
136 }
137
138 reconfigurationEntry = new ReconfigurationEntry(this.getLogger(), this.applicationDir, location,
139 serviceNameList);
140
141 list[listIndex++] = reconfigurationEntry;
142 }
143
144 this.getLogger().debug("Monitoring " + list.length + " resources");
145
146 this.setReconfigurationEntryList(list);
147 }
148
149
150
151
152 public void initialize() throws Exception {
153
154 MessageDigest.getInstance("SHA1");
155
156
157 if (this.serviceManager instanceof ServiceLifecycleManager == false)
158 throw new IllegalArgumentException(
159 "The ServiceManager instance does not implement ServiceLifecycleManager!");
160
161
162 this.workerThread = new Thread(this, "ReconfigurationService");
163 }
164
165
166
167
168 public void start() throws Exception {
169 this.getLogger().debug("Starting worker thread ...");
170 this.workerThread.start();
171 }
172
173
174
175
176 public void stop() throws Exception {
177 this.getLogger().debug("Stopping worker thread ...");
178 this.terminateNow = true;
179 this.workerThread.interrupt();
180 this.workerThread.join(10000);
181 }
182
183
184
185
186 public void dispose() {
187 this.terminateNow = false;
188 this.applicationDir = null;
189 this.workerThread = null;
190 this.serviceManager = null;
191 this.reconfigurationEntryList = null;
192 }
193
194
195
196
197 public void reconfigure(Configuration configuration) throws ConfigurationException {
198 this.configure(configuration);
199 }
200
201
202
203
204
205
206
207
208
209
210
211 public void run() {
212 ReconfigurationEntry[] list = null;
213 while (this.terminateNow == false) {
214 list = this.getReconfigurationEntryList();
215 try {
216 for (ReconfigurationEntry reconfigurationEntry : list) {
217 if (reconfigurationEntry.hasChanged())
218 this.onReconfigure(reconfigurationEntry);
219 }
220
221 Thread.sleep(this.interval);
222 } catch (InterruptedException e) {
223 continue;
224 } catch (Exception e) {
225 String msg = "The ReconfigurationService had a problem";
226 this.getLogger().error(msg, e);
227 continue;
228 }
229 }
230 }
231
232
233
234
235
236
237
238
239
240
241
242
243 protected void onReconfigure(ReconfigurationEntry reconfigurationEntry) throws Exception {
244 if (reconfigurationEntry.getServiceList() == null) {
245
246 InputStream is = reconfigurationEntry.locate();
247 DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
248 Configuration configuration = builder.build(is);
249 is.close();
250 is = null;
251
252 this.getLogger().warn("Starting to reconfigure the container");
253
254 if (this.serviceManager instanceof Suspendable) {
255 this.getLogger().info("Calling suspend() of the container");
256 ((Suspendable) this.serviceManager).suspend();
257 }
258
259 if (this.serviceManager instanceof Reconfigurable) {
260 this.getLogger().info("Calling reconfigure() of the container");
261 ((Reconfigurable) this.serviceManager).reconfigure(configuration);
262 }
263
264 if (this.serviceManager instanceof Suspendable) {
265 this.getLogger().info("Calling resume() of the container");
266 ((Suspendable) this.serviceManager).resume();
267 }
268
269 this.getLogger().info("Reconfiguring the container was successful");
270 } else {
271 String[] serviceList = reconfigurationEntry.getServiceList();
272 this.getLogger().warn("Calling reconfigure() on individual services : " + serviceList.length);
273 this.serviceLifecycleManager.reconfigure(serviceList);
274 }
275 }
276
277
278
279
280 private synchronized ReconfigurationEntry[] getReconfigurationEntryList() {
281 return reconfigurationEntryList;
282 }
283
284
285
286
287 private synchronized void setReconfigurationEntryList(ReconfigurationEntry[] reconfigurationEntryList) {
288 this.reconfigurationEntryList = reconfigurationEntryList;
289 }
290 }