1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.datadictionary;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20
21 import java.io.IOException;
22 import java.net.URL;
23 import java.util.LinkedList;
24 import java.util.Map;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.Executors;
27 import java.util.concurrent.ScheduledExecutorService;
28 import java.util.concurrent.TimeUnit;
29 import java.util.zip.CRC32;
30 import java.util.zip.CheckedInputStream;
31
32
33
34
35
36
37
38 public class URLMonitor {
39 private static final Log LOG = LogFactory.getLog(URLMonitor.class);
40
41 private final LinkedList<URLContentChangedListener> listeners = new LinkedList<URLContentChangedListener>();
42 private final Map<URL, Long> resourceMap = new ConcurrentHashMap();
43 private final int reloadIntervalMilliseconds;
44 private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
45
46
47 public URLMonitor(int reloadIntervalMilliseconds) {
48 this.reloadIntervalMilliseconds = reloadIntervalMilliseconds;
49 }
50
51 public void shutdownScheduler() {
52 scheduler.shutdown();
53 }
54
55 public synchronized void addListener(URLContentChangedListener listener) {
56
57 listeners.add(listener);
58
59 if (listeners.size() == 1) {
60 scheduler.scheduleAtFixedRate(urlPoller,
61 reloadIntervalMilliseconds, reloadIntervalMilliseconds, TimeUnit.MILLISECONDS);
62 }
63 }
64
65 public void addURI(URL zipUrl) {
66
67 resourceMap.put(zipUrl, getCRC(zipUrl));
68 }
69
70 private Long getCRC(URL zipUrl) {
71 Long result = -1l;
72 try {
73 CRC32 crc = new CRC32();
74 CheckedInputStream cis = new CheckedInputStream(zipUrl.openStream(), crc);
75
76 byte[] buffer = new byte[1024];
77 int length;
78
79
80 while( (length = cis.read(buffer)) > 0);
81
82 cis.close();
83
84 result = crc.getValue();
85 } catch (IOException e) {
86 LOG.warn("Unable to calculate CRC, resource doesn't exist?", e);
87 }
88 return result;
89 }
90
91 private final Runnable urlPoller = new Runnable() {
92
93 @Override
94 public void run() {
95 for (Map.Entry<URL, Long> entry : resourceMap.entrySet()) {
96 Long crc = getCRC(entry.getKey());
97
98 if (!entry.getValue().equals(crc)) {
99 entry.setValue(crc);
100 for (URLContentChangedListener listener : listeners) {
101 listener.urlContentChanged(entry.getKey());
102 }
103 }
104 }
105 }
106 };
107
108 public static interface URLContentChangedListener {
109 public void urlContentChanged(URL url);
110 }
111 }