Author: toad
Date: 2007-05-09 21:12:03 +0000 (Wed, 09 May 2007)
New Revision: 13181
Added:
trunk/freenet/src/freenet/node/updater/NodeUpdateManager.java
Removed:
trunk/freenet/src/freenet/node/updater/NodeUpdaterManager.java
Modified:
trunk/freenet/src/freenet/node/Node.java
trunk/freenet/src/freenet/node/updater/NodeUpdater.java
trunk/freenet/src/freenet/node/updater/RevocationChecker.java
trunk/freenet/src/freenet/node/useralerts/UpdatedVersionAvailableUserAlert.java
Log:
NodeUpdaterManager -> NodeUpdateManager
(it's the latter in the l10n files already...)
Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java 2007-05-09 21:10:48 UTC (rev
13180)
+++ trunk/freenet/src/freenet/node/Node.java 2007-05-09 21:12:03 UTC (rev
13181)
@@ -82,7 +82,7 @@
import freenet.keys.SSKBlock;
import freenet.keys.SSKVerifyException;
import freenet.l10n.L10n;
-import freenet.node.updater.NodeUpdaterManager;
+import freenet.node.updater.NodeUpdateManager;
import freenet.node.useralerts.BuildOldAgeUserAlert;
import freenet.node.useralerts.ExtOldAgeUserAlert;
import freenet.node.useralerts.MeaningfulNodeNameUserAlert;
@@ -428,7 +428,7 @@
public int lastVersion;
/** NodeUpdater **/
- public NodeUpdaterManager nodeUpdater;
+ public NodeUpdateManager nodeUpdater;
// Things that's needed to keep track of
public final PluginManager pluginManager;
@@ -1400,7 +1400,7 @@
// Node Updater
try{
- nodeUpdater = NodeUpdaterManager.maybeCreate(this,
config);
+ nodeUpdater = NodeUpdateManager.maybeCreate(this,
config);
Logger.normal(this, "Starting the node updater");
nodeUpdater.start();
}catch (Exception e) {
@@ -2480,7 +2480,7 @@
config.store();
}
- public NodeUpdaterManager getNodeUpdater(){
+ public NodeUpdateManager getNodeUpdater(){
return nodeUpdater;
}
Copied: trunk/freenet/src/freenet/node/updater/NodeUpdateManager.java (from rev
13180, trunk/freenet/src/freenet/node/updater/NodeUpdaterManager.java)
===================================================================
--- trunk/freenet/src/freenet/node/updater/NodeUpdateManager.java
(rev 0)
+++ trunk/freenet/src/freenet/node/updater/NodeUpdateManager.java
2007-05-09 21:12:03 UTC (rev 13181)
@@ -0,0 +1,760 @@
+package freenet.node.updater;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import org.tanukisoftware.wrapper.WrapperManager;
+
+import freenet.config.Config;
+import freenet.config.InvalidConfigValueException;
+import freenet.config.SubConfig;
+import freenet.keys.FreenetURI;
+import freenet.l10n.L10n;
+import freenet.node.Node;
+import freenet.node.NodeStarter;
+import freenet.node.Version;
+import freenet.node.updater.UpdateDeployContext.UpdateCatastropheException;
+import freenet.node.useralerts.RevocationKeyFoundUserAlert;
+import freenet.node.useralerts.SimpleUserAlert;
+import freenet.node.useralerts.UpdatedVersionAvailableUserAlert;
+import freenet.node.useralerts.UserAlert;
+import freenet.support.Logger;
+import freenet.support.api.BooleanCallback;
+import freenet.support.api.StringCallback;
+
+/**
+ * Supervises NodeUpdater's. Enables us to easily update multiple files,
+ * change the URI's on the fly, eliminates some messy code in the
+ * callbacks etc.
+ */
+public class NodeUpdateManager {
+
+ public final static String UPDATE_URI = "freenet:USK at
BFa1voWr5PunINSZ5BGMqFwhkJTiDBBUrOZ0MYBXseg,BOrxeLzUMb6R9tEZzexymY0zyKAmBNvrU4A9Q0tAqu0,AQACAAE/update/"+Version.buildNumber();
+ public final static String REVOCATION_URI = "SSK at
tHlY8BK2KFB7JiO2bgeAw~e4sWU43YdJ6kmn73gjrIw,DnQzl0BYed15V8WQn~eRJxxIA-yADuI8XW7mnzEbut8,AQACAAE/revoked";
+ public final static String EXT_URI = "freenet:USK at
BFa1voWr5PunINSZ5BGMqFwhkJTiDBBUrOZ0MYBXseg,BOrxeLzUMb6R9tEZzexymY0zyKAmBNvrU4A9Q0tAqu0,AQACAAE/ext/"+NodeStarter.extBuildNumber;
+
+ FreenetURI updateURI;
+ FreenetURI extURI;
+ FreenetURI revocationURI;
+
+ NodeUpdater mainUpdater;
+ NodeUpdater extUpdater;
+
+ boolean wasEnabledOnStartup;
+ /** Is auto-update enabled? */
+ boolean isAutoUpdateAllowed;
+ /** Has the user given the go-ahead? */
+ boolean armed;
+ /** Should we check for freenet-ext.jar updates?
+ * Normally set only when our freenet-ext.jar is known to be out of
date. */
+ final boolean shouldUpdateExt;
+ /** Currently deploying an update? */
+ boolean isDeployingUpdate;
+
+ Node node;
+
+ final RevocationChecker revocationChecker;
+ private String revocationMessage;
+ private boolean hasBeenBlown;
+
+ /** Is there a new main jar ready to deploy? */
+ private boolean hasNewMainJar;
+ /** Is there a new ext jar ready to deploy? */
+ private boolean hasNewExtJar;
+ /** If another main jar is being fetched, when did the fetch start? */
+ private long startedFetchingNextMainJar;
+ /** If another ext jar is being fetched, when did the fetch start? */
+ private long startedFetchingNextExtJar;
+
+ // Revocation alert
+ private RevocationKeyFoundUserAlert revocationAlert;
+ // Update alert
+ private final UpdatedVersionAvailableUserAlert alert;
+
+ private boolean logMINOR;
+
+ public NodeUpdateManager(Node node, Config config) throws
InvalidConfigValueException {
+ logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ this.node = node;
+ this.hasBeenBlown = false;
+ shouldUpdateExt = NodeStarter.extBuildNumber <
NodeStarter.RECOMMENDED_EXT_BUILD_NUMBER;
+ this.alert= new UpdatedVersionAvailableUserAlert(this);
+ alert.isValid(false);
+
+ SubConfig updaterConfig = new SubConfig("node.updater", config);
+
+ updaterConfig.register("enabled",
WrapperManager.isControlledByNativeWrapper(), 1, true, false,
"NodeUpdateManager.enabled",
+ "NodeUpdateManager.enabledLong",
+ new UpdaterEnabledCallback());
+
+ wasEnabledOnStartup = updaterConfig.getBoolean("enabled");
+
+ // is the auto-update allowed ?
+ updaterConfig.register("autoupdate", false, 2, false, true,
"NodeUpdateManager.installNewVersions",
"NodeUpdateManager.installNewVersionsLong",
+ new AutoUpdateAllowedCallback());
+ isAutoUpdateAllowed = updaterConfig.getBoolean("autoupdate");
+
+ updaterConfig.register("URI", UPDATE_URI, 3,
+ true, false, "NodeUpdateManager.updateURI",
+ "NodeUpdateManager.updateURILong",
+ new UpdateURICallback(false));
+
+ // FIXME remove when 101X is long gone
+ updaterConfig.fixOldDefaultRegex("URI", "USK at
SIDKS6l-eOU8IQqDo03d~3qqBd-69WG60aDgg4nWqss,CPFqYi95Is3GwzAdAKtAuFMCXDZFFWC3~uPoidCD67s,AQABAAE/update/[0-9]++");
+
+ try {
+ updateURI = new
FreenetURI(updaterConfig.getString("URI"));
+ } catch (MalformedURLException e) {
+ throw new InvalidConfigValueException("Invalid
updateURI: "+e);
+ }
+
+ if(updateURI.lastMetaString() != null &&
updateURI.lastMetaString().length() == 0) {
+ // FIXME remove this hack, put in because of bad default
+ System.err.println("Correcting auto-update URI:
Removing extra /");
+ updateURI = updateURI.popMetaString();
+ }
+
+ updaterConfig.register("revocationURI", REVOCATION_URI,4,
+ true, false, "NodeUpdateManager.revocationURI",
+ "NodeUpdateManager.revocationURILong",
+ new UpdateRevocationURICallback());
+
+ // FIXME remove
+ updaterConfig.fixOldDefault("revocationURI", "freenet:SSK at
VOfCZVTYPaatJ~eB~4lu2cPrWEmGyt4bfbB1v15Z6qQ,B6EynLhm7QE0se~rMgWWhl7wh3rFWjxJsEUcyohAm8A,AQABAAE/revoked");
+ updaterConfig.fixOldDefault("revocationURI", "freenet:SSK at
i1F0GnBgMHNLZC~KrI8IiMCnDZeIy2YaLGsX~C0Mgv0,NlgBgblPys8YINj8CXabLW6AtUlWvZYNpYfNV08aoPo,AQACAAE/revoked");
+
+ try {
+ revocationURI = new
FreenetURI(updaterConfig.getString("revocationURI"));
+ } catch (MalformedURLException e) {
+ throw new InvalidConfigValueException("Invalid
revocationURI: "+e);
+ }
+
+ if(revocationURI.lastMetaString() != null &&
revocationURI.lastMetaString().length() == 0) {
+ // FIXME remove this hack, put in because of bad default
+ System.err.println("Correcting auto-update revocation
URI: Removing extra /");
+ revocationURI = revocationURI.popMetaString();
+ }
+
+ updaterConfig.register("extURI", EXT_URI, 5, true, false,
"NodeUpdateManager.extURI", "NodeUpdateManager.extURILong", new
UpdateURICallback(true));
+
+ // FIXME remove
+ updaterConfig.fixOldDefaultRegex("extURI", "USK at
SIDKS6l-eOU8IQqDo03d~3qqBd-69WG60aDgg4nWqss,CPFqYi95Is3GwzAdAKtAuFMCXDZFFWC3~uPoidCD67s,AQABAAE/ext/[0-9]++");
+
+ try {
+ extURI = new
FreenetURI(updaterConfig.getString("extURI"));
+ } catch (MalformedURLException e) {
+ throw new InvalidConfigValueException("Invalid extURI:
"+e);
+ }
+
+ updaterConfig.finishedInitialization();
+
+ this.revocationChecker = new RevocationChecker(this);
+
+ }
+
+ public void start() throws InvalidConfigValueException {
+
+ node.clientCore.alerts.register(alert);
+
+ enable(wasEnabledOnStartup);
+
+ }
+
+ /**
+ * Is auto-update enabled?
+ */
+ public boolean isEnabled() {
+ synchronized(this) {
+ return mainUpdater != null && mainUpdater.isRunning();
+ }
+ }
+
+ /**
+ * Enable or disable auto-update.
+ * @param enable Whether auto-update should be enabled.
+ * @throws InvalidConfigValueException If enable=true and we are not
running under the wrapper.
+ */
+ void enable(boolean enable) throws InvalidConfigValueException {
+ logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ if(!node.isUsingWrapper()){
+ Logger.normal(this, "Don't try to start the updater as
we are not running under the wrapper.");
+ return;
+ }
+ NodeUpdater main = null, ext = null;
+ synchronized(this) {
+ boolean enabled = (mainUpdater != null &&
mainUpdater.isRunning());
+ if(enabled == enable) return;
+ if(!enable) {
+ // Kill it
+ mainUpdater.preKill();
+ main = mainUpdater;
+ mainUpdater = null;
+ if(extUpdater != null)
+ extUpdater.preKill();
+ ext = extUpdater;
+ extUpdater = null;
+ } else {
+
if((!WrapperManager.isControlledByNativeWrapper()) ||
(NodeStarter.extBuildNumber == -1)) {
+ Logger.error(this, "Cannot update
because not running under wrapper");
+ throw new
InvalidConfigValueException("Cannot update because not running under wrapper");
+ }
+ // Start it
+ mainUpdater = new NodeUpdater(this, updateURI,
false, Version.buildNumber());
+ if(shouldUpdateExt)
+ extUpdater = new NodeUpdater(this,
extURI, true, NodeStarter.extBuildNumber);
+ }
+ }
+ if(!enable) {
+ if(main != null) main.kill();
+ if(ext != null) ext.kill();
+ revocationChecker.kill();
+ } else {
+ mainUpdater.start();
+ if(extUpdater != null)
+ extUpdater.start();
+ revocationChecker.start(false);
+ }
+ }
+
+ /**
+ * Create a NodeUpdateManager. Called by node constructor.
+ * @param node The node object.
+ * @param config The global config object. Options will be added to a
subconfig called node.updater.
+ * @return A new NodeUpdateManager
+ * @throws InvalidConfigValueException If there is an error in the
config.
+ */
+ public static NodeUpdateManager maybeCreate(Node node, Config config)
throws InvalidConfigValueException {
+ return new NodeUpdateManager(node, config);
+ }
+
+ /**
+ * Get the URI for either the freenet.jar updater or the
freenet-ext.jar updater.
+ * @param isExt If true, return the freenet-ext.jar update URI; if
false, return the freenet.jar URI.
+ * @return See above.
+ */
+ public synchronized FreenetURI getURI(boolean isExt) {
+ return isExt ? extURI : updateURI;
+ }
+
+ /**
+ * Set the URI for either the freenet.jar updater or the
freenet-ext.jar updater.
+ * @param isExt If true, set the freenet-ext.jar update URI; if false,
set the freenet.jar update URI.
+ * @param uri The URI to set.
+ */
+ public void setURI(boolean isExt, FreenetURI uri) {
+ NodeUpdater updater;
+ synchronized(this) {
+ if(isExt) {
+ if(extURI.equals(uri)) return;
+ extURI = uri;
+ updater = extUpdater;
+ } else {
+ if(updateURI.equals(uri)) return;
+ updateURI = uri;
+ updater = mainUpdater;
+ }
+ }
+ if(updater == null) return;
+ if(updater.isRunning()) return;
+ updater.onChangeURI(uri);
+ }
+
+ /** @return The revocation URI. */
+ public synchronized FreenetURI getRevocationURI() {
+ return revocationURI;
+ }
+
+ /**
+ * Set the revocation URI.
+ * @param uri The new revocation URI.
+ */
+ public void setRevocationURI(FreenetURI uri) {
+ synchronized(this) {
+ if(revocationURI.equals(uri)) return;
+ this.revocationURI = uri;
+ }
+ revocationChecker.onChangeRevocationURI();
+ }
+
+ /**
+ * @return Is auto-update currently enabled?
+ */
+ public synchronized boolean isAutoUpdateAllowed() {
+ return isAutoUpdateAllowed;
+ }
+
+ /**
+ * Enable or disable auto-update.
+ * @param val If true, enable auto-update (and immediately update if an
update is ready). If false, disable it.
+ */
+ public void setAutoUpdateAllowed(boolean val) {
+ synchronized(this) {
+ if(val == isAutoUpdateAllowed) return;
+ isAutoUpdateAllowed = val;
+ if(val) {
+ if(!isReadyToDeployUpdate(false)) return;
+ } else return;
+ }
+ deployOffThread(0);
+ }
+
+ private static final int WAIT_FOR_SECOND_FETCH_TO_COMPLETE = 240*1000;
+ private static final int RECENT_REVOCATION_INTERVAL = 120*1000;
+
+ /** Does the updater have an update ready to deploy? May be called
synchronized(this) */
+ private boolean isReadyToDeployUpdate(boolean ignoreRevocation) {
+ long now = System.currentTimeMillis();
+ long startedMillisAgo;
+ synchronized(this) {
+ if(!(hasNewMainJar || hasNewExtJar)) return false; //
no jar
+ if(hasBeenBlown) return false; // Duh
+ // Don't immediately deploy if still fetching
+ startedMillisAgo = now -
Math.max(startedFetchingNextMainJar, startedFetchingNextExtJar);
+ if(startedMillisAgo < WAIT_FOR_SECOND_FETCH_TO_COMPLETE)
+ return false; // Wait for running fetch to
complete
+ if(!ignoreRevocation) {
+ if(now - revocationChecker.lastSucceeded() <
RECENT_REVOCATION_INTERVAL)
+ return true;
+ }
+ }
+ revocationChecker.start(true);
+ if(ignoreRevocation) return true;
+ deployOffThread(WAIT_FOR_SECOND_FETCH_TO_COMPLETE -
startedMillisAgo);
+ return false;
+ }
+
+ /** Check whether there is an update to deploy. If there is, do it. */
+ private void deployUpdate() {
+ logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ try {
+ synchronized(this) {
+ if(hasBeenBlown) {
+ String msg = "Trying to update but key
has been blown! Message was "+revocationMessage;
+ Logger.error(this, msg);
+ System.err.println(msg);
+ return;
+ }
+ if(!isEnabled()) return;
+ if(!(isAutoUpdateAllowed || armed)) return;
+ if(!isReadyToDeployUpdate(false)) return;
+ if(isDeployingUpdate) return;
+ isDeployingUpdate = true;
+ }
+
+ innerDeployUpdate();
+ } catch (Throwable t) {
+ synchronized(this) {
+ isDeployingUpdate = false;
+ }
+ }
+ }
+
+ /**
+ * Deploy the update. Inner method. Doesn't check anything, just does
it.
+ */
+ private void innerDeployUpdate() {
+ // Write the jars, config etc.
+ // Then restart
+
+ UpdateDeployContext ctx;
+ try {
+ ctx = new UpdateDeployContext();
+ } catch (UpdaterParserException e) {
+ failUpdate("Could not determine which jars are in use:
"+e.getMessage());
+ return;
+ }
+
+ if(writeJars(ctx))
+ restart(ctx);
+ }
+
+ /**
+ * Write the updated jars, if necessary rewrite the wrapper.conf.
+ * @return True if this part of the update succeeded.
+ */
+ private boolean writeJars(UpdateDeployContext ctx) {
+ /**
+ * What do we want to do here?
+ * 1. If we have a new main jar:
+ * - If on Windows, write it to a new jar file, update the
wrapper.conf to point to it.
+ * - Otherwise, write to a new jar file, then move the new jar
file over the old jar file.
+ * 2. If we have a new ext jar:
+ * - Write it to a new jar file, update the wrapper.conf to
point to it.
+ */
+
+ boolean writtenNewJar = false;
+ boolean writtenNewExt = false;
+
+ boolean tryEasyWay = File.pathSeparatorChar == '/' &&
!hasNewExtJar;
+
+ File mainJar = ctx.getMainJar();
+ File newMainJar = ctx.getNewMainJar();
+
+ if(hasNewMainJar) {
+ writtenNewJar = true;
+ boolean writtenToTempFile = false;
+ try {
+ if(newMainJar.exists()) {
+ if(!newMainJar.delete()) {
+ if(newMainJar.exists()) {
+
System.err.println("Cannot write to preferred new jar location "+newMainJar);
+ if(tryEasyWay) {
+ try {
+
newMainJar = File.createTempFile("freenet", ".jar", mainJar.getParentFile());
+ } catch
(IOException e) {
+
failUpdate("Cannot write to any other location either - disk full? "+e);
+ return
false;
+ }
+ // Try writing
to it
+ try {
+
mainUpdater.writeJarTo(newMainJar);
+
writtenToTempFile = true;
+ } catch
(IOException e) {
+
newMainJar.delete();
+
failUpdate("Cannot write new jar - disk full? "+e);
+ return
false;
+ }
+ } else {
+ // Try writing
it to the new one even though we can't delete it.
+
mainUpdater.writeJarTo(newMainJar);
+ }
+ } else {
+
mainUpdater.writeJarTo(newMainJar);
+ }
+ } else {
+ if(logMINOR) Logger.minor(this,
"Deleted old jar "+newMainJar);
+
mainUpdater.writeJarTo(newMainJar);
+ }
+ } else {
+ mainUpdater.writeJarTo(newMainJar);
+ }
+ } catch (IOException e) {
+ failUpdate("Cannot update: Cannot write to " +
(tryEasyWay ? " temp file " : "new jar ")+newMainJar);
+ return false;
+ }
+
+ if(tryEasyWay) {
+ // Do it the easy way. Just rewrite the main
jar.
+ if(!newMainJar.renameTo(mainJar)) {
+ Logger.error(this, "Cannot rename temp
file "+newMainJar+" over original jar "+mainJar);
+ if(writtenToTempFile) {
+ // Fail the update - otherwise
we will leak disk space
+ newMainJar.delete();
+ failUpdate("Cannot write to
preferred new jar location and cannot rename temp file over old jar, update
failed");
+ return false;
+ }
+ // Try the hard way
+ } else {
+ System.err.println("Written new Freenet
jar: "+mainUpdater.getWrittenVersion());
+ return true;
+ }
+ }
+
+ }
+
+ // Easy way didn't work or we can't do the easy way. Try the
hard way.
+
+ if(hasNewExtJar) {
+
+ writtenNewExt = true;
+
+ // Write the new ext jar
+
+ File newExtJar = ctx.getNewExtJar();
+
+ try {
+ extUpdater.writeJarTo(newExtJar);
+ } catch (IOException e) {
+ failUpdate("Cannot write new ext jar to
"+newExtJar);
+ return false;
+ }
+
+ }
+
+ try {
+ ctx.rewriteWrapperConf(writtenNewJar, writtenNewExt);
+ } catch (IOException e) {
+ failUpdate("Cannot rewrite wrapper.conf: "+e);
+ return false;
+ } catch (UpdateCatastropheException e) {
+ failUpdate(e.getMessage());
+ node.clientCore.alerts.register(new
SimpleUserAlert(false, l10n("updateCatastropheTitle"), e.getMessage(),
UserAlert.CRITICAL_ERROR));
+ return false;
+ } catch (UpdaterParserException e) {
+ node.clientCore.alerts.register(new
SimpleUserAlert(false, l10n("updateFailedTitle"), e.getMessage(),
UserAlert.CRITICAL_ERROR));
+ return false;
+ }
+
+ return true;
+ }
+
+ /** Restart the node. Does not return. */
+ private void restart(UpdateDeployContext ctx) {
+ node.getNodeStarter().restart();
+ try {
+ Thread.sleep(5*60*1000);
+ } catch (InterruptedException e) {
+ // Break
+ } // in case it's still restarting
+ System.err.println("Failed to restart. Exiting, please restart
the node.");
+ System.exit(Node.EXIT_RESTART_FAILED);
+ }
+
+ private void failUpdate(String reason) {
+ Logger.error(this, "Update failed: "+reason);
+ System.err.println("Update failed: "+reason);
+ this.killUpdateAlerts();
+ node.clientCore.alerts.register(new SimpleUserAlert(true,
l10n("updateFailedTitle"), l10n("updateFailed", "reason", reason),
UserAlert.ERROR));
+ }
+
+ private String l10n(String key) {
+ return L10n.getString("NodeUpdateManager."+key);
+ }
+
+ private String l10n(String key, String pattern, String value) {
+ return L10n.getString("NodeUpdateManager."+key, pattern, value);
+ }
+
+ /**
+ * Called when a new jar has been downloaded.
+ * @param isExt If true, the new jar is the ext jar; if false, it is
the main jar.
+ */
+ void onDownloadedNewJar(boolean isExt) {
+ synchronized(this) {
+ if(isExt) {
+ hasNewExtJar = true;
+ startedFetchingNextExtJar = -1;
+ } else {
+ hasNewMainJar = true;
+ startedFetchingNextMainJar = -1;
+ }
+ }
+ revocationChecker.start(true);
+ }
+
+ /**
+ * Called when the NodeUpdater starts to fetch a new version of the jar.
+ * @param isExt If true, the new jar is the ext jar; if false, it is
the main jar.
+ */
+ void onStartFetching(boolean isExt) {
+ long now = System.currentTimeMillis();
+ synchronized(this) {
+ if(isExt) {
+ startedFetchingNextExtJar = now;
+ } else {
+ startedFetchingNextMainJar = now;
+ }
+ }
+ }
+
+ public void blow(String msg){
+ NodeUpdater main, ext;
+ synchronized(this) {
+ if(hasBeenBlown){
+ Logger.error(this, "The key has ALREADY been
marked as blown! Message was "+revocationMessage+" new message "+msg);
+ return;
+ }else{
+ this.revocationMessage = msg;
+ this.hasBeenBlown = true;
+ // We must get to the lower part, and show the
user the message
+ try {
+ System.err.println("THE AUTO-UPDATING
SYSTEM HAS BEEN COMPROMIZED!");
+ System.err.println("The auto-updating
system revocation key has been inserted. It says: "+revocationMessage);
+ } catch (Throwable t) {
+ try {
+ Logger.error(this, "Caught "+t,
t);
+ } catch (Throwable t1) {}
+ }
+ }
+ main = mainUpdater;
+ ext = extUpdater;
+ if(main != null) main.preKill();
+ if(ext != null) ext.preKill();
+ mainUpdater = null;
+ extUpdater = null;
+ }
+ if(main != null) main.kill();
+ if(ext != null) ext.kill();
+ if(revocationAlert==null){
+ revocationAlert = new RevocationKeyFoundUserAlert(msg);
+ node.clientCore.alerts.register(revocationAlert);
+ // we don't need to advertize updates : we are not
going to do them
+ killUpdateAlerts();
+ }
+ }
+
+ /**
+ * Kill all UserAlerts asking the user whether he wants to update.
+ */
+ private void killUpdateAlerts() {
+ node.clientCore.alerts.unregister(alert);
+ }
+
+ /** Called when the RevocationChecker has got 3 DNFs on the revocation
key */
+ public void noRevocationFound() {
+ deployUpdate(); // May have been waiting for the revocation.
+ // If we're still here, we didn't update.
+ node.ps.queueTimedJob(new Runnable() {
+ public void run() {
+ revocationChecker.start(false);
+ }
+ }, node.random.nextInt(24*60*60*1000));
+ }
+
+ public void arm() {
+ synchronized(this) {
+ armed = true;
+ }
+ deployOffThread(0);
+ }
+
+ void deployOffThread(long delay) {
+ node.ps.queueTimedJob(new Runnable() {
+ public void run() {
+ deployUpdate();
+ }
+ }, delay);
+ }
+
+ /**
+ * Has the private key been revoked?
+ */
+ public boolean isBlown() {
+ return hasBeenBlown;
+ }
+
+ public synchronized boolean hasNewMainJar() {
+ return hasNewMainJar;
+ }
+
+ public synchronized boolean hasNewExtJar() {
+ return hasNewExtJar;
+ }
+
+ public int newMainJarVersion() {
+ if(mainUpdater == null) return -1;
+ return mainUpdater.getFetchedVersion();
+ }
+
+ public int newExtJarVersion() {
+ if(extUpdater == null) return -1;
+ return extUpdater.getFetchedVersion();
+ }
+
+ public boolean fetchingNewMainJar() {
+ return mainUpdater != null && mainUpdater.isFetching();
+ }
+
+ public boolean fetchingNewExtJar() {
+ return extUpdater != null && extUpdater.isFetching();
+ }
+
+ public int fetchingNewMainJarVersion() {
+ if(mainUpdater == null) return -1;
+ return mainUpdater.fetchingVersion();
+ }
+
+ public int fetchingNewExtJarVersion() {
+ if(extUpdater == null) return -1;
+ return extUpdater.fetchingVersion();
+ }
+
+ public boolean inFinalCheck() {
+ return isReadyToDeployUpdate(true) &&
!isReadyToDeployUpdate(false);
+ }
+
+ public int getRevocationDNFCounter() {
+ return revocationChecker.getRevocationDNFCounter();
+ }
+
+ public int getMainVersion() {
+ return Version.buildNumber();
+ }
+
+ public int getExtVersion() {
+ return NodeStarter.extBuildNumber;
+ }
+
+ public boolean isArmed() {
+ return armed || isAutoUpdateAllowed;
+ }
+
+ /** Is the node able to update as soon as the revocation fetch has been
completed? */
+ public boolean canUpdateNow() {
+ return isReadyToDeployUpdate(true);
+ }
+
+ /** Is the node able to update *immediately*? (i.e. not only is it
ready in every other sense, but also a revocation
+ * fetch has completed recently enough not to need another one) */
+ public boolean canUpdateImmediately() {
+ return isReadyToDeployUpdate(false);
+ }
+
+ // Config callbacks
+
+ class UpdaterEnabledCallback implements BooleanCallback {
+
+ public boolean get() {
+ return isEnabled();
+ }
+
+ public void set(boolean val) throws InvalidConfigValueException
{
+ enable(val);
+ }
+ }
+
+ class AutoUpdateAllowedCallback implements BooleanCallback {
+
+ public boolean get() {
+ return isAutoUpdateAllowed();
+ }
+
+ public void set(boolean val) throws InvalidConfigValueException
{
+ setAutoUpdateAllowed(val);
+ }
+ }
+
+ class UpdateURICallback implements StringCallback {
+
+ boolean isExt;
+
+ UpdateURICallback(boolean isExt) {
+ this.isExt = isExt;
+ }
+
+ public String get() {
+ return getURI(isExt).toString(false, false);
+ }
+
+ public void set(String val) throws InvalidConfigValueException {
+ FreenetURI uri;
+ try {
+ uri = new FreenetURI(val);
+ } catch (MalformedURLException e) {
+ throw new InvalidConfigValueException("Invalid
key: "+val+" : "+e);
+ }
+ setURI(isExt, uri);
+ }
+
+ }
+
+ public class UpdateRevocationURICallback implements StringCallback {
+
+ public String get() {
+ return getRevocationURI().toString(false, false);
+ }
+
+ public void set(String val) throws InvalidConfigValueException {
+ FreenetURI uri;
+ try {
+ uri = new FreenetURI(val);
+ } catch (MalformedURLException e) {
+ throw new InvalidConfigValueException("Invalid
key: "+val+" : "+e);
+ }
+ setRevocationURI(uri);
+ }
+
+ }
+
+}
Modified: trunk/freenet/src/freenet/node/updater/NodeUpdater.java
===================================================================
--- trunk/freenet/src/freenet/node/updater/NodeUpdater.java 2007-05-09
21:10:48 UTC (rev 13180)
+++ trunk/freenet/src/freenet/node/updater/NodeUpdater.java 2007-05-09
21:12:03 UTC (rev 13181)
@@ -33,7 +33,7 @@
private final Ticker ticker;
public final NodeClientCore core;
private final Node node;
- public final NodeUpdaterManager manager;
+ public final NodeUpdateManager manager;
private final int currentVersion;
private int availableVersion;
@@ -46,7 +46,7 @@
public final boolean extUpdate;
- NodeUpdater(NodeUpdaterManager manager, FreenetURI URI, boolean
extUpdate, int current) {
+ NodeUpdater(NodeUpdateManager manager, FreenetURI URI, boolean
extUpdate, int current) {
logMINOR = Logger.shouldLog(Logger.MINOR, this);
this.manager = manager;
this.node = manager.node;
Deleted: trunk/freenet/src/freenet/node/updater/NodeUpdaterManager.java
===================================================================
--- trunk/freenet/src/freenet/node/updater/NodeUpdaterManager.java
2007-05-09 21:10:48 UTC (rev 13180)
+++ trunk/freenet/src/freenet/node/updater/NodeUpdaterManager.java
2007-05-09 21:12:03 UTC (rev 13181)
@@ -1,760 +0,0 @@
-package freenet.node.updater;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-
-import org.tanukisoftware.wrapper.WrapperManager;
-
-import freenet.config.Config;
-import freenet.config.InvalidConfigValueException;
-import freenet.config.SubConfig;
-import freenet.keys.FreenetURI;
-import freenet.l10n.L10n;
-import freenet.node.Node;
-import freenet.node.NodeStarter;
-import freenet.node.Version;
-import freenet.node.updater.UpdateDeployContext.UpdateCatastropheException;
-import freenet.node.useralerts.RevocationKeyFoundUserAlert;
-import freenet.node.useralerts.SimpleUserAlert;
-import freenet.node.useralerts.UpdatedVersionAvailableUserAlert;
-import freenet.node.useralerts.UserAlert;
-import freenet.support.Logger;
-import freenet.support.api.BooleanCallback;
-import freenet.support.api.StringCallback;
-
-/**
- * Supervises NodeUpdater's. Enables us to easily update multiple files,
- * change the URI's on the fly, eliminates some messy code in the
- * callbacks etc.
- */
-public class NodeUpdaterManager {
-
- public final static String UPDATE_URI = "freenet:USK at
BFa1voWr5PunINSZ5BGMqFwhkJTiDBBUrOZ0MYBXseg,BOrxeLzUMb6R9tEZzexymY0zyKAmBNvrU4A9Q0tAqu0,AQACAAE/update/"+Version.buildNumber();
- public final static String REVOCATION_URI = "SSK at
tHlY8BK2KFB7JiO2bgeAw~e4sWU43YdJ6kmn73gjrIw,DnQzl0BYed15V8WQn~eRJxxIA-yADuI8XW7mnzEbut8,AQACAAE/revoked";
- public final static String EXT_URI = "freenet:USK at
BFa1voWr5PunINSZ5BGMqFwhkJTiDBBUrOZ0MYBXseg,BOrxeLzUMb6R9tEZzexymY0zyKAmBNvrU4A9Q0tAqu0,AQACAAE/ext/"+NodeStarter.extBuildNumber;
-
- FreenetURI updateURI;
- FreenetURI extURI;
- FreenetURI revocationURI;
-
- NodeUpdater mainUpdater;
- NodeUpdater extUpdater;
-
- boolean wasEnabledOnStartup;
- /** Is auto-update enabled? */
- boolean isAutoUpdateAllowed;
- /** Has the user given the go-ahead? */
- boolean armed;
- /** Should we check for freenet-ext.jar updates?
- * Normally set only when our freenet-ext.jar is known to be out of
date. */
- final boolean shouldUpdateExt;
- /** Currently deploying an update? */
- boolean isDeployingUpdate;
-
- Node node;
-
- final RevocationChecker revocationChecker;
- private String revocationMessage;
- private boolean hasBeenBlown;
-
- /** Is there a new main jar ready to deploy? */
- private boolean hasNewMainJar;
- /** Is there a new ext jar ready to deploy? */
- private boolean hasNewExtJar;
- /** If another main jar is being fetched, when did the fetch start? */
- private long startedFetchingNextMainJar;
- /** If another ext jar is being fetched, when did the fetch start? */
- private long startedFetchingNextExtJar;
-
- // Revocation alert
- private RevocationKeyFoundUserAlert revocationAlert;
- // Update alert
- private final UpdatedVersionAvailableUserAlert alert;
-
- private boolean logMINOR;
-
- public NodeUpdaterManager(Node node, Config config) throws
InvalidConfigValueException {
- logMINOR = Logger.shouldLog(Logger.MINOR, this);
- this.node = node;
- this.hasBeenBlown = false;
- shouldUpdateExt = NodeStarter.extBuildNumber <
NodeStarter.RECOMMENDED_EXT_BUILD_NUMBER;
- this.alert= new UpdatedVersionAvailableUserAlert(this);
- alert.isValid(false);
-
- SubConfig updaterConfig = new SubConfig("node.updater", config);
-
- updaterConfig.register("enabled",
WrapperManager.isControlledByNativeWrapper(), 1, true, false,
"NodeUpdateManager.enabled",
- "NodeUpdateManager.enabledLong",
- new UpdaterEnabledCallback());
-
- wasEnabledOnStartup = updaterConfig.getBoolean("enabled");
-
- // is the auto-update allowed ?
- updaterConfig.register("autoupdate", false, 2, false, true,
"NodeUpdateManager.installNewVersions",
"NodeUpdateManager.installNewVersionsLong",
- new AutoUpdateAllowedCallback());
- isAutoUpdateAllowed = updaterConfig.getBoolean("autoupdate");
-
- updaterConfig.register("URI", UPDATE_URI, 3,
- true, false, "NodeUpdateManager.updateURI",
- "NodeUpdateManager.updateURILong",
- new UpdateURICallback(false));
-
- // FIXME remove when 101X is long gone
- updaterConfig.fixOldDefaultRegex("URI", "USK at
SIDKS6l-eOU8IQqDo03d~3qqBd-69WG60aDgg4nWqss,CPFqYi95Is3GwzAdAKtAuFMCXDZFFWC3~uPoidCD67s,AQABAAE/update/[0-9]++");
-
- try {
- updateURI = new
FreenetURI(updaterConfig.getString("URI"));
- } catch (MalformedURLException e) {
- throw new InvalidConfigValueException("Invalid
updateURI: "+e);
- }
-
- if(updateURI.lastMetaString() != null &&
updateURI.lastMetaString().length() == 0) {
- // FIXME remove this hack, put in because of bad default
- System.err.println("Correcting auto-update URI:
Removing extra /");
- updateURI = updateURI.popMetaString();
- }
-
- updaterConfig.register("revocationURI", REVOCATION_URI,4,
- true, false, "NodeUpdateManager.revocationURI",
- "NodeUpdateManager.revocationURILong",
- new UpdateRevocationURICallback());
-
- // FIXME remove
- updaterConfig.fixOldDefault("revocationURI", "freenet:SSK at
VOfCZVTYPaatJ~eB~4lu2cPrWEmGyt4bfbB1v15Z6qQ,B6EynLhm7QE0se~rMgWWhl7wh3rFWjxJsEUcyohAm8A,AQABAAE/revoked");
- updaterConfig.fixOldDefault("revocationURI", "freenet:SSK at
i1F0GnBgMHNLZC~KrI8IiMCnDZeIy2YaLGsX~C0Mgv0,NlgBgblPys8YINj8CXabLW6AtUlWvZYNpYfNV08aoPo,AQACAAE/revoked");
-
- try {
- revocationURI = new
FreenetURI(updaterConfig.getString("revocationURI"));
- } catch (MalformedURLException e) {
- throw new InvalidConfigValueException("Invalid
revocationURI: "+e);
- }
-
- if(revocationURI.lastMetaString() != null &&
revocationURI.lastMetaString().length() == 0) {
- // FIXME remove this hack, put in because of bad default
- System.err.println("Correcting auto-update revocation
URI: Removing extra /");
- revocationURI = revocationURI.popMetaString();
- }
-
- updaterConfig.register("extURI", EXT_URI, 5, true, false,
"NodeUpdateManager.extURI", "NodeUpdateManager.extURILong", new
UpdateURICallback(true));
-
- // FIXME remove
- updaterConfig.fixOldDefaultRegex("extURI", "USK at
SIDKS6l-eOU8IQqDo03d~3qqBd-69WG60aDgg4nWqss,CPFqYi95Is3GwzAdAKtAuFMCXDZFFWC3~uPoidCD67s,AQABAAE/ext/[0-9]++");
-
- try {
- extURI = new
FreenetURI(updaterConfig.getString("extURI"));
- } catch (MalformedURLException e) {
- throw new InvalidConfigValueException("Invalid extURI:
"+e);
- }
-
- updaterConfig.finishedInitialization();
-
- this.revocationChecker = new RevocationChecker(this);
-
- }
-
- public void start() throws InvalidConfigValueException {
-
- node.clientCore.alerts.register(alert);
-
- enable(wasEnabledOnStartup);
-
- }
-
- /**
- * Is auto-update enabled?
- */
- public boolean isEnabled() {
- synchronized(this) {
- return mainUpdater != null && mainUpdater.isRunning();
- }
- }
-
- /**
- * Enable or disable auto-update.
- * @param enable Whether auto-update should be enabled.
- * @throws InvalidConfigValueException If enable=true and we are not
running under the wrapper.
- */
- void enable(boolean enable) throws InvalidConfigValueException {
- logMINOR = Logger.shouldLog(Logger.MINOR, this);
- if(!node.isUsingWrapper()){
- Logger.normal(this, "Don't try to start the updater as
we are not running under the wrapper.");
- return;
- }
- NodeUpdater main = null, ext = null;
- synchronized(this) {
- boolean enabled = (mainUpdater != null &&
mainUpdater.isRunning());
- if(enabled == enable) return;
- if(!enable) {
- // Kill it
- mainUpdater.preKill();
- main = mainUpdater;
- mainUpdater = null;
- if(extUpdater != null)
- extUpdater.preKill();
- ext = extUpdater;
- extUpdater = null;
- } else {
-
if((!WrapperManager.isControlledByNativeWrapper()) ||
(NodeStarter.extBuildNumber == -1)) {
- Logger.error(this, "Cannot update
because not running under wrapper");
- throw new
InvalidConfigValueException("Cannot update because not running under wrapper");
- }
- // Start it
- mainUpdater = new NodeUpdater(this, updateURI,
false, Version.buildNumber());
- if(shouldUpdateExt)
- extUpdater = new NodeUpdater(this,
extURI, true, NodeStarter.extBuildNumber);
- }
- }
- if(!enable) {
- if(main != null) main.kill();
- if(ext != null) ext.kill();
- revocationChecker.kill();
- } else {
- mainUpdater.start();
- if(extUpdater != null)
- extUpdater.start();
- revocationChecker.start(false);
- }
- }
-
- /**
- * Create a NodeUpdaterManager. Called by node constructor.
- * @param node The node object.
- * @param config The global config object. Options will be added to a
subconfig called node.updater.
- * @return A new NodeUpdaterManager
- * @throws InvalidConfigValueException If there is an error in the
config.
- */
- public static NodeUpdaterManager maybeCreate(Node node, Config config)
throws InvalidConfigValueException {
- return new NodeUpdaterManager(node, config);
- }
-
- /**
- * Get the URI for either the freenet.jar updater or the
freenet-ext.jar updater.
- * @param isExt If true, return the freenet-ext.jar update URI; if
false, return the freenet.jar URI.
- * @return See above.
- */
- public synchronized FreenetURI getURI(boolean isExt) {
- return isExt ? extURI : updateURI;
- }
-
- /**
- * Set the URI for either the freenet.jar updater or the
freenet-ext.jar updater.
- * @param isExt If true, set the freenet-ext.jar update URI; if false,
set the freenet.jar update URI.
- * @param uri The URI to set.
- */
- public void setURI(boolean isExt, FreenetURI uri) {
- NodeUpdater updater;
- synchronized(this) {
- if(isExt) {
- if(extURI.equals(uri)) return;
- extURI = uri;
- updater = extUpdater;
- } else {
- if(updateURI.equals(uri)) return;
- updateURI = uri;
- updater = mainUpdater;
- }
- }
- if(updater == null) return;
- if(updater.isRunning()) return;
- updater.onChangeURI(uri);
- }
-
- /** @return The revocation URI. */
- public synchronized FreenetURI getRevocationURI() {
- return revocationURI;
- }
-
- /**
- * Set the revocation URI.
- * @param uri The new revocation URI.
- */
- public void setRevocationURI(FreenetURI uri) {
- synchronized(this) {
- if(revocationURI.equals(uri)) return;
- this.revocationURI = uri;
- }
- revocationChecker.onChangeRevocationURI();
- }
-
- /**
- * @return Is auto-update currently enabled?
- */
- public synchronized boolean isAutoUpdateAllowed() {
- return isAutoUpdateAllowed;
- }
-
- /**
- * Enable or disable auto-update.
- * @param val If true, enable auto-update (and immediately update if an
update is ready). If false, disable it.
- */
- public void setAutoUpdateAllowed(boolean val) {
- synchronized(this) {
- if(val == isAutoUpdateAllowed) return;
- isAutoUpdateAllowed = val;
- if(val) {
- if(!isReadyToDeployUpdate(false)) return;
- } else return;
- }
- deployOffThread(0);
- }
-
- private static final int WAIT_FOR_SECOND_FETCH_TO_COMPLETE = 240*1000;
- private static final int RECENT_REVOCATION_INTERVAL = 120*1000;
-
- /** Does the updater have an update ready to deploy? May be called
synchronized(this) */
- private boolean isReadyToDeployUpdate(boolean ignoreRevocation) {
- long now = System.currentTimeMillis();
- long startedMillisAgo;
- synchronized(this) {
- if(!(hasNewMainJar || hasNewExtJar)) return false; //
no jar
- if(hasBeenBlown) return false; // Duh
- // Don't immediately deploy if still fetching
- startedMillisAgo = now -
Math.max(startedFetchingNextMainJar, startedFetchingNextExtJar);
- if(startedMillisAgo < WAIT_FOR_SECOND_FETCH_TO_COMPLETE)
- return false; // Wait for running fetch to
complete
- if(!ignoreRevocation) {
- if(now - revocationChecker.lastSucceeded() <
RECENT_REVOCATION_INTERVAL)
- return true;
- }
- }
- revocationChecker.start(true);
- if(ignoreRevocation) return true;
- deployOffThread(WAIT_FOR_SECOND_FETCH_TO_COMPLETE -
startedMillisAgo);
- return false;
- }
-
- /** Check whether there is an update to deploy. If there is, do it. */
- private void deployUpdate() {
- logMINOR = Logger.shouldLog(Logger.MINOR, this);
- try {
- synchronized(this) {
- if(hasBeenBlown) {
- String msg = "Trying to update but key
has been blown! Message was "+revocationMessage;
- Logger.error(this, msg);
- System.err.println(msg);
- return;
- }
- if(!isEnabled()) return;
- if(!(isAutoUpdateAllowed || armed)) return;
- if(!isReadyToDeployUpdate(false)) return;
- if(isDeployingUpdate) return;
- isDeployingUpdate = true;
- }
-
- innerDeployUpdate();
- } catch (Throwable t) {
- synchronized(this) {
- isDeployingUpdate = false;
- }
- }
- }
-
- /**
- * Deploy the update. Inner method. Doesn't check anything, just does
it.
- */
- private void innerDeployUpdate() {
- // Write the jars, config etc.
- // Then restart
-
- UpdateDeployContext ctx;
- try {
- ctx = new UpdateDeployContext();
- } catch (UpdaterParserException e) {
- failUpdate("Could not determine which jars are in use:
"+e.getMessage());
- return;
- }
-
- if(writeJars(ctx))
- restart(ctx);
- }
-
- /**
- * Write the updated jars, if necessary rewrite the wrapper.conf.
- * @return True if this part of the update succeeded.
- */
- private boolean writeJars(UpdateDeployContext ctx) {
- /**
- * What do we want to do here?
- * 1. If we have a new main jar:
- * - If on Windows, write it to a new jar file, update the
wrapper.conf to point to it.
- * - Otherwise, write to a new jar file, then move the new jar
file over the old jar file.
- * 2. If we have a new ext jar:
- * - Write it to a new jar file, update the wrapper.conf to
point to it.
- */
-
- boolean writtenNewJar = false;
- boolean writtenNewExt = false;
-
- boolean tryEasyWay = File.pathSeparatorChar == '/' &&
!hasNewExtJar;
-
- File mainJar = ctx.getMainJar();
- File newMainJar = ctx.getNewMainJar();
-
- if(hasNewMainJar) {
- writtenNewJar = true;
- boolean writtenToTempFile = false;
- try {
- if(newMainJar.exists()) {
- if(!newMainJar.delete()) {
- if(newMainJar.exists()) {
-
System.err.println("Cannot write to preferred new jar location "+newMainJar);
- if(tryEasyWay) {
- try {
-
newMainJar = File.createTempFile("freenet", ".jar", mainJar.getParentFile());
- } catch
(IOException e) {
-
failUpdate("Cannot write to any other location either - disk full? "+e);
- return
false;
- }
- // Try writing
to it
- try {
-
mainUpdater.writeJarTo(newMainJar);
-
writtenToTempFile = true;
- } catch
(IOException e) {
-
newMainJar.delete();
-
failUpdate("Cannot write new jar - disk full? "+e);
- return
false;
- }
- } else {
- // Try writing
it to the new one even though we can't delete it.
-
mainUpdater.writeJarTo(newMainJar);
- }
- } else {
-
mainUpdater.writeJarTo(newMainJar);
- }
- } else {
- if(logMINOR) Logger.minor(this,
"Deleted old jar "+newMainJar);
-
mainUpdater.writeJarTo(newMainJar);
- }
- } else {
- mainUpdater.writeJarTo(newMainJar);
- }
- } catch (IOException e) {
- failUpdate("Cannot update: Cannot write to " +
(tryEasyWay ? " temp file " : "new jar ")+newMainJar);
- return false;
- }
-
- if(tryEasyWay) {
- // Do it the easy way. Just rewrite the main
jar.
- if(!newMainJar.renameTo(mainJar)) {
- Logger.error(this, "Cannot rename temp
file "+newMainJar+" over original jar "+mainJar);
- if(writtenToTempFile) {
- // Fail the update - otherwise
we will leak disk space
- newMainJar.delete();
- failUpdate("Cannot write to
preferred new jar location and cannot rename temp file over old jar, update
failed");
- return false;
- }
- // Try the hard way
- } else {
- System.err.println("Written new Freenet
jar: "+mainUpdater.getWrittenVersion());
- return true;
- }
- }
-
- }
-
- // Easy way didn't work or we can't do the easy way. Try the
hard way.
-
- if(hasNewExtJar) {
-
- writtenNewExt = true;
-
- // Write the new ext jar
-
- File newExtJar = ctx.getNewExtJar();
-
- try {
- extUpdater.writeJarTo(newExtJar);
- } catch (IOException e) {
- failUpdate("Cannot write new ext jar to
"+newExtJar);
- return false;
- }
-
- }
-
- try {
- ctx.rewriteWrapperConf(writtenNewJar, writtenNewExt);
- } catch (IOException e) {
- failUpdate("Cannot rewrite wrapper.conf: "+e);
- return false;
- } catch (UpdateCatastropheException e) {
- failUpdate(e.getMessage());
- node.clientCore.alerts.register(new
SimpleUserAlert(false, l10n("updateCatastropheTitle"), e.getMessage(),
UserAlert.CRITICAL_ERROR));
- return false;
- } catch (UpdaterParserException e) {
- node.clientCore.alerts.register(new
SimpleUserAlert(false, l10n("updateFailedTitle"), e.getMessage(),
UserAlert.CRITICAL_ERROR));
- return false;
- }
-
- return true;
- }
-
- /** Restart the node. Does not return. */
- private void restart(UpdateDeployContext ctx) {
- node.getNodeStarter().restart();
- try {
- Thread.sleep(5*60*1000);
- } catch (InterruptedException e) {
- // Break
- } // in case it's still restarting
- System.err.println("Failed to restart. Exiting, please restart
the node.");
- System.exit(Node.EXIT_RESTART_FAILED);
- }
-
- private void failUpdate(String reason) {
- Logger.error(this, "Update failed: "+reason);
- System.err.println("Update failed: "+reason);
- this.killUpdateAlerts();
- node.clientCore.alerts.register(new SimpleUserAlert(true,
l10n("updateFailedTitle"), l10n("updateFailed", "reason", reason),
UserAlert.ERROR));
- }
-
- private String l10n(String key) {
- return L10n.getString("NodeUpdateManager."+key);
- }
-
- private String l10n(String key, String pattern, String value) {
- return L10n.getString("NodeUpdateManager."+key, pattern, value);
- }
-
- /**
- * Called when a new jar has been downloaded.
- * @param isExt If true, the new jar is the ext jar; if false, it is
the main jar.
- */
- void onDownloadedNewJar(boolean isExt) {
- synchronized(this) {
- if(isExt) {
- hasNewExtJar = true;
- startedFetchingNextExtJar = -1;
- } else {
- hasNewMainJar = true;
- startedFetchingNextMainJar = -1;
- }
- }
- revocationChecker.start(true);
- }
-
- /**
- * Called when the NodeUpdater starts to fetch a new version of the jar.
- * @param isExt If true, the new jar is the ext jar; if false, it is
the main jar.
- */
- void onStartFetching(boolean isExt) {
- long now = System.currentTimeMillis();
- synchronized(this) {
- if(isExt) {
- startedFetchingNextExtJar = now;
- } else {
- startedFetchingNextMainJar = now;
- }
- }
- }
-
- public void blow(String msg){
- NodeUpdater main, ext;
- synchronized(this) {
- if(hasBeenBlown){
- Logger.error(this, "The key has ALREADY been
marked as blown! Message was "+revocationMessage+" new message "+msg);
- return;
- }else{
- this.revocationMessage = msg;
- this.hasBeenBlown = true;
- // We must get to the lower part, and show the
user the message
- try {
- System.err.println("THE AUTO-UPDATING
SYSTEM HAS BEEN COMPROMIZED!");
- System.err.println("The auto-updating
system revocation key has been inserted. It says: "+revocationMessage);
- } catch (Throwable t) {
- try {
- Logger.error(this, "Caught "+t,
t);
- } catch (Throwable t1) {}
- }
- }
- main = mainUpdater;
- ext = extUpdater;
- if(main != null) main.preKill();
- if(ext != null) ext.preKill();
- mainUpdater = null;
- extUpdater = null;
- }
- if(main != null) main.kill();
- if(ext != null) ext.kill();
- if(revocationAlert==null){
- revocationAlert = new RevocationKeyFoundUserAlert(msg);
- node.clientCore.alerts.register(revocationAlert);
- // we don't need to advertize updates : we are not
going to do them
- killUpdateAlerts();
- }
- }
-
- /**
- * Kill all UserAlerts asking the user whether he wants to update.
- */
- private void killUpdateAlerts() {
- node.clientCore.alerts.unregister(alert);
- }
-
- /** Called when the RevocationChecker has got 3 DNFs on the revocation
key */
- public void noRevocationFound() {
- deployUpdate(); // May have been waiting for the revocation.
- // If we're still here, we didn't update.
- node.ps.queueTimedJob(new Runnable() {
- public void run() {
- revocationChecker.start(false);
- }
- }, node.random.nextInt(24*60*60*1000));
- }
-
- public void arm() {
- synchronized(this) {
- armed = true;
- }
- deployOffThread(0);
- }
-
- void deployOffThread(long delay) {
- node.ps.queueTimedJob(new Runnable() {
- public void run() {
- deployUpdate();
- }
- }, delay);
- }
-
- /**
- * Has the private key been revoked?
- */
- public boolean isBlown() {
- return hasBeenBlown;
- }
-
- public synchronized boolean hasNewMainJar() {
- return hasNewMainJar;
- }
-
- public synchronized boolean hasNewExtJar() {
- return hasNewExtJar;
- }
-
- public int newMainJarVersion() {
- if(mainUpdater == null) return -1;
- return mainUpdater.getFetchedVersion();
- }
-
- public int newExtJarVersion() {
- if(extUpdater == null) return -1;
- return extUpdater.getFetchedVersion();
- }
-
- public boolean fetchingNewMainJar() {
- return mainUpdater != null && mainUpdater.isFetching();
- }
-
- public boolean fetchingNewExtJar() {
- return extUpdater != null && extUpdater.isFetching();
- }
-
- public int fetchingNewMainJarVersion() {
- if(mainUpdater == null) return -1;
- return mainUpdater.fetchingVersion();
- }
-
- public int fetchingNewExtJarVersion() {
- if(extUpdater == null) return -1;
- return extUpdater.fetchingVersion();
- }
-
- public boolean inFinalCheck() {
- return isReadyToDeployUpdate(true) &&
!isReadyToDeployUpdate(false);
- }
-
- public int getRevocationDNFCounter() {
- return revocationChecker.getRevocationDNFCounter();
- }
-
- public int getMainVersion() {
- return Version.buildNumber();
- }
-
- public int getExtVersion() {
- return NodeStarter.extBuildNumber;
- }
-
- public boolean isArmed() {
- return armed || isAutoUpdateAllowed;
- }
-
- /** Is the node able to update as soon as the revocation fetch has been
completed? */
- public boolean canUpdateNow() {
- return isReadyToDeployUpdate(true);
- }
-
- /** Is the node able to update *immediately*? (i.e. not only is it
ready in every other sense, but also a revocation
- * fetch has completed recently enough not to need another one) */
- public boolean canUpdateImmediately() {
- return isReadyToDeployUpdate(false);
- }
-
- // Config callbacks
-
- class UpdaterEnabledCallback implements BooleanCallback {
-
- public boolean get() {
- return isEnabled();
- }
-
- public void set(boolean val) throws InvalidConfigValueException
{
- enable(val);
- }
- }
-
- class AutoUpdateAllowedCallback implements BooleanCallback {
-
- public boolean get() {
- return isAutoUpdateAllowed();
- }
-
- public void set(boolean val) throws InvalidConfigValueException
{
- setAutoUpdateAllowed(val);
- }
- }
-
- class UpdateURICallback implements StringCallback {
-
- boolean isExt;
-
- UpdateURICallback(boolean isExt) {
- this.isExt = isExt;
- }
-
- public String get() {
- return getURI(isExt).toString(false, false);
- }
-
- public void set(String val) throws InvalidConfigValueException {
- FreenetURI uri;
- try {
- uri = new FreenetURI(val);
- } catch (MalformedURLException e) {
- throw new InvalidConfigValueException("Invalid
key: "+val+" : "+e);
- }
- setURI(isExt, uri);
- }
-
- }
-
- public class UpdateRevocationURICallback implements StringCallback {
-
- public String get() {
- return getRevocationURI().toString(false, false);
- }
-
- public void set(String val) throws InvalidConfigValueException {
- FreenetURI uri;
- try {
- uri = new FreenetURI(val);
- } catch (MalformedURLException e) {
- throw new InvalidConfigValueException("Invalid
key: "+val+" : "+e);
- }
- setRevocationURI(uri);
- }
-
- }
-
-}
Modified: trunk/freenet/src/freenet/node/updater/RevocationChecker.java
===================================================================
--- trunk/freenet/src/freenet/node/updater/RevocationChecker.java
2007-05-09 21:10:48 UTC (rev 13180)
+++ trunk/freenet/src/freenet/node/updater/RevocationChecker.java
2007-05-09 21:12:03 UTC (rev 13181)
@@ -14,7 +14,7 @@
/**
* Fetches the revocation key. Each time it starts, it will try to fetch it
until it has 3 DNFs. If it ever finds it, it will
- * be immediately fed to the NodeUpdaterManager.
+ * be immediately fed to the NodeUpdateManager.
*/
public class RevocationChecker implements ClientCallback {
@@ -22,7 +22,7 @@
private boolean logMINOR;
- private NodeUpdaterManager manager;
+ private NodeUpdateManager manager;
private NodeClientCore core;
private int revocationDNFCounter;
private FetchContext ctxRevocation;
@@ -31,7 +31,7 @@
/** Last time at which we got 3 DNFs on the revocation key */
private long lastSucceeded;
- public RevocationChecker(NodeUpdaterManager manager) {
+ public RevocationChecker(NodeUpdateManager manager) {
this.manager = manager;
core = manager.node.clientCore;
this.revocationDNFCounter = 0;
Modified:
trunk/freenet/src/freenet/node/useralerts/UpdatedVersionAvailableUserAlert.java
===================================================================
---
trunk/freenet/src/freenet/node/useralerts/UpdatedVersionAvailableUserAlert.java
2007-05-09 21:10:48 UTC (rev 13180)
+++
trunk/freenet/src/freenet/node/useralerts/UpdatedVersionAvailableUserAlert.java
2007-05-09 21:12:03 UTC (rev 13181)
@@ -4,14 +4,14 @@
package freenet.node.useralerts;
import freenet.l10n.L10n;
-import freenet.node.updater.NodeUpdaterManager;
+import freenet.node.updater.NodeUpdateManager;
import freenet.node.updater.RevocationChecker;
import freenet.support.HTMLNode;
public class UpdatedVersionAvailableUserAlert implements UserAlert {
- private final NodeUpdaterManager updater;
+ private final NodeUpdateManager updater;
- public UpdatedVersionAvailableUserAlert(NodeUpdaterManager updater){
+ public UpdatedVersionAvailableUserAlert(NodeUpdateManager updater){
this.updater = updater;
}