1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.classpathwatch;
35
36 import info.magnolia.init.MagnoliaConfigurationProperties;
37
38 import java.io.IOException;
39 import java.net.URL;
40 import java.util.concurrent.Executors;
41 import java.util.concurrent.Future;
42 import java.util.concurrent.ScheduledExecutorService;
43 import java.util.concurrent.TimeUnit;
44
45 import javax.inject.Inject;
46 import javax.inject.Singleton;
47 import javax.servlet.ServletContext;
48
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 import com.google.common.base.Function;
53 import com.google.common.base.Predicate;
54
55
56
57
58 @Singleton
59 public class ClasspathScannerService {
60
61 private static final int SCAN_INTERVAL = 10;
62
63 private static final Logger log = LoggerFactory.getLogger(ClasspathScannerService.class);
64
65 private final ServletContext servletContext;
66 private final boolean devMode;
67
68 private ScheduledExecutorService executorService;
69 private ClasspathScanner scanner;
70
71 private Future<?> scannerFuture;
72
73 @Inject
74 public ClasspathScannerService(MagnoliaConfigurationProperties mcp, ServletContext servletContext) throws IOException {
75 this.servletContext = servletContext;
76 this.devMode = mcp.getBooleanProperty("magnolia.develop");
77 if (!devMode) {
78 log.info("Not in dev mode, will not watch resource changes on the classpath.");
79 }
80 }
81
82 public void start() {
83 }
84
85 public boolean isEnabled() {
86 return devMode;
87 }
88
89
90
91
92 public synchronized void watch(Predicate<String> resourcesFilter, Predicate<? super URL> urlsFilter, Function<String, Void> callbackFunction) {
93 if (!devMode) {
94 return;
95 }
96
97
98
99
100
101
102
103
104
105 if (scannerFuture == null) {
106 scanner = new ClasspathScanner(resourcesFilter, urlsFilter, servletContext);
107
108
109 executorService = Executors.newSingleThreadScheduledExecutor();
110 log.info("Scheduling execution of ClasspathScanner every {}s.", SCAN_INTERVAL);
111 scannerFuture = executorService.scheduleWithFixedDelay(scanner, SCAN_INTERVAL, SCAN_INTERVAL, TimeUnit.SECONDS);
112 }
113 scanner.watchResourceChanges(callbackFunction);
114 }
115
116 public void stop() {
117 if (executorService != null) {
118 executorService.shutdownNow();
119 boolean terminated = false;
120 try {
121 terminated = executorService.awaitTermination(1, TimeUnit.SECONDS);
122 } catch (InterruptedException e) {
123 log.error("Exception during service termination", e);
124 }
125 if (terminated) {
126 log.info("{} terminated.", getClass().getSimpleName());
127 } else {
128 log.warn("{} not terminated, some tasks are still running.", getClass().getSimpleName());
129 }
130 }
131 }
132
133 }