1
18 package org.torweg.pulse.invocation.lifecycle;
19
20 import java.io.File;
21 import java.io.UnsupportedEncodingException;
22 import java.security.NoSuchAlgorithmException;
23 import java.security.SecureRandom;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Random;
30 import java.util.Set;
31 import java.util.Timer;
32 import java.util.TimerTask;
33 import java.util.concurrent.ConcurrentHashMap;
34
35 import javax.xml.bind.JAXBContext;
36 import javax.xml.bind.JAXBException;
37 import javax.xml.bind.Unmarshaller;
38
39 import org.apache.fop.apps.FopFactory;
40 import org.apache.log4j.NDC;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43 import org.torweg.pulse.accesscontrol.attributes.AttributeFactory;
44 import org.torweg.pulse.annotations.Action.Security;
45 import org.torweg.pulse.bundle.Bundle;
46 import org.torweg.pulse.bundle.JobletScheduler;
47 import org.torweg.pulse.component.Component;
48 import org.torweg.pulse.configuration.Configuration;
49 import org.torweg.pulse.configuration.ConfigurationException;
50 import org.torweg.pulse.configuration.PoorMansCache;
51 import org.torweg.pulse.email.MailQueue;
52 import org.torweg.pulse.email.MailQueueConfiguration;
53 import org.torweg.pulse.service.ServletConfig;
54 import org.torweg.pulse.service.request.Locale;
55 import org.torweg.pulse.service.request.LocaleManager;
56 import org.torweg.pulse.util.HibernateDataSource;
57 import org.torweg.pulse.util.HibernateDataSourceImpl;
58 import org.torweg.pulse.util.captcha.ICaptchaAdapter;
59 import org.torweg.pulse.util.geolocation.IGeoLocationProvider;
60 import org.torweg.pulse.util.geolocation.NoLookupLocationProvider;
61 import org.torweg.pulse.vfs.VirtualFileSystem;
62
63 import com.sun.jersey.api.json.JSONJAXBContext;
64
65
91 public final class Lifecycle {
92
93
96 private static final Logger LOGGER = LoggerFactory
97 .getLogger(Lifecycle.class);
98
99
102 private static Lifecycle lifecycleInstance;
103
104
107 private static Random random;
108
109
112 private final File pulseRootDir;
113
114
117 private final File coreConfigDir;
118
119
122 private final File bundlesRootDir;
123
124
127 private final ConcurrentHashMap<String, Bundle> bundles = new ConcurrentHashMap<String, Bundle>();
128
129
132 private final Set<Component> components = new HashSet<Component>();
133
134
137 private Timer timer;
138
139
142 private HibernateDataSourceImpl hibernateDataSource;
143
144
147 private Collection<Locale> locales;
148
149
152 private JAXBContext jaxbContext;
153
154
157 private MailQueue mailQueue;
158
159
162 private IGeoLocationProvider geoLocationProvider;
163
164
167 private ICaptchaAdapter<?> captchaAdapter;
168
169
172 private AttributeFactory attributeFactory;
173
174
177 private WatchDog watchDog;
178
179
182 private FopFactory fopFactoryInstance;
183
184
187 private JSONJAXBContext jsonJaxbContext;
188
189
194 private byte[] serverSalt;
195
196
202 private Lifecycle(final File pulseWebapp) {
203 this.pulseRootDir = pulseWebapp;
204 this.coreConfigDir = new File(this.pulseRootDir, "WEB-INF"
205 + File.separator + "conf");
206 this.bundlesRootDir = new File(pulseWebapp, "WEB-INF" + File.separator
207 + "bundles");
208 }
209
210
215 public static AttributeFactory getAttributeFactory() {
216 if (lifecycleInstance != null) {
217 return lifecycleInstance.attributeFactory;
218 }
219 throw new LifecycleException("The Lifecycle has not been started.");
220 }
221
222
225 public static Collection<Bundle> getBundles() {
226 if (lifecycleInstance != null) {
227 return lifecycleInstance.bundles.values();
228 }
229 throw new LifecycleException("The Lifecycle has not been started.");
230 }
231
232
239 public static Bundle getBundle(final String name) {
240 if (lifecycleInstance != null) {
241 return lifecycleInstance.bundles.get(name);
242 }
243 throw new LifecycleException("The Lifecycle has not been started.");
244 }
245
246
247
248
253 public static File getBasePath() {
254 if (lifecycleInstance != null) {
255 return lifecycleInstance.pulseRootDir.getAbsoluteFile();
256 }
257 throw new LifecycleException("The Lifecycle has not been started.");
258 }
259
260
265 public static HibernateDataSource getHibernateDataSource() {
266 if (lifecycleInstance != null) {
267 return lifecycleInstance.hibernateDataSource;
268 }
269 throw new LifecycleException("The Lifecycle has not been started.");
270 }
271
272
277 public static IGeoLocationProvider getGeoLocationProvider() {
278 if (lifecycleInstance != null) {
279 return lifecycleInstance.geoLocationProvider;
280 }
281 throw new LifecycleException("The Lifecycle has not been started.");
282 }
283
284
289 public static ICaptchaAdapter<?> getCaptchaAdapter() {
290 if (lifecycleInstance != null) {
291 return lifecycleInstance.captchaAdapter;
292 }
293 throw new LifecycleException("The Lifecycle has not been started.");
294 }
295
296
302 public static FopFactory getFopFactory() {
303 if (lifecycleInstance != null) {
304 return lifecycleInstance.fopFactoryInstance;
305 }
306 throw new LifecycleException("The Lifecycle has not been started.");
307 }
308
309
313 public static JAXBContext getJAXBContext() {
314 return lifecycleInstance.jaxbContext;
315 }
316
317
322 public static JSONJAXBContext getJSONJAXBContext() {
323 return lifecycleInstance.jsonJaxbContext;
324 }
325
326
332 public static Collection<java.util.Locale> getKnownLocales() {
333 if (lifecycleInstance != null) {
334 return convertLocaleList(lifecycleInstance.locales, false);
335 }
336 throw new LifecycleException("The Lifecycle has not been started.");
337 }
338
339
345 public static Collection<java.util.Locale> getActiveLocales() {
346 if (lifecycleInstance != null) {
347 return convertLocaleList(lifecycleInstance.locales, true);
348 }
349 throw new LifecycleException("The Lifecycle has not been started.");
350 }
351
352
357 public static MailQueue getMailQueue() {
358 if (lifecycleInstance != null) {
359 return lifecycleInstance.mailQueue;
360 }
361 throw new LifecycleException("The Lifecycle has not been started.");
362 }
363
364
369 public static boolean isTransportLayerSecurityAvailable() {
370 if (lifecycleInstance != null) {
371 return lifecycleInstance.getPulseConfiguration()
372 .isTransportLayerSecurityAvailable();
373 }
374 throw new LifecycleException("The Lifecycle has not been started.");
375 }
376
377
384 public static Security getWeakestCommandSecurityLevel() {
385 if (lifecycleInstance != null) {
386 return lifecycleInstance.getPulseConfiguration()
387 .getWeakestCommandSecurityLevel();
388 }
389 throw new LifecycleException("The Lifecycle has not been started.");
390 }
391
392
397 public static int getDefaultPort() {
398 if (lifecycleInstance != null) {
399 return lifecycleInstance.getPulseConfiguration().getDefaultPort();
400 }
401 throw new LifecycleException("The Lifecycle has not been started.");
402 }
403
404
409 public static int getSecurePort() {
410 if (lifecycleInstance != null) {
411 return lifecycleInstance.getPulseConfiguration().getSecurePort();
412 }
413 throw new LifecycleException("The Lifecycle has not been started.");
414 }
415
416
422 public static String getVersioningPrefix() {
423 if (lifecycleInstance != null) {
424 return lifecycleInstance.getPulseConfiguration()
425 .getVersioningPrefix();
426 }
427 throw new LifecycleException("The Lifecycle has not been started.");
428 }
429
430
436 public static Random getRandom() {
437 return random;
438 }
439
440
447 public static byte[] getSaltedHash(final byte[] src) {
448 if (lifecycleInstance.serverSalt.length == 0) {
449 return src;
450 }
451 byte[] salted = new byte[src.length
452 + lifecycleInstance.serverSalt.length];
453 System.arraycopy(src, 0, salted, 0, src.length);
454 System.arraycopy(lifecycleInstance.serverSalt, 0, salted, src.length,
455 lifecycleInstance.serverSalt.length);
456 return salted;
457 }
458
459
465 public static synchronized void startup(final File pulseWebapp) { if (lifecycleInstance == null) {
467 Lifecycle localLifecycle = new Lifecycle(pulseWebapp);
468 lifecycleInstance = localLifecycle;
469 localLifecycle.init();
470 } else {
471 throw new LifecycleException("Lifecycle has already been started.");
472 }
473 LOGGER.info("The Lifecycle has begun...");
474 }
475
476
479 @Deprecated
480 public static Lifecycle getInstance() {
481 if (lifecycleInstance == null) {
482 throw new LifecycleException("Lifecycle has not been started.");
483 }
484 return lifecycleInstance;
485 }
486
487
490 public static synchronized void shutdown() { if (lifecycleInstance == null) {
492 throw new LifecycleException("Lifecycle has not been started.");
493 }
494 lifecycleInstance.destroy();
495 lifecycleInstance = null; LOGGER.info("The Lifecycle has stopped...");
497 }
498
499
500
501
506 protected File getPulseRootDir() {
507 return this.pulseRootDir;
508 }
509
510
515 protected Collection<Locale> getLocalesDirectly() {
516 return this.locales;
517 }
518
519
524 protected Set<Component> getComponentsDirectly() {
525 return this.components;
526 }
527
528
533 protected ConcurrentHashMap<String, Bundle> getBundlesDirectly() {
534 return this.bundles;
535 }
536
537
542 protected HibernateDataSourceImpl getHibernateDatasourceDirectly() {
543 return this.hibernateDataSource;
544 }
545
546
552 protected void setHibernateDataSourceDirectly(
553 final HibernateDataSourceImpl ds) {
554 this.hibernateDataSource = ds;
555 }
556
557
562 protected MailQueue getMailQueueDirectly() {
563 return this.mailQueue;
564 }
565
566
572 protected void setMailQueueDirectly(final MailQueue mc) {
573 this.mailQueue = mc;
574 }
575
576
581 protected ServletConfig getPulseConfiguration() {
582 return (ServletConfig) PoorMansCache.getConfig(new File(
583 this.coreConfigDir, "pulse.xml"));
584 }
585
586
592 protected void setJAXBContext(final JAXBContext ctx) {
593 this.jaxbContext = ctx;
594 }
595
596
602 protected void setJSONJAXBContext(final JSONJAXBContext context) {
603 this.jsonJaxbContext = context;
604 }
605
606
612 protected void setAttributeFactoryDirectly(final AttributeFactory factory) {
613 this.attributeFactory = factory;
614 }
615
616
628 protected static Collection<java.util.Locale> convertLocaleList(
629 final Collection<Locale> collection, final boolean onlyActive) {
630 Set<java.util.Locale> locs = new HashSet<java.util.Locale>();
631 for (Locale l : collection) {
632 if (onlyActive && l.isInactive()) {
633 continue;
634 }
635 locs.add(LocaleManager.localeToLocale(l));
636 }
637 return locs;
638 }
639
640
641
642
645 private void init() {
646
647
648 createRandom();
649
650
651 LifecycleJAXBTasks.initialiseJAXBContext(this);
652
653
654 initialiseLocalCache(this);
655
656
657 initializeJobletScheduler();
658
659
660 initialiseComponents();
661
662
663 List<File> bundleDirs = identifyBundles();
664
665
666 LifecycleBundleTasks.initialiseBundles(bundleDirs, this);
667
668
669 LifecycleJAXBTasks.initialiseJAXBContext(this);
670
671
672 LifecycleHibernateTasks.initialiseHibernate(this);
673
674
675 LifecycleHibernateTasks.initialiseRegistries(this);
676
677
678 LifecycleBundleTasks.processControllerAnnotations(this);
679
680
681 LifecycleAccessControlTasks.initialiseUsersAndGroups(this);
682
683
684 LifecycleAttributeTasks.initializeAttributeFactory(this);
685
686
687 try {
688 PoorMansCache.getXSLHandle(new File(this.pulseRootDir
689 .getAbsolutePath()
690 + File.separator
691 + "WEB-INF"
692 + File.separator
693 + "xsl"
694 + File.separator + "main.xsl"));
695 } catch (ConfigurationException e) {
696 LOGGER.error(e.getLocalizedMessage(), e);
697 }
698
699
700 LifecycleMailQueueTasks.startMailQueue(this);
701
702
703 startGeoLocationProvider(this);
704
705
706 initializeCaptchaAdapter(this);
707
708
709 initializeFopFactoryInstance(this);
710
711
712 initialiseVirtualFileSystem();
713
714
715 JobletScheduler.resume();
716
717
718 startWatchDog();
719
720 }
721
722
725 private void destroy() {
726
727 stopWatchDog(this);
728
729
730 JobletScheduler.pause();
731
732
733 LifecycleBundleTasks.stopBundles(this);
734
735
736 stopJobletScheduler();
737
738
739 LifecycleMailQueueTasks.stopMailQueue(this);
740
741
742 if (this.hibernateDataSource != null) {
743 this.hibernateDataSource.close();
744 } else {
745 LOGGER.warn("The HibernateDataSource was null.");
746 }
747
748
749 if (this.geoLocationProvider != null) {
750 this.geoLocationProvider.shutdown();
751 } else {
752 LOGGER.info("The GeoLocationProvider was null.");
753 }
754
755
756 stopLocalCache();
757 }
758
759
762 private void createRandom() {
763 try {
764 random = SecureRandom.getInstance("SHA1PRNG");
765 } catch (NoSuchAlgorithmException e) {
766 LOGGER.warn("Not using SecureRandom: {}", e.getLocalizedMessage());
767 random = new Random();
768 random.setSeed(System.currentTimeMillis());
769 }
770 }
771
772
775 private void stopLocalCache() {
776 LOGGER.trace("Stopping the local cache...");
777 if (PoorMansCache.getInstance() != null) {
778 ((PoorMansCache) PoorMansCache.getInstance()).shutdown();
779 } else {
780 LOGGER.info("PoorMansCache was null.");
781 }
782 this.locales = null; LOGGER.info("Local cache stopped.");
784 }
785
786
789 private void stopJobletScheduler() {
790 LOGGER.trace("Stopping the JobletScheduler...");
791 try {
792 JobletScheduler.stop();
793 } catch (Exception e) {
794 LOGGER.error("Cannot stop the JobletScheduler: ", e);
795 }
796 }
797
798
801 private void startWatchDog() {
802 ServletConfig servletConfig = getPulseConfiguration();
803 if (servletConfig.isReloadable()) {
804 LOGGER.trace("Initialising the WatchDog...");
805 this.timer = new Timer();
806 this.watchDog = new WatchDog();
807 this.timer.scheduleAtFixedRate(this.watchDog, servletConfig
808 .getReloadInterval(), servletConfig.getReloadInterval());
809 LOGGER.info("WatchDog initialised.");
810 }
811 }
812
813
819 private void stopWatchDog(final Lifecycle lc) {
820 if (lc.timer != null) {
821 LOGGER.trace("Stopping the WatchDog...");
822 lc.timer.cancel();
823 long start = System.currentTimeMillis();
824
825 while (lc.watchDog.isRunning()
826 && (System.currentTimeMillis() - start < 30000)) {
827 try {
828 Thread.sleep(100);
829 } catch (InterruptedException e) {
830 LOGGER.trace("Error stopping the WatchDog: {}", e
831 .getLocalizedMessage());
832 }
833 }
834 LOGGER.info("WatchDog stopped.");
835 } else {
836 LOGGER.info("The WatchDog has not been started.");
837 }
838 }
839
840
846 private void initialiseLocalCache(final Lifecycle lc) {
847 LOGGER.trace("Initialising local cache...");
848 PoorMansCache.init(this.coreConfigDir);
849 PoorMansCache.getInstance();
850
851
852 ServletConfig pulseConfiguration = getPulseConfiguration();
853 LOGGER.info("Local cache initialised with a reload interval of {} ms.",
854 pulseConfiguration.getReloadInterval());
855 try {
856 lc.serverSalt = pulseConfiguration.getServerSalt()
857 .getBytes("utf-8");
858 } catch (UnsupportedEncodingException e) {
859 LOGGER.warn(e.getLocalizedMessage());
860 lc.serverSalt = pulseConfiguration.getServerSalt().getBytes();
861 }
862 lc.locales = LocaleManager.getInstance().getLocales();
863 }
864
865
868 private void initializeJobletScheduler() {
869 LOGGER.trace("Initialising the JobletScheduler...");
870 try {
871 JobletScheduler.startPaused(getPulseConfiguration()
872 .getJobletSchedulerConfiguration());
873 } catch (Exception exception) {
874 LOGGER.error("Cannot initialise the JobletScheduler: ", exception);
875 }
876 }
877
878
884 private void startGeoLocationProvider(final Lifecycle lc) {
885
886 try {
887 LOGGER.debug("Starting GeoLocationProvider...");
888 IGeoLocationProvider locationProvider = getPulseConfiguration()
889 .getGeoLocationProvider().newInstance();
890 locationProvider.startup();
891 lc.geoLocationProvider = locationProvider;
892 LOGGER.info("GeoLocationProvider [{}] started.", locationProvider
893 .getClass().getCanonicalName());
894 } catch (Exception e) {
895 LOGGER.error("Could not setup GeoLocationProvider, "
896 + "using NoLookupLocationProvider instead: {}", e
897 .getLocalizedMessage());
898 this.geoLocationProvider = new NoLookupLocationProvider();
899 }
900 }
901
902
907 private List<File> indentifyComponents() {
908 LOGGER.trace("Identifying components...");
909
910 ArrayList<File> identifiedComponents = new ArrayList<File>();
911 File[] entries = new File(this.pulseRootDir, "WEB-INF" + File.separator
912 + "components").listFiles();
913 if (entries == null) {
914 entries = new File[1];
915 }
916
917
918 for (File entry : entries) {
919 if (entry.isDirectory()) {
920 LOGGER.trace("Checking component '" + entry.getName()
921 + "' in '" + entry.getAbsolutePath() + "'.");
922 if (new File(entry, "component.xml").exists()) {
923 identifiedComponents.add(entry);
924 LOGGER.debug("Found component '" + entry.getName()
925 + "' in '" + entry.getAbsolutePath() + "'.");
926 } else {
927 LOGGER.warn("Missing 'component.xml' in '"
928 + entry.getAbsolutePath()
929 + "' -> Component will not be initialised.");
930 }
931
932 }
933 }
934
935
936 if (identifiedComponents.isEmpty()) {
937 LOGGER.error("The container contains no components!");
938 }
939 return identifiedComponents;
940 }
941
942
945 private void initialiseComponents() {
946 Set<Component> localComponents = new HashSet<Component>();
947 Unmarshaller unmarshaller;
948 try {
949 unmarshaller = this.jaxbContext.createUnmarshaller();
950 } catch (JAXBException e) {
951 throw new LifecycleException("Error initialising Unmarshaller: "
952 + e.getLocalizedMessage(), e);
953 }
954
955 for (File configFile : indentifyComponents()) {
956 try {
957 localComponents.add((Component) unmarshaller
958 .unmarshal(new File(configFile, "component.xml")));
959 } catch (JAXBException e) {
960 throw new LifecycleException("Error initialising component ["
961 + configFile.getName() + "]: "
962 + e.getLocalizedMessage(), e);
963 }
964 }
965
966 this.components.clear();
967 this.components.addAll(localComponents);
968 }
969
970
975 private List<File> identifyBundles() {
976 LOGGER.trace("Identifying bundles...");
977
978 ArrayList<File> identifiedBundles = new ArrayList<File>();
979 File[] entries = this.bundlesRootDir.listFiles();
980 if (entries == null) {
981 entries = new File[1];
982 }
983
984
985 for (File entry : entries) {
986 if (entry.isDirectory()) {
987 LOGGER.trace("Checking bundle '" + entry.getName() + "' in '"
988 + entry.getAbsolutePath() + "'.");
989 if (new File(entry, "bundle.xml").exists()) {
990 identifiedBundles.add(entry);
991 LOGGER.debug("Found bundle '" + entry.getName() + "' in '"
992 + entry.getAbsolutePath() + "'.");
993 } else {
994 LOGGER.warn("Missing 'bundle.xml' in '"
995 + entry.getAbsolutePath()
996 + "' -> Bundle will not be loaded.");
997 }
998
999 }
1000 }
1001
1002
1003 if (identifiedBundles.isEmpty()) {
1004 LOGGER.error("The container contains no bundles!");
1005 }
1006 return identifiedBundles;
1007 }
1008
1009
1012 private void initialiseVirtualFileSystem() {
1013 VirtualFileSystem.init(getPulseConfiguration().getVFSConfiguration());
1014 LOGGER.info("Initialised VirtualFileSystem.");
1015 }
1016
1017
1023 private void initializeCaptchaAdapter(final Lifecycle lc) {
1024
1025 try {
1026
1027 if (getPulseConfiguration().getCaptchaAdapter() != null) {
1028
1029 LOGGER.debug("Setting-up captcha-adapter...");
1030
1031 ICaptchaAdapter<Configuration> adapter = getPulseConfiguration()
1032 .getCaptchaAdapter().newInstance();
1033
1034 adapter.initialize(PoorMansCache.getConfiguration(new File(
1036 this.coreConfigDir, adapter.getClass()
1037 .getCanonicalName()
1038 + ".xml")));
1039
1040 lc.captchaAdapter = adapter;
1041
1042 LOGGER.info("Captcha-adapter [{}] set up.", adapter.getClass()
1043 .getCanonicalName());
1044
1045 } else {
1046 LOGGER
1047 .info("Captcha-adapter: Not configured! Not available! Howto: "
1048 + "Add <captcha-adapter class=\"your.available.implementation.of.ICaptchaAdapter\"/> "
1049 + "to pulse.xml. "
1050 + "Add the your.available.implementation.of.ICaptchaAdapter.xml to WEB-INF/conf.");
1051 }
1052
1053 } catch (Exception e) {
1054 LOGGER.error("Setting-up captcha-adapter has failed: {}", e
1055 .getLocalizedMessage());
1056 }
1057 }
1058
1059
1065 private void initializeFopFactoryInstance(final Lifecycle lc) {
1066 try {
1067 FopFactory fopFactory = FopFactory.newInstance();
1069 if (getPulseConfiguration().getFopPath() != null) {
1071 File file = new File(getBasePath(), getPulseConfiguration()
1072 .getFopPath());
1073 if (file.exists()) {
1075 File fopConf = new File(file, "fop.conf.xml");
1076 if (fopConf.exists()) {
1077 fopFactory
1078 .setUserConfig(new File(file, "fop.conf.xml"));
1079 LOGGER.info(
1080 "Configured FopFactory with configuration: {}",
1081 fopConf.toURL());
1082 }
1083 fopFactory.setBaseURL(file.toURL().toString());
1084 fopFactory.setFontBaseURL(file.toURL().toString());
1085 }
1086 }
1087 lc.fopFactoryInstance = fopFactory;
1089 LOGGER.info("FopFactory uses base-url: " + fopFactory.getBaseURL());
1090 LOGGER.info("FopFactory uses font-base-url: "
1091 + fopFactory.getFontBaseURL());
1092 } catch (Exception e) {
1093 LOGGER.error("Initialising FopFactory has failed..."
1094 + e.getLocalizedMessage(), e);
1095 }
1096 }
1097
1098
1101 protected File getBundlesRootDir() {
1102 return this.bundlesRootDir;
1103 }
1104
1105
1108 private class WatchDog extends TimerTask {
1109
1110
1113 private boolean running = false;
1114
1115
1118 @Override
1119 public void run() {
1120 synchronized (this) {
1121 if (this.running) {
1122 return;
1123 }
1124 this.running = true;
1125 }
1126 try {
1127 NDC.push("watchdog");
1128 LOGGER.trace("WatchDog: run()");
1129
1130 boolean cacheChanges = checkLocalCache((PoorMansCache) PoorMansCache
1131 .getInstance());
1132
1133
1134 boolean bundleChanges = checkBundles();
1135
1136
1140 if (cacheChanges || bundleChanges) {
1141 LifecycleJAXBTasks.initialiseJAXBContext(lifecycleInstance);
1142 LifecycleBundleTasks
1143 .processControllerAnnotations(lifecycleInstance);
1144 }
1145
1146
1147 if (geoLocationProvider.isModified()) {
1148 LOGGER.info("restarting GeoLocationProvider.");
1149 geoLocationProvider.restart();
1150 }
1151 } finally {
1152 synchronized (this) {
1153 this.running = false;
1154 }
1155 NDC.pop();
1156 NDC.remove();
1157 }
1158
1159 }
1160
1161
1167 public final boolean isRunning() {
1168 return this.running;
1169 }
1170
1171
1178 private boolean checkLocalCache(final PoorMansCache pool) {
1179 if (pool.isModified()) {
1180 pool.restart();
1181 LOGGER.info("WatchDog: Config pool reloaded.");
1182
1183 reconfigureMailQueue();
1184
1185 geoLocationProvider.restart();
1186 return true;
1187 }
1188 return false;
1189 }
1190
1191
1194 private void reconfigureMailQueue() {
1195 MailQueueConfiguration conf = new MailQueueConfiguration();
1196 conf.init(getPulseConfiguration().getMailQueueConfiguration());
1197 conf.setPulseRootDir(getBasePath());
1198 getMailQueue().reconfigure(conf);
1199 }
1200
1201
1206 private boolean checkBundles() {
1207 File[] bundleDirectories = getBundlesRootDir().listFiles();
1208 if (bundleDirectories == null) {
1209 LOGGER
1210 .debug("Bundle check aborted: Could not list bundle directory.");
1211 return false;
1212 }
1213 ArrayList<File> possibleBundles = new ArrayList<File>(Arrays
1214 .asList(bundleDirectories));
1215
1216 boolean initializedBundles = checkInitializedBundles(possibleBundles);
1217
1218
1219 boolean newBundles = checkNewBundles(possibleBundles);
1220
1221 return (initializedBundles | newBundles);
1222 }
1223
1224
1231 private boolean checkNewBundles(final List<File> newBundles) {
1232 boolean changed = false;
1233 for (File f : newBundles) {
1234 if ((f.isDirectory()) && (new File(f, "bundle.xml").exists())) {
1235 try {
1236 Bundle bundle = LifecycleBundleTasks.initBundle(f,
1237 lifecycleInstance);
1238 lifecycleInstance.bundles.put(bundle.getName(), bundle);
1239 LOGGER.info("WatchDog: Bundle '{}' loaded.", bundle
1240 .getName());
1241 changed = true;
1242 } catch (LifecycleException e) {
1243 LOGGER.error("WatchDog: Bundle defined in '"
1244 + f.getAbsolutePath() + "' cannot be loaded.",
1245 e);
1246 }
1247 }
1248 }
1249 return changed;
1250 }
1251
1252
1260 private boolean checkInitializedBundles(
1261 final List<File> initializedBundles) {
1262 boolean changed = false;
1263 for (Bundle bundle : getBundles()) {
1264 if (!bundle.getDirectory().exists()) {
1265
1266 PoorMansCache.flushBundle(bundle);
1267 changed = true;
1268 } else if (bundle.isModified()) {
1269 PoorMansCache.flushBundle(bundle);
1270
1271 initializedBundles.remove(bundle.getDirectory());
1272 try {
1273 bundle.restart();
1274 LOGGER.info("WatchDog: Bundle '{}' reloaded.", bundle
1275 .getName());
1276 changed = true;
1277 } catch (LifecycleException e) {
1278 LOGGER.error("WatchDog: Bundle '" + bundle.getName()
1279 + "' cannot be reloaded.", e);
1280 }
1281 } else {
1282
1283 initializedBundles.remove(bundle.getDirectory());
1284 }
1285 }
1286 return changed;
1287 }
1288 }
1289
1290 }
1291