View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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   * This is a description of what this class does - gilesp don't forget to fill this in.
34   *
35   * @author Kuali Rice Team (rice.collab@kuali.org)
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              //read the entry from zip file and extract it to disk
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 }