diff --git a/apps/desktopgui/build.xml b/apps/desktopgui/build.xml
index 7e25f3897..3f6256b89 100644
--- a/apps/desktopgui/build.xml
+++ b/apps/desktopgui/build.xml
@@ -5,7 +5,6 @@
-
@@ -36,9 +35,6 @@
-
-
-
@@ -76,6 +72,8 @@
+
+
diff --git a/apps/desktopgui/resources/images/logo.jpg b/apps/desktopgui/resources/images/logo.jpg
deleted file mode 100644
index f1b5ccfc8..000000000
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 ad89a9864..000000000
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 d558efcea..000000000
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 d131f21b6..000000000
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 c1a60b8bb..000000000
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 2a3a16b63..e15e5c08b 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 1cb464308..90017c035 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 c07e03f44..4592ae7b1 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;
/**
- * Start the tray icon code (loads tray icon in the tray area).
- * @throws Exception
+ * @since 0.9.26
*/
- public void startUp() throws Exception {
- trayManager = TrayManager.getInstance();
+ 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 AWTException on startup error, including systray not supported
+ */
+ 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);
+ // TODO process args with getopt if needed
- final Main main = new Main();
-
- 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 227050735..ac0242dd6 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 a697c5779..98e513eb3 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 3778c4ad9..9fae60ed1 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 82b36938a..9267bcef0 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 cc0516bd6..000000000
--- 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 stringConfigurations = new HashMap();
- ///Configurations with a Boolean as value
- private Map booleanConfigurations = new HashMap();
-
- 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