diff --git a/LICENSE.txt b/LICENSE.txt index 02b2862d89bdf6b27c75b7e188374cd03a92d753..f68af6e0cd2944d5936c64c66fcf600c99edfa6f 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -179,6 +179,10 @@ distributions. See the source package for the additional license information. Atalk: Public domain + Desktopgui + Copyright (c) Mathias De Maré + See apps/desktopgui/LICENSE + SAM C Library: Copyright (c) 2004, Matthew P. Cashdollar <mpc@innographx.com> See apps/sam/c/doc/license.txt diff --git a/apps/desktopgui/build.xml b/apps/desktopgui/build.xml index 77bd6d77858b1a4f548faf1a8efb6668561bd009..795edf046e2b8caa8ad8b1eb4b5ed500941af0f7 100644 --- a/apps/desktopgui/build.xml +++ b/apps/desktopgui/build.xml @@ -76,10 +76,12 @@ <property name="build_dist" location="dist"/> <property name="build_lib" location="lib"/> <property name="build_i2pref" location="../../build"/> + <property name="build_routerconsole" location="../routerconsole/java/build/"/> <path id="build_classpath"> <fileset dir="${build_lib}" includes="**/*.jar"/> <fileset dir="${build_i2pref}" includes="**/*.jar"/> + <fileset dir="${build_routerconsole}" includes="**/*.jar"/> </path> <target name="build_init"> <!-- Create the time stamp --> diff --git a/apps/desktopgui/nbproject/project.properties b/apps/desktopgui/nbproject/project.properties index e9f5d1a2a159f3695a72d31d03a2e8aeb743ce61..fb880932f7c35816c0be8da01b34a1c637b3d934 100644 --- a/apps/desktopgui/nbproject/project.properties +++ b/apps/desktopgui/nbproject/project.properties @@ -23,6 +23,7 @@ excludes= file.reference.appframework.jar=lib/appframework.jar file.reference.i2p.jar=../../core/java/build/i2p.jar file.reference.router.jar=../../router/java/build/router.jar +file.reference.routerconsole.jar=../routerconsole/java/build/routerconsole.jar file.reference.swing-worker.jar=lib/swing-worker.jar includes=** jar.compress=false @@ -30,7 +31,8 @@ javac.classpath=\ ${file.reference.router.jar}:\ ${file.reference.appframework.jar}:\ ${file.reference.swing-worker.jar}:\ - ${file.reference.i2p.jar} + ${file.reference.i2p.jar}:\ + ${file.reference.routerconsole.jar} # Space-separated list of extra javac options javac.compilerargs= javac.deprecation=false diff --git a/apps/desktopgui/src/net/i2p/desktopgui/desktopgui/GUIVersion.java b/apps/desktopgui/src/net/i2p/desktopgui/desktopgui/GUIVersion.java index f4e948e52c05df8d2c848d9cb5221d77609120c7..10a6e52939a5c12359f00d3fa7970ea1f9d420d4 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/desktopgui/GUIVersion.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/desktopgui/GUIVersion.java @@ -10,5 +10,5 @@ package net.i2p.desktopgui.desktopgui; * @author mathias */ public class GUIVersion { - public static final String VERSION = "0.0.1.2"; + public static final String VERSION = "0.0.1.3"; } diff --git a/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.form b/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.form index 7c0fc8edcdf41c794e426e3b8937ded3d2782e88..4c7cb5afcefb7fed23f6ae7c8793fcfef61924a4 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.form +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.form @@ -2,7 +2,7 @@ <Form version="1.5" maxVersion="1.6" type="org.netbeans.modules.form.forminfo.JFrameFormInfo"> <NonVisualComponents> - <Component class="javax.swing.ButtonGroup" name="buttonGroup1"> + <Component class="javax.swing.ButtonGroup" name="updateButtonGroup"> </Component> </NonVisualComponents> <Properties> @@ -81,12 +81,18 @@ <Property name="text" type="java.lang.String" resourceKey="cancel.text"/> <Property name="name" type="java.lang.String" value="cancel" noResource="true"/> </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="cancelMouseClicked"/> + </Events> </Component> <Component class="javax.swing.JToggleButton" name="ok"> <Properties> <Property name="text" type="java.lang.String" resourceKey="ok.text"/> <Property name="name" type="java.lang.String" value="ok" noResource="true"/> </Properties> + <Events> + <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="okMouseClicked"/> + </Events> </Component> </SubComponents> </Container> @@ -141,7 +147,7 @@ <Property name="name" type="java.lang.String" value="uploadspeed" noResource="true"/> </Properties> <Events> - <EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="speedKeyTyped"/> + <EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="speedKeyReleased"/> </Events> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> @@ -155,7 +161,7 @@ <Property name="name" type="java.lang.String" value="downloadspeed" noResource="true"/> </Properties> <Events> - <EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="speedKeyTyped"/> + <EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="speedKeyReleased"/> </Events> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> @@ -201,10 +207,10 @@ </Constraint> </Constraints> </Component> - <Component class="javax.swing.JLabel" name="jLabel3"> + <Component class="javax.swing.JLabel" name="uploadUsageLabel"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jLabel3.text"/> - <Property name="name" type="java.lang.String" value="jLabel3" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="uploadUsageLabel.text"/> + <Property name="name" type="java.lang.String" value="uploadUsageLabel" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> @@ -212,10 +218,10 @@ </Constraint> </Constraints> </Component> - <Component class="javax.swing.JLabel" name="jLabel4"> + <Component class="javax.swing.JLabel" name="downloadUsageLabel"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jLabel4.text"/> - <Property name="name" type="java.lang.String" value="jLabel4" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="downloadUsageLabel.text"/> + <Property name="name" type="java.lang.String" value="downloadUsageLabel" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> @@ -229,7 +235,7 @@ <Property name="name" type="java.lang.String" value="uploadgb" noResource="true"/> </Properties> <Events> - <EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="uploadgbKeyTyped"/> + <EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="monthKeyReleased"/> </Events> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> @@ -243,7 +249,7 @@ <Property name="name" type="java.lang.String" value="downloadgb" noResource="true"/> </Properties> <Events> - <EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="downloadgbKeyTyped"/> + <EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="monthKeyReleased"/> </Events> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> @@ -251,10 +257,10 @@ </Constraint> </Constraints> </Component> - <Component class="javax.swing.JLabel" name="jLabel5"> + <Component class="javax.swing.JLabel" name="gbUploadLabel"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jLabel5.text"/> - <Property name="name" type="java.lang.String" value="jLabel5" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="gbUploadLabel.text"/> + <Property name="name" type="java.lang.String" value="gbUploadLabel" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> @@ -262,10 +268,10 @@ </Constraint> </Constraints> </Component> - <Component class="javax.swing.JLabel" name="jLabel6"> + <Component class="javax.swing.JLabel" name="gbDownloadLabel"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jLabel6.text"/> - <Property name="name" type="java.lang.String" value="jLabel6" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="gbDownloadLabel.text"/> + <Property name="name" type="java.lang.String" value="gbDownloadLabel" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> @@ -273,10 +279,10 @@ </Constraint> </Constraints> </Component> - <Component class="javax.swing.JLabel" name="jLabel7"> + <Component class="javax.swing.JLabel" name="uploadDownloadExplanation"> <Properties> - <Property name="text" type="java.lang.String" resourceKey="jLabel7.text"/> - <Property name="name" type="java.lang.String" value="jLabel7" noResource="true"/> + <Property name="text" type="java.lang.String" resourceKey="uploadDownloadExplanation.text"/> + <Property name="name" type="java.lang.String" value="uploadDownloadExplanation" noResource="true"/> </Properties> <Constraints> <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription"> @@ -365,7 +371,7 @@ <Component class="javax.swing.JRadioButton" name="updateInform"> <Properties> <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor"> - <ComponentRef name="buttonGroup1"/> + <ComponentRef name="updateButtonGroup"/> </Property> <Property name="text" type="java.lang.String" resourceKey="updateInform.text"/> <Property name="name" type="java.lang.String" value="updateInform" noResource="true"/> @@ -374,7 +380,7 @@ <Component class="javax.swing.JRadioButton" name="updateDownload"> <Properties> <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor"> - <ComponentRef name="buttonGroup1"/> + <ComponentRef name="updateButtonGroup"/> </Property> <Property name="text" type="java.lang.String" resourceKey="updateDownload.text"/> <Property name="name" type="java.lang.String" value="updateDownload" noResource="true"/> @@ -383,7 +389,7 @@ <Component class="javax.swing.JRadioButton" name="updateDownloadRestart"> <Properties> <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor"> - <ComponentRef name="buttonGroup1"/> + <ComponentRef name="updateButtonGroup"/> </Property> <Property name="text" type="java.lang.String" resourceKey="updateDownloadRestart.text"/> <Property name="name" type="java.lang.String" value="updateDownloadRestart" noResource="true"/> @@ -394,18 +400,27 @@ <Property name="text" type="java.lang.String" resourceKey="checkUpdates.text"/> <Property name="name" type="java.lang.String" value="checkUpdates" noResource="true"/> </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="checkUpdatesActionPerformed"/> + </Events> </Component> <Component class="javax.swing.JToggleButton" name="updateNow"> <Properties> <Property name="text" type="java.lang.String" resourceKey="updateNow.text"/> <Property name="name" type="java.lang.String" value="updateNow" noResource="true"/> </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="updateNowActionPerformed"/> + </Events> </Component> <Component class="javax.swing.JToggleButton" name="advancedUpdateConfig"> <Properties> <Property name="text" type="java.lang.String" resourceKey="advancedUpdateConfig.text"/> <Property name="name" type="java.lang.String" value="advancedUpdateConfig" noResource="true"/> </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="advancedUpdateConfigActionPerformed"/> + </Events> </Component> </SubComponents> </Container> diff --git a/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.java index 910ca21fb5eeee8fec14984eaa501704f7c2f9e6..474e3947319287ee9928aae312ce407f0417a7fe 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/GeneralConfiguration.java @@ -6,7 +6,23 @@ package net.i2p.desktopgui.gui; +import java.awt.Desktop; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.logging.Level; +import java.util.logging.Logger; import net.i2p.desktopgui.router.configuration.SpeedHelper; +import javax.swing.JComboBox; +import javax.swing.ButtonModel; +import javax.swing.JTextField; +import net.i2p.desktopgui.router.RouterHelper; +import net.i2p.desktopgui.router.configuration.SpeedHandler; +import net.i2p.desktopgui.router.configuration.UpdateHelper; +import net.i2p.router.web.NewsFetcher; +import net.i2p.desktopgui.router.configuration.UpdateHandler; +import java.util.Date; +import javax.swing.SwingWorker; /** * @@ -19,11 +35,56 @@ public class GeneralConfiguration extends javax.swing.JFrame { initComponents(); extraInitComponents(); this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); + this.setLocationRelativeTo(null); + this.requestFocus(); this.setVisible(true); } private void extraInitComponents() { - downloadspeed.setText(SpeedHelper.getInboundBandwidth()); + initSpeedTab(); + initUpdateTab(); + } + + private void initSpeedTab() { + try { + String inbound = SpeedHelper.getInboundBandwidth(); + String outbound = SpeedHelper.getOutboundBandwidth(); + + initSpeeds("" + Integer.parseInt(inbound)*8, "" + Integer.parseInt(outbound)*8); + initUsage("" + Integer.parseInt(inbound), "" + Integer.parseInt(outbound)); + } + catch(Exception e) { + e.printStackTrace(); + System.out.println("Exception noticed, probably running desktopgui in a debugger instead of along with I2P!?"); + initSpeeds("100", "100"); + initUsage("12", "12"); + } + } + + private void initUpdateTab() { + //Set update policy + String updatePolicy = UpdateHelper.getUpdatePolicy(); + if(updatePolicy.equals(UpdateHelper.NOTIFY_UPDATE_POLICY)) { + updateButtonGroup.setSelected(updateInform.getModel(), true); + } + else if(updatePolicy.equals(UpdateHelper.DOWNLOAD_UPDATE_POLICY)) { + updateButtonGroup.setSelected(updateDownload.getModel(), true); + } + else if(updatePolicy.equals(UpdateHelper.INSTALL_UPDATE_POLICY)) { + updateButtonGroup.setSelected(updateDownloadRestart.getModel(), true); + } + else { + System.out.println("desktopgui: no updates for you!"); + } + + //Check if an update is available + //TODO: move this method out of the routerconsole so desktopgui doesn't depend on routerconsole!!! + if(NewsFetcher.getInstance(RouterHelper.getContext()).updateAvailable()) { + updateNow.setVisible(true); + } + else { + updateNow.setVisible(false); + } } /** This method is called from within the constructor to @@ -35,7 +96,7 @@ public class GeneralConfiguration extends javax.swing.JFrame { // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { - buttonGroup1 = new javax.swing.ButtonGroup(); + updateButtonGroup = new javax.swing.ButtonGroup(); applyPanel = new javax.swing.JPanel(); cancel = new javax.swing.JToggleButton(); ok = new javax.swing.JToggleButton(); @@ -47,13 +108,13 @@ public class GeneralConfiguration extends javax.swing.JFrame { downloadspeed = new javax.swing.JTextField(); uploadkbps = new javax.swing.JComboBox(); downloadkbps = new javax.swing.JComboBox(); - jLabel3 = new javax.swing.JLabel(); - jLabel4 = new javax.swing.JLabel(); + uploadUsageLabel = new javax.swing.JLabel(); + downloadUsageLabel = new javax.swing.JLabel(); uploadgb = new javax.swing.JTextField(); downloadgb = new javax.swing.JTextField(); - jLabel5 = new javax.swing.JLabel(); - jLabel6 = new javax.swing.JLabel(); - jLabel7 = new javax.swing.JLabel(); + gbUploadLabel = new javax.swing.JLabel(); + gbDownloadLabel = new javax.swing.JLabel(); + uploadDownloadExplanation = new javax.swing.JLabel(); updatesPanel = new javax.swing.JPanel(); updateMethod = new javax.swing.JLabel(); updateInform = new javax.swing.JRadioButton(); @@ -80,9 +141,19 @@ public class GeneralConfiguration extends javax.swing.JFrame { cancel.setText(resourceMap.getString("cancel.text")); // NOI18N cancel.setName("cancel"); // NOI18N + cancel.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + cancelMouseClicked(evt); + } + }); ok.setText(resourceMap.getString("ok.text")); // NOI18N ok.setName("ok"); // NOI18N + ok.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent evt) { + okMouseClicked(evt); + } + }); javax.swing.GroupLayout applyPanelLayout = new javax.swing.GroupLayout(applyPanel); applyPanel.setLayout(applyPanelLayout); @@ -122,8 +193,8 @@ public class GeneralConfiguration extends javax.swing.JFrame { uploadspeed.setText(resourceMap.getString("uploadspeed.text")); // NOI18N uploadspeed.setName("uploadspeed"); // NOI18N uploadspeed.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyTyped(java.awt.event.KeyEvent evt) { - speedKeyTyped(evt); + public void keyReleased(java.awt.event.KeyEvent evt) { + speedKeyReleased(evt); } }); speedPanel.add(uploadspeed); @@ -132,8 +203,8 @@ public class GeneralConfiguration extends javax.swing.JFrame { downloadspeed.setText(resourceMap.getString("downloadspeed.text")); // NOI18N downloadspeed.setName("downloadspeed"); // NOI18N downloadspeed.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyTyped(java.awt.event.KeyEvent evt) { - speedKeyTyped(evt); + public void keyReleased(java.awt.event.KeyEvent evt) { + speedKeyReleased(evt); } }); speedPanel.add(downloadspeed); @@ -159,21 +230,21 @@ public class GeneralConfiguration extends javax.swing.JFrame { speedPanel.add(downloadkbps); downloadkbps.setBounds(240, 60, 68, 27); - jLabel3.setText(resourceMap.getString("jLabel3.text")); // NOI18N - jLabel3.setName("jLabel3"); // NOI18N - speedPanel.add(jLabel3); - jLabel3.setBounds(330, 20, 97, 30); + uploadUsageLabel.setText(resourceMap.getString("uploadUsageLabel.text")); // NOI18N + uploadUsageLabel.setName("uploadUsageLabel"); // NOI18N + speedPanel.add(uploadUsageLabel); + uploadUsageLabel.setBounds(330, 20, 97, 30); - jLabel4.setText(resourceMap.getString("jLabel4.text")); // NOI18N - jLabel4.setName("jLabel4"); // NOI18N - speedPanel.add(jLabel4); - jLabel4.setBounds(330, 60, 97, 30); + downloadUsageLabel.setText(resourceMap.getString("downloadUsageLabel.text")); // NOI18N + downloadUsageLabel.setName("downloadUsageLabel"); // NOI18N + speedPanel.add(downloadUsageLabel); + downloadUsageLabel.setBounds(330, 60, 97, 30); uploadgb.setText(resourceMap.getString("uploadgb.text")); // NOI18N uploadgb.setName("uploadgb"); // NOI18N uploadgb.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyTyped(java.awt.event.KeyEvent evt) { - uploadgbKeyTyped(evt); + public void keyReleased(java.awt.event.KeyEvent evt) { + monthKeyReleased(evt); } }); speedPanel.add(uploadgb); @@ -182,27 +253,27 @@ public class GeneralConfiguration extends javax.swing.JFrame { downloadgb.setText(resourceMap.getString("downloadgb.text")); // NOI18N downloadgb.setName("downloadgb"); // NOI18N downloadgb.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyTyped(java.awt.event.KeyEvent evt) { - downloadgbKeyTyped(evt); + public void keyReleased(java.awt.event.KeyEvent evt) { + monthKeyReleased(evt); } }); speedPanel.add(downloadgb); downloadgb.setBounds(440, 60, 60, 27); - jLabel5.setText(resourceMap.getString("jLabel5.text")); // NOI18N - jLabel5.setName("jLabel5"); // NOI18N - speedPanel.add(jLabel5); - jLabel5.setBounds(510, 20, 19, 30); + gbUploadLabel.setText(resourceMap.getString("gbUploadLabel.text")); // NOI18N + gbUploadLabel.setName("gbUploadLabel"); // NOI18N + speedPanel.add(gbUploadLabel); + gbUploadLabel.setBounds(510, 20, 19, 30); - jLabel6.setText(resourceMap.getString("jLabel6.text")); // NOI18N - jLabel6.setName("jLabel6"); // NOI18N - speedPanel.add(jLabel6); - jLabel6.setBounds(510, 60, 19, 30); + gbDownloadLabel.setText(resourceMap.getString("gbDownloadLabel.text")); // NOI18N + gbDownloadLabel.setName("gbDownloadLabel"); // NOI18N + speedPanel.add(gbDownloadLabel); + gbDownloadLabel.setBounds(510, 60, 19, 30); - jLabel7.setText(resourceMap.getString("jLabel7.text")); // NOI18N - jLabel7.setName("jLabel7"); // NOI18N - speedPanel.add(jLabel7); - jLabel7.setBounds(20, 100, 520, 70); + uploadDownloadExplanation.setText(resourceMap.getString("uploadDownloadExplanation.text")); // NOI18N + uploadDownloadExplanation.setName("uploadDownloadExplanation"); // NOI18N + speedPanel.add(uploadDownloadExplanation); + uploadDownloadExplanation.setBounds(20, 100, 520, 70); settingsPanel.addTab(resourceMap.getString("speedPanel.TabConstraints.tabTitle"), speedPanel); // NOI18N @@ -211,26 +282,41 @@ public class GeneralConfiguration extends javax.swing.JFrame { updateMethod.setText(resourceMap.getString("updateMethod.text")); // NOI18N updateMethod.setName("updateMethod"); // NOI18N - buttonGroup1.add(updateInform); + updateButtonGroup.add(updateInform); updateInform.setText(resourceMap.getString("updateInform.text")); // NOI18N updateInform.setName("updateInform"); // NOI18N - buttonGroup1.add(updateDownload); + updateButtonGroup.add(updateDownload); updateDownload.setText(resourceMap.getString("updateDownload.text")); // NOI18N updateDownload.setName("updateDownload"); // NOI18N - buttonGroup1.add(updateDownloadRestart); + updateButtonGroup.add(updateDownloadRestart); updateDownloadRestart.setText(resourceMap.getString("updateDownloadRestart.text")); // NOI18N updateDownloadRestart.setName("updateDownloadRestart"); // NOI18N checkUpdates.setText(resourceMap.getString("checkUpdates.text")); // NOI18N checkUpdates.setName("checkUpdates"); // NOI18N + checkUpdates.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkUpdatesActionPerformed(evt); + } + }); updateNow.setText(resourceMap.getString("updateNow.text")); // NOI18N updateNow.setName("updateNow"); // NOI18N + updateNow.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + updateNowActionPerformed(evt); + } + }); advancedUpdateConfig.setText(resourceMap.getString("advancedUpdateConfig.text")); // NOI18N advancedUpdateConfig.setName("advancedUpdateConfig"); // NOI18N + advancedUpdateConfig.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + advancedUpdateConfigActionPerformed(evt); + } + }); javax.swing.GroupLayout updatesPanelLayout = new javax.swing.GroupLayout(updatesPanel); updatesPanel.setLayout(updatesPanelLayout); @@ -377,7 +463,7 @@ public class GeneralConfiguration extends javax.swing.JFrame { pack(); }// </editor-fold>//GEN-END:initComponents -private void speedKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_speedKeyTyped + private void speedKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_speedKeyReleased try { String upload = ""; if(uploadkbps.getSelectedIndex() == KILOBIT) @@ -395,47 +481,179 @@ private void speedKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_speed e.printStackTrace(); return; } -}//GEN-LAST:event_speedKeyTyped +}//GEN-LAST:event_speedKeyReleased private void uploadkbpsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_uploadkbpsActionPerformed - // TODO add your handling code here: + kbpsSwitchPerformed(uploadkbps, uploadspeed); }//GEN-LAST:event_uploadkbpsActionPerformed private void downloadkbpsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_downloadkbpsActionPerformed - // TODO add your handling code here: + kbpsSwitchPerformed(downloadkbps, downloadspeed); }//GEN-LAST:event_downloadkbpsActionPerformed -private void uploadgbKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_uploadgbKeyTyped - // TODO add your handling code here: -}//GEN-LAST:event_uploadgbKeyTyped +private void monthKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_monthKeyReleased + try { + int uploadMonthValue = Integer.parseInt(uploadgb.getText()); + int downloadMonthValue = Integer.parseInt(downloadgb.getText()); + + String upload = ""; + String burstUpload = ""; + String download = ""; + String burstDownload = ""; + + if(uploadkbps.getSelectedIndex() == KILOBIT) + upload = "" + SpeedHelper.calculateSpeed(uploadMonthValue)*8; //kbit + else + upload = "" + SpeedHelper.calculateSpeed(uploadMonthValue); //kbyte + + if(downloadkbps.getSelectedIndex() == KILOBIT) + download = "" + SpeedHelper.calculateSpeed(downloadMonthValue)*8; //kbit + else + download = "" + SpeedHelper.calculateSpeed(downloadMonthValue); //kbyte + + initSpeeds(upload, download); + } + catch(NumberFormatException e) { + e.printStackTrace(); + return; + } +}//GEN-LAST:event_monthKeyReleased + +private void cancelMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_cancelMouseClicked + this.dispose(); +}//GEN-LAST:event_cancelMouseClicked + +private void okMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_okMouseClicked + saveSpeeds(); + saveUpdatePolicy(); + this.dispose(); +}//GEN-LAST:event_okMouseClicked -private void downloadgbKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_downloadgbKeyTyped - // TODO add your handling code here: -}//GEN-LAST:event_downloadgbKeyTyped +private void checkUpdatesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkUpdatesActionPerformed + long current = new Date().getTime(); + if(current < newsLastFetched + 5*60*1000) { + return; + } + checkUpdates.setText("Checking for updates"); + checkUpdates.setEnabled(false); + newsLastFetched = current; + SwingWorker sw = new SwingWorker() { + + @Override + protected Object doInBackground() throws Exception { + NewsFetcher.getInstance(RouterHelper.getContext()).fetchNews(); + return null; + } + + @Override + protected void done() { + checkUpdates.setText("Check for updates now"); + checkUpdates.setEnabled(true); + if(NewsFetcher.getInstance(RouterHelper.getContext()).updateAvailable()) { + updateNow.setVisible(true); + } + } + + }; +}//GEN-LAST:event_checkUpdatesActionPerformed + +private void updateNowActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateNowActionPerformed + SwingWorker sw = new SwingWorker() { + + @Override + protected Object doInBackground() throws Exception { + new net.i2p.router.web.UpdateHandler().update(); + return null; + } + + }; + updateNow.setEnabled(false); + updateNow.setText("Updating..."); + checkUpdates.setEnabled(false); + +}//GEN-LAST:event_updateNowActionPerformed + +private void advancedUpdateConfigActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_advancedUpdateConfigActionPerformed + try { + Desktop.getDesktop().browse(new URI("http://127.0.0.1:7657/configupdate.jsp")); + } catch (URISyntaxException ex) { + Logger.getLogger(GeneralConfiguration.class.getName()).log(Level.SEVERE, null, ex); + } + catch (IOException ex) { + Logger.getLogger(GeneralConfiguration.class.getName()).log(Level.SEVERE, null, ex); + } +}//GEN-LAST:event_advancedUpdateConfigActionPerformed protected void initUsage(String upload, String download) { uploadgb.setText("" + SpeedHelper.calculateMonthlyUsage(Integer.parseInt(upload))); downloadgb.setText("" + SpeedHelper.calculateMonthlyUsage(Integer.parseInt(download))); } + protected void initSpeeds(String upload, String download) { + uploadspeed.setText(upload); + downloadspeed.setText(download); + } + + private void kbpsSwitchPerformed(JComboBox kbps, JTextField speed) { + int index = kbps.getSelectedIndex(); + int previous = Integer.parseInt(speed.getText()); + if(index == KILOBIT) { + speed.setText("" + previous*8); + } + else { + speed.setText("" + previous/8); + } + } + + protected void saveSpeeds() { + int maxDownload = Integer.parseInt(downloadspeed.getText()); + int maxUpload = Integer.parseInt(uploadspeed.getText()); + if(uploadkbps.getSelectedIndex() == KILOBIT) { + SpeedHandler.setOutboundBandwidth(maxUpload/8); + SpeedHandler.setOutboundBurstBandwidth(maxUpload/8); + } + else { + SpeedHandler.setOutboundBandwidth(maxUpload); + SpeedHandler.setOutboundBurstBandwidth(maxUpload); + } + if(downloadkbps.getSelectedIndex() == KILOBIT) { + SpeedHandler.setInboundBandwidth(maxDownload/8); + SpeedHandler.setInboundBurstBandwidth(maxDownload/8); + } + else { + SpeedHandler.setInboundBandwidth(maxDownload); + SpeedHandler.setInboundBurstBandwidth(maxDownload); + } + } + + protected void saveUpdatePolicy() { + ButtonModel policyButton = updateButtonGroup.getSelection(); + if(policyButton.equals(updateInform.getModel())) { + UpdateHandler.setUpdatePolicy(UpdateHelper.NOTIFY_UPDATE_POLICY); + } + else if(policyButton.equals(updateDownload.getModel())) { + UpdateHandler.setUpdatePolicy(UpdateHelper.DOWNLOAD_UPDATE_POLICY); + } + else if(policyButton.equals(updateDownloadRestart.getModel())) { + UpdateHandler.setUpdatePolicy(UpdateHelper.INSTALL_UPDATE_POLICY); + } + } + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JPanel advancedPanel; private javax.swing.JToggleButton advancedUpdateConfig; private javax.swing.JPanel applyPanel; - private javax.swing.ButtonGroup buttonGroup1; private javax.swing.JToggleButton cancel; private javax.swing.JToggleButton checkUpdates; private javax.swing.JScrollPane clientFrame; private javax.swing.JLabel clientTunnelLabel; private javax.swing.JLabel downloadSpeedLabel; + private javax.swing.JLabel downloadUsageLabel; private javax.swing.JTextField downloadgb; private javax.swing.JComboBox downloadkbps; private javax.swing.JTextField downloadspeed; - private javax.swing.JLabel jLabel3; - private javax.swing.JLabel jLabel4; - private javax.swing.JLabel jLabel5; - private javax.swing.JLabel jLabel6; - private javax.swing.JLabel jLabel7; + private javax.swing.JLabel gbDownloadLabel; + private javax.swing.JLabel gbUploadLabel; private javax.swing.JPanel networkPanel; private javax.swing.JToggleButton ok; private javax.swing.JScrollPane serverFrame; @@ -444,13 +662,16 @@ private void downloadgbKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_ private javax.swing.JPanel speedPanel; private javax.swing.JPanel tunnelPanel; private javax.swing.JLabel tunnelsExplanation; + private javax.swing.ButtonGroup updateButtonGroup; private javax.swing.JRadioButton updateDownload; private javax.swing.JRadioButton updateDownloadRestart; private javax.swing.JRadioButton updateInform; private javax.swing.JLabel updateMethod; private javax.swing.JToggleButton updateNow; private javax.swing.JPanel updatesPanel; + private javax.swing.JLabel uploadDownloadExplanation; private javax.swing.JLabel uploadSpeedLabel; + private javax.swing.JLabel uploadUsageLabel; private javax.swing.JTextField uploadgb; private javax.swing.JComboBox uploadkbps; private javax.swing.JTextField uploadspeed; @@ -458,4 +679,6 @@ private void downloadgbKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_ public static final int KILOBIT = 0; public static final int KILOBYTE = 1; + + private long newsLastFetched = 0; } diff --git a/apps/desktopgui/src/net/i2p/desktopgui/gui/Tray.java b/apps/desktopgui/src/net/i2p/desktopgui/gui/Tray.java index b20a850f6d744075da74d2e9cd51ae82deb37799..02fb5b2df8449d070e81defaaff0f864e66760d3 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/gui/Tray.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/Tray.java @@ -151,7 +151,7 @@ public class Tray { public void actionPerformed(ActionEvent arg0) { RouterHandler.setStatus(RouterHandler.SHUTDOWN_GRACEFULLY); long shutdownTime = RouterHelper.getGracefulShutdownTimeRemaining(); - System.out.println(shutdownTime); + System.out.println("Shutdowntime remaining: " + shutdownTime); if(shutdownTime>0) { trayIcon.displayMessage("Shutting down...", "Shutdown time remaining: " + shutdownTime/1000 + " seconds." + System.getProperty("line.separator") + "Shutdown will not happen immediately, because we are still participating in the network.", TrayIcon.MessageType.INFO); @@ -170,7 +170,7 @@ public class Tray { popup.addSeparator(); config.add(speedConfig); - //config.add(generalConfig); + config.add(generalConfig); config.add(advancedConfig); popup.add(config); diff --git a/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/GeneralConfiguration.properties b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/GeneralConfiguration.properties index e1c16a08cb12f393dacb7b3190ecbe899c11a529..c6af27a514ed4a9d4a63df413f77efc3fd94fd50 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/GeneralConfiguration.properties +++ b/apps/desktopgui/src/net/i2p/desktopgui/gui/resources/GeneralConfiguration.properties @@ -1,10 +1,5 @@ cancel.text=Cancel ok.text=OK -jLabel3.text=Monthly usage: -jLabel4.text=Monthly usage: -jLabel5.text=GB -jLabel6.text=GB -jLabel7.text=Explanation ... Form.title=General Configuration speedPanel.TabConstraints.tabTitle=Speed updatesPanel.TabConstraints.tabTitle=Updates @@ -27,3 +22,8 @@ advancedUpdateConfig.text=Advanced update configuration clientTunnelLabel.text=Client tunnels: serverTunnelLabel.text=Server tunnels: tunnelsExplanation.text=Tunnel explanation +uploadUsageLabel.text=Monthly usage: +downloadUsageLabel.text=Monthly usage: +gbUploadLabel.text=GB +gbDownloadLabel.text=GB +uploadDownloadExplanation.text=Explanation ... diff --git a/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/SpeedHelper.java b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/SpeedHelper.java index 5d2074de2c76b3ce893caee53947a32646787d84..51b8b5a6f6e45455a7c8d8f2c22cb2148208eda1 100644 --- a/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/SpeedHelper.java +++ b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/SpeedHelper.java @@ -36,4 +36,8 @@ public class SpeedHelper { public static String getInboundBandwidth() { return RouterHelper.getContext().router().getConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH); } + + public static String getOutboundBandwidth() { + return RouterHelper.getContext().router().getConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH); + } } diff --git a/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/UpdateHandler.java b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/UpdateHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..e913f5e518a82420a4b3dc8e43ea5a748733a364 --- /dev/null +++ b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/UpdateHandler.java @@ -0,0 +1,19 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package net.i2p.desktopgui.router.configuration; + +import net.i2p.desktopgui.router.RouterHelper; + +/** + * + * @author mathias + */ +public class UpdateHandler { + public static void setUpdatePolicy(String policy) { + RouterHelper.getContext().router().setConfigSetting(UpdateHelper.PROP_UPDATE_POLICY, policy); + RouterHelper.getContext().router().saveConfig(); + } +} diff --git a/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/UpdateHelper.java b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/UpdateHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..86db6f7080010e6982bbb95ad93cf7badd84f3ba --- /dev/null +++ b/apps/desktopgui/src/net/i2p/desktopgui/router/configuration/UpdateHelper.java @@ -0,0 +1,66 @@ +package net.i2p.desktopgui.router.configuration; + +import net.i2p.desktopgui.router.RouterHelper; + +/** + * + * @author mathias + */ +public class UpdateHelper { + + public static final String PROP_NEWS_URL = "router.newsURL"; + public static final String DEFAULT_NEWS_URL = "http://complication.i2p/news.xml"; + + public static final String PROP_REFRESH_FREQUENCY = "router.newsRefreshFrequency"; + public static final String DEFAULT_REFRESH_FREQUENCY = 24*60*60*1000 + ""; + + public static final String PROP_UPDATE_POLICY = "router.updatePolicy"; + public static final String NOTIFY_UPDATE_POLICY = "notify"; + public static final String DOWNLOAD_UPDATE_POLICY = "download"; + public static final String INSTALL_UPDATE_POLICY = "install"; + public static final String DEFAULT_UPDATE_POLICY = DOWNLOAD_UPDATE_POLICY; + + public static final String PROP_SHOULD_PROXY = "router.updateThroughProxy"; + public static final String DEFAULT_SHOULD_PROXY = Boolean.TRUE.toString(); + public static final String PROP_PROXY_HOST = "router.updateProxyHost"; + public static final String DEFAULT_PROXY_HOST = "127.0.0.1"; + public static final String PROP_PROXY_PORT = "router.updateProxyPort"; + public static final String DEFAULT_PROXY_PORT = "4444"; + + public static final String PROP_UPDATE_URL = "router.updateURL"; + public static final String DEFAULT_UPDATE_URL = + "http://echelon.i2p/i2p/i2pupdate.sud\r\n" + + "http://stats.i2p/i2p/i2pupdate.sud\r\n" + + "http://complication.i2p/i2p/i2pupdate.sud\r\n" + + "http://www.i2p2.i2p/_static/i2pupdate.sud\r\n" + + "http://update.postman.i2p/i2pupdate.sud" ; + + public static final String PROP_TRUSTED_KEYS = "router.trustedUpdateKeys"; + + public static String getNewsURL() { + String url = RouterHelper.getContext().getProperty(PROP_NEWS_URL); + if(url == null) { + return DEFAULT_NEWS_URL; + } + else { + return url; + } + } + + public static String getUpdatePolicy() { + String policy = null; + try { + policy = RouterHelper.getContext().getProperty(PROP_UPDATE_POLICY); + } + catch(Exception e) { + e.printStackTrace(); + } + System.out.println("Policy: " + policy); + if(policy == null) { + return DEFAULT_UPDATE_POLICY; + } + else { + return policy; + } + } +} diff --git a/build.xml b/build.xml index cd1b6c5b9116541452a1d368c059b1431b9297ef..f7a7294e38d0a23c949a7f23ea3a4bf45e97b48c 100644 --- a/build.xml +++ b/build.xml @@ -520,7 +520,7 @@ </exec> <echo message="Findbugs output stored in findbugs.xml" /> </target> - <target name="buildWithDesktopgui" depends="buildrouter"> + <target name="buildWithDesktopgui" depends="buildrouter,builddepSmall"> <ant dir="apps/desktopgui" target="build_jar" /> </target> <target name="preppkgWithDesktopgui" depends="buildWithDesktopgui,preppkg"> diff --git a/history.txt b/history.txt index 895f2bfc30c7bca9b9ef2261157f5451a76a36be..de28b4f586670592292e39ada3d618acacfa739f 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,53 @@ +2009-05-23 Mathiasdm + * Router netDB: + - Added flags to the netDB page + +2009-05-22 Mathiasdm + * desktopgui: + - Updating works in general config + - Switched to Swingworker threads for improved responsiveness + +2009-05-21 zzz + * Router Watchdog: + - Log memory stats + - Dump threads on linux + - Restart after 20 minutes (give the dog his teeth back) + +2009-05-21 zzz + * DataStore: + - Adjust interface to have persistent and non-persistent methods, + to prepare for partial storage in RAM + * ExpireRoutersJob: + - Rewrite, not enabled yet + * I2Punnel: + - Increase eepsite default to 3+0 for new installs + * PersistentDataStore: + - Cleanup, simplify, and concurrentify + - Tweak stats + - Remove write limit + - Flush to disk on shutdown + - Don't write out what we just read in + * Router and console: + - Bundle geoIP files and flags in new installs, + spiff up tunnels.jsp and profiles.jsp. + Existing installs can get files with 'ant updaterWIthGeoIP' + or in the console docs bundle 'ant consoleDocs' + - Use flags for shitlist and peers.jsp too + - Tweak tunnels.jsp to show class letters + - Hide in-progress details on tunnels.jsp + - Add a little color to confignav + - Remove 'no skew' message + - More message tweaks if no wrapper + * TunnelManager: + - Remove now-unused isInUse() + * UPnP: + - Fix up port binding, add some logging on bind fails + - Force IPv4 only for binds + +2009-05-20 Mathiasdm + * General configuration enabled by default + * General configuration speed tab works completely + 2009-05-17 zzz * Merge i2p.i2p.zzz.upnp branch * Major changes: diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index b74a3a021a67537a1c5a88fd8f2ae075a48f864b..ef84e9e97b23943b36323de092e6e12d02dc671b 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 1; + public final static long BUILD = 3; /** for example "-test" */ public final static String EXTRA = ""; public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA; diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java index 436fc526e39518f669002d5c9078784fd2f62637..4c935be5445b8c47240d9177ab6d67c51b2f56fd 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java @@ -1067,6 +1067,11 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { else buf.append("Published: <i>in ").append(DataHelper.formatDuration(0-age)).append("???</i><br />\n"); buf.append("Address(es): <i>"); + String country = _context.commSystem().getCountry(info.getIdentity().getHash()); + if(country != null) { + buf.append(" <img alt=\"").append(country.toUpperCase()).append("\""); + buf.append(" src=\"/flags.jsp?c=").append(country).append("\">"); + } for (Iterator iter = info.getAddresses().iterator(); iter.hasNext(); ) { RouterAddress addr = (RouterAddress)iter.next(); buf.append(addr.getTransportStyle()).append(": ");