1 19 20 package com.sslexplorer.rss; 21 22 import java.io.BufferedReader ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.io.InputStreamReader ; 26 import java.net.MalformedURLException ; 27 import java.net.URL ; 28 import java.net.URLConnection ; 29 import java.text.DateFormat ; 30 import java.util.ArrayList ; 31 import java.util.Collection ; 32 import java.util.Date ; 33 import java.util.HashMap ; 34 import java.util.List ; 35 import java.util.Map ; 36 37 import org.apache.commons.logging.Log; 38 import org.apache.commons.logging.LogFactory; 39 40 import com.sslexplorer.boot.Util; 41 import com.sun.syndication.io.SyndFeedInput; 42 43 48 public final class FeedManager implements Runnable { 49 50 53 public static final int CONNECT_TIMEOUT = 30000; 54 55 58 public static final int READ_TIMEOUT = 30000; 59 60 private static final Log log = LogFactory.getLog(FeedManager.class); 61 private static final int ONE_DAY_MILLIS = 1000 * 60 * 60 * 24; 62 private static final int FOUR_HOURS_MILLIS = 1000 * 60 * 60 * 4; 63 private static final String HOME_URL = "http://download.3sp.com/"; 64 private static final String FEED_3SP_URL = HOME_URL + "feeds/"; 65 66 private Map <String , Feed> feeds; 67 private List <String > availableFeeds; 68 private boolean running = false; 69 private Thread thread; 70 private int interval = ONE_DAY_MILLIS; 71 private URL baseLocation; 72 73 private static FeedManager instance; 74 75 80 protected FeedManager(URL baseLocation) { 81 this.baseLocation = baseLocation; 82 feeds = new HashMap <String , Feed>(); 83 availableFeeds = new ArrayList <String >(); 84 } 85 86 91 public static FeedManager getInstance() { 92 if (instance == null) { 93 try { 94 URL baseLocation = new URL (System.getProperty("sslexplorer.rssFeeds.baseLocation", FEED_3SP_URL)); 95 instance = new FeedManager(baseLocation); 96 } 97 catch(MalformedURLException murle) { 98 try { 99 URL baseLocation = new URL (FEED_3SP_URL); 100 instance = new FeedManager(baseLocation); 101 } 102 catch(MalformedURLException murle2) { 103 throw new Error ("Invalid default feed location."); 105 } 106 } 107 } 108 return instance; 109 } 110 111 116 public boolean isUpdating() { 117 return running; 118 } 119 120 125 public void startUpdating() { 126 if (running) { 127 throw new IllegalStateException ("Already updating."); 128 } 129 try { 130 loadAvailable(); 131 } 132 catch(Exception e) { 133 log.error("Failed to get initial feeds. Next update attempt will occur in 4 hours", e); 134 interval = FOUR_HOURS_MILLIS; 135 } 136 137 thread = new Thread (this, "FeedManager"); 138 thread.setPriority(Thread.MIN_PRIORITY); 139 running = true; 140 141 if (!isTestMode()) { 142 thread.start(); 143 } 144 } 145 146 private boolean isTestMode() { 147 return Boolean.valueOf(System.getProperty("sslexplorer.testing", "false")); 148 } 149 150 public void run() { 151 try { 152 while (running) { 153 154 if (!running) 155 break; 156 157 if (log.isInfoEnabled()) 158 log.info("Checking for feed updates"); 159 160 try { 161 retrieveFeeds(); 162 interval = ONE_DAY_MILLIS; 163 } 164 catch (Exception e) { 165 log.error("Failed to check for updated feeds. Will check again in 4 hours"); 166 interval = FOUR_HOURS_MILLIS; 167 } 168 sleep(interval); 169 } 170 } catch(InterruptedException ie) { 171 172 } finally { 173 running = false; 174 if(log.isInfoEnabled()) { 175 log.info("Stopped checking for RSS updates"); 176 } 177 } 178 } 179 180 185 public void stopUpdating() { 186 if (running) { 187 running = false; 188 synchronized (this) { 189 thread.interrupt(); 190 } 191 } else { 192 if(!isTestMode()) { 193 throw new IllegalStateException ("Not updating."); 194 } 195 } 196 } 197 198 204 public Feed getFeed(String feedName) { 205 206 synchronized (feeds) { 207 if (!feeds.containsKey(feedName) && !feedName.equals("${rssFeed}") && 208 availableFeeds.contains(feedName)) { 209 try { 210 Feed feed = new Feed(feedName, new SyndFeedInput(), new URL (baseLocation, feedName + ".xml")); 211 feeds.put(feedName, feed); 212 feed.load(); 213 return feed; 214 } catch (Exception ex) { 215 log.error("Failed to load feed.", ex); 216 } 217 } 218 return (Feed) feeds.get(feedName); 219 } 220 } 221 222 protected Collection <String > getAvailableFeedNames() { 223 return availableFeeds; 224 } 225 226 private static void sleep(int checkAgainIn) throws InterruptedException { 227 if (log.isInfoEnabled()) 228 log.info("Finished checking for updates / feeds, next check will occur at " + getDateAsString(checkAgainIn)); 229 Thread.sleep(checkAgainIn); 230 } 231 232 private static String getDateAsString(int checkAgainIn) { 233 return DateFormat.getDateTimeInstance().format(new Date (System.currentTimeMillis() + checkAgainIn)); 234 } 235 236 protected void retrieveFeeds() throws IOException { 237 238 if (log.isInfoEnabled()) 239 log.info("Retrieving RSS feeds"); 240 241 Map <String , Feed> updatedFeeds = new HashMap <String , Feed>(); 242 synchronized (feeds) { 243 for (String feedName : availableFeeds) { 244 try { 245 Feed feed = new Feed(feedName, new SyndFeedInput(), new URL (baseLocation, feedName + ".xml")); 246 updatedFeeds.put(feedName, feed); 247 feed.load(); 248 } catch (Exception ex) { 249 log.error("Failed to load feed.", ex); 250 } 251 } 252 feeds = updatedFeeds; 253 } 254 } 255 256 protected void loadAvailable() throws IOException { 257 URL location = new URL (baseLocation, "index.txt"); 258 259 availableFeeds.clear(); 260 URLConnection conx = location.openConnection(); 261 conx.setConnectTimeout(CONNECT_TIMEOUT); 262 conx.setReadTimeout(READ_TIMEOUT); 263 264 if (log.isInfoEnabled()) { 265 log.info("Retrieving RSS feeds index from " + location); 266 } 267 InputStream inputStream = null; 268 try { 269 inputStream = conx.getInputStream(); 270 BufferedReader reader = new BufferedReader (new InputStreamReader (inputStream)); 271 String line; 272 while ( ( line = reader.readLine() ) != null) { 273 availableFeeds.add(line); 274 } 275 } finally { 276 Util.closeStream(inputStream); 277 } 278 if (log.isInfoEnabled()) 279 log.info("There are " + availableFeeds.size() + " available feeds"); 280 } 281 } | Popular Tags |