1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.appstatus.core;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.net.URL;
22 import java.util.ArrayList;
23 import java.util.Enumeration;
24 import java.util.List;
25 import java.util.Locale;
26 import java.util.Map;
27 import java.util.Properties;
28 import java.util.Set;
29 import java.util.TreeMap;
30 import java.util.concurrent.Callable;
31 import java.util.concurrent.ExecutionException;
32 import java.util.concurrent.ExecutorService;
33 import java.util.concurrent.Executors;
34 import java.util.concurrent.Future;
35
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 import net.sf.appstatus.core.batch.IBatch;
40 import net.sf.appstatus.core.batch.IBatchManager;
41 import net.sf.appstatus.core.batch.IBatchProgressMonitor;
42 import net.sf.appstatus.core.batch.IBatchScheduleManager;
43 import net.sf.appstatus.core.check.CheckResultBuilder;
44 import net.sf.appstatus.core.check.IAppStatusAware;
45 import net.sf.appstatus.core.check.ICheck;
46 import net.sf.appstatus.core.check.ICheckResult;
47 import net.sf.appstatus.core.check.IConfigurationAware;
48 import net.sf.appstatus.core.loggers.ILoggersManager;
49 import net.sf.appstatus.core.property.IPropertyProvider;
50 import net.sf.appstatus.core.services.IService;
51 import net.sf.appstatus.core.services.IServiceManager;
52 import net.sf.appstatus.core.services.IServiceMonitor;
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 public class AppStatus {
68
69 private static final String CONFIG_LOCATION = "status-check.properties";
70 private static Logger logger = LoggerFactory.getLogger(AppStatus.class);
71
72 private IBatchManager batchManager = null;
73 private IBatchScheduleManager batchScheduleManager;
74 protected List<ICheck> checkers;
75 private Properties configuration = null;
76 private ExecutorService executorService = null;
77 private boolean initDone = false;
78 private ILoggersManager loggersManager = null;
79 private boolean maintenance = false;
80 private String maintenanceFile = null;
81 private IObjectInstantiationListener objectInstanciationListener = null;
82 private List<IPropertyProvider> propertyProviders;
83 private IServiceManager serviceManager = null;
84 private IServletContextProvider servletContextProvider = null;
85
86
87
88
89 public AppStatus() {
90 }
91
92 private void addPropertyProvider(String clazz) {
93 IPropertyProvider provider = (IPropertyProvider) getClassInstance(clazz);
94
95 if (provider != null) {
96 propertyProviders.add(provider);
97 logger.info("Registered property provider " + clazz);
98 } else {
99 logger.error("cannot instanciate class {}, Please configure \"{}\" file properly", clazz, CONFIG_LOCATION);
100 }
101 }
102
103 private void addStatusChecker(String clazz) {
104 ICheck check = (ICheck) getClassInstance(clazz);
105 if (check == null) {
106 logger.error("cannot instanciate class {}, Please configure \"{}\" file properly", clazz, CONFIG_LOCATION);
107 return;
108 }
109
110 if (check instanceof IServletContextAware) {
111 ((IServletContextAware) check).setServletContext(servletContextProvider.getServletContext());
112 }
113
114 checkers.add(check);
115 logger.info("Registered status checker {}", clazz);
116 }
117
118 public List<ICheckResult> checkAll() {
119 return checkAll(null);
120 }
121
122 public List<ICheckResult> checkAll(final Locale locale) {
123 checkInit();
124
125 List<Future<ICheckResult>> statusFutureList = new ArrayList<Future<ICheckResult>>();
126 for (final ICheck check : checkers) {
127 injectServletContext(check);
128
129 statusFutureList.add(executorService.submit(new Callable<ICheckResult>() {
130 public ICheckResult call() throws Exception {
131
132 if (check instanceof IAppStatusAware) {
133 ((IAppStatusAware) check).setAppStatus(AppStatus.this);
134 }
135
136
137 if (check instanceof IConfigurationAware) {
138 ((IConfigurationAware) check).setConfiguration(getConfiguration());
139 }
140 return check.checkStatus(locale);
141 }
142 }));
143 }
144
145 ArrayList<ICheckResult> statusList = new ArrayList<ICheckResult>();
146
147 for (int i = 0; i < statusFutureList.size(); i++) {
148 Future<ICheckResult> f = statusFutureList.get(i);
149 ICheck c = checkers.get(i);
150
151 try {
152 statusList.add(f.get());
153 } catch (InterruptedException e) {
154 statusList.add(createCheckResultFromException(c, e));
155 logger.error("", e);
156 } catch (ExecutionException e) {
157 statusList.add(createCheckResultFromException(c, e));
158 logger.error("", e);
159 }
160 }
161
162 return statusList;
163 }
164
165 private void checkInit() {
166 if (!initDone) {
167 logger.warn("Not initialized. Starting init");
168 init();
169 }
170 }
171
172 private ICheckResult createCheckResultFromException(ICheck c, Exception e) {
173
174 return new CheckResultBuilder().from(c).code(ICheckResult.ERROR).fatal()
175 .description("Check failed with exception: " + e.getClass().getCanonicalName() + " " + e.getMessage())
176 .build();
177
178 }
179
180 private boolean existsAndReadable(String filename) {
181 return null != filename && new File(filename).canRead();
182 }
183
184 public IBatchManager getBatchManager() {
185 return batchManager;
186 }
187
188 public IBatchProgressMonitor getBatchProgressMonitor(String name, String group, String uuid) {
189
190 checkInit();
191
192 IBatch batch = null;
193 if (batchManager != null) {
194 batch = batchManager.addBatch(name, group, uuid);
195 return batchManager.getMonitor(batch);
196 }
197
198 return null;
199 }
200
201
202
203
204 public IBatchScheduleManager getBatchScheduleManager() {
205 return batchScheduleManager;
206 }
207
208
209
210
211
212
213
214
215 private Object getClassInstance(String className) {
216 Object obj = null;
217
218 if (objectInstanciationListener != null) {
219 obj = objectInstanciationListener.getInstance(className);
220 }
221
222 if (obj == null) {
223 try {
224 obj = Thread.currentThread().getContextClassLoader().loadClass(className).newInstance();
225 } catch (ClassNotFoundException e) {
226 logger.warn("Class {} not found ", className, e);
227 } catch (InstantiationException e) {
228 logger.warn("Cannot instanciate {} ", className, e);
229 } catch (IllegalAccessException e) {
230 logger.warn("Cannot access class {} for instantiation ", className, e);
231 }
232 }
233
234 if (obj == null) {
235 try {
236 obj = Class.forName(className).newInstance();
237 logger.warn("Class {} loaded using a deprecated method. Please report to http://sourceforge.net/apps/mantisbt/appstatus/login_select_proj_page.php?ref=bug_report_page.php", className);
238 } catch (ClassNotFoundException e) {
239 logger.warn("Class {} not found ", className, e);
240 } catch (InstantiationException e) {
241 logger.warn("Cannot instanciate {} ", className, e);
242 } catch (IllegalAccessException e) {
243 logger.warn("Cannot access class {} for instantiation ", className, e);
244 }
245 }
246
247 if (obj != null) {
248 injectServletContext(obj);
249 }
250
251 return obj;
252 }
253
254 protected Properties getConfiguration() {
255 return this.configuration;
256 }
257
258 public ILoggersManager getLoggersManager() {
259 return loggersManager;
260 }
261
262 public String getMaintenanceFile() {
263 return maintenanceFile;
264 }
265
266 public Map<String, Map<String, String>> getProperties() {
267 checkInit();
268
269 TreeMap<String, Map<String, String>> categories = new TreeMap<String, Map<String, String>>();
270
271 for (IPropertyProvider provider : propertyProviders) {
272 injectServletContext(provider);
273
274
275 if (categories.get(provider.getCategory()) == null) {
276 categories.put(provider.getCategory(), new TreeMap<String, String>());
277 }
278
279
280 Map<String, String> l = categories.get(provider.getCategory());
281 l.putAll(provider.getProperties());
282 }
283 return categories;
284 }
285
286 @Deprecated
287 public List<IBatch> getRunningBatches() {
288 return batchManager.getRunningBatches();
289 }
290
291 public IServiceManager getServiceManager() {
292 return serviceManager;
293 }
294
295 public IServiceMonitor getServiceMonitor(String name, String group) {
296 checkInit();
297
298 IService service = null;
299 if (serviceManager != null) {
300 service = serviceManager.getService(name, group);
301 return serviceManager.getMonitor(service);
302 }
303
304 return null;
305 }
306
307 public List<IService> getServices() {
308 if (serviceManager == null) {
309 return null;
310 }
311
312 return serviceManager.getServices();
313 }
314
315 public IServletContextProvider getServletContext() {
316 return servletContextProvider;
317 }
318
319 public synchronized void init() {
320
321 if (initDone) {
322 logger.warn("Already initialized");
323 return;
324 }
325 executorService = Executors.newCachedThreadPool();
326
327
328 loadPlugins();
329
330
331 if (checkers != null || propertyProviders != null || configuration != null) {
332 logger.info("Configuration is injected : skip loading properties from classpath");
333 } else {
334
335
336 checkers = new ArrayList<ICheck>();
337 propertyProviders = new ArrayList<IPropertyProvider>();
338 configuration = new Properties();
339
340 try {
341
342
343 Enumeration<URL> configFiles;
344
345 configFiles = Thread.currentThread().getContextClassLoader().getResources(CONFIG_LOCATION);
346
347 if (configFiles == null) {
348 logger.info("config file {} not found in classpath", CONFIG_LOCATION);
349 return;
350 }
351
352 while (configFiles.hasMoreElements()) {
353 Properties p = loadProperties(configFiles.nextElement());
354
355 configuration.putAll(p);
356
357 Set<Object> keys = p.keySet();
358 for (Object oName : keys) {
359 String name = (String) oName;
360 String clazz = (String) p.get(name);
361 if (name.startsWith("check")) {
362 addStatusChecker(clazz);
363 } else if (name.startsWith("property")) {
364 addPropertyProvider(clazz);
365 } else {
366 logger.debug("Global property {} : {} ", name, clazz);
367 }
368 }
369 }
370
371 } catch (Exception e) {
372 logger.error("Initialization error", e);
373 }
374 }
375
376
377
378 if (configuration == null) {
379 configuration = new Properties();
380 }
381
382
383 if (getBatchManager() != null) {
384 Properties newConfiguration = getBatchManager().getConfiguration();
385
386 if (newConfiguration != null) {
387 newConfiguration.putAll(configuration);
388 } else {
389 newConfiguration = configuration;
390 }
391
392 getBatchManager().setConfiguration(newConfiguration);
393 }
394 if (getServiceManager() != null) {
395 Properties newConfiguration = getServiceManager().getConfiguration();
396
397 if (newConfiguration != null) {
398 newConfiguration.putAll(configuration);
399 } else {
400 newConfiguration = configuration;
401 }
402
403 getServiceManager().setConfiguration(newConfiguration);
404 }
405
406 if (getLoggersManager() != null) {
407 Properties newConfiguration = getLoggersManager().getConfiguration();
408
409 if (newConfiguration != null) {
410 newConfiguration.putAll(configuration);
411 } else {
412 newConfiguration = configuration;
413 }
414
415 getLoggersManager().setConfiguration(newConfiguration);
416 }
417
418 if (null == maintenanceFile) {
419 String path = System.getProperty("java.io.tmpdir");
420 if (!path.endsWith(File.separator)) {
421 path += File.separator;
422 }
423 path += "appstatus-maintenance";
424 maintenanceFile = path;
425 }
426
427 initDone = true;
428
429 }
430
431 private void injectServletContext(Object instance) {
432
433 if (instance instanceof IServletContextAware && servletContextProvider != null) {
434 ((IServletContextAware) instance).setServletContext(servletContextProvider.getServletContext());
435 }
436 }
437
438 public boolean isMaintenance() {
439 return maintenance || existsAndReadable(maintenanceFile);
440 }
441
442
443
444
445
446
447
448 private void loadPlugins() {
449 int count = 0;
450 try {
451 Enumeration<URL> plugins = Thread.currentThread().getContextClassLoader().getResources("net/sf/appstatus/plugin.properties");
452
453 while (plugins.hasMoreElements()) {
454 URL url = plugins.nextElement();
455 logger.info("AppStatus: found plugin: " + url.toString());
456 Properties p = loadProperties(url);
457
458
459 String batchManagerClass = p.getProperty("batchManager");
460 if (batchManagerClass != null && batchManager == null) {
461 batchManager = (IBatchManager) getClassInstance(batchManagerClass);
462 }
463
464
465 String serviceManagerClass = p.getProperty("serviceManager");
466 if (serviceManagerClass != null && serviceManager == null) {
467 serviceManager = (IServiceManager) getClassInstance(serviceManagerClass);
468 }
469
470
471 String loggersManagerClass = p.getProperty("loggersManager");
472 if (loggersManagerClass != null && loggersManager == null) {
473 loggersManager = (ILoggersManager) getClassInstance(loggersManagerClass);
474 }
475
476 count++;
477 }
478 } catch (IOException e) {
479 logger.warn("AppStatus: Error loading plugins", e);
480 }
481 logger.info("AppStatus: found {} plugins", count);
482 }
483
484
485
486
487
488
489
490
491
492
493 private Properties loadProperties(URL url) throws IOException {
494
495 Properties p = new Properties();
496 InputStream is = url.openStream();
497 p.load(is);
498 is.close();
499 return p;
500 }
501
502 public void setBatchManager(IBatchManager batchManager) {
503 this.batchManager = batchManager;
504 }
505
506
507
508
509
510 public void setBatchScheduleManager(IBatchScheduleManager batchScheduleManager) {
511 this.batchScheduleManager = batchScheduleManager;
512 }
513
514 public void setCheckers(List<ICheck> checkers) {
515 this.checkers = checkers;
516 }
517
518 public void setConfiguration(Properties configuration) {
519 this.configuration = configuration;
520 }
521
522 public void setMaintenance(boolean maintenanceMode) throws IOException {
523 this.maintenance = maintenanceMode;
524
525 if (null == maintenanceFile) {
526 return;
527 }
528
529 File modeFile = new File(maintenanceFile);
530
531 if (maintenanceMode) {
532 modeFile.createNewFile();
533 } else if (modeFile.exists() && !modeFile.delete()) {
534 throw new IOException("Unable to delete maintenance file");
535 }
536
537 }
538
539 public void setMaintenanceFile(String maintenanceModeFile) {
540 this.maintenanceFile = maintenanceModeFile;
541 }
542
543 public void setObjectInstanciationListener(IObjectInstantiationListener objectInstanciationListener) {
544 this.objectInstanciationListener = objectInstanciationListener;
545 }
546
547 public void setPropertyProviders(List<IPropertyProvider> propertyProviders) {
548 this.propertyProviders = propertyProviders;
549 }
550
551 public void setServiceManager(IServiceManager serviceManager) {
552 this.serviceManager = serviceManager;
553 }
554
555 public void setServletContextProvider(IServletContextProvider servletContext) {
556 this.servletContextProvider = servletContext;
557 }
558
559 }