[gui-dev] BeanShell console patch

Jens-Uwe Mager <[email protected]> Wed, 25 Aug 2004 17:36:37 +0200
Newsgroups gmane.network.gnutella.limewire.gui.devel
Message-ID <[email protected]>
As requested by zab I include here the patch I use to add a BeanShell
console tab to LimeWire. The docs and the jar file for BeanShell itself
can be found at www.beanshell.org, I do not repeat it here. Attached
also is a sample LimeWire.bsh file that when put into the preferences
directory will execute upon LimeWire startup. Please note that the
method addSearchTab contains a call to setRepeatTime, that is only there
if the repeat search patch is applied, so comment it out.
-- 
Jens-Uwe Mager	<pgp-mailto:F476EBC2>

_______________________________________________
gui-dev mailing list
[email protected]
http://www.limewire.org/mailman/listinfo/gui-dev
beanshell.patch (text/plain, 17.2 KB)
Index: lib/jars/bsh-2.0b1.jar
===================================================================
Binary files /dev/null and lib/jars/bsh-2.0b1.jar differ
Index: gui/com/limegroup/gnutella/gui/BeanShellAppender.java
===================================================================
--- /dev/null	Wed Aug 25 12:58:17 2004
+++ gui/com/limegroup/gnutella/gui/BeanShellAppender.java	Fri Apr 30 23:42:19 2004
@@ -0,0 +1,17 @@
+package com.limegroup.gnutella.gui;
+
+import java.io.*;
+import java.net.*;
+import org.apache.log4j.*;
+import com.limegroup.gnutella.gui.tabs.BeanShellTab;
+import bsh.util.JConsole;
+
+public class BeanShellAppender extends WriterAppender {
+
+    public BeanShellAppender() {
+        setWriter(createWriter(((JConsole)BeanShellTab.getInstance().getComponent()).getErr()));
+    }
+
+    protected final void closeWriter() {
+    }
+}
Index: gui/com/limegroup/gnutella/gui/BeanShellHandler.java
===================================================================
--- /dev/null	Wed Aug 25 12:58:17 2004
+++ gui/com/limegroup/gnutella/gui/BeanShellHandler.java	Mon Jan 26 23:03:26 2004
@@ -0,0 +1,25 @@
+package com.limegroup.gnutella.gui;
+
+import java.io.*;
+import java.net.*;
+import java.util.logging.*;
+import com.limegroup.gnutella.gui.tabs.BeanShellTab;
+import bsh.util.JConsole;
+
+public class BeanShellHandler extends StreamHandler {
+
+    public BeanShellHandler() {
+        super(((JConsole)BeanShellTab.getInstance().getComponent()).getErr(),
+            new SimpleFormatter());
+        setLevel(Level.ALL);
+    }
+
+    public void publish(LogRecord record) {
+	super.publish(record);	
+	flush();
+    }
+
+    public void close() {
+	flush();
+    }
+}
Index: gui/com/limegroup/gnutella/gui/images/beanshell.gif
===================================================================
Binary files /dev/null and gui/com/limegroup/gnutella/gui/images/beanshell.gif differ
Index: gui/com/limegroup/gnutella/gui/tabs/BeanShellTab.java
===================================================================
--- /dev/null	Wed Aug 25 12:58:17 2004
+++ gui/com/limegroup/gnutella/gui/tabs/BeanShellTab.java	Fri Aug  6 22:34:36 2004
@@ -0,0 +1,69 @@
+package com.limegroup.gnutella.gui.tabs;
+
+import com.limegroup.gnutella.gui.*; 
+import com.limegroup.gnutella.settings.*; 
+import com.limegroup.gnutella.util.CommonUtils; 
+import com.limegroup.gnutella.gui.tables.ComponentMediator;
+import java.io.*;
+import javax.swing.*;
+import java.awt.*;
+import bsh.*;
+import bsh.util.*;
+import bsh.classpath.*;
+
+/**
+ * This class contains all elements of the tab for the BeanShell
+ * console.
+ */
+public final class BeanShellTab extends AbstractTab {
+
+	private JConsole console;
+        private Interpreter interpreter;
+        private static BeanShellTab instance;
+
+	/**
+	 * Constructs the tab for the BeanShell console
+	 *
+	 */
+	private BeanShellTab() {
+            super("BEANSHELL", GUIMediator.BEANSHELL_INDEX, "beanshell");
+            GUIMediator.setSplashScreenString(
+                GUIMediator.getStringResource("SPLASH_STATUS_BEANSHELL"));
+            console = new JConsole();
+            interpreter = new Interpreter(console);
+            NameCompletionTable nct = new NameCompletionTable();
+            nct.add(interpreter.getNameSpace());
+            try {
+                BshClassManager bcm = interpreter.getClassManager();
+                if (bcm != null)
+                    nct.add(((ClassManagerImpl)bcm).getClassPath());
+            } catch (ClassPathException ex) {}
+            console.setNameCompletion(nct);
+            SwingUtilities.invokeLater(new Runnable() {
+                public void run() {
+                    try {
+                        interpreter.source(CommonUtils.getUserSettingsDir() +
+                            "/LimeWire.bsh");
+                    } catch (FileNotFoundException ex) {
+                    } catch (Throwable ex) {
+                        console.print(ex, Color.RED);
+                    }
+                    new Thread(interpreter, "BeanShell").start();
+                }
+            });
+	}
+
+        public static BeanShellTab getInstance() {
+            if (instance == null)
+                instance = new BeanShellTab();
+            return instance;
+        }
+
+	public void storeState(boolean visible) {
+            ApplicationSettings.BEANSHELL_VIEW_ENABLED.setValue(visible);
+	}
+
+	public JComponent getComponent() {
+            return console;
+	}
+}
Index: lib/messagebundles/MessagesBundle.properties
===================================================================
RCS file: /cvs/lib/messagebundles/MessagesBundle.properties,v
retrieving revision 1.122
diff -u -r1.122 MessagesBundle.properties
--- lib/messagebundles/MessagesBundle.properties	21 Aug 2004 20:05:02 -0000	1.122
+++ lib/messagebundles/MessagesBundle.properties	25 Aug 2004 13:02:32 -0000
@@ -153,6 +153,7 @@
 STATS_TITLE=Statistics
 DOWNLOAD_TITLE=Downloads
 UPLOAD_TITLE=Uploads
+BEANSHELL_TITLE=BeanShell
 
 ################################################################################
 # Key/value pairs for the tooltips of the main windows
@@ -162,6 +163,7 @@
 CONNECTIONS_TIP=Connect to Other Clients
 LIBRARY_TIP=View Repository of Saved Files
 SHOPPING_TIP=Go Shopping at the LimeWire Marketplace
+BEANSHELL_TIP=BeanShell Console
 
 ################################################################################
 # Key/Value pairs for the pull-down menus in the main window
@@ -221,6 +223,9 @@
 MENU_NAV_SHOPPING=Shopping
 MENU_NAV_SHOPPING_MNEMONIC=P
 MENU_NAV_SHOPPING_ACCESSIBLE=Display the Shopping Website
+MENU_NAV_BEAN=BeanShell
+MENU_NAV_BEAN_MNEMONIC=B
+MENU_NAV_BEAN_ACCESSIBLE=Show BeanShell Console
 
 MENU_VIEW_TITLE=View
 MENU_VIEW_TITLE_MNEMONIC=V
@@ -245,6 +250,9 @@
 MENU_VIEW_SHOPPING=Shopping
 MENU_VIEW_SHOPPING_MNEMONIC=P
 MENU_VIEW_SHOPPING_ACCESSIBLE=Show Shopping Window
+MENU_VIEW_BEANSHELL=BeanShell
+MENU_VIEW_BEANSHELL_MNEMONIC=B
+MENU_VIEW_BEANSHELL_ACCESSIBLE=Show BeanShell Console
 MENU_VIEW_THEMES_TITLE=Apply Skins
 MENU_VIEW_THEMES_TITLE_MNEMONIC=A
 MENU_VIEW_THEMES_GET_MORE=Get more skins
@@ -855,6 +870,7 @@
 SPLASH_STATUS_PLAYLIST_WINDOW=Loading playlist window...
 SPLASH_STATUS_MENUS=Loading menus...
 SPLASH_STATUS_MESSAGE_SERVICE=Loading messages...
+SPLASH_STATUS_BEANSHELL=Loading BeanShell...
 SPLASH_STATUS_ICONS=Loading icons...
 SPLASH_STATUS_I18N=Loading internationalization support...
 SPLASH_STATUS_DAAP=Loading Digital Audio Access Protocol...
Index: lib/messagebundles/MessagesBundle_de.properties
===================================================================
RCS file: /cvs/lib/messagebundles/MessagesBundle_de.properties,v
retrieving revision 1.10
diff -u -r1.10 MessagesBundle_de.properties
--- lib/messagebundles/MessagesBundle_de.properties	23 Apr 2004 21:53:08 -0000	1.10
+++ lib/messagebundles/MessagesBundle_de.properties	25 Aug 2004 13:02:35 -0000
@@ -153,6 +153,7 @@
 STATS_TITLE=Statistik
 DOWNLOAD_TITLE=Downloads
 UPLOAD_TITLE=Uploads
+BEANSHELL_TITLE=BeanShell
 
 ################################################################################
 # Key/value pairs for the tooltips of the main windows
@@ -162,6 +163,7 @@
 CONNECTIONS_TIP=Verbindungen zu anderen Benutzern.
 LIBRARY_TIP=Zeigt alle lokalen Dateien an.
 SHOPPING_TIP=Erlaubt Ihnen Ihre Einkäufe auf dem LimeWire Marktplatz zu machen.
+BEANSHELL_TIP=BeanShell Console
 
 ################################################################################
 # Key/Value pairs for the pull-down menus in the main window
@@ -221,6 +223,9 @@
 MENU_NAV_SHOPPING=LimeShop
 MENU_NAV_SHOPPING_MNEMONIC=L
 MENU_NAV_SHOPPING_ACCESSIBLE=Geht zur LimeShop-Website.
+MENU_NAV_BEAN=BeanShell
+MENU_NAV_BEAN_MNEMONIC=B
+MENU_NAV_BEAN_ACCESSIBLE=Zeigt die BeanShell Console an.
 
 MENU_VIEW_TITLE=Ansicht
 MENU_VIEW_TITLE_MNEMONIC=A
@@ -239,6 +244,9 @@
 MENU_VIEW_SHOPPING=LimeShop
 MENU_VIEW_SHOPPING_MNEMONIC=L
 MENU_VIEW_SHOPPING_ACCESSIBLE=Schaltet die Seite LimeWire Shopping ein.
+MENU_VIEW_BEANSHELL=BeanShell
+MENU_VIEW_BEANSHELL_MNEMONIC=B
+MENU_VIEW_BEANSHELL_ACCESSIBLE=Schaltet die BeanShell Console ein.
 MENU_VIEW_THEMES_TITLE=Motive verwenden
 MENU_VIEW_THEMES_TITLE_MNEMONIC=M
 MENU_VIEW_THEMES_GET_MORE=Weitere Motive
@@ -785,6 +845,21 @@
 SPLASH_STATUS_STATUS_WINDOW=Statusfenster wird geladen...
 SPLASH_STATUS_MENUS=Menüs werden geladen...
 SPLASH_STATUS_MESSAGE_SERVICE=Meldungsdienst werden geladen...
+SPLASH_STATUS_BEANSHELL=BeanShell wird geladen...
+SPLASH_STATUS_ICONS=Ikonen werden geladen...
+SPLASH_STATUS_I18N=Unterstützung fuer Übersetzungen wird geladen...
+SPLASH_STATUS_COMPONENT_LOADING_ACCEPTOR=Connection Listener wird geladen...
+SPLASH_STATUS_COMPONENT_LOADING_MESSAGE_ROUTER=Message Router wird geladen...
+SPLASH_STATUS_COMPONENT_LOADING_CONNECTION_MANAGER=Verbindungsmanagement wird geladen...
+SPLASH_STATUS_COMPONENT_LOADING_HOST_CATCHER=Verbindungspartner werden gesucht...
+SPLASH_STATUS_COMPONENT_LOADING_FILE_MANAGER=Freigegebende Dateien werden geladen...
+SPLASH_STATUS_COMPONENT_LOADING_DOWNLOAD_MANAGER_POST_GUI=Alte Downloads werden geladen...
+SPLASH_STATUS_COMPONENT_LOADING_UPDATE_MANAGER=Prüfe auf Updates...
+SPLASH_STATUS_COMPONENT_LOADING_QUERY_UNICASTER=Direkte Suche wird geladen...
+SPLASH_STATUS_COMPONENT_LOADING_HTTPACCEPTOR=MAGNET Listener wird geladen...
+SPLASH_STATUS_COMPONENT_LOADING_PINGER=Peer Listener wird geladen...
+SPLASH_STATUS_COMPONENT_LOADING_CONNECTION_WATCHDOG=Management für ungültige Verbindungen wird geladen...
+SPLASH_STATUS_COMPONENT_LOADING_SAVED_FILE_MANAGER=Gesicherte Dateien werden geladen...
 
 ##################################################################
 # Key/value pairs for the message displayed to prompt users to
Index: core/com/limegroup/gnutella/settings/ApplicationSettings.java
===================================================================
RCS file: /cvs/core/com/limegroup/gnutella/settings/ApplicationSettings.java,v
retrieving revision 1.11
diff -u -r1.11 ApplicationSettings.java
--- core/com/limegroup/gnutella/settings/ApplicationSettings.java	31 Mar 2004 23:21:38 -0000	1.11
+++ core/com/limegroup/gnutella/settings/ApplicationSettings.java	25 Aug 2004 13:02:45 -0000
@@ -147,6 +147,12 @@
 	 */    
     public static final BooleanSetting SHOPPING_VIEW_ENABLED =
         FACTORY.createBooleanSetting("SHOPPING_VIEW_ENABLED", true);
+
+    /**
+	 * Sets whether or not BeanShell Tab should be enabled.
+	 */    
+    public static final BooleanSetting BEANSHELL_VIEW_ENABLED =
+        FACTORY.createBooleanSetting("BEANSHELL_VIEW_ENABLED", false);
     
     /**
 	 * Sets the name of the jar file to load on startup, which is read
Index: gui/jdk14.logging.properties
===================================================================
RCS file: /cvs/gui/jdk14.logging.properties,v
retrieving revision 1.21
diff -u -r1.21 jdk14.logging.properties
--- gui/jdk14.logging.properties	30 Apr 2004 18:05:35 -0000	1.21
+++ gui/jdk14.logging.properties	25 Aug 2004 13:02:46 -0000
@@ -1,7 +1,7 @@
 # Specify the handlers to create in the root logger
 # (all loggers are children of the root logger)
 # The following creates two handlers
-handlers=java.util.logging.ConsoleHandler
+handlers=java.util.logging.ConsoleHandler com.limegroup.gnutella.gui.BeanShellHandler
     
 ##### Valid logging levels are:
 # ALL, FINEST, FINE, CONFIG, INFO, WARNING, SEVERE, OFF
Index: gui/log4j.properties
===================================================================
RCS file: /cvs/gui/log4j.properties,v
retrieving revision 1.17
diff -u -r1.17 log4j.properties
--- gui/log4j.properties	10 Aug 2004 21:27:26 -0000	1.17
+++ gui/log4j.properties	25 Aug 2004 13:02:46 -0000
@@ -17,7 +17,7 @@
 ########
 
 # Set the root loggers
-log4j.rootLogger=OFF, stdout, TextFile, XMLFile,socket
+log4j.rootLogger=OFF, stdout, TextFile, XMLFile,socket, BeanShell
 
 
 ######
@@ -89,6 +89,12 @@
 log4j.appender.stdout.layout.ConversionPattern=%-6r %-5p [%t] %c{2}.%M - %m%n
 
 
+# An appender using the BeanShell console window.
+log4j.appender.BeanShell=org.apache.log4j.varia.NullAppender
+#log4j.appender.BeanShell=com.limegroup.gnutella.gui.BeanShellAppender
+#log4j.appender.BeanShell.layout=org.apache.log4j.PatternLayout
+#log4j.appender.BeanShell.layout.ConversionPattern=%-6r %-5p [%t] %c{2}.%M - %m%n
+
 ###  To set the value for specific classes/packages, use the following format:
 ## log4j.logger.<package.class>=LEVEL
 # log4j.logger.com.limegroup.gnutella.gui=INFO
Index: gui/com/limegroup/gnutella/gui/GUIMediator.java
===================================================================
RCS file: /cvs/gui/com/limegroup/gnutella/gui/GUIMediator.java,v
retrieving revision 1.146
diff -u -r1.146 GUIMediator.java
--- gui/com/limegroup/gnutella/gui/GUIMediator.java	23 Aug 2004 17:38:31 -0000	1.146
+++ gui/com/limegroup/gnutella/gui/GUIMediator.java	25 Aug 2004 13:02:47 -0000
@@ -91,10 +91,16 @@
 	public static final int LIBRARY_INDEX = 3;
 
 	/**
+	 * Constant for the index of the BeanShell tab in the main application
+	 * window.
+	 */
+	public static final int BEANSHELL_INDEX = 4;
+
+	/**
 	 * Constant for the index of the shopping tab in the main application
 	 * window.
 	 */
-	public static final int SHOPPING_INDEX = 4;
+	public static final int SHOPPING_INDEX = 5;
 
 	/**
 	 * Constant specifying whether or not the user has donated to the LimeWire
@@ -598,6 +604,9 @@
 			break;
 		case LIBRARY_INDEX:
 			MENU_MEDIATOR.handleLibrarySelection();
+			break;
+		case BEANSHELL_INDEX:
+			MENU_MEDIATOR.handleStandardSelection();
 			break;
 		case SHOPPING_INDEX:
 			SHOPPING_VIEW.prepareComponent();
Index: gui/com/limegroup/gnutella/gui/MainFrame.java
===================================================================
RCS file: /cvs/gui/com/limegroup/gnutella/gui/MainFrame.java,v
retrieving revision 1.221
diff -u -r1.221 MainFrame.java
--- gui/com/limegroup/gnutella/gui/MainFrame.java	17 Aug 2004 14:47:55 -0000	1.221
+++ gui/com/limegroup/gnutella/gui/MainFrame.java	25 Aug 2004 13:02:48 -0000
@@ -242,6 +242,8 @@
             this.setTabVisible(GUIMediator.CONNECTIONS_INDEX, false);
         if (!ApplicationSettings.LIBRARY_VIEW_ENABLED.getValue())
             this.setTabVisible(GUIMediator.LIBRARY_INDEX, false);
+        if (!ApplicationSettings.BEANSHELL_VIEW_ENABLED.getValue())
+            this.setTabVisible(GUIMediator.BEANSHELL_INDEX, false);
         if (!ApplicationSettings.SHOPPING_VIEW_ENABLED.getValue() &&
             GUIMediator.shouldShowShoppingTab())
             this.setTabVisible(GUIMediator.SHOPPING_INDEX, false);
@@ -301,18 +303,20 @@
     private void buildTabs() {
         // Setup the Tabs structure based on advertising mode and Windows
         if (GUIMediator.shouldShowShoppingTab()) {
-            TABS = new Tab[5];
+            TABS = new Tab[6];
             TABS[0]=new SearchDownloadTab(SEARCH_MEDIATOR, DOWNLOAD_MEDIATOR);
             TABS[1]=new MonitorUploadTab(MONITOR_VIEW, UPLOAD_MEDIATOR);
             TABS[2]=new ConnectionsTab(CONNECTION_MEDIATOR);
             TABS[3]=new LibraryPlayListTab(LIBRARY_MEDIATOR, PLAYLIST_MEDIATOR);
-            TABS[4]=new ShoppingBrowserTab(SHOPPING_VIEW);
+            TABS[4]=BeanShellTab.getInstance();
+            TABS[5]=new ShoppingBrowserTab(SHOPPING_VIEW);
         } else {
-            TABS = new Tab[4];
+            TABS = new Tab[5];
             TABS[0]=new SearchDownloadTab(SEARCH_MEDIATOR, DOWNLOAD_MEDIATOR);
             TABS[1]=new MonitorUploadTab(MONITOR_VIEW, UPLOAD_MEDIATOR);
             TABS[2]=new ConnectionsTab(CONNECTION_MEDIATOR);
             TABS[3]=new LibraryPlayListTab(LIBRARY_MEDIATOR, PLAYLIST_MEDIATOR);
+            TABS[4]=BeanShellTab.getInstance();
         }
     }
 
Index: gui/com/limegroup/gnutella/gui/menu/NavMenu.java
===================================================================
RCS file: /cvs/gui/com/limegroup/gnutella/gui/menu/NavMenu.java,v
retrieving revision 1.11
diff -u -r1.11 NavMenu.java
--- gui/com/limegroup/gnutella/gui/menu/NavMenu.java	13 Jan 2004 18:59:38 -0000	1.11
+++ gui/com/limegroup/gnutella/gui/menu/NavMenu.java	25 Aug 2004 13:02:49 -0000
@@ -50,6 +50,10 @@
 		item.putClientProperty(NAV_PROPERTY,
 		    new Integer(GUIMediator.LIBRARY_INDEX));
 
+		item = addMenuItem("NAV_BEAN", NAV_LISTENER);
+		item.putClientProperty(NAV_PROPERTY,
+		    new Integer(GUIMediator.BEANSHELL_INDEX));
+
 		// Conditionally add Shopping entry
 		if (!GUIMediator.hasDonated() && CommonUtils.isWindows()) {
 		    item = addMenuItem("NAV_SHOPPING", NAV_LISTENER);
Index: gui/com/limegroup/gnutella/gui/menu/ShowHideMenu.java
===================================================================
RCS file: /cvs/gui/com/limegroup/gnutella/gui/menu/ShowHideMenu.java,v
retrieving revision 1.6
diff -u -r1.6 ShowHideMenu.java
--- gui/com/limegroup/gnutella/gui/menu/ShowHideMenu.java	10 Aug 2004 21:27:26 -0000	1.6
+++ gui/com/limegroup/gnutella/gui/menu/ShowHideMenu.java	25 Aug 2004 13:02:49 -0000
@@ -36,6 +36,10 @@
                     new ViewListener(GUIMediator.LIBRARY_INDEX), 
                     ApplicationSettings.LIBRARY_VIEW_ENABLED.getValue());
                     
+        addToggleMenuItem("VIEW_BEANSHELL", 
+                    new ViewListener(GUIMediator.BEANSHELL_INDEX), 
+                    ApplicationSettings.BEANSHELL_VIEW_ENABLED.getValue());
+
         MENU.add(new SearchMenu("VIEW_SEARCH").getMenu());
 
 		// Conditionally add Shopping Entry
@@ -110,4 +114,4 @@
 			}
         }
     }
-}
\ No newline at end of file
+}
beanshell.gif (image/gif, 968 B) - not displayed
LimeWire.bsh (text/plain, 4.3 KB)
// Enable access to private fields and methods.
setAccessibility(true);

// Import most of the LimeWire name space for easy typing.
import com.limegroup.gnutella.gui.*;
import com.limegroup.gnutella.gui.menu.*;
import com.limegroup.gnutella.gui.download.*;
import com.limegroup.gnutella.gui.search.*;
import com.limegroup.gnutella.gui.tables.*;
import com.limegroup.gnutella.gui.tabs.*;
import com.limegroup.gnutella.*;
import com.limegroup.gnutella.settings.*;
import com.limegroup.gnutella.util.*;
import com.limegroup.gnutella.uploader.*;
import com.limegroup.gnutella.downloader.*;
import com.limegroup.gnutella.connection.*;

// Define a function for scripting searches, This will open a new search
// tab.
void addSearchTab(String stext, int repTime) {
    byte[] guid = RouterService.newQueryGUID();
    MediaType type = MediaType.getAnyTypeMediaType();
    SearchInformation info = SearchInformation.createKeywordSearch(stext, null, type);
    ResultPanel rp = SearchMediator.addResultTab(new GUID(guid), info);
    RouterService.query(guid, stext);
    if (repTime != 0)
        rp.setRepeatTime(repTime);
}

// Define a function that will try to resume all downloads that are
// pending.
boolean printResume = false;
void resumeAllDownloads() {
    DataLineModel dm = DownloadMediator.instance().DATA_MODEL;
    for (int i = 0; i < dm.getRowCount(); i++) {
        DataLine dd = dm.get(i);
        Downloader dloader =(Downloader)dd.getInitializeObject();
        if (dloader.resume() && printResume)
            print(dloader.getFileName()+ ":" + dloader.getState());
    }
}

// Define a function to clear all completed downloads. That differs from
// the inactive button as it will only clear 100% complete downloads.
void clearCompleted() {
    DataLineModel dm = DownloadMediator.instance().DATA_MODEL;
    boolean didOne;
    do {
        didOne = false;
        for (int i = 0; i < dm.getRowCount(); i++) {
            DownloadDataLine dd = (DownloadDataLine)dm.get(i);
            if (dd._state == Downloader.COMPLETE) {
                //print("Delete " + i + " " + dd);
                dm.remove(i);
                didOne = true;
                break;
            }
        }
    } while (didOne);
}

class ResumeTimer extends ManagedThread {
    ResumeTimer() {
        super("ResumeTimer");
    }
    public void managedRun() {
        for (;;) {
            try {
                Thread.sleep(10*60*1000);
                resumeAllDownloads();
            } catch (Throwable ex) {
                error(ex);
            }
        }
    }
}
new ResumeTimer().start();
print("ResumeTimer started");

// Wait until we have a connection before starting searches
class ConnWaiter extends ManagedThread {
    ConnWaiter() {
        super("ConnWaiter");
    }
    public void managedRun() {
        try {
            while (!RouterService.isConnected())
                Thread.sleep(1000);
            // add a search tab that autorepeats
            addSearchTab("LimeWire", 15);
        } catch (Throwable ex) {
            error(ex);
        }
    }
}
new ConnWaiter().start();
print("ConnWaiter started");

// Re-read the jdk1.4 logging properties
reReadLogProperties() {
    java.util.logging.LogManager.getLogManager().readConfiguration(
            new FileInputStream("jdk14.logging.properties"));
}

// Define a new menu named "BeanShell" for easy access to BeanShell
// functions.
bshMenu = new JMenu("BeanShell");

JMenuItem simpleMenu(name, func) {
    void actionPerformed(event) {
        try {
            eval(func);
        } catch (Throwable ex) {
            error(ex);
        }
    }
    item = new JMenuItem(name);
    item.addActionListener(this);
    return item;
}

bshMenu.add(simpleMenu("test doit", "print(\"doit\");print(event)"));
bshMenu.add(simpleMenu("open prefs", "GUIMediator.launchFile(CommonUtils.getUserSettingsDir())"));
bshMenu.add(simpleMenu("resume all downloads", "resumeAllDownloads()"));
bshMenu.add(simpleMenu("clear completed downloads", "clearCompleted()"));
bshMenu.add(simpleMenu("refresh log properties", "reReadLogProperties()"));
bshMenu.add(simpleMenu("shutdown", "GUIMediator.shutdown()"));

MenuMediator.instance().MENU_BAR.add(bshMenu);

// make the queue monitor a bit larger by default
GUIMediator.instance().getMainFrame().TABS[1].SPLIT_PANE.setDividerLocation(140);

print("LimeWire.bsh done " + new Date());