package net.i2p.desktopgui;
/*
* Main.java
*/
import javax.swing.SwingUtilities;
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.SystemVersion;
import net.i2p.util.Translate;
import net.i2p.util.I2PProperties.I2PPropertyCallback;
/**
* The main class of the application.
*/
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;
public static final String PROP_ENABLE = "desktopgui.enabled";
private static final String PROP_SWING = "desktopgui.swing";
/**
* @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 AWTException on startup error, including systray not supported
*/
private synchronized void startUp() throws Exception {
final TrayManager trayManager;
boolean useSwingDefault = !(SystemVersion.isWindows() || SystemVersion.isMac());
boolean useSwing = _appContext.getProperty(PROP_SWING, useSwingDefault);
if (_context != null)
trayManager = new InternalTrayManager(_context, this, useSwing);
else
trayManager = new ExternalTrayManager(_appContext, this, useSwing);
trayManager.startManager();
_trayManager = trayManager;
changeState(RUNNING);
if (_mgr != null)
_mgr.register(this);
if (_context != null) {
_context.addPropertyCallback(new I2PPropertyCallback() {
@Override
public void propertyChanged(String arg0, String arg1) {
if(arg0.equals(Translate.PROP_LANG)) {
trayManager.languageChanged();
}
}
});
}
}
public static void main(String[] args) {
Main main = new Main();
main.beginStartup(args);
}
/**
* Main method launching the application.
*
* @param args unused
*/
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;
}
// TODO process args with getopt if needed
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 {
startUp();
} catch(Exception e) {
log.error("Failed while running desktopgui!", e);
changeState(START_FAILED, "Failed while running desktopgui!", e);
}
}
});
}
/**
* 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
*/
private static void launchForeverLoop() {
Runnable r = new Runnable() {
public void run() {
try {
Object o = new Object();
synchronized (o) {
o.wait();
}
} catch (InterruptedException ie) {
}
}
};
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();
}
}
}