forked from I2P_Developers/i2p.i2p
2005-03-23 jrandom
* Implemented the news fetch / update policy code, as configurated on /configupdate.jsp. Defaults are to grab the news every 24h (or if it doesn't exist yet, on startup). No action is taken however, though if the news.xml specifies that a new release is available, an option to update will be shown on the router console. * New initialNews.xml delivered with new installs, and moved news.xml out of the i2pwww module and into the i2p module so that we can bundle it within each update.
This commit is contained in:
171
apps/routerconsole/java/src/net/i2p/router/web/NewsFetcher.java
Normal file
171
apps/routerconsole/java/src/net/i2p/router/web/NewsFetcher.java
Normal file
@ -0,0 +1,171 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.RouterVersion;
|
||||
import net.i2p.util.EepGet;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Task to periodically look for updates to the news.xml, and to keep
|
||||
* track of whether that has an announcement for a new version.
|
||||
*/
|
||||
public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private boolean _updateAvailable;
|
||||
private long _lastFetch;
|
||||
private static NewsFetcher _instance;
|
||||
public static final NewsFetcher getInstance() { return _instance; }
|
||||
|
||||
private static final String NEWS_FILE = "docs/news.xml";
|
||||
|
||||
public NewsFetcher(I2PAppContext ctx) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(NewsFetcher.class);
|
||||
_instance = this;
|
||||
File news = new File(NEWS_FILE);
|
||||
if (news.exists())
|
||||
_lastFetch = news.lastModified();
|
||||
else
|
||||
_lastFetch = 0;
|
||||
}
|
||||
|
||||
public boolean updateAvailable() { return _updateAvailable; }
|
||||
|
||||
public void run() {
|
||||
try { Thread.sleep(_context.random().nextLong(5*60*1000)); } catch (InterruptedException ie) {}
|
||||
while (true) {
|
||||
if (!_updateAvailable) checkForUpdates();
|
||||
if (shouldFetchNews())
|
||||
fetchNews();
|
||||
try { Thread.sleep(10*60*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldInstall() {
|
||||
String policy = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_POLICY);
|
||||
return ("install".equals(policy));
|
||||
}
|
||||
|
||||
private boolean shouldFetchNews() {
|
||||
String freq = _context.getProperty(ConfigUpdateHandler.PROP_REFRESH_FREQUENCY);
|
||||
if (freq == null)
|
||||
freq = ConfigUpdateHandler.DEFAULT_REFRESH_FREQUENCY;
|
||||
try {
|
||||
long ms = Long.parseLong(freq);
|
||||
if (ms <= 0)
|
||||
return false;
|
||||
|
||||
if (_lastFetch + ms < _context.clock().now()) {
|
||||
return true;
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Last fetched " + DataHelper.formatDuration(_context.clock().now() - _lastFetch) + " ago");
|
||||
return false;
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Invalid refresh frequency: " + freq);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
private void fetchNews() {
|
||||
String newsURL = _context.getProperty(ConfigUpdateHandler.PROP_NEWS_URL, ConfigUpdateHandler.DEFAULT_NEWS_URL);
|
||||
boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue();
|
||||
String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
|
||||
String port = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_PORT, ConfigUpdateHandler.DEFAULT_PROXY_PORT);
|
||||
int proxyPort = -1;
|
||||
try {
|
||||
proxyPort = Integer.parseInt(port);
|
||||
EepGet get = null;
|
||||
if (shouldProxy)
|
||||
get = new EepGet(_context, proxyHost, proxyPort, 10, NEWS_FILE, newsURL);
|
||||
else
|
||||
get = new EepGet(_context, 10, NEWS_FILE, newsURL);
|
||||
get.addStatusListener(this);
|
||||
get.fetch();
|
||||
} catch (Throwable t) {
|
||||
_log.error("Error fetching the news", t);
|
||||
}
|
||||
|
||||
_lastFetch = _context.clock().now();
|
||||
}
|
||||
|
||||
private static final String VERSION_STRING = "version=\"" + RouterVersion.VERSION + "\"";
|
||||
|
||||
private void checkForUpdates() {
|
||||
File news = new File(NEWS_FILE);
|
||||
if (!news.exists()) return;
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(news);
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
while (DataHelper.readLine(in, buf)) {
|
||||
if (buf.indexOf(VERSION_STRING) != -1) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Our version found, no need to update: " + buf.toString());
|
||||
return;
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("No match in " + buf.toString());
|
||||
}
|
||||
buf.setLength(0);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Error checking the news for an update", ioe);
|
||||
return;
|
||||
} finally {
|
||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
// could not find version="0.5.0.1", so there must be an update ;)
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Our version was NOT found (" + RouterVersion.VERSION + "), update needed");
|
||||
_updateAvailable = true;
|
||||
|
||||
if (shouldInstall()) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Policy requests update, so we update");
|
||||
UpdateHandler handler = null;
|
||||
if (_context instanceof RouterContext) {
|
||||
handler = new UpdateHandler((RouterContext)_context);
|
||||
} else {
|
||||
List contexts = RouterContext.listContexts();
|
||||
if (contexts.size() > 0)
|
||||
handler = new UpdateHandler((RouterContext)contexts.get(0));
|
||||
else
|
||||
_log.log(Log.CRIT, "No router context to update with?");
|
||||
}
|
||||
if (handler != null)
|
||||
handler.update();
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Policy requests manual update, so we do nothing");
|
||||
}
|
||||
}
|
||||
|
||||
public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause) {
|
||||
// ignore
|
||||
}
|
||||
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {
|
||||
// ignore
|
||||
}
|
||||
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("News fetched from " + url);
|
||||
checkForUpdates();
|
||||
}
|
||||
|
||||
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Failed to fetch the news from " + url);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user