View Javadoc

1   /**
2    * Copyright 2005-2012 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 synchronized void addListener(URLContentChangedListener listener) {
52  
53          listeners.add(listener);
54  
55          if (listeners.size() == 1) {
56              scheduler.scheduleAtFixedRate(urlPoller,
57  				reloadIntervalMilliseconds, reloadIntervalMilliseconds, TimeUnit.MILLISECONDS);
58          }
59      }
60  
61      public void addURI(URL zipUrl) {
62  
63          resourceMap.put(zipUrl, getCRC(zipUrl));
64      }
65  
66      private Long getCRC(URL zipUrl) {
67          Long result = -1l;
68          try {
69              CRC32 crc = new CRC32();
70              CheckedInputStream cis = new CheckedInputStream(zipUrl.openStream(), crc);
71  
72              byte[] buffer = new byte[1024];
73              int length;
74  
75              //read the entry from zip file and extract it to disk
76              while( (length = cis.read(buffer)) > 0);
77  
78              cis.close();
79  
80              result = crc.getValue();
81          } catch (IOException e) {
82              LOG.warn("Unable to calculate CRC, resource doesn't exist?", e);
83          }
84          return result;
85      }
86  
87      private final Runnable urlPoller = new Runnable() {
88  
89          @Override
90          public void run() {
91              for (Map.Entry<URL, Long> entry : resourceMap.entrySet()) {
92                  Long crc = getCRC(entry.getKey());
93  
94                  if (!entry.getValue().equals(crc)) {
95                      entry.setValue(crc);
96                      for (URLContentChangedListener listener : listeners) {
97                          listener.urlContentChanged(entry.getKey());
98                      }
99                  }
100             }
101         }
102     };
103 
104     public static interface URLContentChangedListener {
105           public void urlContentChanged(URL url);
106     }
107 }