package com.limegroup.gnutella.gui; import java.awt.Frame; import java.io.File; import java.io.IOException; import java.util.Properties; import javax.swing.JLabel; import javax.swing.UIManager; import javax.swing.plaf.basic.BasicHTML; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.limegroup.gnutella.ActivityCallback; import com.limegroup.gnutella.ErrorService; import com.limegroup.gnutella.RouterService; import com.limegroup.gnutella.UPnPManager; import com.limegroup.gnutella.browser.ExternalControl; import com.limegroup.gnutella.bugs.BugManager; import com.limegroup.gnutella.gui.init.SetupManager; import com.limegroup.gnutella.gui.notify.NotifyUserProxy; import com.limegroup.gnutella.gui.themes.ThemeSettings; import com.limegroup.gnutella.io.NIODispatcher; import com.limegroup.gnutella.settings.ApplicationSettings; import com.limegroup.gnutella.settings.ConnectionSettings; import com.limegroup.gnutella.settings.DaapSettings; import com.limegroup.gnutella.settings.StartupSettings; import com.limegroup.gnutella.util.CommonUtils; import com.limegroup.gnutella.util.FileUtils; import com.limegroup.gnutella.util.I18NConvert; import com.limegroup.gnutella.util.SystemUtils; import com.limegroup.gnutella.util.ThreadFactory; /** * This class instantiates all of the "top-level" application classes. These * include the <tt>ResourceManager</tt>, the <tt>GUIMediator</tt>, the * update checking classes, the <tt>SettingsManager</tt>, the * <tt>FileManager</tt>, <tt>RouterService</tt>, etc. <tt>GUIMediator</tt> * and <tt>RouterService</tt> construct the bulk of the front and back ends, * respectively. This class also links together any top-level classes that * need to know about each other. */ //2345678|012345678|012345678|012345678|012345678|012345678|012345678|012345678| public final class Initializer { private static Log LOG = null; /** * Used to determine whether or not LimeWire is running * from a system startup. */ private static volatile boolean isStartup = false; /** * Suppress the default constructor to ensure that this class can never be * constructed. */ private Initializer() {} /** * Initializes all of the necessary application classes. This begins with * the <tt>ResourceManager</tt> class that handles the look and feel of the * application as well as providing access to any string or image resources * used in the application. This then constructs the <tt>GUIMediator</tt>, * which in turn handles the construction of the entire frontend.<p> * * The <tt>SettingsManager</tt> and the <tt>FileManager</tt> are * initialized early to make sure that their resources are available and * loading as soon as possible. The update and init code is also kicked * off early to check for any available updates and to make sure that all * of the settings have been properly set up (going into the init setup * sequence otherwise). * * Finally, all of the primary backend classes are created, such as the * <tt>RouterService</tt> interface and <tt>StandardMessageRouter</tt>. * <tt>RouterService</tt> handles the creation of the other backend * classes. * * If this throws any exceptions, then LimeWire was not able to construct * properly and must be shut down. */ static void initialize(String args[], Frame awtSplash) throws Throwable { long startMemory = 0; if (CommonUtils.isLog4JAvailable()) { System.getProperties().remove("org.apache.commons.logging.Log"); } LOG = LogFactory.getLog(Initializer.class); if(LOG.isTraceEnabled()) { startMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); LOG.trace("START Initializer, using: " + startMemory + " memory"); } File userDir = new File(System.getProperty("user.dir", "")); if(userDir.exists()) FileUtils.setWriteable(userDir); FileUtils.setWriteable(CommonUtils.getUserSettingsDir()); // Set the error handler so we can receive core errors. ErrorService.setErrorCallback(new ErrorHandler()); // Set the messaging handler so we can receive core messages com.limegroup.gnutella.MessageService.setCallback(new MessageHandler()); // Set the default event error handler so we can receive uncaught // AWT errors. DefaultErrorCatcher.install(); // Register MacOS X specific stuff. if (CommonUtils.isMacOSX()) { LOG.trace("START registering OSX events"); // Enable GURL and fwd enqueud magnets to ExternalControl GURLHandler.getInstance().enable(); // Raise the number of allowed concurrent open files to 1024. SystemUtils.setOpenFileLimit(1024); LOG.trace("STOP registering OSX events"); if(ThemeSettings.isBrushedMetalTheme()) System.setProperty("apple.awt.brushMetalLook", "true"); LOG.trace("START MacEventHandler"); MacEventHandler.instance(); LOG.trace("STOP MacEventHandler"); } // If this is a request to launch a pmf then just do it and exit. if ( args.length >= 2 && "-pmf".equals(args[0]) ) { PackagedMediaFileLauncher.launchFile(args[1], false); return; } // Yield so any other events can be run to determine // startup status, but only if we're going to possibly // be starting... if(StartupSettings.RUN_ON_STARTUP.getValue()) { LOG.trace("START yield"); Thread.yield(); LOG.trace("STOP yield"); } if (args.length >= 1 && "-startup".equals(args[0])) isStartup = true; if (isStartup) { // if the user doesn't want to start on system startup, exit the // JVM immediately if(!StartupSettings.RUN_ON_STARTUP.getValue()) System.exit(0); } // See if our NIODispatcher clunked out. if(!NIODispatcher.instance().isRunning()) { showInternetBlockedFailure(); System.exit(1); } // Test for preexisting LimeWire and pass it a magnet URL if one // has been passed in. String arg = null; LOG.trace("START magnet check"); if (args.length > 0 && !args[0].equals("-startup")) { arg = ExternalControl.preprocessArgs(args); ExternalControl.checkForActiveLimeWire(arg); ExternalControl.enqueueMagnetRequest(arg); } else if (!StartupSettings.ALLOW_MULTIPLE_INSTANCES.getValue()) { // if we don't want multiple instances, we need to check if // limewire is already active. ExternalControl.checkForActiveLimeWire(); } LOG.trace("STOP magnet check"); LOG.trace("START system properties"); Initializer.setSystemProperties(); Initializer.setOSXSystemProperties(); LOG.trace("STOP system properties"); SetupManager setupManager = new SetupManager(); if(!setupManager.shouldShowFirewallWindow()) { if (!ConnectionSettings.DISABLE_UPNP.getValue()) { LOG.trace("START UPnPManager"); UPnPManager.instance().start(); LOG.trace("STOP UPnPManager"); } } LOG.trace("START ResourceManager"); ResourceManager.instance(); LOG.trace("STOP ResourceManager"); // Show the splash screen if we're not starting automatically on // system startup if(!isStartup) SplashWindow.instance().begin(); if(awtSplash != null) awtSplash.dispose(); // Construct gui callback class LOG.trace("START VisualConnectionCallback"); ActivityCallback ac = new VisualConnectionCallback(); LOG.trace("STOP VisualConnectionCallback"); // Construct the RouterService object, which functions as the // backend initializer as well as the interface from the GUI to the // front end. LOG.trace("START new RouterService"); RouterService routerService = new RouterService(ac); if(!setupManager.shouldShowFirewallWindow()) RouterService.asyncGuiInit(); LOG.trace("STOP new RouterService"); // Load up the HTML engine. LOG.trace("START HTML"); GUIMediator.setSplashScreenString( GUIMediator.getStringResource("SPLASH_STATUS_HTML_ENGINE")); BasicHTML.createHTMLView(new JLabel(), "<html>.</html>"); LOG.trace("STOP HTML"); //Initialize the bug manager LOG.trace("START BugManager"); BugManager.instance(); LOG.trace("STOP BugManager"); // Run through the initialization sequence -- this must always be // called before GUIMediator constructs the LibraryTree! LOG.trace("START SetupManager"); setupManager.createIfNeeded(); LOG.trace("STOP SetupManager"); // Make sure the save directory is valid. LOG.trace("START SaveDirectoryHandler"); SaveDirectoryHandler.handleSaveDirectory(); LOG.trace("STOP SaveDirectoryHandler"); GUIMediator.setSplashScreenString( GUIMediator.getStringResource("SPLASH_STATUS_INTERFACE")); // Construct the frontend LOG.trace("START GUIMediator.instance()"); GUIMediator mediator = GUIMediator.instance(); LOG.trace("STOP GUIMediator.instance()"); GUIMediator.setSplashScreenString( GUIMediator.getStringResource("SPLASH_STATUS_CORE_COMPONENTS")); // Notify GUIMediator of the RouterService interface class to the // backend. mediator.setRouterService(routerService); // Create the user desktop notifier object. // This must be done before the GUI is made visible, // otherwise the user can close it and not see the // tray icon. LOG.trace("START NotifyUserProxy"); if (ApplicationSettings.DISPLAY_TRAY_ICON.getValue()) NotifyUserProxy.instance(); LOG.trace("STOP NotifyUserProxy"); // Hide the splash screen and recycle its memory. if(!isStartup) SplashWindow.instance().dispose(); GUIMediator.allowVisibility(); // Make the GUI visible. if(!isStartup) { LOG.trace("START setAppVisible"); GUIMediator.setAppVisible(true); LOG.trace("STOP setAppVisible"); } else { LOG.trace("START startupHidden"); GUIMediator.startupHidden(); LOG.trace("STOP startupHidden"); } // Initialize IconManager. LOG.trace("START IconManager.instance()"); GUIMediator.setSplashScreenString( GUIMediator.getStringResource("SPLASH_STATUS_ICONS")); IconManager.instance(); LOG.trace("STOP IconManager.instance()"); // Touch the I18N stuff to ensure it loads properly. LOG.trace("START I18NConvert.instance()"); GUIMediator.setSplashScreenString( GUIMediator.getStringResource("SPLASH_STATUS_I18N")); I18NConvert.instance(); LOG.trace("STOP I18NConvert.instance()"); // Start the backend threads. Note that the GUI is not yet visible, // but it needs to be constructed at this point LOG.trace("START RouterService"); routerService.start(); LOG.trace("STOP RouterService"); // Instruct the gui to perform tasks that can only be performed // after the backend has been constructed. mediator.startTimer(); // Activate a download for magnet URL locally if one exists ExternalControl.runQueuedMagnetRequest(); // Start DaapManager if enabled if (DaapSettings.DAAP_ENABLED.getValue()) { LOG.trace("START DaapManager"); try { GUIMediator.setSplashScreenString( GUIMediator.getStringResource("SPLASH_STATUS_DAAP")); DaapManager.instance().start(); DaapManager.instance().init(); } catch (IOException err) { GUIMediator.showError("ERROR_DAAP_START_FAILED"); DaapSettings.DAAP_ENABLED.setValue(false); } LOG.trace("STOP DaapManager"); } // Tell the GUI that loading is all done. GUIMediator.instance().loadFinished(); // update the repaintInterval after the Splash is created, // so that the splash gets the smooth animation. if(CommonUtils.isMacOSX()) UIManager.put("ProgressBar.repaintInterval", new Integer(500)); if(LOG.isTraceEnabled()) { long stopMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); LOG.trace("STOP Initializer, using: " + stopMemory + " memory, consumed: " + (stopMemory - startMemory)); } } /** * Sets the startup property to be true. */ static void setStartup() { isStartup = true; } /** * Sets the system properties. */ static void setSystemProperties() { System.setProperty("http.agent", CommonUtils.getHttpServer()); } /** * Sets OSX system properties. */ static void setOSXSystemProperties() { if (!CommonUtils.isMacOSX()) return; System.setProperty("apple.laf.useScreenMenuBar", "true"); } /** * Shows a failure to start LW 'cause of the internet being blocked. */ static void showInternetBlockedFailure() { MultiLineLabel label = new MultiLineLabel(GUIMediator.getStringResource("ERROR_INTERNET_IS_BLOCKED"), 400); MessageService.instance().showMessage(label); } }