From 321c5606488fb9c687257cb5bb79ea5016306ff1 Mon Sep 17 00:00:00 2001
From: jrandom <jrandom>
Date: Thu, 16 Feb 2006 09:33:53 +0000
Subject: [PATCH] drop most of the abandonware

---
 apps/heartbeat/doc/readme.gui.txt             |  39 --
 apps/heartbeat/doc/readme.txt                 | 122 ----
 apps/heartbeat/java/build.xml                 |  66 --
 .../src/net/i2p/heartbeat/ClientConfig.java   | 468 --------------
 .../src/net/i2p/heartbeat/ClientEngine.java   | 133 ----
 .../java/src/net/i2p/heartbeat/Heartbeat.java | 254 --------
 .../src/net/i2p/heartbeat/I2PAdapter.java     | 604 ------------------
 .../java/src/net/i2p/heartbeat/PeerData.java  | 412 ------------
 .../src/net/i2p/heartbeat/PeerDataWriter.java | 142 ----
 .../heartbeat/gui/HeartbeatControlPane.java   | 108 ----
 .../i2p/heartbeat/gui/HeartbeatMonitor.java   | 116 ----
 .../gui/HeartbeatMonitorCommandBar.java       |  67 --
 .../heartbeat/gui/HeartbeatMonitorGUI.java    |  98 ---
 .../heartbeat/gui/HeartbeatMonitorRunner.java |  32 -
 .../heartbeat/gui/HeartbeatMonitorState.java  | 129 ----
 .../i2p/heartbeat/gui/HeartbeatPlotPane.java  |  62 --
 .../i2p/heartbeat/gui/JFreeChartAdapter.java  | 233 -------
 .../gui/JFreeChartHeartbeatPlotPane.java      |  58 --
 .../net/i2p/heartbeat/gui/PeerPlotConfig.java | 367 -----------
 .../i2p/heartbeat/gui/PeerPlotConfigPane.java | 371 -----------
 .../net/i2p/heartbeat/gui/PeerPlotState.java  |  95 ---
 .../heartbeat/gui/PeerPlotStateFetcher.java   | 363 -----------
 .../net/i2p/heartbeat/gui/StaticPeerData.java | 134 ----
 apps/httptunnel/doc/COPYING                   | 278 --------
 apps/httptunnel/doc/readme.license.txt        |  11 -
 apps/httptunnel/java/build.xml                |  47 --
 .../src/net/i2p/httptunnel/HTTPListener.java  |  87 ---
 .../net/i2p/httptunnel/HTTPSocketHandler.java |  62 --
 .../src/net/i2p/httptunnel/HTTPTunnel.java    | 108 ----
 .../java/src/net/i2p/httptunnel/Request.java  | 153 -----
 .../i2p/httptunnel/SocketManagerProducer.java | 120 ----
 .../i2p/httptunnel/filter/ChainFilter.java    |  61 --
 .../src/net/i2p/httptunnel/filter/Filter.java |  25 -
 .../net/i2p/httptunnel/filter/NullFilter.java |  21 -
 .../i2p/httptunnel/handler/EepHandler.java    | 113 ----
 .../i2p/httptunnel/handler/ErrorHandler.java  |  41 --
 .../i2p/httptunnel/handler/LocalHandler.java  |  67 --
 .../i2p/httptunnel/handler/ProxyHandler.java  |  54 --
 .../i2p/httptunnel/handler/RootHandler.java   | 116 ----
 apps/jfreechart/GUI-licenses.txt              | 590 -----------------
 apps/jfreechart/build.xml                     |  29 -
 apps/myi2p/java/build.xml                     |  39 --
 .../java/src/net/i2p/myi2p/MyI2PMessage.java  | 116 ----
 apps/myi2p/java/src/net/i2p/myi2p/Node.java   | 266 --------
 .../java/src/net/i2p/myi2p/NodeAdapter.java   | 178 ------
 .../myi2p/java/src/net/i2p/myi2p/Service.java |  35 -
 .../java/src/net/i2p/myi2p/ServiceImpl.java   |  36 --
 .../net/i2p/myi2p/address/AddressBook.java    | 126 ----
 .../i2p/myi2p/address/AddressBookEntry.java   | 142 ----
 .../i2p/myi2p/address/AddressBookService.java |  90 ---
 .../myi2p/address/AddressBookServiceData.java | 104 ---
 .../net/i2p/myi2p/address/CreateEntryCLI.java | 154 -----
 .../myi2p/address/CreateNameReferenceCLI.java | 125 ----
 .../net/i2p/myi2p/address/NameReference.java  | 198 ------
 .../net/i2p/myi2p/address/Subscription.java   |  66 --
 apps/myi2p/myi2p.config                       |   3 -
 apps/netmonitor/harvester.config              | 130 ----
 apps/netmonitor/java/build.xml                |  69 --
 .../src/net/i2p/netmonitor/DataHarvester.java | 245 -------
 .../src/net/i2p/netmonitor/NetMonitor.java    | 251 --------
 .../net/i2p/netmonitor/NetMonitorRunner.java  | 242 -------
 .../java/src/net/i2p/netmonitor/PeerStat.java |  46 --
 .../src/net/i2p/netmonitor/PeerSummary.java   | 119 ----
 .../net/i2p/netmonitor/PeerSummaryReader.java | 106 ---
 .../net/i2p/netmonitor/PeerSummaryWriter.java |  80 ---
 .../src/net/i2p/netmonitor/StatGroup.java     |  53 --
 .../net/i2p/netmonitor/StatGroupLoader.java   |  93 ---
 .../i2p/netmonitor/gui/JFreeChartAdapter.java | 109 ----
 .../gui/JFreeChartHeartbeatPlotPane.java      |  53 --
 .../src/net/i2p/netmonitor/gui/NetViewer.java |  85 ---
 .../netmonitor/gui/NetViewerCommandBar.java   |  70 --
 .../netmonitor/gui/NetViewerControlPane.java  | 106 ---
 .../net/i2p/netmonitor/gui/NetViewerGUI.java  | 105 ---
 .../i2p/netmonitor/gui/NetViewerPlotPane.java |  46 --
 .../i2p/netmonitor/gui/NetViewerRunner.java   |  16 -
 .../i2p/netmonitor/gui/PeerPlotConfig.java    | 213 ------
 .../netmonitor/gui/PeerPlotConfigPane.java    | 276 --------
 apps/phttprelay/doc/readme.license.txt        |  10 -
 apps/phttprelay/java/build.xml                |  43 --
 apps/phttprelay/java/lib/LICENSE.html         | 159 -----
 apps/phttprelay/java/lib/javax.servlet.jar    | Bin 74543 -> 0 bytes
 apps/phttprelay/java/lib/readme.txt           |   6 -
 .../phttprelay/CheckSendStatusServlet.java    | 114 ----
 .../src/net/i2p/phttprelay/LockManager.java   |  44 --
 .../net/i2p/phttprelay/PHTTPRelayServlet.java |  75 ---
 .../src/net/i2p/phttprelay/PollServlet.java   | 263 --------
 .../net/i2p/phttprelay/RegisterServlet.java   | 158 -----
 .../src/net/i2p/phttprelay/SendServlet.java   | 324 ----------
 apps/phttprelay/java/web.xml                  |  71 --
 apps/tests/COPYING                            | 278 --------
 apps/tests/EchoServer.java                    |  44 --
 apps/tests/GuaranteedBug.java                 | 106 ---
 apps/tests/README                             |   6 -
 .../echotester/BasicEchoTestAnalyzer.java     |  88 ---
 apps/tests/echotester/EchoTestAnalyzer.java   |  17 -
 apps/tests/echotester/EchoTester.java         | 167 -----
 apps/tests/readme.license.txt                 |  10 -
 97 files changed, 12630 deletions(-)
 delete mode 100644 apps/heartbeat/doc/readme.gui.txt
 delete mode 100644 apps/heartbeat/doc/readme.txt
 delete mode 100644 apps/heartbeat/java/build.xml
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/ClientConfig.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/ClientEngine.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/Heartbeat.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/I2PAdapter.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/PeerData.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/PeerDataWriter.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatControlPane.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitor.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorCommandBar.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorGUI.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorRunner.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorState.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatPlotPane.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartAdapter.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartHeartbeatPlotPane.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfig.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfigPane.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotState.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotStateFetcher.java
 delete mode 100644 apps/heartbeat/java/src/net/i2p/heartbeat/gui/StaticPeerData.java
 delete mode 100644 apps/httptunnel/doc/COPYING
 delete mode 100644 apps/httptunnel/doc/readme.license.txt
 delete mode 100644 apps/httptunnel/java/build.xml
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/HTTPListener.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/HTTPSocketHandler.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/HTTPTunnel.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/Request.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/SocketManagerProducer.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/filter/ChainFilter.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/filter/Filter.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/filter/NullFilter.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/handler/EepHandler.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/handler/ErrorHandler.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/handler/LocalHandler.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/handler/ProxyHandler.java
 delete mode 100644 apps/httptunnel/java/src/net/i2p/httptunnel/handler/RootHandler.java
 delete mode 100644 apps/jfreechart/GUI-licenses.txt
 delete mode 100644 apps/jfreechart/build.xml
 delete mode 100644 apps/myi2p/java/build.xml
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/MyI2PMessage.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/Node.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/NodeAdapter.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/Service.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/ServiceImpl.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/address/AddressBook.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookEntry.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookService.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookServiceData.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/address/CreateEntryCLI.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/address/CreateNameReferenceCLI.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/address/NameReference.java
 delete mode 100644 apps/myi2p/java/src/net/i2p/myi2p/address/Subscription.java
 delete mode 100644 apps/myi2p/myi2p.config
 delete mode 100644 apps/netmonitor/harvester.config
 delete mode 100644 apps/netmonitor/java/build.xml
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/DataHarvester.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitor.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitorRunner.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/PeerStat.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummary.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryReader.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryWriter.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/StatGroup.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/StatGroupLoader.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartAdapter.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartHeartbeatPlotPane.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewer.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerCommandBar.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerControlPane.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerGUI.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerPlotPane.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerRunner.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfig.java
 delete mode 100644 apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfigPane.java
 delete mode 100644 apps/phttprelay/doc/readme.license.txt
 delete mode 100644 apps/phttprelay/java/build.xml
 delete mode 100644 apps/phttprelay/java/lib/LICENSE.html
 delete mode 100644 apps/phttprelay/java/lib/javax.servlet.jar
 delete mode 100644 apps/phttprelay/java/lib/readme.txt
 delete mode 100644 apps/phttprelay/java/src/net/i2p/phttprelay/CheckSendStatusServlet.java
 delete mode 100644 apps/phttprelay/java/src/net/i2p/phttprelay/LockManager.java
 delete mode 100644 apps/phttprelay/java/src/net/i2p/phttprelay/PHTTPRelayServlet.java
 delete mode 100644 apps/phttprelay/java/src/net/i2p/phttprelay/PollServlet.java
 delete mode 100644 apps/phttprelay/java/src/net/i2p/phttprelay/RegisterServlet.java
 delete mode 100644 apps/phttprelay/java/src/net/i2p/phttprelay/SendServlet.java
 delete mode 100644 apps/phttprelay/java/web.xml
 delete mode 100644 apps/tests/COPYING
 delete mode 100644 apps/tests/EchoServer.java
 delete mode 100644 apps/tests/GuaranteedBug.java
 delete mode 100644 apps/tests/README
 delete mode 100644 apps/tests/echotester/BasicEchoTestAnalyzer.java
 delete mode 100644 apps/tests/echotester/EchoTestAnalyzer.java
 delete mode 100644 apps/tests/echotester/EchoTester.java
 delete mode 100644 apps/tests/readme.license.txt

diff --git a/apps/heartbeat/doc/readme.gui.txt b/apps/heartbeat/doc/readme.gui.txt
deleted file mode 100644
index fde06a3369..0000000000
--- a/apps/heartbeat/doc/readme.gui.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-The Heartbeat GUI loads up the stat files generated by the Heartbeat
-engine and renders them visually, offering a way to drill through different
-data points and take snapshots as things change (by saving particular stat
-files for later).  The GUI itself doesn't need to be on the same machine
-as the Heartbeat engine - it pulls the stat files through any URL - even 
-through the EepProxy.
-
-An example Heartbeat GUI config file follows
-
-    # how often do we want to pull new data to render
-    refreshFrequency=60
-    ## for each peer test we may want to include in the GUI:
-    # where to find the current stat file (URL or filename)
-    stat.0.location=http://dev.i2p.net/stats/heartbeatStat_khWY_30s_1kb.txt
-    ## optional entries for each peer test describing what we want shown
-    ## (and how we want it shown)
-    # do we want to plot the send time (from when the ping was sent until the pong server got it)?
-    stat.0.plot.current.send=true
-    # do we want to plot the receive time (from when the pong was sent until reception)?
-    stat.0.plot.current.receive=true
-    # do we want to plot the lost messages?
-    stat.0.plot.current.lost=true
-    # what color should the current lines be rendered in?
-    stat.0.plot.current.color=BLUE
-    ## optional entries for each peer test describing what averages we want
-    ## rendered
-    # plot 1 minute send average?
-    stat.0.plot.1m.send=true
-    # plot 1 minute receive average?
-    stat.0.plot.1m.receive=true
-    # plot 1 minute lost message average?
-    stat.0.plot.1m.lost=true
-    # what color should the 1 minute averages be rendered as?
-    stat.0.plot.1m.color=GREEN
-    ## repeated for all of the averaged periods, e.g. 
-    ## stat.0.plot.30m, .60m, 1440m (1 day)
-    
-There may be some other options, such as where to store snapshot files, whether
-to generate PNG images, etc.
\ No newline at end of file
diff --git a/apps/heartbeat/doc/readme.txt b/apps/heartbeat/doc/readme.txt
deleted file mode 100644
index d9b667a1ad..0000000000
--- a/apps/heartbeat/doc/readme.txt
+++ /dev/null
@@ -1,122 +0,0 @@
-Heartbeat
-
-Application layer tool for monitoring the long term health of the
-network by periodically testing peers, generating stats, and
-rendering them visually.  The engine (both server and client) should
-work headless and seperate from the GUI, exposing the data in a simple
-to parse (and human readable) text file for each peer being tested.  
-The GUI then periodically refreshes itself by loading those files (
-either locally or from a URL) and renders the current state accordingly, 
-giving users a way to check that the network is alive, devs a tool to 
-both monitor the state of the network and to debug different situations (by 
-accessing the stat file - either live or archived).
-
-The heartbeat configuration file is organized as a standard properties
-file (by default located at heartbeat.config, but that can be overridden by 
-passing a filename as the first argument to the Heartbeat command):
-
-    # where the router is located (default is localhost)
-    i2cpHost=localhost
-    # I2CP port for the router (default is 7654)
-    i2cpPort=4001
-    # How many hops we want the router to put in our tunnels (default is 2)
-    numHops=2
-    # where our private destination keys are located - if this doesn't exist,
-    # a new one will be created and saved there (by default, heartbeat.keys)
-    privateDestinationFile=heartbeat_r2.keys
-
-    ## peer tests configured below:
-    
-    # destination peer for test 0
-    peer.0.peer=[destination in base64]
-    # where will we write out the stat data?
-    peer.0.statFile=heartbeatStat_khWY_30s_1kb.txt
-    # how many minutes will we keep stats for?
-    peer.0.statDuration=30
-    # how often will we write out new stat data (in seconds)?
-    peer.0.statFrequency=60
-    # how often will we send a ping to the peer (in seconds)?
-    peer.0.sendFrequency=30
-    # how many bytes will be included in the ping?
-    peer.0.sendSize=1024
-    # take a guess...
-    peer.0.comment=Test with localhost sending 1KB of data every 30 seconds
-    # we can keep track of a few moving averages - this value includes a whitespace
-    # delimited list of numbers, each specifying a period to calculate the average
-    # over (in minutes)
-    peer.0.averagePeriods=1 5 30
-    ## repeat the peer.0.* for as many tests as desired, incrementing as necessary
-
-If there are no peer.* lines, it will simply run a pong server.  If any data is
-missing, it will use the defaults (though there are no defaults for peer.* lines) -
-running the Heartbeat app with no heartbeat configuration file whatsoever will create
-a new pong server (storing its keys at heartbeat.keys) and using the I2P router at 
-localhost:7654.
-
-The stat file generated for each set of peer.n.* lines contains the current state
-of the test, its averages, as well as any other interesting data points.  An example
-stat file follows (hopefully it is self explanatory):
-
-    peer            khWYqCETu9YtPUvGV92ocsbEW5DezhKlIG7ci8RLX3g=
-    local           u-9hlR1ik2hemXf0HvKMfeRgrS86CbNQh25e7XBhaQE=
-    peerDest        [base 64 of the full destination]
-    localDest       [base 64 of the full destination]
-    numTunnelHops   2
-    comment         Test with localhost sending 30KB every 20 seconds
-    sendFrequency   20
-    sendSize        30720
-    sessionStart    20040409.22:51:10.915
-    currentTime     20040409.23:31:39.607
-    numPending      2
-    lifetimeSent    118
-    lifetimeRecv    113
-    #averages       minutes sendMs  recvMs  numLost
-    periodAverage   1       1843    771     0
-    periodAverage   5       786     752     1
-    periodAverage   30      855     735     3
-    #action status  date and time sent      sendMs  replyMs
-    EVENT   OK      20040409.23:21:44.742   691     670
-    EVENT   OK      20040409.23:22:05.201   671     581
-    EVENT   OK      20040409.23:22:26.301   1182    1452
-    EVENT   OK      20040409.23:22:47.322   24304   1723
-    EVENT   OK      20040409.23:23:08.232   2293    1081
-    EVENT   OK      20040409.23:23:29.332   1392    641
-    EVENT   OK      20040409.23:23:50.262   641     761
-    EVENT   OK      20040409.23:24:11.102   651     701
-    EVENT   OK      20040409.23:24:31.401   841     621
-    EVENT   OK      20040409.23:24:52.061   651     681
-    EVENT   OK      20040409.23:25:12.480   701     1623
-    EVENT   OK      20040409.23:25:32.990   1442    1212
-    EVENT   OK      20040409.23:25:54.230   591     631
-    EVENT   OK      20040409.23:26:14.620   620     691
-    EVENT   OK      20040409.23:26:35.199   1793    1432
-    EVENT   OK      20040409.23:26:56.570   661     641
-    EVENT   OK      20040409.23:27:17.200   641     660
-    EVENT   OK      20040409.23:27:38.120   611     921
-    EVENT   OK      20040409.23:27:58.699   831     621
-    EVENT   OK      20040409.23:28:19.559   801     661
-    EVENT   OK      20040409.23:28:40.279   601     611
-    EVENT   OK      20040409.23:29:00.648   601     621
-    EVENT   OK      20040409.23:29:21.288   701     661
-    EVENT   LOST    20040409.23:29:41.828
-    EVENT   LOST    20040409.23:30:02.327
-    EVENT   LOST    20040409.23:30:22.656
-    EVENT   OK      20040409.23:31:24.305   1843    771
-
-The actual ping and pong messages sent are formatted trivially -
-ping messages contain
-    $from $series $type $sentOn $size $payload
-while pong messages contain
-    $from $series $type $sentOn $receivedOn $size $payload
-
-$series is a number describing the sending client's test (so that you can
-ping the same peer with different configurations concurrently, varying things
-like the frequency and size of the message, window, etc).
-
-They are sent as raw binary messages though, so see I2PAdapter.sendPing(..)
-and I2PAdapter.sendPong(..) for the details.
-
-To get valid measurements, of course, you will want to make sure that 
-both the heartbeat client and pong server have synchronized clocks (even
-more so than I2P requires).  It is highly recommended that only NTP 
-synchronized peers be used for heartbeat tests.
\ No newline at end of file
diff --git a/apps/heartbeat/java/build.xml b/apps/heartbeat/java/build.xml
deleted file mode 100644
index 99a627956c..0000000000
--- a/apps/heartbeat/java/build.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project basedir="." default="all" name="heartbeat">
-    <target name="all" depends="clean, buildGUI" />
-    <target name="build" depends="builddep, jar" />
-    <target name="buildGUI" depends="build, jarGUI" />
-    <target name="builddep">
-        <ant dir="../../../core/java/" target="build" />
-    </target>
-    <target name="compile">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/obj" />
-        <javac srcdir="./src" debug="true" deprecation="on" source="1.3" target="1.3" destdir="./build/obj" includes="**/*.java" excludes="net/i2p/heartbeat/gui/**" classpath="../../../core/java/build/i2p.jar" />
-    </target>
-    <target name="compileGUI">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/obj" />
-        <javac debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj">
-            <src path="src/" />
-            <classpath path="../../../core/java/build/i2p.jar" />
-            <classpath path="../../jfreechart/jfreechart-0.9.17/lib/jcommon-0.9.2.jar" />
-            <classpath path="../../jfreechart/jfreechart-0.9.17/lib/log4j-1.2.8.jar" />
-            <classpath path="../../jfreechart/jfreechart-0.9.17/jfreechart-0.9.17.jar" />
-        </javac>
-    </target>
-    <target name="jar" depends="compile">
-        <jar destfile="./build/heartbeat.jar" basedir="./build/obj" includes="**/*.class">
-            <manifest>
-                <attribute name="Main-Class" value="net.i2p.heartbeat.Heartbeat" />
-                <attribute name="Class-Path" value="i2p.jar heartbeat.jar" />
-            </manifest>
-        </jar>
-    </target>
-    <target name="jarGUI" depends="compileGUI">
-        <copy file="../../jfreechart/jfreechart-0.9.17/jfreechart-0.9.17.jar" todir="build/" />
-        <copy file="../../jfreechart/jfreechart-0.9.17/lib/log4j-1.2.8.jar" todir="build/" />
-        <copy file="../../jfreechart/jfreechart-0.9.17/lib/jcommon-0.9.2.jar" todir="build/" />
-        <jar destfile="./build/heartbeatGUI.jar" basedir="./build/obj" includes="**">
-            <manifest>
-                <attribute name="Main-Class" value="net.i2p.heartbeat.gui.HeartbeatMonitor" />
-                <attribute name="Class-Path" value="log4j-1.2.8.jar jcommon-0.9.2.jar jfreechart-0.9.17.jar heartbeatGUI.jar i2p.jar" />
-            </manifest>
-        </jar>
-        <echo message="You will need to copy the log4j, jcommon, and jfreechart jar files into your lib dir" />
-    </target>
-    <target name="javadoc">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/javadoc" />
-        <javadoc 
-            sourcepath="./src:../../../core/java/src:../../../core/java/test" destdir="./build/javadoc" 
-            packagenames="*" 
-            use="true" 
-            access="package"
-            splitindex="true" 
-            windowtitle="I2P heartbeat monitor" />
-    </target>
-    <target name="clean">
-        <delete dir="./build" />
-    </target>
-    <target name="cleandep" depends="clean">
-        <ant dir="../../../core/java/" target="cleandep" />
-        <ant dir="../../../core/java/" target="cleandep" />
-    </target>
-    <target name="distclean" depends="clean">
-        <ant dir="../../../core/java/" target="distclean" />
-    </target>
-</project>
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/ClientConfig.java b/apps/heartbeat/java/src/net/i2p/heartbeat/ClientConfig.java
deleted file mode 100644
index 59b9dfc873..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/ClientConfig.java
+++ /dev/null
@@ -1,468 +0,0 @@
-package net.i2p.heartbeat;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Properties;
-import java.util.StringTokenizer;
-
-import net.i2p.data.DataFormatException;
-import net.i2p.data.Destination;
-import net.i2p.util.Log;
-
-/**
- * Define the configuration for testing against one particular peer as a client
- */
-public class ClientConfig {
-    private static final Log _log = new Log(ClientConfig.class);
-    private Destination _peer;
-    private Destination _us;
-    private String _statFile;
-    private int _statDuration;
-    private int _statFrequency;
-    private int _sendFrequency;
-    private int _sendSize;
-    private int _numHops;
-    private String _comment;
-    private int _averagePeriods[];
-
-    /**
-     * @seeRoutine ClientConfig#load
-     * @seeRoutine ClientConfig#store
-     */
-    public static final String PROP_PREFIX = "peer.";
-
-    /**
-     * @seeRoutine ClientConfig#load
-     * @seeRoutine ClientConfig#store
-     */
-    public static final String PROP_PEER = ".peer";
-
-    /**
-     * @seeRoutine ClientConfig#load
-     * @seeRoutine ClientConfig#store
-     */
-    public static final String PROP_STATFILE = ".statFile";
-
-    /**
-     * @seeRoutine ClientConfig#load
-     * @seeRoutine ClientConfig#store
-     */
-    public static final String PROP_STATDURATION = ".statDuration";
-
-    /**
-     * @seeRoutine ClientConfig#load
-     * @seeRoutine ClientConfig#store
-     */
-    public static final String PROP_STATFREQUENCY = ".statFrequency";
-
-    /**
-     * @seeRoutine ClientConfig#load
-     * @seeRoutine ClientConfig#store
-     */
-    public static final String PROP_SENDFREQUENCY = ".sendFrequency";
-
-    /**
-     * @seeRoutine ClientConfig#load
-     * @seeRoutine ClientConfig#store
-     */
-    public static final String PROP_SENDSIZE = ".sendSize";
-
-    /**
-     * @seeRoutine ClientConfig#load
-     * @seeRoutine ClientConfig#store
-     */
-    public static final String PROP_COMMENT = ".comment";
-
-    /**
-     * @seeRoutine ClientConfig#load
-     * @seeRoutine ClientConfig#store
-     */
-    public static final String PROP_AVERAGEPERIODS = ".averagePeriods";
-
-    /**
-     * Default constructor...
-     */
-    public ClientConfig() {
-        this(null, null, null, -1, -1, -1, -1, 0, null, null);
-    }
-    
-    /**
-     * Create a dummy client config to be fetched from the specified location
-     * @param location the location to fetch from
-     */
-    public ClientConfig(String location) {
-        this(null, null, location, -1, -1, -1, -1, 0, null, null);
-    }
-
-    /**
-     * @param peer who we will test against
-     * @param us who we are
-     * @param statLocation where the stat data should be stored/fetched
-     * @param duration how many minutes to keep events for
-     * @param statFreq how often to write out stats
-     * @param sendFreq how often to send pings
-     * @param sendSize how large the pings should be
-     * @param numHops how many hops is the current Heartbeat app using
-     * @param comment describe this test
-     * @param averagePeriods list of minutes to summarize over
-     */
-    public ClientConfig(Destination peer, Destination us, String statLocation, int duration, int statFreq, int sendFreq,
-                        int sendSize, int numHops, String comment, int averagePeriods[]) {
-        _peer = peer;
-        _us = us;
-        _statFile = statLocation;
-        _statDuration = duration;
-        _statFrequency = statFreq;
-        _sendFrequency = sendFreq;
-        _sendSize = sendSize;
-        _numHops = numHops;
-        _comment = comment;
-        _averagePeriods = averagePeriods;
-    }
-
-    /**
-     * Retrieves the peer to test against
-     * 
-     * @return the Destination (peer)
-     */
-    public Destination getPeer() {
-        return _peer;
-    }
-
-    /**
-     * Sets the peer to test against
-     * 
-     * @param peer the Destination (peer)
-     */
-    public void setPeer(Destination peer) {
-        _peer = peer;
-    }
-
-    /**
-     * Retrieves who we are when we test
-     * 
-     * @return the Destination (us)
-     */
-    public Destination getUs() {
-        return _us;
-    }
-
-    /**
-     * Sets who we are when we test
-     * 
-     * @param us the Destination (us)
-     */
-    public void setUs(Destination us) {
-        _us = us;
-    }
-
-    /**
-     * Retrieves the location to write the current stats to
-     * 
-     * @return the name of the file
-     */
-    public String getStatFile() {
-        return _statFile;
-    }
-
-    /**
-     * Sets the name of the location we write the current stats to
-     * 
-     * @param statFile the name of the file
-     */
-    public void setStatFile(String statFile) {
-        _statFile = statFile;
-    }
-
-    /**
-     * Retrieves how many minutes of statistics should be maintained within the window for this client
-     * 
-     * @return the number of minutes
-     */
-    public int getStatDuration() {
-        return _statDuration;
-    }
-
-    /**
-     * Sets how many minutes of statistics should be maintained within the window for this client
-     * 
-     * @param durationMinutes the number of minutes
-     */
-    public void setStatDuration(int durationMinutes) {
-        _statDuration = durationMinutes;
-    }
-
-    /**
-     * Retrieves how frequently the stats are written out (in seconds)
-     * 
-     * @return the frequency in seconds
-     */
-    public int getStatFrequency() {
-        return _statFrequency;
-    }
-
-    /**
-     * Sets how frequently the stats are written out (in seconds)
-     * 
-     * @param freqSeconds the frequency in seconds
-     */
-    public void setStatFrequency(int freqSeconds) {
-        _statFrequency = freqSeconds;
-    }
-
-    /**
-     * Retrieves how frequenty we send messages to the peer (in seconds)
-     * 
-     * @return the frequency in seconds
-     */
-    public int getSendFrequency() {
-        return _sendFrequency;
-    }
-
-    /**
-     * Sets how frequenty we send messages to the peer (in seconds)
-     * 
-     * @param freqSeconds the frequency in seconds
-     */
-    public void setSendFrequency(int freqSeconds) {
-        _sendFrequency = freqSeconds;
-    }
-
-    /**
-     * Retrieves how many bytes the ping messages should be (min values ~700, max ~32KB)
-     * 
-     * @return the size in bytes
-     */
-    public int getSendSize() {
-        return _sendSize;
-    }
-
-    /**
-     * Sets how many bytes the ping messages should be (min values ~700, max ~32KB)
-     * 
-     * @param numBytes the size in bytes
-     */
-    public void setSendSize(int numBytes) {
-        _sendSize = numBytes;
-    }
-
-    /**
-     * Retrieves the brief, 1 line description of the test. Useful comments are along the lines of "The peer is located on a fast router and connection with 2
-     * hop tunnels".
-     * 
-     * @return the brief comment
-     */
-    public String getComment() {
-        return _comment;
-    }
-
-    /**
-     * Sets a brief, 1 line description (comment) of the test.
-     * 
-     * @param comment the brief comment
-     */
-    public void setComment(String comment) {
-        _comment = comment;
-    }
-
-    /**
-     * Retrieves the periods that the client's tests should be averaged over.
-     * 
-     * @return list of periods (in minutes) that the data should be averaged over, or null
-     */
-    public int[] getAveragePeriods() {
-        return _averagePeriods;
-    }
-
-    /**
-     * Sets the periods that the client's tests should be averaged over.
-     * 
-     * @param periods the list of periods (in minutes) that the data should be averaged over, or null
-     */
-    public void setAveragePeriods(int periods[]) {
-        _averagePeriods = periods;
-    }
-    
-    /**
-     * Make sure we're keeping track of the average over the given time period.
-     *
-     * @param minutes how many minutes to monitor
-     */
-    public void addAveragePeriod(int minutes) {
-        if (_averagePeriods != null) {
-            for (int i = 0; i < _averagePeriods.length; i++) {
-                if (_averagePeriods[i] == minutes)
-                    return;
-            }
-        }
-        
-        int numPeriods = 1;
-        if (_averagePeriods != null)
-            numPeriods += _averagePeriods.length;
-        int periods[] = new int[numPeriods];
-        if (_averagePeriods != null)
-            System.arraycopy(_averagePeriods, 0, periods, 0, _averagePeriods.length);
-        periods[periods.length-1] = minutes;
-        Arrays.sort(periods);
-        _averagePeriods = periods;
-    }
-
-    /**
-     * Retrieves how many hops this test engine is configured to use for its outbound and inbound tunnels
-     * 
-     * @return the number of hops
-     */
-    public int getNumHops() {
-        return _numHops;
-    }
-
-    /**
-     * Sets how many hops this test engine is configured to use for its outbound and inbound tunnels
-     * 
-     * @param numHops the number of hops
-     */
-    public void setNumHops(int numHops) {
-        _numHops = numHops;
-    }
-
-    /**
-     * Load the client config from the properties specified, deriving the current config entry from the peer number.
-     * 
-     * @param clientConfig the properties to load from
-     * @param peerNum the number associated with the peer
-     * @return true if it was loaded correctly, false if there were errors
-     */
-    public boolean load(Properties clientConfig, int peerNum) {
-        if ((clientConfig == null) || (peerNum < 0)) return false;
-        String peerVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_PEER);
-        String statFileVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_STATFILE);
-        String statDurationVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_STATDURATION);
-        String statFrequencyVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_STATFREQUENCY);
-        String sendFrequencyVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_SENDFREQUENCY);
-        String sendSizeVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_SENDSIZE);
-        String commentVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_COMMENT);
-        String periodsVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_AVERAGEPERIODS);
-
-        if ((peerVal == null) || (statFileVal == null) || (statDurationVal == null) || (statFrequencyVal == null)
-            || (sendFrequencyVal == null) || (sendSizeVal == null)) {
-            if (_log.shouldLog(Log.DEBUG)) {
-                _log.debug("Peer number " + peerNum + " does not exist");
-            }
-            return false;
-        }
-
-        try {
-            int duration = getInt(statDurationVal);
-            int statFreq = getInt(statFrequencyVal);
-            int sendFreq = getInt(sendFrequencyVal);
-            int sendSize = getInt(sendSizeVal);
-
-            if ((duration <= 0) || (statFreq <= 0) || (sendFreq < 0) || (sendSize <= 0)) {
-                if (_log.shouldLog(Log.WARN)) {
-                    _log.warn("Invalid client config: duration [" + statDurationVal + "] stat frequency ["
-                              + statFrequencyVal + "] send frequency [" + sendFrequencyVal + "] send size ["
-                              + sendSizeVal + "]");
-                }
-                return false;
-            }
-
-            statFileVal = statFileVal.trim();
-            if (statFileVal.length() <= 0) {
-                if (_log.shouldLog(Log.WARN)) {
-                    _log.warn("Stat file is blank for peer " + peerNum);
-                }
-                return false;
-            }
-
-            Destination d = new Destination();
-            d.fromBase64(peerVal);
-
-            if (commentVal == null) {
-                commentVal = "";
-            }
-
-            commentVal = commentVal.trim();
-            commentVal = commentVal.replace('\n', '_');
-
-            List periods = new ArrayList(4);
-            if (periodsVal != null) {
-                StringTokenizer tok = new StringTokenizer(periodsVal);
-                while (tok.hasMoreTokens()) {
-                    String periodVal = tok.nextToken();
-                    int minutes = getInt(periodVal);
-                    if (minutes > 0) {
-                        periods.add(new Integer(minutes));
-                    }
-                }
-            }
-            int avgPeriods[] = new int[periods.size()];
-            for (int i = 0; i < periods.size(); i++) {
-                avgPeriods[i] = ((Integer) periods.get(i)).intValue();
-            }
-
-            _comment = commentVal;
-            _statDuration = duration;
-            _statFrequency = statFreq;
-            _sendFrequency = sendFreq;
-            _sendSize = sendSize;
-            _statFile = statFileVal;
-            _peer = d;
-            _averagePeriods = avgPeriods;
-            return true;
-        } catch (DataFormatException dfe) {
-            _log.error("Peer destination for " + peerNum + " was invalid: " + peerVal);
-            return false;
-        }
-    }
-
-    /**
-     * Store the client config to the properties specified, deriving the current config entry from the peer number.
-     * 
-     * @param clientConfig the properties to store to
-     * @param peerNum the number associated with the peer
-     * @return true if it was stored correctly, false if there were errors
-     */
-    public boolean store(Properties clientConfig, int peerNum) {
-        if ((_peer == null) || (_sendFrequency < 0) || (_sendSize <= 0) || (_statDuration <= 0)
-            || (_statFrequency <= 0) || (_statFile == null)) { return false; }
-
-        String comment = _comment;
-        if (comment == null) {
-            comment = "";
-        }
-
-        comment = comment.trim();
-        comment = comment.replace('\n', '_');
-
-        StringBuffer buf = new StringBuffer(32);
-        if (_averagePeriods != null) {
-            for (int i = 0; i < _averagePeriods.length; i++) {
-                buf.append(_averagePeriods[i]).append(' ');
-            }
-        }
-
-        clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_PEER, _peer.toBase64());
-        clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_STATFILE, _statFile);
-        clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_STATDURATION, _statDuration + "");
-        clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_STATFREQUENCY, _statFrequency + "");
-        clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_SENDFREQUENCY, _sendFrequency + "");
-        clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_SENDSIZE, _sendSize + "");
-        clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_COMMENT, comment);
-        clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_AVERAGEPERIODS, buf.toString());
-        return true;
-    }
-
-    private static final int getInt(String val) {
-        if (val == null) return -1;
-        try {
-            int i = Integer.parseInt(val);
-            return i;
-        } catch (NumberFormatException nfe) {
-            if (_log.shouldLog(Log.DEBUG)) {
-                _log.debug("Value [" + val + "] is not a valid integer");
-            }
-            return -1;
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/ClientEngine.java b/apps/heartbeat/java/src/net/i2p/heartbeat/ClientEngine.java
deleted file mode 100644
index 15230f40a7..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/ClientEngine.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package net.i2p.heartbeat;
-
-import net.i2p.data.Destination;
-import net.i2p.util.Clock;
-import net.i2p.util.I2PThread;
-import net.i2p.util.Log;
-
-/**
- * Responsible for actually conducting the tests, coordinating the storing of the 
- * stats, and the management of the rates.  This has its own thread specific for
- * pumping data around as well.
- *
- */
-class ClientEngine {
-    private static final Log _log = new Log(ClientEngine.class);
-    /** who can send our pings? */
-    private Heartbeat _heartbeat;
-    /** actual test state */
-    private PeerData _data;
-    /** have we been stopped? */
-    private boolean _active;
-    /** used to generate engine IDs */
-    private static int __id = 0;
-    /** this engine's id, unique to the {test,sendingClient,startTime} */
-    private int _id;
-    private static PeerDataWriter writer = new PeerDataWriter();
-
-    /**
-     * Create a new engine that will send its pings through the given heartbeat
-     * system, and will coordinate the test according to the configuration specified.
-     * @param heartbeat the Heartbeat to send pings through
-     * @param config the Configuration to load configuration from =p
-     */
-    public ClientEngine(Heartbeat heartbeat, ClientConfig config) {
-        _heartbeat = heartbeat;
-        _data = new PeerData(config);
-        _active = false;
-        _id = ++__id;
-    }
-
-    /** stop sending any more pings or writing any more state */
-    public void stopEngine() {
-        _active = false;
-        if (_log.shouldLog(Log.INFO))
-            _log.info("Stopping engine talking to peer " + _data.getConfig().getPeer().calculateHash().toBase64());
-    }
-
-    /** start up the test (this does not block, as it fires up the test thread) */
-    public void startEngine() {
-        _active = true;
-        I2PThread t = new I2PThread(new ClientRunner());
-        t.setName("HeartbeatClient " + _id);
-        t.start();
-    }
-
-    /**
-     * Who are we testing? 
-     * @return the Destination (peer) we're testing
-     */
-    public Destination getPeer() {
-        return _data.getConfig().getPeer();
-    }
-
-    /**
-     * What is our series identifier (used to locally identify a test) 
-     * @return the series identifier
-     */
-    public int getSeriesNum() {
-        return _id;
-    }
-
-    /** 
-     * receive notification from the heartbeat system that a pong was received in 
-     * reply to a ping we have sent.  
-     *
-     * @param sentOn when did we send the ping?
-     * @param replyOn when did the peer send the pong?
-     */
-    public void receivePong(long sentOn, long replyOn) {
-        _data.pongReceived(sentOn, replyOn);
-    }
-
-    /** fire off a new ping */
-    private void doSend() {
-        long now = Clock.getInstance().now();
-        _data.addPing(now);
-        _heartbeat.sendPing(_data.getConfig().getPeer(), _id, now, _data.getConfig().getSendSize());
-    }
-
-    /** our actual heartbeat pumper - this drives the test */
-    private class ClientRunner implements Runnable {
-
-        /**
-         * @see java.lang.Runnable#run()
-         */
-        public void run() {
-            if (_log.shouldLog(Log.INFO))
-                _log.info("Starting engine talking to peer " + _data.getConfig().getPeer().calculateHash().toBase64());
-
-            // when do we need to send the next PING?
-            long nextSend = Clock.getInstance().now();
-            // when do we need to write out the next state data?
-            long nextWrite = Clock.getInstance().now();
-
-            while (_active) {
-
-                if (Clock.getInstance().now() >= nextSend) {
-                    doSend();
-                    nextSend = Clock.getInstance().now() + _data.getConfig().getSendFrequency() * 1000;
-                }
-
-                if (Clock.getInstance().now() >= nextWrite) {
-                    boolean written = writer.persist(_data);
-                    if (!written) {
-                        if (_log.shouldLog(Log.ERROR)) _log.error("Unable to write the client state data");
-                    } else {
-                        if (_log.shouldLog(Log.DEBUG)) _log.debug("Client state data written");
-                    }
-                }
-
-                _data.cleanup();
-
-                long timeToWait = nextSend - Clock.getInstance().now();
-                if (timeToWait > 0) {
-                    try {
-                        Thread.sleep(timeToWait);
-                    } catch (InterruptedException ie) {
-                    }
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/Heartbeat.java b/apps/heartbeat/java/src/net/i2p/heartbeat/Heartbeat.java
deleted file mode 100644
index c577945f63..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/Heartbeat.java
+++ /dev/null
@@ -1,254 +0,0 @@
-package net.i2p.heartbeat;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-
-import net.i2p.data.Destination;
-import net.i2p.util.Log;
-
-/**
- * Main driver for the heartbeat engine, loading 0 or more tests, firing
- * up a ClientEngine for each, and serving as a pong server.  If there isn't
- * a configuration file, or if the configuration file doesn't specify any tests,
- * it simply sits around as a pong server, passively responding to whatever is 
- * sent its way.  <p />
- *
- * The config file format is examplified below:
- * <pre>
- *    # where the router is located (default is localhost)
- *    i2cpHost=localhost
- *    # I2CP port for the router (default is 7654)
- *    i2cpPort=4001
- *    # How many hops we want the router to put in our tunnels (default is 2)
- *    numHops=2
- *    # where our private destination keys are located - if this doesn't exist,
- *    # a new one will be created and saved there (by default, heartbeat.keys)
- *    privateDestinationFile=heartbeat_r2.keys
- *    # where do we want to export the plain base64 of our destination?
- *    publicDestinationFile=heartbeat_r2.txt
- *
- *    ## peer tests configured below:
- *    
- *    # destination peer for test 0
- *    peer.0.peer=[destination in base64]
- *    # where will we write out the stat data?
- *    peer.0.statFile=heartbeatStat_khWY_30s_1kb.txt
- *    # how many minutes will we keep stats for?
- *    peer.0.statDuration=30
- *    # how often will we write out new stat data (in seconds)?
- *    peer.0.statFrequency=60
- *    # how often will we send a ping to the peer (in seconds)?
- *    peer.0.sendFrequency=30
- *    # how many bytes will be included in the ping?
- *    peer.0.sendSize=1024
- *    # take a guess...
- *    peer.0.comment=Test with localhost sending 1KB of data every 30 seconds
- *    # we can keep track of a few moving averages - this value includes a whitespace
- *    # delimited list of numbers, each specifying a period to calculate the average
- *    # over (in minutes)
- *    peer.0.averagePeriods=1 5 30
- *    ## repeat the peer.0.* for as many tests as desired, incrementing as necessary
- * </pre>
- *
- */
-public class Heartbeat {
-    private static final Log _log = new Log(Heartbeat.class);
-    /** location containing this heartbeat's config */
-    private String _configFile;
-    /** clientNum (Integer) to ClientConfig mapping */
-    private Map _clientConfigs;
-    /** series num (Integer) to ClientEngine mapping */
-    private Map _clientEngines;
-    /** helper class for managing our I2P send/receive and message formatting */
-    private I2PAdapter _adapter;
-    /** our own callback that the I2PAdapter notifies on ping or pong messages */
-    private PingPongAdapter _eventAdapter;
-
-    /** if there are no command line arguments, load the config from "heartbeat.config" */
-    public static final String CONFIG_FILE_DEFAULT = "heartbeat.config";
-
-    /**
-     * build up a new heartbeat manager, but don't actually do anything
-     * @param configFile the name of the configuration file
-     */
-    public Heartbeat(String configFile) {
-        _configFile = configFile;
-        _clientConfigs = new HashMap();
-        _clientEngines = new HashMap();
-        _eventAdapter = new PingPongAdapter();
-        _adapter = new I2PAdapter();
-        _adapter.setListener(_eventAdapter);
-    }
-
-    private Heartbeat() {
-    }
-
-    /** load up the config data (but don't build any engines or start them up) */
-    public void loadConfig() {
-        Properties props = new Properties();
-        FileInputStream fin = null;
-        File configFile = new File(_configFile);
-        if (configFile.exists()) {
-            try {
-                fin = new FileInputStream(_configFile);
-                props.load(fin);
-            } catch (IOException ioe) {
-                if (_log.shouldLog(Log.ERROR)) {
-                    _log.error("Error reading the config data", ioe);
-                }
-            } finally {
-                if (fin != null) try {
-                    fin.close();
-                } catch (IOException ioe) {
-                }
-            }
-        }
-
-        loadBaseConfig(props);
-        loadClientConfigs(props);
-    }
-
-    /** 
-     * send a ping message to the peer
-     *
-     * @param peer peer to ping
-     * @param seriesNum id used to keep track of multiple pings (of different size/frequency) to a peer
-     * @param now current time to be sent in the ping (so we can watch for it in the pong)
-     * @param size total message size to send
-     */
-    void sendPing(Destination peer, int seriesNum, long now, int size) {
-        if (_adapter.getIsConnected()) _adapter.sendPing(peer, seriesNum, now, size);
-    }
-
-    /**
-     * load up the base data (I2CP config, etc)
-     * @param props the properties to load from 
-     */
-    private void loadBaseConfig(Properties props) {
-        _adapter.loadConfig(props);
-    }
-
-    /** 
-     * load up all of the test config data 
-     * @param props the properties to load from
-     * */
-    private void loadClientConfigs(Properties props) {
-        int i = 0;
-        while (true) {
-            ClientConfig config = new ClientConfig();
-            if (!config.load(props, i)) {
-                break;
-            }
-            _clientConfigs.put(new Integer(i), config);
-            i++;
-        }
-    }
-
-    /** connect to the network */
-    private void connect() {
-        boolean connected = _adapter.connect();
-        if (!connected) _log.error("Unable to connect to the router");
-    }
-
-    /** disconnect from the network */
-    private void disconnect() { /* UNUSED */
-        _adapter.disconnect();
-    }
-
-    /** start up all of the tests */
-    public void startEngines() {
-        for (Iterator iter = _clientConfigs.values().iterator(); iter.hasNext();) {
-            ClientConfig config = (ClientConfig) iter.next();
-            ClientEngine engine = new ClientEngine(this, config);
-            config.setUs(_adapter.getLocalDestination());
-            config.setNumHops(_adapter.getNumHops());
-            _clientEngines.put(new Integer(engine.getSeriesNum()), engine);
-            engine.startEngine();
-        }
-    }
-
-    /** stop all of the tests */
-    public void stopEngines() {
-        for (Iterator iter = _clientEngines.values().iterator(); iter.hasNext();) {
-            ClientEngine engine = (ClientEngine) iter.next();
-            engine.stopEngine();
-        }
-        _clientEngines.clear();
-    }
-
-    /**
-     * Fire up a new heartbeat system, waiting until, well, forever.  Builds
-     * a new heartbeat system, loads the config, connects to the network, starts
-     * the engines, and then sits back and relaxes, responding to any pings and
-     * running any tests. <p />
-     *
-     * <code> <b>Usage: </b> Heartbeat [<i>configFileName</i>]</code> <p />
-     * @param args the list of args passed to the program from the command-line
-     */
-    public static void main(String args[]) {
-        String configFile = CONFIG_FILE_DEFAULT;
-        if (args.length == 1) {
-            configFile = args[0];
-        }
-
-        if (_log.shouldLog(Log.INFO)) {
-            _log.info("Starting up with config file " + configFile);
-        }
-        Heartbeat heartbeat = new Heartbeat(configFile);
-        heartbeat.loadConfig();
-        heartbeat.connect();
-        heartbeat.startEngines();
-        Object o = new Object();
-        while (true) {
-            try {
-                synchronized (o) {
-                    o.wait();
-                }
-            } catch (InterruptedException ie) {
-            }
-        }
-    }
-
-    /**
-     * Receive event notification from the I2PAdapter
-     *
-     */
-    private class PingPongAdapter implements I2PAdapter.PingPongEventListener {
-        /**
-         * We were pinged, so always just send a pong back.
-         * 
-         * @param from who sent us the ping?
-         * @param seriesNum what series did the sender specify?
-         * @param sentOn when did the sender say they sent their ping?
-         * @param data arbitrary payload data
-         */
-        public void receivePing(Destination from, int seriesNum, Date sentOn, byte[] data) {
-            if (_adapter.getIsConnected()) {
-                _adapter.sendPong(from, seriesNum, sentOn, data);
-            }
-        }
-
-        /**
-         * We received a pong, so find the right client engine and tell it about the pong.
-         *
-         * @param from who sent us the pong
-         * @param seriesNum our client ID
-         * @param sentOn when did we send the ping?
-         * @param replyOn when did they send their pong?
-         * @param data the arbitrary data we sent in the ping (that they sent back in the pong)
-         */
-        public void receivePong(Destination from, int seriesNum, Date sentOn, Date replyOn, byte[] data) {
-            ClientEngine engine = (ClientEngine) _clientEngines.get(new Integer(seriesNum));
-            if (engine.getPeer().equals(from)) {
-                engine.receivePong(sentOn.getTime(), replyOn.getTime());
-            }
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/I2PAdapter.java b/apps/heartbeat/java/src/net/i2p/heartbeat/I2PAdapter.java
deleted file mode 100644
index 35c157c7bb..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/I2PAdapter.java
+++ /dev/null
@@ -1,604 +0,0 @@
-package net.i2p.heartbeat;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Date;
-import java.util.Properties;
-
-import net.i2p.I2PAppContext;
-import net.i2p.I2PException;
-import net.i2p.client.I2PClient;
-import net.i2p.client.I2PClientFactory;
-import net.i2p.client.I2PSession;
-import net.i2p.client.I2PSessionException;
-import net.i2p.client.I2PSessionListener;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.DataHelper;
-import net.i2p.data.Destination;
-import net.i2p.util.Clock;
-import net.i2p.util.Log;
-
-/**
- * Tie-in to the I2P SDK for the Heartbeat system, talking to the I2PSession and
- * dealing with the raw ping and pong messages.
- *
- */
-class I2PAdapter {
-    private final static Log _log = new Log(I2PAdapter.class);
-    /** I2CP host */
-    private String _i2cpHost;
-    /** I2CP port */
-    private int _i2cpPort;
-    /** how long do we want our tunnels to be? */
-    private int _numHops;
-    /** filename containing the heartbeat engine's private destination info */
-    private String _privateDestFile;
-    /** filename to store the heartbeat engine's public destination in base64*/
-    private String _publicDestFile;
-    /** our destination */
-    private Destination _localDest;
-    /** who do we tell? */
-    private PingPongEventListener _listener;
-    /** how do we talk to the router */
-    private I2PSession _session;
-    /** object that receives our i2cp notifications from the session and tells us */
-    private I2PListener _i2pListener; /* UNUSED */
-
-    /** 
-     * This config property tells us where the private destination data for our 
-     * connection (or if it doesn't exist, where will we save it)
-     */
-    private static final String DEST_FILE_PROP = "privateDestinationFile";
-    /** by default, the private destination data is in "heartbeat.keys" */
-    private static final String DEST_FILE_DEFAULT = "heartbeat.keys";
-    /** where will we export the public destination in base 64? */
-    private static final String PUBLIC_DEST_FILE_PROP = "publicDestinationFile";
-    /** where will we export the public destination in base 64? */
-    private static final String PUBLIC_DEST_FILE_DEFAULT = "heartbeat.txt";
-    /** This config property defines where the I2P router is */
-    private static final String I2CP_HOST_PROP = "i2cpHost";
-    /** by default, the I2P host is "localhost" */
-    private static final String I2CP_HOST_DEFAULT = "localhost";
-    /** This config property defines the I2CP port on the router */
-    private static final String I2CP_PORT_PROP = "i2cpPort";
-    /** by default, the I2CP port is 7654 */
-    private static final int I2CP_PORT_DEFAULT = 7654;
-
-    /** This property defines how many hops we want in our tunnels. */
-    public static final String NUMHOPS_PROP = "numHops";
-    /** by default, use 2 hop tunnels */
-    public static final int NUMHOPS_DEFAULT = 2;
-
-    /**
-     * Constructs an I2PAdapter . . .
-     */
-    public I2PAdapter() {
-        _privateDestFile = null;
-        _publicDestFile = null;
-        _i2cpHost = null;
-        _i2cpPort = -1;
-        _localDest = null;
-        _listener = null;
-        _session = null;
-        _numHops = 0;
-    }
-
-    /**
-     * who are we?
-     * @return the destination (us)
-     */
-    public Destination getLocalDestination() {
-        return _localDest;
-    }
-
-    /** 
-     * who gets notified when we receive a ping or a pong? 
-     * @return the event listener who gets notified
-     */
-    public PingPongEventListener getListener() {
-        return _listener;
-    }
-
-    /**
-     * Sets who gets notified when we receive a ping or a pong
-     * @param listener the event listener to get notified
-     */
-    public void setListener(PingPongEventListener listener) {
-        _listener = listener;
-    }
-
-    /** 
-     * how many hops do we want in our tunnels?
-     * @return the number of hops
-     */
-    public int getNumHops() {
-        return _numHops;
-    }
-
-    /**
-     * are we connected?
-     * @return true or false . . .
-     */
-    public boolean getIsConnected() {
-        return _session != null;
-    }
-
-    /**
-     * Read in all of the config data
-     * @param props the properties to load from
-     */
-    void loadConfig(Properties props) {
-        String privDestFile = props.getProperty(DEST_FILE_PROP, DEST_FILE_DEFAULT);
-        String pubDestFile = props.getProperty(PUBLIC_DEST_FILE_PROP, PUBLIC_DEST_FILE_DEFAULT);
-        String host = props.getProperty(I2CP_HOST_PROP, I2CP_HOST_DEFAULT);
-        String port = props.getProperty(I2CP_PORT_PROP, "" + I2CP_PORT_DEFAULT);
-        String numHops = props.getProperty(NUMHOPS_PROP, "" + NUMHOPS_DEFAULT);
-
-        int portNum = -1;
-        try {
-            portNum = Integer.parseInt(port);
-        } catch (NumberFormatException nfe) {
-            if (_log.shouldLog(Log.WARN)) {
-                _log.warn("Invalid I2CP port specified [" + port + "]");
-            }
-            portNum = I2CP_PORT_DEFAULT;
-        }
-        int hops = -1;
-        try {
-            hops = Integer.parseInt(numHops);
-        } catch (NumberFormatException nfe) {
-            if (_log.shouldLog(Log.WARN)) {
-                _log.warn("Invalid # hops specified [" + numHops + "]");
-            }
-            hops = NUMHOPS_DEFAULT;
-        }
-
-        _numHops = hops;
-        _privateDestFile = privDestFile;
-        _publicDestFile = pubDestFile;
-        _i2cpHost = host;
-        _i2cpPort = portNum;
-    }
-
-    /**
-     * write out the config to the props
-     * @param props the properties to write to 
-     */
-    void storeConfig(Properties props) {
-        if (_privateDestFile != null) {
-            props.setProperty(DEST_FILE_PROP, _privateDestFile);
-        } else {
-            props.setProperty(DEST_FILE_PROP, DEST_FILE_DEFAULT);
-        }
-        
-        if (_publicDestFile != null) {
-            props.setProperty(PUBLIC_DEST_FILE_PROP, _publicDestFile);
-        } else {
-            props.setProperty(PUBLIC_DEST_FILE_PROP, PUBLIC_DEST_FILE_DEFAULT);
-        }
-
-        if (_i2cpHost != null) {
-            props.setProperty(I2CP_HOST_PROP, _i2cpHost);
-        } else {
-            props.setProperty(I2CP_HOST_PROP, I2CP_HOST_DEFAULT);
-        }
-
-        if (_i2cpPort > 0) {
-            props.setProperty(I2CP_PORT_PROP, "" + _i2cpPort);
-        } else {
-            props.setProperty(I2CP_PORT_PROP, "" + I2CP_PORT_DEFAULT);
-        }
-
-        props.setProperty(NUMHOPS_PROP, "" + _numHops);
-    }
-
-    private static final int TYPE_PING = 0;
-    private static final int TYPE_PONG = 1;
-
-    /** 
-     * send a ping message to the peer
-     *
-     * @param peer peer to ping
-     * @param seriesNum id used to keep track of multiple pings (of different size/frequency) to a peer
-     * @param now current time to be sent in the ping (so we can watch for it in the pong)
-     * @param size total message size to send
-     *
-     * @throws IllegalStateException if we are not connected to the router
-     */
-    public void sendPing(Destination peer, int seriesNum, long now, int size) {
-        if (_session == null) throw new IllegalStateException("Not connected to the router");
-        ByteArrayOutputStream baos = new ByteArrayOutputStream(size);
-        try {
-            _localDest.writeBytes(baos);
-            DataHelper.writeLong(baos, 2, seriesNum);
-            DataHelper.writeLong(baos, 1, TYPE_PING);
-            DataHelper.writeDate(baos, new Date(now));
-            int padding = size - baos.size();
-            byte paddingData[] = new byte[padding];
-            I2PAppContext.getGlobalContext().random().nextBytes(paddingData);
-            //Arrays.fill(paddingData, (byte) 0x2A);
-            DataHelper.writeLong(baos, 2, padding);
-            baos.write(paddingData);
-            boolean sent = _session.sendMessage(peer, baos.toByteArray());
-            if (!sent) {
-                if (_log.shouldLog(Log.ERROR)) {
-                    _log.error("Error sending the ping to " + peer.calculateHash().toBase64() + " for series "
-                               + seriesNum);
-                }
-            } else {
-                if (_log.shouldLog(Log.INFO)) {
-                    _log.info("Ping sent to " + peer.calculateHash().toBase64() + " for series " + seriesNum);
-                }
-            }
-        } catch (IOException ioe) {
-            if (_log.shouldLog(Log.ERROR)) {
-                _log.error("Error sending the ping", ioe);
-            }
-        } catch (DataFormatException dfe) {
-            if (_log.shouldLog(Log.ERROR)) {
-                _log.error("Error writing out the ping message", dfe);
-            }
-        } catch (I2PSessionException ise) {
-            if (_log.shouldLog(Log.ERROR)) {
-                _log.error("Error writing out the ping message", ise);
-            }
-        }
-    }
-
-    /** 
-     * send a pong message to the peer
-     *
-     * @param peer peer to pong
-     * @param seriesNum id given to us in the ping
-     * @param sentOn date the peer said they sent us the message
-     * @param data payload the peer sent us in the ping
-     *
-     * @throws IllegalStateException if we are not connected to the router
-     */
-    public void sendPong(Destination peer, int seriesNum, Date sentOn, byte data[]) {
-        if (_session == null) throw new IllegalStateException("Not connected to the router");
-        ByteArrayOutputStream baos = new ByteArrayOutputStream(data.length + 768);
-        try {
-            _localDest.writeBytes(baos);
-            DataHelper.writeLong(baos, 2, seriesNum);
-            DataHelper.writeLong(baos, 1, TYPE_PONG);
-            DataHelper.writeDate(baos, sentOn);
-            DataHelper.writeDate(baos, new Date(Clock.getInstance().now()));
-            DataHelper.writeLong(baos, 2, data.length);
-            baos.write(data);
-            boolean sent = _session.sendMessage(peer, baos.toByteArray());
-            if (!sent) {
-                if (_log.shouldLog(Log.ERROR)) {
-                    _log.error("Error sending the pong to " + peer.calculateHash().toBase64() + " for series "
-                               + seriesNum + " which was sent on " + sentOn);
-                }
-            } else {
-                if (_log.shouldLog(Log.INFO)) {
-                    _log.info("Pong sent to " + peer.calculateHash().toBase64() + " for series " + seriesNum
-                              + " which was sent on " + sentOn);
-                }
-            }
-        } catch (IOException ioe) {
-            if (_log.shouldLog(Log.ERROR)) {
-                _log.error("Error sending the ping", ioe);
-            }
-        } catch (DataFormatException dfe) {
-            if (_log.shouldLog(Log.ERROR)) {
-                _log.error("Error writing out the pong message", dfe);
-            }
-        } catch (I2PSessionException ise) {
-            if (_log.shouldLog(Log.ERROR)) {
-                _log.error("Error writing out the pong message", ise);
-            }
-        }
-    }
-
-    /**
-     * We've received this data from I2P - parse it into a ping or a pong 
-     * and notify accordingly
-     * @param data the data to handle
-     */
-    private void handleMessage(byte data[]) {
-        ByteArrayInputStream bais = new ByteArrayInputStream(data);
-        try {
-            Destination from = new Destination();
-            from.readBytes(bais);
-            int series = (int) DataHelper.readLong(bais, 2);
-            long type = DataHelper.readLong(bais, 1);
-            Date sentOn = DataHelper.readDate(bais);
-            Date receivedOn = null;
-            if (type == TYPE_PONG) {
-                receivedOn = DataHelper.readDate(bais);
-            }
-            int size = (int) DataHelper.readLong(bais, 2);
-            byte payload[] = new byte[size];
-            int read = DataHelper.read(bais, payload);
-            if (read != size) { throw new IOException("Malformed payload - read " + read + " instead of " + size); }
-
-            if (_listener == null) {
-                if (_log.shouldLog(Log.ERROR)) {
-                    _log.error("Listener isn't set, but we received a valid message of type " + type + " sent from "
-                               + from.calculateHash().toBase64());
-                }
-                return;
-            }
-
-            if (type == TYPE_PING) {
-                if (_log.shouldLog(Log.INFO)) {
-                    _log.info("Ping received from " + from.calculateHash().toBase64() + " on series " + series
-                              + " sent on " + sentOn + " containing " + size + " bytes");
-                }
-                _listener.receivePing(from, series, sentOn, payload);
-            } else if (type == TYPE_PONG) {
-                if (_log.shouldLog(Log.INFO)) {
-                    _log.info("Pong received from " + from.calculateHash().toBase64() + " on series " + series
-                              + " sent on " + sentOn + " with pong sent on " + receivedOn + " containing " + size
-                              + " bytes");
-                }
-                _listener.receivePong(from, series, sentOn, receivedOn, payload);
-            } else {
-                throw new IOException("Invalid message type " + type);
-            }
-
-        } catch (IOException ioe) {
-            if (_log.shouldLog(Log.ERROR)) {
-                _log.error("Error handling the message", ioe);
-            }
-        } catch (DataFormatException dfe) {
-            if (_log.shouldLog(Log.ERROR)) {
-                _log.error("Error parsing the message", dfe);
-            }
-        }
-    }
-
-    /** 
-     * connect to the I2P router and either authenticate ourselves with the 
-     * destination we're given, or create a new one and write that to the 
-     * destination file.
-     *
-     * @return true if we connect successfully, false otherwise
-     */
-    boolean connect() {
-        I2PClient client = I2PClientFactory.createClient();
-        Destination us = null;
-        File destFile = new File(_privateDestFile);
-        us = verifyDestination(client, destFile);
-        if (us == null) return false;
-
-        // if we're here, we got a destination.  lets connect
-        FileInputStream fin = null;
-        try {
-            fin = new FileInputStream(destFile);
-            Properties options = getOptions();
-            I2PSession session = client.createSession(fin, options);
-            I2PListener lsnr = new I2PListener();
-            session.setSessionListener(lsnr);
-            session.connect();
-            _localDest = session.getMyDestination();
-            if (_log.shouldLog(Log.INFO)) {
-                _log.info("I2CP Session created and connected as " + _localDest.calculateHash().toBase64());
-            }
-            _session = session;
-            _i2pListener = lsnr;
-        } catch (I2PSessionException ise) {
-            if (_log.shouldLog(Log.ERROR)) {
-                _log.error("Error connecting", ise);
-            }
-            return false;
-        } catch (IOException ioe) {
-            if (_log.shouldLog(Log.ERROR)) {
-                _log.error("Error loading the destionation", ioe);
-            }
-            return false;
-        } finally {
-            if (fin != null) try {
-                fin.close();
-            } catch (IOException ioe) {
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * load, verify, or create a destination 
-     *
-     * @param client the client
-     * @param destFile the file holding the destination
-     * @return the destination loaded, or null if there was an error
-     */
-    private Destination verifyDestination(I2PClient client, File destFile) {
-        Destination us = null;
-        FileInputStream fin = null;
-        if (destFile.exists()) {
-            try {
-                fin = new FileInputStream(destFile);
-                us = new Destination();
-                us.readBytes(fin);
-                if (_log.shouldLog(Log.INFO)) {
-                    _log.info("Existing destination loaded: [" + us.toBase64() + "]");
-                }
-                
-                FileOutputStream fos = null;
-                try {
-                    fos = new FileOutputStream(_publicDestFile);
-                    fos.write(us.toBase64().getBytes());
-                    fos.flush();
-                } catch (IOException fioe) {
-                    _log.error("Error writing out the plain destination to [" + _publicDestFile + "]", fioe);
-                } finally {
-                    if (fos != null) try { fos.close(); } catch (IOException fioe) {}
-                }
-                
-            } catch (IOException ioe) {
-                if (fin != null) try {
-                    fin.close();
-                } catch (IOException ioe2) {
-                }
-                fin = null;
-                destFile.delete();
-                us = null;
-            } catch (DataFormatException dfe) {
-                if (fin != null) try {
-                    fin.close();
-                } catch (IOException ioe2) {
-                }
-                fin = null;
-                destFile.delete();
-                us = null;
-            } finally {
-                if (fin != null) try {
-                    fin.close();
-                } catch (IOException ioe2) {
-                }
-                fin = null;
-            }
-        }
-
-        if (us == null) {
-            // need to create a new one
-            FileOutputStream fos = null;
-            try {
-                fos = new FileOutputStream(destFile);
-                us = client.createDestination(fos);
-                if (_log.shouldLog(Log.INFO)) {
-                    _log.info("New destination created: [" + us.toBase64() + "]");
-                }
-                fos.close();
-                
-                try {
-                    fos = new FileOutputStream(_publicDestFile);
-                    fos.write(us.toBase64().getBytes());
-                    fos.flush();
-                } catch (IOException fioe) {
-                    _log.error("Error writing out the plain destination to [" + _publicDestFile + "]", fioe);
-                } finally {
-                    if (fos != null) try { fos.close(); } catch (IOException fioe) {}
-                    fos = null;
-                }
-                
-            } catch (IOException ioe) {
-                if (_log.shouldLog(Log.ERROR)) {
-                    _log.error("Error writing out the destination keys being created", ioe);
-                }
-                return null;
-            } catch (I2PException ie) {
-                if (_log.shouldLog(Log.ERROR)) {
-                    _log.error("Error creating the destination", ie);
-                }
-                return null;
-            } finally {
-                if (fos != null) try {
-                    fos.close();
-                } catch (IOException ioe) {
-                }
-            }
-        }
-        return us;
-    }
-
-    /**
-     * I2PSession connect options
-     * @return the options as Properties
-     */
-    private Properties getOptions() {
-        Properties props = new Properties();
-        // this should be BEST_EFFORT, but i'm too lazy to update the code to handle tracking 
-        // sessionTags and sessionKeys, marking them as delivered on pong.
-        props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_GUARANTEED);
-        props.setProperty(I2PClient.PROP_TCP_HOST, _i2cpHost);
-        props.setProperty(I2PClient.PROP_TCP_PORT, _i2cpPort + "");
-        props.setProperty("tunnels.depthInbound", "" + _numHops);
-        props.setProperty("tunnels.depthOutbound", "" + _numHops);
-        return props;
-    }
-
-    /** disconnect from the I2P router */
-    void disconnect() {
-        if (_session != null) {
-            try {
-                _session.destroySession();
-            } catch (I2PSessionException ise) {
-                if (_log.shouldLog(Log.ERROR)) {
-                    _log.error("Error destroying the session", ise);
-                }
-            }
-            _session = null;
-        }
-    }
-
-    /**
-     * Defines an event notification system for receiving pings and pongs
-     * 
-     */
-    public interface PingPongEventListener {
-        /** 
-         * receive a ping message from the peer
-         *
-         * @param from peer that sent us the ping
-         * @param seriesNum id the peer sent us in the ping
-         * @param sentOn date the peer said they sent us the message
-         * @param data payload from the ping
-         */
-        void receivePing(Destination from, int seriesNum, Date sentOn, byte data[]);
-
-        /** 
-         * receive a pong message from the peer
-         *
-         * @param from peer that sent us the pong
-         * @param seriesNum id the peer sent us in the pong (that we sent them in the ping)
-         * @param sentOn when we sent out the ping
-         * @param replyOn when they sent out the pong
-         * @param data payload from the ping/pong
-         */
-        void receivePong(Destination from, int seriesNum, Date sentOn, Date replyOn, byte data[]);
-    }
-
-    /**
-     * Receive data from the session and pass it along to handleMessage for parsing/dispersal
-     *
-     */
-    private class I2PListener implements I2PSessionListener {
-
-        /* (non-Javadoc)
-         * @see net.i2p.client.I2PSessionListener#disconnected(net.i2p.client.I2PSession)
-         */
-        public void disconnected(I2PSession session) {
-            if (_log.shouldLog(Log.ERROR)) {
-                _log.error("Session disconnected");
-            }
-            disconnect();
-        }
-
-        /* (non-Javadoc)
-         * @see net.i2p.client.I2PSessionListener#errorOccurred(net.i2p.client.I2PSession, java.lang.String, java.lang.Throwable)
-         */
-        public void errorOccurred(I2PSession session, String message, Throwable error) {
-            if (_log.shouldLog(Log.ERROR)) _log.error("Error occurred: " + message, error);
-        }
-
-        /* (non-Javadoc)
-         * @see net.i2p.client.I2PSessionListener#reportAbuse(net.i2p.client.I2PSession, int)
-         */
-        public void reportAbuse(I2PSession session, int severity) {
-            if (_log.shouldLog(Log.ERROR)) _log.error("Abuse reported with severity " + String.valueOf(severity));
-        }
-
-        /* (non-Javadoc)
-         * @see net.i2p.client.I2PSessionListener#messageAvailable(net.i2p.client.I2PSession, int, long)
-         */
-        public void messageAvailable(I2PSession session, int msgId, long size) {
-            try {
-                byte data[] = session.receiveMessage(msgId);
-                handleMessage(data);
-            } catch (I2PSessionException ise) {
-                if (_log.shouldLog(Log.ERROR)) _log.error("Error receiving the message", ise);
-                disconnect();
-            }
-        }
-    }
-}
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/PeerData.java b/apps/heartbeat/java/src/net/i2p/heartbeat/PeerData.java
deleted file mode 100644
index 6d9e93fb38..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/PeerData.java
+++ /dev/null
@@ -1,412 +0,0 @@
-package net.i2p.heartbeat;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import net.i2p.stat.Rate;
-import net.i2p.stat.RateStat;
-import net.i2p.util.Clock;
-import net.i2p.util.Log;
-
-/**
- * Contain the current window of data for a particular series of ping/pong stats 
- * sent to a peer.  This should be periodically kept clean by calling cleanup()
- * to timeout expired pings and to drop data outside the window.
- *
- */
-public class PeerData {
-    private final static Log _log = new Log(PeerData.class);
-    /** peer / sequence / config in this data series */
-    private ClientConfig _peer;
-    /** date sent (Long) to EventDataPoint containing the datapoints sent in the current period */
-    private Map _dataPoints;
-    /** date sent (Long) to EventDataPoint containing pings that haven't yet timed out or been ponged */
-    private TreeMap _pendingPings;
-    private long _sessionStart;
-    private long _lifetimeSent;
-    private long _lifetimeReceived;
-    /** rate averaging the time to send over a variety of periods */
-    private RateStat _sendRate;
-    /** rate averaging the time to receive over a variety of periods */
-    private RateStat _receiveRate;
-    /** rate averaging the frequency of lost messages over a variety of periods */
-    private RateStat _lostRate;
-
-    /** how long we wait before timing out pending pings (30 seconds) */
-    private static final long TIMEOUT_PERIOD = 60 * 1000;
-
-    /** synchronize on this when updating _dataPoints or _pendingPings */
-    private Object _updateLock = new Object();
-
-    /**
-     * Creates a PeerData . . .
-     * @param config configuration to load from
-     */
-    public PeerData(ClientConfig config) {
-        _peer = config;
-        _dataPoints = new TreeMap();
-        _pendingPings = new TreeMap();
-        _sessionStart = Clock.getInstance().now();
-        _lifetimeSent = 0;
-        _lifetimeReceived = 0;
-        _sendRate = new RateStat("sendRate", "How long it takes to send", "peer",
-                                 getPeriods(config.getAveragePeriods()));
-        _receiveRate = new RateStat("receiveRate", "How long it takes to receive", "peer",
-                                    getPeriods(config.getAveragePeriods()));
-        _lostRate = new RateStat("lostRate", "How frequently we lose messages", "peer",
-                                 getPeriods(config.getAveragePeriods()));
-    }
-
-    /**
-     * turn the periods (# minutes) into rate periods (# milliseconds)
-     * @param periods (in minutes)
-     * @return an array of periods (in milliseconds)
-     */
-    private static long[] getPeriods(int periods[]) {
-        long rv[] = null;
-        if (periods == null) periods = new int[0];
-        rv = new long[periods.length];
-        for (int i = 0; i < periods.length; i++)
-            rv[i] = (long) periods[i] * 60 * 1000; // they're in minutes
-        Arrays.sort(rv);
-        return rv;
-    }
-
-    /** 
-     * how many pings are still outstanding?
-     * @return the number of pings outstanding
-     */
-    public int getPendingCount() {
-        synchronized (_updateLock) {
-            return _pendingPings.size();
-        }
-    }
-
-    /**
-     * how many data points are available in the current window?
-     * @return the number of datapoints available 
-     */
-    public int getDataPointCount() {
-        synchronized (_updateLock) {
-            return _dataPoints.size();
-        }
-    }
-
-    /**
-     * when did this test begin?
-     * @return when the test began  
-     */
-    public long getSessionStart() { return _sessionStart; }
-    
-    /**
-     * sets when the test began
-     * @param when when it began
-     */
-    public void setSessionStart(long when) { _sessionStart = when; }
-
-    /**
-     * how many pings have we sent for this test?
-     * @return the number of pings sent
-     */
-    public long getLifetimeSent() { return _lifetimeSent; }
-
-    /**
-     * how many pongs have we received for this test?
-     * @return the number of pings received
-     */
-    public long getLifetimeReceived() { return _lifetimeReceived; }
-
-    /**
-     * @return the client configuration
-     */
-    public ClientConfig getConfig() {
-        return _peer;
-    }
-
-    /** 
-     * What periods are we averaging the data over (in minutes)?
-     * @return the periods as an array of ints (in minutes)
-     */
-    public int[] getAveragePeriods() {
-        return (_peer.getAveragePeriods() != null ? _peer.getAveragePeriods() : new int[0]);
-    }
-
-    /** 
-     * average time to send over the given period.
-     *
-     * @param period number of minutes to retrieve the average for
-     * @return milliseconds average, or -1 if we dont track that period
-     */
-    public double getAverageSendTime(int period) {
-        return getAverage(_sendRate, period);
-    }
-
-    /** 
-     * average time to receive over the given period.
-     *
-     * @param period number of minutes to retrieve the average for
-     * @return milliseconds average, or -1 if we dont track that period
-     */
-    public double getAverageReceiveTime(int period) {
-        return getAverage(_receiveRate, period);
-    }
-
-    /** 
-     * number of lost messages over the given period.
-     *
-     * @param period number of minutes to retrieve the average for
-     * @return number of lost messages in the period, or -1 if we dont track that period
-     */
-    public double getLostMessages(int period) {
-        Rate rate = _lostRate.getRate(period * 60 * 1000);
-        if (rate == null) return -1;
-        return rate.getCurrentTotalValue();
-    }
-
-    private double getAverage(RateStat stat, int period) {
-        Rate rate = stat.getRate(period * 60 * 1000);
-        if (rate == null) return -1;
-        return rate.getAverageValue();
-    }
-
-    /**
-     * Return an ordered list of data points in the current window (after doing a cleanup)
-     *
-     * @return list of EventDataPoint objects
-     */
-    public List getDataPoints() {
-        cleanup();
-        synchronized (_updateLock) {
-            return new ArrayList(_dataPoints.values());
-        }
-    }
-
-    /**
-     * We have sent the peer a ping on this series (using the send time as given)
-     * @param dateSent when the ping was sent
-     */
-    public void addPing(long dateSent) {
-        EventDataPoint sent = new EventDataPoint(dateSent);
-        synchronized (_updateLock) {
-            _pendingPings.put(new Long(dateSent), sent);
-        }
-        _lifetimeSent++;
-    }
-
-    /** 
-     * we have received a pong from the peer on this series 
-     * 
-     * @param dateSent when we sent the ping
-     * @param pongSent when the peer received the ping and sent the pong
-     */
-    public void pongReceived(long dateSent, long pongSent) {
-        long now = Clock.getInstance().now();
-        synchronized (_updateLock) {
-            if (_pendingPings.size() <= 0) {
-                _log.warn("Pong received (sent at " + dateSent + ", " + (now-dateSent) 
-                          + "ms ago, pong delay " + (pongSent-dateSent) + "ms, pong receive delay "
-                          + (now-pongSent) + "ms)");
-                return;
-            }
-            Long first = (Long)_pendingPings.firstKey();
-            EventDataPoint data = (EventDataPoint)_pendingPings.remove(new Long(dateSent));
-            
-            if (data != null) {
-                data.setPongReceived(now);
-                data.setPongSent(pongSent);
-                data.setWasPonged(true);
-                locked_addDataPoint(data);
-                
-                if (dateSent != first.longValue()) {
-                    _log.error("Out of order delivery: received " + dateSent 
-                               + " but the first pending is " + first.longValue()
-                               + " (delta " + (dateSent - first.longValue()) + ")");
-                } else {
-                    _log.info("In order delivery for " + dateSent + " in ping " 
-                               + _peer.getComment());
-                }
-            } else {
-                _log.warn("Pong received, but no matching ping?  ping sent at = " + dateSent);
-                return;
-            }
-        }
-        _sendRate.addData(pongSent - dateSent, 0);
-        _receiveRate.addData(now - pongSent, 0);
-        _lifetimeReceived++;
-    }
-    
-    protected void addDataPoint(EventDataPoint data) {
-        synchronized (_updateLock) {
-            locked_addDataPoint(data);
-        }
-    }
-    
-    private void locked_addDataPoint(EventDataPoint data) {
-        Object val = _dataPoints.put(new Long(data.getPingSent()), data);
-        if (val != null) {
-            if (_log.shouldLog(Log.WARN))
-                _log.warn("Duplicate data point received: " + data);
-        }
-    }
-
-    /** 
-     * drop all datapoints outside the window we're watching, and timeout all
-     * pending pings not ponged in the TIMEOUT_PERIOD, both updating the lost message
-     * rate and coallescing all of the rates.
-     *
-     */
-    public void cleanup() {
-        long dropBefore = Clock.getInstance().now() - _peer.getStatDuration() * 60 * 1000;
-        long timeoutBefore = Clock.getInstance().now() - TIMEOUT_PERIOD;
-        long numDropped = 0;
-        long numTimedOut = 0;
-
-        synchronized (_updateLock) {
-            numDropped = locked_dropExpired(dropBefore);
-            numTimedOut = locked_timeoutPending(timeoutBefore);
-        }
-
-        _lostRate.addData(numTimedOut, 0);
-
-        _receiveRate.coalesceStats();
-        _sendRate.coalesceStats();
-        _lostRate.coalesceStats();
-
-        if (_log.shouldLog(Log.DEBUG))
-            _log.debug("Peer data cleaned up " + numTimedOut + " timed out pings and removed " + numDropped
-                       + " old entries");
-    }
-    
-    /**
-     * Drop all data points that are already too old for us to be interested in
-     *
-     * @param when the earliest ping send time we care about
-     * @return number of data points dropped
-     */
-    private int locked_dropExpired(long when) {
-        Set toDrop = new HashSet(4);
-        // drop the failed and really old
-        for (Iterator iter = _dataPoints.keySet().iterator(); iter.hasNext(); ) {
-            Long pingTime = (Long)iter.next();
-            if (pingTime.longValue() < when)
-                toDrop.add(pingTime);
-        }
-        for (Iterator iter = toDrop.iterator(); iter.hasNext(); ) {
-            _dataPoints.remove(iter.next());
-        }
-        return toDrop.size();
-    }
-    
-    /** 
-     * timeout and remove all pings that were sent before the given time, 
-     * moving them from the set of pending pings to the set of data points
-     *
-     * @param when the earliest ping send time we care about
-     * @return number of pings timed out
-     */
-    private int locked_timeoutPending(long when) {
-        Set toDrop = new HashSet(4);
-        for (Iterator iter = _pendingPings.keySet().iterator(); iter.hasNext(); ) {
-            Long pingTime = (Long)iter.next();
-            if (pingTime.longValue() < when) {
-                toDrop.add(pingTime);
-                EventDataPoint point = (EventDataPoint)_pendingPings.get(pingTime);
-                point.setWasPonged(false);
-                locked_addDataPoint(point);
-            }
-        }
-        for (Iterator iter = toDrop.iterator(); iter.hasNext(); ) {
-            _pendingPings.remove(iter.next());
-        }
-        return toDrop.size();
-    }
-
-    /** actual data point for the peer */
-    public class EventDataPoint {
-        private boolean _wasPonged;
-        private long _pingSent;
-        private long _pongSent;
-        private long _pongReceived;
-
-        /**
-         * Creates an EventDataPoint
-         */
-        public EventDataPoint() { this(-1); }
-
-        /**
-         * Creates an EventDataPoint with pingtime associated with it =)
-         * @param pingSentOn the time a ping was sent
-         */
-        public EventDataPoint(long pingSentOn) {
-            _wasPonged = false;
-            _pingSent = pingSentOn;
-            _pongSent = -1;
-            _pongReceived = -1;
-        }
-
-        /** 
-         * when did we send this ping?
-         * @return the time the ping was sent
-         */
-        public long getPingSent() { return _pingSent; }
-        
-        /**
-         * sets when we sent this ping
-         * @param when when we sent the ping
-         */
-        public void setPingSent(long when) { _pingSent = when; }
-
-        /**
-         * when did the peer receive the ping?
-         * @return the time the ping was receieved 
-         */
-        public long getPongSent() {
-            return _pongSent;
-        }
-
-        /**
-         * Set the time the peer received the ping
-         * @param when the time to set
-         */
-        public void setPongSent(long when) {
-            _pongSent = when;
-        }
-
-        /** 
-         * when did we receive the peer's pong?
-         * @return the time we receieved the pong
-         */
-        public long getPongReceived() {
-            return _pongReceived;
-        }
-
-        /**
-         * Set the time the peer's pong was receieved
-         * @param when the time to set
-         */
-        public void setPongReceived(long when) {
-            _pongReceived = when;
-        }
-
-        /** 
-         * did the peer reply in time? 
-         * @return true or false, whether we got a reply in time */
-        public boolean getWasPonged() {
-            return _wasPonged;
-        }
-
-        /**
-         * Set whether we receieved the peer's reply in time
-         * @param pong true or false
-         */
-        public void setWasPonged(boolean pong) {
-            _wasPonged = pong;
-        }
-    }
-}
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/PeerDataWriter.java b/apps/heartbeat/java/src/net/i2p/heartbeat/PeerDataWriter.java
deleted file mode 100644
index ad76fd1cee..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/PeerDataWriter.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package net.i2p.heartbeat;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.Locale;
-
-import net.i2p.util.Clock;
-import net.i2p.util.Log;
-
-/**
- * Actually write out the stats for peer test
- *
- */
-public class PeerDataWriter {
-    private final static Log _log = new Log(PeerDataWriter.class);
-
-    /** 
-     * persist the peer state to the location specified in the peer config
-     *
-     * @param data the peer data to persist
-     * @return true if it was persisted correctly, false on error
-     */
-    public boolean persist(PeerData data) {
-        String filename = data.getConfig().getStatFile();
-        File statFile = new File(filename);
-        FileOutputStream fos = null;
-        try {
-            fos = new FileOutputStream(statFile);
-            persist(data, fos);
-        } catch (IOException ioe) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Error persisting the peer data for "
-                           + data.getConfig().getPeer().calculateHash().toBase64(), ioe);
-            return false;
-        } finally {
-            if (fos != null) try {
-                fos.close();
-            } catch (IOException ioe) {
-            }
-        }
-        return true;
-    }
-    
-    /**
-     * persists the peer state to the output stream
-     * @param data the peer data to persist
-     * @param out where to persist the data
-     * @return true if it was persisted correctly [always (as implemented)], false on error
-     * @throws IOException
-     */
-    public boolean persist(PeerData data, OutputStream out) throws IOException {
-        String header = getHeader(data);
-
-        out.write(header.getBytes());
-        out.write("#action\tstatus\tdate and time sent   \tsendMs\treplyMs\troundTrip\n".getBytes());
-        for (Iterator iter = data.getDataPoints().iterator(); iter.hasNext();) {
-            PeerData.EventDataPoint point = (PeerData.EventDataPoint) iter.next();
-            String line = getEvent(point);
-            out.write(line.getBytes());
-        }
-        return true;
-    }
-
-    private String getHeader(PeerData data) {
-        StringBuffer buf = new StringBuffer(1024);
-        buf.append("peer         \t").append(data.getConfig().getPeer().calculateHash().toBase64()).append('\n');
-        buf.append("local        \t").append(data.getConfig().getUs().calculateHash().toBase64()).append('\n');
-        buf.append("peerDest     \t").append(data.getConfig().getPeer().toBase64()).append('\n');
-        buf.append("localDest    \t").append(data.getConfig().getUs().toBase64()).append('\n');
-        buf.append("numTunnelHops\t").append(data.getConfig().getNumHops()).append('\n');
-        buf.append("comment      \t").append(data.getConfig().getComment()).append('\n');
-        buf.append("sendFrequency\t").append(data.getConfig().getSendFrequency()).append('\n');
-        buf.append("sendSize     \t").append(data.getConfig().getSendSize()).append('\n');
-        buf.append("sessionStart \t").append(getTime(data.getSessionStart())).append('\n');
-        buf.append("currentTime  \t").append(getTime(Clock.getInstance().now())).append('\n');
-        buf.append("numPending   \t").append(data.getPendingCount()).append('\n');
-        buf.append("lifetimeSent \t").append(data.getLifetimeSent()).append('\n');
-        buf.append("lifetimeRecv \t").append(data.getLifetimeReceived()).append('\n');
-        int periods[] = data.getAveragePeriods();
-        buf.append("#averages\tminutes\tsendMs\trecvMs\tnumLost\troundTrip\n");
-        for (int i = 0; i < periods.length; i++) {
-            buf.append("periodAverage\t").append(periods[i]).append('\t');
-            buf.append(getNum(data.getAverageSendTime(periods[i]))).append('\t');
-            buf.append(getNum(data.getAverageReceiveTime(periods[i]))).append('\t');
-            buf.append(getNum(data.getLostMessages(periods[i]))).append('\t');
-            double rtt = data.getAverageSendTime(periods[i]) 
-                         + data.getAverageReceiveTime(periods[i]);
-            buf.append(getNum(rtt)).append('\n');
-        }
-        return buf.toString();
-    }
-
-    private String getEvent(PeerData.EventDataPoint point) {
-        StringBuffer buf = new StringBuffer(128);
-        buf.append("EVENT\t");
-        if (point.getWasPonged())
-            buf.append("OK\t");
-        else
-            buf.append("LOST\t");
-        buf.append(getTime(point.getPingSent())).append('\t');
-        if (point.getWasPonged()) {
-            buf.append(point.getPongSent() - point.getPingSent()).append('\t');
-            buf.append(point.getPongReceived() - point.getPongSent()).append('\t');
-            buf.append(point.getPongReceived() - point.getPingSent()).append('\t');
-        }
-        buf.append('\n');
-        return buf.toString();
-    }
-
-    private final SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd.HH:mm:ss.SSS", Locale.UK);
-
-    /**
-     * Converts a time (long) to text
-     * @param when the time to convert
-     * @return the textual representation
-     */
-    public String getTime(long when) {
-        synchronized (_fmt) {
-            return _fmt.format(new Date(when));
-        }
-    }
-
-    private final DecimalFormat _numFmt = new DecimalFormat("#0", new DecimalFormatSymbols(Locale.UK));
-
-    /**
-     * Converts a number (double) to text
-     * @param val the number to convert
-     * @return the textual representation
-     */
-    public String getNum(double val) {
-        synchronized (_numFmt) {
-            return _numFmt.format(val);
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatControlPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatControlPane.java
deleted file mode 100644
index d281447313..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatControlPane.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTabbedPane;
-
-import net.i2p.util.Log;
-
-/**
- * Render the control widgets (refresh/load/snapshot and the 
- * tabbed panel with the plot config data)
- *
- */
-class HeartbeatControlPane extends JPanel {
-    private final static Log _log = new Log(HeartbeatControlPane.class);
-    private HeartbeatMonitorGUI _gui;
-    private JTabbedPane _configPane;
-    private final static Color WHITE = new Color(255, 255, 255);
-    private final static Color LIGHT_BLUE = new Color(180, 180, 255); /* UNUSED */
-    private final static Color BLACK = new Color(0, 0, 0);
-    private Color _background = WHITE;
-    private Color _foreground = BLACK;
-        
-    /**
-     * Constructs a control panel onto the gui
-     * @param gui the gui the panel is associated with
-     */
-    public HeartbeatControlPane(HeartbeatMonitorGUI gui) {
-        _gui = gui;
-        initializeComponents();
-    }
-    
-    /**
-     * Adds a test to the panel
-     * @param config the configuration for the test
-     */
-    public void addTest(PeerPlotConfig config) {
-        _configPane.addTab(config.getTitle(), null, new JScrollPane(new PeerPlotConfigPane(config, this)), config.getSummary());
-        _configPane.setBackgroundAt(_configPane.getTabCount()-1, _background);
-        _configPane.setForegroundAt(_configPane.getTabCount()-1, _foreground);
-        _gui.pack();
-    }
-    
-    /**
-     * Removes a test from the panel
-     * @param config the configuration for the test
-     */
-    public void removeTest(PeerPlotConfig config) {
-        _gui.getMonitor().getState().removeTest(config);
-        int index = _configPane.indexOfTab(config.getTitle());
-        if (index >= 0)
-            _configPane.removeTabAt(index);
-    }
-    
-    /**
-     * Callback: when tests have changed
-     */
-    public void testsUpdated() {
-        List knownNames = new ArrayList(8);
-        for (int i = 0; i < _gui.getMonitor().getState().getTestCount(); i++) {
-            PeerPlotState state = _gui.getMonitor().getState().getTest(i);
-            String title = state.getPlotConfig().getTitle();
-            knownNames.add(state.getPlotConfig().getTitle());
-            if (_configPane.indexOfTab(title) >= 0) {
-                _log.debug("We already know about [" + title + "]");
-            } else {
-                _log.info("The test [" + title + "] is new to us");
-                PeerPlotConfigPane pane = new PeerPlotConfigPane(state.getPlotConfig(), this);
-                _configPane.addTab(state.getPlotConfig().getTitle(), null, new JScrollPane(pane), state.getPlotConfig().getSummary());
-                _configPane.setBackgroundAt(_configPane.getTabCount()-1, _background);
-                _configPane.setForegroundAt(_configPane.getTabCount()-1, _foreground);
-            }
-        }
-        List toRemove = new ArrayList(4);
-        for (int i = 0; i < _configPane.getTabCount(); i++) {
-            if (knownNames.contains(_configPane.getTitleAt(i))) {
-                // noop
-            } else {
-                toRemove.add(_configPane.getTitleAt(i));
-            }
-        }
-        for (int i = 0; i < toRemove.size(); i++) {
-            String title = (String)toRemove.get(i);
-            _log.info("Removing test [" + title + "]");
-            _configPane.removeTabAt(_configPane.indexOfTab(title));
-        }
-    }
-    
-    private void initializeComponents() {
-        if (_gui != null)
-            setBackground(_gui.getBackground());
-        else
-            setBackground(_background);
-        setLayout(new BorderLayout());
-        HeartbeatMonitorCommandBar bar = new HeartbeatMonitorCommandBar(_gui);
-        bar.setBackground(getBackground());
-        add(bar, BorderLayout.NORTH);
-        _configPane = new JTabbedPane(JTabbedPane.LEFT);
-        _configPane.setBackground(_background);
-        //add(_configPane, BorderLayout.CENTER);
-        add(_configPane, BorderLayout.SOUTH);
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitor.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitor.java
deleted file mode 100644
index 827d93ef6d..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitor.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import net.i2p.util.I2PThread;
-import net.i2p.util.Log;
-
-/**
- * The HeartbeatMonitor, complete with main()!  Act now, and it's only 5 easy
- * payments of $19.95 (plus shipping and handling)!  You heard me, only _5_
- * easy payments of $19.95 (plus shipping and handling)! <p />
- * 
- * (fine print:  something about some states in the US requiring the addition
- * of sales tax... or something) <p />
- * 
- * (finer print:  Satan owns you.  Deal with it.) <p />
- *
- * (even finer print: usage: <code>HeartbeatMonitor [configFilename]</code>)
- */
-public class HeartbeatMonitor implements PeerPlotStateFetcher.FetchStateReceptor, PeerPlotConfig.UpdateListener {
-    private final static Log _log = new Log(HeartbeatMonitor.class);
-    private HeartbeatMonitorState _state;
-    private HeartbeatMonitorGUI _gui;
-    
-    /**
-     * Delegating constructor.
-     * @see HeartbeatMonitor#HeartbeatMonitor(String)
-     */
-    public HeartbeatMonitor() { this(null); }
-    
-    /**
-     * Creates a HeartbeatMonitor . . .
-     * @param configFilename the configuration file to read from
-     */
-    public HeartbeatMonitor(String configFilename) {
-        _state = new HeartbeatMonitorState(configFilename);
-        _gui = new HeartbeatMonitorGUI(this);
-    }
-    
-    /**
-     * Starts the game rollin'
-     */
-    public void runMonitor() {
-        loadConfig();
-        I2PThread t = new I2PThread(new HeartbeatMonitorRunner(this));
-        t.setName("HeartbeatMonitor");
-        t.setDaemon(false);
-        t.start();
-        _log.debug("Monitor started");
-    }
-    
-    /**
-     * give us all the data/config available 
-     * @return the current state (data/config)
-     */
-    HeartbeatMonitorState getState() {
-        return _state;
-    }
-    
-    /** for all of the peer tests being monitored, refetch the data and rerender */
-    void refetchData() {
-        _log.debug("Refetching data");
-        for (int i = 0; i < _state.getTestCount(); i++)
-            PeerPlotStateFetcher.fetchPeerPlotState(this, _state.getTest(i));
-    }
-    
-    /** (re)load the config defining what peer tests we are monitoring (and how to render) */
-    void loadConfig() {
-        //for (int i = 0; i < 10; i++) {
-        //    load("fake" + i);
-        //}
-    }
-    
-    /**
-     * Loads config data
-     * @param location the name of the location to load data from
-     */
-    public void load(String location) {
-        PeerPlotConfig cfg = new PeerPlotConfig(location);
-        cfg.addListener(this);
-        PeerPlotState state = new PeerPlotState(cfg);
-        PeerPlotStateFetcher.fetchPeerPlotState(this, state);
-    }
-    
-    /* (non-Javadoc)
-     * @see PeerPlotStateFetcher.FetchStateReceptor#peerPlotStateFetched
-     */
-    public synchronized void peerPlotStateFetched(PeerPlotState state) {
-        _state.addTest(state);
-        _gui.stateUpdated();
-    }
-    
-    /**
-     *  store the config defining what peer tests we are monitoring (and how to render) 
-     */
-    void storeConfig() {}
-    
-    /**
-     * And now, the main function, the one you've all been waiting for! . . .
-     * @param args da args.  Should take 1, which is the location to load config data from
-     */
-    public static void main(String args[]) {
-        Thread.currentThread().setName("HeartbeatMonitor.main");
-        if (args.length == 1)
-            new HeartbeatMonitor(args[0]).runMonitor();
-        else
-            new HeartbeatMonitor().runMonitor();
-    }
-    
-    /**
-     * Called when the config is updated
-     * @param config the updated config
-     */
-    public void configUpdated(PeerPlotConfig config) { 
-        _log.debug("Config updated, revamping the gui");
-        _gui.stateUpdated(); 
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorCommandBar.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorCommandBar.java
deleted file mode 100644
index c95aa68a38..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorCommandBar.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JFileChooser;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-
-class HeartbeatMonitorCommandBar extends JPanel {
-    private HeartbeatMonitorGUI _gui;
-    private JComboBox _refreshRate;
-    private JTextField _location;
-    
-    /**
-     * Constructs a command bar onto the gui
-     * @param gui the gui the command bar is associated with
-     */
-    public HeartbeatMonitorCommandBar(HeartbeatMonitorGUI gui) {
-        _gui = gui;
-        initializeComponents();
-    }
-    
-    private void refreshChanged(ItemEvent evt) {}
-    private void loadCalled() {
-        _gui.getMonitor().load(_location.getText());
-    }
-    
-    private void browseCalled() {
-        JFileChooser chooser = new JFileChooser(_location.getText());
-        chooser.setBackground(_gui.getBackground());
-        chooser.setMultiSelectionEnabled(false);
-        int rv = chooser.showDialog(this, "Load");
-        if (rv == JFileChooser.APPROVE_OPTION) 
-            _gui.getMonitor().load(chooser.getSelectedFile().getAbsolutePath());
-    }
-    
-    private void initializeComponents() {
-        _refreshRate = new JComboBox(new DefaultComboBoxModel(new Object[] {"10 second refresh", "30 second refresh", "1 minute refresh", "5 minute refresh"}));
-        _refreshRate.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent evt) { refreshChanged(evt); } });
-        _refreshRate.setEnabled(false);
-        _refreshRate.setBackground(_gui.getBackground());
-        //add(_refreshRate);
-        JLabel loadLabel = new JLabel("Load from: ");
-        loadLabel.setBackground(_gui.getBackground());
-        add(loadLabel);
-        _location = new JTextField(20);
-        _location.setToolTipText("Either specify a local filename or a fully qualified URL");
-        _location.setBackground(_gui.getBackground());
-        add(_location);
-        JButton browse = new JButton("Browse...");
-        browse.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { browseCalled(); } });
-        browse.setBackground(_gui.getBackground());
-        add(browse);
-        JButton load = new JButton("Load");
-        load.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadCalled(); } });
-        load.setBackground(_gui.getBackground());
-        add(load);
-        setBackground(_gui.getBackground());
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorGUI.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorGUI.java
deleted file mode 100644
index 27786b1ff4..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorGUI.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.JFrame;
-import javax.swing.JMenu;
-import javax.swing.JMenuBar;
-import javax.swing.JMenuItem;
-import javax.swing.JScrollPane;
-
-class HeartbeatMonitorGUI extends JFrame {
-    private HeartbeatMonitor _monitor;
-    private HeartbeatPlotPane _plotPane;
-    private HeartbeatControlPane _controlPane;
-    private final static Color WHITE = new Color(255, 255, 255);
-    private Color _background = WHITE;
-    
-    /**
-     * Creates the GUI for all youz who be too shoopid for text based shitz
-     * @param monitor the monitor the gui operates over
-     */
-    public HeartbeatMonitorGUI(HeartbeatMonitor monitor) {
-        super("Heartbeat Monitor");
-        _monitor = monitor;
-        initializeComponents();
-        pack();
-        //setResizable(false);
-        setVisible(true);
-    }
-    
-    HeartbeatMonitor getMonitor() { return _monitor; }
-    
-    /** build up all our widgets */
-    private void initializeComponents() {
-        getContentPane().setLayout(new BorderLayout());
-        
-        setBackground(_background);
-        
-        _plotPane = new JFreeChartHeartbeatPlotPane(this); // new HeartbeatPlotPane(this);
-        _plotPane.setBackground(_background);
-        //JScrollPane pane = new JScrollPane(_plotPane);
-        //pane.setBackground(_background);
-        getContentPane().add(new JScrollPane(_plotPane), BorderLayout.CENTER);
-        
-        _controlPane = new HeartbeatControlPane(this);
-        _controlPane.setBackground(_background);
-        getContentPane().add(_controlPane, BorderLayout.SOUTH);
-        
-        //JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(_plotPane), new JScrollPane(_controlPane));
-        //getContentPane().add(pane, BorderLayout.CENTER);
-        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-        initializeMenus();
-    }
-    
-    /**
-     * Callback:  when the state of the world changes . . .
-     */
-    public void stateUpdated() {
-        _controlPane.testsUpdated();
-        _plotPane.stateUpdated();
-    }
-    
-    private void exitCalled() {
-        _monitor.getState().setWasKilled(true);
-        setVisible(false);
-        System.exit(0);
-    }
-    private void loadConfigCalled() {}
-    private void saveConfigCalled() {}
-    private void loadSnapshotCalled() {}
-    private void saveSnapshotCalled() {}
-    
-    private void initializeMenus() {
-        JMenuBar bar = new JMenuBar();
-        JMenu fileMenu = new JMenu("File");
-        JMenuItem loadConfig = new JMenuItem("Load config");
-        loadConfig.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadConfigCalled(); } });
-        JMenuItem saveConfig = new JMenuItem("Save config");
-        saveConfig.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { saveConfigCalled(); } });
-        JMenuItem saveSnapshot = new JMenuItem("Save snapshot");
-        saveSnapshot.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { saveSnapshotCalled(); } });
-        JMenuItem loadSnapshot = new JMenuItem("Load snapshot");
-        loadSnapshot.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadSnapshotCalled(); } });
-        JMenuItem exit = new JMenuItem("Exit");
-        exit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { exitCalled(); } });
-        
-        fileMenu.add(loadConfig);
-        fileMenu.add(saveConfig);
-        fileMenu.add(loadSnapshot);
-        fileMenu.add(saveSnapshot);
-        fileMenu.add(exit);
-        bar.add(fileMenu);
-        setJMenuBar(bar);
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorRunner.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorRunner.java
deleted file mode 100644
index 862fff271d..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorRunner.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import net.i2p.util.Log;
-
-/** 
- * Periodically fire off necessary events (instructing the heartbeat monitor when
- * to refetch the data, etc).  This is the only active thread in the heartbeat 
- * monitor (outside the swing/jvm threads) 
- */
-class HeartbeatMonitorRunner implements Runnable {
-    private final static Log _log = new Log(HeartbeatMonitorRunner.class);
-    private HeartbeatMonitor _monitor;
-    
-    /**
-     * Creates the thread . . .
-     * @param monitor the monitor the thread runs over
-     */
-    public HeartbeatMonitorRunner(HeartbeatMonitor monitor) {
-        _monitor = monitor;
-    }
-    
-    /* (non-Javadoc)
-     * @see java.lang.Runnable#run()
-     */
-    public void run() {
-        while (!_monitor.getState().getWasKilled()) {
-            _monitor.refetchData();
-            try { Thread.sleep(_monitor.getState().getRefreshRateMs()); } catch (InterruptedException ie) {}
-        }
-        _log.info("Stopping the heartbeat monitor runner");
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorState.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorState.java
deleted file mode 100644
index 7de4bc9bb0..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorState.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * manage the current state of the GUI - all data points, as well as any
- * rendering or configuration options.
- */
-class HeartbeatMonitorState {
-    private String _configFile;
-    private List _peerPlotState;
-    private int _currentPeerPlotConfig;
-    private int _refreshRateMs;
-    private boolean _killed;
-    
-    /** by default, refresh every 30 seconds */
-    private final static int DEFAULT_REFRESH_RATE = 30*1000;
-    /** where do we load/store config info from? */
-    private final static String DEFAULT_CONFIG_FILE = "heartbeatMonitor.config";
-    
-    /**
-     * A delegating constructor.
-     * @see HeartbeatMonitorState#HeartbeatMonitorState(String)
-     */
-    public HeartbeatMonitorState() { this(DEFAULT_CONFIG_FILE); }
-
-    /**
-     * Constructs the state, loading from the specified location
-     * @param configFile the name of the file to load info from
-     */
-    public HeartbeatMonitorState(String configFile) {
-        _peerPlotState = Collections.synchronizedList(new ArrayList());
-        _refreshRateMs = DEFAULT_REFRESH_RATE;
-        _configFile = configFile;
-        _killed = false;
-        _currentPeerPlotConfig = 0;
-    }
-    
-    /**
-     * how many tests are we monitoring?
-     * @return the number of tests
-     */
-    public int getTestCount() { return _peerPlotState.size(); }
-
-    /**
-     * Retrieves the current info of a test for a certain peer . . . 
-     * @param peer a number associated with a certain peer
-     * @return the test data
-     */
-    public PeerPlotState getTest(int peer) { return (PeerPlotState)_peerPlotState.get(peer); }
-
-    /**
-     * Adds a test . . .
-     * @param peerState the test (by state) to add . . .
-     */
-    public void addTest(PeerPlotState peerState) { 
-        if (!_peerPlotState.contains(peerState))
-            _peerPlotState.add(peerState); 
-    }
-    /**
-     * Removes a test . . .
-     * @param peerState the test (by state) to remove . . .
-     */
-    public void removeTest(PeerPlotState peerState) { _peerPlotState.remove(peerState); }
-    
-    /**
-     * Removes a test . . .
-     * @param peerConfig the test (by config) to remove . . .
-     */
-    public void removeTest(PeerPlotConfig peerConfig) {
-        for (int i = 0; i < getTestCount(); i++) {
-            PeerPlotState state = getTest(i);
-            if (state.getPlotConfig() == peerConfig) {
-                removeTest(state);
-                return;
-            }
-        }
-    }
-    
-    /** 
-     * which of the tests are we currently editing/viewing?
-     * @return the number associated with the test
-     */
-    public int getPeerPlotConfig() { return _currentPeerPlotConfig; }
-
-    /**
-     * Sets the test we are currently editting/viewing
-     * @param whichTest the number associated with the test
-     */
-    public void setPeerPlotConfig(int whichTest) { _currentPeerPlotConfig = whichTest; }
-    
-    /**
-     * how frequently should we update the data?
-     * @return the current frequency (in milliseconds) 
-     */
-    public int getRefreshRateMs() { return _refreshRateMs; }
-
-    /**
-     * Sets how frequently we should update data
-     * @param ms the frequency (in milliseconds)
-     */
-    public void setRefreshRateMs(int ms) { _refreshRateMs = ms; }
-    
-    /** 
-     * where is our config stored? 
-     * @return the name of the config file
-     */
-    public String getConfigFile() { return _configFile; }
-
-    /**
-     * Sets where our config is stored
-     * @param filename the name of the config file
-     */
-    public void setConfigFile(String filename) { _configFile = filename; }
-    
-    /** 
-     * have we been shut down?
-     * @return true if we have, false otherwise 
-     */
-    public boolean getWasKilled() { return _killed; }
-
-    /**
-     * Sets if we have been shutdown or not
-     * @param killed true if we've been shutdown, false otherwise
-     */
-    public void setWasKilled(boolean killed) { _killed = killed; }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatPlotPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatPlotPane.java
deleted file mode 100644
index 2cc122f0d7..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatPlotPane.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import javax.swing.JPanel;
-import javax.swing.JTextArea;
-
-import net.i2p.heartbeat.PeerDataWriter;
-import net.i2p.util.Log;
-
-/**
- * Render the graph and legend
- */
-class HeartbeatPlotPane extends JPanel {
-    private final static Log _log = new Log(HeartbeatPlotPane.class);
-    protected HeartbeatMonitorGUI _gui;
-    private JTextArea _text;
-    
-    /**
-     * Constructs the plot pane
-     * @param gui the gui the pane is attached to
-     */
-    public HeartbeatPlotPane(HeartbeatMonitorGUI gui) {
-        _gui = gui;
-        initializeComponents();
-    }
-    
-    /**
-     * Callback: when things change . . . 
-     */
-    public void stateUpdated() {
-        StringBuffer buf = new StringBuffer(32*1024);
-        PeerDataWriter writer = new PeerDataWriter();
-        
-        for (int i = 0; i < _gui.getMonitor().getState().getTestCount(); i++) {
-            StaticPeerData data = _gui.getMonitor().getState().getTest(i).getCurrentData();
-            ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
-            try {
-                writer.persist(data, baos);
-            } catch (IOException ioe) {
-                _log.error("wtf, error writing to a byte array?", ioe);
-            }
-            buf.append(new String(baos.toByteArray())).append("\n\n\n");
-        }
-        
-        _text.setText(buf.toString());
-    }
-    
-    protected void initializeComponents() {
-        setBackground(_gui.getBackground());
-        //Dimension size = new Dimension(800, 600);
-        _text = new JTextArea("",30,80); // 16, 60);
-        _text.setAutoscrolls(true);
-        _text.setEditable(false);
-        // _text.setLineWrap(true);
-        // add(new JScrollPane(_text));
-        add(_text);
-        // add(new JScrollPane(_text, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS));
-        // setPreferredSize(size);
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartAdapter.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartAdapter.java
deleted file mode 100644
index 80ef31ca7d..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartAdapter.java
+++ /dev/null
@@ -1,233 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import java.awt.Color;
-import java.awt.Font;
-import java.util.List;
-
-import org.jfree.chart.ChartPanel;
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.axis.DateAxis;
-import org.jfree.chart.axis.NumberAxis;
-import org.jfree.chart.plot.Plot;
-import org.jfree.chart.plot.XYPlot;
-import org.jfree.chart.renderer.XYItemRenderer;
-import org.jfree.chart.renderer.XYLineAndShapeRenderer;
-import org.jfree.data.XYSeries;
-import org.jfree.data.XYSeriesCollection;
-
-import net.i2p.heartbeat.PeerData;
-import net.i2p.util.Log;
-
-class JFreeChartAdapter {
-    private final static Log _log = new Log(JFreeChartAdapter.class); /* UNUSED */
-    private final static Color WHITE = new Color(255, 255, 255);
-    
-    ChartPanel createPanel(HeartbeatMonitorState state) {
-        ChartPanel panel = new ChartPanel(createChart(state));
-        panel.setDisplayToolTips(true);
-        panel.setEnforceFileExtensions(true);
-        panel.setHorizontalZoom(true);
-        panel.setVerticalZoom(true);
-        panel.setMouseZoomable(true, true);
-        panel.getChart().setBackgroundPaint(WHITE);
-        return panel;
-    }
-    
-    JFreeChart createChart(HeartbeatMonitorState state) {
-        Plot plot = createPlot(state);
-        JFreeChart chart = new JFreeChart("I2P Heartbeat performance", Font.getFont("arial"), plot, true);
-        return chart;
-    }
-    
-    void updateChart(ChartPanel panel, HeartbeatMonitorState state) {
-        XYPlot plot = (XYPlot)panel.getChart().getPlot();
-        plot.setDataset(getCollection(state));
-        updateLines(plot, state);
-    }
-    
-    private long getFirst(HeartbeatMonitorState state) { /* UNUSED */
-        long first = -1;
-        for (int i = 0; i < state.getTestCount(); i++) {
-            List dataPoints = state.getTest(i).getCurrentData().getDataPoints();
-            if ( (dataPoints != null) && (dataPoints.size() > 0) ) {
-                PeerData.EventDataPoint data = (PeerData.EventDataPoint)dataPoints.get(0);
-                if ( (first < 0) || (first > data.getPingSent()) )
-                    first = data.getPingSent();
-            }
-        }
-        return first;
-    }
-    
-    Plot createPlot(HeartbeatMonitorState state) {
-        XYItemRenderer renderer = new XYLineAndShapeRenderer(); // new XYDotRenderer(); // 
-        XYPlot plot = new XYPlot(getCollection(state), new DateAxis(), new NumberAxis("ms"), renderer);
-        updateLines(plot, state);
-        return plot;
-    }
-    
-    private void updateLines(XYPlot plot, HeartbeatMonitorState state) {
-        if (true) return;
-        if (state == null) return;
-        for (int i = 0; i < state.getTestCount(); i++) {
-            PeerPlotConfig config = state.getTest(i).getPlotConfig();
-            PeerPlotConfig.PlotSeriesConfig curConfig = config.getCurrentSeriesConfig();
-            XYSeriesCollection col = ((XYSeriesCollection)plot.getDataset());
-            for (int j = 0; j < col.getSeriesCount(); j++) {
-                //XYItemRenderer renderer = plot.getRendererForDataset(col.getSeries(j));
-                XYItemRenderer renderer = plot.getRendererForDataset(col);
-                if (col.getSeriesName(j).startsWith(config.getTitle() + " send")) {
-                    if (curConfig.getPlotSendTime()) {
-                        //renderer.setPaint(curConfig.getPlotLineColor());
-                    }
-                }
-                if (col.getSeriesName(j).startsWith(config.getTitle() + " receive")) {
-                    if (curConfig.getPlotReceiveTime()) {
-                        //renderer.setPaint(curConfig.getPlotLineColor());
-                    }
-                }
-                if (col.getSeriesName(j).startsWith(config.getTitle() + " lost")) {
-                    if (curConfig.getPlotLostMessages()) {
-                        //renderer.setPaint(curConfig.getPlotLineColor());
-                    }
-                }
-            }
-        }
-    }
-    
-    XYSeriesCollection getCollection(HeartbeatMonitorState state) {
-        XYSeriesCollection col = new XYSeriesCollection();
-        if (state != null) {
-            for (int i = 0; i < state.getTestCount(); i++) {
-                addTest(col, state.getTest(i));
-            }
-        } else {
-            XYSeries series = new XYSeries("latency", false, false);
-            series.add(System.currentTimeMillis(), 0);
-            col.addSeries(series);
-        }
-        return col;
-    }
-    
-    void addTest(XYSeriesCollection col, PeerPlotState state) {
-        PeerPlotConfig config = state.getPlotConfig();
-        PeerPlotConfig.PlotSeriesConfig curConfig = config.getCurrentSeriesConfig();
-        addLines(col, curConfig, config.getTitle(), state.getCurrentData().getDataPoints());
-        addAverageLines(col, config, config.getTitle(), state.getCurrentData());
-    }
-    
-    /**
-     * @param col the collection of xy series to add to
-     * @param config preferences for how to display this test
-     * @param lineName minimal name of the test (e.g. "jxHa.32KB.60s")
-     * @param data List of PeerData.EventDataPoint describing all of the events in the test
-     */
-    void addLines(XYSeriesCollection col, PeerPlotConfig.PlotSeriesConfig config, String lineName, List data) {
-        if (config.getPlotSendTime()) {
-            XYSeries sendSeries = getSendSeries(data);
-            sendSeries.setName(lineName + " send");
-            sendSeries.setDescription("milliseconds for the ping to reach the peer");
-            col.addSeries(sendSeries);
-        }
-        if (config.getPlotReceiveTime()) {
-            XYSeries recvSeries = getReceiveSeries(data);
-            recvSeries.setName(lineName + " receive");
-            recvSeries.setDescription("milliseconds for the peer's pong to reach the sender");
-            col.addSeries(recvSeries);
-        }
-        if (config.getPlotLostMessages()) {
-            XYSeries lostSeries = getLostSeries(data);
-            lostSeries.setName(lineName + " lost");
-            lostSeries.setDescription("number of ping/pong messages lost");
-            col.addSeries(lostSeries);
-        }
-    }
-    
-    /**
-     * Add a data series for each average that we're configured to render
-     *
-     * @param col the collection of xy series to add to
-     * @param config preferences for how to display this test
-     * @param lineName minimal name of the test (e.g. "jxHa.32KB.60s")
-     * @param data List of PeerData.EventDataPoint describing all of the events in the test
-     */
-    void addAverageLines(XYSeriesCollection col, PeerPlotConfig config, String lineName, StaticPeerData data) {
-        if (data.getDataPointCount() <= 0) return;
-        PeerData.EventDataPoint start = (PeerData.EventDataPoint)data.getDataPoints().get(0);
-        PeerData.EventDataPoint finish = (PeerData.EventDataPoint)data.getDataPoints().get(data.getDataPointCount()-1);
-
-        List configs = config.getAverageSeriesConfigs();
-
-        for (int i = 0; i < configs.size(); i++) {
-            PeerPlotConfig.PlotSeriesConfig cfg = (PeerPlotConfig.PlotSeriesConfig)configs.get(i);
-            int minutes = (int)cfg.getPeriod()/(60*1000);
-            if (cfg.getPlotSendTime()) {
-                double time = data.getAverageSendTime(minutes);
-                if (time > 0) {
-                    XYSeries series = new XYSeries(lineName + " send " + minutes + "m avg [" + time + "]", false, false);
-                    series.add(start.getPingSent(), time);
-                    series.add(finish.getPingSent(), time);
-                    series.setDescription("send time, averaged over the last " + minutes + " minutes");
-                    col.addSeries(series);
-                }
-            }
-            if (cfg.getPlotReceiveTime()) {
-                double time = data.getAverageReceiveTime(minutes);
-                if (time > 0) {
-                    XYSeries series = new XYSeries(lineName + " receive " + minutes + "m avg[" + time + "]", false, false);
-                    series.add(start.getPingSent(), time);
-                    series.add(finish.getPingSent(), time);
-                    series.setDescription("receive time, averaged over the last " + minutes + " minutes");
-                    col.addSeries(series);
-                }
-            }
-            if (cfg.getPlotLostMessages()) {
-                double num = data.getLostMessages(minutes);
-                if (num > 0) {
-                    XYSeries series = new XYSeries(lineName + " lost messages (" + num + " in " + minutes + "m)", false, false);
-                    series.add(start.getPingSent(), num);
-                    series.add(finish.getPingSent(), num);
-                    series.setDescription("number of messages lost in the last " + minutes + " minutes");
-                    col.addSeries(series);
-                }
-            }
-        }
-    }
-    
-    XYSeries getSendSeries(List data) {
-        XYSeries series = new XYSeries("sent", false, false);
-        for (int i = 0; i < data.size(); i++) {
-            PeerData.EventDataPoint point = (PeerData.EventDataPoint)data.get(i);
-            if (point.getWasPonged()) {
-                series.add(point.getPingSent(), point.getPongSent()-point.getPingSent());
-            } else {
-                // series.add(data.getPingSent(), 0);
-            }
-        }
-        return series;
-    }
-    
-    XYSeries getReceiveSeries(List data) {
-        XYSeries series = new XYSeries("receive", false, false);
-        for (int i = 0; i < data.size(); i++) {
-            PeerData.EventDataPoint point = (PeerData.EventDataPoint)data.get(i);
-            if (point.getWasPonged()) {
-                series.add(point.getPingSent(), point.getPongReceived()-point.getPongSent());
-            } else {
-                // series.add(data.getPingSent(), 0);
-            }
-        }
-        return series;
-    }
-    XYSeries getLostSeries(List data) {
-        XYSeries series = new XYSeries("lost", false, false);
-        for (int i = 0; i < data.size(); i++) {
-            PeerData.EventDataPoint point = (PeerData.EventDataPoint)data.get(i);
-            if (point.getWasPonged()) {
-                //series.add(point.getPingSent(), 0);
-            } else {
-                series.add(point.getPingSent(), 1);
-            }
-        }
-        return series;
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartHeartbeatPlotPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartHeartbeatPlotPane.java
deleted file mode 100644
index 7075c37d1e..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartHeartbeatPlotPane.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import java.awt.BorderLayout;
-
-import javax.swing.JLabel;
-import javax.swing.JScrollPane;
-
-import org.jfree.chart.ChartPanel;
-
-import net.i2p.util.Log;
-
-/**
- * Render the graph and legend
- *
- */
-class JFreeChartHeartbeatPlotPane extends HeartbeatPlotPane {
-    private final static Log _log = new Log(JFreeChartHeartbeatPlotPane.class); /* UNUSED */
-    private ChartPanel _panel;
-    private JFreeChartAdapter _adapter;
-
-    /**
-     * Creates a JFreeChart plot pane for the given gui
-     * @param gui the heartbeat monitor gui
-     */
-    public JFreeChartHeartbeatPlotPane(HeartbeatMonitorGUI gui) {
-        super(gui);
-    }
-    
-    /**
-     * Called when the state is updated
-     */
-    public void stateUpdated() {
-        if (_panel == null) {
-            remove(0); // remove the dummy
-            
-            _adapter = new JFreeChartAdapter();
-            _panel = _adapter.createPanel(_gui.getMonitor().getState());
-            _panel.setBackground(_gui.getBackground());
-            add(new JScrollPane(_panel), BorderLayout.CENTER);
-            _gui.pack();
-        } else {
-            _adapter.updateChart(_panel, _gui.getMonitor().getState());
-            //_gui.pack();
-        }
-    }
-    
-    protected void initializeComponents() {
-        // noop
-        setLayout(new BorderLayout());
-        add(new JLabel(), BorderLayout.CENTER);
-        //dummy.setBackground(_gui.getBackground());
-        //dummy.setPreferredSize(new Dimension(800,600));
-        //add(dummy);
-
-        //add(_panel);
-
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfig.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfig.java
deleted file mode 100644
index 27d8533aed..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfig.java
+++ /dev/null
@@ -1,367 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeMap;
-
-import net.i2p.data.Destination;
-import net.i2p.heartbeat.ClientConfig;
-import net.i2p.util.Log;
-
-/**
- * Configure how we want to render a particular clientConfig in the GUI
- */
-class PeerPlotConfig {
-    private final static Log _log = new Log(PeerPlotConfig.class); /* UNUSED */
-    /** where can we find the current state/data (either as a filename or a URL)? */
-    private String _location;
-    /** what test are we defining the plot data for? */
-    private ClientConfig _config;
-    /** how should we render the current data set? */
-    private PlotSeriesConfig _currentSeriesConfig;
-    /** how should we render the various averages available? */
-    private List _averageSeriesConfigs;
-    private Set _listeners;
-    private boolean _disabled;
-
-    /**
-     * Delegating constructor . . .
-     * @param location the name of the file/URL to get the data from
-     */
-    public PeerPlotConfig(String location) {
-        this(location, null, null, null);
-    }
-    
-    /**
-     * Constructs a config =)
-     * @param location the location of the file/URL to get the data from
-     * @param config the client's configuration
-     * @param currentSeriesConfig the series config
-     * @param averageSeriesConfigs the average
-     */
-    public PeerPlotConfig(String location, ClientConfig config, PlotSeriesConfig currentSeriesConfig, List averageSeriesConfigs) {
-        _location = location;
-        if (config == null) 
-            config = new ClientConfig(location);
-        _config = config;
-        if (currentSeriesConfig != null)
-            _currentSeriesConfig = currentSeriesConfig;
-        else
-            _currentSeriesConfig = new PlotSeriesConfig(0);
-        
-        if (averageSeriesConfigs != null) {
-            _averageSeriesConfigs = averageSeriesConfigs;
-        } else {
-            rebuildAverageSeriesConfigs();
-        }
-        _listeners = Collections.synchronizedSet(new HashSet(2));
-        _disabled = false;
-    }
-    
-    /**
-     * 'Rebuilds' the average series stuff from the client configuration
-     */
-    public void rebuildAverageSeriesConfigs() {
-        int periods[] = _config.getAveragePeriods();
-        if (periods == null) {
-            _averageSeriesConfigs = Collections.synchronizedList(new ArrayList(0));
-        } else {
-            Arrays.sort(periods);
-            _averageSeriesConfigs = Collections.synchronizedList(new ArrayList(periods.length));
-            for (int i = 0; i < periods.length; i++) {
-                _averageSeriesConfigs.add(new PlotSeriesConfig(periods[i]*60*1000));
-            }
-        }
-    }
-    
-    /**
-     * Adds an average period
-     * @param minutes the number of minutes averaged over
-     */
-    public void addAverage(int minutes) {
-        _config.addAveragePeriod(minutes);
-        
-        TreeMap ordered = new TreeMap();
-        for (int i = 0; i < _averageSeriesConfigs.size(); i++) {
-            PlotSeriesConfig cfg = (PlotSeriesConfig)_averageSeriesConfigs.get(i);
-            ordered.put(new Long(cfg.getPeriod()), cfg);
-        }
-        Long period = new Long(minutes*60*1000);
-        if (!ordered.containsKey(period))
-            ordered.put(period, new PlotSeriesConfig(minutes*60*1000));
-        
-        List cfgs = Collections.synchronizedList(new ArrayList(ordered.size()));
-        for (Iterator iter = ordered.values().iterator(); iter.hasNext(); )
-            cfgs.add(iter.next());
-        
-        _averageSeriesConfigs = cfgs;
-    }
-    
-    /** 
-     * Where is the current state data supposed to be found?  This must either be a 
-     * local file path or a URL
-     * @return the current location
-     */
-    public String getLocation() { return _location; }
-
-    /**
-     * The location the current state data is supposed to be found.  This must either be
-     * a local file path or a URL
-     * @param location the location
-     */
-    public void setLocation(String location) { 
-        _location = location; 
-        fireUpdate();
-    }
-    
-    /** 
-     * What are we configuring? 
-     * @return the client configuration
-     */
-    public ClientConfig getClientConfig() { return _config; }
-
-    /**
-     * Sets what we are currently configuring
-     * @param config the new config
-     */
-    public void setClientConfig(ClientConfig config) { 
-        _config = config; 
-        fireUpdate();
-    }
-    
-    /** 
-     * How do we want to render the current data set?
-     * @return the way we currently render the data
-     */
-    public PlotSeriesConfig getCurrentSeriesConfig() { return _currentSeriesConfig; }
-
-    /**
-     * Sets how we want to render the current data set.
-     * @param config the new config
-     */
-    public void setCurrentSeriesConfig(PlotSeriesConfig config) { 
-        _currentSeriesConfig = config; 
-        fireUpdate();
-    }
-    
-    /** 
-     * How do we want to render the averages? 
-     * @return the way we currently render the averages
-     */
-    public List getAverageSeriesConfigs() { return _averageSeriesConfigs; }
-
-    /**
-     * Sets how we want to render the averages
-     * @param configs the new configs
-     */
-    public void setAverageSeriesConfigs(List configs) { _averageSeriesConfigs = configs; }
-    
-    /** 
-     * four char description of the peer 
-     * @return the name
-     */
-    public String getPeerName() { 
-        Destination peer = getClientConfig().getPeer();
-        if (peer == null) 
-            return "????";
-
-        return peer.calculateHash().toBase64().substring(0, 4);
-    }
-
-    /**
-     * title:  name.packetsize.sendfrequency
-     * @return the title
-     */
-    public String getTitle() { 
-        return getPeerName() + '.' + getSize() + '.' + getClientConfig().getSendFrequency(); 
-    }
-    
-    /**
-     * summary.  includes:name, size, sendfrequency, and # of hops  
-     * @return the summary
-     */
-    public String getSummary() { 
-        return "Send peer " + getPeerName() + ' ' + getSize() + " every " + 
-               getClientConfig().getSendFrequency() + " seconds through " +
-               getClientConfig().getNumHops() + "-hop tunnels";
-    }
-    
-    private String getSize() {
-        int bytes = getClientConfig().getSendSize();
-        if (bytes < 1024)
-            return bytes + "b";
-
-        return bytes/1024 + "kb";
-    }
-
-    /** 
-     * we've got someone who wants to be notified of changes to the plot config
-     * @param lsnr the listener to be added 
-     */
-    public void addListener(UpdateListener lsnr) { _listeners.add(lsnr); }
-
-    /**
-     * remove a listener
-     * @param lsnr the listener to remove
-     */
-    public void removeListener(UpdateListener lsnr) { _listeners.remove(lsnr); }
-    
-    void fireUpdate() {
-        if (_disabled) return;
-        for (Iterator iter = _listeners.iterator(); iter.hasNext(); ) {
-            ((UpdateListener)iter.next()).configUpdated(this);
-        }
-    }
-    
-    /**
-     * Disables notification of events listeners
-     * @see PeerPlotConfig#fireUpdate()
-     */
-    public void disableEvents() { _disabled = true; }
-
-    /**
-     * Enables notification of events listeners
-     * @see PeerPlotConfig#fireUpdate()
-     */
-    public void enableEvents() { _disabled = false; }
-    
-    /** 
-     * How do we want to render a particular dataset (either the current or the averaged values)?
-     */
-    public class PlotSeriesConfig {
-        private long _period;
-        private boolean _plotSendTime;
-        private boolean _plotReceiveTime;
-        private boolean _plotLostMessages;
-        private Color _plotLineColor;
-        
-        /**
-         * Delegating constructor . . .
-         * @param period the period for the config 
-         *        (0 for current, otherwise # of milliseconds being averaged over)
-         */
-        public PlotSeriesConfig(long period) {
-            this(period, false, false, false, null);
-            if (period <= 0) {
-                _plotSendTime = true;
-                _plotReceiveTime = true;
-                _plotLostMessages = true;
-            }
-        }
-        
-        
-        /**
-         * Creates a config for the rendering of a particular dataset)
-         * @param period the period for the config
-         *        (0 for current, otherwise # of milliseconds being averaged over)
-         * @param plotSend do we plot send times?
-         * @param plotReceive do we plot receive times?
-         * @param plotLost do we plot lost packets?
-         * @param plotColor in what color?
-         */
-        public PlotSeriesConfig(long period, boolean plotSend, boolean plotReceive, boolean plotLost, Color plotColor) {
-            _period = period;
-            _plotSendTime = plotSend;
-            _plotReceiveTime = plotReceive;
-            _plotLostMessages = plotLost;
-            _plotLineColor = plotColor;
-        }
-        
-        /**
-         * Retrieves the plot config this plot series config is a part of
-         * @return the plot config
-         */
-        public PeerPlotConfig getPlotConfig() { return PeerPlotConfig.this; }
-        
-        /** 
-         * What period is this series config describing?
-         * @return 0 for current, otherwise # milliseconds that are being averaged over
-         */
-        public long getPeriod() { return _period; }
-
-        /**
-         * Sets the period this series config is describing
-         * @param period the period
-         *        (0 for current, otherwise # milliseconds that are being averaged over)
-         */
-        public void setPeriod(long period) { 
-            _period = period; 
-            fireUpdate();
-        }
-        
-        /**
-         * Should we render the time to send (ping to peer)?
-         * @return true or false . . .
-         */
-        public boolean getPlotSendTime() { return _plotSendTime; }
-
-        /**
-         * Sets whether we render the time to send (ping to peer) or not
-         * @param shouldPlot true or false 
-         */
-        public void setPlotSendTime(boolean shouldPlot) { 
-            _plotSendTime = shouldPlot; 
-            fireUpdate();
-        }
-
-        /** 
-         * Should we render the time to receive (peer pong to us)?
-         * @return true or false . . . 
-         */
-        public boolean getPlotReceiveTime() { return _plotReceiveTime; }
-
-        /**
-         * Sets whether we render the time to receive (peer pong to us)
-         * @param shouldPlot true or false
-         */
-        public void setPlotReceiveTime(boolean shouldPlot) { 
-            _plotReceiveTime = shouldPlot; 
-            fireUpdate();
-        }
-        /**
-         * Should we render the number of messages lost (ping sent, no pong received in time)? 
-         * @return true or false . . .
-         */
-        public boolean getPlotLostMessages() { return _plotLostMessages; }
-
-        /**
-         * Sets whether we render the number of messages lost (ping sent, no pong received in time) or not
-         * @param shouldPlot true or false
-         */
-        public void setPlotLostMessages(boolean shouldPlot) { 
-            _plotLostMessages = shouldPlot; 
-            fireUpdate();
-        }
-        /**
-         * What color should we plot the data with? 
-         * @return the color
-         */
-        public Color getPlotLineColor() { return _plotLineColor; }
-
-        /**
-         * Sets the color we should plot the data with
-         * @param color the color to use
-         */
-        public void setPlotLineColor(Color color) { 
-            _plotLineColor = color; 
-            fireUpdate();
-        }
-    }
-    
-    /**
-     * An interface for listening to updates . . .
-     */
-    public interface UpdateListener {
-        /**
-         * @param config the peer plot config that changes
-         * @see PeerPlotConfig#fireUpdate()
-         */
-        void configUpdated(PeerPlotConfig config);
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfigPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfigPane.java
deleted file mode 100644
index aa0ab1cde3..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfigPane.java
+++ /dev/null
@@ -1,371 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import java.awt.Color;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.List;
-import java.util.Random;
-
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JColorChooser;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextArea;
-import javax.swing.JTextField;
-
-import net.i2p.util.Log;
-
-class PeerPlotConfigPane extends JPanel implements PeerPlotConfig.UpdateListener {
-    private final static Log _log = new Log(PeerPlotConfigPane.class);
-    private PeerPlotConfig _config;
-    private HeartbeatControlPane _parent;
-    private JLabel _title;
-    private JButton _delete;
-    private JLabel _fromLabel;
-    private JTextField _from;
-    private JTextArea _comments;
-    private JLabel _peerLabel;
-    private JTextField _peerKey;
-    private JLabel _localLabel;
-    private JTextField _localKey;
-    private OptionLine _options[];
-    private Random _rnd = new Random();
-    private final static Color WHITE = new Color(255, 255, 255);
-    private Color _background = WHITE;
-    
-    /**
-     * Constructs a pane
-     * @param config the plot config it represents
-     * @param pane the pane this one is attached to
-     */
-    public PeerPlotConfigPane(PeerPlotConfig config, HeartbeatControlPane pane) {
-        _config = config;
-        _parent = pane;
-        if (_parent != null)
-            _background = _parent.getBackground();
-        _config.addListener(this);
-        initializeComponents();
-    }
-    
-    /** called when the user wants to stop monitoring this test */
-    private void delete() {
-        _parent.removeTest(_config);
-    }
-    
-    private void initializeComponents() {
-        buildComponents();
-        placeComponents(this);
-        refreshView();
-        //setBorder(new BevelBorder(BevelBorder.RAISED));
-        setBackground(_background);
-    }
-    
-    /** 
-     * place all the gui components onto the given panel 
-     * @param body the panel to place the components on
-     */
-    private void placeComponents(JPanel body) {
-        body.setLayout(new GridBagLayout());
-        GridBagConstraints cts = new GridBagConstraints();
-        
-        // row 0: title + delete
-        cts.gridx = 0;
-        cts.gridy = 0;
-        cts.gridwidth = 5;
-        cts.anchor = GridBagConstraints.WEST;
-        cts.fill = GridBagConstraints.NONE;
-        body.add(_title, cts);
-        cts.gridx = 5;
-        cts.gridwidth = 1;
-        cts.anchor = GridBagConstraints.NORTHWEST;
-        cts.fill = GridBagConstraints.BOTH;
-        body.add(_delete, cts);
-        
-        // row 1: from + location
-        cts.gridx = 0;
-        cts.gridy = 1;
-        cts.gridwidth = 1;
-        cts.fill = GridBagConstraints.NONE;
-        body.add(_fromLabel, cts);
-        cts.gridx = 1;
-        cts.gridwidth = 5;
-        cts.fill = GridBagConstraints.BOTH;
-        body.add(_from, cts);
-
-        // row 2: comment
-        cts.gridx = 0;
-        cts.gridy = 2;
-        cts.gridwidth = 6;
-        cts.fill = GridBagConstraints.BOTH;
-        body.add(_comments, cts);
-        
-        // row 3: peer + peerKey 
-        cts.gridx = 0;
-        cts.gridy = 3;
-        cts.gridwidth = 1;
-        cts.fill = GridBagConstraints.NONE;
-        body.add(_peerLabel, cts);
-        cts.gridx = 1;
-        cts.gridwidth = 5;
-        cts.fill = GridBagConstraints.BOTH;
-        body.add(_peerKey, cts);
-        
-        // row 4: local + localKey
-        cts.gridx = 0;
-        cts.gridy = 4;
-        cts.gridwidth = 1;
-        cts.fill = GridBagConstraints.NONE;
-        body.add(_localLabel, cts);
-        cts.gridx = 1;
-        cts.gridwidth = 5;
-        cts.fill = GridBagConstraints.BOTH;
-        body.add(_localKey, cts);
-        
-        // row 5-N: data row
-        for (int i = 0; i < _options.length; i++) {
-            cts.gridx = 0;
-            cts.gridy = 5 + i;
-            cts.gridwidth = 1;
-            cts.fill = GridBagConstraints.NONE;
-            cts.anchor = GridBagConstraints.WEST;
-            if (_options[i]._durationMinutes <= 0)
-                body.add(new JLabel("Data: "), cts);
-            else
-                body.add(new JLabel(_options[i]._durationMinutes + "m avg: "), cts);
-            
-            cts.gridx = 1;
-            body.add(_options[i]._send, cts);
-            cts.gridx = 2;
-            body.add(_options[i]._recv, cts);
-            cts.gridx = 3;
-            body.add(_options[i]._lost, cts);
-            cts.gridx = 4;
-            body.add(_options[i]._all, cts);
-            cts.gridx = 5;
-            body.add(_options[i]._color, cts);
-        }
-    }
-    
-    /** build all of the gui components */
-    private void buildComponents() {
-        _title = new JLabel(_config.getSummary());
-        _title.setBackground(_background);
-        _delete = new JButton("Delete");
-        _delete.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { delete(); } });
-        _delete.setEnabled(false);
-        _delete.setBackground(_background);
-        _fromLabel = new JLabel("Location: ");
-        _fromLabel.setBackground(_background);
-        _from = new JTextField(_config.getLocation());
-        _from.setEditable(false);
-        _from.setBackground(_background);
-        _comments = new JTextArea(_config.getClientConfig().getComment(), 2, 20);
-        // _comments = new JTextArea(_config.getClientConfig().getComment(), 2, 40);
-        _comments.setEditable(false);
-        _comments.setBackground(_background);
-        _peerLabel = new JLabel("Peer: ");
-        _peerLabel.setBackground(_background);
-        _peerKey = new JTextField(_config.getClientConfig().getPeer().toBase64(), 8);
-        _peerKey.setBackground(_background);
-        _localLabel = new JLabel("Local: ");
-        _localLabel.setBackground(_background);
-        _localKey = new JTextField(_config.getClientConfig().getUs().toBase64(), 8);
-        _localKey.setBackground(_background);
-        
-        int averagedPeriods[] = _config.getClientConfig().getAveragePeriods();
-        if (averagedPeriods == null)
-            averagedPeriods = new int[0];
-        
-        _options = new OptionLine[1 + averagedPeriods.length];
-        _options[0] = new OptionLine(0);
-        for (int i = 0; i < averagedPeriods.length; i++) {
-            _options[1+i] = new OptionLine(averagedPeriods[i]);
-        }   
-    }
-    
-    /** the settings have changed - revise */
-    private void refreshView() {
-        for (int i = 0; i < _options.length; i++) {
-            PeerPlotConfig.PlotSeriesConfig cfg = getConfig(_options[i]._durationMinutes);
-            if (cfg == null) {
-                _log.warn("Config for minutes " + _options[i]._durationMinutes + " was not found?");
-                continue;
-            }
-            //_log.debug("Refreshing view for minutes ["+ _options[i]._durationMinutes + "]: send [" + 
-            //           _options[i]._send.isSelected() + "/" + cfg.getPlotSendTime() + "] recv [" + 
-            //           _options[i]._recv.isSelected() + "/" + cfg.getPlotReceiveTime() + "] lost [" +
-            //           _options[i]._lost.isSelected() + "/" + cfg.getPlotLostMessages() + "]");
-            _options[i]._send.setSelected(cfg.getPlotSendTime());
-            _options[i]._recv.setSelected(cfg.getPlotReceiveTime());
-            _options[i]._lost.setSelected(cfg.getPlotLostMessages());
-            if (cfg.getPlotLineColor() != null)
-                _options[i]._color.setBackground(cfg.getPlotLineColor());
-        }
-    }
-    
-    /** 
-     * find the right config for the given period
-     * @param minutes the minutes to locate the config by
-     * @return the config for the given period, or null
-     */
-    private PeerPlotConfig.PlotSeriesConfig getConfig(int minutes) {
-        if (minutes <= 0)
-            return _config.getCurrentSeriesConfig();
-        
-        List configs = _config.getAverageSeriesConfigs();
-        for (int i = 0; i < configs.size(); i++) {
-            PeerPlotConfig.PlotSeriesConfig cfg = (PeerPlotConfig.PlotSeriesConfig)configs.get(i);
-            if (cfg.getPeriod() == minutes * 60*1000)
-                return cfg;
-        }
-        return null;
-    }
-    
-    /** 
-     * notified that the config has been updated 
-     * @param config the config that was been updated
-     */
-    public void configUpdated(PeerPlotConfig config) { refreshView(); }
-    
-    private class ChooseColor implements ActionListener {
-        private int _minutes;
-        private JButton _button;
-        
-        /**
-         * @param minutes the minutes (line) to change the color of...
-         * @param button the associated button
-         */
-        public ChooseColor(int minutes, JButton button) { 
-            _minutes = minutes; 
-            _button = button;
-        }
-
-        /* (non-Javadoc)
-         * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
-         */
-        public void actionPerformed(ActionEvent evt) { 
-            PeerPlotConfig.PlotSeriesConfig cfg = getConfig(_minutes);
-            Color origColor = null;
-            if (cfg != null)
-                origColor = cfg.getPlotLineColor();
-            Color color = JColorChooser.showDialog(PeerPlotConfigPane.this, "What color should this line be?", origColor);
-            if (color != null) {
-                if (cfg != null)
-                    cfg.setPlotLineColor(color);
-                _button.setBackground(color);
-            }
-        }
-    }
-    
-    private class OptionLine {
-        int _durationMinutes;
-        JCheckBox _send;
-        JCheckBox _recv;
-        JCheckBox _lost;
-        JCheckBox _all;
-        JButton _color;
-        
-        /**
-         * Creates an OptionLine.  
-         * @param durationMinutes the minutes =)
-         */
-        public OptionLine(int durationMinutes) {
-            _durationMinutes = durationMinutes;
-            _send = new JCheckBox("send time");
-            _send.setBackground(_background);
-            _recv = new JCheckBox("receive time");
-            _recv.setBackground(_background);
-            _lost = new JCheckBox("lost messages");
-            _lost.setBackground(_background);
-            _all = new JCheckBox("all");
-            _all.setBackground(_background);
-            _color = new JButton("color");
-            int r = _rnd.nextInt(255);
-            if (r < 0) r = -r;
-            int g = _rnd.nextInt(255);
-            if (g < 0) g = -g;
-            int b = _rnd.nextInt(255);
-            if (b < 0) b = -b;
-            //_color.setBackground(new Color(r, g, b));
-            _color.setBackground(_background);
-            
-            _send.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes));
-            _recv.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes));
-            _lost.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes));
-            _all.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes));
-            _color.addActionListener(new ChooseColor(durationMinutes, _color));
-            _color.setEnabled(false);
-        }
-    }
-    
-    private class UpdateListener implements ActionListener {
-        private OptionLine _line;
-        private int _minutes;
-
-        /**
-         * Update Listener constructor . . . 
-         * @param line the line
-         * @param minutes the minutes
-         */
-        public UpdateListener(OptionLine line, int minutes) {
-            _line = line;
-            _minutes = minutes;
-        }
-        
-        /* (non-Javadoc)
-         * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
-         */
-        public void actionPerformed(ActionEvent evt) { 
-            PeerPlotConfig.PlotSeriesConfig cfg = getConfig(_minutes);
-            
-            cfg.getPlotConfig().disableEvents();
-            _log.debug("Updating data for minutes ["+ _line._durationMinutes + "]: send [" + 
-                       _line._send.isSelected() + "/" + cfg.getPlotSendTime() + "] recv [" + 
-                       _line._recv.isSelected() + "/" + cfg.getPlotReceiveTime() + "] lost [" +
-                       _line._lost.isSelected() + "/" + cfg.getPlotLostMessages() + "]: config = " + cfg);
-            
-            boolean force = _line._all.isSelected();
-            cfg.setPlotSendTime(_line._send.isSelected() || force);
-            cfg.setPlotReceiveTime(_line._recv.isSelected() || force);
-            cfg.setPlotLostMessages(_line._lost.isSelected() || force);
-            cfg.getPlotConfig().enableEvents();
-            cfg.getPlotConfig().fireUpdate();
-        } 
-    }
-    
-    /**
-     * Unit test stuff
-     * @param args da arsg
-     */
-    public final static void main(String args[]) {
-        Test t = new Test();
-        t.runTest();
-    }
-    
-    private final static class Test implements PeerPlotStateFetcher.FetchStateReceptor {
-        /**
-         * Runs da test
-         */
-        public void runTest() {
-            PeerPlotConfig cfg = new PeerPlotConfig("C:\\testnet\\r2\\heartbeatStat_10s_30kb.txt");
-            PeerPlotState state = new PeerPlotState(cfg);
-            PeerPlotStateFetcher.fetchPeerPlotState(this, state);
-            try { Thread.sleep(60*1000); } catch (InterruptedException ie) {}
-            System.exit(-1);
-        }
-        
-        /* (non-Javadoc)
-         * @see net.i2p.heartbeat.gui.PeerPlotStateFetcher.FetchStateReceptor#peerPlotStateFetched(net.i2p.heartbeat.gui.PeerPlotState)
-         */
-        public void peerPlotStateFetched(PeerPlotState state) {
-            javax.swing.JFrame f = new javax.swing.JFrame("Test");
-            f.getContentPane().add(new JScrollPane(new PeerPlotConfigPane(state.getPlotConfig(), null)));
-            f.pack();
-            f.setVisible(true);
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotState.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotState.java
deleted file mode 100644
index d658081a39..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotState.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-
-/**
- * Current data + plot config for a particular test
- * 
- */
-class PeerPlotState {
-    private StaticPeerData _currentData;
-    private PeerPlotConfig _plotConfig;
-    
-    /**
-     * Delegating constructor . . .
-     * @see PeerPlotState#PeerPlotState(PeerPlotConfig, StaticPeerData)
-     */
-    public PeerPlotState() {
-        this(null, null);
-    }
-    
-    /**
-     * Delegating constructor . . .
-     * @param config plot config
-     * @see PeerPlotState#PeerPlotState(PeerPlotConfig, StaticPeerData)
-     */
-    public PeerPlotState(PeerPlotConfig config) {
-        this(config, new StaticPeerData(config.getClientConfig()));
-    }
-    /**
-     * Creates a PeerPlotState
-     * @param config plot config
-     * @param data peer data
-     */
-    public PeerPlotState(PeerPlotConfig config, StaticPeerData data) {
-        _plotConfig = config;
-        _currentData = data;
-    }
-    
-    /**
-     * Add an average
-     * @param minutes mins averaged over
-     * @param sendMs how much later did the peer receieve
-     * @param recvMs how much later did we receieve
-     * @param lost how many were lost
-     */
-    public void addAverage(int minutes, int sendMs, int recvMs, int lost) {
-        // make sure we've got the config entry for the average
-        _plotConfig.addAverage(minutes);
-        // add the data point...
-        _currentData.addAverage(minutes, sendMs, recvMs, lost);
-    }
-    
-    /**
-     * we successfully got a ping/pong through
-     *
-     * @param sendTime when did the ping get sent?
-     * @param sendMs how much later did the peer receive the ping?
-     * @param recvMs how much later than that did we receive the pong? 
-     */
-    public void addSuccess(long sendTime, int sendMs, int recvMs) {
-        _currentData.addData(sendTime, sendMs, recvMs);
-    }
-    
-    /**
-     * we lost a ping/pong
-     *
-     * @param sendTime when did we send the ping?
-     */
-    public void addLost(long sendTime) {
-        _currentData.addData(sendTime);
-    }
-    
-    /**
-     * data set to render 
-     * @return the data set
-     */
-    public StaticPeerData getCurrentData() { return _currentData; }
-
-    /**
-     * Sets the data set to render
-     * @param data the data set
-     */
-    public void setCurrentData(StaticPeerData data) { _currentData = data; }
-    
-    /**
-     * configuration options on how to render the data set 
-     * @return the config options
-     */
-    public PeerPlotConfig getPlotConfig() { return _plotConfig; }
-
-    /**
-     * Sets the configuration options on how to render the data
-     * @param config the config options
-     */
-    public void setPlotConfig(PeerPlotConfig config) { _plotConfig = config; }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotStateFetcher.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotStateFetcher.java
deleted file mode 100644
index 82b5aa73ae..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotStateFetcher.java
+++ /dev/null
@@ -1,363 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Locale;
-import java.util.StringTokenizer;
-
-import net.i2p.data.DataFormatException;
-import net.i2p.data.Destination;
-import net.i2p.util.I2PThread;
-import net.i2p.util.Log;
-
-class PeerPlotStateFetcher {
-    private final static Log _log = new Log(PeerPlotStateFetcher.class);
-    
-    /**
-     * Fetch and fill the specified state structure
-     * @param receptor the 'receptor' (callbacks)
-     * @param state the state
-     */
-    public static void fetchPeerPlotState(FetchStateReceptor receptor, PeerPlotState state) {
-        I2PThread t = new I2PThread(new Fetcher(receptor, state));
-        t.setDaemon(true);
-        t.setName("Fetch state from " + state.getPlotConfig().getLocation());
-        t.start();
-    }
-    
-    /**
-     * Callback stuff . . .
-     */
-    public interface FetchStateReceptor {
-        /**
-         * Called when a peer plot state is fetched
-         * @param state state that was fetched
-         */
-        void peerPlotStateFetched(PeerPlotState state);
-    }
-    
-    private static class Fetcher implements Runnable {
-        private PeerPlotState _state;
-        private FetchStateReceptor _receptor;
-
-        /**
-         * Creates a Fetcher thread
-         * @param receptor the 'receptor' (callbacks)
-         * @param state the state
-         */
-        public Fetcher(FetchStateReceptor receptor, PeerPlotState state) {
-            _state = state;
-            _receptor = receptor;
-        }
-        
-        /* (non-Javadoc)
-         * @see java.lang.Runnable#run()
-         */
-        public void run() {
-            String loc = _state.getPlotConfig().getLocation();
-            _log.debug("Load called [" + loc + "]");
-            InputStream in = null;
-            try {
-                try {
-                    URL location = new URL(loc);
-                    in = location.openStream();
-                } catch (MalformedURLException mue) {
-                    _log.debug("Not a url [" + loc + "]");
-                    in = null;
-                }
-                
-                if (in == null)
-                    in = new FileInputStream(loc);
-                
-                BufferedReader reader = new BufferedReader(new InputStreamReader(in));
-                String line = null;
-                while ( (line = reader.readLine()) != null) {
-                    handleLine(line);
-                }
-                
-                if (valid())
-                    _receptor.peerPlotStateFetched(_state);
-            } catch (IOException ioe) {
-                _log.error("Error retrieving from the location [" + loc + "]", ioe);
-            } finally {
-                if (in != null) try { in.close(); } catch (IOException ioe) {}
-            }
-        }
-        
-        /** 
-         * check to make sure we've got everything we need 
-         * @return true [always]
-         */
-        boolean valid() {
-            return true;
-        }
-        
-        /**
-         * handle a line from the data set - these can be formatted in one of the
-         * following ways.  <p />
-         *
-         * <pre>
-         * peer            khWYqCETu9YtPUvGV92ocsbEW5DezhKlIG7ci8RLX3g=
-         * local           u-9hlR1ik2hemXf0HvKMfeRgrS86CbNQh25e7XBhaQE=
-         * peerDest        [base 64 of the full destination]
-         * localDest       [base 64 of the full destination]
-         * numTunnelHops   2
-         * comment         Test with localhost sending 30KB every 20 seconds
-         * sendFrequency   20
-         * sendSize        30720
-         * sessionStart    20040409.22:51:10.915
-         * currentTime     20040409.23:31:39.607
-         * numPending      2
-         * lifetimeSent    118
-         * lifetimeRecv    113
-         * #averages       minutes sendMs  recvMs  numLost
-         * periodAverage   1       1843    771     0
-         * periodAverage   5       786     752     1
-         * periodAverage   30      855     735     3
-         * #action status  date and time sent      sendMs  replyMs
-         * EVENT   OK      20040409.23:21:44.742   691     670
-         * EVENT   OK      20040409.23:22:05.201   671     581
-         * EVENT   OK      20040409.23:22:26.301   1182    1452
-         * EVENT   OK      20040409.23:22:47.322   24304   1723
-         * EVENT   OK      20040409.23:23:08.232   2293    1081
-         * EVENT   OK      20040409.23:23:29.332   1392    641
-         * EVENT   OK      20040409.23:23:50.262   641     761
-         * EVENT   OK      20040409.23:24:11.102   651     701
-         * EVENT   OK      20040409.23:24:31.401   841     621
-         * EVENT   OK      20040409.23:24:52.061   651     681
-         * EVENT   OK      20040409.23:25:12.480   701     1623
-         * EVENT   OK      20040409.23:25:32.990   1442    1212
-         * EVENT   OK      20040409.23:25:54.230   591     631
-         * EVENT   OK      20040409.23:26:14.620   620     691
-         * EVENT   OK      20040409.23:26:35.199   1793    1432
-         * EVENT   OK      20040409.23:26:56.570   661     641
-         * EVENT   OK      20040409.23:27:17.200   641     660
-         * EVENT   OK      20040409.23:27:38.120   611     921
-         * EVENT   OK      20040409.23:27:58.699   831     621
-         * EVENT   OK      20040409.23:28:19.559   801     661
-         * EVENT   OK      20040409.23:28:40.279   601     611
-         * EVENT   OK      20040409.23:29:00.648   601     621
-         * EVENT   OK      20040409.23:29:21.288   701     661
-         * EVENT   LOST    20040409.23:29:41.828
-         * EVENT   LOST    20040409.23:30:02.327
-         * EVENT   LOST    20040409.23:30:22.656
-         * EVENT   OK      20040409.23:31:24.305   1843    771
-         * </pre>
-         * 
-         * @param line (see above)
-         */
-        private void handleLine(String line) {
-            if (line.startsWith("peerDest"))
-                handlePeerDest(line);
-            else if (line.startsWith("localDest"))
-                handleLocalDest(line);
-            else if (line.startsWith("numTunnelHops"))
-                handleNumTunnelHops(line);
-            else if (line.startsWith("comment"))
-                handleComment(line);
-            else if (line.startsWith("sendFrequency"))
-                handleSendFrequency(line);
-            else if (line.startsWith("sendSize"))
-                handleSendSize(line);
-            else if (line.startsWith("periodAverage"))
-                handlePeriodAverage(line);
-            else if (line.startsWith("EVENT"))
-                handleEvent(line);
-            else if (line.startsWith("numPending"))
-                handleNumPending(line);
-            else if (line.startsWith("sessionStart"))
-                handleSessionStart(line);
-            else
-                _log.debug("Not handled: " + line);
-        }
-        
-        private void handlePeerDest(String line) {
-            StringTokenizer tok = new StringTokenizer(line);
-            tok.nextToken(); // ignore;
-            String destKey = tok.nextToken();
-            try {
-                Destination d = new Destination();
-                d.fromBase64(destKey);
-                _state.getPlotConfig().getClientConfig().setPeer(d);
-                _log.debug("Setting the peer to " + d.calculateHash().toBase64());
-            } catch (DataFormatException dfe) {
-                _log.error("Unable to parse the peerDest line: [" + line + "]", dfe);
-            }
-        }
-        
-        private void handleLocalDest(String line) {
-            StringTokenizer tok = new StringTokenizer(line);
-            tok.nextToken(); // ignore;
-            String destKey = tok.nextToken();
-            try {
-                Destination d = new Destination();
-                d.fromBase64(destKey);
-                _state.getPlotConfig().getClientConfig().setUs(d);
-            } catch (DataFormatException dfe) {
-                _log.error("Unable to parse the localDest line: [" + line + "]", dfe);
-            }
-        }
-        
-        private void handleComment(String line) {
-            StringTokenizer tok = new StringTokenizer(line);
-            tok.nextToken(); // ignore;
-            StringBuffer buf = new StringBuffer(line.length()-32);
-            while (tok.hasMoreTokens())
-                buf.append(tok.nextToken()).append(' ');
-            _state.getPlotConfig().getClientConfig().setComment(buf.toString());
-        }
-        
-        private void handleNumTunnelHops(String line) {
-            StringTokenizer tok = new StringTokenizer(line);
-            tok.nextToken(); // ignore;
-            String num = tok.nextToken();
-            try {
-                int val = Integer.parseInt(num);
-                _state.getPlotConfig().getClientConfig().setNumHops(val);
-            } catch (NumberFormatException nfe) {
-                _log.error("Unable to parse the numTunnelHops line: [" + line + "]", nfe);
-            }
-        }
-        
-        private void handleNumPending(String line) {
-            StringTokenizer tok = new StringTokenizer(line);
-            tok.nextToken(); // ignore;
-            String num = tok.nextToken();
-            try {
-                int val = Integer.parseInt(num);
-                _state.getCurrentData().setPendingCount(val);
-            } catch (NumberFormatException nfe) {
-                _log.error("Unable to parse the numPending line: [" + line + "]", nfe);
-            }
-        }
-        
-        private void handleSendFrequency(String line) {
-            StringTokenizer tok = new StringTokenizer(line);
-            tok.nextToken(); // ignore;
-            String num = tok.nextToken();
-            try {
-                int val = Integer.parseInt(num);
-                _state.getPlotConfig().getClientConfig().setSendFrequency(val);
-            } catch (NumberFormatException nfe) {
-                _log.error("Unable to parse the sendFrequency line: [" + line + "]", nfe);
-            }
-        }
-        
-        private void handleSendSize(String line) {
-            StringTokenizer tok = new StringTokenizer(line);
-            tok.nextToken(); // ignore;
-            String num = tok.nextToken();
-            try {
-                int val = Integer.parseInt(num);
-                _state.getPlotConfig().getClientConfig().setSendSize(val);
-            } catch (NumberFormatException nfe) {
-                _log.error("Unable to parse the sendSize line: [" + line + "]", nfe);
-            }
-        }
-        
-        private void handleSessionStart(String line) {
-            StringTokenizer tok = new StringTokenizer(line);
-            tok.nextToken(); // ignore;
-            String date = tok.nextToken();
-            try {
-                long when = getDate(date);
-                _state.getCurrentData().setSessionStart(when);
-            } catch (NumberFormatException nfe) {
-                _log.error("Unable to parse the sessionStart line: [" + line + "]", nfe);
-            }
-        }
-        
-        private void handlePeriodAverage(String line) {
-            StringTokenizer tok = new StringTokenizer(line);
-            tok.nextToken(); // ignore;
-            try {
-                // periodAverage minutes sendMs  recvMs  numLost
-                int min = Integer.parseInt(tok.nextToken());
-                int send = Integer.parseInt(tok.nextToken());
-                int recv = Integer.parseInt(tok.nextToken());
-                int lost = Integer.parseInt(tok.nextToken());
-                _state.addAverage(min, send, recv, lost);
-            } catch (NumberFormatException nfe) {
-                _log.error("Unable to parse the sendSize line: [" + line + "]", nfe);
-            }
-        }
-        
-        private void handleEvent(String line) {
-            StringTokenizer tok = new StringTokenizer(line);
-            
-            // * EVENT   OK      20040409.23:29:21.288   701     661
-            // * EVENT   LOST    20040409.23:29:41.828
-            tok.nextToken(); // ignore first two
-            tok.nextToken();
-            try {
-                long when = getDate(tok.nextToken());
-                if (when < 0) {
-                    _log.error("Invalid EVENT line: [" + line + "]");
-                    return;
-                }
-                if (tok.hasMoreTokens()) {
-                    int sendMs = Integer.parseInt(tok.nextToken());
-                    int recvMs = Integer.parseInt(tok.nextToken());
-                    _state.addSuccess(when, sendMs, recvMs);
-                } else {
-                    _state.addLost(when);
-                }
-            } catch (NumberFormatException nfe) {
-                _log.error("Unable to parse the EVENT line: [" + line + "]", nfe);
-            }
-        }
-        
-        private static final SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd.HH:mm:ss.SSS", Locale.UK);
-        private long getDate(String date) {
-            synchronized (_fmt) {
-                try {
-                    return _fmt.parse(date).getTime();
-                } catch (ParseException pe) {
-                    _log.error("Unable to parse the date [" + date + "]", pe);
-                    return -1;
-                }
-            }
-        }
-        
-        private void fakeRun() { /* UNUSED */
-            try {
-                Destination peer = new Destination();
-                Destination us = new Destination();
-                peer.fromBase64("3RPLOkQGlq8anNyNWhjbMyHxpAvUyUJKbiUejI80DnPR59T3blc7-XrBhQ2iPbf-BRAR~v1j34Kpba1eDyhPk2gevsE6ULO1irarJ3~C9WcQH2wAbNiVwfWqbh6onQ~YmkSpGNwGHD6ytwbvTyXeBJ" +
-                                "cS8e6gmfNN-sYLn1aQu8UqWB3D6BmTfLtyS3eqWVk66Nrzmwy8E1Hvq5z~1lukYb~cyiDO1oZHAOLyUQtd9eN16yJY~2SRG8LiscpPMl9nSJUr6fmXMUubW-M7QGFH82Om-735PJUk6WMy1Hi9Vgh4Pxhdl7g" +
-                                "fqGRWioFABdhcypb7p1Ca77p73uabLDFK-SjIYmdj7TwSdbNa6PCmzEvCEW~IZeZmnZC5B6pK30AdmD9vc641wUGce9xTJVfNRupf5L7pSsVIISix6FkKQk-FTW2RsZKLbuMCYMaPzLEx5gzODEqtI6Jf2teM" +
-                                "d5xCz51RPayDJl~lJ-W0IWYfosnjM~KxYaqc4agviBuF5ZWeAAAA");
-                us.fromBase64("W~JFpqSH8uopylox2V5hMbpcHSsb-dJkSKvdJ1vj~KQcUFJWXFyfbetBAukcGH5S559aK9oslU0qbVoMDlJITVC4OXfXSnVbJBP1IhsK8SvjSYicjmIi2fA~k4HvSh9Wxu~bg8yo~jgfHA8tjYpp" +
-                              "K9QKc56BpkJb~hx0nNGy4Ny9eW~6A5AwAmHvwdt5NqcREYRMjRd63dMGm8BcEe-6FbOyMo3dnIFcETWAe8TCeoMxm~S1n~6Jlinw3ETxv-L6lQkhFFWnC5zyzQ~4JhVxxT3taTMYXg8td4CBGmrS078jcjW63" +
-                              "rlSiQgZBlYfN3iEYmurhuIEV9NXRcmnMrBOQUAoXPpVuRIxJbaQNDL71FO2iv424n4YjKs84suAho34GGQKq7WoL5V5KQgihfcl0f~xne-qP3FtpoPFeyA9x-sA2JWDAsxoZlfvgkiP5eyOn23prT9TJK47HC" +
-                              "VilHSV11uTVaC4Jc5YsjoBCZadWbgQnMCKlZ4jk-bLE1PSWLg7AAAA");
-                _state.getPlotConfig().getClientConfig().setPeer(peer);
-                _state.getPlotConfig().getClientConfig().setUs(us);
-                _state.getPlotConfig().getClientConfig().setNumHops(2);
-                _state.getPlotConfig().getClientConfig().setComment("we do stuff\nreally nifty stuff.  really");
-                _state.getPlotConfig().getClientConfig().setAveragePeriods(new int[] { 1, 5, 30, 60 });
-                int rnd = new java.util.Random().nextInt();
-                if (rnd > 0) 
-                    rnd = rnd % 10;
-                else
-                    rnd = (-rnd) % 10;
-                _state.getPlotConfig().getClientConfig().setSendFrequency(rnd);
-                _state.getPlotConfig().getClientConfig().setSendSize(16*1024);
-                _state.getPlotConfig().getClientConfig().setStatDuration(10);
-                _state.getPlotConfig().rebuildAverageSeriesConfigs();
-                _state.setCurrentData(new StaticPeerData(_state.getPlotConfig().getClientConfig()));
-                
-                _receptor.peerPlotStateFetched(_state);
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/StaticPeerData.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/StaticPeerData.java
deleted file mode 100644
index bcd20ca804..0000000000
--- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/StaticPeerData.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package net.i2p.heartbeat.gui;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import net.i2p.heartbeat.ClientConfig;
-import net.i2p.heartbeat.PeerData;
-
-/**
- * Raw data points for a test
- */
-class StaticPeerData extends PeerData {
-    private int _pending;
-    /** Integer (period, in minutes) to Integer (milliseconds) for sending a ping */
-    private Map _averageSendTimes;
-    /** Integer (period, in minutes) to Integer (milliseconds) for receiving a pong */
-    private Map _averageReceiveTimes;
-    /** Integer (period, in minutes) to Integer (num messages) of how many messages were lost on average */
-    private Map _lostMessages;
-    
-    /**
-     * Creates a static peer data with a specified client config ... duh
-     * @param config the client config
-     */
-    public StaticPeerData(ClientConfig config) {
-        super(config);
-        _averageSendTimes = new HashMap(4);
-        _averageReceiveTimes = new HashMap(4);
-        _lostMessages = new HashMap(4);
-    }
-    
-    /**
-     * Adds averaged data
-     * @param minutes the minutes (averaged over)
-     * @param sendMs the send time (ping) in milliseconds
-     * @param recvMs the receive time (pong) in milliseconds
-     * @param lost the number lost
-     */
-    public void addAverage(int minutes, int sendMs, int recvMs, int lost) {
-        _averageSendTimes.put(new Integer(minutes), new Integer(sendMs));
-        _averageReceiveTimes.put(new Integer(minutes), new Integer(recvMs));
-        _lostMessages.put(new Integer(minutes), new Integer(lost));
-    }
-    
-    /**
-     * Sets the number pending
-     * @param numPending the number pending
-     */
-    public void setPendingCount(int numPending) { _pending = numPending; }
-
-    /* (non-Javadoc)
-     * @see net.i2p.heartbeat.PeerData#setSessionStart(long)
-     */
-    public void setSessionStart(long when) { super.setSessionStart(when); }
-    
-    /**
-     * Adds data
-     * @param sendTime the time it was sent
-     * @param sendMs the send time (ping) in milliseconds
-     * @param recvMs the receive time (pong) in milliseconds
-     */
-    public void addData(long sendTime, int sendMs, int recvMs) {
-        PeerData.EventDataPoint dataPoint = new PeerData.EventDataPoint(sendTime);
-        dataPoint.setPongSent(sendTime + sendMs);
-        dataPoint.setPongReceived(sendTime + sendMs + recvMs);
-        dataPoint.setWasPonged(true);
-        addDataPoint(dataPoint);
-    }
-    
-    /**
-     * Adds data
-     * @param sendTime the time it was sent
-     */
-    public void addData(long sendTime) {
-        PeerData.EventDataPoint dataPoint = new PeerData.EventDataPoint(sendTime);
-        dataPoint.setWasPonged(false);
-        addDataPoint(dataPoint);
-    }
-
-    /** 
-     * how many pings are still outstanding?
-     * @return the number of pings outstanding
-     */
-    public int getPendingCount() { return _pending; }
-    
-    
-    /** 
-     * average time to send over the given period.
-     *
-     * @param period number of minutes to retrieve the average for
-     * @return milliseconds average, or -1 if we dont track that period
-     */
-    public double getAverageSendTime(int period) { 
-        Integer i = (Integer)_averageSendTimes.get(new Integer(period));
-        if (i == null)
-            return -1;
-
-        return i.doubleValue();
-    }
-    
-    
-    /** 
-     * average time to receive over the given period.
-     *
-     * @param period number of minutes to retrieve the average for
-     * @return milliseconds average, or -1 if we dont track that period
-     */
-    public double getAverageReceiveTime(int period) {
-        Integer i = (Integer)_averageReceiveTimes.get(new Integer(period));
-        if (i == null)
-            return -1;
-
-        return i.doubleValue();
-    }
-       
-    /** 
-     * number of lost messages over the given period.
-     *
-     * @param period number of minutes to retrieve the average for
-     * @return number of lost messages in the period, or -1 if we dont track that period
-     */
-    public double getLostMessages(int period) {
-        Integer i = (Integer)_lostMessages.get(new Integer(period));
-        if (i == null)
-            return -1;
-
-        return i.doubleValue();
-    }
-        
-    /* (non-Javadoc)
-     * @see net.i2p.heartbeat.PeerData#cleanup()
-     */
-    public void cleanup() {}
-}
\ No newline at end of file
diff --git a/apps/httptunnel/doc/COPYING b/apps/httptunnel/doc/COPYING
deleted file mode 100644
index 5ec43ee156..0000000000
--- a/apps/httptunnel/doc/COPYING
+++ /dev/null
@@ -1,278 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
diff --git a/apps/httptunnel/doc/readme.license.txt b/apps/httptunnel/doc/readme.license.txt
deleted file mode 100644
index 7f7c30bc7e..0000000000
--- a/apps/httptunnel/doc/readme.license.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-$Id$
-
-the i2p/apps/httptunnel module is the root of the 
-HTTPTunnel application, and everything within it 
-is released according to the terms of the I2P 
-license policy.  That means everything contained 
-within the i2p/apps/httptunnel module is released 
-under the GPL plus the java exception unless 
-otherwise marked.  Alternate licenses that may be 
-used include BSD, Cryptix, and MIT, as well as
-code granted into the public domain.
diff --git a/apps/httptunnel/java/build.xml b/apps/httptunnel/java/build.xml
deleted file mode 100644
index 9dfe9ac589..0000000000
--- a/apps/httptunnel/java/build.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project basedir="." default="all" name="httptunnel">
-    <target name="all" depends="clean, build" />
-    <target name="build" depends="builddep, jar" />
-    <target name="builddep">
-        <ant dir="../../ministreaming/java/" target="build" />
-	<!-- ministreaming will build core -->
-    </target>
-    <target name="compile">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/obj" />
-        <javac 
-            srcdir="./src" 
-            debug="true" deprecation="on" source="1.3" target="1.3" 
-            destdir="./build/obj" 
-            classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" />
-    </target>
-    <target name="jar" depends="compile">
-        <jar destfile="./build/httptunnel.jar" basedir="./build/obj" includes="**/*.class">
-            <manifest>
-                <attribute name="Main-Class" value="net.i2p.httptunnel.HTTPTunnel" />
-                <attribute name="Class-Path" value="i2p.jar mstreaming.jar" />
-            </manifest>
-        </jar>
-    </target>
-    <target name="javadoc">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/javadoc" />
-        <javadoc 
-            sourcepath="./src:../../../core/java/src:../../ministreaming/java/src" destdir="./build/javadoc" 
-            packagenames="*" 
-            use="true" 
-            splitindex="true" 
-            windowtitle="HTTPTunnel" />
-    </target>
-    <target name="clean">
-        <delete dir="./build" />
-    </target>
-    <target name="cleandep" depends="clean">
-	<!-- ministreaming will clean core -->
-        <ant dir="../../ministreaming/java/" target="distclean" />
-    </target>
-    <target name="distclean" depends="clean">
-	<!-- ministreaming will clean core -->
-        <ant dir="../../ministreaming/java/" target="distclean" />
-    </target>
-</project>
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPListener.java b/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPListener.java
deleted file mode 100644
index 34ad8faa11..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPListener.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package net.i2p.httptunnel;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-
-import net.i2p.util.Log;
-
-/**
- * Listens on a port for HTTP connections.
- */
-public class HTTPListener extends Thread {
-
-    private static final Log _log = new Log(HTTPListener.class);
-
-    private int port;
-    private String listenHost;
-    private SocketManagerProducer smp;
-
-    /**
-     * A public constructor.  It contstructs things.  In this case, 
-     * it constructs a nice HTTPListener, for all your listening on
-     * HTTP needs.  Yep.  That's right.
-     * @param smp A SocketManagerProducer, producing Sockets, no doubt
-     * @param port A port, to connect to.
-     * @param listenHost A host, to connect to.
-     */
-
-    public HTTPListener(SocketManagerProducer smp, int port, String listenHost) {
-        this.smp = smp;
-        this.port = port;
-        start();
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Thread#run()
-     */
-    public void run() {
-        try {
-            InetAddress lh = listenHost == null ? null : InetAddress.getByName(listenHost);
-            ServerSocket ss = new ServerSocket(port, 0, lh);
-            while (true) {
-                Socket s = ss.accept();
-                new HTTPSocketHandler(this, s);
-            }
-        } catch (IOException ex) {
-            _log.error("Error while accepting connections", ex);
-        }
-    }
-
-    private boolean proxyUsed = false;
-
-    /**
-     * Query whether this is the first use of the proxy or not
-     * @return Whether this is the first proxy use, no doubt.
-     */
-    public boolean firstProxyUse() {
-        if (true) return false; // FIXME: check a config option here
-        
-        if (proxyUsed) {
-            return false;
-        }
-
-        proxyUsed = true;
-        return true;
-    }
-
-    /**
-     * @return The SocketManagerProducer being used.
-     */
-    public SocketManagerProducer getSMP() {
-        return smp;
-    }
-
-    /** 
-     * Outputs with HTTP 1.1 flair that a feature isn't implemented.
-     * @param out The stream the text goes to.
-     * @deprecated
-     * @throws IOException
-     */
-    public void handleNotImplemented(OutputStream out) throws IOException {
-        out.write(("HTTP/1.1 200 Document following\n\n" + "<h1>Feature not implemented</h1>").getBytes("ISO-8859-1"));
-        out.flush();
-    }
-}
\ No newline at end of file
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPSocketHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPSocketHandler.java
deleted file mode 100644
index b5a15e019d..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPSocketHandler.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package net.i2p.httptunnel;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-
-import net.i2p.httptunnel.handler.RootHandler;
-import net.i2p.util.Log;
-
-/**
- * Handles a single HTTP socket connection.
- */
-public class HTTPSocketHandler extends Thread {
-
-    private static final Log _log = new Log(HTTPSocketHandler.class);
-
-    private Socket s;
-    private HTTPListener httpl;
-    private RootHandler h;
-
-    /**
-     * A public constructor.
-     * @param httpl An HTTPListener, to listen for HTTP, no doubt
-     * @param s A socket.
-     */
-    public HTTPSocketHandler(HTTPListener httpl, Socket s) {
-        this.httpl = httpl;
-        this.s = s;
-        h = RootHandler.getInstance();
-        start();
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Thread#run()
-     */
-    public void run() {
-        InputStream in = null;
-        OutputStream out = null;
-        try {
-            in = new BufferedInputStream(s.getInputStream());
-            out = new BufferedOutputStream(s.getOutputStream());
-            Request req = new Request(in);
-            h.handle(req, httpl, out);
-        } catch (IOException ex) {
-            _log.error("Error while handling data", ex);
-        } finally {
-            try {
-                if (in != null) in.close();
-                if (out != null) {
-                    out.flush();
-                    out.close();
-                }
-                s.close();
-            } catch (IOException ex) {
-                _log.error("IOException in finalizer", ex);
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPTunnel.java b/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPTunnel.java
deleted file mode 100644
index 4ff9325f0f..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPTunnel.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * HTTPTunnel
- * (c) 2003 - 2004 mihi
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2, or (at
- * your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * In addition, as a special exception, mihi gives permission to link
- * the code of this program with the proprietary Java implementation
- * provided by Sun (or other vendors as well), and distribute linked
- * combinations including the two. You must obey the GNU General
- * Public License in all respects for all of the code used other than
- * the proprietary Java implementation. If you modify this file, you
- * may extend this exception to your version of the file, but you are
- * not obligated to do so. If you do not wish to do so, delete this
- * exception statement from your version.
- */
-package net.i2p.httptunnel;
-
-import net.i2p.client.streaming.I2PSocketManager;
-
-/**
- * HTTPTunnel main class.
- */
-public class HTTPTunnel {
-
-    /**
-     * Create a HTTPTunnel instance.
-     * 
-     * @param initialManagers a list of socket managers to use
-     * @param maxManagers how many managers to have in the cache
-     * @param shouldThrowAwayManagers whether to throw away a manager after use
-     * @param listenPort which port to listen on
-     */
-    public HTTPTunnel(I2PSocketManager[] initialManagers, int maxManagers, boolean shouldThrowAwayManagers,
-                      int listenPort) {
-        this(initialManagers, maxManagers, shouldThrowAwayManagers, listenPort, "127.0.0.1", 7654);
-    }
-
-    /**
-     * Create a HTTPTunnel instance.
-     * 
-     * @param initialManagers a list of socket managers to use
-     * @param maxManagers how many managers to have in the cache
-     * @param shouldThrowAwayManagers whether to throw away a manager after use
-     * @param listenPort which port to listen on
-     * @param i2cpAddress the I2CP address
-     * @param i2cpPort the I2CP port
-     */
-    public HTTPTunnel(I2PSocketManager[] initialManagers, int maxManagers, boolean shouldThrowAwayManagers,
-                      int listenPort, String i2cpAddress, int i2cpPort) {
-        SocketManagerProducer smp = new SocketManagerProducer(initialManagers, maxManagers, shouldThrowAwayManagers,
-                                                              i2cpAddress, i2cpPort);
-        new HTTPListener(smp, listenPort, "127.0.0.1");
-    }
-
-    /**
-     * The all important main function, allowing HTTPTunnel to be 
-     * stand-alone, a program in it's own right, and all that jazz.
-     * @param args A list of String passed to the program
-     */
-    public static void main(String[] args) {
-        String host = "127.0.0.1";
-        int port = 7654, max = 1;
-        boolean throwAwayManagers = false;
-        if (args.length > 1) {
-            if (args.length == 4) {
-                host = args[2];
-                port = Integer.parseInt(args[3]);
-            } else if (args.length != 2) {
-                showInfo();
-                return;
-            }
-            max = Integer.parseInt(args[1]);
-        } else if (args.length != 1) {
-            showInfo();
-            return;
-        }
-        if (max == 0) {
-            max = 1;
-        } else if (max < 0) {
-            max = -max;
-            throwAwayManagers = true;
-        }
-        new HTTPTunnel(null, max, throwAwayManagers, Integer.parseInt(args[0]), host, port);
-    }
-
-    private static void showInfo() {
-        System.out.println("Usage: java HTTPTunnel <listenPort> [<max> " + "[<i2cphost> <i2cpport>]]\n"
-                           + "  <listenPort>  port to listen for browsers\n"
-                           + "  <max>         max number of SocketMangers in pool, " + "use neg. number\n"
-                           + "                to use each SocketManager only once " + "(default: 1)\n"
-                           + "  <i2cphost>    host to connect to the router " + "(default: 127.0.0.1)\n"
-                           + "  <i2cpport>    port to connect to the router " + "(default: 7654)");
-    }
-}
\ No newline at end of file
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/Request.java b/apps/httptunnel/java/src/net/i2p/httptunnel/Request.java
deleted file mode 100644
index b28aef795e..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/Request.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package net.i2p.httptunnel;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.StringReader;
-
-import net.i2p.util.Log;
-
-/**
- * A HTTP request (GET or POST). This will be passed to a hander for
- * handling it.
- */
-public class Request {
-
-    private static final Log _log = new Log(Request.class);
-
-    // all strings are forced to be ISO-8859-1 encoding
-    private String method;
-    private String url;
-    private String proto;
-    private String params;
-    private String postData;
-
-    /**
-     * A constructor, creating a request from an InputStream
-     * @param in InputStream from which we "read-in" a Request
-     * @throws IOException
-     */
-    public Request(InputStream in) throws IOException {
-        BufferedReader br = new BufferedReader(new InputStreamReader(in, "ISO-8859-1"));
-        String line = br.readLine();
-        if (line == null) { // no data at all
-            method = null;
-            _log.error("Connection but no data");
-            return;
-        }
-        int pos = line.indexOf(" ");
-        if (pos == -1) {
-            method = line;
-            url = "";
-            _log.error("Malformed HTTP request: " + line);
-        } else {
-            method = line.substring(0, pos);
-            url = line.substring(pos + 1);
-        }
-        proto = "";
-        pos = url.indexOf(" ");
-        if (pos != -1) {
-            proto = url.substring(pos); // leading space intended
-            url = url.substring(0, pos);
-        }
-        StringBuffer sb = new StringBuffer(512);
-        while ((line = br.readLine()) != null) {
-            if (line.length() == 0) break;
-            sb.append(line).append("\r\n");
-        }
-        params = sb.toString(); // no leading empty line!
-        sb = new StringBuffer();
-        // hack for POST requests, ripped from HttpClient
-        // this won't work for large POSTDATA
-        // FIXME: do this better, please.
-        if (!method.equals("GET")) {
-            while (br.ready()) { // empty the buffer (POST requests)
-                int i = br.read();
-                if (i != -1) {
-                    sb.append((char) i);
-                }
-            }
-            postData = sb.toString();
-        } else {
-            postData = "";
-        }
-    }
-
-    /**
-     * @return A Request as an array of bytes of a String in ISO-8859-1 format
-     * @throws IOException
-     */
-    public byte[] toByteArray() throws IOException {
-        if (method == null) return null;
-        return toISO8859_1String().getBytes("ISO-8859-1");
-
-    }
-
-    private String toISO8859_1String() throws IOException {
-        if (method == null) return null;
-        return method + " " + url + proto + "\r\n" + params + "\r\n" + postData;
-    }
-
-    /**
-     * @return the URL of the request
-     */
-    public String getURL() {
-        return url;
-    }
-
-    /**
-     * Sets the URL of the Request
-     * @param newURL the new URL
-     */
-    public void setURL(String newURL) {
-        url = newURL;
-    }
-
-    /**
-     * Retrieves the value of a param.
-     * @param name The name of the param
-     * @return The value of the param, or null
-     */
-    public String getParam(String name) {
-        try {
-            BufferedReader br = new BufferedReader(new StringReader(params));
-            String line;
-            while ((line = br.readLine()) != null) {
-                if (line.startsWith(name)) { return line.substring(name.length()); }
-            }
-            return null;
-        } catch (IOException ex) {
-            _log.error("Error getting parameter", ex);
-            return null;
-        }
-    }
-
-    /**
-     * Sets the value of a param.
-     * @param name the name of the param
-     * @param value the value to be set
-     */
-    public void setParam(String name, String value) {
-        try {
-            StringBuffer sb = new StringBuffer(params.length() + value.length());
-            BufferedReader br = new BufferedReader(new StringReader(params));
-            String line;
-            boolean replaced = false;
-            while ((line = br.readLine()) != null) {
-                if (line.startsWith(name)) {
-                    replaced = true;
-                    if (value == null) continue; // kill param
-                    line = name + value;
-                }
-                sb.append(line).append("\r\n");
-            }
-            if (!replaced && value != null) {
-                sb.append(name).append(value).append("\r\n");
-            }
-            params = sb.toString();
-        } catch (IOException ex) {
-            _log.error("Error getting parameter", ex);
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/SocketManagerProducer.java b/apps/httptunnel/java/src/net/i2p/httptunnel/SocketManagerProducer.java
deleted file mode 100644
index ddef387f8b..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/SocketManagerProducer.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package net.i2p.httptunnel;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Properties;
-
-import net.i2p.client.streaming.I2PSocketManager;
-import net.i2p.client.streaming.I2PSocketManagerFactory;
-
-/**
- * Produces SocketManagers in a thread and gives them to those who
- * need them.
- */
-public class SocketManagerProducer extends Thread {
-
-    private ArrayList myManagers = new ArrayList();
-    private HashMap usedManagers = new HashMap();
-    private int port;
-    private String host;
-    private int maxManagers;
-    private boolean shouldThrowAwayManagers;
-
-    /**
-     * Public constructor creating a SocketManagerProducer 
-     * @param initialManagers a list of socket managers to use
-     * @param maxManagers how many managers to have in the cache
-     * @param shouldThrowAwayManagers whether to throw away a manager after use
-     * @param host which host to listen on
-     * @param port which port to listen on
-     */
-    public SocketManagerProducer(I2PSocketManager[] initialManagers, int maxManagers, boolean shouldThrowAwayManagers,
-                                 String host, int port) {
-        if (maxManagers < 1) { throw new IllegalArgumentException("maxManagers < 1"); }
-        this.host = host;
-        this.port = port;
-        this.shouldThrowAwayManagers = shouldThrowAwayManagers;
-        if (initialManagers != null) {
-            myManagers.addAll(Arrays.asList(initialManagers));
-        }
-        this.maxManagers = maxManagers;
-        this.shouldThrowAwayManagers = shouldThrowAwayManagers;
-        setDaemon(true);
-        start();
-    }
-
-    /**
-     * Thread producing new SocketManagers.
-     */
-    public void run() {
-        while (true) {
-            synchronized (this) {
-                // without mcDonalds mode, we most probably need no
-                // new managers.
-                while (!shouldThrowAwayManagers && myManagers.size() == maxManagers) {
-                    myWait();
-                }
-            }
-            // produce a new manager, regardless whether it is needed
-            // or not. Do not synchronized this part, since it can be
-            // quite time-consuming.
-            I2PSocketManager newManager = I2PSocketManagerFactory.createManager(host, port, new Properties());
-            // when done, check if it is needed.
-            synchronized (this) {
-                while (myManagers.size() == maxManagers) {
-                    myWait();
-                }
-                myManagers.add(newManager);
-                notifyAll();
-            }
-        }
-    }
-
-    /**
-     * Get a manager for connecting to a given destination. Each
-     * destination will always get the same manager.
-     *
-     * @param dest the destination to connect to
-     * @return the SocketManager to use
-     */
-    public synchronized I2PSocketManager getManager(String dest) {
-        I2PSocketManager result = (I2PSocketManager) usedManagers.get(dest);
-        if (result == null) {
-            result = getManager();
-            usedManagers.put(dest, result);
-        }
-        return result;
-    }
-
-    /**
-     * Get a "new" SocketManager. Depending on the anonymity settings,
-     * this can be a completely new one or one randomly selected from
-     * a pool.
-     *
-     * @return the SocketManager to use
-     */
-    public synchronized I2PSocketManager getManager() {
-        while (myManagers.size() == 0) {
-            myWait(); // no manager here, so wait until one is produced
-        }
-        int which = (int) (Math.random() * myManagers.size());
-        I2PSocketManager result = (I2PSocketManager) myManagers.get(which);
-        if (shouldThrowAwayManagers) {
-            myManagers.remove(which);
-            notifyAll();
-        }
-        return result;
-    }
-
-    /**
-     * Wait until InterruptedException
-     */
-    public void myWait() {
-        try {
-            wait();
-        } catch (InterruptedException ex) {
-            ex.printStackTrace();
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/ChainFilter.java b/apps/httptunnel/java/src/net/i2p/httptunnel/filter/ChainFilter.java
deleted file mode 100644
index b71a194699..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/ChainFilter.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package net.i2p.httptunnel.filter;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Iterator;
-
-import net.i2p.util.Log;
-
-/**
- * Chain multiple filters. Decorator pattern...
- */
-public class ChainFilter implements Filter {
-
-    private static final Log _log = new Log(ChainFilter.class);
-
-    private Collection filters; // perhaps protected?
-
-    /**
-     * @param filters A collection (list) of filters to chain to
-     */
-    public ChainFilter(Collection filters) {
-        this.filters = filters;
-    }
-
-    /* (non-Javadoc)
-     * @see net.i2p.httptunnel.filter.Filter#filter(byte[])
-     */
-    public byte[] filter(byte[] toFilter) {
-        byte[] buf = toFilter;
-        for (Iterator it = filters.iterator(); it.hasNext();) {
-            Filter f = (Filter) it.next();
-            buf = f.filter(buf);
-        }
-        return buf;
-    }
-
-    /* (non-Javadoc)
-     * @see net.i2p.httptunnel.filter.Filter#finish()
-     */
-    public byte[] finish() {
-        // this is a bit complicated. Think about it...
-        try {
-            byte[] buf = EMPTY;
-            for (Iterator it = filters.iterator(); it.hasNext();) {
-                Filter f = (Filter) it.next();
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                if (buf.length != 0) {
-                    baos.write(f.filter(buf));
-                }
-                baos.write(f.finish());
-                buf = baos.toByteArray();
-            }
-            return buf;
-        } catch (IOException ex) {
-            _log.error("Error chaining filters", ex);
-            return EMPTY;
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/Filter.java b/apps/httptunnel/java/src/net/i2p/httptunnel/filter/Filter.java
deleted file mode 100644
index d0ba2b6ff7..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/Filter.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package net.i2p.httptunnel.filter;
-
-/**
- * A generic filtering interface.
- */
-public interface Filter {
-
-    /**
-     * An empty byte array.
-     */
-    public static final byte[] EMPTY = new byte[0];
-
-    /**
-     * Filter some data. Not all filtered data need to be returned.
-     * @param toFilter the bytes that are to be filtered.
-     * @return the filtered data
-     */
-    public byte[] filter(byte[] toFilter);
-
-    /**
-     * Data stream has finished. Return all of the rest data.
-     * @return the rest of the data
-     */
-    public byte[] finish();
-}
\ No newline at end of file
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/NullFilter.java b/apps/httptunnel/java/src/net/i2p/httptunnel/filter/NullFilter.java
deleted file mode 100644
index a609ba5f28..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/NullFilter.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package net.i2p.httptunnel.filter;
-
-/**
- * A filter letting everything pass as is.
- */
-public class NullFilter implements Filter {
-
-    /* (non-Javadoc)
-     * @see net.i2p.httptunnel.filter.Filter#filter(byte[])
-     */
-    public byte[] filter(byte[] toFilter) {
-        return toFilter;
-    }
-
-    /* (non-Javadoc)
-     * @see net.i2p.httptunnel.filter.Filter#finish()
-     */
-    public byte[] finish() {
-        return EMPTY;
-    }
-}
\ No newline at end of file
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/EepHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/handler/EepHandler.java
deleted file mode 100644
index 4e9ffb3677..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/EepHandler.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package net.i2p.httptunnel.handler;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.SocketException;
-
-import net.i2p.I2PAppContext;
-import net.i2p.I2PException;
-import net.i2p.client.streaming.I2PSocket;
-import net.i2p.client.streaming.I2PSocketManager;
-import net.i2p.client.streaming.I2PSocketOptions;
-import net.i2p.data.Destination;
-import net.i2p.httptunnel.HTTPListener;
-import net.i2p.httptunnel.Request;
-import net.i2p.httptunnel.SocketManagerProducer;
-import net.i2p.httptunnel.filter.Filter;
-import net.i2p.httptunnel.filter.NullFilter;
-import net.i2p.util.Log;
-
-/**
- * Handler for browsing Eepsites.
- */
-public class EepHandler {
-
-    private static final Log _log = new Log(EepHandler.class);
-    private static I2PAppContext _context = new I2PAppContext();
-
-    protected ErrorHandler errorHandler;
-
-    /* package private */EepHandler(ErrorHandler eh) {
-        errorHandler = eh;
-    }
-
-    /**
-     * @param req the Request
-     * @param httpl an HTTPListener
-     * @param out where to write the results
-     * @param destination destination as a string, (subject to naming
-     *  service lookup)
-     * @throws IOException
-     */
-    public void handle(Request req, HTTPListener httpl, OutputStream out,
-    /* boolean fromProxy, */String destination) throws IOException {
-        SocketManagerProducer smp = httpl.getSMP();
-        Destination dest = _context.namingService().lookup(destination);
-        if (dest == null) {
-            errorHandler.handle(req, httpl, out, "Could not lookup host: " + destination);
-            return;
-        }
-        I2PSocketManager sm = smp.getManager(destination);
-        Filter f = new NullFilter(); //FIXME: use other filter
-        req.setParam("Host: ", dest.toBase64());
-        if (!handle(req, f, out, dest, sm)) {
-            errorHandler.handle(req, httpl, out, "Unable to reach peer");
-        }
-    }
-
-    /**
-     * @param req the Request to send out
-     * @param f a Filter to apply to the bytes retrieved from the Destination
-     * @param out where to write the results
-     * @param dest the Destination of the Request
-     * @param sm an I2PSocketManager, to get a socket for the Destination
-     * @return boolean, true if something was written, false otherwise.
-     * @throws IOException
-     */
-    public boolean handle(Request req, Filter f, OutputStream out, Destination dest, 
-                          I2PSocketManager sm) throws IOException {
-        I2PSocket s = null;
-        boolean written = false;
-        try {
-            synchronized (sm) {
-                s = sm.connect(dest, new I2PSocketOptions());
-            }
-            InputStream in = new BufferedInputStream(s.getInputStream());
-            OutputStream sout = new BufferedOutputStream(s.getOutputStream());
-            sout.write(req.toByteArray());
-            sout.flush();
-            byte[] buffer = new byte[16384], filtered;
-            int len;
-            while ((len = in.read(buffer)) != -1) {
-                if (len != buffer.length) {
-                    byte[] b2 = new byte[len];
-                    System.arraycopy(buffer, 0, b2, 0, len);
-                    filtered = f.filter(b2);
-                } else {
-                    filtered = f.filter(buffer);
-                }
-                written = true;
-                out.write(filtered);
-            }
-            filtered = f.finish();
-            written = true;
-            out.write(filtered);
-            out.flush();
-        } catch (SocketException ex) {
-            _log.error("Error while handling eepsite request");
-            return written;
-        } catch (IOException ex) {
-            _log.error("Error while handling eepsite request");
-            return written;
-        } catch (I2PException ex) {
-            _log.error("Error while handling eepsite request");
-            return written;
-        } finally {
-            if (s != null) s.close();
-        }
-        return true;
-    }
-}
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ErrorHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ErrorHandler.java
deleted file mode 100644
index 35c2962817..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ErrorHandler.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package net.i2p.httptunnel.handler;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import net.i2p.httptunnel.HTTPListener;
-import net.i2p.httptunnel.Request;
-import net.i2p.util.Log;
-
-/**
- * Handler for general error messages.
- */
-public class ErrorHandler {
-
-    private static final Log _log = new Log(ErrorHandler.class); /* UNUSED */
-
-    /* package private */ErrorHandler() {
-
-    }
-
-    /**
-     * @param req the Request
-     * @param httpl an HTTPListener
-     * @param out where to write the results
-     * @param error the error that happened
-     * @throws IOException
-     */
-    public void handle(Request req, HTTPListener httpl, OutputStream out, String error) throws IOException {
-        // FIXME: Make nicer messages for more likely errors.
-        out
-           .write(("HTTP/1.1 500 Internal Server Error\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n\r\n")
-                                                                                                                    .getBytes("ISO-8859-1"));
-        out
-           .write(("<html><head><title>" + error + "</title></head><body><h1>" + error
-                   + "</h1>An internal error occurred while " + "handling a request by HTTPTunnel:<br><b>" + error + "</b><h2>Complete request:</h2><b>---</b><br><i><pre>\r\n")
-                                                                                                                                                                                .getBytes("ISO-8859-1"));
-        out.write(req.toByteArray());
-        out.write(("</pre></i><br><b>---</b></body></html>").getBytes("ISO-8859-1"));
-        out.flush();
-    }
-}
\ No newline at end of file
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/LocalHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/handler/LocalHandler.java
deleted file mode 100644
index b2142c6102..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/LocalHandler.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package net.i2p.httptunnel.handler;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import net.i2p.httptunnel.HTTPListener;
-import net.i2p.httptunnel.Request;
-import net.i2p.util.Log;
-
-/**
- * Handler for requests that do not require any connection to anyone
- * (except errors).
- */
-public class LocalHandler {
-
-    private static final Log _log = new Log(LocalHandler.class); /* UNUSED */
-
-    /* package private */LocalHandler() {
-    }
-
-    /**
-     * @param req the Request
-     * @param httpl an HTTPListener 
-     * @param out where to write the results
-     * @throws IOException
-     */
-    public void handle(Request req, HTTPListener httpl, OutputStream out
-    /*, boolean fromProxy */) throws IOException {
-        //FIXME: separate multiple pages, not only a start page
-        //FIXME: provide some info on this page
-        out
-           .write(("HTTP/1.1 200 Document following\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
-                   + "<html><head><title>Welcome to I2P HTTPTunnel</title>"
-                   + "</head><body><h1>Welcome to I2P HTTPTunnel</h1>You can "
-                   + "browse Eepsites by adding an eepsite name to the request." + "</body></html>")
-                                                                                                    .getBytes("ISO-8859-1"));
-        out.flush();
-    }
-
-    /**
-     * Currently always throws an IO Exception
-     * @param req the Request
-     * @param httpl an HTTPListener
-     * @param out where to write the results
-     * @throws IOException
-     */
-    public void handleProxyConfWarning(Request req, HTTPListener httpl, OutputStream out) throws IOException {
-        //FIXME
-        throw new IOException("jrandom ate the deprecated method. mooo");
-        //httpl.handleNotImplemented(out);
-
-    }
-
-    /**
-     * Currently always throws an IO Exception
-     * @param req the Request
-     * @param httpl an HTTPListener
-     * @param out where to write the results
-     * @throws IOException
-     */
-    public void handleHTTPWarning(Request req, HTTPListener httpl, OutputStream out /*, boolean fromProxy */)
-                                                                                                              throws IOException {
-        // FIXME
-        throw new IOException("jrandom ate the deprecated method. mooo");
-        //httpl.handleNotImplemented(out);
-    }
-}
\ No newline at end of file
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ProxyHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ProxyHandler.java
deleted file mode 100644
index a0e55e931a..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ProxyHandler.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package net.i2p.httptunnel.handler;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import net.i2p.I2PAppContext;
-import net.i2p.client.streaming.I2PSocketManager;
-import net.i2p.data.Destination;
-import net.i2p.httptunnel.HTTPListener;
-import net.i2p.httptunnel.Request;
-import net.i2p.httptunnel.SocketManagerProducer;
-import net.i2p.httptunnel.filter.Filter;
-import net.i2p.httptunnel.filter.NullFilter;
-import net.i2p.util.Log;
-
-/**
- * Handler for proxying "normal" HTTP requests.
- */
-public class ProxyHandler extends EepHandler {
-
-    private static final Log _log = new Log(ErrorHandler.class); /* UNUSED */
-    private static I2PAppContext _context = new I2PAppContext();
-
-    /* package private */ProxyHandler(ErrorHandler eh) {
-        super(eh);
-    }
-
-    /**
-     * @param req a Request
-     * @param httpl an HTTPListener
-     * @param out where to write the results
-     * @throws IOException
-     */
-    public void handle(Request req, HTTPListener httpl, OutputStream out
-                       /*, boolean fromProxy */) throws IOException {
-        SocketManagerProducer smp = httpl.getSMP();
-        Destination dest = findProxy();
-        if (dest == null) {
-            errorHandler.handle(req, httpl, out, "Could not find proxy");
-            return;
-        }
-        // one manager for all proxy requests
-        I2PSocketManager sm = smp.getManager("--proxy--");
-        Filter f = new NullFilter(); //FIXME: use other filter
-        if (!handle(req, f, out, dest, sm)) {
-            errorHandler.handle(req, httpl, out, "Unable to reach peer");
-        }
-    }
-
-    private Destination findProxy() {
-        //FIXME!
-        return _context.namingService().lookup("squid.i2p");
-    }
-}
\ No newline at end of file
diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/RootHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/handler/RootHandler.java
deleted file mode 100644
index 1cb0b26946..0000000000
--- a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/RootHandler.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package net.i2p.httptunnel.handler;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-import net.i2p.httptunnel.HTTPListener;
-import net.i2p.httptunnel.Request;
-import net.i2p.util.Log;
-
-/**
- * Main handler for all requests. Dispatches requests to other handlers.
- */
-public class RootHandler {
-
-    private static final Log _log = new Log(RootHandler.class); /* UNUSED */
-
-    private RootHandler() {
-        errorHandler = new ErrorHandler();
-        localHandler = new LocalHandler();
-        proxyHandler = new ProxyHandler(errorHandler);
-        eepHandler = new EepHandler(errorHandler);
-    }
-
-    private ErrorHandler errorHandler;
-    private ProxyHandler proxyHandler;
-    private LocalHandler localHandler;
-    private EepHandler eepHandler;
-
-    private static RootHandler instance;
-
-    /**
-     * Singleton stuff
-     * @return the one and only instance, yay!
-     */
-    public static synchronized RootHandler getInstance() {
-        if (instance == null) {
-            instance = new RootHandler();
-        }
-        return instance;
-    }
-
-    /**
-     * The _ROOT_ handler:  it passes its workload off to the other handlers.
-     * @param req a Request
-     * @param httpl an HTTPListener
-     * @param out where to write the results
-     * @throws IOException
-     */
-    public void handle(Request req, HTTPListener httpl, OutputStream out) throws IOException {
-        String url = req.getURL();
-        System.out.println(url);
-        /* boolean byProxy = false; */
-        int pos;
-        if (url.startsWith("http://")) { // access via proxy
-            /* byProxy=true; */
-            if (httpl.firstProxyUse()) {
-                localHandler.handleProxyConfWarning(req, httpl, out);
-                return;
-            }
-            url = url.substring(7);
-            pos = url.indexOf("/");
-            String host;
-
-            if (pos == -1) {
-                errorHandler.handle(req, httpl, out, "No host end in URL");
-                return;
-            }
-            
-            host = url.substring(0, pos);
-            url = url.substring(pos);
-            if ("i2p".equals(host) || "i2p.i2p".equals(host)) {
-                // normal request; go on below...
-            } else if (host.endsWith(".i2p")) {
-                // "old" service request, send a redirect...
-                out.write(("HTTP/1.1 302 Moved\r\nLocation: " + "http://i2p.i2p/" + host + url + "\r\n\r\n").getBytes("ISO-8859-1"));
-                return;
-            } else {
-                // this is for proxying to the real web
-                proxyHandler.handle(req, httpl, out /*, true */);
-                return;
-            }
-        }
-        if (url.equals("/")) { // main page
-            url = "/_/local/index";
-        } else if (!url.startsWith("/")) {
-            errorHandler.handle(req, httpl, out, "No leading slash in URL: " + url);
-            return;
-        }
-        String dest;
-        url = url.substring(1);
-        pos = url.indexOf("/");
-        if (pos == -1) {
-            dest = url;
-            url = "/";
-        } else {
-            dest = url.substring(0, pos);
-            url = url.substring(pos);
-        }
-        req.setURL(url);
-        if (dest.equals("_")) { // no eepsite
-            if (url.startsWith("/local/")) { // local request
-                req.setURL(url.substring(6));
-                localHandler.handle(req, httpl, out /*, byProxy */);
-            } else if (url.startsWith("/http/")) { // http warning
-                localHandler.handleHTTPWarning(req, httpl, out /*, byProxy */);
-            } else if (url.startsWith("/proxy/")) { // http proxying
-                req.setURL("http://" + url.substring(7));
-                proxyHandler.handle(req, httpl, out /*, byProxy */);
-            } else {
-                errorHandler.handle(req, httpl, out, "No local handler for this URL: " + url);
-            }
-        } else {
-            eepHandler.handle(req, httpl, out, /* byProxy, */dest);
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/jfreechart/GUI-licenses.txt b/apps/jfreechart/GUI-licenses.txt
deleted file mode 100644
index dcbe66d024..0000000000
--- a/apps/jfreechart/GUI-licenses.txt
+++ /dev/null
@@ -1,590 +0,0 @@
-The code for the GUI applications netviewer and the 
-heartbeat GUI have been released into the public domain, 
-but they make use of the LGPL JFreeChart library (which
-in turn depends upon the APL log4j library).  These 
-external components, contained within the files:
- lib/jfreechart-0.9.17.jar
- lib/jcommon-0.9.2.jar
- lib/log4j-1.2.8.jar
-were retrieved and built from the source at
-http://www.jfree.org/jfreechart/jfreechart-0.9.17.zip
-
-As a whole, the netviewer and heartbeat GUI applications 
-therefore must state:
-   This product includes software developed by the 
-   Apache Software Foundation (http://www.apache.org/).
-
-The LGPL just makes us state prominently that we use LGPL'ed
-code (the JFreeChart code), and since we make no modifications 
-to it, section 6.b of the LGPL seems to apply.
-
-The relevent licenses are shown below.
-
-*****************************************************************
-For the jfreechart-0.9.17.jar and jcommon-0.9.2.jar, the 
-LGPL is relevent:
-*****************************************************************
-		  GNU LESSER GENERAL PUBLIC LICENSE
-		       Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL.  It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it.  You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
-  When we speak of free software, we are referring to freedom of use,
-not price.  Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
-  To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  To protect each distributor, we want to make it very clear that
-there is no warranty for the free library.  Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
-  Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
-  Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License.  We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
-  When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom.  The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
-  We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less
-of an advantage over competing non-free programs.  These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-  For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard.  To achieve this, non-free programs must be
-allowed to use the library.  A more frequent case is that a free
-library does the same job as widely used non-free libraries.  In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
-  In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software.  For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
-  Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
-		  GNU LESSER GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Use a suitable shared library mechanism for linking with the
-    Library.  A suitable mechanism is one that (1) uses at run time a
-    copy of the library already present on the user's computer system,
-    rather than copying library functions into the executable, and (2)
-    will operate properly with a modified version of the library, if
-    the user installs one, as long as the modified version is
-    interface-compatible with the version that the work was made with.
-
-    c) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    d) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    e) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-			    NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-           How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-
-
-*****************************************************************
-For the file log4j-1.2.8.jar, the APL is relevent:
-*****************************************************************
-/* ====================================================================
- *
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2003 The Apache Software Foundation.  All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The end-user documentation included with the redistribution, if
- *    any, must include the following acknowlegement:
- *       "This product includes software developed by the
- *        Apache Software Foundation (http://www.apache.org/)."
- *    Alternately, this acknowlegement may appear in the software itself,
- *    if and wherever such third-party acknowlegements normally appear.
- *
- * 4. The names "The Apache Logging Services Project", "log4j", and "Apache Software
- *    Foundation" must not be used to endorse or promote products derived
- *    from this software without prior written permission. For written
- *    permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache"
- *    nor may "Apache" appear in their names without prior written
- *    permission of the Apache Group.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation.  For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * [Additional notices, if required by prior licensing conditions]
- *
- */
diff --git a/apps/jfreechart/build.xml b/apps/jfreechart/build.xml
deleted file mode 100644
index 91434d6119..0000000000
--- a/apps/jfreechart/build.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project basedir="." default="all" name="jfreechart">
-    <target name="all">
-        <echo message="The code in the JFreeChart software contains LGPL and APL licensed software," />
-        <echo message="and is not necessary for using I2P.  However, there is a seperate GUI for the " />
-        <echo message="heartbeat and netmonitor applications that uses this, so the retrieval of that " />
-        <echo message="code from the JFreeChart distribution is being made available (though we make no" />
-        <echo message="modifications to the code used here whatsoever - it is simply used by the public domain GUIs.  " />
-        <echo message="If you would like to fetch the code, run the ant task 'fetchJfreechart'" />
-        <echo message="If you would like to build the code, run the ant task 'build'" />
-        <echo message="If you would like to delete the code, run the ant task 'clean'" />
-    </target>
-    <target name="build">
-        <ant dir="./jfreechart-0.9.17/" antfile="ant/build.xml" target="compile" />
-    </target>
-    <target name="fetchJfreechart">
-        <mkdir dir="./lib" />
-        <get src="http://www.jfree.org/jfreechart/jfreechart-0.9.17.zip" verbose="true" dest="jfreechart-0.9.17.zip" />
-        <unzip src="jfreechart-0.9.17.zip" dest="." />
-    </target>
-    <target name="builddep" />
-    <target name="compile" />
-    <target name="jar" />
-    <target name="clean">
-        <delete dir="./jfreechart-0.9.17/" />
-    </target>
-    <target name="cleandep" depends="clean" />
-    <target name="distclean" depends="clean" />
-</project>
diff --git a/apps/myi2p/java/build.xml b/apps/myi2p/java/build.xml
deleted file mode 100644
index 6c79ddc737..0000000000
--- a/apps/myi2p/java/build.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project basedir="." default="all" name="myi2p">
-    <target name="all" depends="clean, build" />
-    <target name="build" depends="builddep, jar" />
-    <target name="builddep">
-        <ant dir="../../../core/java/" target="build" />
-    </target>
-    <target name="compile">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/obj" />
-        <javac 
-            srcdir="./src" 
-            debug="true" deprecation="on" source="1.3" target="1.3" 
-            destdir="./build/obj" 
-            classpath="../../../core/java/build/i2p.jar" />
-    </target>
-    <target name="jar" depends="compile">
-        <jar destfile="./build/myi2p.jar" basedir="./build/obj" includes="**/*.class" />
-    </target>
-    <target name="javadoc">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/javadoc" />
-        <javadoc 
-            sourcepath="./src:../../../core/java/src" destdir="./build/javadoc" 
-            packagenames="*" 
-            use="true" 
-            splitindex="true" 
-            windowtitle="MyI2P" />
-    </target>
-    <target name="clean">
-        <delete dir="./build" />
-    </target>
-    <target name="cleandep" depends="clean">
-        <ant dir="../../../core/java/" target="distclean" />
-    </target>
-    <target name="distclean" depends="clean">
-        <ant dir="../../../core/java/" target="distclean" />
-    </target>
-</project>
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/MyI2PMessage.java b/apps/myi2p/java/src/net/i2p/myi2p/MyI2PMessage.java
deleted file mode 100644
index e2b05666d7..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/MyI2PMessage.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package net.i2p.myi2p;
-
-import net.i2p.data.Destination;
-
-/**
- * Packages up a message for delivery.  The raw format of the message within a
- * repliable datagram is
- *  <code>MyI2P $maj.$min $service $type\n$payload</code>
- * where <code>$maj.$min</code> is currently 1.0, $service is the type of MyI2P
- * service, $type is the type of message within that service, and $payload is 
- * the data specific to that type.
- *
- */
-public class MyI2PMessage {
-    private Destination _peer;
-    private String _service;
-    private String _type;
-    private byte[] _payload;
-    
-    private static final byte[] MESSAGE_PREFIX = "MyI2P 1.0 ".getBytes();
-    
-    /**
-     * Build a new MyI2P message to be sent.
-     *
-     * @param to address to send the message
-     * @param service what MyI2P service is involved
-     * @param type type of message within that service is involved
-     * @param data payload of the message to deliver
-     */
-    public MyI2PMessage(Destination to, String service, String type, byte data[]) {
-        _peer = to;
-        _service = service;
-        _type = type;
-        _payload = data;
-    }
-    
-    /**
-     * Read in the MyI2P data from the given datagram info.
-     *
-     * @param from authenticated from address
-     * @param dgramPayload raw MyI2P formatted message
-     * @throws IllegalArgumentException if the message is not a valid MyI2P message
-     */
-    public MyI2PMessage(Destination from, byte dgramPayload[]) throws IllegalArgumentException {
-        _peer = from;
-        int index = 0;
-        while (index < dgramPayload.length) {
-            if (index >= MESSAGE_PREFIX.length) break;
-            if (dgramPayload[index] != MESSAGE_PREFIX[index])
-                throw new IllegalArgumentException("Invalid payload (not a MyI2P message)");
-            index++;
-        }
-        
-        // $service $type\n$payload
-        StringBuffer service = new StringBuffer(8);
-        while (index < dgramPayload.length) {
-            if (dgramPayload[index] == ' ') {
-                _service = service.toString();
-                index++;
-                break;
-            } else if (dgramPayload[index] == '\n') {
-                throw new IllegalArgumentException("Ran into newline while reading the service");
-            } else {
-                service.append((char)dgramPayload[index]);
-                index++;
-            }
-        }
-        
-        StringBuffer type = new StringBuffer(8);
-        while (index < dgramPayload.length) {
-            if (dgramPayload[index] == '\n') {
-                _type = type.toString();
-                index++;
-                break;
-            } else {
-                service.append((char)dgramPayload[index]);
-                index++;
-            }
-        }
-        
-        _payload = new byte[dgramPayload.length-index];
-        System.arraycopy(dgramPayload, index, _payload, 0, _payload.length);
-    }
-   
-    /** who is this message from or who is it going to? */
-    public Destination getPeer() { return _peer; }
-    /** what MyI2P service is this bound for (addressBook, blog, etc)? */
-    public String getServiceType() { return _service; }
-    /** within that service, what type of message is this? */
-    public String getMessageType() { return _type; }
-    /** what is the raw data for the particular message? */
-    public byte[] getPayload() { return _payload; }
-    
-    /**
-     * Retrieve the raw payload, suitable for wrapping in an I2PDatagramMaker 
-     * and sending to another MyI2P node.
-     *
-     * @throws IllegalStateException if some data is missing
-     */
-    public byte[] toRawPayload() throws IllegalStateException {
-        if (_service == null) throw new IllegalStateException("Service is null");
-        if (_type == null) throw new IllegalStateException("Type is null");
-        if (_payload == null) throw new IllegalStateException("Payload is null");
-        
-        byte service[] = _service.getBytes();
-        byte type[] = _type.getBytes();
-        byte rv[] = new byte[MESSAGE_PREFIX.length + service.length + 1 + type.length + 1 + _payload.length];
-        System.arraycopy(MESSAGE_PREFIX, 0, rv, 0, MESSAGE_PREFIX.length);
-        System.arraycopy(service, 0, rv, MESSAGE_PREFIX.length, service.length);
-        rv[MESSAGE_PREFIX.length + service.length] = ' ';
-        System.arraycopy(type, 0, rv, MESSAGE_PREFIX.length + service.length + 1, type.length);
-        rv[MESSAGE_PREFIX.length + service.length + 1 + type.length] = '\n';
-        System.arraycopy(_payload, 0, rv, MESSAGE_PREFIX.length + service.length + 1 + type.length + 1, _payload.length);
-        return rv;
-    }
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/Node.java b/apps/myi2p/java/src/net/i2p/myi2p/Node.java
deleted file mode 100644
index 71845f31e7..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/Node.java
+++ /dev/null
@@ -1,266 +0,0 @@
-package net.i2p.myi2p;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import net.i2p.I2PAppContext;
-import net.i2p.util.Log;
-
-/**
- * Main controller for a MyI2P node, coordinating all network communication and
- * distributing messages to the appropriate services.
- *
- */
-public class Node {
-    private static List _nodes = new ArrayList(1);
-    /**
-     * Return a list of Node instances that are currently 
-     * operating in the JVM
-     */
-    private static List nodes() { 
-        synchronized (_nodes) {
-            return new ArrayList(_nodes);
-        }
-    }
-    
-    private I2PAppContext _context;
-    private Log _log;
-    private NodeAdapter _adapter;
-    /** 
-     * contains configuration properties, such where our router is, what 
-     * services to run, etc
-     *
-     */
-    private Properties _config;
-    /** filename where _config is stored */
-    private String _configFile = DEFAULT_CONFIG_FILE;
-    /** mapping of service name (String) to Service for all services loaded */
-    private Map _services;
-    
-    private static final String DEFAULT_CONFIG_FILE = "myi2p.config";
-    private static final String DEFAULT_KEY_FILE = "myi2p.keys";
-    private static final String PROP_KEY_FILE = "keyFile";
-    
-    public Node(I2PAppContext context) {
-        _context = context;
-        _log = context.logManager().getLog(Node.class);
-        _config = new Properties();
-        _services = new HashMap(1);
-        if (_log.shouldLog(Log.CRIT))
-            _log.log(Log.CRIT, "Node created");
-        _adapter = new NodeAdapter(_context, this);
-    }
-    
-    /**
-     * Main driver for the node.  Usage: <code>Node [configFile]</code>
-     *
-     */
-    public static void main(String args[]) {
-        String filename = DEFAULT_CONFIG_FILE;
-        if ( (args != null) && (args.length == 1) )
-            filename = args[0];
-        Node node = new Node(I2PAppContext.getGlobalContext());
-        node.setConfigFile(filename);
-        node.loadConfig();
-        node.startup();
-        while (true) {
-            //try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
-            //node.shutdown();
-            //if (true) return;
-            synchronized (node) {
-                try { node.wait(); } catch (InterruptedException ie) {}
-            }
-        }
-    }
-    
-    public Properties getConfig() { 
-        synchronized (_config) {
-            return new Properties(_config); 
-        }
-    }
-    public void setConfig(Properties props) { 
-        synchronized (_config) {
-            _config.clear();
-            _config.putAll(props);
-        }
-    }
-    
-    public String getConfigFile() { return _configFile; }
-    public void setConfigFile(String filename) { _configFile = filename; }
-    
-    /**
-     * Load up the config and all of the services
-     *
-     */
-    public void loadConfig() {
-        FileInputStream fis = null;
-        try {
-            File cfgFile = new File(_configFile);
-            if (cfgFile.exists()) {
-                fis = new FileInputStream(cfgFile);
-                Properties props = new Properties();
-                props.load(fis);
-                setConfig(props);
-                if (_log.shouldLog(Log.INFO))
-                    _log.info("Config loaded from " + _configFile);
-            } else {
-                if (_log.shouldLog(Log.ERROR))
-                    _log.error("Config file " + _configFile + " does not exist, so we aren't going to do much");
-            }
-        } catch (IOException ioe) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Error reading config file " + _configFile, ioe);
-        } finally {
-            if (fis != null) try { fis.close(); } catch (IOException ioe) {}
-        }
-    }
-    
-    /**
-     * Boot up the node, connect to the router, and start all the services
-     *
-     */
-    public void startup() {
-        boolean connected = connect();
-        if (connected) {
-            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
-                public void run() { shutdown(); }
-            }));
-            loadServices();
-            startServices();
-            synchronized (_nodes) {
-                _nodes.add(this);
-            }
-            if (_log.shouldLog(Log.INFO))
-                _log.info("Node started");
-        } else {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Unable to connect, startup didn't do much");
-        }
-    }
-    
-    /**
-     * Drop any connections to the network and stop all services
-     *
-     */
-    public void shutdown() {
-        disconnect();
-        stopServices();
-        synchronized (_nodes) {
-            _nodes.remove(this);
-        }
-    }
-    
-    /**
-     * Send a message from the node to the peer as specified in the message
-     *
-     * @return true if it was sent
-     */
-    public boolean sendMessage(MyI2PMessage msg) {
-        return _adapter.sendMessage(msg);
-    }
-    
-    private void loadServices() {
-        Properties config = getConfig();
-        int i = 0;
-        while (true) {
-            String classname = config.getProperty("service."+i+".classname");
-            if ( (classname == null) || (classname.trim().length() <= 0) )
-                break;
-            boolean ok = loadService("service." + i + ".", config);
-            if (ok) i++;
-        }
-        if (_log.shouldLog(Log.INFO))
-            _log.info(i + " services loaded");
-    }
-    
-    private boolean loadService(String prefix, Properties config) {
-        String classname = config.getProperty(prefix + "classname");
-        String type = config.getProperty(prefix + "type");
-        if (type == null) return false;
-        
-        Properties opts = new Properties();
-        int i = 0;
-        while (true) {
-            String name = config.getProperty(prefix + "option." + i + ".name");
-            String value = config.getProperty(prefix + "option." + i + ".value");
-            if ( (name == null) || (name.trim().length() <= 0) || (value == null) || (value.trim().length() <= 0) )
-                break;
-            opts.setProperty(name.trim(), value.trim());
-            i++;
-        }
-        
-        try {
-            Class cls = Class.forName(classname);
-            Object obj = cls.newInstance();
-            if (obj instanceof Service) {
-                Service service = (Service)obj;
-                service.setType(type);
-                service.setOptions(opts);
-                service.setNode(this);
-                service.setContext(_context);
-                synchronized (_services) {
-                    _services.put(type, service);
-                }
-                if (_log.shouldLog(Log.INFO))
-                    _log.info("Service " + type + " loaded");
-                return true;
-            } else {
-                if (_log.shouldLog(Log.ERROR))
-                    _log.error("Error loading service " + type + ": not a service [" + classname + "]");
-            }
-        } catch (ClassNotFoundException cnfe) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Error loading service " + type + ": class " + classname + " is invalid", cnfe);
-        } catch (InstantiationException ie) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Error instantiating service " + type + ": class " + classname + " could not be created", ie);
-        } catch (IllegalAccessException iae) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Error creating service " + type + ": class " + classname + " could not be accessed", iae);
-        }
-        return false;
-    }
-    
-    private boolean connect() {
-        Properties config = getConfig();
-        File keyFile = new File(config.getProperty(PROP_KEY_FILE, DEFAULT_KEY_FILE));
-        return _adapter.connect(config, keyFile);
-    }
-    
-    private void disconnect() {
-        _adapter.disconnect();
-    }
-    
-    private void startServices() {
-        for (Iterator iter = _services.values().iterator(); iter.hasNext(); ) {
-            Service service = (Service)iter.next();
-            service.startup();
-        }
-    }
-    private void stopServices() {
-        for (Iterator iter = _services.values().iterator(); iter.hasNext(); ) {
-            Service service = (Service)iter.next();
-            service.shutdown();
-        }
-    }
-    
-    void handleMessage(MyI2PMessage msg) {
-        Service service = (Service)_services.get(msg.getServiceType());
-        if (service == null) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Message received for an unknown service [" 
-                           + msg.getServiceType() + "] from " 
-                           + msg.getPeer().calculateHash().toBase64());
-        } else {
-            service.receiveMessage(msg);
-        }
-    }
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/NodeAdapter.java b/apps/myi2p/java/src/net/i2p/myi2p/NodeAdapter.java
deleted file mode 100644
index bfb5906ece..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/NodeAdapter.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package net.i2p.myi2p;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-import java.util.Properties;
-
-import net.i2p.I2PAppContext;
-import net.i2p.I2PException;
-import net.i2p.client.I2PClient;
-import net.i2p.client.I2PClientFactory;
-import net.i2p.client.I2PSession;
-import net.i2p.client.I2PSessionListener;
-import net.i2p.client.I2PSessionException;
-import net.i2p.client.datagram.I2PDatagramDissector;
-import net.i2p.client.datagram.I2PDatagramMaker;
-import net.i2p.client.datagram.I2PInvalidDatagramException;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.Destination;
-import net.i2p.util.Log;
-
-/**
- * Bind the MyI2P node to the I2P network, handling messages, sessions,
- * etc.
- *
- */
-public class NodeAdapter implements I2PSessionListener {
-    private I2PAppContext _context;
-    private Log _log;
-    private Node _node;
-    private I2PSession _session;
-    
-    public NodeAdapter(I2PAppContext context, Node node) {
-        _node = node;
-        _context = context;
-        _log = context.logManager().getLog(NodeAdapter.class);
-    }
-    
-    boolean sendMessage(MyI2PMessage msg) {
-        if (_session == null) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Cannot send the message, as we are not connected");
-            return false;
-        }
-        try {
-            I2PDatagramMaker builder = new I2PDatagramMaker(_session);
-            byte dgram[] = builder.makeI2PDatagram(msg.toRawPayload());
-            return _session.sendMessage(msg.getPeer(), dgram);
-        } catch (IllegalStateException ise) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("MyI2PMessage was not valid", ise);
-            return false;
-        } catch (I2PSessionException ise) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Error sending to the peer", ise);
-            return false;
-        }
-    }
-    
-    /**
-     * Connect to the network using the current I2CP config and the private 
-     * key file specified in the node config.  If the file does not exist, a new 
-     * destination will be created.
-     *
-     * @param config MyI2P node and I2CP configuration
-     * @param keyFile file to load the private keystream from (if it doesn't 
-     *                exist, a new one will be created and stored at that location)
-     *
-     * @return true if connection was successful, false otherwise
-     */
-    boolean connect(Properties config, File keyFile) {
-        I2PClient client = I2PClientFactory.createClient();
-        if (!keyFile.exists()) {
-            File parent = keyFile.getParentFile();
-            if (parent != null) parent.mkdirs();
-            FileOutputStream fos = null;
-            try {
-                fos = new FileOutputStream(keyFile);
-                Destination dest = client.createDestination(fos);
-                if (_log.shouldLog(Log.INFO))
-                    _log.info("New destination created [" 
-                              + dest.calculateHash().toBase64() 
-                              + "] with keys at " + keyFile);
-            } catch (IOException ioe) {
-                if (_log.shouldLog(Log.ERROR))
-                    _log.error("Error writing new keystream to " + keyFile, ioe);
-                return false;
-            } catch (I2PException ie) {
-                if (_log.shouldLog(Log.ERROR))
-                    _log.error("Internal error creating new destination", ie);
-                return false;
-            } finally {
-                if (fos != null) try { fos.close(); } catch (IOException ioe) {}
-            }
-        }
-        
-        FileInputStream fis = null;
-        try {
-            fis = new FileInputStream(keyFile);
-            _session = client.createSession(fis, config);
-            if (_session == null) {
-                _log.error("wtf, why did it create a null session?");
-                return false;
-            }
-            _session.setSessionListener(this);
-            _session.connect();
-            if (_log.shouldLog(Log.INFO))
-                _log.info("I2P session created");
-            return true;
-        } catch (IOException ioe) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Unable to read the keystream from " + keyFile, ioe);
-            return false;
-        } catch (I2PSessionException ise) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Unable to connect to the router", ise);
-            return false;
-        } finally {
-            if (fis != null) try { fis.close(); } catch (IOException ioe) {}
-        }
-    }
-    
-    void disconnect() {
-        if (_session != null) {
-            try {
-                _session.destroySession();
-            } catch (I2PSessionException ise) {
-                if (_log.shouldLog(Log.WARN))
-                    _log.warn("Error destroying the session in shutdown", ise);
-            }
-            _session = null;
-        }
-    }
-    
-    public void disconnected(I2PSession session) {
-        if (_log.shouldLog(Log.INFO))
-            _log.info("Session disconnected");
-    }
-    
-    public void errorOccurred(I2PSession session, String message, Throwable error) {
-        if (_log.shouldLog(Log.ERROR))
-            _log.error("Session error occurred - " + message, error);
-    }
-    
-    public void messageAvailable(I2PSession session, int msgId, long size) {
-        if (_log.shouldLog(Log.INFO))
-            _log.info("message available [" + msgId + "/"+ size + " bytes]");
-        
-        try {
-            byte data[] = session.receiveMessage(msgId);
-            I2PDatagramDissector dissector = new I2PDatagramDissector();
-            dissector.loadI2PDatagram(data);
-            try {
-                MyI2PMessage msg = new MyI2PMessage(dissector.getSender(), dissector.getPayload());
-                _node.handleMessage(msg);
-            } catch (IllegalArgumentException iae) {
-                if (_log.shouldLog(Log.ERROR))
-                    _log.error("Message is a valid datagram but invalid MyI2P message", iae);
-            }
-        } catch (I2PSessionException ise) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Error retrieving message payload for message " + msgId, ise);
-        } catch (I2PInvalidDatagramException iide) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Message received was not a valid repliable datagram", iide);
-        } catch (DataFormatException dfe) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Message received was a corrupt repliable datagram", dfe);
-        }
-    }
-    
-    public void reportAbuse(I2PSession session, int severity) {
-        if (_log.shouldLog(Log.INFO))
-            _log.info("abuse occurred");
-    }
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/Service.java b/apps/myi2p/java/src/net/i2p/myi2p/Service.java
deleted file mode 100644
index f18f2ebf26..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/Service.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package net.i2p.myi2p;
-
-import java.util.Properties;
-import net.i2p.I2PAppContext;
-
-/**
- * Defines a service that can operate within a MyI2P node, responding to 
- * messages and performing whatever tasks are necessary.
- *
- */
-public interface Service {
-    /** what type of message will this service respond to? */
-    public String getType();
-    public void setType(String type);
-    
-    /** what node is this service hooked into */
-    public Node getNode();
-    public void setNode(Node node);
-    
-    /** what options specific to this node does the service have? */
-    public Properties getOptions();
-    public void setOptions(Properties opts);
-    
-    /** give the service a scope */
-    public I2PAppContext getContext();
-    public void setContext(I2PAppContext context);
-    
-    /** called when a message is received for the service */
-    public void receiveMessage(MyI2PMessage msg);
-    
-    /** start the service up - the node is ready */
-    public void startup();
-    /** shut the service down - the node is going offline */
-    public void shutdown();
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/ServiceImpl.java b/apps/myi2p/java/src/net/i2p/myi2p/ServiceImpl.java
deleted file mode 100644
index f5a4ff6c07..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/ServiceImpl.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package net.i2p.myi2p;
-
-import java.util.Properties;
-
-import net.i2p.I2PAppContext;
-import net.i2p.myi2p.Service;
-import net.i2p.myi2p.Node;
-import net.i2p.myi2p.MyI2PMessage;
-
-/**
- * Base service implementation
- *
- */
-public abstract class ServiceImpl implements Service {
-    private I2PAppContext _context;
-    private Node _node;
-    private Properties _options;
-    private String _serviceType;
-    
-    public ServiceImpl() {
-        _context = null;
-        _node = null;
-        _options = null;
-        _serviceType = null;
-    }
-    
-    // base inspectors / mutators
-    public Node getNode() { return _node; }
-    public void setNode(Node node) { _node = node; }
-    public I2PAppContext getContext() { return _context; }
-    public void setContext(I2PAppContext context) { _context = context; }
-    public Properties getOptions() { return _options; }
-    public void setOptions(Properties opts) { _options = opts; }
-    public String getType() { return _serviceType; }
-    public void setType(String type) { _serviceType = type; }
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBook.java b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBook.java
deleted file mode 100644
index aa74445d2a..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBook.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package net.i2p.myi2p.address;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import net.i2p.I2PAppContext;
-import net.i2p.data.DataHelper;
-import net.i2p.data.DataFormatException;
-
-/**
- * Main lookup component for maintaining references to other I2P destinations.
- *
- */
-public class AddressBook {
-    private I2PAppContext _context;
-    /** Name (String) to AddressBookEntry */
-    private Map _entries;
-    /** 
-     * List of NameReference that has been received but whose preferred 
-     * name conflicts with an existing entry.
-     */
-    private List _conflictingReferences;
-    
-    public AddressBook(I2PAppContext context) {
-        _context = context;
-        _entries = new HashMap(16);
-        _conflictingReferences = new ArrayList(0);
-    }
-    
-    /** retrieve a list of entry names (strings) */
-    public Set getEntryNames() { 
-        synchronized (_entries) { 
-            return new HashSet(_entries.keySet()); 
-        }
-    }
-    public AddressBookEntry getEntry(String name) { 
-        synchronized (_entries) {
-            return (AddressBookEntry)_entries.get(name); 
-        }
-    }
-    public AddressBookEntry addEntry(AddressBookEntry entry) {
-        synchronized (_entries) {
-            return (AddressBookEntry)_entries.put(entry.getLocalName(), entry);
-        }
-    }
-    public void removeEntry(String name) { 
-        synchronized (_entries) {
-            _entries.remove(name); 
-        }
-    }
-    
-    public int getConflictingReferenceCount() { 
-        synchronized (_conflictingReferences) {
-            return _conflictingReferences.size(); 
-        }
-    }
-    public NameReference getConflictingReference(int index) { 
-        synchronized (_conflictingReferences) {
-            return (NameReference)_conflictingReferences.get(index); 
-        }
-    }
-    public void addConflictingReference(NameReference ref) { 
-        synchronized (_conflictingReferences) {
-            _conflictingReferences.add(ref); 
-        }
-    }
-    public void removeConflictingReference(int index) { 
-        synchronized (_conflictingReferences) {
-            _conflictingReferences.remove(index);
-        }
-    }
-    
-    public void read(InputStream in) throws IOException {
-        try {
-            int numEntries = (int)DataHelper.readLong(in, 2);
-            if (numEntries < 0) throw new IOException("Corrupt AddressBook - " + numEntries + " entries?");
-            for (int i = 0; i < numEntries; i++) {
-                AddressBookEntry entry = new AddressBookEntry(_context);
-                entry.read(in);
-                addEntry(entry);
-            }
-            int numConflicting = (int)DataHelper.readLong(in, 2);
-            if (numConflicting < 0) throw new IOException("Corrupt AddressBook - " + numConflicting + " conflicting?");
-            for (int i = 0; i < numConflicting; i++) {
-                NameReference ref = new NameReference(_context);
-                ref.read(in);
-                addConflictingReference(ref);
-            }
-        } catch (DataFormatException dfe) {
-            throw new IOException("Corrupt address book - " + dfe.getMessage());
-        }
-    }
-    public void write(OutputStream out) throws IOException {
-        try {
-            synchronized (_entries) {
-                DataHelper.writeLong(out, 2, _entries.size());
-                for (Iterator iter = _entries.values().iterator(); iter.hasNext(); ) {
-                    AddressBookEntry entry = (AddressBookEntry)iter.next();
-                    entry.write(out);
-                }
-            }
-            synchronized (_conflictingReferences) {
-                DataHelper.writeLong(out, 2, _conflictingReferences.size());
-                for (int i = 0; i < _conflictingReferences.size(); i++) {
-                    NameReference ref = (NameReference)_conflictingReferences.get(i);
-                    ref.write(out);
-                }
-            }
-        } catch (DataFormatException dfe) {
-            throw new IOException("Corrupt address book - " + dfe.getMessage());
-        }
-    }
-    
-    public String toString() {
-        return "Entries: " + _entries.size() + " conflicting: " + _conflictingReferences.size();
-    }
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookEntry.java b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookEntry.java
deleted file mode 100644
index b0f2138619..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookEntry.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package net.i2p.myi2p.address;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import java.util.Date;
-import java.util.Properties;
-
-import net.i2p.I2PAppContext;
-import net.i2p.data.DataHelper;
-import net.i2p.data.DataFormatException;
-
-/**
- * Implements a local address book entry, pointing at a known secure 
- * NameReference as well as an optional Subscription.
- *
- */
-public class AddressBookEntry {
-    private I2PAppContext _context;
-    private String _localName;
-    private Properties _options;
-    private NameReference _reference;
-    private Subscription _subscription;
-    private long _addedOn;
-    
-    public AddressBookEntry(I2PAppContext context) {
-        _context = context;
-        _localName = null;
-        _options = new Properties();
-        _reference = null;
-        _subscription = null;
-        _addedOn = context.clock().now();
-    }
-    
-    /** Local (unique) name we use to reference the given destination */
-    public String getLocalName() { return _localName; }
-    public void setLocalName(String name) { _localName = name; }
-    
-    public Properties getOptions() { 
-        synchronized (_options) {
-            return new Properties(_options);
-        }
-    }
-    public void setOptions(Properties props) { 
-        synchronized (_options) {
-            _options.clear();
-            if (props != null)
-                _options.putAll(props);
-        }
-    }
-    
-    /** Secure name reference, provided by the destination */
-    public NameReference getNameReference() { return _reference; }
-    public void setNameReference(NameReference ref) { _reference = ref; }
-    
-    /** 
-     * If specified, the details of our subscription to the MyI2P address
-     * book at the referenced destination.
-     *
-     */
-    public Subscription getSubscription() { return _subscription; }
-    public void setSubscription(Subscription sub) { _subscription = sub; }
-    
-    /** When this entry was added */
-    public long getAddedOn() { return _addedOn; }
-    public void setAddedOn(long when) { _addedOn = when; }
-    
-    /** load the data from the stream */
-    public void read(InputStream in) throws IOException {
-        try {
-            Boolean localNameDefined = DataHelper.readBoolean(in);
-            if ( (localNameDefined != null) && (localNameDefined.booleanValue()) ) 
-                _localName = DataHelper.readString(in);
-            else
-                _localName = null;
-            
-            Date when = DataHelper.readDate(in);
-            if (when == null)
-                _addedOn = -1;
-            else
-                _addedOn = when.getTime();
-            
-            Properties props = DataHelper.readProperties(in);
-            setOptions(props);
-            
-            Boolean refDefined = DataHelper.readBoolean(in);
-            if ( (refDefined != null) && (refDefined.booleanValue()) ) {
-                _reference = new NameReference(_context);
-                _reference.read(in);
-            } else {
-                _reference = null;
-            }
-            
-            Boolean subDefined = DataHelper.readBoolean(in);
-            if ( (subDefined != null) && (subDefined.booleanValue()) ) {
-                Subscription sub = new Subscription(_context);
-                sub.read(in);
-                _subscription = sub;
-            } else {
-                _subscription = null;
-            }
-            
-        } catch (DataFormatException dfe) {
-            throw new IOException("Corrupt subscription: " + dfe.getMessage());
-        }
-    }
-    
-    /** persist the data to the stream */
-    public void write(OutputStream out) throws IOException {
-        try {
-            if ( (_localName != null) && (_localName.trim().length() > 0) ) {
-                DataHelper.writeBoolean(out, Boolean.TRUE);
-                DataHelper.writeString(out, _localName);
-            } else {
-                DataHelper.writeBoolean(out, Boolean.FALSE);
-            }
-            
-            DataHelper.writeDate(out, new Date(_addedOn));
-            
-            synchronized (_options) {
-                DataHelper.writeProperties(out, _options);
-            }
-            
-            if (_reference != null) {
-                DataHelper.writeBoolean(out, Boolean.TRUE);
-                _reference.write(out);
-            } else {
-                DataHelper.writeBoolean(out, Boolean.FALSE);
-            }
-            
-            if (_subscription != null) {
-                DataHelper.writeBoolean(out, Boolean.TRUE);
-                _subscription.write(out);
-            } else {
-                DataHelper.writeBoolean(out, Boolean.FALSE);
-            }
-        } catch (DataFormatException dfe) {
-            throw new IOException("Corrupt subscription: " + dfe.getMessage());
-        }
-    }
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookService.java b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookService.java
deleted file mode 100644
index b428635075..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookService.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package net.i2p.myi2p.address;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import net.i2p.data.DataHelper;
-import net.i2p.data.DataFormatException;
-import net.i2p.util.Log;
-
-import net.i2p.myi2p.Service;
-import net.i2p.myi2p.ServiceImpl;
-import net.i2p.myi2p.Node;
-import net.i2p.myi2p.MyI2PMessage;
-
-/**
- * Main service handler / coordinator for the MyI2P address book.
- *
- */
-public class AddressBookService extends ServiceImpl {
-    private Log _log;
-    private AddressBook _addressBook;
-    /** contains a mapping of event time (Long) to description (String) */
-    private Map _activityLog;
-    private String _addressBookFile;
-    
-    private static String PROP_ADDRESSBOOK_FILE = "datafile";
-    private static String DEFAULT_ADDRESSBOOK_FILE = "addressbook.dat";
-    
-    public static final String SERVICE_TYPE = "AddressBook";
-    public String getType() { return SERVICE_TYPE; }
-    
-    public void startup() {
-        _log = getContext().logManager().getLog(AddressBookService.class);
-        
-        _addressBookFile = getOptions().getProperty(PROP_ADDRESSBOOK_FILE, DEFAULT_ADDRESSBOOK_FILE);
-        File file = new File(_addressBookFile);
-    
-        if (file.exists()) {
-            loadData(file);
-        } else {
-            _addressBook = new AddressBook(getContext());
-            _activityLog = new HashMap(16);
-        }
-    }
-    
-    public void shutdown() {
-        File file = new File(_addressBookFile);
-        storeData(file);
-    }
-    
-    public void receiveMessage(MyI2PMessage msg) {
-        _log.info("Received a " + msg.getMessageType() + " from " 
-                  + msg.getPeer().calculateHash().toBase64() 
-                  + new String(msg.getPayload()));
-    }
-    
-    /** load everything from disk */
-    private void loadData(File dataFile) {
-        AddressBookServiceData data = new AddressBookServiceData(getContext());
-        data.load(dataFile);
-        if (data.getErrorMessage() != null) {
-            _log.warn(data.getErrorMessage(), data.getError());
-            _addressBook = new AddressBook(getContext());
-            _activityLog = new HashMap(16);
-        } else {
-            _addressBook = data.getAddressBook();
-            _activityLog = data.getActivityLog();
-        }
-    }
-    
-    /** persist everything to disk */
-    private void storeData(File dataFile) {
-        AddressBookServiceData data = new AddressBookServiceData(getContext());
-        data.setActivityLog(_activityLog);
-        data.setAddressBook(_addressBook);
-        data.store(dataFile);
-        if (data.getErrorMessage() != null) {
-            _log.warn(data.getErrorMessage(), data.getError());
-        }
-    }
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookServiceData.java b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookServiceData.java
deleted file mode 100644
index 3bfaa8e74e..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookServiceData.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package net.i2p.myi2p.address;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import net.i2p.I2PAppContext;
-import net.i2p.data.DataHelper;
-import net.i2p.util.Log;
-
-/**
- * Component for loading and storing the service data to disk
- *
- */
-public class AddressBookServiceData {
-    private I2PAppContext _context;
-    private Log _log;
-    private AddressBook _addressBook;
-    private Map _activityLog;
-    private Exception _error;
-    private String _errorMessage;
-    
-    public AddressBookServiceData(I2PAppContext context) {
-        _context = context;
-        _log = context.logManager().getLog(AddressBookServiceData.class);
-        _addressBook = null;
-        _activityLog = null;
-        _error = null;
-        _errorMessage = null;
-    }
-    
-    public AddressBook getAddressBook() { return _addressBook; }
-    public void setAddressBook(AddressBook book) { _addressBook = book; }
-    public Map getActivityLog() { return _activityLog; }
-    public void setActivityLog(Map log) { _activityLog = log; }
-    
-    public Exception getError() { return _error; }
-    public String getErrorMessage() { return _errorMessage; }
-    
-    public void load(File from) {
-        FileInputStream fis = null;
-        try {
-            fis = new FileInputStream(from);
-            AddressBook addressBook = new AddressBook(_context);
-            addressBook.read(fis);
-            _addressBook = addressBook;
-            if (_log.shouldLog(Log.DEBUG))
-                _log.debug("Address book: " + addressBook);
-            Properties props = DataHelper.readProperties(fis);
-            Map log = new HashMap(props.size());
-            for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
-                String key = (String)iter.next();
-                String event = props.getProperty(key);
-                long when = 0;
-                try {
-                    when = Long.parseLong(key);
-                    while (log.containsKey(new Long(when)))
-                        when++;
-                    log.put(new Long(when), event);
-                    if (_log.shouldLog(Log.DEBUG))
-                        _log.debug("Activity log: on " + new Date(when) + ": " + event);
-                } catch (NumberFormatException nfe) {
-                    if (_log.shouldLog(Log.WARN))
-                        _log.warn("Corrupt activity log entry: when=" + key, nfe);
-                }
-            }
-            _activityLog = log;
-        } catch (Exception e) {
-            _error = e;
-            _errorMessage = "Error reading the address book from " + from;
-        }
-    }
-    
-    public void store(File to) {
-        FileOutputStream fos = null;
-        try {
-            fos = new FileOutputStream(to);
-            _addressBook.write(fos);
-            Properties props = new Properties();
-            for (Iterator iter = _activityLog.keySet().iterator(); iter.hasNext(); ) {
-                Long when = (Long)iter.next();
-                String msg = (String)_activityLog.get(when);
-                props.setProperty(when.toString(), msg);
-            }
-            DataHelper.writeProperties(fos, props);
-        } catch (Exception e) {
-            _error = e;
-            _errorMessage = "Error writing the address book to " + to;
-        } finally {
-            if (fos != null) try { fos.close(); } catch (IOException ioe) {}
-        }
-    }
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/CreateEntryCLI.java b/apps/myi2p/java/src/net/i2p/myi2p/address/CreateEntryCLI.java
deleted file mode 100644
index b90de3c577..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/address/CreateEntryCLI.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package net.i2p.myi2p.address;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-import net.i2p.I2PAppContext;
-import net.i2p.data.Destination;
-import net.i2p.util.Log;
-
-/**
- * CreateEntryCLI addressBookFile referenceFile localName subscriptionFrequencyHours [ key=value]*
- */
-public class CreateEntryCLI {
-    private I2PAppContext _context;
-    private String _args[];
-    private String _addressBook;
-    private String _referenceFile;
-    private String _localName;
-    private int _subscriptionFrequencyHours;
-    private Properties _options;
-    
-    public CreateEntryCLI(String args[]) {
-        _context = new I2PAppContext();
-        _args = args;
-        _options = new Properties();
-    }
-    
-    public void execute() {
-        if (parseArgs())
-            doExecute();
-        else
-            System.err.println("Usage: CreateEntryCLI addressBookFile referenceFile localName subscriptionFrequencyHours[ key=value]*");
-    }
-    
-    private boolean parseArgs() {
-        if ( (_args == null) || (_args.length < 3) ) 
-            return false;
-        _addressBook = _args[0];
-        _referenceFile = _args[1];
-        _localName = _args[2];
-        try {
-            _subscriptionFrequencyHours = Integer.parseInt(_args[3]);
-        } catch (NumberFormatException nfe) {
-            return false;
-        }
-        for (int i = 4; i < _args.length; i++) {
-            int eq = _args[i].indexOf('=');
-            if ( (eq <= 0) || (eq >= _args[i].length() - 1) )
-                continue;
-            String key = _args[i].substring(0,eq);
-            String val = _args[i].substring(eq+1);
-            _options.setProperty(key, val);
-        }
-        return true;
-    }
-    
-    private void doExecute() {
-        AddressBookServiceData data = new AddressBookServiceData(_context);
-        File f = new File(_addressBook);
-        if (f.exists()) {
-            data.load(f);
-            if (data.getError() != null) {
-                if (data.getErrorMessage() != null)
-                    System.err.println(data.getErrorMessage());
-                data.getError().printStackTrace();
-                return;
-            }
-        } else {
-            data.setAddressBook(new AddressBook(_context));
-            data.setActivityLog(new HashMap());
-        }
-        NameReference ref = null;
-        FileInputStream fis = null;
-        try {
-            fis = new FileInputStream(_referenceFile); 
-            ref = new NameReference(_context);
-            ref.read(fis);
-        } catch (Exception e) {
-            System.err.println("Name reference under " + _referenceFile + " is corrupt");
-            e.printStackTrace();
-            return;
-        } finally {
-            if (fis != null) try { fis.close(); } catch (IOException ioe) {}
-        }
-        
-        AddressBook book = data.getAddressBook();
-        Map activityLog = data.getActivityLog();
-        
-        AddressBookEntry oldEntry = book.getEntry(_localName);
-        
-        AddressBookEntry entry = new AddressBookEntry(_context);
-        entry.setLocalName(_localName);
-        entry.setNameReference(ref);
-        
-        Subscription sub = new Subscription(_context);
-        sub.setQueryFrequencyMinutes(60*_subscriptionFrequencyHours);
-        
-        entry.setSubscription(sub);
-        entry.setOptions(_options);
-
-        if (oldEntry == null) {
-            book.addEntry(entry);
-            System.out.println("New address book entry added for " + entry.getLocalName());
-            activityLog.put(new Long(_context.clock().now()), "New address book entry added for " + entry.getLocalName());
-        } else {
-            Destination oldDest = oldEntry.getNameReference().getDestination();
-            if (oldDest.equals(ref.getDestination())) {
-                if (ref.getSequenceNum() < oldEntry.getNameReference().getSequenceNum()) {
-                    System.err.println("Not updating the address book - newer reference for " + entry.getLocalName() + " exists");
-                    return;
-                } else {
-                    // same or newer rev
-                    if (null != entry.getSubscription()) {
-                        if (null != oldEntry.getSubscription()) {
-                            entry.getSubscription().setLastQueryAttempt(oldEntry.getSubscription().getLastQueryAttempt());
-                            entry.getSubscription().setLastQuerySuccess(oldEntry.getSubscription().getLastQuerySuccess());
-                        }
-                    }
-                    book.addEntry(entry);
-                    System.err.println("Updating the options and subscription for an existing reference to " + entry.getLocalName());
-                    activityLog.put(new Long(_context.clock().now()), "Updating options and subscription for " + entry.getLocalName());
-                }
-            } else {
-                book.addConflictingReference(ref);
-                System.out.println("Old entry exists for " + _localName + " - adding a conflicting reference");
-                System.out.println("Existing entry points to " + oldEntry.getNameReference().getDestination().calculateHash().toBase64());
-                System.out.println("New entry points to " + entry.getNameReference().getDestination().calculateHash().toBase64());
-                
-                activityLog.put(new Long(_context.clock().now()), "Adding conflicting reference for " + entry.getLocalName());
-            }
-        }
-
-        data.setAddressBook(book);
-        data.setActivityLog(activityLog);
-        
-        data.store(f);
-        if (data.getError() != null) {
-            if (data.getErrorMessage() != null)
-                System.err.println(data.getErrorMessage());
-            data.getError().printStackTrace();
-            return;
-        }
-    }
-    
-    public static void main(String args[]) {
-        CreateEntryCLI cli = new CreateEntryCLI(args);
-        cli.execute();
-    }
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/CreateNameReferenceCLI.java b/apps/myi2p/java/src/net/i2p/myi2p/address/CreateNameReferenceCLI.java
deleted file mode 100644
index f57ede9368..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/address/CreateNameReferenceCLI.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package net.i2p.myi2p.address;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-import java.util.Iterator;
-import java.util.Properties;
-
-import net.i2p.I2PAppContext;
-import net.i2p.data.Destination;
-import net.i2p.data.PrivateKey;
-import net.i2p.data.SigningPrivateKey;
-import net.i2p.util.Log;
-
-/**
- * CreateNameReferenceCLI outputFile privateDestFile preferredName sequenceNum serviceType[ key=value]*
- */
-public class CreateNameReferenceCLI {
-    private I2PAppContext _context;
-    private String _args[];
-    private String _outputFile;
-    private String _destFile;
-    private String _preferredName;
-    private long _sequenceNum;
-    private String _serviceType;
-    private Properties _options;
-    
-    public CreateNameReferenceCLI(String[] args) {
-        _context = new I2PAppContext();
-        _args = args;
-        _options = new Properties();
-    }
-    
-    public void execute() {
-        if (parseArgs())
-            doExecute();
-        else
-            System.err.println("Usage: CreateNameReferenceCLI outputFile privateDestFile preferredName sequenceNum serviceType[ key=value]*");
-    }
-    
-    private boolean parseArgs() {
-        if ( (_args == null) || (_args.length < 4) ) 
-            return false;
-        _outputFile = _args[0];
-        _destFile = _args[1];
-        _preferredName = _args[2];
-        try {
-            _sequenceNum = Long.parseLong(_args[3]);
-        } catch (NumberFormatException nfe) {
-            return false;
-        }
-        _serviceType = _args[4];
-        
-        for (int i = 5; i < _args.length; i++) {
-            int eq = _args[i].indexOf('=');
-            if ( (eq <= 0) || (eq >= _args[i].length() - 1) )
-                continue;
-            String key = _args[i].substring(0,eq);
-            String val = _args[i].substring(eq+1);
-            _options.setProperty(key, val);
-        }
-        return true;
-    }
-    
-    private void doExecute() {
-        Destination dest = null;
-        SigningPrivateKey priv = null;
-        FileInputStream fis = null;
-        try {
-            fis = new FileInputStream(_destFile);
-            dest = new Destination();
-            dest.readBytes(fis);
-            PrivateKey whocares = new PrivateKey();
-            whocares.readBytes(fis);
-            priv = new SigningPrivateKey();
-            priv.readBytes(fis);
-        } catch (Exception e) {
-            System.err.println("Destination private keys under " + _destFile + " are corrupt");
-            e.printStackTrace();
-            return;
-        } finally {
-            if (fis != null) try { fis.close(); } catch (IOException ioe) {}
-        }
-        
-        NameReference ref = new NameReference(_context);
-        ref.setDestination(dest);
-        ref.setPreferredName(_preferredName);
-        ref.setSequenceNum(_sequenceNum);
-        ref.setServiceType(_serviceType);
-        if (_options != null) {
-            for (Iterator iter = _options.keySet().iterator(); iter.hasNext(); ) {
-                String key = (String)iter.next();
-                String val = _options.getProperty(key);
-                ref.setOption(key, val);
-            }
-        }
-        
-        try {
-            ref.sign(priv);
-        } catch (IllegalStateException ise) {
-            System.err.println("Error signing the new reference");
-            ise.printStackTrace();
-        }
-        
-        FileOutputStream fos = null;
-        try {
-            fos = new FileOutputStream(_outputFile);
-            ref.write(fos);
-        } catch (IOException ioe) {
-            System.err.println("Error writing out the new reference");
-            ioe.printStackTrace();
-        } finally {
-            if (fos != null) try { fos.close(); } catch (IOException ioe) {}
-        }
-        
-        System.out.println("Reference created at " + _outputFile);
-    }
-    
-    public static void main(String args[]) {
-        CreateNameReferenceCLI cli = new CreateNameReferenceCLI(args);
-        cli.execute();
-    }
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/NameReference.java b/apps/myi2p/java/src/net/i2p/myi2p/address/NameReference.java
deleted file mode 100644
index c8e5971553..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/address/NameReference.java
+++ /dev/null
@@ -1,198 +0,0 @@
-package net.i2p.myi2p.address;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.HashSet;
-import java.util.Properties;
-import java.util.Set;
-
-import net.i2p.I2PAppContext;
-
-import net.i2p.data.DataHelper;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.Destination;
-import net.i2p.data.Signature;
-import net.i2p.data.SigningPrivateKey;
-import net.i2p.util.Log;
-
-/**
- * Define a verified and immutable reference to a particular I2P destination.
- *
- */
-public class NameReference {
-    private I2PAppContext _context;
-    private Log _log;
-    private Destination _destination;
-    private String _preferredName;
-    private String _serviceType;
-    private long _sequenceNum;
-    private Properties _options;
-    private Signature _signature;
-    
-    public static final byte[] VERSION_PREFIX = "MyI2P_NameReference_1.0".getBytes();
-    
-    public NameReference(I2PAppContext context) {
-        _context = context;
-        _log = context.logManager().getLog(NameReference.class);
-        _destination = null;
-        _preferredName = null;
-        _serviceType = null;
-        _sequenceNum = -1;
-        _options = new Properties();
-        _signature = null;
-    }
-    
-    /** retrieve the destination this reference points at */
-    public Destination getDestination() { return _destination; }
-    public void setDestination(Destination dest) { _destination = dest; }
-    
-    /** retrieve the name this destination would like to be called */
-    public String getPreferredName() { return _preferredName; }
-    public void setPreferredName(String name) { _preferredName = name; }
-    
-    /** retrieve the type of service at this destination (eepsite, ircd, etc) */
-    public String getServiceType() { return _serviceType; }
-    public void setServiceType(String type) { _serviceType = type; }
-    
-    /** 
-     * data point to allow the reference to be updated.  The reference with the
-     * larger sequence number should clobber an older reference.
-     *
-     */
-    public long getSequenceNum() { return _sequenceNum; }
-    public void setSequenceNum(long num) { _sequenceNum = num; }
-    
-    /** Get a list of option names (strings) */
-    public Set getOptionNames() { return new HashSet(_options.keySet()); }
-    
-    /** Access any options published in the reference */
-    public String getOption(String name) { return (String)_options.getProperty(name); }
-    
-    /**
-     * Specify a particular value for an option.  If the value is null, the 
-     * entry is removed.  The name cannot have an '=' or newline, and the 
-     * value cannot have a newline.
-     *
-     * @throws IllegalArgumentException if the name or value is illegal
-     */
-    public void setOption(String name, String value) { 
-        if (name == null) throw new IllegalArgumentException("Missing name");
-        if (name.indexOf('=') != -1) 
-            throw new IllegalArgumentException("Name cannot have an = sign");
-        if (name.indexOf('\n') != -1)
-            throw new IllegalArgumentException("Name cannot have a newline");
-        
-        if (value != null) {
-            if (value.indexOf('\n') != -1)
-                throw new IllegalArgumentException("Values do not allow newlines");
-            _options.setProperty(name, value);
-        } else {
-            _options.remove(name);
-        }
-    }
-
-    /** Access the DSA signature authenticating this reference */
-    public Signature getSignature() { return _signature; }
-    public void setSignature(Signature sig) { _signature = sig; }
-    
-    /** Verify the DSA signature, returning true if it is valid, false otherwise */
-    public boolean validate() {
-        try {
-            byte raw[] = toSignableByteArray();
-            return _context.dsa().verifySignature(_signature, raw, _destination.getSigningPublicKey());
-        } catch (IllegalStateException ise) {
-            return false;
-        }
-    }
-    
-    /**
-     * Sign the data
-     *
-     * @throws IllegalStateException if the data is invalid
-     */
-    public void sign(SigningPrivateKey key) throws IllegalStateException {
-        byte signable[] = toSignableByteArray();
-        _signature = _context.dsa().sign(signable, key);
-    }
-    
-    /**
-     * Retrieve the full serialized and signed version of this name reference
-     * 
-     * @throws IllegalStateException if the signature or other data is invalid
-     */
-    public void write(OutputStream out) throws IllegalStateException, IOException {
-        if (_signature == null) throw new IllegalStateException("No signature");
-        byte signable[] = toSignableByteArray();
-        out.write(signable);
-        try {
-            _signature.writeBytes(out);
-        } catch (DataFormatException dfe) {
-            throw new IllegalStateException("Signature was corrupt - " + dfe.getMessage());
-        }
-    }
-    
-    /**
-     * Retrieve the signable (but not including the signature) name reference
-     *
-     * @throws IllegalStateException if the data is invalid
-     */
-    private byte[] toSignableByteArray() throws IllegalStateException {
-        if (_sequenceNum < 0) throw new IllegalStateException("Sequence number is invalid");
-        if (_preferredName == null) throw new IllegalStateException("Preferred name is invalid");
-        if (_serviceType == null) throw new IllegalStateException("Service type is invalid");
-        if (_options == null) throw new IllegalStateException("Options not constructed");
-        if (_destination == null) throw new IllegalStateException("Destination not specified");
-        
-        ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
-        try {
-            baos.write(VERSION_PREFIX);
-            _destination.writeBytes(baos);
-            DataHelper.writeLong(baos, 4, _sequenceNum);
-            DataHelper.writeString(baos, _preferredName);
-            DataHelper.writeString(baos, _serviceType);
-            DataHelper.writeProperties(baos, _options); // sorts alphabetically
-            return baos.toByteArray();
-        } catch (DataFormatException dfe) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("Corrupted trying to write entry", dfe);
-            return null;
-        } catch (IOException ioe) {
-            if (_log.shouldLog(Log.ERROR))
-                _log.error("IOError writing to memory?", ioe);
-            return null;
-        }
-    }
-    
-    /**
-     * Read a full signed reference from the given stream
-     *
-     * @throws DataFormatException if the reference is corrupt
-     * @throws IOException if there is an error reading the stream
-     */
-    public void read(InputStream in) throws DataFormatException, IOException {
-        byte versionBuf[] = new byte[VERSION_PREFIX.length];
-        int len = DataHelper.read(in, versionBuf);
-        if (len != versionBuf.length) 
-            throw new IllegalArgumentException("Version length too short ("+ len + ")");
-        if (!DataHelper.eq(versionBuf, VERSION_PREFIX))
-            throw new IllegalArgumentException("Version mismatch (" + new String(versionBuf) + ")");
-        Destination dest = new Destination();
-        dest.readBytes(in);
-        long seq = DataHelper.readLong(in, 4);
-        String name = DataHelper.readString(in);
-        String type = DataHelper.readString(in);
-        Properties opts = DataHelper.readProperties(in);
-        Signature sig = new Signature();
-        sig.readBytes(in);
-        
-        // ok, nothing b0rked
-        _destination = dest;
-        _sequenceNum = seq;
-        _preferredName = name;
-        _serviceType = type;
-        _options = opts;
-        _signature = sig;
-    }
-}
diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/Subscription.java b/apps/myi2p/java/src/net/i2p/myi2p/address/Subscription.java
deleted file mode 100644
index 0680fc6a29..0000000000
--- a/apps/myi2p/java/src/net/i2p/myi2p/address/Subscription.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package net.i2p.myi2p.address;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import java.util.Date;
-
-import net.i2p.I2PAppContext;
-import net.i2p.data.DataHelper;
-import net.i2p.data.DataFormatException;
-
-/**
- * Contains the preferences for subscribing to a particular peer's address 
- * book.
- */
-public class Subscription {
-    private I2PAppContext _context;
-    private int _queryFrequencyMinutes;
-    private long _lastQueryAttempt;
-    private long _lastQuerySuccess;
-    
-    /** no subscription more often than 4 times a day */
-    public static final int MIN_FREQUENCY = 6*60*60*1000;
-    
-    public Subscription(I2PAppContext context) {
-        _context = context;
-    }
-    
-    /** how often do we want to query the peer (in minutes) */
-    public int getQueryFrequencyMinutes() { return _queryFrequencyMinutes; }
-    public void setQueryFrequencyMinutes(int freq) { _queryFrequencyMinutes = freq; }
-    
-    /** when did we last successfully query the peer */
-    public long getLastQuerySuccess() { return _lastQuerySuccess; }
-    public void setLastQuerySuccess(long when) { _lastQuerySuccess = when; }
-    
-    /** when did we last attempt to query the peer */
-    public long getLastQueryAttempt() { return _lastQueryAttempt; }
-    public void setLastQueryAttempt(long when) { _lastQueryAttempt = when; }
-        
-    /** load the data from the stream */
-    public void read(InputStream in) throws IOException {
-        try {
-            int freq = (int)DataHelper.readLong(in, 2);
-            Date attempt = DataHelper.readDate(in);
-            Date success = DataHelper.readDate(in);
-            _queryFrequencyMinutes = (freq < MIN_FREQUENCY ? MIN_FREQUENCY : freq);
-            _lastQueryAttempt = (attempt != null ? attempt.getTime() : -1);
-            _lastQuerySuccess = (success != null ? success.getTime() : -1);
-        } catch (DataFormatException dfe) {
-            throw new IOException("Corrupt subscription: " + dfe.getMessage());
-        }
-    }
-    
-    /** persist the data to the stream */
-    public void write(OutputStream out) throws IOException {
-        try {
-            DataHelper.writeLong(out, 2, _queryFrequencyMinutes);
-            DataHelper.writeDate(out, new Date(_lastQueryAttempt));
-            DataHelper.writeDate(out, new Date(_lastQuerySuccess));
-        } catch (DataFormatException dfe) {
-            throw new IOException("Corrupt subscription: " + dfe.getMessage());
-        }
-    }
-}
diff --git a/apps/myi2p/myi2p.config b/apps/myi2p/myi2p.config
deleted file mode 100644
index 2d66d576c1..0000000000
--- a/apps/myi2p/myi2p.config
+++ /dev/null
@@ -1,3 +0,0 @@
-keyFile=myi2p.keys
-service.0.classname=net.i2p.myi2p.address.AddressBookService
-service.0.type=AddressBook
\ No newline at end of file
diff --git a/apps/netmonitor/harvester.config b/apps/netmonitor/harvester.config
deleted file mode 100644
index 91f3332245..0000000000
--- a/apps/netmonitor/harvester.config
+++ /dev/null
@@ -1,130 +0,0 @@
-# dropped jobs
-statGroup.0.name=droppedJobs
-statGroup.0.detail.0.name=num dropped jobs (minute)
-statGroup.0.detail.0.option=stat_jobQueue.droppedJobs.60m
-statGroup.0.detail.0.field=3
-statGroup.0.detail.1.name=num dropped jobs (hour)
-statGroup.0.detail.1.option=stat_jobQueue.droppedJobs.60h
-statGroup.0.detail.1.field=3
-# 
-statGroup.1.name=encryptTime
-statGroup.1.detail.0.name=encryption time avg ms (minute)
-statGroup.1.detail.0.option=stat_crypto.elGamal.encrypt.60s
-statGroup.1.detail.0.field=0
-statGroup.1.detail.1.name=num encryptions (minute)
-statGroup.1.detail.1.option=stat_crypto.elGamal.encrypt.60s
-statGroup.1.detail.1.field=7
-statGroup.1.detail.2.name=encryption time avg ms (hour)
-statGroup.1.detail.2.option=stat_crypto.elGamal.encrypt.60s
-statGroup.1.detail.2.field=0
-statGroup.1.detail.3.name=num encryptions (hour)
-statGroup.1.detail.3.option=stat_crypto.elGamal.encrypt.60s
-statGroup.1.detail.3.field=7
-# 
-statGroup.2.name=processingTime
-statGroup.2.detail.0.name=process time avg ms (minute)
-statGroup.2.detail.0.option=stat_transport.sendProcessingTime.60s
-statGroup.2.detail.0.field=0
-statGroup.2.detail.1.name=process events (minute)
-statGroup.2.detail.1.option=stat_transport.sendProcessingTime.60s
-statGroup.2.detail.1.field=7
-statGroup.2.detail.2.name=process time avg ms (hour)
-statGroup.2.detail.2.option=stat_transport.sendProcessingTime.60m
-statGroup.2.detail.2.field=0
-statGroup.2.detail.3.name=process events(hour)
-statGroup.2.detail.3.option=stat_transport.sendProcessingTime.60m
-statGroup.2.detail.3.field=7
-# 
-statGroup.3.name=jobInfo
-statGroup.3.detail.0.name=job run avg ms (minute)
-statGroup.3.detail.0.option=stat_jobQueue.jobRun.60s
-statGroup.3.detail.0.field=0
-statGroup.3.detail.1.name=job lag avg ms (minute)
-statGroup.3.detail.1.option=stat_jobQueue.jobLag.60s
-statGroup.3.detail.1.field=0
-statGroup.3.detail.2.name=job count (minute)
-statGroup.3.detail.2.option=stat_jobQueue.jobRun.60s
-statGroup.3.detail.2.field=7
-statGroup.3.detail.3.name=job run avg ms (hour)
-statGroup.3.detail.3.option=stat_jobQueue.jobRun.60m
-statGroup.3.detail.3.field=0
-statGroup.3.detail.4.name=job lag avg ms (hour)
-statGroup.3.detail.4.option=stat_jobQueue.jobLag.60m
-statGroup.3.detail.4.field=0
-statGroup.3.detail.5.name=job count (hour)
-statGroup.3.detail.5.option=stat_jobQueue.jobRun.60m
-statGroup.3.detail.5.field=7
-# 
-statGroup.4.name=tunnels
-statGroup.4.detail.0.name=participating tunnels count (5 minutes)
-statGroup.4.detail.0.option=stat_tunnel.participatingTunnels.5m
-statGroup.4.detail.0.field=0
-statGroup.4.detail.1.name=participating tunnels joined (5 minutes)
-statGroup.4.detail.1.option=stat_tunnel.participatingTunnels.5m
-statGroup.4.detail.1.field=3
-statGroup.4.detail.2.name=participating tunnels count (hour)
-statGroup.4.detail.2.option=stat_tunnel.participatingTunnels.60m
-statGroup.4.detail.2.field=0
-statGroup.4.detail.3.name=participating tunnels joined (hour)
-statGroup.4.detail.3.option=stat_tunnel.participatingTunnels.60m
-statGroup.4.detail.3.field=3
-# 
-statGroup.5.name=transfer
-statGroup.5.detail.0.name=messages sent (5 minutes)
-statGroup.5.detail.0.option=stat_transport.sendMessageSize.5m
-statGroup.5.detail.0.field=7
-statGroup.5.detail.1.name=send message size avg (5 minutes)
-statGroup.5.detail.1.option=stat_transport.sendMessageSize.5m
-statGroup.5.detail.1.field=0
-statGroup.5.detail.2.name=messages sent (hour)
-statGroup.5.detail.2.option=stat_transport.sendMessageSize.60m
-statGroup.5.detail.2.field=7
-statGroup.5.detail.3.name=send message size avg (hour)
-statGroup.5.detail.3.option=stat_transport.sendMessageSize.60m
-statGroup.5.detail.3.field=0
-statGroup.5.detail.4.name=messages received (5 minutes)
-statGroup.5.detail.4.option=stat_transport.receiveMessageSize.5m
-statGroup.5.detail.4.field=7
-statGroup.5.detail.5.name=receive message size avg (5 minutes)
-statGroup.5.detail.5.option=stat_transport.receiveMessageSize.5m
-statGroup.5.detail.5.field=0
-statGroup.5.detail.6.name=messages received (hour)
-statGroup.5.detail.6.option=stat_transport.receiveMessageSize.60m
-statGroup.5.detail.6.field=7
-statGroup.5.detail.7.name=receive message size avg (hour)
-statGroup.5.detail.7.option=stat_transport.receiveMessageSize.60m
-statGroup.5.detail.7.field=0
-# 
-statGroup.6.name=networkDbHandling
-statGroup.6.detail.0.name=lookups received (5 minutes)
-statGroup.6.detail.0.option=stat_netDb.lookupsReceived.5m
-statGroup.6.detail.0.field=3
-statGroup.6.detail.1.name=lookups handled (5 minutes)
-statGroup.6.detail.1.option=stat_netDb.lookupsHandled.5m
-statGroup.6.detail.1.field=3
-statGroup.6.detail.2.name=lookups matched (5 minutes)
-statGroup.6.detail.2.option=stat_netDb.lookupsReceived.5m
-statGroup.6.detail.2.field=3
-statGroup.6.detail.3.name=lookups received (hour)
-statGroup.6.detail.3.option=stat_netDb.lookupsReceived.60m
-statGroup.6.detail.3.field=3
-statGroup.6.detail.4.name=lookups handled (hour)
-statGroup.6.detail.4.option=stat_netDb.lookupsHandled.60m
-statGroup.6.detail.4.field=3
-statGroup.6.detail.5.name=lookups matched (hour)
-statGroup.6.detail.5.option=stat_netDb.lookupsReceived.60m
-statGroup.6.detail.5.field=3
-# 
-statGroup.7.name=networkDbActivity
-statGroup.7.detail.0.name=lookups sent (hour)
-statGroup.7.detail.0.option=stat_netDb.successPeers.60m
-statGroup.7.detail.0.field=3
-statGroup.7.detail.1.name=lookup peers (hour)
-statGroup.7.detail.1.option=stat_netDb.successPeers.60m
-statGroup.7.detail.1.field=0
-statGroup.7.detail.2.name=db store sent (5 minutes)
-statGroup.7.detail.2.option=stat_netDb.storeSent.5m
-statGroup.7.detail.2.field=3
-statGroup.7.detail.3.name=db store sent (hour)
-statGroup.7.detail.3.option=stat_netDb.storeSent.60m
-statGroup.7.detail.3.field=3
\ No newline at end of file
diff --git a/apps/netmonitor/java/build.xml b/apps/netmonitor/java/build.xml
deleted file mode 100644
index a463045561..0000000000
--- a/apps/netmonitor/java/build.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project basedir="." default="all" name="netmonitor">
-    <target name="all" depends="clean, build" />
-    <target name="build" depends="builddep, jar" />
-    <target name="builddep">
-        <ant dir="../../../core/java/" target="build" />
-    </target>
-    <target name="buildGUI" depends="build, jarGUI" />
-    <target name="compile">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/obj" />
-        <javac srcdir="./src" debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj" includes="net/**/*.java" excludes="net/i2p/netmonitor/gui/**" classpath="../../../core/java/build/i2p.jar" />
-    </target>
-
-    <target name="compileGUI" depends="builddep">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/obj" />
-        <javac debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj">
-            <src path="src/" />
-            <classpath path="../../../core/java/build/i2p.jar" />
-            <classpath path="../../jfreechart/jfreechart-0.9.17/lib/jcommon-0.9.2.jar" />
-            <classpath path="../../jfreechart/jfreechart-0.9.17/lib/log4j-1.2.8.jar" />
-            <classpath path="../../jfreechart/jfreechart-0.9.17/jfreechart-0.9.17.jar" />
-        </javac>
-    </target>
-
-    <target name="jarGUI" depends="compileGUI">
-        <copy file="../../jfreechart/jfreechart-0.9.17/jfreechart-0.9.17.jar" todir="build/" />
-        <copy file="../../jfreechart/jfreechart-0.9.17/lib/log4j-1.2.8.jar" todir="build/" />
-        <copy file="../../jfreechart/jfreechart-0.9.17/lib/jcommon-0.9.2.jar" todir="build/" />
-        <jar destfile="./build/netviewer.jar" basedir="./build/obj" includes="**">
-            <manifest>
-                <attribute name="Main-Class" value="net.i2p.netmonitor.gui.NetViewer" />
-                <attribute name="Class-Path" value="log4j-1.2.8.jar jcommon-0.9.2.jar jfreechart-0.9.17.jar netviewer.jar i2p.jar" />
-            </manifest>
-        </jar>
-        <echo message="You will need to copy the log4j, jcommon, and jfreechart jar files into your lib dir" />
-    </target>
-
-    <target name="jar" depends="compile">
-        <jar destfile="./build/netmonitor.jar" basedir="./build/obj" includes="**/*.class">
-            <manifest>
-                <attribute name="Main-Class" value="net.i2p.netmonitor.NetMonitor" />
-                <attribute name="Class-Path" value="i2p.jar netmonitor.jar" />
-            </manifest>
-        </jar>
-    </target>
-    <target name="javadoc">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/javadoc" />
-        <javadoc 
-            sourcepath="./src:../../../core/java/src:../../../core/java/test" destdir="./build/javadoc" 
-            packagenames="*" 
-            use="true" 
-            access="package"
-            splitindex="true" 
-            windowtitle="I2P netmonitor" />
-    </target>
-    <target name="clean">
-        <delete dir="./build" />
-    </target>
-    <target name="cleandep" depends="clean">
-        <ant dir="../../../core/java/" target="cleandep" />
-    </target>
-    <target name="distclean" depends="clean">
-        <ant dir="../../../core/java/" target="distclean" />
-        <delete dir="./lib/" />
-    </target>
-</project>
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/DataHarvester.java b/apps/netmonitor/java/src/net/i2p/netmonitor/DataHarvester.java
deleted file mode 100644
index 6d14a8174f..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/DataHarvester.java
+++ /dev/null
@@ -1,245 +0,0 @@
-package net.i2p.netmonitor;
-
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Properties;
-import java.util.StringTokenizer;
-
-import net.i2p.data.RouterInfo;
-import net.i2p.util.Clock;
-import net.i2p.util.Log;
-
-/**
- * Pull out important data from the published routerInfo and stash it away
- * in the netMonitor
- *
- */
-class DataHarvester {
-    private static final Log _log = new Log(DataHarvester.class);
-    private static final DataHarvester _instance = new DataHarvester();
-    public static final DataHarvester getInstance() { return _instance; }
-    /**
-     * Contains the list of StatGroup objects loaded from the harvest.config file
-     * {@see StatGroupLoader} where each statGroup defines a set of stats to pull
-     * from each router's options.
-     *
-     */
-    private List _statGroups;
-    
-    /**
-     * Where are we reading the stat groups from?  For now, "harvester.config".
-     */
-    private static final String STAT_GROUP_CONFIG_FILENAME = "harvester.config";
-    
-    protected DataHarvester() {
-        _statGroups = StatGroupLoader.loadStatGroups(STAT_GROUP_CONFIG_FILENAME);
-    }
-    
-    /**
-     * Harvest all of the data from the peers and store it in the monitor.
-     *
-     * @param peers list of RouterInfo structures to harvest from
-     */
-    public void harvestData(NetMonitor monitor, List peers) {
-        for (int i = 0; i < peers.size(); i++) {
-            harvestData(monitor, (RouterInfo)peers.get(i), peers);
-        }
-    }
-    
-    /**
-     * Pull out all the data we can for the specified peer
-     *
-     * @param peer who are we focusing on in this pass
-     * @param peers everyone on the network, to co
-     */
-    private void harvestData(NetMonitor monitor, RouterInfo peer, List peers) {
-        _log.info("Harvest the data from " + peer.getIdentity().getHash().toBase64());
-        harvestRank(monitor, peer, peers);
-        harvestRankAs(monitor, peer);
-        harvestGroups(monitor, peer);
-    }
-    
-    /**
-     *  How does the peer rank other routers?  Stored in the peer summary as 
-     * "rankAs", containing 4 longs (numFast, numReliable, numNotFailing, numFailing)
-     *
-     * @param peer who is doing the ranking
-     */
-    private void harvestRankAs(NetMonitor monitor, RouterInfo peer) {
-        int numFast = 0;
-        int numHighCapacity = 0;
-        int numNotFailing = 0;
-        int numFailing = 0;
-        
-        Properties props = peer.getOptions();
-        for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
-            String key = (String)iter.next();
-            if (key.startsWith("profile.")) {
-                String val = (String)props.get(key);
-                if (val.indexOf("fast") != -1)
-                    numFast++;
-                else if (val.indexOf("highCapacity") != -1)
-                    numHighCapacity++;
-                else if (val.indexOf("notFailing") != -1)
-                    numNotFailing++;
-                else if (val.indexOf("failing") != -1)
-                    numFailing++;
-            }
-        }
-        
-        long rankAs[] = new long[4];
-        rankAs[0] = numFast;
-        rankAs[1] = numHighCapacity;
-        rankAs[2] = numNotFailing;
-        rankAs[3] = numFailing;
-        String description = "how we rank peers"; 
-        String valDescr[] = new String[4];
-        valDescr[0] = "# peers we rank as fast";
-        valDescr[1] = "# peers we rank as high capacity";
-        valDescr[2] = "# peers we rank as not failing";
-        valDescr[3] = "# peers we rank as failing";
-        monitor.addData(peer.getIdentity().getHash().toBase64(), "rankAs", description, valDescr, peer.getPublished(), rankAs);
-    }
-    
-    /**
-     * How do other peers rank the current peer?  Stored in the peer summary as 
-     * "rank", containing 4 longs (numFast, numReliable, numNotFailing, numFailing)
-     *
-     * @param peer who do we want to check the network's perception of
-     * @param peers peers whose rankings we will use
-     */
-    private void harvestRank(NetMonitor monitor, RouterInfo peer, List peers) {
-        int numFast = 0;
-        int numHighCapacity = 0;
-        int numNotFailing = 0;
-        int numFailing = 0;
-        
-        // now count 'em
-        for (int i = 0; i < peers.size(); i++) {
-            RouterInfo cur = (RouterInfo)peers.get(i);
-            if (peer == cur) continue;
-            String prop = "profile." + peer.getIdentity().getHash().toBase64().replace('=', '_');
-            String val = cur.getOptions().getProperty(prop);
-            if ( (val == null) || (val.length() <= 0) ) continue;
-            if (val.indexOf("fast") != -1)
-                numFast++;
-            else if (val.indexOf("highCapacity") != -1)
-                numHighCapacity++;
-            else if (val.indexOf("notFailing") != -1)
-                numNotFailing++;
-            else if (val.indexOf("failing") != -1)
-                numFailing++;
-        }
-        
-        long rank[] = new long[4];
-        rank[0] = numFast;
-        rank[1] = numHighCapacity;
-        rank[2] = numNotFailing;
-        rank[3] = numFailing;
-        String description = "how peers rank us";
-        String valDescr[] = new String[4];
-        valDescr[0] = "# peers ranking us as fast";
-        valDescr[1] = "# peers ranking us as high capacity";
-        valDescr[2] = "# peers ranking us as not failing";
-        valDescr[3] = "# peers ranking us as failing";
-        // we use the current date, not the published date, since this sample doesnt come from them
-        monitor.addData(peer.getIdentity().getHash().toBase64(), "rank", description, valDescr, Clock.getInstance().now(), rank);
-    }
-    
-    /**
-     * Harvest all data points from the peer 
-     * 
-     */
-    private void harvestGroups(NetMonitor monitor, RouterInfo peer) {
-        _log.debug("Harvesting group data for " + peer.getIdentity().getHash().toBase64());
-        for (int i = 0; i < _statGroups.size(); i++) {
-            StatGroup group = (StatGroup)_statGroups.get(i);
-            harvestGroup(monitor, peer, group);
-        }
-    }
-    
-    /**
-     * Harvest the data points for the given group from the peer and toss them 
-     * into the monitor
-     *
-     */
-    private void harvestGroup(NetMonitor monitor, RouterInfo peer, StatGroup group) {
-        _log.debug("Harvesting group data for " + peer.getIdentity().getHash().toBase64() + " / " + group.getDescription());
-        double values[] = harvestGroupValues(peer, group);
-        if (values == null) return;
-           
-        String valDescr[] = new String[group.getStatCount()];
-        for (int i = 0; i < group.getStatCount(); i++)
-            valDescr[i] = group.getStat(i).getStatDescription();
-        monitor.addData(peer.getIdentity().getHash().toBase64(), group.getDescription(), group.getDescription(), valDescr, peer.getPublished(), values);
-    }
-    
-    /** 
-     * Pull up a list of all values associated with the group (in the order that the 
-     * group specifies).  
-     *
-     * @return values or null on error
-     */
-    private double[] harvestGroupValues(RouterInfo peer, StatGroup group) {
-        List values = new ArrayList(8);
-        for (int i = 0; i < group.getStatCount(); i++) {
-            StatGroup.StatDescription stat = group.getStat(i);
-            double val = getDouble(peer, stat.getOptionName(), stat.getOptionField());
-            if (val == -1) 
-                return null;
-            else
-                values.add(new Double(val));
-        }
-        double rv[] = new double[values.size()];
-        for (int i = 0; i < values.size(); i++)
-            rv[i] = ((Double)values.get(i)).doubleValue();
-        return rv;
-    }
-    
-    /**
-     * Pull a value from the peer's option as a double, assuming the standard semicolon
-     * delimited formatting
-     *
-     * @param peer peer to query
-     * @param key peer option to check
-     * @param index 0-based index into the semicolon delimited values to pull out
-     * @return value, or -1 if there was an error
-     */
-    private static final double getDouble(RouterInfo peer, String key, int index) {
-        String val = peer.getOptions().getProperty(key);
-        if (val == null) return -1;
-        StringTokenizer tok = new StringTokenizer(val, ";");
-        for (int i = 0; i < index; i++) {
-            if (!tok.hasMoreTokens()) return -1;
-            tok.nextToken(); // ignore
-        }
-        if (!tok.hasMoreTokens()) return -1;
-        String cur = tok.nextToken();
-        try {
-            return getDoubleValue(cur);
-        } catch (ParseException pe) {
-            _log.warn("Unable to parse out the double from field " + index + " out of " + val + " for " + key, pe);
-            return -1;
-        } 
-    }
- 
-    /** this mimics the format used in the router's StatisticsManager */
-    private static final DecimalFormat _numFmt = new DecimalFormat("###,###,###,###,##0.00", new DecimalFormatSymbols(Locale.UK));
-
-    /**
-     * Converts a number (double) to text
-     * @param val the number to convert
-     * @return the textual representation
-     */
-    private static final double getDoubleValue(String val) throws ParseException {
-        synchronized (_numFmt) {
-            Number n = _numFmt.parse(val);
-            return n.doubleValue();
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitor.java b/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitor.java
deleted file mode 100644
index 5fdf1aab76..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitor.java
+++ /dev/null
@@ -1,251 +0,0 @@
-package net.i2p.netmonitor;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import net.i2p.util.I2PThread;
-import net.i2p.util.Log;
-
-/**
- * Main driver for the app that harvests data about the performance of the network,
- * building summaries for each peer that change over time. <p />
- *
- * Usage: <code>NetMonitor [configFilename] [--routers filename[,filename]*] [--netDbURL url] </code> <p />
- *
- *
- *
- */
-public class NetMonitor {
-    private static final Log _log = new Log(NetMonitor.class);
-    public static final String CONFIG_LOCATION_DEFAULT = "netmonitor.config";
-    public static final String HARVEST_DELAY_PROP = "harvestDelaySeconds";
-    public static final int HARVEST_DELAY_DEFAULT = 5*60;
-    public static final String EXPORT_DELAY_PROP = "exportDelaySeconds";
-    public static final int EXPORT_DELAY_DEFAULT = 120;
-    public static final String SUMMARY_DURATION_PROP = "summaryDurationHours";
-    public static final int SUMMARY_DURATION_DEFAULT = 72;
-    public static final String NETDB_DIR_PROP = "netDbDir";
-    public static final String NETDB_DIR_DEFAULT = "netDb";
-    public static final String EXPORT_DIR_PROP = "exportDir";
-    public static final String EXPORT_DIR_DEFAULT = "monitorData";
-    private String _configLocation;
-    private int _harvestDelay;
-    private int _exportDelay;
-    private String _exportDir;
-    private String _netDbDir;
-    private String _netDbURL;
-    private String _explicitRouters;
-    private int _summaryDurationHours;
-    private boolean _isRunning;
-    private Map _peerSummaries;
-    
-    public NetMonitor() {
-        this(CONFIG_LOCATION_DEFAULT, null, null);
-    }
-    public NetMonitor(String configLocation) {
-        this(configLocation, null, null);
-    }
-    public NetMonitor(String configLocation, String explicitFilenames, String url) {
-        _configLocation = configLocation;
-        _explicitRouters = explicitFilenames;
-        _netDbURL = url;
-        _peerSummaries = new HashMap(32);
-        loadConfig();
-    }
-    
-    /** read and call parse */
-    private void loadConfig() {
-        Properties props = new Properties();
-        FileInputStream fis = null;
-        try {
-            fis = new FileInputStream(_configLocation);
-            props.load(fis);
-        } catch (IOException ioe) {
-            _log.warn("Error loading the net monitor config", ioe);
-        } finally {
-            if (fis != null) try { fis.close(); } catch (IOException ioe) {}
-        }
-        parseConfig(props);
-    }
-    
-    /** interpret the config elements and shove 'em in the vars */
-    private void parseConfig(Properties props) {
-        String val = props.getProperty(HARVEST_DELAY_PROP, ""+HARVEST_DELAY_DEFAULT);
-        try {
-            _harvestDelay = Integer.parseInt(val);
-        } catch (NumberFormatException nfe) {
-            _log.warn("Error parsing the harvest delay [" + val + "]", nfe);
-            _harvestDelay = HARVEST_DELAY_DEFAULT;
-        }
-        
-        val = props.getProperty(EXPORT_DELAY_PROP, ""+EXPORT_DELAY_DEFAULT);
-        try {
-            _exportDelay = Integer.parseInt(val);
-        } catch (NumberFormatException nfe) {
-            _log.warn("Error parsing the export delay [" + val + "]", nfe);
-            _exportDelay = EXPORT_DELAY_DEFAULT;
-        }
-        
-        val = props.getProperty(SUMMARY_DURATION_PROP, ""+SUMMARY_DURATION_DEFAULT);
-        try {
-            _summaryDurationHours = Integer.parseInt(val);
-        } catch (NumberFormatException nfe) {
-            _log.warn("Error parsing the summary duration [" + val + "]", nfe);
-            _summaryDurationHours = SUMMARY_DURATION_DEFAULT;
-        }
-        
-        _netDbDir = props.getProperty(NETDB_DIR_PROP, NETDB_DIR_DEFAULT);
-        _exportDir = props.getProperty(EXPORT_DIR_PROP, EXPORT_DIR_DEFAULT);
-    }
-    
-    public void startMonitor() {
-        _isRunning = true;
-        I2PThread t = new I2PThread(new NetMonitorRunner(this));
-        t.setName("DataHarvester");
-        t.setPriority(I2PThread.MIN_PRIORITY);
-        t.setDaemon(false);
-        t.start();
-    }
-    
-    public void stopMonitor() { _isRunning = false; }
-    public boolean isRunning() { return _isRunning; }
-    /** how many seconds should we wait between harvestings? */
-    public int getHarvestDelay() { return _harvestDelay; }
-    /** how many seconds should we wait between exporting the data? */
-    public int getExportDelay() { return _exportDelay; }
-    /** where should we export the data? */
-    public String getExportDir() { return _exportDir; }
-    public void setExportDir(String dir) { _exportDir = dir; }
-    public int getSummaryDurationHours() { return _summaryDurationHours; }
-    /** where should we read the data from? */
-    public String getNetDbDir() { return _netDbDir; }
-    /** if specified, contains a set of filenames we want to harvest routerInfo data from */
-    public String getExplicitRouters() { return _explicitRouters; }
-    /** if specified, contains a URL to fetch references from */
-    public String getNetDbURL() { return _netDbURL; }
-    
-    /** 
-     * what peers are we keeping track of?  
-     *
-     * @return list of peer names (H(routerIdentity).toBase64())
-     */
-    public List getPeers() { 
-        synchronized (_peerSummaries) {
-            return new ArrayList(_peerSummaries.keySet()); 
-        } 
-    }
-    
-    /** what data do we have for the peer? */
-    public PeerSummary getSummary(String peer) {
-        synchronized (_peerSummaries) {
-            return (PeerSummary)_peerSummaries.get(peer);
-        }
-    }
-    
-    /** keep track of the given stat on the given peer */
-    public void addData(String peer, String stat, String descr, String valDescr[], long sampleDate, double val[]) {
-        synchronized (_peerSummaries) {
-            if (!_peerSummaries.containsKey(peer)) 
-                _peerSummaries.put(peer, new PeerSummary(peer));
-            PeerSummary summary = (PeerSummary)_peerSummaries.get(peer);
-            summary.addData(stat, descr, valDescr, sampleDate, val);
-        }
-    }
-
-    /** keep track of the given stat on the given peer */
-    public void addData(String peer, String stat, String descr, String valDescr[], long sampleDate, long val[]) {
-        synchronized (_peerSummaries) {
-            if (!_peerSummaries.containsKey(peer)) 
-                _peerSummaries.put(peer, new PeerSummary(peer));
-            PeerSummary summary = (PeerSummary)_peerSummaries.get(peer);
-            summary.addData(stat, descr, valDescr, sampleDate, val);
-        }
-    }
-    
-    /** keep track of the loaded summary, overwriting any existing summary for the specified peer */
-    public void addSummary(PeerSummary summary) {
-        synchronized (_peerSummaries) {
-            Object rv = _peerSummaries.put(summary.getPeer(), summary);
-            if (rv != summary) _log.error("Updating the peer summary changed objects!  old = " + rv + " new = " + summary);
-        }
-    }
-    
-    public void importData() {
-        _log.debug("Running import");
-        File dataDir = new File(getExportDir());
-        if (!dataDir.exists()) return;
-        File dataFiles[] = dataDir.listFiles(new FilenameFilter() {
-            public boolean accept(File f, String name) {
-                return name.endsWith(".txt");
-            }
-        });
-        if (dataFiles == null) return;
-        for (int i = 0; i < dataFiles.length; i++) {
-            FileInputStream fis = null;
-            boolean delete = false;
-            try { 
-                fis = new FileInputStream(dataFiles[i]);
-                PeerSummaryReader.getInstance().read(this, fis);
-            } catch (IOException ioe) {
-                _log.error("Error reading the data file " + dataFiles[i].getAbsolutePath(), ioe);
-                delete = true;
-            } finally {
-                if (fis != null) try { fis.close(); } catch (IOException ioe) {}
-                if (delete) dataFiles[i].delete();
-            }
-        }
-        _log.debug(dataFiles.length + " summaries imported");
-    }
-    
-    /** drop all the old summary data */
-    public void coalesceData() {
-        synchronized (_peerSummaries) {
-            for (Iterator iter = _peerSummaries.values().iterator(); iter.hasNext(); ) {
-                PeerSummary summary = (PeerSummary)iter.next();
-                summary.coalesceData(_summaryDurationHours * 60*60*1000);
-            }
-        }
-    }
-    
-    /**
-     * main driver for the netMonitor.  the usage is:
-     * <code>NetMonitor [configFilename] [--routers filename[,filename]*] [--netDbURL url]</code> 
-     */
-    public static final void main(String args[]) {
-        String cfgLocation = CONFIG_LOCATION_DEFAULT;
-        String explicitFilenames = null;
-        String explicitURL = null;
-        switch (args.length) {
-            case 0:
-                break;
-            case 1:
-                cfgLocation = args[0];
-                break;
-            case 2:
-                if ("--routers".equalsIgnoreCase(args[0]))
-                    explicitFilenames = args[1];
-                else
-                    explicitURL = args[1];
-                break;
-            case 3:
-                cfgLocation = args[0];
-                if ("--routers".equalsIgnoreCase(args[1]))
-                    explicitFilenames = args[2];
-                else
-                    explicitURL = args[2];
-                break;
-            default:
-                System.err.println("Usage: NetMonitor [configFilename] [--routers filename[,filename]*] [--netDbURL url]");
-                return;
-        }
-        new NetMonitor(cfgLocation, explicitFilenames, explicitURL).startMonitor();
-    }
-}
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitorRunner.java b/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitorRunner.java
deleted file mode 100644
index 0df06f76eb..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitorRunner.java
+++ /dev/null
@@ -1,242 +0,0 @@
-package net.i2p.netmonitor;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.StringTokenizer;
-
-import net.i2p.data.DataFormatException;
-import net.i2p.data.RouterInfo;
-import net.i2p.util.Clock;
-import net.i2p.util.Log;
-
-/**
- * Active process that drives the monitoring by periodically rading the 
- * netDb dir, pumping the router data throug the data harvester, updating 
- * the state, and coordinating the export.
- *
- */
-class NetMonitorRunner implements Runnable {
-    private static final Log _log = new Log(NetMonitorRunner.class);
-    private NetMonitor _monitor;
-    /** 
-     * @param monitor who do we give our data to? 
-     */
-    public NetMonitorRunner(NetMonitor monitor) {
-        _monitor = monitor;
-    }
-    
-    public void run() {
-        runImport();
-        long now = Clock.getInstance().now();
-        long nextHarvest = now;
-        long nextExport = now + _monitor.getExportDelay() * 1000;
-        while (_monitor.isRunning()) {
-            now = Clock.getInstance().now();
-            _monitor.coalesceData();
-            if (now >= nextHarvest) {
-                runHarvest();
-                nextHarvest = now + _monitor.getHarvestDelay() * 1000;
-            }
-            if (now >= nextExport) {
-                runExport();
-                nextExport = now + _monitor.getExportDelay() * 1000;
-            }
-            pauseHarvesting();
-        }
-    }
-    
-    private void runHarvest() {
-        try {
-            List routers = getRouters();
-            DataHarvester.getInstance().harvestData(_monitor, routers);
-        } catch (Throwable t) {
-            _log.error("Unhandled exception harvesting the data", t);
-        }
-    }
-    
-    /**
-     * Fetch all of the available RouterInfo structures
-     *
-     */
-    private List getRouters() {
-        if (_monitor.getNetDbURL() != null)
-            return fetchRouters(_monitor.getNetDbURL());
-        
-        File routers[] = listRouters();
-        List rv = new ArrayList(64);
-        if (routers != null) {
-            for (int i = 0; i < routers.length; i++) {
-                FileInputStream fis = null;
-                try {
-                    fis = new FileInputStream(routers[i]);
-                    RouterInfo ri = new RouterInfo();
-                    ri.readBytes(fis);
-                    rv.add(ri);
-                } catch (DataFormatException dfe) {
-                    _log.warn("Unable to parse the routerInfo from " + routers[i].getAbsolutePath(), dfe);
-                } catch (IOException ioe) {
-                    _log.warn("Unable to read the routerInfo from " + routers[i].getAbsolutePath(), ioe);
-                } finally {
-                    if (fis != null) try { fis.close(); } catch (IOException ioe) {}
-                }
-            }
-        }
-        return rv;
-    }
-    
-    
-    private List fetchRouters(String seedURL) {
-        List rv = new ArrayList();
-        try {
-            URL dir = new URL(seedURL);
-            String content = new String(readURL(dir));
-            Set urls = new HashSet();
-            int cur = 0;
-            while (true) {
-                int start = content.indexOf("href=\"routerInfo-", cur);
-                if (start < 0)
-                    break;
-
-                int end = content.indexOf(".dat\">", start);
-                String name = content.substring(start+"href=\"routerInfo-".length(), end);
-                urls.add(name);
-                cur = end + 1;
-            }
-
-            for (Iterator iter = urls.iterator(); iter.hasNext(); ) {
-                rv.add(fetchSeed((String)iter.next()));
-            }
-        } catch (Throwable t) {
-            _log.error("Error fetching routers from " + seedURL, t);
-        }
-        return rv;
-    }
-    
-    private RouterInfo fetchSeed(String peer) throws Exception {
-        URL url = new URL("http://i2p.net/i2pdb/routerInfo-" + peer + ".dat");
-        if (_log.shouldLog(Log.INFO))
-            _log.info("Fetching seed from " + url.toExternalForm());
-
-        byte data[] = readURL(url);
-        RouterInfo info = new RouterInfo();
-        try {
-            info.fromByteArray(data);
-            return info;
-        } catch (DataFormatException dfe) {
-            _log.error("Router data at " + url.toExternalForm() + " was corrupt", dfe);
-            return null;
-        }
-    }
-    
-    private byte[] readURL(URL url) throws Exception {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
-        URLConnection con = url.openConnection();
-        InputStream in = con.getInputStream();
-        byte buf[] = new byte[1024];
-        while (true) {
-            int read = in.read(buf);
-            if (read < 0)
-                break;
-            baos.write(buf, 0, read);
-        }
-        in.close();
-        return baos.toByteArray();
-    }
-    
-    /**
-     * dump the data to the filesystem
-     */
-    private void runExport() {
-        _log.info("Export");
-        List peers = _monitor.getPeers();
-        File exportDir = new File(_monitor.getExportDir());
-        if (!exportDir.exists())
-            exportDir.mkdirs();
-        for (int i = 0; i < peers.size(); i++) {
-            String peerName = (String)peers.get(i);
-            PeerSummary summary = (PeerSummary)_monitor.getSummary(peerName);
-            FileOutputStream fos = null;
-            try {
-                File summaryFile = new File(exportDir, peerName + ".txt");
-                fos = new FileOutputStream(summaryFile);
-                PeerSummaryWriter.getInstance().write(summary, fos);
-                _log.debug("Peer summary written to " + summaryFile.getAbsolutePath());
-            } catch (IOException ioe) {
-                _log.error("Error exporting the peer summary for " + peerName, ioe);
-            } catch (Throwable t) {
-                _log.error("Unhandled exception exporting the data", t);
-            } finally {
-                if (fos != null) try { fos.close(); } catch (IOException ioe) {}
-            }
-        }
-    }
-    
-    /**
-     * Read in all the peer summaries we had previously exported, overwriting any
-     * existing ones in memory
-     *
-     */
-    private void runImport() {
-        _monitor.importData();
-    }
-    
-    /** 
-     * Find all of the routers to load 
-     *
-     * @return list of File objects pointing at the routers around
-     */
-    private File[] listRouters() { 
-        if (_monitor.getExplicitRouters() != null) {
-            return listRoutersExplicit();
-        } else {
-            File dbDir = new File(_monitor.getNetDbDir());
-            File files[] = dbDir.listFiles(new FilenameFilter() {
-                public boolean accept(File f, String name) {
-                    return name.startsWith("routerInfo-");
-                }
-            });
-            return files;
-        }
-    }
-
-    /**
-     * Get a list of router files that were explicitly specified by the netMonitor
-     *
-     */
-    private File[] listRoutersExplicit() {
-        StringTokenizer tok = new StringTokenizer(_monitor.getExplicitRouters().trim(), ",");
-        List rv = new ArrayList();
-        while (tok.hasMoreTokens()) {
-            String name = tok.nextToken();
-            File cur = new File(name);
-            if (cur.exists())
-                rv.add(cur);
-        }
-        File files[] = new File[rv.size()];
-        for (int i = 0; i < rv.size(); i++)
-            files[i] = (File)rv.get(i);
-        return files;
-    }
-    
-    /**
-     * Wait the correct amount of time before harvesting again
-     *
-     */
-    private void pauseHarvesting() {
-        try {
-            Thread.sleep(_monitor.getHarvestDelay());
-        } catch (InterruptedException ie) {}
-    }
-}
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerStat.java b/apps/netmonitor/java/src/net/i2p/netmonitor/PeerStat.java
deleted file mode 100644
index d19e31dd27..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerStat.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package net.i2p.netmonitor;
-
-/**
- * Actual data point (though its not fully normalized, but KISS)
- *
- */
-public class PeerStat {
-    private String _statName;
-    private String _description;
-    private String _valueDescriptions[];
-    private long _sampleDate;
-    private long _lvalues[];
-    private double _dvalues[];
-    
-    public PeerStat(String name, String description, String valueDescriptions[], long sampleDate, double values[]) {
-        this(name, description, valueDescriptions, sampleDate, null, values);
-    }
-    public PeerStat(String name, String description, String valueDescriptions[], long sampleDate, long values[]) {
-        this(name, description, valueDescriptions, sampleDate, values, null);
-    }
-    private PeerStat(String name, String description, String valueDescriptions[], long sampleDate, long lvalues[], double dvalues[]) {
-        _statName = name;
-        _description = description;
-        _valueDescriptions = valueDescriptions;
-        _sampleDate = sampleDate;
-        _lvalues = lvalues;
-        _dvalues = dvalues;
-    }
-  
-    /** unique name of the stat */
-    public String getStatName() { return _statName; }
-    /** one line summary of the stat */
-    public String getDescription() { return _description; }
-    /** description of each value */
-    public String getValueDescription(int index) { return _valueDescriptions[index]; }
-    /** description of all values */
-    public String[] getValueDescriptions() { return _valueDescriptions; }
-    /** when did the router publish the info being sampled? */
-    public long getSampleDate() { return _sampleDate; }
-    /** if the values are integers, this contains their values */
-    public long[] getLongValues() { return _lvalues; }
-    /** if the values are floating point numbers, this contains their values */
-    public double[] getDoubleValues() { return _dvalues; }
-    /** are the values floating poing numbers? */
-    public boolean getIsDouble() { return _dvalues != null; }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummary.java b/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummary.java
deleted file mode 100644
index f2e74b9e01..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummary.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package net.i2p.netmonitor;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import net.i2p.util.Clock;
-import net.i2p.util.Log;
-
-/** 
- * coordinate the data points summarizing the performance of a particular peer 
- * within the network
- */
-public class PeerSummary {
-    private static final Log _log = new Log(PeerSummary.class);
-    private String _peer;
-    /** statName to a List of PeerStat elements (sorted by sample date, earliest first) */
-    private Map _stats;
-    /** lock on this when accessing stat data */
-    private Object _coalesceLock = new Object();
-    
-    public PeerSummary(String peer) {
-        _peer = peer;
-        _stats = new HashMap(16);   
-    }
-    
-    /** 
-     * Track a data point
-     *
-     * @param stat what data are we tracking?
-     * @param description what does this data mean?  (and what are the values?)
-     * @param when what data set is this sample based off?
-     * @param val actual data harvested
-     */
-    public void addData(String stat, String description, String valueDescriptions[], long when, double val[]) {
-        synchronized (_coalesceLock) {
-            TreeMap stats = locked_getData(stat);
-            stats.put(new Long(when), new PeerStat(stat, description, valueDescriptions, when, val));
-        }
-    }
-    
-    /** 
-     * Track a data point
-     *
-     * @param stat what data are we tracking?
-     * @param description what does this data mean?  (and what are the values?)
-     * @param when what data set is this sample based off?
-     * @param val actual data harvested
-     */
-    public void addData(String stat, String description, String valueDescriptions[], long when, long val[]) {
-        synchronized (_coalesceLock) {
-            TreeMap stats = locked_getData(stat);
-            stats.put(new Long(when), new PeerStat(stat, description, valueDescriptions, when, val));
-        }
-    }
-    
-    /** get the peer's name (H(routerIdentity).toBase64()) */
-    public String getPeer() { return _peer; }
-    
-    /** 
-     * fetch the ordered list of PeerStat objects for the given stat (or null if 
-     * isn't being tracked or has no data) 
-     *
-     */
-    public List getData(String statName) {
-        synchronized (_coalesceLock) {
-            return new ArrayList(((TreeMap)_stats.get(statName)).values());
-        }
-    }
-    
-    /**
-     * Get the names of all of the stats that are being tracked 
-     *
-     */
-    public Set getStatNames() { 
-        synchronized (_coalesceLock) {
-            return new HashSet(_stats.keySet());
-        }
-    }
-    
-    /** drop old data points */
-    public void coalesceData(long summaryDurationMs) {
-        long earliest = Clock.getInstance().now() - summaryDurationMs;
-        synchronized (_coalesceLock) {
-            locked_coalesce(earliest);
-        }
-    }
-    
-    /** go through all the stats and remove ones from before the given date */
-    private void locked_coalesce(long earliestSampleDate) {
-        if (true) return;
-        for (Iterator iter = _stats.keySet().iterator(); iter.hasNext(); ) {
-            String statName = (String)iter.next();
-            TreeMap stats = (TreeMap)_stats.get(statName);
-            while (stats.size() > 0) {
-                Long when = (Long)stats.keySet().iterator().next();
-                if (when.longValue() < earliestSampleDate) {
-                    stats.remove(when);
-                } else {
-                    break;
-                }
-            }
-        }
-    }
-    
-    /**
-     * @return PeerStat elements, ordered by sample date (earliest first)
-     */
-    private TreeMap locked_getData(String statName) {
-        if (!_stats.containsKey(statName))
-            _stats.put(statName, new TreeMap());
-        return (TreeMap)_stats.get(statName);
-    }
-}
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryReader.java b/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryReader.java
deleted file mode 100644
index 2b67dc87a4..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryReader.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package net.i2p.netmonitor;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.StringTokenizer;
-
-import net.i2p.util.Log;
-
-/**
- * Load up the peer summary 
- *
- */
-class PeerSummaryReader {
-    private static final Log _log = new Log(PeerSummaryReader.class);
-    private static final PeerSummaryReader _instance = new PeerSummaryReader();
-    public static final PeerSummaryReader getInstance() { return _instance; }
-    private PeerSummaryReader() {}
-    
-    /**  */
-    public void read(NetMonitor monitor, InputStream in) throws IOException {
-        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
-        String line = null;
-        PeerSummary summary = null;
-        String curDescription = null;
-        List curArgs = null;
-        try {
-            while ((line = reader.readLine()) != null) {
-                if (line.startsWith("peer\t")) {
-                    String name = line.substring("peer\t".length()).trim();
-                    summary = monitor.getSummary(name);
-                    if (summary == null)
-                        summary = new PeerSummary(name);
-                } else if (line.startsWith("## ")) {
-                    curDescription = line.substring("## ".length()).trim();
-                    curArgs = new ArrayList(4);
-                } else if (line.startsWith("# param ")) {
-                    int start = line.indexOf(':');
-                    String arg = line.substring(start+1).trim();
-                    curArgs.add(arg);
-                } else {
-                    StringTokenizer tok = new StringTokenizer(line);
-                    String name = tok.nextToken();
-                    try {
-                        long when = getTime(tok.nextToken());
-                        boolean isDouble = false;
-                        List argVals = new ArrayList(curArgs.size());
-                        while (tok.hasMoreTokens()) {
-                            String val = (String)tok.nextToken();
-                            if (val.indexOf('.') >= 0) {
-                                argVals.add(new Double(val));
-                                isDouble = true;
-                            } else {
-                                argVals.add(new Long(val));
-                            }
-                        }
-                        String valDescriptions[] = new String[curArgs.size()];
-                        for (int i = 0; i < curArgs.size(); i++)
-                            valDescriptions[i] = (String)curArgs.get(i);
-                        if (isDouble) {
-                            double values[] = new double[argVals.size()];
-                            for (int i = 0; i < argVals.size(); i++) 
-                                values[i] = ((Double)argVals.get(i)).doubleValue();
-                            summary.addData(name, curDescription, valDescriptions, when, values);
-                        } else {
-                            long values[] = new long[argVals.size()];
-                            for (int i = 0; i < argVals.size(); i++) 
-                                values[i] = ((Long)argVals.get(i)).longValue();
-                            summary.addData(name, curDescription, valDescriptions, when, values);
-                        }
-                    } catch (ParseException pe) {
-                        _log.error("Error parsing the data line [" + line + "]", pe);
-                    } catch (NumberFormatException nfe) {
-                        _log.error("Error parsing the data line [" + line + "]", nfe);
-                    }
-                }
-            }
-        } catch (Exception e) {
-            _log.error("Error handling the data", e);
-            throw new IOException("Error parsing the data");
-        } 
-        if (summary == null)
-            return;
-        summary.coalesceData(monitor.getSummaryDurationHours() * 60*60*1000);
-        monitor.addSummary(summary);
-    }
-    
-    private static final SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd.HH:mm:ss.SSS", Locale.UK);
-
-    /**
-     * Converts a time (long) to text
-     * @param when the time to convert
-     * @return the textual representation
-     */
-    public long getTime(String when) throws ParseException {
-        synchronized (_fmt) {
-            return _fmt.parse(when).getTime();
-        }
-    }
-}
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryWriter.java b/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryWriter.java
deleted file mode 100644
index ba848ed948..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryWriter.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package net.i2p.netmonitor;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.TreeSet;
-
-import net.i2p.util.Log;
-
-/**
- * Dump various peer summaries to disk (so external apps (or good ol' vi) can
- * peek into what we're harvesting
- *
- */
-class PeerSummaryWriter {
-    private static final Log _log = new Log(PeerSummaryWriter.class);
-    private static final PeerSummaryWriter _instance = new PeerSummaryWriter();
-    public static final PeerSummaryWriter getInstance() { return _instance; }
-    private PeerSummaryWriter() {}
-    
-    /** write out the peer summary to the stream specified */
-    public void write(PeerSummary summary, OutputStream out) throws IOException {
-        StringBuffer buf = new StringBuffer(4*1024);
-        buf.append("peer\t").append(summary.getPeer()).append('\n');
-        TreeSet names = new TreeSet(summary.getStatNames());
-        for (Iterator iter = names.iterator(); iter.hasNext(); ) {
-            String statName = (String)iter.next();
-            List stats = summary.getData(statName);
-            for (int i = 0; i < stats.size(); i++) {
-                PeerStat stat = (PeerStat)stats.get(i);
-                if (i == 0) {
-                    buf.append("## ").append(stat.getDescription()).append('\n');
-                    String descr[] = stat.getValueDescriptions();
-                    if (descr != null) {
-                        for (int j = 0; j < descr.length; j++)
-                            buf.append("# param ").append(j).append(": ").append(descr[j]).append('\n');
-                    }
-                }
-                buf.append(statName).append('\t');
-                buf.append(getTime(stat.getSampleDate())).append('\t');
-                
-                if (stat.getIsDouble()) {
-                    double vals[] = stat.getDoubleValues();
-                    if (vals != null) {
-                        for (int j = 0; j < vals.length; j++)
-                            buf.append(vals[j]).append('\t');
-                    }
-                } else {
-                    long vals[] = stat.getLongValues();
-                    if (vals != null) {
-                        for (int j = 0; j < vals.length; j++)
-                            buf.append(vals[j]).append('\t');
-                    }
-                }
-                buf.append('\n');
-            }
-        }
-        String data = buf.toString();
-        if (_log.shouldLog(Log.DEBUG))
-            _log.debug("Stat: \n" + data);
-        out.write(data.getBytes());
-    }
-    
-    private static final SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd.HH:mm:ss.SSS", Locale.UK);
-
-    /**
-     * Converts a time (long) to text
-     * @param when the time to convert
-     * @return the textual representation
-     */
-    public String getTime(long when) {
-        synchronized (_fmt) {
-            return _fmt.format(new Date(when));
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroup.java b/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroup.java
deleted file mode 100644
index dcf9e58174..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroup.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package net.i2p.netmonitor;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Stupid little structure to configure the DataHarvester's gathering of statistics.
- *
- */
-public class StatGroup {
-    private String _groupDescription;
-    private List _stats;
-    
-    public StatGroup(String description) {
-        _groupDescription = description;
-        _stats = new ArrayList();
-    }
-    
-    public String getDescription() { return _groupDescription; }
-    public int getStatCount() { return _stats.size(); }
-    public StatDescription getStat(int index) { return (StatDescription)_stats.get(index); }
-    public void addStat(String description, String optionName, int optionField) {
-        StatDescription descr = new StatDescription(description, optionName, optionField);
-        _stats.add(descr);
-    }
-    
-    public class StatDescription {
-        private String _statDescription;
-        private String _optionName;
-        private int _optionField;
-        
-        public StatDescription(String descr, String optionName, int optionField) {
-            _statDescription = descr;
-            _optionName = optionName;
-            _optionField = optionField;
-        }
-        
-        /** brief description of this data point */
-        public String getStatDescription() { return _statDescription; }
-        /** 
-         * if this is harvested from the RouterInfo's options, this specifies
-         * which key in that map to pull from (or null if it isn't harvested
-         * from there)
-         */
-        public String getOptionName() { return _optionName; }
-        /** 
-         * if this is harvested from the RouterInfo's options, this specifies
-         * which field in value of that map to pull from (or -1 if it isn't harvested
-         * from there)
-         */
-        public int getOptionField() { return _optionField; }
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroupLoader.java b/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroupLoader.java
deleted file mode 100644
index 1b777f2097..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroupLoader.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package net.i2p.netmonitor;
-
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-
-import net.i2p.util.Log;
-
-/**
- * Load up the StatGroups from the location specified to configure the data harvester.
- * The stat groups are formatted in a simple properties file style, e.g.: <pre>
- * # dropped jobs
- * statGroup.0.name=droppedJobs
- * statGroup.0.detail.0.name=num dropped jobs (minute)
- * statGroup.0.detail.0.option=stat_jobQueue.droppedJobs.60m
- * statGroup.0.detail.0.field=3
- * statGroup.0.detail.1.name=num dropped jobs (hour)
- * statGroup.0.detail.1.option=stat_jobQueue.droppedJobs.60h
- * statGroup.0.detail.1.field=3
- * # 
- * statGroup.1.name=encryptTime
- * statGroup.1.detail.0.name=encryption time avg ms (minute)
- * statGroup.1.detail.0.option=stat_crypto.elGamal.encrypt.60s
- * statGroup.1.detail.0.field=0
- * statGroup.1.detail.1.name=num encryptions (minute)
- * statGroup.1.detail.1.option=stat_crypto.elGamal.encrypt.60s
- * statGroup.1.detail.1.field=7
- * statGroup.1.detail.2.name=encryption time avg ms (hour)
- * statGroup.1.detail.2.option=stat_crypto.elGamal.encrypt.60s
- * statGroup.1.detail.2.field=0
- * statGroup.1.detail.3.name=num encryptions (hour)
- * statGroup.1.detail.3.option=stat_crypto.elGamal.encrypt.60s
- * statGroup.1.detail.3.field=7
- * </pre>
- */
-class StatGroupLoader {
-    private static final Log _log = new Log(StatGroupLoader.class);
-    /**
-     * Load a list of stat  groups from the file specified
-     *
-     * @return list of StatGroup objects
-     */
-    public static List loadStatGroups(String filename) {
-        _log.debug("Loading stat groups from " + filename);
-        FileInputStream fis = null;
-        File f = new File(filename);
-        try {
-            fis = new FileInputStream(f);
-            Properties p = new Properties();
-            p.load(fis);
-            _log.debug("Config loaded from " + filename);
-            return loadStatGroups(p);
-        } catch (IOException ioe) {
-            _log.error("Error loading the stat groups from " + f.getAbsolutePath(), ioe);
-            return new ArrayList();
-        }
-    }
-    
-    private static List loadStatGroups(Properties props) {
-        List rv = new ArrayList(8);
-        int groupNum = 0;
-        while (true) {
-            String description = props.getProperty("statGroup." + groupNum + ".name");
-            if (description == null) break;
-            int detailNum = 0;
-            StatGroup group = new StatGroup(description);
-            while (true) {
-                String detailPrefix = "statGroup." + groupNum + ".detail." + detailNum + '.';
-                String name = props.getProperty(detailPrefix + "name");
-                if (name == null) break;
-                String option = props.getProperty(detailPrefix + "option");
-                if (option == null) break;
-                String field = props.getProperty(detailPrefix + "field");
-                if (field == null) break;
-                try {
-                    int fieldNum = Integer.parseInt(field);
-                    group.addStat(name, option, fieldNum);
-                } catch (NumberFormatException nfe) {
-                    _log.warn("Unable to parse the field number from [" + field + "]", nfe);
-                    break;
-                }
-                detailNum++;
-            }
-            rv.add(group);
-            groupNum++;
-        }
-        return rv;
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartAdapter.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartAdapter.java
deleted file mode 100644
index 95a26e4ced..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartAdapter.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package net.i2p.netmonitor.gui;
-
-import java.awt.Color;
-import java.awt.Font;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import org.jfree.chart.ChartPanel;
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.axis.DateAxis;
-import org.jfree.chart.axis.NumberAxis;
-import org.jfree.chart.plot.Plot;
-import org.jfree.chart.plot.XYPlot;
-import org.jfree.chart.renderer.XYItemRenderer;
-import org.jfree.chart.renderer.XYLineAndShapeRenderer;
-import org.jfree.data.XYSeries;
-import org.jfree.data.XYSeriesCollection;
-
-import net.i2p.netmonitor.PeerStat;
-import net.i2p.util.Log;
-
-class JFreeChartAdapter {
-    private final static Log _log = new Log(JFreeChartAdapter.class);
-    private final static Color WHITE = new Color(255, 255, 255);
-    
-    ChartPanel createPanel(NetViewer state) {
-        ChartPanel panel = new ChartPanel(createChart(state));
-        panel.setDisplayToolTips(true);
-        panel.setEnforceFileExtensions(true);
-        panel.setHorizontalZoom(true);
-        panel.setVerticalZoom(true);
-        panel.setMouseZoomable(true, true);
-        panel.getChart().setBackgroundPaint(WHITE);
-        return panel;
-    }
-    
-    JFreeChart createChart(NetViewer state) {
-        Plot plot = createPlot(state);
-        JFreeChart chart = new JFreeChart("I2P network performance", Font.getFont("arial"), plot, true);
-        return chart;
-    }
-    
-    void updateChart(ChartPanel panel, NetViewer state) {
-        XYPlot plot = (XYPlot)panel.getChart().getPlot();
-        plot.setDataset(getCollection(state));
-    }
-    
-    Plot createPlot(NetViewer state) {
-        XYItemRenderer renderer = new XYLineAndShapeRenderer(); // new XYDotRenderer(); // 
-        XYPlot plot = new XYPlot(getCollection(state), new DateAxis(), new NumberAxis("val"), renderer);
-        return plot;
-    }
-    
-    XYSeriesCollection getCollection(NetViewer state) {
-        XYSeriesCollection col = new XYSeriesCollection();
-        if (state != null) {
-            List names = state.getConfigNames();
-            for (int i = 0; i < names.size(); i++) {
-                addPeer(col, state.getConfig((String)names.get(i)));
-            }
-        } else {
-            XYSeries series = new XYSeries("latency", false, false);
-            series.add(System.currentTimeMillis(), 0);
-            col.addSeries(series);
-        }
-        return col;
-    }
-    
-    void addPeer(XYSeriesCollection col, PeerPlotConfig config) {
-        Set statNames = config.getSummary().getStatNames();
-        for (Iterator iter = statNames.iterator(); iter.hasNext(); ) {
-            String statName = (String)iter.next();
-            List statData = config.getSummary().getData(statName);
-            if (statData.size() > 0) {
-                PeerStat data = (PeerStat)statData.get(0);
-                String args[] = data.getValueDescriptions();
-                if (args != null) {
-                    for (int i = 0; i < args.length; i++) {
-                        if (config.getSeriesConfig().getShouldPlotValue(statName, args[i], false))
-                            addLine(col, config.getPeerName(), statName, args[i], statData);
-                    }
-                }
-            }
-        }
-    }
-    
-    /**
-     */
-    void addLine(XYSeriesCollection col, String peer, String statName, String argName, List dataPoints) {
-        XYSeries series = new XYSeries(peer.substring(0, 4) + ": " + argName, false, false);
-        for (int i = 0; i < dataPoints.size(); i++) {
-            PeerStat data = (PeerStat)dataPoints.get(i);
-            String argNames[] = data.getValueDescriptions();
-            int argIndex = -1;
-            for (int j = 0; j < argNames.length; j++) {
-                if (argNames[j].equals(argName)) {
-                    argIndex = j;
-                    break;
-                }
-            }
-            if (data.getIsDouble())
-                series.add(data.getSampleDate(), data.getDoubleValues()[argIndex]);
-            else
-                series.add(data.getSampleDate(), data.getLongValues()[argIndex]);
-        }
-        col.addSeries(series);
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartHeartbeatPlotPane.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartHeartbeatPlotPane.java
deleted file mode 100644
index 9d4a4e7f18..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartHeartbeatPlotPane.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package net.i2p.netmonitor.gui;
-
-import java.awt.BorderLayout;
-import java.awt.Dimension;
-
-import javax.swing.JLabel;
-import javax.swing.JScrollPane;
-
-import org.jfree.chart.ChartPanel;
-
-import net.i2p.util.Log;
-
-/**
- * Render the graph and legend
- *
- */
-class JFreeChartHeartbeatPlotPane extends NetViewerPlotPane {
-    private final static Log _log = new Log(JFreeChartHeartbeatPlotPane.class);
-    private ChartPanel _panel;
-    private JFreeChartAdapter _adapter;
-        
-    public JFreeChartHeartbeatPlotPane(NetViewerGUI gui) {
-        super(gui);
-    }
-    
-    public void stateUpdated() {
-        if (_panel == null) {
-            remove(0); // remove the dummy
-            
-            _adapter = new JFreeChartAdapter();
-            _panel = _adapter.createPanel(_gui.getViewer());
-            _panel.setBackground(_gui.getBackground());
-            JScrollPane pane = new JScrollPane(_panel);
-            pane.setBackground(_gui.getBackground());
-            add(pane, BorderLayout.CENTER);
-        } else {
-            _adapter.updateChart(_panel, _gui.getViewer());
-            //_gui.pack();
-        }
-    }
-    
-    protected void initializeComponents() {
-        // noop
-        setLayout(new BorderLayout());
-        add(new JLabel(), BorderLayout.CENTER);
-        //dummy.setBackground(_gui.getBackground());
-        //dummy.setPreferredSize(new Dimension(800,600));
-        //add(dummy);
-        setPreferredSize(new Dimension(800,600));
-        //add(_panel);
-
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewer.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewer.java
deleted file mode 100644
index 174860b3f2..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewer.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package net.i2p.netmonitor.gui;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import net.i2p.netmonitor.NetMonitor;
-import net.i2p.util.I2PThread;
-import net.i2p.util.Log;
-
-/**
- * Coordinate the visualization of the network monitor. <p />
- *
- * <b>Usage: <code>NetViewer [exportDir]</code></b> <br />
- * (exportDir is where the NetMonitor exports its state, "monitorData" by default)
- */
-public class NetViewer {
-    private static final Log _log = new Log(NetViewer.class);
-    private NetMonitor _monitor;
-    private NetViewerGUI _gui;
-    private Map _plotConfigs;
-    private boolean _isClosed;
-    
-    public NetViewer() {
-        this(NetMonitor.EXPORT_DIR_DEFAULT);
-    }
-    public NetViewer(String dataDir) {
-        _monitor = new NetMonitor();
-        _monitor.setExportDir(dataDir);
-        _isClosed = false;
-        _gui = new NetViewerGUI(this);
-        _plotConfigs = new HashMap();
-    }
- 
-    public void runViewer() {
-        I2PThread t = new I2PThread(new NetViewerRunner(this));
-        t.setName("NetViewer");
-        t.setDaemon(false);
-        t.start();
-    }
-    
-    void refreshGUI() {
-        _gui.stateUpdated();
-    }
-    
-    void reloadData() { 
-        _log.debug("Reloading data");
-        _monitor.importData(); 
-        refreshGUI();
-    }
-    
-    public void addConfig(String peerName, PeerPlotConfig config) {
-        synchronized (_plotConfigs) {
-            _plotConfigs.put(peerName, config);
-        }
-    }
-    
-    public PeerPlotConfig getConfig(String peerName) {
-        synchronized (_plotConfigs) {
-            return (PeerPlotConfig)_plotConfigs.get(peerName);
-        }
-    }
-    
-    public List getConfigNames() {
-        synchronized (_plotConfigs) {
-            return new ArrayList(_plotConfigs.keySet());
-        }
-    }
-    
-    public NetMonitor getMonitor() { return _monitor; }
-    
-    long getDataLoadDelay() { return _monitor.getExportDelay(); }
-    
-    /** has the viewer been closed? */
-    public boolean getIsClosed() { return _isClosed; }
-    public void setIsClosed(boolean closed) { _isClosed = closed; }
-    
-    public static final void main(String args[]) {
-        if (args.length == 1)
-            new NetViewer(args[0]).runViewer();
-        else
-            new NetViewer().runViewer();
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerCommandBar.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerCommandBar.java
deleted file mode 100644
index b1b0b923b4..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerCommandBar.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package net.i2p.netmonitor.gui;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JFileChooser;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-
-class NetViewerCommandBar extends JPanel {
-    private NetViewerGUI _gui;
-    private JComboBox _refreshRate;
-    private JTextField _location;
-    
-    /**
-     * Constructs a command bar onto the gui
-     * @param gui the gui the command bar is associated with
-     */
-    public NetViewerCommandBar(NetViewerGUI gui) {
-        _gui = gui;
-        initializeComponents();
-    }
-    
-    private void refreshChanged(ItemEvent evt) {}
-    private void loadCalled() {
-        //_gui.getMonitor().load(_location.getText());
-    }
-    
-    private void browseCalled() {
-        JFileChooser chooser = new JFileChooser(_location.getText());
-        chooser.setBackground(_gui.getBackground());
-        chooser.setMultiSelectionEnabled(false);
-        int rv = chooser.showDialog(this, "Load");
-        //if (rv == JFileChooser.APPROVE_OPTION) 
-        //    _gui.getMonitor().load(chooser.getSelectedFile().getAbsolutePath());
-    }
-    
-    private void initializeComponents() {
-        _refreshRate = new JComboBox(new DefaultComboBoxModel(new Object[] {"10 second refresh", "30 second refresh", "1 minute refresh", "5 minute refresh"}));
-        _refreshRate.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent evt) { refreshChanged(evt); } });
-        _refreshRate.setEnabled(false);
-        _refreshRate.setBackground(_gui.getBackground());
-        //add(_refreshRate);
-        JLabel loadLabel = new JLabel("Load from: ");
-        loadLabel.setBackground(_gui.getBackground());
-        add(loadLabel);
-        _location = new JTextField(20);
-        _location.setToolTipText("Either specify a local filename or a fully qualified URL");
-        _location.setBackground(_gui.getBackground());
-        _location.setEnabled(false);        
-        add(_location);
-        JButton browse = new JButton("Browse...");
-        browse.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { browseCalled(); } });
-        browse.setBackground(_gui.getBackground());
-        browse.setEnabled(false);
-        add(browse);
-        JButton load = new JButton("Load");
-        load.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadCalled(); } });
-        load.setBackground(_gui.getBackground());
-        load.setEnabled(false);
-        add(load);
-        setBackground(_gui.getBackground());
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerControlPane.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerControlPane.java
deleted file mode 100644
index 22aca39d5b..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerControlPane.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package net.i2p.netmonitor.gui;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTabbedPane;
-
-import net.i2p.util.Log;
-
-/**
- * Render the control widgets (refresh/load/snapshot and the 
- * tabbed panel with the plot config data)
- *
- */
-class NetViewerControlPane extends JPanel {
-    private final static Log _log = new Log(NetViewerControlPane.class);
-    private NetViewerGUI _gui;
-    private JTabbedPane _configPane;
-    private final static Color WHITE = new Color(255, 255, 255);
-    private final static Color LIGHT_BLUE = new Color(180, 180, 255);
-    private final static Color BLACK = new Color(0, 0, 0);
-    private Color _background = WHITE;
-    private Color _foreground = BLACK;
-        
-    /**
-     * Constructs a control panel onto the gui
-     * @param gui the gui the panel is associated with
-     */
-    public NetViewerControlPane(NetViewerGUI gui) {
-        _gui = gui;
-        initializeComponents();
-    }
-    
-    /** the settings have changed - revise */
-    void refreshView() {
-        _gui.refreshView();
-    }
-    
-    /**
-     * Callback: when tests have changed
-     */
-    public synchronized void stateUpdated() {
-        List knownNames = new ArrayList(8);
-        List peers = _gui.getViewer().getMonitor().getPeers();
-        _log.debug("GUI updated with peers: " + peers);
-        for (int i = 0; i < peers.size(); i++) {
-            String name = (String)peers.get(i);
-            String shortName = name.substring(0,4);
-            knownNames.add(shortName);
-            if (_configPane.indexOfTab(shortName) >= 0) {
-                JScrollPane pane = (JScrollPane)_configPane.getComponentAt(_configPane.indexOfTab(shortName));
-                PeerPlotConfigPane cfgPane = (PeerPlotConfigPane)pane.getViewport().getView();
-                cfgPane.stateUpdated();
-                _log.debug("We already know about [" + name + "]");
-            } else {
-                _log.info("The peer [" + name + "] is new to us");
-                PeerPlotConfig cfg = new PeerPlotConfig(_gui.getViewer().getMonitor().getSummary(name));
-                _gui.getViewer().addConfig(name, cfg);
-                PeerPlotConfigPane pane = new PeerPlotConfigPane(cfg, this);
-                JScrollPane p = new JScrollPane(pane);
-                p.setBackground(_background);
-                _configPane.addTab(shortName, null, p, "Peer " + name);
-                _configPane.setBackgroundAt(_configPane.getTabCount()-1, _background);
-                _configPane.setForegroundAt(_configPane.getTabCount()-1, _foreground);
-            }
-        }
-        List toRemove = new ArrayList(4);
-        for (int i = 0; i < _configPane.getTabCount(); i++) {
-            if (knownNames.contains(_configPane.getTitleAt(i))) {
-                // noop
-            } else {
-                toRemove.add(_configPane.getTitleAt(i));
-            }
-        }
-        for (int i = 0; i < toRemove.size(); i++) {
-            String title = (String)toRemove.get(i);
-            _log.info("Removing peer [" + title + "]");
-            _configPane.removeTabAt(_configPane.indexOfTab(title));
-        }
-    }
-    
-    private void initializeComponents() {
-        if (_gui != null)
-            setBackground(_gui.getBackground());
-        else
-            setBackground(_background);
-        setLayout(new BorderLayout());
-        NetViewerCommandBar bar = new NetViewerCommandBar(_gui);
-        bar.setBackground(getBackground());
-        add(bar, BorderLayout.NORTH);
-        _configPane = new JTabbedPane(JTabbedPane.LEFT);
-        _configPane.setBackground(_background);
-        JScrollPane pane = new JScrollPane(_configPane);
-        pane.setBackground(_background);
-        add(pane, BorderLayout.CENTER);
-        //setPreferredSize(new Dimension(800, 400));
-        //setMinimumSize(new Dimension(800, 400));
-        //setMaximumSize(new Dimension(800, 400));
-    }
-    
-    NetViewer getViewer() { return _gui.getViewer(); }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerGUI.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerGUI.java
deleted file mode 100644
index c50d45144d..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerGUI.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package net.i2p.netmonitor.gui;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.JFrame;
-import javax.swing.JMenu;
-import javax.swing.JMenuBar;
-import javax.swing.JMenuItem;
-import javax.swing.JScrollPane;
-import javax.swing.JSplitPane;
-
-class NetViewerGUI extends JFrame {
-    private NetViewer _viewer;
-    private NetViewerPlotPane _plotPane;
-    private NetViewerControlPane _controlPane;
-    private final static Color WHITE = new Color(255, 255, 255);
-    private Color _background = WHITE;
-    
-    /**
-     * Creates the GUI for all youz who be too shoopid for text based shitz
-     * @param monitor the monitor the gui operates over
-     */
-    public NetViewerGUI(NetViewer viewer) {
-        super("Network Viewer");
-        _viewer = viewer;
-        initializeComponents();
-        pack();
-        //setResizable(false);
-        setVisible(true);
-    }
-    
-    NetViewer getViewer() { return _viewer; }
-    
-    /** build up all our widgets */
-    private void initializeComponents() {
-        getContentPane().setLayout(new BorderLayout());
-        
-        setBackground(_background);
-        
-        _plotPane = new JFreeChartHeartbeatPlotPane(this); // // new NetViewerPlotPane(this); // 
-        _plotPane.setBackground(_background);
-        JScrollPane pane = new JScrollPane(_plotPane);
-        pane.setBackground(_background);
-        //getContentPane().add(pane, BorderLayout.CENTER);
-        
-        _controlPane = new NetViewerControlPane(this);
-        _controlPane.setBackground(_background);
-        //getContentPane().add(_controlPane, BorderLayout.SOUTH);
-        
-        JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, _plotPane, _controlPane);
-        //split.setDividerLocation(0.3d);
-        getContentPane().add(split, BorderLayout.CENTER);
-        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-        initializeMenus();
-    }
-    
-    /**
-     * Callback:  when the state of the world changes . . .
-     */
-    public void stateUpdated() {
-        _controlPane.stateUpdated();
-        _plotPane.stateUpdated();
-        //pack();
-    }
-    
-    public void refreshView() {
-        _plotPane.stateUpdated();
-    }
-    
-    private void exitCalled() {
-        _viewer.setIsClosed(true);
-        setVisible(false);
-        System.exit(0);
-    }
-    private void loadConfigCalled() {}
-    private void saveConfigCalled() {}
-    private void loadSnapshotCalled() {}
-    private void saveSnapshotCalled() {}
-    
-    private void initializeMenus() {
-        JMenuBar bar = new JMenuBar();
-        JMenu fileMenu = new JMenu("File");
-        JMenuItem loadConfig = new JMenuItem("Load config");
-        loadConfig.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadConfigCalled(); } });
-        JMenuItem saveConfig = new JMenuItem("Save config");
-        saveConfig.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { saveConfigCalled(); } });
-        JMenuItem saveSnapshot = new JMenuItem("Save snapshot");
-        saveSnapshot.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { saveSnapshotCalled(); } });
-        JMenuItem loadSnapshot = new JMenuItem("Load snapshot");
-        loadSnapshot.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadSnapshotCalled(); } });
-        JMenuItem exit = new JMenuItem("Exit");
-        exit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { exitCalled(); } });
-        
-        fileMenu.add(loadConfig);
-        fileMenu.add(saveConfig);
-        fileMenu.add(loadSnapshot);
-        fileMenu.add(saveSnapshot);
-        fileMenu.add(exit);
-        bar.add(fileMenu);
-        setJMenuBar(bar);
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerPlotPane.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerPlotPane.java
deleted file mode 100644
index 321698d0c2..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerPlotPane.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package net.i2p.netmonitor.gui;
-
-import javax.swing.JPanel;
-import javax.swing.JTextArea;
-
-import net.i2p.util.Log;
-
-/**
- * Render the graph and legend
- */
-class NetViewerPlotPane extends JPanel {
-    private final static Log _log = new Log(NetViewerPlotPane.class);
-    protected NetViewerGUI _gui;
-    private JTextArea _text;
-    
-    /**
-     * Constructs the plot pane
-     * @param gui the gui the pane is attached to
-     */
-    public NetViewerPlotPane(NetViewerGUI gui) {
-        _gui = gui;
-        initializeComponents();
-    }
-    
-    /**
-     * Callback: when things change . . . 
-     */
-    public void stateUpdated() {
-        StringBuffer buf = new StringBuffer(32*1024);
-        buf.append("moo");
-        _text.setText(buf.toString());
-    }
-    
-    protected void initializeComponents() {
-        setBackground(_gui.getBackground());
-        //Dimension size = new Dimension(800, 600);
-        _text = new JTextArea("",30,80); // 16, 60);
-        _text.setAutoscrolls(true);
-        _text.setEditable(false);
-        // _text.setLineWrap(true);
-        // add(new JScrollPane(_text));
-        add(_text);
-        // add(new JScrollPane(_text, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS));
-        // setPreferredSize(size);
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerRunner.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerRunner.java
deleted file mode 100644
index 2917e14eeb..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerRunner.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package net.i2p.netmonitor.gui;
-
-class NetViewerRunner implements Runnable {
-    private NetViewer _viewer;
-    
-    public NetViewerRunner(NetViewer viewer) {
-        _viewer = viewer;
-    }
-    
-    public void run() {
-        while (!_viewer.getIsClosed()) {
-            _viewer.reloadData();
-            try { Thread.sleep(_viewer.getDataLoadDelay()*1000); } catch (InterruptedException ie) {}
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfig.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfig.java
deleted file mode 100644
index fafbd22b9d..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfig.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package net.i2p.netmonitor.gui;
-
-import java.awt.Color;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import net.i2p.netmonitor.PeerSummary;
-import net.i2p.util.Log;
-
-/**
- * Configure how we want to render a particular peerSummary in the GUI
- */
-class PeerPlotConfig {
-    private final static Log _log = new Log(PeerPlotConfig.class);
-    /** where can we find the current state/data (either as a filename or a URL)? */
-    private String _location;
-    /** what test are we defining the plot data for? */
-    private PeerSummary _summary;
-    /** how should we render the current data set? */
-    private PlotSeriesConfig _seriesConfig;
-    private Set _listeners;
-    private boolean _disabled;
-
-    /**
-     * Delegating constructor . . .
-     * @param location the name of the file/URL to get the data from
-     */
-    public PeerPlotConfig(String location) {
-        this(location, null, null);
-    }
-    
-    /**
-     * Delegating constructor . . .
-     * @param location the name of the file/URL to get the data from
-     */
-    public PeerPlotConfig(PeerSummary summary) {
-        this(null, summary, null);
-    }
-    
-    /**
-     * Constructs a config =)
-     * @param location the location of the file/URL to get the data from
-     * @param config the client's configuration
-     * @param seriesConfig the series config
-     */
-    public PeerPlotConfig(String location, PeerSummary summary, PlotSeriesConfig seriesConfig) {
-        _location = location;
-        _summary = summary;
-        if (seriesConfig != null)
-            _seriesConfig = seriesConfig;
-        else
-            _seriesConfig = new PlotSeriesConfig();
-        
-        _listeners = Collections.synchronizedSet(new HashSet(2));
-        _disabled = false;
-    }
-    
-    /** 
-     * Where is the current state data supposed to be found?  This must either be a 
-     * local file path or a URL
-     * @return the current location
-     */
-    public String getLocation() { return _location; }
-
-    /**
-     * The location the current state data is supposed to be found.  This must either be
-     * a local file path or a URL
-     * @param location the location
-     */
-    public void setLocation(String location) { 
-        _location = location; 
-        fireUpdate();
-    }
-    
-    /** 
-     * What are we configuring? 
-     * @return the client configuration
-     */
-    public PeerSummary getSummary() { return _summary; }
-
-    /**
-     * Sets what we are currently configuring
-     * @param config the new config
-     */
-    public void setPeerSummary(PeerSummary summary) { 
-        _summary = summary;
-        fireUpdate();
-    }
-    
-    /** 
-     * How do we want to render the current data set?
-     * @return the way we currently render the data
-     */
-    public PlotSeriesConfig getSeriesConfig() { return _seriesConfig; }
-
-    /**
-     * Sets how we want to render the current data set.
-     * @param config the new config
-     */
-    public void setSeriesConfig(PlotSeriesConfig config) { 
-        _seriesConfig = config; 
-        fireUpdate();
-    }
-    
-    /** 
-     * four char description of the peer 
-     * @return the name
-     */
-    public String getPeerName() { return _summary.getPeer(); }
-    
-    /** 
-     * we've got someone who wants to be notified of changes to the plot config
-     * @param lsnr the listener to be added 
-     */
-    public void addListener(UpdateListener lsnr) { _listeners.add(lsnr); }
-
-    /**
-     * remove a listener
-     * @param lsnr the listener to remove
-     */
-    public void removeListener(UpdateListener lsnr) { _listeners.remove(lsnr); }
-    
-    void fireUpdate() {
-        if (_disabled) return;
-        for (Iterator iter = _listeners.iterator(); iter.hasNext(); ) {
-            ((UpdateListener)iter.next()).configUpdated(this);
-        }
-    }
-    
-    /**
-     * Disables notification of events listeners
-     * @see PeerPlotConfig#fireUpdate()
-     */
-    public void disableEvents() { _disabled = true; }
-
-    /**
-     * Enables notification of events listeners
-     * @see PeerPlotConfig#fireUpdate()
-     */
-    public void enableEvents() { _disabled = false; }
-    
-    /** 
-     * How do we want to render a particular dataset (either the current or the averaged values)?
-     */
-    public class PlotSeriesConfig {
-        private Map _shouldPlot;
-        private Map _plotColors;
-        
-        /**
-         * Creates a config for the rendering of a particular dataset)
-         * @param plotLost do we plot lost packets?
-         * @param plotColor in what color?
-         */
-        public PlotSeriesConfig() {
-            _shouldPlot = new HashMap(16);
-            _plotColors = new HashMap(16);
-        }
-        
-        /**
-         * Retrieves the plot config this plot series config is a part of
-         * @return the plot config
-         */
-        public PeerPlotConfig getPlotConfig() { return PeerPlotConfig.this; }
-        
-        public boolean getShouldPlotValue(String statName, String argName, boolean defaultVal) { 
-            Boolean val = (Boolean)_shouldPlot.get(statName + argName);
-            if (val == null) 
-                return defaultVal;
-            else
-                return val.booleanValue();
-        }
-        
-        public void setShouldPlotValue(String statName, String argName, boolean shouldPlot) { 
-            _shouldPlot.put(statName + argName, new Boolean(shouldPlot));
-            fireUpdate();
-        }
-
-        /**
-         * What color should we plot the data with? 
-         * @return the color
-         */
-        public Color getPlotLineColor(String statName, String argName) { 
-            return (Color)_plotColors.get(statName + argName);
-        }
-
-        /**
-         * Sets the color we should plot the data with
-         * @param color the color to use
-         */
-        public void setPlotLineColor(String statName, String argName, Color color) { 
-            if (color == null)
-                _plotColors.remove(statName + argName);
-            else
-                _plotColors.put(statName + argName, color);
-            fireUpdate();
-        }
-    }
-    
-    /**
-     * An interface for listening to updates . . .
-     */
-    public interface UpdateListener {
-        /**
-         * @param config the peer plot config that changes
-         * @see PeerPlotConfig#fireUpdate()
-         */
-        void configUpdated(PeerPlotConfig config);
-    }
-}
\ No newline at end of file
diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfigPane.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfigPane.java
deleted file mode 100644
index 864fd1be83..0000000000
--- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfigPane.java
+++ /dev/null
@@ -1,276 +0,0 @@
-package net.i2p.netmonitor.gui;
-
-import java.awt.Color;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-import java.util.TreeMap;
-
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-
-import net.i2p.netmonitor.PeerStat;
-import net.i2p.util.Log;
-
-class PeerPlotConfigPane extends JPanel implements PeerPlotConfig.UpdateListener {
-    private final static Log _log = new Log(PeerPlotConfigPane.class);
-    private PeerPlotConfig _config;
-    private NetViewerControlPane _parent;
-    private JLabel _peer;
-    private JButton _toggleAll;
-    private OptionGroup _options[];
-    private Random _rnd = new Random();
-    private final static Color WHITE = new Color(255, 255, 255);
-    private Color _background = WHITE;
-    
-    /**
-     * Constructs a pane
-     * @param config the plot config it represents
-     * @param pane the pane this one is attached to
-     */
-    public PeerPlotConfigPane(PeerPlotConfig config, NetViewerControlPane pane) {
-        _config = config;
-        _parent = pane;
-        if (_parent != null)
-            _background = _parent.getBackground();
-        _config.addListener(this);
-        initializeComponents();
-    }
-    
-    private void initializeComponents() {
-        buildComponents();
-        placeComponents(this);
-        refreshView();
-        //setBorder(new BevelBorder(BevelBorder.RAISED));
-        setBackground(_background);
-    }
-    
-    /** 
-     * place all the gui components onto the given panel 
-     * @param body the panel to place the components on
-     */
-    private void placeComponents(JPanel body) {
-        body.setLayout(new GridBagLayout());
-        GridBagConstraints cts = new GridBagConstraints();
-        
-        // row 0: peer name + toggle All
-        cts.gridx = 0;
-        cts.gridy = 0;
-        cts.gridwidth = 2;
-        cts.anchor = GridBagConstraints.WEST;
-        cts.fill = GridBagConstraints.NONE;
-        body.add(_peer, cts);
-        cts.gridx = 2;
-        cts.gridy = 0;
-        cts.gridwidth = 1;
-        cts.anchor = GridBagConstraints.EAST;
-        cts.fill = GridBagConstraints.NONE;
-        body.add(_toggleAll, cts);
-        
-        int row = 0;
-        for (int i = 0; i < _options.length; i++) {
-            row++;
-            cts.gridx = 0;
-            cts.gridy = row;
-            cts.gridwidth = 3;
-            cts.weightx = 5;
-            cts.fill = GridBagConstraints.BOTH;
-            cts.anchor = GridBagConstraints.WEST;
-            body.add(_options[i]._statName, cts);
-            
-            for (int j = 0; j < _options[i]._statAttributes.size(); j++) {
-                row++;
-                cts.gridx = 0;
-                cts.gridy = row;
-                cts.gridwidth = 1;
-                cts.weightx = 1;
-                cts.fill = GridBagConstraints.NONE;
-                body.add(new JLabel("   "), cts);
-                cts.gridx = 1;
-                cts.gridy = row;
-                cts.gridwidth = 1;
-                cts.weightx = 5;
-                cts.fill = GridBagConstraints.BOTH;
-                JCheckBox box = (JCheckBox)_options[i]._statAttributes.get(j);
-                box.setBackground(_background);
-                body.add(box, cts);
-                cts.gridx = 2;
-                cts.fill = GridBagConstraints.NONE;
-                cts.anchor = GridBagConstraints.EAST;
-                JButton toggleAttr = new JButton("Toggle all");
-                toggleAttr.setBackground(_background);
-                toggleAttr.addActionListener(new ToggleAttribute(_options[i].getStatName(), box.getText(), box));
-                body.add(toggleAttr, cts);
-            }
-        }
-    }
-    
-    private class ToggleAttribute implements ActionListener {
-        private String _statName;
-        private String _attrName;
-        private JCheckBox _box;
-        public ToggleAttribute(String statName, String attrName, JCheckBox box) {
-            _statName = statName;
-            _attrName = attrName;
-            _box = box;
-        }
-        public void actionPerformed(ActionEvent evt) {
-            boolean setActive = true;
-            if (_box.isSelected()) {
-                setActive = false;
-            }
-
-            List names = _parent.getViewer().getConfigNames();
-            for (int i = 0; i < names.size(); i++) {
-                String name = (String)names.get(i);
-                PeerPlotConfig cfg = _parent.getViewer().getConfig(name);
-                cfg.getSeriesConfig().setShouldPlotValue(_statName, _attrName, setActive);
-                _log.debug("Setting " + _statName + "." + _attrName + " to " + setActive + " for " + name);
-            }
-            _parent.stateUpdated();
-            _parent.refreshView();
-        }
-    }
-    
-    /** build all of the gui components */
-    private void buildComponents() {
-        _peer = new JLabel("Router: " + _config.getPeerName());
-        
-        _toggleAll = new JButton("Show all");
-        _toggleAll.setBackground(_background);
-        _toggleAll.addActionListener(new ActionListener() {
-            public void actionPerformed(ActionEvent evt) {
-                _config.disableEvents();
-                for (int i = 0; i < _options.length; i++) {
-                    for (int j = 0; j < _options[i]._statAttributes.size(); j++) {
-                        JCheckBox box = (JCheckBox)_options[i]._statAttributes.get(j);
-                        String statName = _options[i].getStatName();
-                        String attrName = box.getText();
-                        if (_toggleAll.getText().equals("Show all")) {
-                            box.setSelected(true);
-                            _config.getSeriesConfig().setShouldPlotValue(statName, attrName, true);
-                        } else {
-                            box.setSelected(false);
-                            _config.getSeriesConfig().setShouldPlotValue(statName, attrName, false);
-                        }
-                    }
-                }
-                if (_toggleAll.getText().equals("Show all"))
-                    _toggleAll.setText("Hide all");
-                else
-                    _toggleAll.setText("Show all");
-                _config.enableEvents();
-                _config.fireUpdate();
-            }
-        });
-        
-        Set statNames = _config.getSummary().getStatNames();
-        List options = new ArrayList(statNames.size());
-        for (Iterator iter = statNames.iterator(); iter.hasNext(); ) {
-            String statName = (String)iter.next();
-            List data = _config.getSummary().getData(statName);
-            if ( (data != null) && (data.size() > 0) ) {
-                PeerStat stat = (PeerStat)data.get(0);
-                String attributes[] = stat.getValueDescriptions();
-                OptionGroup group = new OptionGroup(statName, attributes);
-                options.add(group);
-            }
-        }
-        TreeMap orderedOptions = new TreeMap();
-        for (int i = 0; i < options.size(); i++) {
-            OptionGroup grp = (OptionGroup)options.get(i);
-            orderedOptions.put(grp.getStatName(), grp);
-        }
-        _options = new OptionGroup[options.size()];
-        int i = 0;
-        for (Iterator iter = orderedOptions.values().iterator(); iter.hasNext(); ) {
-            OptionGroup grp = (OptionGroup)iter.next();
-            _options[i] = grp;
-            i++;
-        }
-    }
-    
-    /** the settings have changed - revise */
-    private void refreshView() {
-        _parent.refreshView();
-    }
-    
-    /** 
-     * notified that the config has been updated 
-     * @param config the config that was been updated
-     */
-    public void configUpdated(PeerPlotConfig config) { refreshView(); }
-    
-    public void stateUpdated() {
-        for (int i = 0; i < _options.length; i++) {
-            for (int j = 0; j < _options[i]._statAttributes.size(); j++) {
-                JCheckBox box = (JCheckBox)_options[i]._statAttributes.get(j);
-                if (_config.getSeriesConfig().getShouldPlotValue(_options[i].getStatName(), box.getText(), false))
-                    box.setSelected(true);
-                else
-                    box.setSelected(false);
-            }
-        }
-    }
-    
-    private class OptionGroup {
-        JTextField _statName;
-        List _statAttributes;
-        
-        public String getStatName() { return _statName.getText(); }
-        
-        /**
-         * Creates an OptionLine.  
-         * @param statName statistic group in question
-         * @param statAttributes list of attributes we keep about this stat
-         */
-        public OptionGroup(String statName, String statAttributes[]) {
-            _statName = new JTextField(statName);
-            _statName.setEditable(false);
-            _statName.setBackground(_background);
-            _statAttributes = new ArrayList(4);
-            if (statAttributes != null) {
-                for (int i = 0; i < statAttributes.length; i++) {
-                    JCheckBox box = new JCheckBox(statAttributes[i]);
-                    box.addActionListener(new UpdateListener(OptionGroup.this));
-                    _statAttributes.add(box);
-                }
-            }
-        }
-    }
-    
-    private class UpdateListener implements ActionListener {
-        private OptionGroup _group;
-
-        /**
-         * Update Listener constructor . . . 
-         * @param group the group of stats to watch
-         */
-        public UpdateListener(OptionGroup group) {
-            _group = group;
-        }
-        
-        /* (non-Javadoc)
-         * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
-         */
-        public void actionPerformed(ActionEvent evt) { 
-            _config.disableEvents();
-            
-            for (int i = 0; i < _group._statAttributes.size(); i++) {
-                JCheckBox box = (JCheckBox)_group._statAttributes.get(i);
-                _config.getSeriesConfig().setShouldPlotValue(_group.getStatName(), box.getText(), box.isSelected());
-            }
-            _config.enableEvents();
-            _config.fireUpdate();
-        } 
-    }
-}
\ No newline at end of file
diff --git a/apps/phttprelay/doc/readme.license.txt b/apps/phttprelay/doc/readme.license.txt
deleted file mode 100644
index 18f90e09bb..0000000000
--- a/apps/phttprelay/doc/readme.license.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-$Id$
-
-the i2p/apps/phttprelay module is the root of the 
-PHTTPRelay application, and everything within it 
-is released according to the terms of the I2P 
-license policy.  That means everything contained 
-within the i2p/apps/phttprelay module is released 
-into the public domain unless otherwise marked.  
-Alternate licenses that may be used include BSD, 
-Cryptix, and MIT.
diff --git a/apps/phttprelay/java/build.xml b/apps/phttprelay/java/build.xml
deleted file mode 100644
index 6d924a2a27..0000000000
--- a/apps/phttprelay/java/build.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project basedir="." default="all" name="phttprelay">
-    <target name="all" depends="clean, build" />
-    <target name="build" depends="builddep, jar" />
-    <target name="builddep">
-        <ant dir="../../../core/java/" target="build" />
-    </target>
-    <target name="compile">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/obj" />
-        <javac srcdir="./src" debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar:lib/javax.servlet.jar" />
-    </target>
-    <target name="jar" depends="compile">
-        <war destfile="./build/phttprelay.war" webxml="web.xml">
-            <classes dir="./build/obj/">
-                <include name="**/*.class" />
-            </classes>
-            <lib dir="../../../core/java/build/">
-                <include name="i2p.jar" />
-            </lib>
-        </war>
-    </target>
-    <target name="javadoc">
-        <mkdir dir="./build" />
-        <mkdir dir="./build/javadoc" />
-        <javadoc 
-            sourcepath="./src:../../../core/java/src" destdir="./build/javadoc" 
-            classpath="./lib/javax.servlet.jar" 
-            packagenames="*" 
-            use="true" 
-            splitindex="true" 
-            windowtitle="I2P phttp relay" />
-    </target>
-    <target name="clean">
-        <delete dir="./build" />
-    </target>
-    <target name="cleandep" depends="clean">
-        <ant dir="../../../core/java/" target="cleandep" />
-    </target>
-    <target name="distclean" depends="clean">
-        <ant dir="../../../core/java/" target="distclean" />
-    </target>
-</project>
diff --git a/apps/phttprelay/java/lib/LICENSE.html b/apps/phttprelay/java/lib/LICENSE.html
deleted file mode 100644
index 678cdec531..0000000000
--- a/apps/phttprelay/java/lib/LICENSE.html
+++ /dev/null
@@ -1,159 +0,0 @@
-<HTML>
-<HEAD>
-   <TITLE>Jetty License</TITLE>
-</HEAD>
-<BODY BGCOLOR="#FFFFFF">
-<FONT FACE=ARIAL,HELVETICA>
-<CENTER><FONT SIZE=+3><B>Jetty License</B></FONT></CENTER>
-<CENTER><FONT SIZE=-1><B>$Revision: 1.1 $</B></FONT></CENTER>
-
-<B>Preamble:</B><p>
-
-The intent of this document is to state the conditions under which the
-Jetty Package may be copied, such that the Copyright Holder maintains some
-semblance of control over the development of the package, while giving the
-users of the package the right to use, distribute and make reasonable
-modifications to the Package in accordance with the goals and ideals of
-the Open Source concept as described at
-<A HREF="http://www.opensource.org">http://www.opensource.org</A>.
-<P>
-It is the intent of this license to allow commercial usage of the Jetty
-package, so long as the source code is distributed or suitable visible
-credit given or other arrangements made with the copyright holders.
-
-<P><B>Definitions:</B><P>
-
-<UL>
-  <LI> "Jetty" refers to the collection of Java classes that are
-       distributed as a HTTP server with servlet capabilities and
-       associated utilities.<p>
-
-  <LI>	"Package" refers to the collection of files distributed by the
-       Copyright Holder, and derivatives of that collection of files
-       created through textual modification.<P>
-       
-  <LI>	"Standard Version" refers to such a Package if it has not been
-       modified, or has been modified in accordance with the wishes
-       of the Copyright Holder.<P>
-       
-  <LI>	"Copyright Holder" is whoever is named in the copyright or
-       copyrights for the package. <BR>
-       Mort Bay Consulting Pty. Ltd. (Australia) is the "Copyright
-       Holder" for the Jetty package.<P>
-       
-  <LI>	"You" is you, if you're thinking about copying or distributing
-       this Package.<P>
-       
-  <LI>	"Reasonable copying fee" is whatever you can justify on the
-       basis of media cost, duplication charges, time of people involved,
-       and so on.  (You will not be required to justify it to the
-       Copyright Holder, but only to the computing community at large
-       as a market that must bear the fee.)<P>
-       
-  <LI>	"Freely Available" means that no fee is charged for the item
-       itself, though there may be fees involved in handling the item.
-       It also means that recipients of the item may redistribute it
-       under the same conditions they received it.<P>
-</UL>
-
-0. The Jetty Package is Copyright (c) Mort Bay Consulting Pty. Ltd.
-(Australia) and others. Individual files in this package may contain
-additional copyright notices. The javax.servlet packages are copyright
-Sun Microsystems Inc. <P>
-
-1. The Standard Version of the Jetty package is
-available from <A HREF=http://jetty.mortbay.org>http://jetty.mortbay.org</A>.<P>
-
-2. You may make and distribute verbatim copies of the source form 
-of the Standard Version of this Package without restriction, provided that 
-you include this license and all of the original copyright notices
-and associated disclaimers.<P>
-
-3. You may make and distribute verbatim copies of the compiled form of the 
-Standard Version of this Package without restriction, provided that you
-include this license.<P>
-
-4. You may apply bug fixes, portability fixes and other modifications
-derived from the Public Domain or from the Copyright Holder.  A Package
-modified in such a way shall still be considered the Standard Version.<P>
-
-5. You may otherwise modify your copy of this Package in any way, provided
-that you insert a prominent notice in each changed file stating how and
-when you changed that file, and provided that you do at least ONE of the
-following:<P>
-
-<BLOCKQUOTE>
-a) Place your modifications in the Public Domain or otherwise make them
-Freely Available, such as by posting said modifications to Usenet or
-an equivalent medium, or placing the modifications on a major archive
-site such as ftp.uu.net, or by allowing the Copyright Holder to include
-your modifications in the Standard Version of the Package.<P>
-
-b) Use the modified Package only within your corporation or organization.<P>
-
-c) Rename any non-standard classes so the names do not conflict
-with standard classes, which must also be provided, and provide
-a separate manual page for each non-standard class that clearly
-documents how it differs from the Standard Version.<P>
-
-d) Make other arrangements with the Copyright Holder.<P>
-</BLOCKQUOTE>
-
-6. You may distribute modifications or subsets of this Package in source 
-code or compiled form, provided that you do at least ONE of the following:<P>
-
-<BLOCKQUOTE>
-a) Distribute this license and all original copyright messages, together 
-with instructions (in the about dialog, manual page or equivalent) on where 
-to get the complete Standard Version.<P>
-
-b) Accompany the distribution with the machine-readable source of
-the Package with your modifications. The modified package must include
-this license and all of the original copyright notices and associated
-disclaimers, together with instructions on where to get the complete
-Standard Version.<P>
-
-c) Make other arrangements with the Copyright Holder.<P>
-</BLOCKQUOTE>
-
-7. You may charge a reasonable copying fee for any distribution of this
-Package.  You may charge any fee you choose for support of this Package.
-You may not charge a fee for this Package itself.  However,
-you may distribute this Package in aggregate with other (possibly
-commercial) programs as part of a larger (possibly commercial) software
-distribution provided that you meet the other distribution requirements
-of this license.<P>
-
-8. Input to or the output produced from the programs of this Package
-do not automatically fall under the copyright of this Package, but
-belong to whomever generated them, and may be sold commercially, and
-may be aggregated with this Package.<P>
-
-9. Any program subroutines supplied by you and linked into this Package
-shall not be considered part of this Package.<P>
-
-10. The name of the Copyright Holder may not be used to endorse or promote
-products derived from this software without specific prior written
-permission.<P>
-
-11. This license may change with each release of a Standard Version of
-the Package. You may choose to use the license associated with version
-you are using or the license of the latest Standard Version.<P>
-
-12. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.<P>
-
-13. If any superior law implies a warranty, the sole remedy under such shall
-be , at the Copyright Holders option either a) return of any price paid or 
-b) use or reasonable endeavours to repair or replace the software.<P>
-
-14. This license shall be read under the laws of Australia.  <P>
-
-<center>The End</center>
-
-<center><FONT size=-1>This license was derived from the <I>Artistic</I> license published 
-on <a href=http://www.opensource.org>http://www.opensource.com</a></font></center>
-</FONT>
-
-
diff --git a/apps/phttprelay/java/lib/javax.servlet.jar b/apps/phttprelay/java/lib/javax.servlet.jar
deleted file mode 100644
index 6bee0cc32157b81cbae461f3c465dc413d796c46..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 74543
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
CpF_I<

diff --git a/apps/phttprelay/java/lib/readme.txt b/apps/phttprelay/java/lib/readme.txt
deleted file mode 100644
index d16d9e6791..0000000000
--- a/apps/phttprelay/java/lib/readme.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-The file javax.servlet.jar is distributed under the terms of LICENSE.html, 
-which is the implementation of the java servlet classes as retrieved from
-http://jetty.mortbay.org/jetty/
-
-It is only included to assist in building the phttprelay.war file on hosts
-that do not have a servlet container / implementation.
diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/CheckSendStatusServlet.java b/apps/phttprelay/java/src/net/i2p/phttprelay/CheckSendStatusServlet.java
deleted file mode 100644
index b7c2af1b94..0000000000
--- a/apps/phttprelay/java/src/net/i2p/phttprelay/CheckSendStatusServlet.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package net.i2p.phttprelay;
-
-/*
- * free (adj.): unencumbered; not under the control of others
- * Written by jrandom in 2003 and released into the public domain 
- * with no warranty of any kind, either expressed or implied.  
- * It probably won't make your computer catch on fire, or eat 
- * your children, but it might.  Use at your own risk.
- *
- */
-
-import java.io.File;
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Check the status of previous message delivery, returning either pending or
- * unknown, where pending means that particular message ID for that particular
- * target is still on the server, and unknown means it has either not been created
- * or it has been sent successfully.  It does this by sending HTTP 204 (NO CONTENT) 
- * for pending, and HTTP 404 (NOT FOUND) for unknown. <p />
- *
- * This servlet should be set up in web.xml as follows:
- *
- *  <servlet>
- *   <servlet-name>CheckSendStatus</servlet-name>
- *   <servlet-class>net.i2p.phttprelay.CheckSendStatusServlet</servlet-class>
- *   <init-param>
- *     <param-name>baseDir</param-name>
- *     <param-value>/usr/local/jetty/phttprelayDir</param-value>
- *   </init-param>
- *  </servlet>
- *
- * <servlet-mapping>
- *   <servlet-name>CheckSendStatus</servlet-name>
- *   <url-pattern>/phttpCheckSendStatus</url-pattern>
- * </servlet-mapping>
- *
- * baseDir is the directory under which registrants and their pending messages are stored
- *
- */
-public class CheckSendStatusServlet extends PHTTPRelayServlet {
-    /* URL parameters on the check */
-
-    /** H(routerIdent).toBase64() of the target to receive the message */
-    public final static String PARAM_SEND_TARGET = "target";
-    /** msgId parameter */
-    public final static String PARAM_MSG_ID = "msgId";
-
-    public final static String PROP_STATUS = "status";
-    public final static String STATUS_PENDING = "pending";
-    public final static String STATUS_UNKNOWN = "unknown";
-
-    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        String target = req.getParameter(PARAM_SEND_TARGET);
-        String msgIdStr = req.getParameter(PARAM_MSG_ID);
-
-        log("Checking status of [" + target + "] message [" + msgIdStr + "]");
-        if (!isKnownMessage(target, msgIdStr)) {
-            log("Not known - its not pending");
-            notPending(req, resp);
-            return;
-        } else {
-            log("Known - its still pending");
-            pending(req, resp);
-            return;
-        }
-    }
-
-    private boolean isKnownMessage(String target, String msgId) throws IOException {
-        if ((target == null) || (target.trim().length() <= 0)) return false;
-        if ((msgId == null) || (msgId.trim().length() <= 0)) return false;
-        File identDir = getIdentDir(target);
-        if (identDir.exists()) {
-            File identFile = new File(identDir, "identity.dat");
-            if (identFile.exists()) {
-                // known and valid (maybe we need to check the file format... naw, fuck it
-                File msgFile = new File(identDir, "msg" + msgId + ".dat");
-                if (msgFile.exists())
-                    return true;
-                else
-                    return false;
-            } else {
-                return false;
-            }
-        } else {
-            return false;
-        }
-    }
-
-    private void pending(HttpServletRequest req, HttpServletResponse resp) throws IOException {
-        resp.setStatus(HttpServletResponse.SC_OK);
-        ServletOutputStream out = resp.getOutputStream();
-        StringBuffer buf = new StringBuffer();
-        buf.append(PROP_STATUS).append('=').append(STATUS_PENDING).append('\n');
-        out.write(buf.toString().getBytes());
-        out.flush();
-        out.close();
-    }
-
-    private void notPending(HttpServletRequest req, HttpServletResponse resp) throws IOException {
-        resp.setStatus(HttpServletResponse.SC_OK);
-        ServletOutputStream out = resp.getOutputStream();
-        StringBuffer buf = new StringBuffer();
-        buf.append(PROP_STATUS).append('=').append(STATUS_UNKNOWN).append('\n');
-        out.write(buf.toString().getBytes());
-        out.flush();
-        out.close();
-    }
-}
\ No newline at end of file
diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/LockManager.java b/apps/phttprelay/java/src/net/i2p/phttprelay/LockManager.java
deleted file mode 100644
index 433203169f..0000000000
--- a/apps/phttprelay/java/src/net/i2p/phttprelay/LockManager.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package net.i2p.phttprelay;
-
-/*
- * free (adj.): unencumbered; not under the control of others
- * Written by jrandom in 2003 and released into the public domain 
- * with no warranty of any kind, either expressed or implied.  
- * It probably won't make your computer catch on fire, or eat 
- * your children, but it might.  Use at your own risk.
- *
- */
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Lock identities for updating messages (so that they aren't read / deleted 
- * while being written)
- *
- */
-class LockManager {
-    private volatile static Set _locks = new HashSet(); // target
-
-    public static void lockIdent(String target) {
-        while (true) {
-            synchronized (_locks) {
-                if (!_locks.contains(target)) {
-                    _locks.add(target);
-                    return;
-                }
-                try {
-                    _locks.wait(1000);
-                } catch (InterruptedException ie) {
-                }
-            }
-        }
-    }
-
-    public static void unlockIdent(String target) {
-        synchronized (_locks) {
-            _locks.remove(target);
-            _locks.notifyAll();
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/PHTTPRelayServlet.java b/apps/phttprelay/java/src/net/i2p/phttprelay/PHTTPRelayServlet.java
deleted file mode 100644
index 45744a2d20..0000000000
--- a/apps/phttprelay/java/src/net/i2p/phttprelay/PHTTPRelayServlet.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package net.i2p.phttprelay;
-
-/*
- * free (adj.): unencumbered; not under the control of others
- * Written by jrandom in 2003 and released into the public domain 
- * with no warranty of any kind, either expressed or implied.  
- * It probably won't make your computer catch on fire, or eat 
- * your children, but it might.  Use at your own risk.
- *
- */
-
-import java.io.File;
-import java.io.IOException;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-
-import net.i2p.util.Log;
-
-abstract class PHTTPRelayServlet extends HttpServlet {
-    private Log _log = new Log(getClass());
-    protected String _baseDir;
-
-    /* config params */
-    /*public final static String PARAM_BASEDIR = "baseDir";*/
-    public final static String ENV_BASEDIR = "phttpRelay.baseDir";
-
-    /** match the clock fudge factor on the router, rather than importing the entire router cvs module */
-    public final static long CLOCK_FUDGE_FACTOR = 1 * 60 * 1000;
-
-    protected String buildURL(HttpServletRequest req, String path) {
-        StringBuffer buf = new StringBuffer();
-        buf.append(req.getScheme()).append("://");
-        buf.append(req.getServerName()).append(":").append(req.getServerPort());
-        buf.append(req.getContextPath());
-        buf.append(path);
-        log("URL built: " + buf.toString());
-        return buf.toString();
-    }
-
-    protected File getIdentDir(String target) throws IOException {
-        if ((_baseDir == null) || (target == null)) throw new IOException("dir not specified to deal with");
-        File baseDir = new File(_baseDir);
-        if (!baseDir.exists()) {
-            boolean created = baseDir.mkdirs();
-            log("Creating PHTTP Relay Base Directory: " + baseDir.getAbsolutePath() + " - ok? " + created);
-        }
-        File identDir = new File(baseDir, target);
-        log("Ident dir: " + identDir.getAbsolutePath());
-        return identDir;
-    }
-
-    public void init(ServletConfig config) throws ServletException {
-        super.init(config);
-        String dir = System.getProperty(ENV_BASEDIR);
-        if (dir == null) {
-            _log.warn("Base directory for the polling http relay system not in the environment [" + ENV_BASEDIR + "]");
-            _log.warn("Setting the base directory to ./relayDir for " + getServletName());
-            _baseDir = ".relayDir";
-        } else {
-            _baseDir = dir;
-            log("Loaded up " + getServletName() + " with base directory " + _baseDir);
-        }
-    }
-
-    public void log(String msg) {
-        _log.debug(msg);
-    }
-
-    public void log(String msg, Throwable t) {
-        _log.debug(msg, t);
-    }
-}
\ No newline at end of file
diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/PollServlet.java b/apps/phttprelay/java/src/net/i2p/phttprelay/PollServlet.java
deleted file mode 100644
index d1cf4acaf3..0000000000
--- a/apps/phttprelay/java/src/net/i2p/phttprelay/PollServlet.java
+++ /dev/null
@@ -1,263 +0,0 @@
-package net.i2p.phttprelay;
-
-/*
- * free (adj.): unencumbered; not under the control of others
- * Written by jrandom in 2003 and released into the public domain 
- * with no warranty of any kind, either expressed or implied.  
- * It probably won't make your computer catch on fire, or eat 
- * your children, but it might.  Use at your own risk.
- *
- */
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Date;
-
-import javax.servlet.ServletException;
-import javax.servlet.ServletInputStream;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import net.i2p.crypto.DSAEngine;
-import net.i2p.data.Base64;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.DataHelper;
-import net.i2p.data.RouterIdentity;
-import net.i2p.data.Signature;
-import net.i2p.util.Clock;
-
-/**
- * Handle poll requests for new messages - checking the poll request for a valid signature,
- * sending back all of the messages found, and after all messages are written out, delete
- * them from the local store.  If the signature fails, it sends back an HTTP 403 (UNAUTHORIZED).
- * If the target is not registered, it sends back an HTTP 404 (NOT FOUND) <p />
- *
- * This servlet should be set up in web.xml as follows:
- *
- *  <servlet>
- *   <servlet-name>Poll</servlet-name>
- *   <servlet-class>net.i2p.phttprelay.PollServlet</servlet-class>
- *   <init-param>
- *     <param-name>baseDir</param-name>
- *     <param-value>/usr/local/jetty/phttprelayDir</param-value>
- *   </init-param>
- *  </servlet>
- *
- * <servlet-mapping>
- *   <servlet-name>Poll</servlet-name>
- *   <url-pattern>/phttpPoll</url-pattern>
- * </servlet-mapping>
- *
- * baseDir is the directory under which registrants and their pending messages are stored
- *
- */
-public class PollServlet extends PHTTPRelayServlet {
-    /* URL parameters on the check */
-
-    /** H(routerIdent).toBase64() of the target to receive the message */
-    public final static String PARAM_SEND_TARGET = "target";
-
-    /** HTTP error code if the target is not known*/
-    public final static int CODE_UNKNOWN = HttpServletResponse.SC_NOT_FOUND;
-    /** HTTP error code if the signature failed */
-    public final static int CODE_UNAUTHORIZED = HttpServletResponse.SC_UNAUTHORIZED;
-    /** HTTP error code if everything is ok */
-    public final static int CODE_OK = HttpServletResponse.SC_OK;
-
-    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        byte data[] = getData(req);
-        if (data == null) return;
-        ByteArrayInputStream bais = new ByteArrayInputStream(data);
-        String target = getTarget(bais);
-        if (target == null) {
-            log("Target not specified");
-            resp.sendError(CODE_UNKNOWN);
-            return;
-        }
-
-        if (!isKnown(target)) {
-            resp.sendError(CODE_UNKNOWN);
-            return;
-        }
-
-        if (!isAuthorized(target, bais)) {
-            resp.sendError(CODE_UNAUTHORIZED);
-            return;
-        } else {
-            log("Authorized access for target " + target);
-        }
-
-        sendMessages(resp, target);
-    }
-
-    private byte[] getData(HttpServletRequest req) throws ServletException, IOException {
-        ServletInputStream in = req.getInputStream();
-        int len = req.getContentLength();
-        byte data[] = new byte[len];
-        int cur = 0;
-        int read = DataHelper.read(in, data);
-        if (read != len) {
-            log("Size read is incorrect [" + read + " instead of expected " + len + "]");
-            return null;
-        } else {
-            log("Read data length: " + data.length + " in base64: " + Base64.encode(data));
-            return data;
-        }
-    }
-
-    private String getTarget(InputStream in) throws IOException {
-        StringBuffer buf = new StringBuffer(64);
-        int numBytes = 0;
-        int c = 0;
-        while ((c = in.read()) != -1) {
-            if (c == (int) '&') break;
-            buf.append((char) c);
-            numBytes++;
-            if (numBytes > 128) {
-                log("Target didn't find the & after 128 bytes [" + buf.toString() + "]");
-                return null;
-            }
-        }
-        if (buf.toString().indexOf("target=") != 0) {
-            log("Did not start with target= [" + buf.toString() + "]");
-            return null;
-        }
-        return buf.substring("target=".length());
-    }
-
-    private void sendMessages(HttpServletResponse resp, String target) throws IOException {
-        log("Before lock " + target);
-        LockManager.lockIdent(target);
-        log("Locked " + target);
-        try {
-            File identDir = getIdentDir(target);
-            expire(identDir);
-            File messageFiles[] = identDir.listFiles();
-            resp.setStatus(CODE_OK);
-            log("Sending back " + (messageFiles.length - 1) + " messages");
-            ServletOutputStream out = resp.getOutputStream();
-            DataHelper.writeDate(out, new Date(Clock.getInstance().now()));
-            DataHelper.writeLong(out, 2, messageFiles.length - 1);
-            for (int i = 0; i < messageFiles.length; i++) {
-                if ("identity.dat".equals(messageFiles[i].getName())) {
-                    // skip
-                } else {
-                    log("Message file " + messageFiles[i].getName() + " is " + messageFiles[i].length() + " bytes");
-                    DataHelper.writeLong(out, 4, messageFiles[i].length());
-                    writeFile(out, messageFiles[i]);
-                    boolean deleted = messageFiles[i].delete();
-                    if (!deleted) {
-                        log("!!!Error removing message file " + messageFiles[i].getAbsolutePath() + " - please delete!");
-                    }
-                }
-            }
-            out.flush();
-            out.close();
-        } catch (DataFormatException dfe) {
-            log("Error sending message", dfe);
-        } finally {
-            LockManager.unlockIdent(target);
-            log("Unlocked " + target);
-        }
-    }
-
-    private final static long EXPIRE_DELAY = 60 * 1000; // expire messages every minute
-
-    private void expire(File identDir) throws IOException {
-        File files[] = identDir.listFiles();
-        long now = System.currentTimeMillis();
-        for (int i = 0; i < files.length; i++) {
-            if ("identity.dat".equals(files[i].getName())) {
-                continue;
-            }
-            if (files[i].lastModified() + EXPIRE_DELAY < now) {
-                log("Expiring " + files[i].getAbsolutePath());
-                files[i].delete();
-            }
-        }
-    }
-
-    private void writeFile(ServletOutputStream out, File file) throws IOException {
-        FileInputStream fis = new FileInputStream(file);
-        try {
-            byte buf[] = new byte[4096];
-            while (true) {
-                int read = DataHelper.read(fis, buf);
-                if (read > 0)
-                    out.write(buf, 0, read);
-                else
-                    break;
-            }
-        } finally {
-            fis.close();
-        }
-    }
-
-    private boolean isKnown(String target) throws IOException {
-        File identDir = getIdentDir(target);
-        if (identDir.exists()) {
-            File identFile = new File(identDir, "identity.dat");
-            if (identFile.exists()) {
-                // known and valid (maybe we need to check the file format... naw, fuck it
-                return true;
-            } else {
-                return false;
-            }
-        } else {
-            return false;
-        }
-    }
-
-    private boolean isAuthorized(String target, InputStream in) throws IOException {
-        RouterIdentity ident = null;
-        try {
-            ident = getRouterIdentity(target);
-        } catch (DataFormatException dfe) {
-            log("Identity was not valid", dfe);
-        }
-
-        if (ident == null) {
-            log("Identity not registered");
-            return false;
-        }
-
-        try {
-            long val = DataHelper.readLong(in, 4);
-            Signature sig = new Signature();
-            sig.readBytes(in);
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            DataHelper.writeLong(baos, 4, val);
-            if (DSAEngine.getInstance().verifySignature(sig, baos.toByteArray(), ident.getSigningPublicKey())) {
-                return true;
-            } else {
-                log("Signature does NOT match");
-                return false;
-            }
-        } catch (DataFormatException dfe) {
-            log("Format error reading the nonce and signature", dfe);
-            return false;
-        }
-    }
-
-    private RouterIdentity getRouterIdentity(String target) throws IOException, DataFormatException {
-        File identDir = getIdentDir(target);
-        if (identDir.exists()) {
-            File identFile = new File(identDir, "identity.dat");
-            if (identFile.exists()) {
-                // known and valid (maybe we need to check the file format... naw, fuck it
-                RouterIdentity ident = new RouterIdentity();
-                ident.readBytes(new FileInputStream(identFile));
-                return ident;
-            } else {
-                return null;
-            }
-        } else {
-            return null;
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/RegisterServlet.java b/apps/phttprelay/java/src/net/i2p/phttprelay/RegisterServlet.java
deleted file mode 100644
index 822228b18b..0000000000
--- a/apps/phttprelay/java/src/net/i2p/phttprelay/RegisterServlet.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package net.i2p.phttprelay;
-
-/*
- * free (adj.): unencumbered; not under the control of others
- * Written by jrandom in 2003 and released into the public domain 
- * with no warranty of any kind, either expressed or implied.  
- * It probably won't make your computer catch on fire, or eat 
- * your children, but it might.  Use at your own risk.
- *
- */
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Date;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletInputStream;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import net.i2p.data.DataFormatException;
-import net.i2p.data.DataHelper;
-import net.i2p.data.RouterIdentity;
-import net.i2p.util.Clock;
-
-/**
- * Accept registrations for PHTTP relaying, allowing the Polling HTTP (PHTTP) 
- * transport for I2P to bridge past firewalls, NATs, and proxy servers. <p />
- *
- * This servlet should be set up in web.xml as follows:
- *
- *  <servlet>
- *   <servlet-name>Register</servlet-name>
- *   <servlet-class>net.i2p.phttprelay.RegisterServlet</servlet-class>
- *   <init-param>
- *     <param-name>baseDir</param-name>
- *     <param-value>/usr/local/jetty/phttprelayDir</param-value>
- *   </init-param>
- *   <init-param>
- *     <param-name>pollPath</param-name>
- *     <param-value>phttpPoll</param-value>
- *   </init-param>
- *   <init-param>
- *     <param-name>sendPath</param-name>
- *     <param-value>phttpSend</param-value>
- *   </init-param>
- *  </servlet>
- *
- * <servlet-mapping>
- *   <servlet-name>Register</servlet-name>
- *   <url-pattern>/phttpRegister</url-pattern>
- * </servlet-mapping>
- *
- * baseDir is the directory under which registrants and their pending messages are stored
- * pollPath is the path under the current host that requests polling for messages should be sent
- * sendPath is the path under the current host that requests submitting messages should be sent
- *
- * The pollPath and sendPath must not start with / as they are translated ala http://host:port/[path]
- */
-public class RegisterServlet extends PHTTPRelayServlet {
-    private String _pollPath;
-    private String _sendPath;
-
-    /* config params */
-    public final static String PARAM_POLL_PATH = "pollPath";
-    public final static String PARAM_SEND_PATH = "sendPath";
-
-    /* key=val keys sent back on registration */
-    public final static String PROP_STATUS = "status";
-    public final static String PROP_POLL_URL = "pollURL";
-    public final static String PROP_SEND_URL = "sendURL";
-    public final static String PROP_TIME_OFFSET = "timeOffset"; // ms (local-remote)
-
-    /* values for the PROP_STATUS */
-    public final static String STATUS_FAILED = "failed";
-    public final static String STATUS_REGISTERED = "registered";
-
-    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        ServletInputStream in = req.getInputStream();
-        RouterIdentity ident = new RouterIdentity();
-        try {
-            Date remoteTime = DataHelper.readDate(in);
-            long skew = getSkew(remoteTime);
-            ident.readBytes(in);
-            boolean ok = registerIdent(ident);
-            sendURLs(req, resp, skew, ok);
-        } catch (DataFormatException dfe) {
-            log("Invalid format for router identity posted", dfe);
-        } finally {
-            in.close();
-        }
-    }
-
-    private long getSkew(Date remoteDate) {
-        if (remoteDate == null) {
-            log("*ERROR: remote date was null");
-            return Long.MAX_VALUE;
-        } else {
-            long diff = Clock.getInstance().now() - remoteDate.getTime();
-            return diff;
-        }
-    }
-
-    private boolean registerIdent(RouterIdentity ident) throws DataFormatException, IOException {
-        File identDir = getIdentDir(ident.getHash().toBase64());
-        boolean created = identDir.mkdirs();
-        File identFile = new File(identDir, "identity.dat");
-        FileOutputStream fos = null;
-        try {
-            fos = new FileOutputStream(identFile);
-            ident.writeBytes(fos);
-        } finally {
-            if (fos != null) try {
-                fos.close();
-            } catch (IOException ioe) {
-            }
-        }
-        log("Identity registered into " + identFile.getAbsolutePath());
-        return true;
-    }
-
-    private void sendURLs(HttpServletRequest req, HttpServletResponse resp, long skew, boolean ok) throws IOException {
-        ServletOutputStream out = resp.getOutputStream();
-
-        log("*Debug: clock skew of " + skew + "ms (local-remote)");
-
-        StringBuffer buf = new StringBuffer();
-        if (ok) {
-            buf.append(PROP_POLL_URL).append("=").append(buildURL(req, _pollPath)).append("\n");
-            buf.append(PROP_SEND_URL).append("=").append(buildURL(req, _sendPath)).append("\n");
-            buf.append(PROP_TIME_OFFSET).append("=").append(skew).append("\n");
-            buf.append(PROP_STATUS).append("=").append(STATUS_REGISTERED).append("\n");
-        } else {
-            buf.append(PROP_TIME_OFFSET).append("=").append(skew).append("\n");
-            buf.append(PROP_STATUS).append("=").append(STATUS_FAILED).append("\n");
-        }
-        out.write(buf.toString().getBytes());
-        out.close();
-    }
-
-    public void init(ServletConfig config) throws ServletException {
-        super.init(config);
-
-        String pollPath = config.getInitParameter(PARAM_POLL_PATH);
-        if (pollPath == null)
-            throw new ServletException("Polling path for the registration servlet required [" + PARAM_POLL_PATH + "]");
-        else
-            _pollPath = pollPath;
-        String sendPath = config.getInitParameter(PARAM_SEND_PATH);
-        if (sendPath == null)
-            throw new ServletException("Sending path for the registration servlet required [" + PARAM_SEND_PATH + "]");
-        else
-            _sendPath = sendPath;
-    }
-}
\ No newline at end of file
diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/SendServlet.java b/apps/phttprelay/java/src/net/i2p/phttprelay/SendServlet.java
deleted file mode 100644
index a09a4258c4..0000000000
--- a/apps/phttprelay/java/src/net/i2p/phttprelay/SendServlet.java
+++ /dev/null
@@ -1,324 +0,0 @@
-package net.i2p.phttprelay;
-
-/*
- * free (adj.): unencumbered; not under the control of others
- * Written by jrandom in 2003 and released into the public domain 
- * with no warranty of any kind, either expressed or implied.  
- * It probably won't make your computer catch on fire, or eat 
- * your children, but it might.  Use at your own risk.
- *
- */
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletInputStream;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Accept messages for PHTTP relaying, allowing the Polling HTTP (PHTTP) 
- * transport for I2P to bridge past firewalls, NATs, and proxy servers.  This
- * delivers them into the queue, returning HTTP 201 (created) if the queue is
- * known, as well as the URL at which requests can be made to check the delivery
- * status of the message.  If the queue is not known, HTTP 410 (resource gone) is
- * sent back.  <p />
- *
- * This servlet should be set up in web.xml as follows:
- *
- *  <servlet>
- *   <servlet-name>Send</servlet-name>
- *   <servlet-class>net.i2p.phttprelay.SendServlet</servlet-class>
- *   <init-param>
- *     <param-name>baseDir</param-name>
- *     <param-value>/usr/local/jetty/phttprelayDir</param-value>
- *   </init-param>
- *   <init-param>
- *     <param-name>checkPath</param-name>
- *     <param-value>phttpCheckStatus</param-value>
- *   </init-param>
- *   <init-param>
- *     <param-name>maxMessagesPerIdent</param-name>
- *     <param-value>100</param-value>
- *   </init-param>
- *  </servlet>
- *
- * <servlet-mapping>
- *   <servlet-name>Send</servlet-name>
- *   <url-pattern>/phttpSend</url-pattern>
- * </servlet-mapping>
- *
- * baseDir is the directory under which registrants and their pending messages are stored
- * checkPath is the path under the current host that requests for the status of delivery should be sent
- * maxMessagesPerIdent is the maximum number of outstanding messages per peer being relayed
- *
- * The checkPath must not start with / as they are translated ala http://host:port/[path]
- */
-public class SendServlet extends PHTTPRelayServlet {
-    private String _checkPath;
-    private int _maxMessagesPerIdent;
-
-    /* config params */
-    public final static String PARAM_CHECK_PATH = "checkPath";
-    public final static String PARAM_MAX_MESSAGES_PER_IDENT = "maxMessagesPerIdent";
-
-    /* URL parameters on the send */
-
-    /** H(routerIdent).toBase64() of the target to receive the message */
-    public final static String PARAM_SEND_TARGET = "target";
-    /** # ms to wait for the message to be delivered before failing it */
-    public final static String PARAM_SEND_TIMEOUTMS = "timeoutMs";
-    /** # bytes to be sent in the message */
-    public final static String PARAM_SEND_DATA_LENGTH = "dataLength";
-    /** sending router's time in ms */
-    public final static String PARAM_SEND_TIME = "localTime";
-
-    /** msgId parameter to access the check path servlet with (along side PARAM_SEND_TARGET) */
-    public final static String PARAM_MSG_ID = "msgId";
-
-    /* key=val keys sent back on registration */
-    public final static String PROP_CHECK_URL = "statusCheckURL";
-    public final static String PROP_STATUS = "status";
-    public final static String STATUS_OK = "accepted";
-    public final static String STATUS_UNKNOWN = "unknown";
-    private final static String STATUS_CLOCKSKEW = "clockSkew_";
-
-    /** prefix for (local-remote) */
-
-    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-        ServletInputStream in = req.getInputStream();
-        try {
-            int contentLen = req.getContentLength();
-            String firstLine = getFirstLine(in, contentLen);
-            if (firstLine == null) { return; }
-            Map params = getParameters(firstLine);
-            String target = (String) params.get(PARAM_SEND_TARGET);
-            String timeoutStr = (String) params.get(PARAM_SEND_TIMEOUTMS);
-            String lenStr = (String) params.get(PARAM_SEND_DATA_LENGTH);
-            String remoteTimeStr = (String) params.get(PARAM_SEND_TIME);
-            long skew = 0;
-            try {
-                long remTime = Long.parseLong(remoteTimeStr);
-                skew = System.currentTimeMillis() - remTime;
-            } catch (Throwable t) {
-                skew = Long.MAX_VALUE;
-                log("*ERROR could not parse the remote time from [" + remoteTimeStr + "]");
-            }
-
-            log("Target [" + target + "] timeout [" + timeoutStr + "] length [" + lenStr + "] skew [" + skew + "]");
-
-            if ((skew > CLOCK_FUDGE_FACTOR) || (skew < 0 - CLOCK_FUDGE_FACTOR)) {
-                log("Attempt to send by a skewed router: skew = " + skew + "ms (local-remote)");
-                failSkewed(req, resp, skew);
-            }
-
-            if (!isValidTarget(target)) {
-                log("Attempt to send to an invalid target [" + target + "]");
-                fail(req, resp, "Unknown or invalid target");
-                return;
-            }
-
-            long len = -1;
-            try {
-                len = Long.parseLong(lenStr);
-            } catch (Throwable t) {
-                log("Unable to parse length parameter [" + PARAM_SEND_DATA_LENGTH + "] (" + lenStr + ")");
-                fail(req, resp, "Invalid length parameter");
-                return;
-            }
-
-            int msgId = saveFile(in, resp, target, len);
-            if (msgId >= 0) {
-                sendSuccess(req, resp, target, msgId);
-            } else {
-                fail(req, resp, "Unable to queue up the message for delivery");
-            }
-        } finally {
-            try {
-                in.close();
-            } catch (IOException ioe) {
-            }
-        }
-    }
-
-    private String getFirstLine(ServletInputStream in, int len) throws ServletException, IOException {
-        StringBuffer buf = new StringBuffer(128);
-        int numBytes = 0;
-        int c = 0;
-        while ((c = in.read()) != -1) {
-            if (c == (int) '\n') break;
-            buf.append((char) c);
-            numBytes++;
-            if (numBytes > 512) {
-                log("First line is > 512 bytes [" + buf.toString() + "]");
-                return null;
-            }
-        }
-        log("First line: " + buf.toString());
-        return buf.toString();
-    }
-
-    private static Map getParameters(String line) {
-        //StringTokenizer tok = new StringTokenizer(line, "&=", true);
-        Map params = new HashMap();
-        while (line != null) {
-            String key = null;
-            String val = null;
-            int firstAmp = line.indexOf('&');
-            int firstEq = line.indexOf('=');
-            if (firstAmp > 0) {
-                key = line.substring(0, firstEq);
-                val = line.substring(firstEq + 1, firstAmp);
-                line = line.substring(firstAmp + 1);
-                params.put(key, val);
-            } else {
-                line = null;
-            }
-        }
-        return params;
-    }
-
-    private boolean isValidTarget(String target) throws IOException {
-        File identDir = getIdentDir(target);
-        if (identDir.exists()) {
-            File identFile = new File(identDir, "identity.dat");
-            if (identFile.exists()) {
-                // known and valid (maybe we need to check the file format... naw, fuck it
-                String files[] = identDir.list();
-                // we skip 1 because of identity.dat
-                if (files.length - 1 > _maxMessagesPerIdent) {
-                    log("Too many messages pending for " + target + ": " + (files.length - 1));
-                    return false;
-                } else {
-                    return true;
-                }
-            } else {
-                log("Ident directory exists, but identity does not... corrupt for " + target);
-                return false;
-            }
-        } else {
-            log("Unknown ident " + target);
-            return false;
-        }
-    }
-
-    private int saveFile(InputStream in, HttpServletResponse resp, String target, long len) throws IOException {
-        File identDir = getIdentDir(target);
-        if (!identDir.exists()) return -1;
-        try {
-            LockManager.lockIdent(target);
-            int i = 0;
-            while (true) {
-                File curFile = new File(identDir, "msg" + i + ".dat");
-                if (!curFile.exists()) {
-                    boolean ok = writeFile(curFile, in, len);
-                    if (ok)
-                        return i;
-                    else
-                        return -1;
-                }
-                i++;
-                continue;
-            }
-        } finally {
-            LockManager.unlockIdent(target);
-        }
-    }
-
-    private boolean writeFile(File file, InputStream in, long len) throws IOException {
-        long remaining = len;
-        FileOutputStream fos = null;
-        try {
-            fos = new FileOutputStream(file);
-            byte buf[] = new byte[4096];
-            while (remaining > 0) {
-                int read = in.read(buf);
-                if (read == -1) break;
-                remaining -= read;
-                if (read > 0) fos.write(buf, 0, read);
-            }
-        } finally {
-            if (fos != null) {
-                try {
-                    fos.close();
-                } catch (IOException ioe) {
-                }
-            }
-            if (remaining != 0) {
-                log("Invalid remaining bytes [" + remaining + " out of " + len
-                    + "] - perhaps message was cancelled partway through delivery?  deleting " + file.getAbsolutePath());
-                boolean deleted = file.delete();
-                if (!deleted) log("!!!Error deleting temporary file " + file.getAbsolutePath());
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private void sendSuccess(HttpServletRequest req, HttpServletResponse resp, String target, int msgId)
-                                                                                                        throws IOException {
-        ServletOutputStream out = resp.getOutputStream();
-        StringBuffer buf = new StringBuffer();
-        buf.append(PROP_STATUS).append('=').append(STATUS_OK).append('\n');
-        buf.append(PROP_CHECK_URL).append('=').append(buildURL(req, _checkPath));
-        buf.append('?');
-        buf.append(PARAM_SEND_TARGET).append('=').append(target).append("&");
-        buf.append(PARAM_MSG_ID).append('=').append(msgId).append("\n");
-        out.write(buf.toString().getBytes());
-        out.flush();
-    }
-
-    private void fail(HttpServletRequest req, HttpServletResponse resp, String err) throws IOException {
-        ServletOutputStream out = resp.getOutputStream();
-        StringBuffer buf = new StringBuffer();
-        buf.append(PROP_STATUS).append('=').append(STATUS_UNKNOWN).append('\n');
-        out.write(buf.toString().getBytes());
-        out.flush();
-    }
-
-    private void failSkewed(HttpServletRequest req, HttpServletResponse resp, long skew) throws IOException {
-        ServletOutputStream out = resp.getOutputStream();
-        StringBuffer buf = new StringBuffer();
-        buf.append(PROP_STATUS).append('=').append(STATUS_CLOCKSKEW).append(skew).append('\n');
-        out.write(buf.toString().getBytes());
-        out.flush();
-    }
-
-    public void init(ServletConfig config) throws ServletException {
-        super.init(config);
-
-        String checkPath = config.getInitParameter(PARAM_CHECK_PATH);
-        if (checkPath == null)
-            throw new ServletException("Check status path for the sending servlet required [" + PARAM_CHECK_PATH + "]");
-        else
-            _checkPath = checkPath;
-
-        String maxMessagesPerIdentStr = config.getInitParameter(PARAM_MAX_MESSAGES_PER_IDENT);
-        if (maxMessagesPerIdentStr == null)
-            throw new ServletException("Max messages per ident for the sending servlet required ["
-                                       + PARAM_MAX_MESSAGES_PER_IDENT + "]");
-        try {
-            _maxMessagesPerIdent = Integer.parseInt(maxMessagesPerIdentStr);
-        } catch (Throwable t) {
-            throw new ServletException("Valid max messages per ident for the sending servlet required ["
-                                       + PARAM_MAX_MESSAGES_PER_IDENT + "]");
-        }
-    }
-
-    public static void main(String args[]) {
-        String line = "target=pp0ARjQiB~IKC-0FsMUsPEMrwR3gxVBZGRYfEr1IzHI=&timeoutMs=52068&dataLength=2691&";
-        Map props = getParameters(line);
-        for (java.util.Iterator iter = props.keySet().iterator(); iter.hasNext();) {
-            String key = (String) iter.next();
-            String val = (String) props.get(key);
-            System.out.println("[" + key + "] = [" + val + "]");
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/phttprelay/java/web.xml b/apps/phttprelay/java/web.xml
deleted file mode 100644
index 8a82891fed..0000000000
--- a/apps/phttprelay/java/web.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!DOCTYPE web-app
-    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
-    "http://java.sun.com/dtd/web-app_2_3.dtd">
-
-
-<web-app>
-    <display-name>I2P Polling HTTP Relay</display-name>
-
-    <servlet>
-        <servlet-name>Register</servlet-name>
-        <servlet-class>net.i2p.phttprelay.RegisterServlet</servlet-class>
-        <init-param>
-            <param-name>pollPath</param-name>
-            <param-value>/phttpPoll</param-value>
-        </init-param>
-        <init-param>
-            <param-name>sendPath</param-name>
-            <param-value>/phttpSend</param-value>
-        </init-param>
-        <load-on-startup>1</load-on-startup>
-    </servlet>
-
-    <servlet>
-        <servlet-name>Send</servlet-name>
-        <servlet-class>net.i2p.phttprelay.SendServlet</servlet-class>
-        <init-param>
-            <param-name>checkPath</param-name>
-            <param-value>/phttpCheckSendStatus</param-value>
-        </init-param>
-        <init-param>
-            <param-name>maxMessagesPerIdent</param-name>
-            <param-value>100</param-value>
-        </init-param>
-        <load-on-startup>1</load-on-startup>
-    </servlet>
- 
-    <servlet>
-        <servlet-name>CheckSendStatus</servlet-name>
-        <servlet-class>net.i2p.phttprelay.CheckSendStatusServlet</servlet-class>
-        <load-on-startup>1</load-on-startup>
-    </servlet>
-    
-    <servlet>
-        <servlet-name>Poll</servlet-name>
-        <servlet-class>net.i2p.phttprelay.PollServlet</servlet-class>
-        <load-on-startup>1</load-on-startup>
-    </servlet>
-
-    <servlet-mapping>
-        <servlet-name>Register</servlet-name>
-        <url-pattern>/phttpRegister</url-pattern>
-    </servlet-mapping>
-
-    <servlet-mapping>
-        <servlet-name>Send</servlet-name>
-        <url-pattern>/phttpSend</url-pattern>
-    </servlet-mapping>
-
-    <servlet-mapping>
-        <servlet-name>CheckSendStatus</servlet-name>
-        <url-pattern>/phttpCheckSendStatus</url-pattern>
-    </servlet-mapping>
-
-    <servlet-mapping>
-        <servlet-name>Poll</servlet-name>
-        <url-pattern>/phttpPoll</url-pattern>
-    </servlet-mapping>
-
-</web-app>
diff --git a/apps/tests/COPYING b/apps/tests/COPYING
deleted file mode 100644
index 5ec43ee156..0000000000
--- a/apps/tests/COPYING
+++ /dev/null
@@ -1,278 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
diff --git a/apps/tests/EchoServer.java b/apps/tests/EchoServer.java
deleted file mode 100644
index 1ffe8f2e35..0000000000
--- a/apps/tests/EchoServer.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * A Minimal echo server.
- *
- * Copyright (c) 2004 Michael Schierl
- *
- * Licensed unter GNU General Public License.
- */
-
-import java.io.*;
-import java.net.*;
-
-public class EchoServer extends Thread {
-
-    public static void main(String[] args) throws IOException {
-        ServerSocket ss = new ServerSocket(Integer.parseInt(args[0]));
-        while (true) {
-            Socket s = ss.accept();
-            new EchoServer(s);
-        }
-    }
-
-    private Socket s;
-    
-    public EchoServer(Socket s) {
-        this.s=s;
-        start();
-    }
-
-    public void run() {
-        try {
-            InputStream in = s.getInputStream();
-            OutputStream out = s.getOutputStream();
-            byte[] b = new byte[4096];
-            int len;
-            while ((len = in.read(b)) != -1) {
-                out.write(b, 0, len);
-            }
-        } catch (SocketException ex) {
-            // nothing
-        } catch (IOException ex) {
-            ex.printStackTrace();
-        }
-    }
-}
diff --git a/apps/tests/GuaranteedBug.java b/apps/tests/GuaranteedBug.java
deleted file mode 100644
index 147b845267..0000000000
--- a/apps/tests/GuaranteedBug.java
+++ /dev/null
@@ -1,106 +0,0 @@
-// compile & run this file against i2p.jar
-
-import java.io.*;
-import java.util.*;
-import net.i2p.*;
-import net.i2p.client.*;
-import net.i2p.data.*;
-
-public class GuaranteedBug {
-
-
-    public void reproduce() {
-        try {
-            Destination d1 = null;
-            // first client (receiver)
-            if (true) { // smaller scope for variables ...
-                I2PClient client = I2PClientFactory.createClient();
-                ByteArrayOutputStream keyStream =
-                    new ByteArrayOutputStream(512);
-                d1 = client.createDestination(keyStream);
-                ByteArrayInputStream in =
-                    new ByteArrayInputStream(keyStream.toByteArray());
-                Properties opts = new Properties();
-                opts.setProperty(I2PClient.PROP_RELIABILITY,
-                                 I2PClient.PROP_RELIABILITY_GUARANTEED);
-                opts.setProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
-                opts.setProperty(I2PClient.PROP_TCP_PORT, "7654");
-                I2PSession session = client.createSession(in, opts);
-                session.connect();
-                session.setSessionListener(new PacketCounter());
-            }
-            // second client (sender)
-            I2PClient client = I2PClientFactory.createClient();
-            ByteArrayOutputStream keyStream = new ByteArrayOutputStream(512);
-            Destination d2 = client.createDestination(keyStream);
-            ByteArrayInputStream in =
-                new ByteArrayInputStream(keyStream.toByteArray());
-            Properties opts = new Properties();
-            opts.setProperty(I2PClient.PROP_RELIABILITY,
-                             I2PClient.PROP_RELIABILITY_GUARANTEED);
-            opts.setProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
-            opts.setProperty(I2PClient.PROP_TCP_PORT, "7654");
-            I2PSession session = client.createSession(in, opts);
-            session.connect();
-            session.setSessionListener(new DummyListener());
-            for (int i=0;i<1000; i++) {
-                byte[] msg = (""+i).getBytes("ISO-8859-1");
-                session.sendMessage(d1,msg);
-                System.out.println(">>"+i);
-            }
-        } catch (IOException ex) {
-            ex.printStackTrace();
-        } catch (I2PException ex) {
-            ex.printStackTrace();
-        }
-    }
-
-    public static void main(String[] args) {
-        new GuaranteedBug().reproduce();
-    }
-    
-    // -------------------------------------------------------
-    public class DummyListener implements I2PSessionListener {
-        public void disconnected(I2PSession session) {
-            System.err.println("Disconnected: "+session);
-        }
-    
-        public void errorOccurred(I2PSession session, String message,
-                                  Throwable error) {
-            System.err.println("Error: "+session+"/"+message);
-            error.printStackTrace();
-        }
-    
-        public void messageAvailable(I2PSession session, int msgId,
-                                     long size) {
-            System.err.println("Message here? "+session);
-        }
-    
-        public void reportAbuse(I2PSession session, int severity) {
-            System.err.println("Abuse: "+severity+"/"+session);
-        }
-    }
-
-    public class PacketCounter extends DummyListener {
-        private int lastPacket = -1;
-        public void messageAvailable(I2PSession session, int msgId,
-                                     long size) {
-            try {
-                byte msg[] = session.receiveMessage(msgId);
-                String m = new String(msg, "ISO-8859-1");
-                int no = Integer.parseInt(m);
-                if (no != ++lastPacket) {
-                    System.out.println("ERROR: <<"+no);
-                } else {
-                    System.out.println("<<"+no);
-                }
-            } catch (NumberFormatException ex) {
-                ex.printStackTrace();
-            } catch (I2PException ex) {
-                ex.printStackTrace();
-            } catch (IOException ex) {
-                ex.printStackTrace();
-            }    
-        }
-    }
-}
diff --git a/apps/tests/README b/apps/tests/README
deleted file mode 100644
index 83f17a4a88..0000000000
--- a/apps/tests/README
+++ /dev/null
@@ -1,6 +0,0 @@
-This directory is intended for tests which are useful for testing 
-I2P, but don't test any of the I2P components directly. Instead,
-tests are run on "application" level (TCP, IRC, HTTP etc.).
-
-IOW: These tests may be useful for any other project that allows 
-tunneling of "normal" protocols, not only I2P.
diff --git a/apps/tests/echotester/BasicEchoTestAnalyzer.java b/apps/tests/echotester/BasicEchoTestAnalyzer.java
deleted file mode 100644
index 577db8feb0..0000000000
--- a/apps/tests/echotester/BasicEchoTestAnalyzer.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * A basic implementation for the EchoTestAnalyzer.
- */
-public class BasicEchoTestAnalyzer implements EchoTestAnalyzer {
-
-    /**
-     * How many events must appear until a detailed report is
-     * printed. Default is every 20 events.
-     */
-    private static int REPORT_DELAY = 20;
-
-    private static int SUMMARY_SIZE = 100;
-
-    public BasicEchoTestAnalyzer() {
-        this(20, 100);
-    }
-
-    public BasicEchoTestAnalyzer(int reportDelay, int summarySize) {
-        REPORT_DELAY = reportDelay;
-        SUMMARY_SIZE = summarySize;
-    }
-
-    private int events = 0, packetLosses = 0, packetLossesDisconnect = 0, disconnects = 0, disconnectsRefused = 0,
-            delayCount = 0, lastDelayPtr = 0;
-    private long minDelay = Long.MAX_VALUE, maxDelay = 0, delaySum = 0;
-    private long[] lastDelays = new long[SUMMARY_SIZE];
-
-    public synchronized void packetLossOccurred(boolean beforeDisconnect) {
-        System.out.println("1: Packet lost" + (beforeDisconnect ? " before disconnect" : "") + ".");
-        packetLosses++;
-        if (beforeDisconnect) packetLossesDisconnect++;
-        countEvent();
-    }
-
-    public synchronized void successOccurred(long delay) {
-        System.out.println("0: Delay = " + delay);
-        if (delay > maxDelay) maxDelay = delay;
-        if (delay < minDelay) minDelay = delay;
-        delaySum += delay;
-        delayCount++;
-        lastDelays[lastDelayPtr++] = delay;
-        lastDelayPtr %= SUMMARY_SIZE;
-        countEvent();
-    }
-
-    public synchronized void disconnected(boolean refused) {
-        System.out.println("2: Disconnected" + (refused ? " (connection refused)" : "") + ".");
-        disconnects++;
-        if (refused) disconnectsRefused++;
-        countEvent();
-    }
-
-    private void countEvent() {
-        events++;
-        if (events % REPORT_DELAY == 0) {
-            int packets = packetLosses + delayCount;
-            long delaySummary = 0;
-            for (int i = 0; i < SUMMARY_SIZE; i++) {
-                delaySummary += lastDelays[i];
-            }
-            System.out.println("++++++++++++++++ ECHO STATISTICS +++++++++++++++++++++++++"
-                               + "\n++ Number of total echo messages: "
-                               + packets
-                               + "\n++ No response for "
-                               + packetLosses
-                               + "\n++    (of which "
-                               + packetLossesDisconnect
-                               + " due to a disconnect)"
-                               + "\n++ Disconnects: "
-                               + disconnects
-                               + "\n++    (of which "
-                               + disconnectsRefused
-                               + " due to 'connection refused')"
-                               + (disconnects > 0 || true ? "\n++ Average lost packets per disconnect: "
-                                                            + (packetLossesDisconnect / (float) disconnects) : "")
-                               + "\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
-                               + "\n++ Minimal delay: "
-                               + minDelay
-                               + "\n++ Average delay: "
-                               + (delaySum / (float) delayCount)
-                               + "\n++ Maximal delay: "
-                               + maxDelay
-                               + (delayCount >= SUMMARY_SIZE ? "\n++ Average delay over last " + SUMMARY_SIZE + ": "
-                                                               + (delaySummary / (float) SUMMARY_SIZE) : "")
-                               + "\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/tests/echotester/EchoTestAnalyzer.java b/apps/tests/echotester/EchoTestAnalyzer.java
deleted file mode 100644
index 96c5f715b7..0000000000
--- a/apps/tests/echotester/EchoTestAnalyzer.java
+++ /dev/null
@@ -1,17 +0,0 @@
-
-/**
- * A class that wants to analyze tests implements this interface. This
- * allows to "mix" several test values (from different echo servers)
- * as well as different algorithms for analyzing the data (for
- * jrandom: Strategy Pattern *g*).
- */
-public interface EchoTestAnalyzer {
-
-    public void packetLossOccurred(boolean beforeDisconnect);
-
-    public void successOccurred(long delay);
-
-    public void disconnected(boolean refused);
-
-}
-
diff --git a/apps/tests/echotester/EchoTester.java b/apps/tests/echotester/EchoTester.java
deleted file mode 100644
index 750ccb7ba6..0000000000
--- a/apps/tests/echotester/EchoTester.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Test for an echo server. This test is intended to be used via an
- * I2PTunnel, but should work as well on other networks that provide
- * TCP tunneling and an echo server.
- *
- * Copyright (c) 2004 Michael Schierl
- *
- * Licensed unter GNU General Public License.
- */
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.net.ConnectException;
-import java.net.Socket;
-import java.net.SocketException;
-
-/**
- * The main engine for the EchoTester.
- */
-public class EchoTester extends Thread {
-
-    /**
-     * How long to wait between packets. Default is 6 seconds.
-     */
-    private static long PACKET_DELAY = 6000;
-
-    /**
-     * How many packets may be on the way before the connection is
-     * seen as "broken" and disconnected.
-     */
-    private static final long MAX_PACKETS_QUEUED = 50; // unused
-
-    private EchoTestAnalyzer eta;
-    private String host;
-    private int port;
-
-    // the following vars are synchronized via the lock.
-    private Object lock = new Object();
-    private long nextPacket = 0;
-    private long nextUnreceived = 0;
-    private boolean readerRunning = false;
-
-    public static void main(String[] args) {
-        if (args.length == 3) PACKET_DELAY = Long.parseLong(args[2]);
-        new EchoTester(args[0], Integer.parseInt(args[1]), new BasicEchoTestAnalyzer());
-    }
-
-    public EchoTester(String host, int port, EchoTestAnalyzer eta) {
-        this.eta = eta;
-        this.host = host;
-        this.port = port;
-        start();
-    }
-
-    public void run() {
-        try {
-            while (true) {
-                Socket s;
-                try {
-                    s = new Socket(host, port);
-                } catch (ConnectException ex) {
-                    eta.disconnected(true);
-                    Thread.sleep(PACKET_DELAY);
-                    continue;
-                }
-                System.out.println("41: Connected to " + host + ":" + port);
-                synchronized (lock) {
-                    nextUnreceived = nextPacket;
-                }
-                Thread t = new ResponseReaderThread(s);
-                Writer w = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
-                while (true) {
-                    long no;
-                    synchronized (lock) {
-                        no = nextPacket++;
-                    }
-                    try {
-                        w.write(no + " " + System.currentTimeMillis() + "\n");
-                        w.flush();
-                    } catch (SocketException ex) {
-                        break;
-                    }
-                    Thread.sleep(PACKET_DELAY);
-                }
-                s.close();
-                t.join();
-                synchronized (lock) {
-                    if (readerRunning) {
-                        System.out.println("*** WHY IS THIS THREAD STILL" + " RUNNING?");
-                    }
-                    while (nextUnreceived < nextPacket) {
-                        nextUnreceived++;
-                        eta.packetLossOccurred(true);
-                    }
-                    if (nextUnreceived > nextPacket) {
-                        System.out.println("*** WTF? " + nextUnreceived + " > " + nextPacket);
-                    }
-                }
-                eta.disconnected(false);
-            }
-        } catch (InterruptedException ex) {
-            ex.printStackTrace();
-            System.exit(1); // treat these errors as fatal          
-        } catch (IOException ex) {
-            ex.printStackTrace();
-            System.exit(1); // treat these errors as fatal
-        }
-
-    }
-
-    private class ResponseReaderThread extends Thread {
-
-        private Socket s;
-
-        public ResponseReaderThread(Socket s) {
-            this.s = s;
-            synchronized (lock) {
-                readerRunning = true;
-            }
-            start();
-        }
-
-        public void run() {
-            try {
-                BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
-                String line;
-                int index;
-                while ((line = br.readLine()) != null) {
-                    if ((index = line.indexOf(" ")) == -1) continue;
-                    long now, packetNumber, packetTime;
-                    now = System.currentTimeMillis();
-                    try {
-                        packetNumber = Long.parseLong(line.substring(0, index));
-                        packetTime = Long.parseLong(line.substring(index + 1));
-                    } catch (NumberFormatException ex) {
-                        System.out.println(ex.toString());
-                        continue;
-                    }
-                    synchronized (lock) {
-                        while (packetNumber > nextUnreceived) {
-                            nextUnreceived++;
-                            eta.packetLossOccurred(false);
-                        }
-                        if (nextUnreceived > packetNumber) {
-                            System.out.println("*** DOUBLE PACKET!");
-                        } else {
-                            nextUnreceived++;
-                        }
-                    }
-                    eta.successOccurred(now - packetTime);
-                }
-            } catch (SocketException ex) {
-                // ignore
-            } catch (IOException ex) {
-                ex.printStackTrace();
-                System.exit(0);
-            }
-            synchronized (lock) {
-                readerRunning = false;
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/apps/tests/readme.license.txt b/apps/tests/readme.license.txt
deleted file mode 100644
index 4c14112cb0..0000000000
--- a/apps/tests/readme.license.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-$Id$
-
-the i2p/apps/tests module is the root of application
-level tests, and everything within it is released 
-according to the terms of the I2P license policy.  
-That means everything contained within the 
-i2p/apps/tests module is released into the public 
-domain unless otherwise marked.  Alternate licenses 
-that may be used include GPL, GPL + java exception, 
-BSD, Cryptix, and MIT.
-- 
GitLab