diff --git a/apps/desktopgui/build.xml b/apps/desktopgui/build.xml
index 7e25f3897757cb3ac006c2492c7707751621e56d..3f6256b8994d836ecea94a627b0068e359211c02 100644
--- a/apps/desktopgui/build.xml
+++ b/apps/desktopgui/build.xml
@@ -5,7 +5,6 @@
 	<property name="build" value="build"/>
 	<property name="dist"  location="dist"/>
 	<property name="jar" value="desktopgui.jar"/>
-	<property name="resources" value="resources"/>
 	<property name="javadoc" value="javadoc"/>
 	<property name="javac.compilerargs" value=""/>
 	<property name="javac.version" value="1.6" />
@@ -36,9 +35,6 @@
                     <pathelement location="../../router/java/build/router.jar" />
                 </classpath>
             </javac>
-            <copy todir="${build}/desktopgui/${resources}">
-                <fileset dir="${resources}" />
-            </copy>
         </target>
 
         <target name="bundle" unless="no.bundle">
@@ -76,6 +72,8 @@
 	<target name="jar" depends="compile, bundle, listChangedFiles" unless="jar.uptodate" >
 		<!-- set if unset -->
 		<property name="workspace.changes.tr" value="" />
+                <!-- ideal for linux: 24x24, but transparency doesn't work -->
+                <copy tofile="${build}/desktopgui/resources/images/logo.png" file="../../installer/resources/themes/console/images/itoopie_xsm.png" />
 		<jar basedir="${build}" excludes="messages-src/**" destfile="${dist}/${jar}">
 			<manifest>
 				<attribute name="Main-Class" value="net.i2p.desktopgui.Main"/>
diff --git a/apps/desktopgui/resources/images/logo.jpg b/apps/desktopgui/resources/images/logo.jpg
deleted file mode 100644
index f1b5ccfc8728618281387d7a4b8ed11dedb8f39e..0000000000000000000000000000000000000000
Binary files a/apps/desktopgui/resources/images/logo.jpg and /dev/null differ
diff --git a/apps/desktopgui/resources/images/logo.png b/apps/desktopgui/resources/images/logo.png
deleted file mode 100644
index ad89a98643d2fd0a323a9beadd1a70f05de9d159..0000000000000000000000000000000000000000
Binary files a/apps/desktopgui/resources/images/logo.png and /dev/null differ
diff --git a/apps/desktopgui/resources/images/logo_green.jpg b/apps/desktopgui/resources/images/logo_green.jpg
deleted file mode 100644
index d558efcea3a319fdea21fd624fe5b72813d37918..0000000000000000000000000000000000000000
Binary files a/apps/desktopgui/resources/images/logo_green.jpg and /dev/null differ
diff --git a/apps/desktopgui/resources/images/logo_orange.jpg b/apps/desktopgui/resources/images/logo_orange.jpg
deleted file mode 100644
index d131f21b6297f0955632ab353844db0c4a8c587f..0000000000000000000000000000000000000000
Binary files a/apps/desktopgui/resources/images/logo_orange.jpg and /dev/null differ
diff --git a/apps/desktopgui/resources/images/logo_red.jpg b/apps/desktopgui/resources/images/logo_red.jpg
deleted file mode 100644
index c1a60b8bbe680066069f5db62318055542c75958..0000000000000000000000000000000000000000
Binary files a/apps/desktopgui/resources/images/logo_red.jpg and /dev/null differ
diff --git a/apps/desktopgui/src/net/i2p/desktopgui/ExternalTrayManager.java b/apps/desktopgui/src/net/i2p/desktopgui/ExternalTrayManager.java
index 2a3a16b63ea68964ed9d98d9043ec1611e9e76f2..e15e5c08b553de3d177d74f0047a2944f949ffce 100644
--- a/apps/desktopgui/src/net/i2p/desktopgui/ExternalTrayManager.java
+++ b/apps/desktopgui/src/net/i2p/desktopgui/ExternalTrayManager.java
@@ -8,14 +8,21 @@ import java.awt.event.ActionListener;
 
 import javax.swing.SwingWorker;
 
+import net.i2p.I2PAppContext;
 import net.i2p.desktopgui.router.RouterManager;
-import net.i2p.util.Log;
 
-public class ExternalTrayManager extends TrayManager {
+/**
+ *  When started before the router, e.g. with
+ *  java -cp i2p.jar:desktopgui.jar net.i2p.desktopgui.Main
+ *
+ *  No access to context, very limited abilities.
+ *  Not fully supported.
+ */
+class ExternalTrayManager extends TrayManager {
 	
-    private final static Log log = new Log(ExternalTrayManager.class);
-
-    protected ExternalTrayManager() {}
+    public ExternalTrayManager(I2PAppContext ctx) {
+        super(ctx);
+    }
 
     @Override
     public PopupMenu getMainMenu() {
diff --git a/apps/desktopgui/src/net/i2p/desktopgui/InternalTrayManager.java b/apps/desktopgui/src/net/i2p/desktopgui/InternalTrayManager.java
index 1cb464308c8bc6e12d208f58b5675ccd49befe97..90017c0353222588cfa7bb7c3912c4888944587c 100644
--- a/apps/desktopgui/src/net/i2p/desktopgui/InternalTrayManager.java
+++ b/apps/desktopgui/src/net/i2p/desktopgui/InternalTrayManager.java
@@ -11,13 +11,24 @@ import net.i2p.desktopgui.gui.DesktopguiConfigurationFrame;
 import net.i2p.desktopgui.router.RouterManager;
 import net.i2p.desktopgui.util.BrowseException;
 import net.i2p.desktopgui.util.I2PDesktop;
+import net.i2p.router.RouterContext;
 import net.i2p.util.Log;
 
-public class InternalTrayManager extends TrayManager {
+/**
+ *  java -cp i2p.jar:desktopgui.jar net.i2p.desktopgui.Main
+ *
+ *  Full access to router context.
+ */
+class InternalTrayManager extends TrayManager {
 	
-	private final static Log log = new Log(InternalTrayManager.class);
+    private final RouterContext _context;
+    private final Log log;
 
-    protected InternalTrayManager() {}
+    public InternalTrayManager(RouterContext ctx) {
+        super(ctx);
+        _context = ctx;
+        log = ctx.logManager().getLog(InternalTrayManager.class);
+    }
 
     @Override
     public PopupMenu getMainMenu() {
@@ -56,7 +67,7 @@ public class InternalTrayManager extends TrayManager {
 
                     @Override
                     protected Object doInBackground() throws Exception {
-                        new DesktopguiConfigurationFrame().setVisible(true);
+                        new DesktopguiConfigurationFrame(_context).setVisible(true);
                         return null;
                     }
 
@@ -73,7 +84,7 @@ public class InternalTrayManager extends TrayManager {
 
                     @Override
                     protected Object doInBackground() throws Exception {
-                        RouterManager.restart();
+                        RouterManager.restart(_context);
                         return null;
                     }
                     
@@ -91,7 +102,7 @@ public class InternalTrayManager extends TrayManager {
                     
                     @Override
                     protected Object doInBackground() throws Exception {
-                        RouterManager.shutDown();
+                        RouterManager.shutDown(_context);
                         return null;
                     }
                     
diff --git a/apps/desktopgui/src/net/i2p/desktopgui/Main.java b/apps/desktopgui/src/net/i2p/desktopgui/Main.java
index c07e03f44671aa3246d3e39e6c893caac70b9296..4592ae7b166fcfb03ecaf3cf53b926e7b0ad6d9d 100644
--- a/apps/desktopgui/src/net/i2p/desktopgui/Main.java
+++ b/apps/desktopgui/src/net/i2p/desktopgui/Main.java
@@ -7,8 +7,15 @@ package net.i2p.desktopgui;
 import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
 import javax.swing.UnsupportedLookAndFeelException;
+
+import net.i2p.I2PAppContext;
+import net.i2p.app.ClientAppManager;
+import net.i2p.app.ClientAppState;
+import static net.i2p.app.ClientAppState.*;
 import net.i2p.desktopgui.router.RouterManager;
 import net.i2p.desktopgui.util.*;
+import net.i2p.router.RouterContext;
+import net.i2p.router.app.RouterApp;
 import net.i2p.util.Log;
 import net.i2p.util.Translate;
 import net.i2p.util.I2PProperties.I2PPropertyCallback;
@@ -16,22 +23,57 @@ import net.i2p.util.I2PProperties.I2PPropertyCallback;
 /**
  * The main class of the application.
  */
-public class Main {
-    
-    ///Manages the lifetime of the tray icon.
-    private TrayManager trayManager = null;
-    private final static Log log = new Log(Main.class);
+public class Main implements RouterApp {
+
+    private final I2PAppContext _appContext;
+    private final RouterContext _context;
+    private final ClientAppManager _mgr;
+    private final Log log;
+    private ClientAppState _state = UNINITIALIZED;
+    private TrayManager _trayManager;
 
+    /**
+     *  @since 0.9.26
+     */
+    public Main(RouterContext ctx, ClientAppManager mgr, String args[]) {
+        _appContext = _context = ctx;
+        _mgr = mgr;
+        log = _appContext.logManager().getLog(Main.class);
+        _state = INITIALIZED;
+    }
+
+    /**
+     *  @since 0.9.26
+     */
+    public Main() {
+        _appContext = I2PAppContext.getGlobalContext();
+        if (_appContext instanceof RouterContext)
+            _context = (RouterContext) _appContext;
+        else
+            _context = null;
+        _mgr = null;
+        log = _appContext.logManager().getLog(Main.class);
+        _state = INITIALIZED;
+    }
+    
     /**
      * Start the tray icon code (loads tray icon in the tray area).
-     * @throws Exception 
+     * @throws AWTException on startup error, including systray not supported 
      */
-    public void startUp() throws Exception {
-        trayManager = TrayManager.getInstance();
+    private synchronized void startUp() throws Exception {
+        final TrayManager trayManager;
+        if (_context != null)
+            trayManager = new InternalTrayManager(_context);
+        else
+            trayManager = new ExternalTrayManager(_appContext);
         trayManager.startManager();
+        _trayManager = trayManager;
+        changeState(RUNNING);
+        if (_mgr != null)
+            _mgr.register(this);
         
-        if(RouterManager.inI2P()) {
-            RouterManager.getRouterContext().addPropertyCallback(new I2PPropertyCallback() {
+        if (_context != null) {
+            _context.addPropertyCallback(new I2PPropertyCallback() {
 
                 @Override
                 public void propertyChanged(String arg0, String arg1) {
@@ -45,26 +87,36 @@ public class Main {
     }
     
     public static void main(String[] args) {
-        beginStartup(args);
+        Main main = new Main();
+        main.beginStartup(args);
     }
 
     /**
      * Main method launching the application.
+     *
+     * @param args unused
      */
-    public static void beginStartup(String[] args) {
-        try {
-            String headless = System.getProperty("java.awt.headless");
-            boolean isHeadless = Boolean.parseBoolean(headless);
-            if(isHeadless) {
-            	log.warn("Headless environment: not starting desktopgui!");
-                return;
-            }
-        }
-        catch(Exception e) {
+    private void beginStartup(String[] args) {
+        changeState(STARTING);
+        String headless = System.getProperty("java.awt.headless");
+        boolean isHeadless = Boolean.parseBoolean(headless);
+        if (isHeadless) {
+        	log.warn("Headless environment: not starting desktopgui!");
+            changeState(START_FAILED, "Headless environment: not starting desktopgui!", null);
             return;
         }
         try {
-            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+            //UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels();
+            //for (int i = 0; i < lafs.length; i++) {
+            //    System.out.println("LAF " + i + ": " + lafs[i].getName() + ' ' + lafs[i].getClassName());
+            //}
+            String laf = UIManager.getSystemLookAndFeelClassName();
+            //System.out.println("Default: " + laf);
+            UIManager.setLookAndFeel(laf);
+            //laf = UIManager.getCrossPlatformLookAndFeelClassName();
+            //System.out.println("Cross-Platform: " + laf);
+            //UIManager.setLookAndFeel(laf);
+            //UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
         } catch (ClassNotFoundException ex) {
             log.log(Log.ERROR, null, ex);
         } catch (InstantiationException ex) {
@@ -73,23 +125,28 @@ public class Main {
             log.log(Log.ERROR, null, ex);
         } catch (UnsupportedLookAndFeelException ex) {
             log.log(Log.ERROR, null, ex);
+        } catch (Error ex) {
+            // on permissions error (different user)
+            // Exception in thread "main" java.lang.InternalError: Can't connect to X11 window server using ':0' as the value of the DISPLAY variable.
+            log.log(Log.ERROR, "No permissions? Different user?", ex);
+            changeState(START_FAILED, "No permissions? Different user?", new RuntimeException(ex));
+            return;
         }
         
-        ConfigurationManager.getInstance().loadArguments(args);
-        
-        final Main main = new Main();
+        // TODO process args with getopt if needed
         
-        main.launchForeverLoop();
+        if (_context == null)
+            launchForeverLoop();
         //We'll be doing GUI work, so let's stay in the event dispatcher thread.
         SwingUtilities.invokeLater(new Runnable() {
 
             @Override
             public void run() {
                 try {
-                    main.startUp();
-                }
-                catch(Exception e) {
+                    startUp();
+                } catch(Exception e) {
                     log.error("Failed while running desktopgui!", e);
+                    changeState(START_FAILED, "Failed while running desktopgui!", e);
                 }
                 
             }
@@ -102,7 +159,7 @@ public class Main {
      * Avoids the app terminating because no Window is opened anymore.
      * More info: http://java.sun.com/javase/6/docs/api/java/awt/doc-files/AWTThreadIssues.html#Autoshutdown
      */
-    public void launchForeverLoop() {
+    private static void launchForeverLoop() {
        Runnable r = new Runnable() {
             public void run() {
                 try {
@@ -114,9 +171,60 @@ public class Main {
                 }
             }
         };
-        Thread t = new Thread(r);
+        Thread t = new Thread(r, "DesktopGUI spinner");
         t.setDaemon(false);
         t.start();
     }
-    
+
+    /////// ClientApp methods
+
+    /** @since 0.9.26 */
+    public synchronized void startup() {
+        beginStartup(null);
+    }
+
+    /** @since 0.9.26 */
+    public synchronized void shutdown(String[] args) {
+        if (_state == STOPPED)
+            return;
+        changeState(STOPPING);
+        if (_trayManager != null)
+            _trayManager.stopManager();
+        changeState(STOPPED);
+    }
+
+    /** @since 0.9.26 */
+    public synchronized ClientAppState getState() {
+        return _state;
+    }
+
+    /** @since 0.9.26 */
+    public String getName() {
+        return "desktopgui";
+    }
+
+    /** @since 0.9.26 */
+    public String getDisplayName() {
+        return "Desktop GUI";
+    }
+
+    /////// end ClientApp methods
+
+    /** @since 0.9.26 */
+    private void changeState(ClientAppState state) {
+        changeState(state, null, null);
+    }
+
+    /** @since 0.9.26 */
+    private synchronized void changeState(ClientAppState state, String msg, Exception e) {
+        _state = state;
+        if (_mgr != null)
+            _mgr.notify(this, state, msg, e);
+        if (_context == null) {
+            if (msg != null)
+                System.out.println(state + ": " + msg);
+            if (e != null)
+                e.printStackTrace();
+        }
+    }
 }
diff --git a/apps/desktopgui/src/net/i2p/desktopgui/TrayManager.java b/apps/desktopgui/src/net/i2p/desktopgui/TrayManager.java
index 227050735c62123fb13a9516c305216a742ddb87..ac0242dd67ca417526fac2e35c45492671137723 100644
--- a/apps/desktopgui/src/net/i2p/desktopgui/TrayManager.java
+++ b/apps/desktopgui/src/net/i2p/desktopgui/TrayManager.java
@@ -8,58 +8,65 @@ import java.awt.Toolkit;
 import java.awt.TrayIcon;
 import java.net.URL;
 
+import net.i2p.I2PAppContext;
 import net.i2p.desktopgui.i18n.DesktopguiTranslator;
-import net.i2p.desktopgui.router.RouterManager;
-import net.i2p.util.Log;
+import net.i2p.util.SystemVersion;
 
 /**
  * Manages the tray icon life.
  */
-public abstract class TrayManager {
+abstract class TrayManager {
 
-    private static TrayManager instance = null;
+    protected final I2PAppContext _appContext;
     ///The tray area, or null if unsupported
-    protected SystemTray tray = null;
+    protected SystemTray tray;
     ///Our tray icon, or null if unsupported
-    protected TrayIcon trayIcon = null;
-    private final static Log log = new Log(TrayManager.class);
-    
+    protected TrayIcon trayIcon;
+
     /**
      * Instantiate tray manager.
      */
-    protected TrayManager() {}
-    
-    protected static TrayManager getInstance() {
-        if(instance == null) {
-            boolean inI2P = RouterManager.inI2P();
-            if(inI2P) {
-                instance = new InternalTrayManager();
-            }
-            else {
-                instance = new ExternalTrayManager();
-            }
-        }
-        return instance;
+    protected TrayManager(I2PAppContext ctx) {
+        _appContext = ctx;
     }
-
+    
     /**
      * Add the tray icon to the system tray and start everything up.
      */
-    protected void startManager() {
+    public synchronized void startManager()  throws AWTException {
         if(SystemTray.isSupported()) {
+            // TODO figure out how to get menu to pop up on left-click
+            // left-click does nothing by default
+            // MouseListener, MouseEvent, ...
             tray = SystemTray.getSystemTray();
-            trayIcon = new TrayIcon(getTrayImage(), "I2P", getMainMenu());
+            // Windows typically has tooltips; Linux (at least Ubuntu) doesn't
+            String tooltip = SystemVersion.isWindows() ? _t("I2P: Right-click for menu") : null;
+            trayIcon = new TrayIcon(getTrayImage(), tooltip, getMainMenu());
             trayIcon.setImageAutoSize(true); //Resize image to fit the system tray
-            try {
-                tray.add(trayIcon);
-            } catch (AWTException e) {
-                log.log(Log.WARN, "Problem creating system tray icon!", e);
-            }
+            tray.add(trayIcon);
+            // 16x16 on Windows, 24x24 on Linux, but that will probably vary
+            //System.out.println("Tray icon size is " + trayIcon.getSize());
+        } else {
+            throw new AWTException("SystemTray not supported");
+        }
+    }
+
+    /**
+     * Remove the tray icon from the system tray
+     *
+     * @since 0.9.26
+     */
+    public synchronized void stopManager() {
+        if (tray != null && trayIcon != null) {
+            tray.remove(trayIcon);
+            tray = null;
+            trayIcon = null;
         }
     }
     
-    protected void languageChanged() {
-        trayIcon.setPopupMenu(getMainMenu());
+    public synchronized void languageChanged() {
+        if (trayIcon != null)
+            trayIcon.setPopupMenu(getMainMenu());
     }
     
     /**
@@ -71,14 +78,17 @@ public abstract class TrayManager {
     /**
      * Get tray icon image from the desktopgui resources in the jar file.
      * @return image used for the tray icon
+     * @throws AWTException if image not found
      */
-    private Image getTrayImage() {
+    private Image getTrayImage() throws AWTException {
         URL url = getClass().getResource("/desktopgui/resources/images/logo.png");
+        if (url == null)
+            throw new AWTException("cannot load tray image");
         Image image = Toolkit.getDefaultToolkit().getImage(url);
         return image;
     }
     
-    protected static String _t(String s) {
-        return DesktopguiTranslator._t(s);
+    protected String _t(String s) {
+        return DesktopguiTranslator._t(_appContext, s);
     }
 }
diff --git a/apps/desktopgui/src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java
index a697c5779f18633f7b25e7876e6fcb53af3d4a32..98e513eb3747deedd171ab4070414d170951b38f 100644
--- a/apps/desktopgui/src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java
+++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/DesktopguiConfigurationFrame.java
@@ -13,8 +13,10 @@ package net.i2p.desktopgui.gui;
 
 import java.util.logging.Level;
 import java.util.logging.Logger;
+
 import net.i2p.desktopgui.i18n.DesktopguiTranslator;
 import net.i2p.desktopgui.router.RouterManager;
+import net.i2p.router.RouterContext;
 
 /**
  *
@@ -22,9 +24,12 @@ import net.i2p.desktopgui.router.RouterManager;
  */
 public class DesktopguiConfigurationFrame extends javax.swing.JFrame {
 
+    private final RouterContext _context;
+
     /** Creates new form ConfigurationFrame */
-    public DesktopguiConfigurationFrame() {
+    public DesktopguiConfigurationFrame(RouterContext ctx) {
         initComponents();
+        _context = ctx;
     }
 
     /** This method is called from within the constructor to
@@ -98,8 +103,8 @@ public class DesktopguiConfigurationFrame extends javax.swing.JFrame {
         configureDesktopgui();
     }//GEN-LAST:event_okButtonMouseReleased
 
-    protected static String _t(String s) {
-        return DesktopguiTranslator._t(s);
+    private String _t(String s) {
+        return DesktopguiTranslator._t(_context, s);
     }
 
     private void configureDesktopgui() {
@@ -114,7 +119,7 @@ public class DesktopguiConfigurationFrame extends javax.swing.JFrame {
             System.out.println("Enabling desktopgui");
         }
         try {
-            RouterManager.getRouterContext().router().saveConfig(property, value);
+            _context.router().saveConfig(property, value);
         } catch (Exception ex) {
             Logger.getLogger(DesktopguiConfigurationFrame.class.getName()).log(Level.SEVERE, null, ex);
         }
diff --git a/apps/desktopgui/src/net/i2p/desktopgui/i18n/DesktopguiTranslator.java b/apps/desktopgui/src/net/i2p/desktopgui/i18n/DesktopguiTranslator.java
index 3778c4ad93e420ea886274dfcf70e94c7cba1b8e..9fae60ed1401140d01429a5d48bbc9de0eaf00a0 100644
--- a/apps/desktopgui/src/net/i2p/desktopgui/i18n/DesktopguiTranslator.java
+++ b/apps/desktopgui/src/net/i2p/desktopgui/i18n/DesktopguiTranslator.java
@@ -7,20 +7,11 @@ public class DesktopguiTranslator {
     
     private static final String BUNDLE_NAME = "net.i2p.desktopgui.messages";
     
-    private static I2PAppContext ctx;
-    
-    private static I2PAppContext getRouterContext() {
-        if(ctx == null) {
-            ctx = I2PAppContext.getCurrentContext();
-        }
-        return ctx;
-    }
-    
-    public static String _t(String s) {
-        return Translate.getString(s, getRouterContext(), BUNDLE_NAME);
+    public static String _t(I2PAppContext ctx, String s) {
+        return Translate.getString(s, ctx, BUNDLE_NAME);
     }
 
-    public static String _t(String s, Object o) {
-        return Translate.getString(s, o, getRouterContext(), BUNDLE_NAME);
+    public static String _t(I2PAppContext ctx, String s, Object o) {
+        return Translate.getString(s, o, ctx, BUNDLE_NAME);
     }
 }
diff --git a/apps/desktopgui/src/net/i2p/desktopgui/router/RouterManager.java b/apps/desktopgui/src/net/i2p/desktopgui/router/RouterManager.java
index 82b36938ac3f7de5cecfeac20a8678df7457c84e..9267bcef082b924e80d9fa4ed274319dd961503d 100644
--- a/apps/desktopgui/src/net/i2p/desktopgui/router/RouterManager.java
+++ b/apps/desktopgui/src/net/i2p/desktopgui/router/RouterManager.java
@@ -16,29 +16,9 @@ import net.i2p.util.Log;
  */
 public class RouterManager {
 	
-	private final static Log log = new Log(RouterManager.class);
-	private static I2PAppContext context = I2PAppContext.getCurrentContext();
-	
-	public static I2PAppContext getAppContext() {
-		return context;
-	}
-	
-	public static RouterContext getRouterContext() throws Exception {
-		if(context.isRouterContext()) {
-			return (RouterContext) context;
-		}
-		else {
-			throw new Exception("No RouterContext available!");
-		}
-	}
-	
-	private static Router getRouter() {
-		try {
-			return getRouterContext().router();
-		} catch (Exception e) {
-	        log.error("Failed to get router. Why did we request it if no RouterContext is available?", e);
-            return null;
-        }
+    /** @return non-null */
+    private static I2PAppContext getAppContext() {
+        return I2PAppContext.getGlobalContext();
     }
     
     /**
@@ -53,9 +33,10 @@ public class RouterManager {
             //TODO: set/get PID
             String separator = System.getProperty("file.separator");
             String location = getAppContext().getBaseDir().getAbsolutePath();
-            
-            Runtime.getRuntime().exec(location + separator + "i2psvc " + location + separator + "wrapper.config");
+            String[] args = new String[] { location + separator + "i2psvc", location + separator + "wrapper.config" };
+            Runtime.getRuntime().exec(args);
         } catch (IOException e) {
+            Log log = getAppContext().logManager().getLog(RouterManager.class);
             log.log(Log.WARN, "Failed to start I2P", e);
         }
     }
@@ -63,17 +44,14 @@ public class RouterManager {
     /**
      * Restart the running I2P instance.
      */
-    public static void restart() {
-        if(inI2P()) {
-            getRouter().restart();
-        }
+    public static void restart(RouterContext ctx) {
+        ctx.router().restart();
     }
 
     /**
      * Stop the running I2P instance.
      */
-    public static void shutDown() {
-        if(inI2P()) {
+    public static void shutDown(RouterContext ctx) {
             Thread t = new Thread(new Runnable() {
 
                 @Override
@@ -83,14 +61,6 @@ public class RouterManager {
                 
             });
             t.start();
-            getRouter().shutdown(Router.EXIT_HARD);
-        }
-    }
-    
-    /**
-     * Check if we are running inside I2P.
-     */
-    public static boolean inI2P() {
-        return context.isRouterContext();
+            ctx.router().shutdown(Router.EXIT_HARD);
     }
 }
diff --git a/apps/desktopgui/src/net/i2p/desktopgui/util/ConfigurationManager.java b/apps/desktopgui/src/net/i2p/desktopgui/util/ConfigurationManager.java
deleted file mode 100644
index cc0516bd61581d88ae63109fa03914a0203a3145..0000000000000000000000000000000000000000
--- a/apps/desktopgui/src/net/i2p/desktopgui/util/ConfigurationManager.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package net.i2p.desktopgui.util;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Manage the configuration of desktopgui.
- * @author mathias
- *
- */
-public class ConfigurationManager {
-	
-	private static ConfigurationManager instance;
-	///Configurations with a String as value
-	private Map<String, String> stringConfigurations = new HashMap<String, String>();
-	///Configurations with a Boolean as value
-	private Map<String, Boolean> booleanConfigurations = new HashMap<String, Boolean>();
-
-	private ConfigurationManager() {}
-	
-	public static ConfigurationManager getInstance() {
-		if(instance == null) {
-			instance = new ConfigurationManager();
-		}
-		return instance;
-	}
-	
-	/**
-	 * Collects arguments of the form --word, --word=otherword and -blah
-	 * to determine user parameters.
-	 * @param args Command line arguments to the application
-	 */
-	public void loadArguments(String[] args) {
-		for(int i=0; i<args.length; i++) {
-			String arg = args[i];
-			if(arg.startsWith("--")) {
-				arg = arg.substring(2);
-				if(arg.length() < 1) {
-					continue;
-				}
-				int equals = arg.indexOf('=');
-				if(equals != -1 && equals < arg.length() - 1) { //String configuration
-					loadStringConfiguration(arg, equals);
-				}
-				else { //Boolean configuration
-					loadBooleanConfiguration(arg);
-				}
-			}
-			else if(arg.startsWith("-")) { //Boolean configuration
-				loadBooleanConfiguration(arg);
-			}
-		}
-	}
-	
-	/**
-	 * Add a boolean configuration.
-	 * @param arg The key we wish to add as a configuration.
-	 */
-	public void loadBooleanConfiguration(String arg) {
-		booleanConfigurations.put(arg, Boolean.TRUE);
-	}
-	
-	/**
-	 * Add a String configuration which consists a key and a value.
-	 * @param arg String of the form substring1=substring2.
-	 * @param equalsPosition Position of the '=' element.
-	 */
-	public void loadStringConfiguration(String arg, int equalsPosition) {
-		String key = arg.substring(0, equalsPosition);
-		String value = arg.substring(equalsPosition+1);
-		stringConfigurations.put(key, value);
-	}
-	
-	/**
-	 * Check if a specific boolean configuration exists.
-	 * @param arg The key for the configuration.
-	 * @param defaultValue If the configuration is not found, we use a default value.
-	 * @return The value of a configuration: true if found, defaultValue if not found.
-	 */
-	public boolean getBooleanConfiguration(String arg, boolean defaultValue) {
-		Boolean value = booleanConfigurations.get("startWithI2P");
-		System.out.println(value);
-		if(value != null) {
-			return value;
-		}
-		return defaultValue;
-	}
-	
-	/**
-	 * Get a specific String configuration.
-	 * @param arg The key for the configuration.
-	 * @param defaultValue If the configuration is not found, we use a default value.
-	 * @return The value of the configuration, or the defaultValue.
-	 */
-	public String getStringConfiguration(String arg, String defaultValue) {
-		String value = stringConfigurations.get(arg);
-		System.out.println(value);
-		if(value != null) {
-			return value;
-		}
-		return defaultValue;
-	}
-}
diff --git a/apps/desktopgui/src/net/i2p/desktopgui/util/I2PDesktop.java b/apps/desktopgui/src/net/i2p/desktopgui/util/I2PDesktop.java
index 6ddfc4a970d810eabae4fd147223a4f64310b969..696088cfb67b4d76917fe537ae54f617eb7f1e6c 100644
--- a/apps/desktopgui/src/net/i2p/desktopgui/util/I2PDesktop.java
+++ b/apps/desktopgui/src/net/i2p/desktopgui/util/I2PDesktop.java
@@ -3,12 +3,9 @@ package net.i2p.desktopgui.util;
 import java.awt.Desktop;
 import java.awt.Desktop.Action;
 import java.net.URI;
-import net.i2p.util.Log;
 
 public class I2PDesktop {
     
-    private final static Log log = new Log(I2PDesktop.class);
-    
     public static void browse(String url) throws BrowseException {
         if(Desktop.isDesktopSupported()) {
             Desktop desktop = Desktop.getDesktop();
@@ -27,4 +24,4 @@ public class I2PDesktop {
             throw new BrowseException();
         }
     }
-}
\ No newline at end of file
+}