Author: toad
Date: 2008-11-06 13:53:57 +0000 (Thu, 06 Nov 2008)
New Revision: 23351

Added:
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue/
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue/theme.css
   trunk/freenet/src/freenet/node/BandwidthUsageHistory.java
   trunk/freenet/src/freenet/support/compress/Bzip2Compressor.java
   trunk/freenet/src/freenet/support/compress/CompressJob.java
   trunk/freenet/src/freenet/support/compress/LZMACompressor.java
   trunk/freenet/src/freenet/support/compress/RealCompressor.java
   trunk/freenet/src/net/
   trunk/freenet/src/net/i2p/
   trunk/freenet/src/net/i2p/util/
   trunk/freenet/src/net/i2p/util/NativeBigInteger.java
   trunk/freenet/test/freenet/support/compress/Bzip2CompressorTest.java
   trunk/freenet/test/freenet/support/io/ArrayBucketTest.java
   trunk/freenet/test/freenet/support/io/BucketTestBase.java
   
trunk/freenet/test/freenet/support/io/PaddedEphemerallyEncryptedBucketTest.java
   trunk/freenet/test/freenet/support/io/TempFileBucketTest.java
   trunk/freenet/test/net/
   trunk/freenet/test/net/i2p/
   trunk/freenet/test/net/i2p/util/
   trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java
Removed:
   trunk/freenet/src/freenet/client/SplitFetchException.java
   trunk/freenet/src/freenet/client/StartableSplitfileBlock.java
   trunk/freenet/src/freenet/client/events/BlockInsertErrorEvent.java
   trunk/freenet/src/freenet/client/events/DecodedBlockEvent.java
   trunk/freenet/src/freenet/client/events/FetchedMetadataEvent.java
   trunk/freenet/src/freenet/client/events/GeneratedURIEvent.java
   trunk/freenet/src/freenet/client/events/GotBlockEvent.java
   trunk/freenet/src/freenet/client/events/SimpleBlockPutEvent.java
   trunk/freenet/src/freenet/clients/http/TrivialToadlet.java
   trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategories.java
   trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItems.java
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue/theme.css
   trunk/freenet/src/freenet/crypt/CipherInputStream.java
   trunk/freenet/src/freenet/crypt/CipherModes.java
   trunk/freenet/src/freenet/crypt/CipherOutputStream.java
   trunk/freenet/src/freenet/crypt/DecipherOutputStream.java
   trunk/freenet/src/freenet/crypt/DecryptionFailedException.java
   trunk/freenet/src/freenet/crypt/DigestInputStream.java
   trunk/freenet/src/freenet/crypt/DigestOutputStream.java
   trunk/freenet/src/freenet/crypt/EncipherInputStream.java
   trunk/freenet/src/freenet/crypt/KEProtocol.java
   trunk/freenet/src/freenet/crypt/UnsupportedDigestException.java
   trunk/freenet/src/freenet/io/comm/DumpDispatcher.java
   trunk/freenet/src/freenet/node/CPUAdjustingSwapRequestInterval.java
   trunk/freenet/src/freenet/node/CPUUsageMonitor.java
   trunk/freenet/src/freenet/node/DSAPublicKeyDatabase.java
   trunk/freenet/src/freenet/node/StaticSwapRequestInterval.java
   trunk/freenet/src/freenet/node/SwapRequestInterval.java
   trunk/freenet/src/freenet/node/updater/PrivkeyHasBeenBlownException.java
   trunk/freenet/src/freenet/node/useralerts/OpennetUserAlert.java
   trunk/freenet/src/freenet/plugin/api/FreenetPlugin.java
   trunk/freenet/src/freenet/plugin/api/FreenetPluginManager.java
   trunk/freenet/src/freenet/plugin/api/NeedsConfig.java
   trunk/freenet/src/freenet/plugin/api/NeedsSimpleKeyFetch.java
   trunk/freenet/src/freenet/plugin/api/NeedsTempBuckets.java
   trunk/freenet/src/freenet/plugin/api/NeedsWebInterfaceGeneric.java
   trunk/freenet/src/freenet/plugin/api/NeedsWebInterfaceHTMLString.java
   trunk/freenet/src/freenet/plugin/api/PluginFetchException.java
   trunk/freenet/src/freenet/plugin/api/PluginFetchResult.java
   trunk/freenet/src/freenet/plugin/api/PluginFreenetURI.java
   trunk/freenet/src/freenet/plugin/api/ProvidesSimpleKeyFetch.java
   trunk/freenet/src/freenet/plugin/api/package-info.java
   trunk/freenet/src/freenet/pluginmanager/FredPluginToadlet.java
   trunk/freenet/src/freenet/pluginmanager/PluginSecurityException.java
   trunk/freenet/src/freenet/support/DoubleTokenBucket.java
   trunk/freenet/src/freenet/support/NumberedItem.java
   trunk/freenet/src/freenet/support/NumberedItemComparator.java
   trunk/freenet/src/freenet/support/NumberedRecentItems.java
   trunk/freenet/src/freenet/support/RandomGrabArrayWithInt.java
   trunk/freenet/src/freenet/support/api/BaseSubConfig.java
   trunk/freenet/src/freenet/support/api/HTTPReply.java
   trunk/freenet/src/freenet/support/compress/DecompressException.java
   trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java
   trunk/freenet/src/net/
   trunk/freenet/src/net/i2p/
   trunk/freenet/src/net/i2p/util/
   trunk/freenet/src/net/i2p/util/NativeBigInteger.java
   trunk/freenet/test/net/
   trunk/freenet/test/net/i2p/
   trunk/freenet/test/net/i2p/util/
   trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java
Modified:
   trunk/freenet/.classpath
   trunk/freenet/src/freenet/client/ArchiveManager.java
   trunk/freenet/src/freenet/client/ArchiveStoreContext.java
   trunk/freenet/src/freenet/client/ClientMetadata.java
   trunk/freenet/src/freenet/client/FECCodec.java
   trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
   trunk/freenet/src/freenet/client/InsertContext.java
   trunk/freenet/src/freenet/client/Metadata.java
   trunk/freenet/src/freenet/client/async/ClientPutter.java
   trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
   trunk/freenet/src/freenet/client/async/ClientRequester.java
   trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
   trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
   trunk/freenet/src/freenet/client/async/SingleFileInserter.java
   trunk/freenet/src/freenet/client/async/SplitFileInserter.java
   trunk/freenet/src/freenet/client/events/StartedCompressionEvent.java
   trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java
   trunk/freenet/src/freenet/clients/http/BrowserTestToadlet.java
   trunk/freenet/src/freenet/clients/http/ConfigToadlet.java
   trunk/freenet/src/freenet/clients/http/ConnectionsToadlet.java
   trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
   trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
   trunk/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java
   trunk/freenet/src/freenet/clients/http/HTTPRequestImpl.java
   trunk/freenet/src/freenet/clients/http/LocalFileInsertToadlet.java
   trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java
   trunk/freenet/src/freenet/clients/http/OpennetConnectionsToadlet.java
   trunk/freenet/src/freenet/clients/http/PageMaker.java
   trunk/freenet/src/freenet/clients/http/PproxyToadlet.java
   trunk/freenet/src/freenet/clients/http/QueueToadlet.java
   trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
   trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java
   trunk/freenet/src/freenet/clients/http/SymlinkerToadlet.java
   trunk/freenet/src/freenet/clients/http/Toadlet.java
   trunk/freenet/src/freenet/clients/http/ToadletContext.java
   trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java
   trunk/freenet/src/freenet/clients/http/TranslationToadlet.java
   trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java
   trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java
   trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java
   trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/bookmark-new.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/cut.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/delete.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/edit.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/folder-new.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/go-down.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/go-up.png
   trunk/freenet/src/freenet/clients/http/staticfiles/icon/paste.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/background.png
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/logo.png
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/clean/logo.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/alert-16.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/alert.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/error-16.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/error.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/fail.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/information-16.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/information.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/logo.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/query.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/success.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/warning-16.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/warning.png
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/alert-16.png
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/error-16.png
   
trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/information-16.png
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/logo.png
   trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/warning-16.png
   trunk/freenet/src/freenet/config/EnumerableOptionCallback.java
   trunk/freenet/src/freenet/crypt/DSAGroup.java
   trunk/freenet/src/freenet/crypt/DiffieHellman.java
   trunk/freenet/src/freenet/crypt/HMAC.java
   trunk/freenet/src/freenet/crypt/RandomSource.java
   trunk/freenet/src/freenet/crypt/SHA256.java
   trunk/freenet/src/freenet/crypt/Yarrow.java
   trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Algorithm.java
   trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Properties.java
   trunk/freenet/src/freenet/io/AddressTracker.java
   trunk/freenet/src/freenet/io/AllowedHosts.java
   trunk/freenet/src/freenet/io/NetworkInterface.java
   trunk/freenet/src/freenet/io/comm/DMT.java
   trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java
   trunk/freenet/src/freenet/io/comm/IOStatisticCollector.java
   trunk/freenet/src/freenet/io/comm/Message.java
   trunk/freenet/src/freenet/io/comm/MessageCore.java
   trunk/freenet/src/freenet/io/comm/MessageFilter.java
   trunk/freenet/src/freenet/io/comm/MessageType.java
   trunk/freenet/src/freenet/io/comm/PeerContext.java
   trunk/freenet/src/freenet/io/comm/UdpSocketHandler.java
   trunk/freenet/src/freenet/io/xfer/BlockReceiver.java
   trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java
   trunk/freenet/src/freenet/io/xfer/PacketThrottle.java
   trunk/freenet/src/freenet/io/xfer/PartiallyReceivedBlock.java
   trunk/freenet/src/freenet/io/xfer/WaitedTooLongException.java
   trunk/freenet/src/freenet/keys/FreenetURI.java
   trunk/freenet/src/freenet/keys/Key.java
   trunk/freenet/src/freenet/l10n/freenet.l10n.de.properties
   trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
   trunk/freenet/src/freenet/l10n/freenet.l10n.fi.properties
   trunk/freenet/src/freenet/l10n/freenet.l10n.it.properties
   trunk/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties
   trunk/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties
   trunk/freenet/src/freenet/node/Announcer.java
   trunk/freenet/src/freenet/node/CHKInsertSender.java
   trunk/freenet/src/freenet/node/DarknetPeerNode.java
   trunk/freenet/src/freenet/node/FNPPacketMangler.java
   trunk/freenet/src/freenet/node/FailureTable.java
   trunk/freenet/src/freenet/node/FailureTableEntry.java
   trunk/freenet/src/freenet/node/GlobalProbe.java
   trunk/freenet/src/freenet/node/IPDetectorPluginManager.java
   trunk/freenet/src/freenet/node/KeyTracker.java
   trunk/freenet/src/freenet/node/LocationManager.java
   trunk/freenet/src/freenet/node/LoggingConfigHandler.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/NodeCryptoConfig.java
   trunk/freenet/src/freenet/node/NodeIPDetector.java
   trunk/freenet/src/freenet/node/NodeIPPortDetector.java
   trunk/freenet/src/freenet/node/PacketSender.java
   trunk/freenet/src/freenet/node/PeerManager.java
   trunk/freenet/src/freenet/node/PeerNode.java
   trunk/freenet/src/freenet/node/PeerNodeStatus.java
   trunk/freenet/src/freenet/node/RequestSender.java
   trunk/freenet/src/freenet/node/RequestStarter.java
   trunk/freenet/src/freenet/node/RequestStarterGroup.java
   trunk/freenet/src/freenet/node/ResettingHTLProbeRequestSender.java
   trunk/freenet/src/freenet/node/SSKInsertSender.java
   trunk/freenet/src/freenet/node/SecurityLevels.java
   trunk/freenet/src/freenet/node/SeedServerPeerNode.java
   trunk/freenet/src/freenet/node/SemiOrderedShutdownHook.java
   trunk/freenet/src/freenet/node/SyncSendWaitedTooLongException.java
   trunk/freenet/src/freenet/node/TextModeClientInterface.java
   trunk/freenet/src/freenet/node/TextModeClientInterfaceServer.java
   trunk/freenet/src/freenet/node/UptimeEstimator.java
   trunk/freenet/src/freenet/node/Version.java
   trunk/freenet/src/freenet/node/fcp/ClientGet.java
   trunk/freenet/src/freenet/node/fcp/ClientPut.java
   trunk/freenet/src/freenet/node/fcp/NodeHelloMessage.java
   trunk/freenet/src/freenet/node/fcp/StartedCompressionMessage.java
   trunk/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java
   trunk/freenet/src/freenet/node/simulator/SeednodePingTest.java
   trunk/freenet/src/freenet/pluginmanager/FredPluginHTTP.java
   trunk/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
   trunk/freenet/src/freenet/support/DoublyLinkedList.java
   trunk/freenet/src/freenet/support/DoublyLinkedListImpl.java
   trunk/freenet/src/freenet/support/FileLoggerHook.java
   trunk/freenet/src/freenet/support/MultiValueTable.java
   trunk/freenet/src/freenet/support/UpdatableSortedLinkedList.java
   trunk/freenet/src/freenet/support/UpdatableSortedLinkedListItemImpl.java
   
trunk/freenet/src/freenet/support/UpdatableSortedLinkedListWithForeignIndex.java
   trunk/freenet/src/freenet/support/compress/Compressor.java
   trunk/freenet/src/freenet/support/compress/GzipCompressor.java
   trunk/freenet/src/freenet/support/io/ArrayBucket.java
   trunk/freenet/src/freenet/support/io/FileBucket.java
   trunk/freenet/src/freenet/support/io/NullBucket.java
   trunk/freenet/src/freenet/support/io/NullPersistentFileTracker.java
   trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java
   trunk/freenet/src/freenet/support/math/SimpleRunningAverage.java
   trunk/freenet/test/freenet/support/MultiValueTableTest.java
   trunk/freenet/test/freenet/support/compress/GzipCompressorTest.java
Log:
Restore trunk.


Modified: trunk/freenet/.classpath
===================================================================
--- trunk/freenet/.classpath    2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/.classpath    2008-11-06 13:53:57 UTC (rev 23351)
@@ -2,8 +2,8 @@
 <classpath>
        <classpathentry 
excluding="freenet/node/*Test.java|plugins/JSTUN/**|test/**" kind="src" 
path="src"/>
        <classpathentry including="freenet/|org/" kind="src" path="test"/>
-       <classpathentry exported="true" kind="lib" path="lib/freenet-ext.jar"/>
        <classpathentry kind="con" 
path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
        <classpathentry kind="lib" path="/usr/share/java/junit.jar"/>
+       <classpathentry kind="lib" path="lib/freenet-ext.jar"/>
        <classpathentry kind="output" path="bin"/>
 </classpath>

Modified: trunk/freenet/src/freenet/client/ArchiveManager.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveManager.java        2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/ArchiveManager.java        2008-11-06 
13:53:57 UTC (rev 23351)
@@ -18,7 +18,15 @@
 import freenet.support.MutableBoolean;
 import freenet.support.api.Bucket;
 import freenet.support.api.BucketFactory;
+import freenet.support.compress.Compressor.COMPRESSOR_TYPE;
 import freenet.support.io.BucketTools;
+import freenet.support.io.Closer;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+import net.contrapunctus.lzma.LzmaInputStream;
+import org.apache.tools.bzip2.CBZip2InputStream;
+import org.apache.tools.tar.TarEntry;
+import org.apache.tools.tar.TarInputStream;

 /**
  * Cache of recently decoded archives:
@@ -34,6 +42,59 @@
        public static final String METADATA_NAME = ".metadata";
        private static boolean logMINOR;

+       public enum ARCHIVE_TYPE {
+               ZIP((short)0, new String[] { "application/zip", 
"application/x-zip" }),         /* eventually get rid of ZIP support at some 
point */
+               TAR((short)1, new String[] { "application/x-tar" });
+               
+               public final short metadataID;
+               public final String[] mimeTypes;
+               
+               private ARCHIVE_TYPE(short metadataID, String[] mimeTypes) {
+                       this.metadataID = metadataID;
+                       this.mimeTypes = mimeTypes;
+               }
+               
+               public static boolean isValidMetadataID(short id) {
+                       for(ARCHIVE_TYPE current : values())
+                               if(id == current.metadataID)
+                                       return true;
+                       return false;
+               }
+
+               /**
+                * Is the given MIME type an archive type that we can deal with?
+                */
+               public static boolean isUsableArchiveType(String type) {
+                       for(ARCHIVE_TYPE current : values())
+                               for(String ctype : current.mimeTypes)
+                                       if(ctype.equalsIgnoreCase(type))
+                                               return true;
+                       return false;
+               }
+
+               /** If the given MIME type is an archive type that we can deal 
with,
+                * get its archive type number (see the ARCHIVE_ constants in 
Metadata).
+                */
+               public static ARCHIVE_TYPE getArchiveType(String type) {
+                       for(ARCHIVE_TYPE current : values())
+                               for(String ctype : current.mimeTypes)
+                                       if(ctype.equalsIgnoreCase(type))
+                                               return current;
+                       return null;
+               }
+               
+               public static ARCHIVE_TYPE getArchiveType(short type) {
+                       for(ARCHIVE_TYPE current : values())
+                               if(current.metadataID == type)
+                                       return current;
+                       return null;
+               }
+               
+               public final static ARCHIVE_TYPE getDefault() {
+                       return TAR;
+               }
+       }
+       
        final long maxArchivedFileSize;

        // ArchiveHandler's
@@ -104,12 +165,12 @@
         * @param archiveType The archive type, defined in Metadata.
         * @return An archive handler. 
         */
-       public synchronized ArchiveHandler makeHandler(FreenetURI key, short 
archiveType, boolean returnNullIfNotFound, boolean forceRefetchArchive) {
+       public synchronized ArchiveHandler makeHandler(FreenetURI key, 
ARCHIVE_TYPE archiveType, COMPRESSOR_TYPE ctype, boolean returnNullIfNotFound, 
boolean forceRefetchArchive) {
                ArchiveHandler handler = null;
                if(!forceRefetchArchive) handler = getCached(key);
                if(handler != null) return handler;
                if(returnNullIfNotFound) return null;
-               handler = new ArchiveStoreContext(this, key, archiveType, 
forceRefetchArchive);
+               handler = new ArchiveStoreContext(this, key, archiveType, 
ctype, forceRefetchArchive);
                putCached(key, handler);
                return handler;
        }
@@ -154,7 +215,7 @@
        /**
         * Extract data to cache. Call synchronized on ctx.
         * @param key The key the data was fetched from.
-        * @param archiveType The archive type. Must be Metadata.ARCHIVE_ZIP.
+        * @param archiveType The archive type. Must be Metadata.ARCHIVE_ZIP | 
Metadata.ARCHIVE_TAR.
         * @param data The actual data fetched.
         * @param archiveContext The context for the whole fetch process.
         * @param ctx The ArchiveStoreContext for this key.
@@ -165,7 +226,7 @@
         * @throws ArchiveRestartException If the request needs to be restarted 
because the archive
         * changed.
         */
-       public void extractToCache(FreenetURI key, short archiveType, Bucket 
data, ArchiveContext archiveContext, ArchiveStoreContext ctx, String element, 
ArchiveExtractCallback callback) throws ArchiveFailureException, 
ArchiveRestartException {
+       public void extractToCache(FreenetURI key, ARCHIVE_TYPE archiveType, 
COMPRESSOR_TYPE ctype, Bucket data, ArchiveContext archiveContext, 
ArchiveStoreContext ctx, String element, ArchiveExtractCallback callback) 
throws ArchiveFailureException, ArchiveRestartException {

                logMINOR = Logger.shouldLog(Logger.MINOR, this);

@@ -198,12 +259,111 @@
                }
                if(data.size() > archiveContext.maxArchiveSize)
                        throw new ArchiveFailureException("Archive too big 
("+data.size()+" > "+archiveContext.maxArchiveSize+")!");
-               if(archiveType != Metadata.ARCHIVE_ZIP)
-                       throw new ArchiveFailureException("Unknown or 
unsupported archive algorithm "+archiveType);

+               
+               InputStream is = null;
+               try {
+                       if((ctype == null) || (ARCHIVE_TYPE.ZIP == 
archiveType)) {
+                               if(logMINOR) Logger.minor(this, "No 
compression");
+                               is = data.getInputStream();
+                       } else if(ctype == COMPRESSOR_TYPE.BZIP2) {
+                               if(logMINOR) Logger.minor(this, "dealing with 
BZIP2");
+                               is = new 
CBZip2InputStream(data.getInputStream());
+                       } else if(ctype == COMPRESSOR_TYPE.GZIP) {
+                               if(logMINOR) Logger.minor(this, "dealing with 
GZIP");
+                               is = new GZIPInputStream(data.getInputStream());
+                       } else if(ctype == COMPRESSOR_TYPE.LZMA) {
+                               if(logMINOR) Logger.minor(this, "dealing with 
LZMA");
+                               is = new LzmaInputStream(data.getInputStream());
+                       }
+                       
+                       if(ARCHIVE_TYPE.ZIP == archiveType)
+                               handleZIPArchive(ctx, key, is, element, 
callback, gotElement, throwAtExit);
+                       else if(ARCHIVE_TYPE.TAR == archiveType)
+                               handleTARArchive(ctx, key, is, element, 
callback, gotElement, throwAtExit);
+               else
+                               throw new ArchiveFailureException("Unknown or 
unsupported archive algorithm " + archiveType);
+               } catch (IOException ioe) {
+                       throw new ArchiveFailureException("An IOE occured: 
"+ioe.getMessage(), ioe);
+               }finally {
+                       Closer.close(is);
+       }
+       }
+       
+       private void handleTARArchive(ArchiveStoreContext ctx, FreenetURI key, 
InputStream data, String element, ArchiveExtractCallback callback, 
MutableBoolean gotElement, boolean throwAtExit) throws ArchiveFailureException, 
ArchiveRestartException {
+               if(logMINOR) Logger.minor(this, "Handling a TAR Archive");
+               TarInputStream tarIS = null;
+               try {
+                       tarIS = new TarInputStream(data);
+                       
+                       // MINOR: Assumes the first entry in the tarball is a 
directory. 
+                       TarEntry entry;
+                       
+                       byte[] buf = new byte[32768];
+                       HashSet names = new HashSet();
+                       boolean gotMetadata = false;
+                       
+outerTAR:              while(true) {
+                               entry = tarIS.getNextEntry();
+                               if(entry == null) break;
+                               if(entry.isDirectory()) continue;
+                               String name = entry.getName();
+                               if(names.contains(name)) {
+                                       Logger.error(this, "Duplicate key 
"+name+" in archive "+key);
+                                       continue;
+                               }
+                               long size = entry.getSize();
+                               if(size > maxArchivedFileSize) {
+                                       addErrorElement(ctx, key, name, "File 
too big: "+maxArchivedFileSize+" greater than current archived file size limit 
"+maxArchivedFileSize);
+                               } else {
+                                       // Read the element
+                                       long realLen = 0;
+                                       Bucket output = 
tempBucketFactory.makeBucket(size);
+                                       OutputStream out = 
output.getOutputStream();
+
+                                       int readBytes;
+                                       while((readBytes = tarIS.read(buf)) > 
0) {
+                                               out.write(buf, 0, readBytes);
+                                               readBytes += realLen;
+                                               if(readBytes > 
maxArchivedFileSize) {
+                                                       addErrorElement(ctx, 
key, name, "File too big: "+maxArchivedFileSize+" greater than current archived 
file size limit "+maxArchivedFileSize);
+                                                       out.close();
+                                                       output.free();
+                                                       continue outerTAR;
+                                               }
+                                       }
+
+                                       out.close();
+                                       if(name.equals(".metadata"))
+                                               gotMetadata = true;
+                                       addStoreElement(ctx, key, name, output, 
gotElement, element, callback);
+                                       names.add(name);
+                                       trimStoredData();
+                               }
+                       }
+
+                       // If no metadata, generate some
+                       if(!gotMetadata) {
+                               generateMetadata(ctx, key, names, gotElement, 
element, callback);
+                               trimStoredData();
+                       }
+                       if(throwAtExit) throw new 
ArchiveRestartException("Archive changed on re-fetch");
+                       
+                       if((!gotElement.value) && element != null)
+                               callback.notInArchive();
+                       
+               } catch (IOException e) {
+                       throw new ArchiveFailureException("Error reading 
archive: "+e.getMessage(), e);
+               } finally {
+                       Closer.close(tarIS);
+               }
+       }
+       
+       private void handleZIPArchive(ArchiveStoreContext ctx, FreenetURI key, 
InputStream data, String element, ArchiveExtractCallback callback, 
MutableBoolean gotElement, boolean throwAtExit) throws ArchiveFailureException, 
ArchiveRestartException {
+               if(logMINOR) Logger.minor(this, "Handling a ZIP Archive");
                ZipInputStream zis = null;
                try {
-                       zis = new ZipInputStream(data.getInputStream());
+                       zis = new ZipInputStream(data);

                        // MINOR: Assumes the first entry in the zip is a 
directory. 
                        ZipEntry entry;
@@ -212,7 +372,7 @@
                        HashSet names = new HashSet();
                        boolean gotMetadata = false;

-outer:         while(true) {
+outerZIP:              while(true) {
                                entry = zis.getNextEntry();
                                if(entry == null) break;
                                if(entry.isDirectory()) continue;
@@ -238,7 +398,7 @@
                                                        addErrorElement(ctx, 
key, name, "File too big: "+maxArchivedFileSize+" greater than current archived 
file size limit "+maxArchivedFileSize);
                                                        out.close();
                                                        output.free();
-                                                       continue outer;
+                                                       continue outerZIP;
                                                }
                                        }

@@ -452,21 +612,4 @@
                }
                }
        }
-
-       /**
-        * Is the given MIME type an archive type that we can deal with?
-        */
-       public static boolean isUsableArchiveType(String type) {
-               return type.equals("application/zip") || 
type.equals("application/x-zip");
-               // Update when add new archive types
-       }
-
-       /** If the given MIME type is an archive type that we can deal with,
-        * get its archive type number (see the ARCHIVE_ constants in Metadata).
-        */
-       public static short getArchiveType(String type) {
-               if(type.equals("application/zip") || 
type.equals("application/x-zip"))
-                       return Metadata.ARCHIVE_ZIP;
-               else throw new IllegalArgumentException(); 
-       }
 }

Modified: trunk/freenet/src/freenet/client/ArchiveStoreContext.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveStoreContext.java   2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/ArchiveStoreContext.java   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -7,6 +7,7 @@
 import freenet.support.DoublyLinkedListImpl;
 import freenet.support.Logger;
 import freenet.support.api.Bucket;
+import freenet.support.compress.Compressor.COMPRESSOR_TYPE;

 /**
  * Tracks all files currently in the cache from a given key.
@@ -24,7 +25,8 @@

        private ArchiveManager manager;
        private FreenetURI key;
-       private short archiveType;
+       private final ArchiveManager.ARCHIVE_TYPE archiveType;
+       private final COMPRESSOR_TYPE compressorType;
        private boolean forceRefetchArchive;
        /** Archive size */
        private long lastSize = -1;
@@ -36,10 +38,11 @@
         * the inner lock to avoid deadlocks. */
        private final DoublyLinkedListImpl myItems;

-       public ArchiveStoreContext(ArchiveManager manager, FreenetURI key, 
short archiveType, boolean forceRefetchArchive) {
+       public ArchiveStoreContext(ArchiveManager manager, FreenetURI key, 
ArchiveManager.ARCHIVE_TYPE archiveType, COMPRESSOR_TYPE ctype, boolean 
forceRefetchArchive) {
                this.manager = manager;
                this.key = key;
                this.archiveType = archiveType;
+               this.compressorType = ctype;
                myItems = new DoublyLinkedListImpl();
                this.forceRefetchArchive = forceRefetchArchive;
        }
@@ -131,7 +134,7 @@
        }

        public short getArchiveType() {
-               return archiveType;
+               return archiveType.metadataID;
        }

        public FreenetURI getKey() {
@@ -139,7 +142,7 @@
        }

        public void extractToCache(Bucket bucket, ArchiveContext actx, String 
element, ArchiveExtractCallback callback) throws ArchiveFailureException, 
ArchiveRestartException {
-               manager.extractToCache(key, archiveType, bucket, actx, this, 
element, callback);
+               manager.extractToCache(key, archiveType, compressorType, 
bucket, actx, this, element, callback);
        }

        /** Called just before extracting this container to the cache */

Modified: trunk/freenet/src/freenet/client/ClientMetadata.java
===================================================================
--- trunk/freenet/src/freenet/client/ClientMetadata.java        2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/ClientMetadata.java        2008-11-06 
13:53:57 UTC (rev 23351)
@@ -11,14 +11,13 @@
        /** The document MIME type */
        private String mimeType;

+       public ClientMetadata(){
+               mimeType = null;
+       }
+
        public ClientMetadata(String mime) {
                mimeType = (mime == null) ? null : mime.intern();
        }
-
-       /** Create an empty ClientMetadata instance */
-       public ClientMetadata() {
-               mimeType = null;
-       }

        /** Get the document MIME type. Will always be a valid MIME type, 
unless there
         * has been an error; if it is unknown, will return 
application/octet-stream. */

Modified: trunk/freenet/src/freenet/client/FECCodec.java
===================================================================
--- trunk/freenet/src/freenet/client/FECCodec.java      2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/client/FECCodec.java      2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -347,7 +347,7 @@
                synchronized(_awaitingJobs) {
                        _awaitingJobs.addFirst(job);
                        if(runningFECThreads < maxThreads) {
-                               executor.execute(fecRunner, "FEC Pool 
"+fecPoolCounter++);
+                               executor.execute(fecRunner, "FEC Pool(" + 
(fecPoolCounter++) + ")");
                                runningFECThreads++;
                        }
                        _awaitingJobs.notifyAll();

Modified: trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2008-11-06 13:53:57 UTC (rev 23351)
@@ -166,7 +166,7 @@
        }

        public FreenetURI insertRedirect(FreenetURI insertURI, FreenetURI 
targetURI) throws InsertException {
-               Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, targetURI, 
new ClientMetadata());
+               Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, null, null, 
targetURI, new ClientMetadata());
                Bucket b;
                try {
                        b = BucketTools.makeImmutableBucket(bucketFactory, 
m.writeToByteArray());
@@ -218,7 +218,7 @@

        public InsertContext getInsertContext(boolean forceNonPersistent) {
                return new InsertContext(bucketFactory, forceNonPersistent ? 
bucketFactory : persistentBucketFactory,
-                               forceNonPersistent ? new 
NullPersistentFileTracker() : persistentFileTracker,
+                               forceNonPersistent ? 
NullPersistentFileTracker.getInstance() : persistentFileTracker,
                                random, INSERT_RETRIES, 
CONSECUTIVE_RNFS_ASSUME_SUCCESS,
                                SPLITFILE_INSERT_THREADS, 
SPLITFILE_BLOCKS_PER_SEGMENT, SPLITFILE_CHECK_BLOCKS_PER_SEGMENT, 
                                globalEventProducer, cacheLocalRequests, 
core.uskManager, blockEncoder, core.getExecutor());

Modified: trunk/freenet/src/freenet/client/InsertContext.java
===================================================================
--- trunk/freenet/src/freenet/client/InsertContext.java 2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/client/InsertContext.java 2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -10,6 +10,7 @@
 import freenet.crypt.RandomSource;
 import freenet.support.Executor;
 import freenet.support.api.BucketFactory;
+import freenet.support.compress.RealCompressor;
 import freenet.support.io.NullPersistentFileTracker;
 import freenet.support.io.PersistentFileTracker;

@@ -34,6 +35,7 @@
        public final USKManager uskManager;
        public final BackgroundBlockEncoder backgroundBlockEncoder;
        public final Executor executor;
+       public final RealCompressor compressor;

        public InsertContext(BucketFactory bf, BucketFactory persistentBF, 
PersistentFileTracker tracker, RandomSource random,
                        int maxRetries, int rnfsToSuccess, int maxThreads, int 
splitfileSegmentDataBlocks, int splitfileSegmentCheckBlocks,
@@ -54,10 +56,12 @@
                this.cacheLocalRequests = cacheLocalRequests;
                this.backgroundBlockEncoder = blockEncoder;
                this.executor = executor;
+               this.compressor = new RealCompressor(executor);
+               executor.execute(compressor, "Compression scheduler");
        }

        public InsertContext(InsertContext ctx, SimpleEventProducer producer, 
boolean forceNonPersistent) {
-               this.persistentFileTracker = forceNonPersistent ? new 
NullPersistentFileTracker() : ctx.persistentFileTracker;
+               this.persistentFileTracker = forceNonPersistent ? 
NullPersistentFileTracker.getInstance() : ctx.persistentFileTracker;
                this.uskManager = ctx.uskManager;
                this.bf = ctx.bf;
                this.persistentBucketFactory = forceNonPersistent ? ctx.bf : 
ctx.persistentBucketFactory;
@@ -73,6 +77,7 @@
                this.cacheLocalRequests = ctx.cacheLocalRequests;
                this.backgroundBlockEncoder = ctx.backgroundBlockEncoder;
                this.executor = ctx.executor;
+               this.compressor = ctx.compressor;
        }

        public InsertContext(InsertContext ctx, SimpleEventProducer producer) {
@@ -92,6 +97,7 @@
                this.cacheLocalRequests = ctx.cacheLocalRequests;
                this.backgroundBlockEncoder = ctx.backgroundBlockEncoder;
                this.executor = ctx.executor;
+               this.compressor = ctx.compressor;
        }

 }

Modified: trunk/freenet/src/freenet/client/Metadata.java
===================================================================
--- trunk/freenet/src/freenet/client/Metadata.java      2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/client/Metadata.java      2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -19,10 +19,12 @@
 import freenet.keys.BaseClientKey;
 import freenet.keys.ClientCHK;
 import freenet.keys.FreenetURI;
+import freenet.client.ArchiveManager.ARCHIVE_TYPE;
 import freenet.support.Fields;
 import freenet.support.Logger;
 import freenet.support.api.Bucket;
 import freenet.support.api.BucketFactory;
+import freenet.support.compress.Compressor.COMPRESSOR_TYPE;
 import freenet.support.io.BucketTools;


@@ -44,8 +46,8 @@
        public static final byte SIMPLE_REDIRECT = 0;
        static final byte MULTI_LEVEL_METADATA = 1;
        static final byte SIMPLE_MANIFEST = 2;
-       public static final byte ZIP_MANIFEST = 3;
-       public static final byte ZIP_INTERNAL_REDIRECT = 4;
+       public static final byte ARCHIVE_MANIFEST = 3;
+       public static final byte ARCHIVE_INTERNAL_REDIRECT = 4;

        // 2 bytes of flags
        /** Is a splitfile */
@@ -69,15 +71,15 @@
 //     static final short FLAGS_SPLIT_USE_LENGTHS = 64; FIXME not supported, 
reassign to something else if we need a new flag
        static final short FLAGS_COMPRESSED = 128;

-       /** Container archive type */
-       short archiveType;
-       static final short ARCHIVE_ZIP = 0;
-       static final short ARCHIVE_TAR = 1; // FIXME for future use
+       /** Container archive type 
+        * @see ARCHIVE_TYPE
+        */
+       ARCHIVE_TYPE archiveType;

-       /** Compressed splitfile codec */
-       short compressionCodec = -1;
-       static public final short COMPRESS_GZIP = 0;
-       static final short COMPRESS_BZIP2 = 1; // FIXME for future use
+       /** Compressed splitfile codec 
+        * @see COMPRESSOR_TYPE
+        */
+       COMPRESSOR_TYPE compressionCodec;

        /** The length of the splitfile */
        long dataLength;
@@ -182,7 +184,7 @@

                boolean compressed = false;
                if((documentType == SIMPLE_REDIRECT) || (documentType == 
MULTI_LEVEL_METADATA)
-                               || (documentType == ZIP_MANIFEST) || 
(documentType == ZIP_INTERNAL_REDIRECT)) {
+                               || (documentType == ARCHIVE_MANIFEST) || 
(documentType == ARCHIVE_INTERNAL_REDIRECT)) {
                        short flags = dis.readShort();
                        splitfile = (flags & FLAGS_SPLITFILE) == 
FLAGS_SPLITFILE;
                        dbr = (flags & FLAGS_DBR) == FLAGS_DBR;
@@ -193,10 +195,10 @@
                        compressed = (flags & FLAGS_COMPRESSED) == 
FLAGS_COMPRESSED;
                }

-               if(documentType == ZIP_MANIFEST) {
-                       if(logMINOR) Logger.minor(this, "Zip manifest");
-                       archiveType = dis.readShort();
-                       if(archiveType != ARCHIVE_ZIP)
+               if(documentType == ARCHIVE_MANIFEST) {
+                       if(logMINOR) Logger.minor(this, "Archive manifest");
+                       archiveType = 
ARCHIVE_TYPE.getArchiveType(dis.readShort());
+                       if(archiveType == null)
                                throw new MetadataParseException("Unrecognized 
archive type "+archiveType);
                }

@@ -213,8 +215,8 @@
                }

                if(compressed) {
-                       compressionCodec = dis.readShort();
-                       if(compressionCodec != COMPRESS_GZIP)
+                       compressionCodec = 
COMPRESSOR_TYPE.getCompressorByMetadataID(dis.readShort());
+                       if(compressionCodec == null)
                                throw new MetadataParseException("Unrecognized 
splitfile compression codec "+compressionCodec);

                        decompressedLength = dis.readLong();
@@ -267,7 +269,7 @@

                clientMetadata = new ClientMetadata(mimeType);

-               if((!splitfile) && ((documentType == SIMPLE_REDIRECT) || 
(documentType == ZIP_MANIFEST))) {
+               if((!splitfile) && ((documentType == SIMPLE_REDIRECT) || 
(documentType == ARCHIVE_MANIFEST))) {
                        simpleRedirectKey = readKey(dis);
                } else if(splitfile) {
                        splitfileAlgorithm = dis.readShort();
@@ -344,13 +346,13 @@
                        if(logMINOR) Logger.minor(this, "End of manifest"); // 
Make it easy to search for it!
                }

-               if(documentType == ZIP_INTERNAL_REDIRECT) {
+               if(documentType == ARCHIVE_INTERNAL_REDIRECT) {
                        int len = dis.readShort();
                        if(logMINOR) Logger.minor(this, "Reading zip internal 
redirect length "+len);
                        byte[] buf = new byte[len];
                        dis.readFully(buf);
                        nameInArchive = new String(buf, "UTF-8");
-                       if(logMINOR) Logger.minor(this, "Zip internal redirect: 
"+nameInArchive+" ("+len+ ')');
+                       if(logMINOR) Logger.minor(this, "Archive internal 
redirect: "+nameInArchive+" ("+len+ ')');
                }
        }

@@ -386,7 +388,7 @@
                        if(o instanceof String) {
                                // External redirect
                                FreenetURI uri = new FreenetURI((String)o);
-                               target = new Metadata(SIMPLE_REDIRECT, uri, 
null);
+                               target = new Metadata(SIMPLE_REDIRECT, null, 
null, uri, null);
                        } else if(o instanceof HashMap) {
                                target = new Metadata();
                                target.addRedirectionManifest((HashMap)o);
@@ -459,7 +461,7 @@
                documentType = SIMPLE_MANIFEST;
                noMIME = true;
                mimeType = null;
-               clientMetadata = new ClientMetadata(null);
+               clientMetadata = new ClientMetadata();
                manifestEntries = new HashMap();
                int count = 0;
                for(Iterator i = dir.keySet().iterator();i.hasNext();) {
@@ -469,7 +471,8 @@
                        Metadata target;
                        if(o instanceof String) {
                                // Zip internal redirect
-                               target = new Metadata(ZIP_INTERNAL_REDIRECT, 
prefix+key, new ClientMetadata(DefaultMIMETypes.guessMIMEType(key, false)));
+                               target = new 
Metadata(ARCHIVE_INTERNAL_REDIRECT, null, null, prefix+key,
+                                       new 
ClientMetadata(DefaultMIMETypes.guessMIMEType(key, false)));
                        } else if(o instanceof HashMap) {
                                target = new Metadata((HashMap)o, 
prefix+key+"/");
                        } else throw new IllegalArgumentException("Not String 
nor HashMap: "+o);
@@ -484,11 +487,13 @@
         * @param arg The argument; in the case of ZIP_INTERNAL_REDIRECT, the 
filename in
         * the archive to read from.
         */
-       public Metadata(byte docType, String arg, ClientMetadata cm) {
-               if(docType == ZIP_INTERNAL_REDIRECT) {
+       public Metadata(byte docType, ARCHIVE_TYPE archiveType, COMPRESSOR_TYPE 
compressionCodec, String arg, ClientMetadata cm) {
+               if(docType == ARCHIVE_INTERNAL_REDIRECT) {
                        documentType = docType;
+                       this.archiveType = archiveType;
                        // Determine MIME type
                        this.clientMetadata = cm;
+                       this.compressionCodec = compressionCodec;
                        if(cm != null)
                                this.setMIMEType(cm.getMIMEType());
                        nameInArchive = arg;
@@ -502,9 +507,11 @@
         * @param uri The URI pointed to.
         * @param cm The client metadata, if any.
         */
-       public Metadata(byte docType, FreenetURI uri, ClientMetadata cm) {
-               if((docType == SIMPLE_REDIRECT) || (docType == ZIP_MANIFEST)) {
+       public Metadata(byte docType, ARCHIVE_TYPE archiveType, COMPRESSOR_TYPE 
compressionCodec, FreenetURI uri, ClientMetadata cm) {
+               if((docType == SIMPLE_REDIRECT) || (docType == 
ARCHIVE_MANIFEST)) {
                        documentType = docType;
+                       this.archiveType = archiveType;
+                       this.compressionCodec = compressionCodec;
                        clientMetadata = cm;
                        if((cm != null) && !cm.isTrivial()) {
                                setMIMEType(cm.getMIMEType());
@@ -520,23 +527,25 @@
        }

        public Metadata(short algo, ClientCHK[] dataURIs, ClientCHK[] 
checkURIs, int segmentSize, int checkSegmentSize, 
-                       ClientMetadata cm, long dataLength, short 
compressionAlgo, long decompressedLength, boolean isMetadata, boolean 
insertAsArchiveManifest) {
+                       ClientMetadata cm, long dataLength, ARCHIVE_TYPE 
archiveType, COMPRESSOR_TYPE compressionCodec, long decompressedLength, boolean 
isMetadata) {
                if(isMetadata)
                        documentType = MULTI_LEVEL_METADATA;
                else {
-                       if(insertAsArchiveManifest)
-                               documentType = ZIP_MANIFEST;
-                       else documentType = SIMPLE_REDIRECT;
+                       if(archiveType != null) {
+                               documentType = ARCHIVE_MANIFEST;
+                               this.archiveType = archiveType;
+                       } else documentType = SIMPLE_REDIRECT;
                }
                splitfile = true;
                splitfileAlgorithm = algo;
                this.dataLength = dataLength;
-               this.compressionCodec = compressionAlgo;
+               this.compressionCodec = compressionCodec;
                splitfileBlocks = dataURIs.length;
                splitfileCheckBlocks = checkURIs.length;
                splitfileDataKeys = dataURIs;
                splitfileCheckKeys = checkURIs;
                clientMetadata = cm;
+               this.compressionCodec = compressionCodec;
                this.decompressedLength = decompressedLength;
                if(cm != null)
                        setMIMEType(cm.getMIMEType());
@@ -667,7 +676,7 @@
        public boolean isSingleFileRedirect() {
                return (((!splitfile) &&
                                (documentType == SIMPLE_REDIRECT)) || 
(documentType == MULTI_LEVEL_METADATA) ||
-                               (documentType == ZIP_MANIFEST));
+                               (documentType == ARCHIVE_MANIFEST));
        }

        /**
@@ -681,7 +690,7 @@
         * Is this a ZIP manifest?
         */
        public boolean isArchiveManifest() {
-               return documentType == ZIP_MANIFEST;
+               return documentType == ARCHIVE_MANIFEST;
        }

        /**
@@ -689,7 +698,7 @@
         * @return
         */
        public boolean isArchiveInternalRedirect() {
-               return documentType == ZIP_INTERNAL_REDIRECT;
+               return documentType == ARCHIVE_INTERNAL_REDIRECT;
        }

        /**
@@ -723,7 +732,7 @@
        }

        /** What kind of archive is it? */
-       public short getArchiveType() {
+       public ARCHIVE_TYPE getArchiveType() {
                return archiveType;
        }

@@ -742,7 +751,7 @@
                dos.writeShort(0); // version
                dos.writeByte(documentType);
                if((documentType == SIMPLE_REDIRECT) || (documentType == 
MULTI_LEVEL_METADATA)
-                               || (documentType == ZIP_MANIFEST) || 
(documentType == ZIP_INTERNAL_REDIRECT)) {
+                               || (documentType == ARCHIVE_MANIFEST) || 
(documentType == ARCHIVE_INTERNAL_REDIRECT)) {
                        short flags = 0;
                        if(splitfile) flags |= FLAGS_SPLITFILE;
                        if(dbr) flags |= FLAGS_DBR;
@@ -750,20 +759,21 @@
                        if(compressedMIME) flags |= FLAGS_COMPRESSED_MIME;
                        if(extraMetadata) flags |= FLAGS_EXTRA_METADATA;
                        if(fullKeys) flags |= FLAGS_FULL_KEYS;
-                       if(compressionCodec >= 0) flags |= FLAGS_COMPRESSED;
+                       if(compressionCodec != null) flags |= FLAGS_COMPRESSED;
                        dos.writeShort(flags);
                }

-               if(documentType == ZIP_MANIFEST) {
-                       dos.writeShort(archiveType);
+               if(documentType == ARCHIVE_MANIFEST) {
+                       short code = archiveType.metadataID;
+                       dos.writeShort(code);
                }

                if(splitfile) {
                        dos.writeLong(dataLength);
                }

-               if(compressionCodec >= 0) {
-                       dos.writeShort(compressionCodec);
+               if(compressionCodec != null) {
+                       dos.writeShort(compressionCodec.metadataID);
                        dos.writeLong(decompressedLength);
                }

@@ -788,7 +798,7 @@
                if(extraMetadata)
                        throw new UnsupportedOperationException("No extra 
metadata support yet");

-               if((!splitfile) && ((documentType == SIMPLE_REDIRECT) || 
(documentType == ZIP_MANIFEST))) {
+               if((!splitfile) && ((documentType == SIMPLE_REDIRECT) || 
(documentType == ARCHIVE_MANIFEST))) {
                        writeKey(dos, simpleRedirectKey);
                } else if(splitfile) {
                        dos.writeShort(splitfileAlgorithm);
@@ -822,7 +832,7 @@
                                        if(data.length > Short.MAX_VALUE) {
                                                FreenetURI uri = 
meta.resolvedURI;
                                                if(uri != null) {
-                                                       meta = new 
Metadata(SIMPLE_REDIRECT, uri, null);
+                                                       meta = new 
Metadata(SIMPLE_REDIRECT, null, null, uri, null);
                                                        data = 
meta.writeToByteArray();
                                                } else {
                                                        kill = true;
@@ -849,7 +859,7 @@
                        }
                }

-               if(documentType == ZIP_INTERNAL_REDIRECT) {
+               if(documentType == ARCHIVE_INTERNAL_REDIRECT) {
                        byte[] data = nameInArchive.getBytes("UTF-8");
                        if(data.length > Short.MAX_VALUE) throw new 
IllegalArgumentException("Zip internal redirect name too long");
                        dos.writeShort(data.length);
@@ -873,10 +883,10 @@
        }

        public boolean isCompressed() {
-               return compressionCodec >= 0;
+               return compressionCodec != null;
        }

-       public short getCompressionCodec() {
+       public COMPRESSOR_TYPE getCompressionCodec() {
                return compressionCodec;
        }

@@ -910,9 +920,11 @@
        }

        public void setArchiveManifest() {
-               archiveType = 
ArchiveManager.getArchiveType(clientMetadata.getMIMEType());
+               ARCHIVE_TYPE type = 
ARCHIVE_TYPE.getArchiveType(clientMetadata.getMIMEType());
+               archiveType = type;
+               compressionCodec = null;
                clientMetadata.clear();
-               documentType = ZIP_MANIFEST;
+               documentType = ARCHIVE_MANIFEST;
        }

        public String getMIMEType() {

Deleted: trunk/freenet/src/freenet/client/SplitFetchException.java
===================================================================
--- trunk/freenet/src/freenet/client/SplitFetchException.java   2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/SplitFetchException.java   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,28 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.client;
-
-public class SplitFetchException extends FetchException {
-
-       final int failed;
-       final int fatal;
-       final int succeeded;
-       final int enough;
-       
-       public SplitFetchException(int failed, int fatal, int succeeded, int 
enough, FailureCodeTracker errorCodes) {
-               super(FetchException.SPLITFILE_ERROR, errorCodes);
-               this.failed = failed;
-               this.fatal = fatal;
-               this.succeeded = succeeded;
-               this.enough = enough;
-       }
-
-       @Override
-       public String getMessage() {
-               return "Splitfile fetch failure: "+failed+" failed, "+fatal+" 
fatal errors, "+succeeded+" succeeded, "+enough+" enough";
-       }
-       
-       private static final long serialVersionUID = 1523809424508826893L;
-
-}

Deleted: trunk/freenet/src/freenet/client/StartableSplitfileBlock.java
===================================================================
--- trunk/freenet/src/freenet/client/StartableSplitfileBlock.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/StartableSplitfileBlock.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,28 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.client;
-
-import freenet.keys.FreenetURI;
-
-/** Simple interface for a splitfile block */
-public interface StartableSplitfileBlock extends SplitfileBlock {
-
-       /** Start the fetch (or insert). Implementation is required to call 
relevant
-        * methods on RetryTracker when done. */
-       abstract void start();
-
-       /**
-        * Shut down the fetch as soon as reasonably possible.
-        */
-       abstract public void kill();
-
-       abstract public int getRetryCount();
-       
-       /**
-        * Get the URI of the file. For an insert, this is derived during 
insert.
-        * For a request, it is fixed in the constructor.
-        */
-       abstract public FreenetURI getURI();
-
-}

Modified: trunk/freenet/src/freenet/client/async/ClientPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientPutter.java    2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/async/ClientPutter.java    2008-11-06 
13:53:57 UTC (rev 23351)
@@ -96,7 +96,7 @@
                                        if(!binaryBlob)
                                                currentState =
                                                        new 
SingleFileInserter(this, this, new InsertBlock(data, cm, targetURI), 
isMetadata, ctx, 
-                                                                       false, 
getCHKOnly, false, null, false, false, targetFilename, earlyEncode);
+                                                                       false, 
getCHKOnly, false, null, null, false, targetFilename, earlyEncode);
                                        else
                                                currentState =
                                                        new 
BinaryBlobInserter(data, this, null, false, priorityClass, ctx);
@@ -231,12 +231,16 @@
                return uri;
        }

-       public synchronized void onTransition(ClientPutState oldState, 
ClientPutState newState) {
+       public void onTransition(ClientPutState oldState, ClientPutState 
newState) {            
                if(newState == null) throw new NullPointerException();
-               if(currentState == oldState)
-                       currentState = newState;
-               else
-                       Logger.error(this, "onTransition: cur="+currentState+", 
old="+oldState+", new="+newState);
+               
+               synchronized (this) {
+                       if (currentState == oldState) {
+                               currentState = newState;
+                               return;
+                       }
+               }
+               Logger.error(this, "onTransition: cur=" + currentState + ", 
old=" + oldState + ", new=" + newState);
        }

        public void onMetadata(Metadata m, ClientPutState state) {

Modified: trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-11-06 13:53:57 UTC (rev 23351)
@@ -74,10 +74,6 @@
                public String[] getPossibleValues() {
                        return possibleValues;
                }
-               
-               public void setPossibleValues(String[] val) {
-                       throw new NullPointerException("Should not happen!");
-               }
        }

        /**

Modified: trunk/freenet/src/freenet/client/async/ClientRequester.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientRequester.java 2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/async/ClientRequester.java 2008-11-06 
13:53:57 UTC (rev 23351)
@@ -68,23 +68,36 @@
                notifyClients();
        }

-       public synchronized void addBlock() {
-               if(blockSetFinalized)
-                       if(Logger.globalGetThreshold() > Logger.MINOR)
-                               Logger.error(this, "addBlock() but set 
finalized! on "+this);
+       public void addBlock() {
+               boolean wasFinalized;
+               synchronized (this) {
+                       totalBlocks++;
+                       wasFinalized = blockSetFinalized;
+               }
+
+               if (wasFinalized) {
+                       if (Logger.globalGetThreshold() > Logger.MINOR)
+                               Logger.error(this, "addBlock() but set 
finalized! on " + this);
                        else
-                               Logger.error(this, "addBlock() but set 
finalized! on "+this, new Exception("error"));
-               totalBlocks++;
+                               Logger.error(this, "addBlock() but set 
finalized! on " + this, new Exception("error"));
+               }
+               
                if(Logger.shouldLog(Logger.MINOR, this)) Logger.minor(this, 
"addBlock(): total="+totalBlocks+" successful="+successfulBlocks+" 
failed="+failedBlocks+" required="+minSuccessBlocks); 
        }

-       public synchronized void addBlocks(int num) {
-               if(blockSetFinalized)
+       public void addBlocks(int num) {
+               boolean wasFinalized;
+               synchronized (this) {
+                       totalBlocks += num;
+                       wasFinalized = blockSetFinalized;
+               }
+
+               if (wasFinalized)
                        if(Logger.globalGetThreshold() > Logger.MINOR)
                                Logger.error(this, "addBlocks() but set 
finalized! on "+this);
                        else
                                Logger.error(this, "addBlocks() but set 
finalized! on "+this, new Exception("error"));
-               totalBlocks+=num;
+               
                if(Logger.shouldLog(Logger.MINOR, this)) Logger.minor(this, 
"addBlocks("+num+"): total="+totalBlocks+" successful="+successfulBlocks+" 
failed="+failedBlocks+" required="+minSuccessBlocks); 
        }


Modified: trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java    
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java    
2008-11-06 13:53:57 UTC (rev 23351)
@@ -7,11 +7,15 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 import java.util.Vector;
 import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
 import java.util.zip.ZipOutputStream;

+import org.apache.tools.tar.TarEntry;
+import org.apache.tools.tar.TarOutputStream;
+
 import freenet.client.ClientMetadata;
 import freenet.client.DefaultMIMETypes;
 import freenet.client.InsertBlock;
@@ -19,6 +23,7 @@
 import freenet.client.InsertException;
 import freenet.client.Metadata;
 import freenet.client.MetadataUnresolvedException;
+import freenet.client.ArchiveManager.ARCHIVE_TYPE;
 import freenet.client.events.SplitfileProgressEvent;
 import freenet.keys.BaseClientKey;
 import freenet.keys.FreenetURI;
@@ -38,7 +43,7 @@
                        InsertBlock block = 
                                new InsertBlock(data, cm, 
FreenetURI.EMPTY_CHK_URI);
                        this.origSFI =
-                               new SingleFileInserter(this, this, block, 
false, ctx, false, getCHKOnly, true, null, false, false, null, earlyEncode);
+                               new SingleFileInserter(this, this, block, 
false, ctx, false, getCHKOnly, true, null, null, false, null, earlyEncode);
                        metadata = null;
                }

@@ -46,17 +51,17 @@
                        super(smp.getPriorityClass(), smp.chkScheduler, 
smp.sskScheduler, smp.client);
                        this.cm = cm;
                        this.data = null;
-                       Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
target, cm);
+                       Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
null, null, target, cm);
                        metadata = m;
                        origSFI = null;
                }

-               protected PutHandler(final SimpleManifestPutter smp, String 
name, String targetInZip, ClientMetadata cm, Bucket data) {
+               protected PutHandler(final SimpleManifestPutter smp, String 
name, String targetInArchive, ClientMetadata cm, Bucket data) {
                        super(smp.getPriorityClass(), smp.chkScheduler, 
smp.sskScheduler, smp.client);
                        this.cm = cm;
                        this.data = data;
-                       this.targetInZip = targetInZip;
-                       Metadata m = new 
Metadata(Metadata.ZIP_INTERNAL_REDIRECT, targetInZip, cm);
+                       this.targetInArchive = targetInArchive;
+                       Metadata m = new 
Metadata(Metadata.ARCHIVE_INTERNAL_REDIRECT, null, null, targetInArchive, cm);
                        metadata = m;
                        origSFI = null;
                }
@@ -64,7 +69,7 @@
                private SingleFileInserter origSFI;
                private ClientMetadata cm;
                private Metadata metadata;
-               private String targetInZip;
+               private String targetInArchive;
                private final Bucket data;

                public void start() throws InsertException {
@@ -115,7 +120,7 @@
                                // The file was too small to have its own 
metadata, we get this instead.
                                // So we make the key into metadata.
                                Metadata m =
-                                       new Metadata(Metadata.SIMPLE_REDIRECT, 
key.getURI(), cm);
+                                       new Metadata(Metadata.SIMPLE_REDIRECT, 
null, null, key.getURI(), cm);
                                onMetadata(m, null);
                        }
                }
@@ -222,7 +227,7 @@
        private final static String[] defaultDefaultNames =
                new String[] { "index.html", "index.htm", "default.html", 
"default.htm" };
        private int bytesOnZip;
-       private LinkedList elementsToPutInZip;
+       private LinkedList<PutHandler> elementsToPutInArchive;
        private boolean fetchable;
        private final boolean earlyEncode;

@@ -244,7 +249,7 @@
                waitingForBlockSets = new HashSet();
                metadataPuttersByMetadata = new HashMap();
                metadataPuttersUnfetchable = new HashMap();
-               elementsToPutInZip = new LinkedList();
+               elementsToPutInArchive = new LinkedList();
                makePutHandlers(manifestElements, putHandlersByName);
                checkZips();
        }
@@ -324,7 +329,7 @@
                                                bytesOnZip += sz;
                                                // Put it in the zip.
                                                ph = new PutHandler(this, name, 
ZipPrefix+element.fullName, cm, data);
-                                               elementsToPutInZip.addLast(ph);
+                                               
elementsToPutInArchive.addLast(ph);
                                                numberOfFiles++;
                                                totalSize += data.size();
                                        } else {
@@ -415,52 +420,30 @@
                InsertBlock block;
                boolean isMetadata = true;
                boolean insertAsArchiveManifest = false;
-               if(!(elementsToPutInZip.isEmpty())) {
-                       // There is a zip to insert.
+               ARCHIVE_TYPE archiveType = null;
+               if(!(elementsToPutInArchive.isEmpty())) {
+                       // There is an archive to insert.
                        // We want to include the metadata.
                        // We have the metadata, fortunately enough, because 
everything has been resolve()d.
-                       // So all we need to do is create the actual ZIP.
-                       try {
+                       // So all we need to do is create the actual archive.
+                       try {                           
+                               Bucket outputBucket = 
ctx.bf.makeBucket(baseMetadata.dataLength());
+                               // TODO: try both ? - maybe not worth it
+                               archiveType = ARCHIVE_TYPE.getDefault();
+                               String mimeType = (archiveType == 
ARCHIVE_TYPE.TAR ?
+                                       createTarBucket(bucket, outputBucket) :
+                                       createZipBucket(bucket, outputBucket));

-                               // FIXME support formats other than .zip.
-                               // Only the *decoding* is generic at present.
+                               if(logMINOR) Logger.minor(this, "We are using 
"+archiveType);

-                               Bucket zipBucket = 
ctx.bf.makeBucket(baseMetadata.dataLength());
-                               OutputStream os = new 
BufferedOutputStream(zipBucket.getOutputStream());
-                               ZipOutputStream zos = new ZipOutputStream(os);
-                               ZipEntry ze;
+                               // Now we have to insert the Archive we have 
generated.

-                               for(Iterator 
i=elementsToPutInZip.iterator();i.hasNext();) {
-                                       PutHandler ph = (PutHandler) i.next();
-                                       ze = new ZipEntry(ph.targetInZip);
-                                       ze.setTime(0);
-                                       zos.putNextEntry(ze);
-                                       BucketTools.copyTo(ph.data, zos, 
ph.data.size());
-                               }
-                               
-                               // Add .metadata - after the rest.
-                               ze = new ZipEntry(".metadata");
-                               ze.setTime(0); // -1 = now, 0 = 1970.
-                               zos.putNextEntry(ze);
-                               BucketTools.copyTo(bucket, zos, bucket.size());
-                               
-                               zos.closeEntry();
-                               // Both finish() and close() are necessary.
-                               zos.finish();
-                               zos.flush();
-                               zos.close();
-                               
-                               // Now we have to insert the ZIP.
-                               
                                // Can we just insert it, and not bother with a 
redirect to it?
                                // Thereby exploiting implicit manifest 
support, which will pick up on .metadata??
                                // We ought to be able to !!
-                               block = new InsertBlock(zipBucket, new 
ClientMetadata("application/zip"), targetURI);
+                               block = new InsertBlock(outputBucket, new 
ClientMetadata(mimeType), targetURI);
                                isMetadata = false;
                                insertAsArchiveManifest = true;
-                       } catch (ZipException e) {
-                               fail(new 
InsertException(InsertException.INTERNAL_ERROR, e, null));
-                               return;
                        } catch (IOException e) {
                                fail(new 
InsertException(InsertException.BUCKET_ERROR, e, null));
                                return;
@@ -469,7 +452,7 @@
                        block = new InsertBlock(bucket, null, targetURI);
                try {
                        SingleFileInserter metadataInserter = 
-                               new SingleFileInserter(this, this, block, 
isMetadata, ctx, false, getCHKOnly, false, baseMetadata, 
insertAsArchiveManifest, true, null, earlyEncode);
+                               new SingleFileInserter(this, this, block, 
isMetadata, ctx, (archiveType == ARCHIVE_TYPE.ZIP) , getCHKOnly, false, 
baseMetadata, archiveType, true, null, earlyEncode);
                        if(logMINOR) Logger.minor(this, "Inserting main 
metadata: "+metadataInserter);
                        this.metadataPuttersByMetadata.put(baseMetadata, 
metadataInserter);
                        metadataPuttersUnfetchable.put(baseMetadata, 
metadataInserter);
@@ -479,6 +462,71 @@
                }
        }

+       private String createTarBucket(Bucket inputBucket, Bucket outputBucket) 
throws IOException {
+               if(logMINOR) Logger.minor(this, "Create a TAR Bucket");
+               
+               OutputStream os = new 
BufferedOutputStream(outputBucket.getOutputStream());
+               TarOutputStream tarOS = new TarOutputStream(os);
+               TarEntry ze;
+
+               for(PutHandler ph : elementsToPutInArchive) {
+                       ze = new TarEntry(ph.targetInArchive);
+                       ze.setModTime(0);
+                       long size = ph.data.size();
+                       ze.setSize(size);
+                       tarOS.putNextEntry(ze);
+                       BucketTools.copyTo(ph.data, tarOS, size);
+                       tarOS.closeEntry();
+               }
+
+               // Add .metadata - after the rest.
+               ze = new TarEntry(".metadata");
+               ze.setModTime(0); // -1 = now, 0 = 1970.
+               long size = inputBucket.size();
+               ze.setSize(size);
+               tarOS.putNextEntry(ze);
+               BucketTools.copyTo(inputBucket, tarOS, size);
+
+               tarOS.closeEntry();
+               // Both finish() and close() are necessary.
+               tarOS.finish();
+               tarOS.flush();
+               tarOS.close();
+               
+               return ARCHIVE_TYPE.TAR.mimeTypes[0];
+       }
+       
+       private String createZipBucket(Bucket inputBucket, Bucket outputBucket) 
throws IOException {
+               if(logMINOR) Logger.minor(this, "Create a ZIP Bucket");
+               
+               OutputStream os = new 
BufferedOutputStream(outputBucket.getOutputStream());
+               ZipOutputStream zos = new ZipOutputStream(os);
+               ZipEntry ze;
+
+               for(Iterator i = elementsToPutInArchive.iterator(); 
i.hasNext();) {
+                       PutHandler ph = (PutHandler) i.next();
+                       ze = new ZipEntry(ph.targetInArchive);
+                       ze.setTime(0);
+                       zos.putNextEntry(ze);
+                       BucketTools.copyTo(ph.data, zos, ph.data.size());
+                       zos.closeEntry();
+               }
+
+               // Add .metadata - after the rest.
+               ze = new ZipEntry(".metadata");
+               ze.setTime(0); // -1 = now, 0 = 1970.
+               zos.putNextEntry(ze);
+               BucketTools.copyTo(inputBucket, zos, inputBucket.size());
+
+               zos.closeEntry();
+               // Both finish() and close() are necessary.
+               zos.finish();
+               zos.flush();
+               zos.close();
+               
+               return ARCHIVE_TYPE.ZIP.mimeTypes[0];
+       }
+
        private boolean resolve(MetadataUnresolvedException e) throws 
InsertException, IOException {
                Metadata[] metas = e.mustResolve;
                boolean mustWait = false;
@@ -494,7 +542,7 @@

                                InsertBlock ib = new InsertBlock(b, null, 
FreenetURI.EMPTY_CHK_URI);
                                SingleFileInserter metadataInserter = 
-                                       new SingleFileInserter(this, this, ib, 
true, ctx, false, getCHKOnly, false, m, false, true, null, earlyEncode);
+                                       new SingleFileInserter(this, this, ib, 
true, ctx, false, getCHKOnly, false, m, null, true, null, earlyEncode);
                                if(logMINOR) Logger.minor(this, "Inserting 
subsidiary metadata: "+metadataInserter+" for "+m);
                                synchronized(this) {
                                        this.metadataPuttersByMetadata.put(m, 
metadataInserter);
@@ -702,25 +750,25 @@
         * Note that this can throw a ClassCastException if the vector passed 
in is
         * bogus (has files pretending to be directories).
         */
-       public static HashMap unflatten(Vector v) {
-               HashMap manifestElements = new HashMap();
-               for(int i=0;i<v.size();i++) {
-                       ManifestElement oldElement = (ManifestElement)v.get(i);
+       public static <T> HashMap<String, Object> 
unflatten(List<ManifestElement> v) {
+               HashMap<String, Object> manifestElements = new HashMap<String, 
Object>();
+               for(ManifestElement oldElement : v) {
                        add(oldElement, oldElement.getName(), manifestElements);
                }
                return manifestElements;
        }

-       private static void add(ManifestElement e, String namePart, HashMap 
target) {
+       private static void add(ManifestElement e, String namePart, Map<String, 
Object> target) {
                int idx = namePart.indexOf('/');
                if(idx < 0) {
                        target.put(namePart, new ManifestElement(e, namePart));
                } else {
                        String before = namePart.substring(0, idx);
                        String after = namePart.substring(idx+1);
-                       HashMap hm = (HashMap) (target.get(before));
+                       @SuppressWarnings("unchecked")
+                       HashMap<String, Object> hm = (HashMap<String, Object>) 
target.get(before);
                        if(hm == null) {
-                               hm = new HashMap();
+                               hm = new HashMap<String, Object>();
                                target.put(before.intern(), hm);
                        }
                        add(e, after, hm);

Modified: trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileFetcher.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/async/SingleFileFetcher.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -30,7 +30,7 @@
 import freenet.support.Logger;
 import freenet.support.api.Bucket;
 import freenet.support.compress.CompressionOutputSizeException;
-import freenet.support.compress.Compressor;
+import freenet.support.compress.Compressor.COMPRESSOR_TYPE;
 import freenet.support.io.BucketTools;

 public class SingleFileFetcher extends SimpleSingleFileFetcher {
@@ -52,7 +52,7 @@
        private int recursionLevel;
        /** The URI of the currently-being-processed data, for archives etc. */
        private FreenetURI thisKey;
-       private final LinkedList decompressors;
+       private final LinkedList<COMPRESSOR_TYPE> decompressors;
        private final boolean dontTellClientGet;
        private final Bucket returnBucket;
        /** If true, success/failure is immediately reported to the client, and 
therefore we can check TOO_MANY_PATH_COMPONENTS. */
@@ -89,7 +89,7 @@
                this.recursionLevel = recursionLevel + 1;
                if(recursionLevel > ctx.maxRecursionLevel)
                        throw new 
FetchException(FetchException.TOO_MUCH_RECURSION, "Too much recursion: 
"+recursionLevel+" > "+ctx.maxRecursionLevel);
-               this.decompressors = new LinkedList();
+               this.decompressors = new LinkedList<COMPRESSOR_TYPE>();
        }

        /** Copy constructor, modifies a few given fields, don't call 
schedule().
@@ -107,7 +107,7 @@
                this.actx = fetcher.actx;
                this.ah = fetcher.ah;
                this.archiveMetadata = fetcher.archiveMetadata;
-               this.clientMetadata = (ClientMetadata) 
fetcher.clientMetadata.clone();
+               this.clientMetadata = (fetcher.clientMetadata != null ? 
(ClientMetadata) fetcher.clientMetadata.clone() : null);
                this.metadata = newMeta;
                this.metaStrings = new LinkedList();
                this.addedMetaStrings = 0;
@@ -160,15 +160,15 @@
                        // Parse metadata
                        try {
                                metadata = Metadata.construct(data);
+                               wrapHandleMetadata(false);
                        } catch (MetadataParseException e) {
-                               onFailure(new FetchException(e), sched);
+                               onFailure(new 
FetchException(FetchException.INVALID_METADATA, e), sched);
                                return;
                        } catch (IOException e) {
                                // Bucket error?
                                onFailure(new 
FetchException(FetchException.BUCKET_ERROR, e), sched);
                                return;
                        }
-                       wrapHandleMetadata(false);
                }
        }

@@ -186,7 +186,7 @@
                if(!decompressors.isEmpty()) {
                        Bucket data = result.asBucket();
                        while(!decompressors.isEmpty()) {
-                               Compressor c = (Compressor) 
decompressors.removeLast();
+                               COMPRESSOR_TYPE c = decompressors.removeLast();
                                try {
                                        long maxLen = 
Math.max(ctx.maxTempLength, ctx.maxOutputLength);
                                        data = c.decompress(data, 
ctx.bucketFactory, maxLen, maxLen * 4, decompressors.isEmpty() ? returnBucket : 
null);
@@ -255,11 +255,11 @@
                                        metadata = metadata.getDocument(name);
                                        thisKey = thisKey.pushMetaString(name);
                                        if(metadata == null)
-                                               throw new 
FetchException(FetchException.NOT_IN_ARCHIVE);
+                                               throw new 
FetchException(FetchException.NOT_IN_ARCHIVE, "can't find "+name);
                                }
                                continue; // loop
                        } else if(metadata.isArchiveManifest()) {
-                               if(logMINOR) Logger.minor(this, "Is archive 
manifest");
+                               if(logMINOR) Logger.minor(this, "Is archive 
manifest (type="+metadata.getArchiveType()+" 
codec="+metadata.getCompressionCodec()+')');
                                if(metaStrings.isEmpty() && 
ctx.returnZIPManifests) {
                                        // Just return the archive, whole.
                                        metadata.setSimpleRedirect();
@@ -270,7 +270,7 @@
                                // It's more efficient to keep the existing ah 
if we can, and it is vital in
                                // the case of binary blobs.
                                if(ah == null || !ah.getKey().equals(thisKey))
-                                       ah = (ArchiveStoreContext) 
ctx.archiveManager.makeHandler(thisKey, metadata.getArchiveType(), false, 
+                                       ah = (ArchiveStoreContext) 
ctx.archiveManager.makeHandler(thisKey, metadata.getArchiveType(), 
metadata.getCompressionCodec(), false, 
                                                        (parent instanceof 
ClientGetter ? ((ClientGetter)parent).collectingBinaryBlob() : false));
                                archiveMetadata = metadata;
                                // ah is set. This means we are currently 
handling an archive.
@@ -396,7 +396,7 @@
                                if(mime != null) rcb.onExpectedMIME(mime);

                                String mimeType = 
clientMetadata.getMIMETypeNoParams();
-                               if(mimeType != null && 
ArchiveManager.isUsableArchiveType(mimeType) && metaStrings.size() > 0) {
+                               if(mimeType != null && 
ArchiveManager.ARCHIVE_TYPE.isUsableArchiveType(mimeType) && metaStrings.size() 
> 0) {
                                        // Looks like an implicit archive, 
handle as such
                                        metadata.setArchiveManifest();
                                        // Pick up MIME type from inside archive
@@ -442,7 +442,7 @@
                                if((redirectedKey instanceof ClientCHK) && 
!((ClientCHK)redirectedKey).isMetadata())
                                        rcb.onBlockSetFinished(this);
                                if(metadata.isCompressed()) {
-                                       Compressor codec = 
Compressor.getCompressionAlgorithmByMetadataID(metadata.getCompressionCodec());
+                                       COMPRESSOR_TYPE codec = 
metadata.getCompressionCodec();
                                        f.addDecompressor(codec);
                                }
                                parent.onTransition(this, f);
@@ -461,7 +461,7 @@
                                if(mime != null) rcb.onExpectedMIME(mime);

                                String mimeType = 
clientMetadata.getMIMETypeNoParams();
-                               if(mimeType != null && 
ArchiveManager.isUsableArchiveType(mimeType) && metaStrings.size() > 0) {
+                               if(mimeType != null && 
ArchiveManager.ARCHIVE_TYPE.isUsableArchiveType(mimeType) && metaStrings.size() 
> 0) {
                                        // Looks like an implicit archive, 
handle as such
                                        metadata.setArchiveManifest();
                                        // Pick up MIME type from inside archive
@@ -478,7 +478,7 @@
                                // Splitfile (possibly compressed)

                                if(metadata.isCompressed()) {
-                                       Compressor codec = 
Compressor.getCompressionAlgorithmByMetadataID(metadata.getCompressionCodec());
+                                       COMPRESSOR_TYPE codec = 
metadata.getCompressionCodec();
                                        addDecompressor(codec);
                                }

@@ -539,7 +539,7 @@
                return name;
        }

-       private void addDecompressor(Compressor codec) {
+       private void addDecompressor(COMPRESSOR_TYPE codec) {
                decompressors.addLast(codec);
        }

@@ -573,7 +573,7 @@
                try {
                        handleMetadata();
                } catch (MetadataParseException e) {
-                       onFailure(new FetchException(e), sched);
+                       onFailure(new 
FetchException(FetchException.INVALID_METADATA, e), sched);
                } catch (FetchException e) {
                        if(notFinalizedSize)
                                e.setNotFinalizedSize();

Modified: trunk/freenet/src/freenet/client/async/SingleFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileInserter.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/async/SingleFileInserter.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -9,20 +9,23 @@
 import freenet.client.InsertException;
 import freenet.client.Metadata;
 import freenet.client.MetadataUnresolvedException;
+import freenet.client.ArchiveManager.ARCHIVE_TYPE;
 import freenet.client.events.FinishedCompressionEvent;
 import freenet.client.events.StartedCompressionEvent;
 import freenet.keys.BaseClientKey;
 import freenet.keys.CHKBlock;
 import freenet.keys.FreenetURI;
 import freenet.keys.SSKBlock;
+import freenet.node.PrioRunnable;
 import freenet.support.Logger;
-import freenet.support.OOMHandler;
 import freenet.support.SimpleFieldSet;
 import freenet.support.api.Bucket;
+import freenet.support.compress.CompressJob;
 import freenet.support.compress.CompressionOutputSizeException;
-import freenet.support.compress.Compressor;
+import freenet.support.compress.Compressor.COMPRESSOR_TYPE;
 import freenet.support.io.BucketChainBucketFactory;
 import freenet.support.io.BucketTools;
+import freenet.support.io.NativeThread;

 /**
  * Attempt to insert a file. May include metadata.
@@ -31,11 +34,8 @@
  * Attempt to compress the file. Off-thread if it will take a while.
  * Then hand it off to SimpleFileInserter.
  */
-class SingleFileInserter implements ClientPutState {
+public class SingleFileInserter implements ClientPutState, CompressJob {

-       // Config option???
-       private static final long COMPRESS_OFF_THREAD_LIMIT = 65536;
-       
        private static boolean logMINOR;
        final BaseClientPutter parent;
        final InsertBlock block;
@@ -43,7 +43,8 @@
        final boolean metadata;
        final PutCompletionCallback cb;
        final boolean getCHKOnly;
-       final boolean insertAsArchiveManifest;
+       final ARCHIVE_TYPE archiveType;
+       COMPRESSOR_TYPE compressorUsed;
        /** If true, we are not the top level request, and should not
         * update our parent to point to us as current put-stage. */
        private final boolean reportMetadataOnly;
@@ -69,7 +70,7 @@
         */
        SingleFileInserter(BaseClientPutter parent, PutCompletionCallback cb, 
InsertBlock block, 
                        boolean metadata, InsertContext ctx, boolean 
dontCompress, 
-                       boolean getCHKOnly, boolean reportMetadataOnly, Object 
token, boolean insertAsArchiveManifest, 
+                       boolean getCHKOnly, boolean reportMetadataOnly, Object 
token, ARCHIVE_TYPE archiveType, 
                        boolean freeData, String targetFilename, boolean 
earlyEncode) throws InsertException {
                this.earlyEncode = earlyEncode;
                this.reportMetadataOnly = reportMetadataOnly;
@@ -80,7 +81,7 @@
                this.metadata = metadata;
                this.cb = cb;
                this.getCHKOnly = getCHKOnly;
-               this.insertAsArchiveManifest = insertAsArchiveManifest;
+               this.archiveType = archiveType;
                this.freeData = freeData;
                this.targetFilename = targetFilename;
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
@@ -103,39 +104,11 @@
                                }
                        }
                }
-               Bucket data = block.getData();
-               if(data.size() > COMPRESS_OFF_THREAD_LIMIT) {
-                       // Run off thread
-                       OffThreadCompressor otc = new OffThreadCompressor();
-                       ctx.executor.execute(otc, "Compressor for "+this);
-               } else {
-                       tryCompress();
-               }
+               // Run off thread in any case
+               ctx.compressor.enqueueNewJob(this);
        }
-
-       private class OffThreadCompressor implements Runnable {
-               public void run() {
-                   freenet.support.Logger.OSThread.logPID(this);
-                       try {
-                               tryCompress();
-                       } catch (InsertException e) {
-                               cb.onFailure(e, SingleFileInserter.this);
-            } catch (OutOfMemoryError e) {
-                               OOMHandler.handleOOM(e);
-                               System.err.println("OffThreadCompressor thread 
above failed.");
-                               // Might not be heap, so try anyway
-                               cb.onFailure(new 
InsertException(InsertException.INTERNAL_ERROR, e, null), 
SingleFileInserter.this);
-            } catch (Throwable t) {
-                Logger.error(this, "Caught in OffThreadCompressor: "+t, t);
-                System.err.println("Caught in OffThreadCompressor: "+t);
-                t.printStackTrace();
-                // Try to fail gracefully
-                               cb.onFailure(new 
InsertException(InsertException.INTERNAL_ERROR, t, null), 
SingleFileInserter.this);
-                       }
-               }
-       }

-       private void tryCompress() throws InsertException {
+       public void tryCompress() throws InsertException {
                // First, determine how small it needs to be
                Bucket origData = block.getData();
                Bucket data = origData;
@@ -155,144 +128,179 @@
                        throw new InsertException(InsertException.INVALID_URI, 
"Unknown key type: "+type, null);
                }

-               Compressor bestCodec = null;
+               COMPRESSOR_TYPE bestCodec = null;
                Bucket bestCompressedData = null;
+               long bestCompressedDataSize = origSize;

                boolean tryCompress = (origSize > blockSize) && 
(!ctx.dontCompress) && (!dontCompress);
                if(tryCompress) {
+                       if(logMINOR) Logger.minor(this, "Attempt to compress 
the data");
                        // Try to compress the data.
                        // Try each algorithm, starting with the fastest and 
weakest.
                        // Stop when run out of algorithms, or the compressed 
data fits in a single block.
-                       int algos = Compressor.countCompressAlgorithms();
-                       try {
-                               for(int i=0;i<algos;i++) {
+                       for(COMPRESSOR_TYPE comp : COMPRESSOR_TYPE.values()) {
+                               boolean shouldFreeOnFinally = true;
+                               Bucket result = null;
+                               try {
+                                       if(logMINOR)
+                                               Logger.minor(this, "Attempt to 
compress using " + comp);
                                        // Only produce if we are compressing 
*the original data*
                                        if(parent == cb)
-                                               
ctx.eventProducer.produceEvent(new StartedCompressionEvent(i));
-                                       Compressor comp = 
Compressor.getCompressionAlgorithmByDifficulty(i);
-                                       Bucket result;
-                                       result = comp.compress(origData, new 
BucketChainBucketFactory(ctx.persistentBucketFactory, CHKBlock.DATA_LENGTH), 
origData.size());
-                                       if(result.size() < 
oneBlockCompressedSize) {
+                                               
ctx.eventProducer.produceEvent(new StartedCompressionEvent(comp));
+                                       result = comp.compress(origData, new 
BucketChainBucketFactory(ctx.persistentBucketFactory, CHKBlock.DATA_LENGTH), 
bestCompressedDataSize);
+                                       long resultSize = result.size();
+                                       if(resultSize < oneBlockCompressedSize) 
{
                                                bestCodec = comp;
                                                if(bestCompressedData != null)
                                                        
bestCompressedData.free();
                                                bestCompressedData = result;
+                                               bestCompressedDataSize = 
resultSize;
+                                               shouldFreeOnFinally = false;
                                                break;
                                        }
-                                       if((bestCompressedData != null) && 
(result.size() <  bestCompressedData.size())) {
-                                               bestCompressedData.free();
+                                       if(resultSize < bestCompressedDataSize) 
{
+                                               if(bestCompressedData != null)
+                                                       
bestCompressedData.free();
                                                bestCompressedData = result;
+                                               bestCompressedDataSize = 
resultSize;
                                                bestCodec = comp;
-                                       } else if((bestCompressedData == null) 
&& (result.size() < data.size())) {
-                                               bestCompressedData = result;
-                                               bestCodec = comp;
-                                       } else {
+                                               shouldFreeOnFinally = false;
+                                       }
+                               } catch(CompressionOutputSizeException e) {
+                                       continue;       // try next compressor 
type
+                               } catch(IOException e) {
+                                       throw new 
InsertException(InsertException.BUCKET_ERROR, e, null);
+                               } finally {
+                                       if(shouldFreeOnFinally && (result != 
null))
                                                result.free();
-                                       }
                                }
-                       } catch (IOException e) {
-                               throw new 
InsertException(InsertException.BUCKET_ERROR, e, null);
-                       } catch (CompressionOutputSizeException e) {
-                               // Impossible
-                               throw new Error(e);
                        }
                }
-               boolean freeData = false;
+               boolean shouldFreeData = false;
                if(bestCompressedData != null) {
+                       if(logMINOR) Logger.minor(this, "The best compression 
algorithm is "+bestCodec+ " we have gained "+ 
(100-(bestCompressedDataSize*100/origSize)) +"% ! 
("+origSize+'/'+bestCompressedDataSize+')');
                        data = bestCompressedData;
-                       freeData = true;
+                       shouldFreeData = true;
+                       compressorUsed = bestCodec;
                }

                if(parent == cb) {
                        if(tryCompress)
-                               ctx.eventProducer.produceEvent(new 
FinishedCompressionEvent(bestCodec == null ? -1 : 
bestCodec.codecNumberForMetadata(), origSize, data.size()));
+                               ctx.eventProducer.produceEvent(new 
FinishedCompressionEvent(bestCodec == null ? -1 : bestCodec.metadataID, 
origSize, data.size()));
                        if(logMINOR) Logger.minor(this, "Compressed 
"+origSize+" to "+data.size()+" on "+this);
-               }
-               
-               // Compressed data
-               
-               // Insert it...
-               short codecNumber = bestCodec == null ? -1 : 
bestCodec.codecNumberForMetadata();
-               long compressedDataSize = data.size();
-               boolean fitsInOneBlockAsIs = bestCodec == null ? 
compressedDataSize < blockSize : compressedDataSize < oneBlockCompressedSize;
-               boolean fitsInOneCHK = bestCodec == null ? compressedDataSize < 
CHKBlock.DATA_LENGTH : compressedDataSize < CHKBlock.MAX_COMPRESSED_DATA_LENGTH;
+               }               
+               // Compressed data ; now insert it
+               // We do it off thread so that RealCompressor can release the 
semaphore
+               final COMPRESSOR_TYPE fbestCodec = bestCodec;
+               final Bucket fdata = data;
+               final int foneBlockCompressedSize = oneBlockCompressedSize;
+               final int fblockSize = blockSize;
+               final long forigSize = origSize;
+               final boolean fshouldFreeData = shouldFreeData;
+               ctx.executor.execute(new PrioRunnable() {

-               if((fitsInOneBlockAsIs || fitsInOneCHK) && 
block.getData().size() > Integer.MAX_VALUE)
-                       throw new 
InsertException(InsertException.INTERNAL_ERROR, "2GB+ should not encode to one 
block!", null);
+                       public int getPriority() {
+                               return NativeThread.NORM_PRIORITY;
+                       }

-               boolean noMetadata = ((block.clientMetadata == null) || 
block.clientMetadata.isTrivial()) && targetFilename == null;
-               if(noMetadata && !insertAsArchiveManifest) {
-                       if(fitsInOneBlockAsIs) {
-                               // Just insert it
-                               ClientPutState bi =
-                                       createInserter(parent, data, 
codecNumber, block.desiredURI, ctx, cb, metadata, (int)block.getData().size(), 
-1, getCHKOnly, true, true);
-                               cb.onTransition(this, bi);
-                               bi.schedule();
-                               cb.onBlockSetFinished(this);
+                       public void run() {
+                               insert(fbestCodec, fdata, 
foneBlockCompressedSize, fblockSize, forigSize, fshouldFreeData);
+                       }
+               }, "Insert thread for "+this);
+       }
+       
+       private void insert(COMPRESSOR_TYPE bestCodec, Bucket data, int 
oneBlockCompressedSize, int blockSize, long origSize, boolean shouldFreeData) {
+               try {
+                       // Insert it...
+                       short codecNumber = bestCodec == null ? -1 : 
bestCodec.metadataID;
+                       long compressedDataSize = data.size();
+                       boolean fitsInOneBlockAsIs = bestCodec == null ? 
compressedDataSize < blockSize : compressedDataSize < oneBlockCompressedSize;
+                       boolean fitsInOneCHK = bestCodec == null ? 
compressedDataSize < CHKBlock.DATA_LENGTH : compressedDataSize < 
CHKBlock.MAX_COMPRESSED_DATA_LENGTH;
+
+                       if((fitsInOneBlockAsIs || fitsInOneCHK) && 
block.getData().size() > Integer.MAX_VALUE)
+                               throw new 
InsertException(InsertException.INTERNAL_ERROR, "2GB+ should not encode to one 
block!", null);
+
+                       boolean noMetadata = ((block.clientMetadata == null) || 
block.clientMetadata.isTrivial()) && targetFilename == null;
+                       if(noMetadata && archiveType == null)
+                               if(fitsInOneBlockAsIs) {
+                                       // Just insert it
+                                       ClientPutState bi =
+                                               createInserter(parent, data, 
codecNumber, block.desiredURI, ctx, cb, metadata, (int) block.getData().size(), 
-1, getCHKOnly, true, true);
+                                       cb.onTransition(this, bi);
+                                       bi.schedule();
+                                       cb.onBlockSetFinished(this);
+                                       return;
+                               }
+                       if(fitsInOneCHK) {
+                               // Insert single block, then insert pointer to 
it
+                               if(reportMetadataOnly) {
+                                       SingleBlockInserter dataPutter = new 
SingleBlockInserter(parent, data, codecNumber, FreenetURI.EMPTY_CHK_URI, ctx, 
cb, metadata, (int) origSize, -1, getCHKOnly, true, true, token);
+                                       Metadata meta = 
makeMetadata(archiveType, bestCodec, dataPutter.getURI());
+                                       cb.onMetadata(meta, this);
+                                       cb.onTransition(this, dataPutter);
+                                       dataPutter.schedule();
+                                       cb.onBlockSetFinished(this);
+                               } else {
+                                       MultiPutCompletionCallback mcb =
+                                               new 
MultiPutCompletionCallback(cb, parent, token);
+                                       SingleBlockInserter dataPutter = new 
SingleBlockInserter(parent, data, codecNumber, FreenetURI.EMPTY_CHK_URI, ctx, 
mcb, metadata, (int) origSize, -1, getCHKOnly, true, false, token);
+                                       Metadata meta = 
makeMetadata(archiveType, bestCodec, dataPutter.getURI());
+                                       Bucket metadataBucket;
+                                       try {
+                                               metadataBucket = 
BucketTools.makeImmutableBucket(ctx.bf, meta.writeToByteArray());
+                                       } catch(IOException e) {
+                                               Logger.error(this, "Caught " + 
e, e);
+                                               throw new 
InsertException(InsertException.BUCKET_ERROR, e, null);
+                                       } catch(MetadataUnresolvedException e) {
+                                               // Impossible, we're not 
inserting a manifest.
+                                               Logger.error(this, "Caught " + 
e, e);
+                                               throw new 
InsertException(InsertException.INTERNAL_ERROR, "Got 
MetadataUnresolvedException in SingleFileInserter: " + e.toString(), null);
+                                       }
+                                       ClientPutState metaPutter = 
createInserter(parent, metadataBucket, (short) -1, block.desiredURI, ctx, mcb, 
true, (int) origSize, -1, getCHKOnly, true, false);
+                                       mcb.addURIGenerator(metaPutter);
+                                       mcb.add(dataPutter);
+                                       cb.onTransition(this, mcb);
+                                       Logger.minor(this, "" + mcb + " : data 
" + dataPutter + " meta " + metaPutter);
+                                       mcb.arm();
+                                       dataPutter.schedule();
+                                       if(metaPutter instanceof 
SingleBlockInserter)
+                                               ((SingleBlockInserter) 
metaPutter).encode();
+                                       metaPutter.schedule();
+                                       cb.onBlockSetFinished(this);
+                               }
                                return;
                        }
-               }
-               if (fitsInOneCHK) {
-                       // Insert single block, then insert pointer to it
+                       // Otherwise the file is too big to fit into one block
+                       // We therefore must make a splitfile
+                       // Job of SplitHandler: when the splitinserter has the 
metadata,
+                       // insert it. Then when the splitinserter has finished, 
and the
+                       // metadata insert has finished too, tell the master 
callback.
                        if(reportMetadataOnly) {
-                               SingleBlockInserter dataPutter = new 
SingleBlockInserter(parent, data, codecNumber, FreenetURI.EMPTY_CHK_URI, ctx, 
cb, metadata, (int)origSize, -1, getCHKOnly, true, true, token);
-                               Metadata meta = 
makeMetadata(dataPutter.getURI());
-                               cb.onMetadata(meta, this);
-                               cb.onTransition(this, dataPutter);
-                               dataPutter.schedule();
-                               cb.onBlockSetFinished(this);
+                               SplitFileInserter sfi = new 
SplitFileInserter(parent, cb, data, bestCodec, origSize, block.clientMetadata, 
ctx, getCHKOnly, metadata, token, archiveType, shouldFreeData);
+                               cb.onTransition(this, sfi);
+                               sfi.start();
+                               if(earlyEncode)
+                                       sfi.forceEncode();
                        } else {
-                               MultiPutCompletionCallback mcb = 
-                                       new MultiPutCompletionCallback(cb, 
parent, token);
-                               SingleBlockInserter dataPutter = new 
SingleBlockInserter(parent, data, codecNumber, FreenetURI.EMPTY_CHK_URI, ctx, 
mcb, metadata, (int)origSize, -1, getCHKOnly, true, false, token);
-                               Metadata meta = 
makeMetadata(dataPutter.getURI());
-                               Bucket metadataBucket;
-                               try {
-                                       metadataBucket = 
BucketTools.makeImmutableBucket(ctx.bf, meta.writeToByteArray());
-                               } catch (IOException e) {
-                                       Logger.error(this, "Caught "+e, e);
-                                       throw new 
InsertException(InsertException.BUCKET_ERROR, e, null);
-                               } catch (MetadataUnresolvedException e) {
-                                       // Impossible, we're not inserting a 
manifest.
-                                       Logger.error(this, "Caught "+e, e);
-                                       throw new 
InsertException(InsertException.INTERNAL_ERROR, "Got 
MetadataUnresolvedException in SingleFileInserter: "+e.toString(), null);
-                               }
-                               ClientPutState metaPutter = 
createInserter(parent, metadataBucket, (short) -1, block.desiredURI, ctx, mcb, 
true, (int)origSize, -1, getCHKOnly, true, false);
-                               mcb.addURIGenerator(metaPutter);
-                               mcb.add(dataPutter);
-                               cb.onTransition(this, mcb);
-                               Logger.minor(this, ""+mcb+" : data 
"+dataPutter+" meta "+metaPutter);
-                               mcb.arm();
-                               dataPutter.schedule();
-                               if(metaPutter instanceof SingleBlockInserter)
-                                       
((SingleBlockInserter)metaPutter).encode();
-                               metaPutter.schedule();
-                               cb.onBlockSetFinished(this);
+                               SplitHandler sh = new SplitHandler();
+                               SplitFileInserter sfi = new 
SplitFileInserter(parent, sh, data, bestCodec, origSize, block.clientMetadata, 
ctx, getCHKOnly, metadata, token, archiveType, shouldFreeData);
+                               sh.sfi = sfi;
+                               cb.onTransition(this, sh);
+                               sfi.start();
+                               if(earlyEncode)
+                                       sfi.forceEncode();
                        }
-                       return;
+               } catch(InsertException e) {
+                       onFailure(e, this);
                }
-               // Otherwise the file is too big to fit into one block
-               // We therefore must make a splitfile
-               // Job of SplitHandler: when the splitinserter has the metadata,
-               // insert it. Then when the splitinserter has finished, and the
-               // metadata insert has finished too, tell the master callback.
-               if(reportMetadataOnly) {
-                       SplitFileInserter sfi = new SplitFileInserter(parent, 
cb, data, bestCodec, origSize, block.clientMetadata, ctx, getCHKOnly, metadata, 
token, insertAsArchiveManifest, freeData);
-                       cb.onTransition(this, sfi);
-                       sfi.start();
-                       if(earlyEncode) sfi.forceEncode();
-               } else {
-                       SplitHandler sh = new SplitHandler();
-                       SplitFileInserter sfi = new SplitFileInserter(parent, 
sh, data, bestCodec, origSize, block.clientMetadata, ctx, getCHKOnly, metadata, 
token, insertAsArchiveManifest, freeData);
-                       sh.sfi = sfi;
-                       cb.onTransition(this, sh);
-                       sfi.start();
-                       if(earlyEncode) sfi.forceEncode();
-               }
        }

-       private Metadata makeMetadata(FreenetURI uri) {
-               Metadata meta = new Metadata(insertAsArchiveManifest ? 
Metadata.ZIP_MANIFEST : Metadata.SIMPLE_REDIRECT, uri, block.clientMetadata);
+       private Metadata makeMetadata(ARCHIVE_TYPE archiveType, COMPRESSOR_TYPE 
codec, FreenetURI uri) {
+               Metadata meta = null;
+               if(archiveType != null)
+                       meta = new Metadata(Metadata.ARCHIVE_MANIFEST, 
archiveType, codec, uri, block.clientMetadata);
+               else  // redirect
+                       meta = new Metadata(Metadata.SIMPLE_REDIRECT, 
archiveType, codec, uri, block.clientMetadata);
                if(targetFilename != null) {
                        HashMap hm = new HashMap();
                        hm.put(targetFilename, meta);
@@ -360,7 +368,7 @@
                        if(sfiFS == null)
                                throw new ResumeException("No 
SplitFileInserter");
                        ClientPutState newSFI, newMetaPutter = null;
-                       newSFI = new SplitFileInserter(parent, this, 
forceMetadata ? null : block.clientMetadata, ctx, getCHKOnly, meta, token, 
insertAsArchiveManifest, sfiFS);
+                       newSFI = new SplitFileInserter(parent, this, 
forceMetadata ? null : block.clientMetadata, ctx, getCHKOnly, meta, token, 
archiveType, sfiFS);
                        if(logMINOR) Logger.minor(this, "Starting "+newSFI+" 
for "+this);
                        fs.removeSubset("SplitFileInserter");
                        SimpleFieldSet metaFS = fs.subset("MetadataPutter");
@@ -370,7 +378,7 @@
                                        if(type.equals("SplitFileInserter")) {
                                                // FIXME 
insertAsArchiveManifest ?!?!?!
                                                newMetaPutter = 
-                                                       new 
SplitFileInserter(parent, this, null, ctx, getCHKOnly, true, token, 
insertAsArchiveManifest, metaFS);
+                                                       new 
SplitFileInserter(parent, this, null, ctx, getCHKOnly, true, token, 
archiveType, metaFS);
                                        } else if(type.equals("SplitHandler")) {
                                                newMetaPutter = new 
SplitHandler();
                                                
((SplitHandler)newMetaPutter).start(metaFS, true);
@@ -519,7 +527,7 @@
                        InsertBlock newBlock = new InsertBlock(metadataBucket, 
null, block.desiredURI);
                        try {
                                synchronized(this) {
-                                       metadataPutter = new 
SingleFileInserter(parent, this, newBlock, true, ctx, false, getCHKOnly, false, 
token, false, true, metaPutterTargetFilename, earlyEncode);
+                                       metadataPutter = new 
SingleFileInserter(parent, this, newBlock, true, ctx, false, getCHKOnly, false, 
token, archiveType, true, metaPutterTargetFilename, earlyEncode);
                                        // If EarlyEncode, then start the 
metadata insert ASAP, to get the key.
                                        // Otherwise, wait until the data is 
fetchable (to improve persistence).
                                        if(!(earlyEncode || 
splitInsertSuccess)) return;
@@ -698,4 +706,11 @@
        public SimpleFieldSet getProgressFieldset() {
                return null;
        }
+
+       public void onFailure(InsertException e, ClientPutState c) {
+               if(cb != null)
+                       cb.onFailure(e, c);
+               else
+                       Logger.error(this, "The callback is null but we have 
onFailure to call!");
+       }
 }

Modified: trunk/freenet/src/freenet/client/async/SplitFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileInserter.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/async/SplitFileInserter.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -3,6 +3,7 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.client.async;

+import freenet.client.ArchiveManager.ARCHIVE_TYPE;
 import java.io.IOException;
 import java.util.Vector;

@@ -17,7 +18,7 @@
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
 import freenet.support.api.Bucket;
-import freenet.support.compress.Compressor;
+import freenet.support.compress.Compressor.COMPRESSOR_TYPE;
 import freenet.support.io.BucketTools;

 public class SplitFileInserter implements ClientPutState {
@@ -27,7 +28,7 @@
        final InsertContext ctx;
        final PutCompletionCallback cb;
        final long dataLength;
-       final short compressionCodec;
+       final COMPRESSOR_TYPE compressionCodec;
        final short splitfileAlgorithm;
        final int segmentSize;
        final int checkSegmentSize;
@@ -41,7 +42,7 @@
        private volatile boolean finished;
        private boolean fetchable;
        public final Object token;
-       final boolean insertAsArchiveManifest;
+       final ARCHIVE_TYPE archiveType;
        private boolean forceEncode;
        private final long decompressedLength;

@@ -52,7 +53,7 @@
                fs.putSingle("Type", "SplitFileInserter");
                fs.put("DataLength", dataLength);
                fs.put("DecompressedLength", decompressedLength);
-               fs.put("CompressionCodec", compressionCodec);
+               fs.putSingle("CompressionCodec", compressionCodec.toString());
                fs.put("SplitfileCodec", splitfileAlgorithm);
                fs.put("Finished", finished);
                fs.put("SegmentSize", segmentSize);
@@ -66,10 +67,11 @@
                return fs;
        }

-       public SplitFileInserter(BaseClientPutter put, PutCompletionCallback 
cb, Bucket data, Compressor bestCodec, long decompressedLength, ClientMetadata 
clientMetadata, InsertContext ctx, boolean getCHKOnly, boolean isMetadata, 
Object token, boolean insertAsArchiveManifest, boolean freeData) throws 
InsertException {
+       public SplitFileInserter(BaseClientPutter put, PutCompletionCallback 
cb, Bucket data, COMPRESSOR_TYPE bestCodec, long decompressedLength, 
ClientMetadata clientMetadata, InsertContext ctx, boolean getCHKOnly, boolean 
isMetadata, Object token, ARCHIVE_TYPE archiveType, boolean freeData) throws 
InsertException {
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
                this.parent = put;
-               this.insertAsArchiveManifest = insertAsArchiveManifest;
+               this.archiveType = archiveType;
+               this.compressionCodec = bestCodec;
                this.token = token;
                this.finished = false;
                this.isMetadata = isMetadata;
@@ -87,10 +89,6 @@
                }
                countDataBlocks = dataBuckets.length;
                // Encoding is done by segments
-               if(bestCodec == null)
-                       compressionCodec = -1;
-               else
-                       compressionCodec = bestCodec.codecNumberForMetadata();
                this.splitfileAlgorithm = ctx.splitfileAlgorithm;
                segmentSize = ctx.splitfileSegmentDataBlocks;
                checkSegmentSize = splitfileAlgorithm == 
Metadata.SPLITFILE_NONREDUNDANT ? 0 : ctx.splitfileSegmentCheckBlocks;
@@ -105,10 +103,10 @@
                parent.onMajorProgress();
        }

-       public SplitFileInserter(BaseClientPutter parent, PutCompletionCallback 
cb, ClientMetadata clientMetadata, InsertContext ctx, boolean getCHKOnly, 
boolean metadata, Object token, boolean insertAsArchiveManifest, SimpleFieldSet 
fs) throws ResumeException {
+       public SplitFileInserter(BaseClientPutter parent, PutCompletionCallback 
cb, ClientMetadata clientMetadata, InsertContext ctx, boolean getCHKOnly, 
boolean metadata, Object token, ARCHIVE_TYPE archiveType, SimpleFieldSet fs) 
throws ResumeException {
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
                this.parent = parent;
-               this.insertAsArchiveManifest = insertAsArchiveManifest;
+               this.archiveType = archiveType;
                this.token = token;
                this.finished = false;
                this.isMetadata = metadata;
@@ -149,12 +147,9 @@
                        throw new ResumeException("Corrupt CheckSegmentSize: 
"+e+" : "+length);
                }
                String ccodec = fs.get("CompressionCodec");
-               if(ccodec == null) throw new ResumeException("No compression 
codec");
-               try {
-                       compressionCodec = Short.parseShort(ccodec);
-               } catch (NumberFormatException e) {
-                       throw new ResumeException("Corrupt CompressionCodec: 
"+e+" : "+ccodec);
-               }
+               if(ccodec == null)
+                       throw new ResumeException("No compression codec");
+               compressionCodec = COMPRESSOR_TYPE.valueOf(ccodec);
                String scodec = fs.get("SplitfileCodec");
                if(scodec == null) throw new ResumeException("No splitfile 
codec");
                try {
@@ -290,7 +285,7 @@

                        if(!missingURIs) {
                                // Create Metadata
-                               m = new Metadata(splitfileAlgorithm, dataURIs, 
checkURIs, segmentSize, checkSegmentSize, cm, dataLength, compressionCodec, 
decompressedLength, isMetadata, insertAsArchiveManifest);
+                               m = new Metadata(splitfileAlgorithm, dataURIs, 
checkURIs, segmentSize, checkSegmentSize, cm, dataLength, archiveType, 
compressionCodec, decompressedLength, isMetadata);
                        }
                        haveSentMetadata = true;
                }

Deleted: trunk/freenet/src/freenet/client/events/BlockInsertErrorEvent.java
===================================================================
--- trunk/freenet/src/freenet/client/events/BlockInsertErrorEvent.java  
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/events/BlockInsertErrorEvent.java  
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,30 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.client.events;
-
-import freenet.client.InsertException;
-import freenet.keys.FreenetURI;
-
-public class BlockInsertErrorEvent implements ClientEvent {
-
-       public static final int code = 0x05;
-       public final InsertException e;
-       public final FreenetURI key;
-       public final int retryNumber;
-
-       public BlockInsertErrorEvent(InsertException e, FreenetURI key, int 
retryNumber) {
-               this.e = e;
-               this.key = key;
-               this.retryNumber = retryNumber;
-       }
-       
-       public String getDescription() {
-               return e.getMessage()+" for "+key+" ("+retryNumber+ ')';
-       }
-
-       public int getCode() {
-               return code;
-       }
-
-}

Deleted: trunk/freenet/src/freenet/client/events/DecodedBlockEvent.java
===================================================================
--- trunk/freenet/src/freenet/client/events/DecodedBlockEvent.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/events/DecodedBlockEvent.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,25 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.client.events;
-
-import freenet.keys.ClientKey;
-
-public class DecodedBlockEvent implements ClientEvent {
-
-       public static final int code = 0x03;
-       public final ClientKey key; 
-       
-       public DecodedBlockEvent(ClientKey key) {
-               this.key = key;
-       }
-
-       public String getDescription() {
-               return "Decoded a block of data: "+key.getURI();
-       }
-
-       public int getCode() {
-               return code;
-       }
-
-}

Deleted: trunk/freenet/src/freenet/client/events/FetchedMetadataEvent.java
===================================================================
--- trunk/freenet/src/freenet/client/events/FetchedMetadataEvent.java   
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/events/FetchedMetadataEvent.java   
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,18 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.client.events;
-
-public class FetchedMetadataEvent implements ClientEvent {
-
-       public final static int code = 0x01;
-       
-       public String getDescription() {
-               return "Fetched metadata";
-       }
-
-       public int getCode() {
-               return code;
-       }
-
-}

Deleted: trunk/freenet/src/freenet/client/events/GeneratedURIEvent.java
===================================================================
--- trunk/freenet/src/freenet/client/events/GeneratedURIEvent.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/events/GeneratedURIEvent.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,24 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.client.events;
-
-import freenet.keys.FreenetURI;
-
-public class GeneratedURIEvent implements ClientEvent {
-
-       public static final int code = 0x06;
-       public final FreenetURI uri;
-
-       public GeneratedURIEvent(FreenetURI uri) {
-               this.uri = uri;
-       }
-       
-       public String getDescription() {
-               return "Generated URI on insert: "+uri;
-       }
-
-       public int getCode() {
-               return code;
-       }
-}

Deleted: trunk/freenet/src/freenet/client/events/GotBlockEvent.java
===================================================================
--- trunk/freenet/src/freenet/client/events/GotBlockEvent.java  2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/events/GotBlockEvent.java  2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,28 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.client.events;
-
-import freenet.keys.ClientKey;
-
-/**
- * Fetched a block of data.
- */
-public class GotBlockEvent implements ClientEvent {
-
-       public static final int code = 0x02;
-       public final ClientKey key; 
-       
-       public GotBlockEvent(ClientKey key) {
-               this.key = key;
-       }
-
-       public String getDescription() {
-               return "Fetched a block of data: "+key.getURI();
-       }
-
-       public int getCode() {
-               return code;
-       }
-
-}

Deleted: trunk/freenet/src/freenet/client/events/SimpleBlockPutEvent.java
===================================================================
--- trunk/freenet/src/freenet/client/events/SimpleBlockPutEvent.java    
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/events/SimpleBlockPutEvent.java    
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,26 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.client.events;
-
-import freenet.keys.ClientKey;
-
-public class SimpleBlockPutEvent implements ClientEvent {
-
-       public final static int code = 0x04;
-       
-       private final ClientKey key;
-       
-       public SimpleBlockPutEvent(ClientKey key) {
-               this.key = key;
-       }
-
-       public String getDescription() {
-               return "Inserting simple key: "+key.getURI();
-       }
-
-       public int getCode() {
-               return code;
-       }
-
-}

Modified: trunk/freenet/src/freenet/client/events/StartedCompressionEvent.java
===================================================================
--- trunk/freenet/src/freenet/client/events/StartedCompressionEvent.java        
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/client/events/StartedCompressionEvent.java        
2008-11-06 13:53:57 UTC (rev 23351)
@@ -3,21 +3,23 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.client.events;

+import freenet.support.compress.Compressor.COMPRESSOR_TYPE;
+
 /**
  * Event indicating that we are attempting to compress the file.
  */
 public class StartedCompressionEvent implements ClientEvent {

-       public final int codec;
+       public final COMPRESSOR_TYPE codec;

-       public StartedCompressionEvent(int codec) {
+       public StartedCompressionEvent(COMPRESSOR_TYPE codec) {
                this.codec = codec;
        }

-       static final int code = 0x08;
+       final static int code = 0x08;

        public String getDescription() {
-               return "Started compression attempt with codec "+codec;
+               return "Started compression attempt with "+codec.name;
        }

        public int getCode() {

Modified: trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java   
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java   
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,20 +1,20 @@
 package freenet.clients.http;

+import static freenet.clients.http.QueueToadlet.MAX_KEY_LENGTH;
+
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URI;
+import java.util.List;

+import freenet.client.HighLevelSimpleClient;
 import freenet.clients.http.bookmark.Bookmark;
+import freenet.clients.http.bookmark.BookmarkCategory;
 import freenet.clients.http.bookmark.BookmarkItem;
-import freenet.clients.http.bookmark.BookmarkItems;
-import freenet.clients.http.bookmark.BookmarkCategory;
-import freenet.clients.http.bookmark.BookmarkCategories;
 import freenet.clients.http.bookmark.BookmarkManager;
-
 import freenet.keys.FreenetURI;
 import freenet.l10n.L10n;
 import freenet.node.NodeClientCore;
-import freenet.client.HighLevelSimpleClient;
 import freenet.support.HTMLNode;
 import freenet.support.Logger;
 import freenet.support.URLDecoder;
@@ -22,12 +22,18 @@
 import freenet.support.URLEncoder;
 import freenet.support.api.HTTPRequest;

+/**
+ * BookmarkEditor Toadlet 
+ * 
+ * Accessible from http://.../bookmarkEditor/
+ */
 public class BookmarkEditorToadlet extends Toadlet {
-
        private static final int MAX_ACTION_LENGTH = 20;
-       private static final int MAX_KEY_LENGTH = QueueToadlet.MAX_KEY_LENGTH;
+       /** Max. bookmark name length */
        private static final int MAX_NAME_LENGTH = 500;
+       /** Max. bookmark path length (e.g. <code>Freenet related software and 
documentation/Freenet Message System</code> ) */
        private static final int MAX_BOOKMARK_PATH_LENGTH = 10 * 
MAX_NAME_LENGTH;
+       
        private final NodeClientCore core;
        private final BookmarkManager bookmarkManager;
        private String cutedPath;
@@ -39,8 +45,11 @@
                this.cutedPath = null;
        }

+       /**
+        * Get all bookmark as a tree of &lt;li&gt;...&lt;/li&gt;s
+        */
        private void addCategoryToList(BookmarkCategory cat, String path, 
HTMLNode list) {
-               BookmarkItems items = cat.getItems();
+               List<BookmarkItem> items = cat.getItems();

                final String edit = 
L10n.getString("BookmarkEditorToadlet.edit");
                final String delete = 
L10n.getString("BookmarkEditorToadlet.delete");
@@ -52,10 +61,11 @@
                final String addCategory = 
L10n.getString("BookmarkEditorToadlet.addCategory");

                for(int i = 0; i < items.size(); i++) {
+                       BookmarkItem item =  items.get(i);
+                               
+                       String itemPath = URLEncoder.encode(path + 
item.getName(), false);
+                       HTMLNode li = new HTMLNode("li", "class", "item", 
item.getName());

-                       String itemPath = URLEncoder.encode(path + 
items.get(i).getName(), false);
-                       HTMLNode li = new HTMLNode("li", "class", "item", 
items.get(i).getName());
-
                        HTMLNode actions = new HTMLNode("span", "class", 
"actions");
                        actions.addChild("a", "href", "?action=edit&bookmark=" 
+ itemPath).addChild("img", new String[]{"src", "alt", "title"}, new 
String[]{"/static/icon/edit.png", edit, edit});

@@ -74,9 +84,8 @@
                        list.addChild(li);
                }

-               BookmarkCategories cats = cat.getSubCategories();
+               List<BookmarkCategory> cats = cat.getSubCategories();
                for(int i = 0; i < cats.size(); i++) {
-
                        String catPath = path + cats.get(i).getName() + '/';
                        String catPathEncoded = URLEncoder.encode(catPath, 
false);


Modified: trunk/freenet/src/freenet/clients/http/BrowserTestToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/BrowserTestToadlet.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/BrowserTestToadlet.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -9,10 +9,13 @@
 import freenet.support.api.HTTPRequest;

 /**
- * Browser Test Toadlet.
- * Usefull to test browser's capabilities :
- *     * warn the user about useless enabled features/plugins wich might be 
dangerous
- *     * Assist the user in configuring his browser properly to surf on freenet
+ * Browser Test Toadlet. Accessible from <code>http://.../test/</code>.
+ * 
+ * Useful to test browser's capabilities:
+ * <ul>
+ * <li>warn the user about useless enabled features/plugins which might be 
dangerous</li>
+ * <li>Assist the user in configuring his browser properly to surf on 
freenet</li>
+ * <ul>
  */
 public class BrowserTestToadlet extends Toadlet {
        BrowserTestToadlet(HighLevelSimpleClient client, NodeClientCore c) {
@@ -204,7 +207,7 @@
                        maxConnectionsPerServerContent.addChild("img", "src", 
".?wontload");
                maxConnectionsPerServerContent.addChild("img", new 
String[]{"src", "alt"}, new String[]{"/static/themes/clean/success.gif", 
"fail!"});

-               // #### Test whether JS is aviable. : should do the test with 
pictures insteed!
+               // #### Test whether JS is available. : should do the test with 
pictures instead!
                HTMLNode jsTestBox = 
contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-warning", 
"Javascript"));
                HTMLNode jsTestContent= 
ctx.getPageMaker().getContentNode(jsTestBox);
                HTMLNode jsTest = jsTestContent.addChild("div");

Modified: trunk/freenet/src/freenet/clients/http/ConfigToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ConfigToadlet.java   2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/ConfigToadlet.java   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -110,7 +110,7 @@
     public void handlePost(URI uri, HTTPRequest request, ToadletContext ctx) 
throws ToadletContextClosedException, IOException {
                String pass = request.getPartAsString("formPassword", 32);
                if((pass == null) || !pass.equals(core.formPassword)) {
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String,String> headers = new 
MultiValueTable<String,String>();
                        headers.put("Location", "/config/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -221,7 +221,7 @@
                                writeHTMLReply(ctx, 200, "OK", 
pageNode.generate());
                                return;
                        } else {
-                               MultiValueTable headers = new MultiValueTable();
+                               MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                                headers.put("Location", 
"/config/?mode="+MODE_SECURITY_LEVELS);
                                ctx.sendReplyHeaders(302, "Found", headers, 
null, 0);
                                return;

Modified: trunk/freenet/src/freenet/clients/http/ConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ConnectionsToadlet.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/ConnectionsToadlet.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -39,10 +39,9 @@
 import freenet.support.TimeUtil;
 import freenet.support.api.HTTPRequest;

+/** Base class for DarknetConnectionsToadlet and OpennetConnectionsToadlet */
 public abstract class ConnectionsToadlet extends Toadlet {
-
-       protected class ComparatorByStatus implements Comparator {
-               
+       protected class ComparatorByStatus implements 
Comparator<PeerNodeStatus> {              
                protected final String sortBy;
                protected final boolean reversed;

@@ -51,11 +50,9 @@
                        this.reversed = reversed;
                }

-               public int compare(Object first, Object second) {
+               public int compare(PeerNodeStatus firstNode, PeerNodeStatus 
secondNode) {
                        int result = 0;
                        boolean isSet = true;
-                       PeerNodeStatus firstNode = (PeerNodeStatus) first;
-                       PeerNodeStatus secondNode = (PeerNodeStatus) second;

                        if(sortBy != null){
                                result = customCompare(firstNode, secondNode, 
sortBy);
@@ -83,7 +80,8 @@
                        }
                }

-               // TODO: check why we do not just return the result of 
(long1-long2)
+               // xor: check why we do not just return the result of 
(long1-long2)
+               // j16sdiz: (Long.MAX_VALUE - (-1) ) would overflow and become 
negative
                private int compareLongs(long long1, long long2) {
                        int diff = Long.valueOf(long1).compareTo(long2);
                        if(diff == 0)
@@ -180,7 +178,7 @@
                        SimpleFieldSet fs = getNoderef();
                        StringWriter sw = new StringWriter();
                        fs.writeTo(sw);
-                       MultiValueTable extraHeaders = new MultiValueTable();
+                       MultiValueTable<String, String> extraHeaders = new 
MultiValueTable<String, String>();
                        // Force download to disk
                        extraHeaders.put("Content-Disposition", "attachment; 
filename=myref.fref");
                        this.writeReply(ctx, 200, 
"application/x-freenet-reference", "OK", extraHeaders, sw.toString());
@@ -499,7 +497,7 @@

                String pass = request.getPartAsString("formPassword", 32);
                if((pass == null) || !pass.equals(core.formPassword)) {
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", defaultRedirectLocation());
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        if(logMINOR) Logger.minor(this, "No password ("+pass+" 
should be "+core.formPassword+ ')');
@@ -607,7 +605,7 @@
                                return;
                        }

-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", defaultRedirectLocation());
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -690,7 +688,7 @@
                peerAdditionForm.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "submit", "add", l10n("add") });
        }

-       protected Comparator comparator(String sortBy, boolean reversed) {
+       protected Comparator<PeerNodeStatus> comparator(String sortBy, boolean 
reversed) {
                return new ComparatorByStatus(sortBy, reversed);
        }

@@ -839,35 +837,35 @@
                countHeaderRow.addChild("th", "Message");
                countHeaderRow.addChild("th", "Incoming");
                countHeaderRow.addChild("th", "Outgoing");
-               List messageNames = new ArrayList();
-               Map messageCounts = new HashMap();
-               for (Iterator incomingMessages = 
peerNodeStatus.getLocalMessagesReceived().keySet().iterator(); 
incomingMessages.hasNext(); ) {
-                       String messageName = (String) incomingMessages.next();
+               List<String> messageNames = new ArrayList<String>();
+               Map<String, Long[]> messageCounts = new HashMap<String, 
Long[]>();
+               for (Map.Entry<String,Long> entry : 
peerNodeStatus.getLocalMessagesReceived().entrySet() ) {
+                       String messageName = entry.getKey();
+                       Long messageCount = entry.getValue();
                        messageNames.add(messageName);
-                       Long messageCount = (Long) 
peerNodeStatus.getLocalMessagesReceived().get(messageName);
                        messageCounts.put(messageName, new Long[] { 
messageCount, new Long(0) });
                }
-               for (Iterator outgoingMessages = 
peerNodeStatus.getLocalMessagesSent().keySet().iterator(); 
outgoingMessages.hasNext(); ) {
-                       String messageName = (String) outgoingMessages.next();
+               for (Map.Entry<String,Long> entry : 
peerNodeStatus.getLocalMessagesSent().entrySet() ) {
+                       String messageName =  entry.getKey();
+                       Long messageCount = entry.getValue();
                        if (!messageNames.contains(messageName)) {
                                messageNames.add(messageName);
                        }
-                       Long messageCount = (Long) 
peerNodeStatus.getLocalMessagesSent().get(messageName);
-                       Long[] existingCounts = (Long[]) 
messageCounts.get(messageName);
+                       Long[] existingCounts = messageCounts.get(messageName);
                        if (existingCounts == null) {
                                messageCounts.put(messageName, new Long[] { new 
Long(0), messageCount });
                        } else {
                                existingCounts[1] = messageCount;
                        }
                }
-               Collections.sort(messageNames, new Comparator() {
-                       public int compare(Object first, Object second) {
-                               return ((String) 
first).compareToIgnoreCase((String) second);
+               Collections.sort(messageNames, new Comparator<String>() {
+                       public int compare(String first, String second) {
+                               return first.compareToIgnoreCase(second);
                        }
                });
-               for (Iterator messageNamesIterator = messageNames.iterator(); 
messageNamesIterator.hasNext(); ) {
-                       String messageName = (String) 
messageNamesIterator.next();
-                       Long[] messageCount = (Long[]) 
messageCounts.get(messageName);
+               for (Iterator<String> messageNamesIterator = 
messageNames.iterator(); messageNamesIterator.hasNext(); ) {
+                       String messageName = messageNamesIterator.next();
+                       Long[] messageCount = messageCounts.get(messageName);
                        HTMLNode messageRow = messageCountTable.addChild("tr");
                        messageRow.addChild("td", messageName);
                        messageRow.addChild("td", "class", "right-align", 
String.valueOf(messageCount[0]));
@@ -890,6 +888,4 @@
        private String sortString(boolean isReversed, String type) {
                return (isReversed ? ("?sortBy="+type) : 
("?sortBy="+type+"&reversed"));
        }
-
-
 }

Modified: trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -59,7 +59,7 @@
        }

        @Override
-       protected Comparator comparator(String sortBy, boolean reversed) {
+       protected Comparator<PeerNodeStatus> comparator(String sortBy, boolean 
reversed) {
                return new DarknetComparator(sortBy, reversed);
        }

@@ -167,10 +167,9 @@
                        HTMLNode pageNode = 
ctx.getPageMaker().getPageNode(l10n("sendMessageTitle"), ctx);
                        HTMLNode contentNode = 
ctx.getPageMaker().getContentNode(pageNode);
                        DarknetPeerNode[] peerNodes = 
node.getDarknetConnections();
-                       HashMap peers = new HashMap();
-                       for(int i = 0; i < peerNodes.length; i++) {
-                               if 
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
-                                       DarknetPeerNode pn = peerNodes[i];
+                       HashMap<String, String> peers = new HashMap<String, 
String>();
+                       for(DarknetPeerNode pn : peerNodes) {
+                               if (request.isPartSet("node_"+pn.hashCode())) {
                                        String peer_name = pn.getName();
                                        String peer_hash = "" + pn.hashCode();
                                        if(!peers.containsKey(peer_hash)) {
@@ -192,7 +191,7 @@
                                        }
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -205,7 +204,7 @@
                                        peerNodes[i].enablePeer();
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -218,7 +217,7 @@
                                        peerNodes[i].disablePeer();
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -231,7 +230,7 @@
                                        peerNodes[i].setBurstOnly(true);
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -244,7 +243,7 @@
                                        peerNodes[i].setBurstOnly(false);
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -257,7 +256,7 @@
                                        peerNodes[i].setIgnoreSourcePort(true);
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -270,7 +269,7 @@
                                        peerNodes[i].setIgnoreSourcePort(false);
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -281,7 +280,7 @@
                                        peerNodes[i].setRoutingStatus(true, 
true);
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -292,7 +291,7 @@
                                        peerNodes[i].setRoutingStatus(false, 
true);
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -305,7 +304,7 @@
                                        peerNodes[i].setListenOnly(true);
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -318,7 +317,7 @@
                                        peerNodes[i].setListenOnly(false);
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -331,7 +330,7 @@
                                        
peerNodes[i].setAllowLocalAddresses(true);
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -344,7 +343,7 @@
                                        
peerNodes[i].setAllowLocalAddresses(false);
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -378,7 +377,7 @@
                                        if(logMINOR) Logger.minor(this, "Part 
not set: node_"+peerNodes[i].hashCode());
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -392,7 +391,7 @@
                                        break;
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -406,7 +405,7 @@
                                        break;
                                }
                        }
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/friends/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;

Modified: trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -44,7 +44,7 @@
        final NodeClientCore core;

        private static FoundURICallback prefetchHook;
-       static final Set prefetchAllowedTypes = new HashSet();
+       static final Set<String> prefetchAllowedTypes = new HashSet<String>();
        static {
                // Only valid inlines
                prefetchAllowedTypes.add("image/png");
@@ -192,20 +192,20 @@
                                                        new String[] { "<a 
href=\"/\">", "</a>" });

                                        byte[] pageBytes = 
pageNode.generate().getBytes("UTF-8");
-                                       context.sendReplyHeaders(200, "OK", new 
MultiValueTable(), "text/html; charset=utf-8", pageBytes.length);
+                                       context.sendReplyHeaders(200, "OK", new 
MultiValueTable<String, String>(), "text/html; charset=utf-8", 
pageBytes.length);
                                        context.writeData(pageBytes);
                                        return;
                                }
                        }

                        if (forceDownload) {
-                               MultiValueTable headers = new MultiValueTable();
+                               MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                                headers.put("Content-Disposition", "attachment; 
filename=\"" + key.getPreferredFilename() + '"');
                                context.sendReplyHeaders(200, "OK", headers, 
"application/x-msdownload", data.size());
                                context.writeData(data);
                        } else {
                                // Send the data, intact
-                               context.sendReplyHeaders(200, "OK", new 
MultiValueTable(), mimeType, data.size());
+                               context.sendReplyHeaders(200, "OK", new 
MultiValueTable<String, String>(), mimeType, data.size());
                                context.writeData(data);
                        }
                } catch (URISyntaxException use1) {
@@ -223,15 +223,18 @@
                        
infoboxContent.addChild("p").addChild(e.getHTMLExplanation());
                        infoboxContent.addChild("p", l10n("options"));
                        HTMLNode optionList = infoboxContent.addChild("ul");
-                       HTMLNode option = optionList.addChild("li");
-                       L10n.addL10nSubstitution(option, 
"FProxyToadlet.openAsText", new String[] { "link", "/link" }, new String[] { 
"<a href=\""+basePath+key.toString()+"?type=text/plain"+extrasNoMime+"\">", 
"</a>" });
-                       // FIXME: is this safe? See bug #131
+                       HTMLNode option;

                        if((mimeType.equals("application/x-freenet-index")) && 
(core.node.pluginManager.isPluginLoaded("plugins.ThawIndexBrowser.ThawIndexBrowser")))
 {
                                option = optionList.addChild("li");
-                               L10n.addL10nSubstitution(option, 
"FProxyToadlet.openAsThawIndex", new String[] { "link", "/link" }, new String[] 
{ "<a href=\""+basePath + 
"plugins/plugins.ThawIndexBrowser.ThawIndexBrowser/?key=" + key.toString() + 
"\">", "</a>" });
+                               L10n.addL10nSubstitution(option, 
"FProxyToadlet.openAsThawIndex", new String[] { "link", "/link" }, new String[] 
{ "<b><a href=\""+basePath + 
"plugins/plugins.ThawIndexBrowser.ThawIndexBrowser/?key=" + key.toString() + 
"\">", "</a></b>" });
                        }
+                       
                        option = optionList.addChild("li");
+                       // FIXME: is this safe? See bug #131
+                       L10n.addL10nSubstitution(option, 
"FProxyToadlet.openAsText", new String[] { "link", "/link" }, new String[] { 
"<a href=\""+basePath+key.toString()+"?type=text/plain"+extrasNoMime+"\">", 
"</a>" });
+
+                       option = optionList.addChild("li");
                        L10n.addL10nSubstitution(option, 
"FProxyToadlet.openForceDisk", new String[] { "link", "/link" }, new String[] { 
"<a href=\""+basePath+key.toString()+"?forcedownload"+extras+"\">", "</a>" });
                        if(!(mimeType.equals("application/octet-stream") || 
mimeType.equals("application/x-msdownload"))) {
                                option = optionList.addChild("li");
@@ -256,7 +259,7 @@
                        }

                        byte[] pageBytes = 
pageNode.generate().getBytes("UTF-8");
-                       context.sendReplyHeaders(200, "OK", new 
MultiValueTable(), "text/html; charset=utf-8", pageBytes.length);
+                       context.sendReplyHeaders(200, "OK", new 
MultiValueTable<String, String>(), "text/html; charset=utf-8", 
pageBytes.length);
                        context.writeData(pageBytes);
                }
        }
@@ -330,8 +333,6 @@

                if (ks.equals("/")) {
                        if (httprequest.isParameterSet("key")) {
-                               MultiValueTable headers = new MultiValueTable();
-                               
                                String k = httprequest.getParam("key");
                                FreenetURI newURI;
                                try {
@@ -344,12 +345,13 @@

                                if(logMINOR) Logger.minor(this, "Redirecting to 
FreenetURI: "+newURI);
                                String type = httprequest.getParam("type");
+                               String location;
                                if ((type != null) && (type.length() > 0)) {
-                                       headers.put("Location", "/"+newURI + 
"?type=" + type);
+                                       location =  "/"+newURI + "?type=" + 
type;
                                } else {
-                                       headers.put("Location", "/"+newURI);
+                                       location =  "/"+newURI;
                                }
-                               ctx.sendReplyHeaders(302, "Found", headers, 
null, 0);
+                               writeTemporaryRedirect(ctx, null, location);
                                return;
                        }

@@ -386,15 +388,11 @@
                }else if(ks.equals("/robots.txt") && ctx.doRobots()){
                        this.writeTextReply(ctx, 200, "Ok", "User-agent: 
*\nDisallow: /");
                        return;
-               }else if(ks.startsWith("/darknet/")) { //TODO: remove when 
obsolete
-                       MultiValueTable headers = new MultiValueTable();
-                       headers.put("Location", "/friends/");
-                       ctx.sendReplyHeaders(301, "Permanent Redirect", 
headers, null, 0);
+               }else if(ks.startsWith("/darknet/") || ks.equals("/darknet")) { 
//TODO (pre-build 1045 url format) remove when obsolete
+                       writePermanentRedirect(ctx, "obsoleted", "/friends/");
                        return;
-               }else if(ks.startsWith("/opennet/")) { //TODO: remove when 
obsolete
-                       MultiValueTable headers = new MultiValueTable();
-                       headers.put("Location", "/strangers/");
-                       ctx.sendReplyHeaders(301, "Permanent Redirect", 
headers, null, 0);
+               }else if(ks.startsWith("/opennet/") || ks.equals("/opennet")) { 
//TODO (pre-build 1045 url format) remove when obsolete
+                       writePermanentRedirect(ctx, "obsoleted", "/strangers/");
                        return;
                }

@@ -611,7 +609,7 @@

        private String sanitizeReferer(ToadletContext ctx) {
                // FIXME we do something similar in the GenericFilterCallback 
thingy?
-               String referer = (String) ctx.getHeaders().get("referer");
+               String referer = ctx.getHeaders().get("referer");
                if(referer != null) {
                        try {
                                URI refererURI = new URI(referer);

Modified: trunk/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java  
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java  
2008-11-06 13:53:57 UTC (rev 23351)
@@ -45,7 +45,8 @@
                BANDWIDTH,
                DATASTORE_SIZE,
                MEMORY,
-               CONGRATZ;
+               CONGRATZ,
+               FINAL;
        }


@@ -271,10 +272,19 @@
                        congratzInfoboxHeader.addChild("#", l10n("congratz"));
                        congratzInfoboxContent.addChild("p", 
l10n("congratzLong"));

-                       congratzInfoboxContent.addChild("a", "href", "/", 
L10n.getString("FirstTimeWizardToadlet.continueEnd"));
+                       congratzInfoboxContent.addChild("a", "href", 
"?step="+WIZARD_STEP.FINAL, 
L10n.getString("FirstTimeWizardToadlet.continueEnd"));

                        this.writeHTMLReply(ctx, 200, "OK", 
pageNode.generate());
                        return;
+               } else if(currentStep == WIZARD_STEP.FINAL) {
+                       try {
+                               config.get("fproxy").set("hasCompletedWizard", 
true);
+                                config.store();
+                               this.writeTemporaryRedirect(ctx, "Return to 
home", "/");
+                       } catch (ConfigException e) {
+                               Logger.error(this, e.getMessage(), e);
+                       }
+                       return;
                }

                HTMLNode pageNode = 
ctx.getPageMaker().getPageNode(l10n("homepageTitle"), false, ctx);
@@ -291,7 +301,7 @@
                secondParagraph.addChild("a", "href", 
"?step="+WIZARD_STEP.SECURITY_NETWORK).addChild("#", 
L10n.getString("FirstTimeWizardToadlet.clickContinue"));

                HTMLNode thirdParagraph = welcomeInfoboxContent.addChild("p");
-               thirdParagraph.addChild("a", "href", "/").addChild("#", 
l10n("skipWizard"));
+               thirdParagraph.addChild("a", "href", 
"?step="+WIZARD_STEP.FINAL).addChild("#", l10n("skipWizard"));

                this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
        }

Modified: trunk/freenet/src/freenet/clients/http/HTTPRequestImpl.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/HTTPRequestImpl.java 2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/HTTPRequestImpl.java 2008-11-06 
13:53:57 UTC (rev 23351)
@@ -3,7 +3,6 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.clients.http;

-import freenet.support.Fields;
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.DataInputStream;
@@ -16,12 +15,12 @@
 import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.StringTokenizer;

+import freenet.support.Fields;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
 import freenet.support.SimpleReadOnlyArrayBucket;
@@ -35,7 +34,7 @@

 /**
  * Used for passing all HTTP request information to the FredPlugin that handles
- * the request. It parses the query string and has several methods for acessing
+ * the request. It parses the query string and has several methods for 
accessing
  * the request parameter values.
  * 
  * @author nacktschneck
@@ -43,13 +42,12 @@
 public class HTTPRequestImpl implements HTTPRequest {

        /**
-        * This map is used to store all parameter values. The name (as String) 
of
-        * the parameter is used as key, the returned value is a list (of 
Strings)
-        * with all values for that parameter sent in the request. You shouldn't
-        * access this map directly, use {@link #getParameterValueList(String)} 
and
-        * {@link #isParameterSet(String)} insted
+        * This map is used to store all parameter values.
+        *  
+        * Don't access this map directly, use {@link 
#getParameterValueList(String)} and
+        * {@link #isParameterSet(String)} instead
         */
-       private final Map parameterNameValuesMap = new HashMap();
+       private final Map<String, List<String>> parameterNameValuesMap = new 
HashMap<String, List<String>>();

        /**
         * the original URI as given to the constructor
@@ -59,7 +57,7 @@
        /**
         * The headers sent by the client
         */
-       private MultiValueTable headers;
+       private MultiValueTable<String, String> headers;

        /**
         * The data sent in the connection
@@ -67,12 +65,12 @@
        private Bucket data;

        /**
-        * A hasmap of buckets that we use to store all the parts for a 
multipart/form-data request
+        * A hashmap of buckets that we use to store all the parts for a 
multipart/form-data request
         */
-       private HashMap parts;
+       private HashMap<String, Bucket> parts;

        /** A map for uploaded files. */
-       private Map uploadedFiles = new HashMap();
+       private Map<String, HTTPUploadedFileImpl> uploadedFiles = new 
HashMap<String, HTTPUploadedFileImpl>();

        private final BucketFactory bucketfactory;

@@ -124,7 +122,7 @@
                this.headers = ctx.getHeaders();
                this.parseRequestParameters(uri.getRawQuery(), true, false);
                this.data = d;
-               this.parts = new HashMap();
+               this.parts = new HashMap<String, Bucket>();
                this.bucketfactory = ctx.getBucketFactory();
                if(data != null) {
                        try {
@@ -226,7 +224,7 @@
                                        Logger.minor(this, "Added as part: 
name="+name+" value="+value);
                        } else {
                                // get the list of values for this parameter 
that were parsed so far
-                               List valueList = 
this.getParameterValueList(name);
+                               List<String> valueList = 
this.getParameterValueList(name);
                                // add this value to the list
                                valueList.add(value);
                        }
@@ -245,8 +243,8 @@
                if (!this.isParameterSet(name)) {
                        return null;
                }
-               List allValues = this.getParameterValueList(name);
-               return (String) allValues.get(0);
+               List<String> allValues = this.getParameterValueList(name);
+               return allValues.get(0);
        }

        /**
@@ -262,10 +260,10 @@
         * @return the list of all values for this parameter that were parsed so
         *         far.
         */
-       private List getParameterValueList(String name) {
-               List values = (List) this.parameterNameValuesMap.get(name);
+       private List<String> getParameterValueList(String name) {
+               List<String> values = this.parameterNameValuesMap.get(name);
                if (values == null) {
-                       values = new LinkedList();
+                       values = new LinkedList<String>();
                        this.parameterNameValuesMap.put(name, values);
                }
                return values;
@@ -339,7 +337,7 @@
         * @see 
freenet.clients.http.HTTPRequest#getMultipleParam(java.lang.String)
         */
        public String[] getMultipleParam(String name) {
-               List valueList = this.getParameterValueList(name);
+               List<String> valueList = this.getParameterValueList(name);
                String[] values = new String[valueList.size()];
                valueList.toArray(values);
                return values;
@@ -349,13 +347,13 @@
         * @see 
freenet.clients.http.HTTPRequest#getMultipleIntParam(java.lang.String)
         */
        public int[] getMultipleIntParam(String name) {
-               List valueList = this.getParameterValueList(name);
+               List<String> valueList = this.getParameterValueList(name);

                // try parsing all values and put the valid Integers in a new 
list
-               List intValueList = new ArrayList();
+               List<Integer> intValueList = new ArrayList<Integer>();
                for (int i = 0; i < valueList.size(); i++) {
                        try {
-                               intValueList.add(new Integer((String) 
valueList.get(i)));
+                               intValueList.add(new Integer(valueList.get(i)));
                        } catch (Exception e) {
                                // ignore invalid parameter values
                        }
@@ -364,7 +362,7 @@
                // convert the valid Integers to an array of ints
                int[] values = new int[intValueList.size()];
                for (int i = 0; i < intValueList.size(); i++) {
-                       values[i] = ((Integer) intValueList.get(i)).intValue();
+                       values[i] = intValueList.get(i);
                }
                return values;
        }
@@ -389,7 +387,7 @@
                        boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
                        if(data == null)
                                return;
-                       String ctype = (String) 
this.headers.get("content-type");
+                       String ctype = this.headers.get("content-type");
                        if(ctype == null)
                                return;
                        if(logMINOR)
@@ -512,10 +510,10 @@
                                                if(b == bbound[0])
                                                        offset = 1;
                                                else
-                                                       bbos.write((int) b & 
0xff);
+                                                       bbos.write(b);
                                        }
                                        else
-                                               bbos.write((int) b & 0xff);
+                                               bbos.write(b);
                                }

                                bbos.flush();
@@ -541,14 +539,14 @@
         * @see 
freenet.clients.http.HTTPRequest#getUploadedFile(java.lang.String)
         */
        public HTTPUploadedFile getUploadedFile(String name) {
-               return (HTTPUploadedFile) uploadedFiles.get(name);
+               return uploadedFiles.get(name);
        }

        /* (non-Javadoc)
         * @see freenet.clients.http.HTTPRequest#getPart(java.lang.String)
         */
        public Bucket getPart(String name) {
-               return (Bucket)this.parts.get(name);
+               return this.parts.get(name);
        }

        /* (non-Javadoc)
@@ -573,7 +571,7 @@
         * @see 
freenet.clients.http.HTTPRequest#getPartAsString(java.lang.String, int)
         */
        public byte[] getPartAsBytes(String name, int maxlength) {
-               Bucket part = (Bucket)this.parts.get(name);
+               Bucket part = this.parts.get(name);
                if(part == null) return new byte[0];

                if (part.size() > maxlength) return new byte[0];
@@ -601,11 +599,8 @@
         */
        public void freeParts() {
                if (this.parts == null) return;
-               Iterator i = this.parts.keySet().iterator();

-               while (i.hasNext()) {
-                       String key = (String) i.next();
-                       Bucket b = (Bucket)this.parts.get(key);
+               for (Bucket b : this.parts.values()) {
                        b.free();
                }
                parts.clear();

Modified: trunk/freenet/src/freenet/clients/http/LocalFileInsertToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/LocalFileInsertToadlet.java  
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/LocalFileInsertToadlet.java  
2008-11-06 13:53:57 UTC (rev 23351)
@@ -84,11 +84,8 @@

                if (currentPath.exists() && currentPath.isDirectory() && 
currentPath.canRead()) {
                        File[] files = currentPath.listFiles();
-                       Arrays.sort(files, new Comparator() {
-
-                               public int compare(Object first, Object second) 
{
-                                       File firstFile = (File) first;
-                                       File secondFile = (File) second;
+                       Arrays.sort(files, new Comparator<File>() {
+                               public int compare(File firstFile, File 
secondFile) {
                                        if (firstFile.isDirectory() && 
!secondFile.isDirectory()) {
                                                return -1;
                                        }

Modified: trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java    2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java    2008-11-06 
13:53:57 UTC (rev 23351)
@@ -7,7 +7,6 @@
 import java.io.IOException;
 import java.net.URI;
 import java.util.HashMap;
-import java.util.Iterator;

 import freenet.client.HighLevelSimpleClient;
 import freenet.l10n.L10n;
@@ -80,13 +79,13 @@
                                                .generate());
                                return;
                        }
-                       HashMap peers = new HashMap();
+                       HashMap<String, String> peers = new HashMap<String, 
String>();
                        peers.put(input_hashcode_string, peernode_name);
                        createN2NTMSendForm(pageNode, contentNode, ctx, peers);
                        this.writeHTMLReply(ctx, 200, "OK", 
pageNode.generate());
                        return;
                }
-               MultiValueTable headers = new MultiValueTable();
+               MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                headers.put("Location", "/friends/");
                ctx.sendReplyHeaders(302, "Found", headers, null, 0);
        }
@@ -122,7 +121,7 @@
                        RedirectException {
                String pass = request.getPartAsString("formPassword", 32);
                if ((pass == null) || !pass.equals(core.formPassword)) {
-                       MultiValueTable headers = new MultiValueTable();
+                       MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                        headers.put("Location", "/send_n2ntm/");
                        ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                        return;
@@ -229,13 +228,13 @@
                        this.writeHTMLReply(ctx, 200, "OK", 
pageNode.generate());
                        return;
                }
-               MultiValueTable headers = new MultiValueTable();
+               MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                headers.put("Location", "/friends/");
                ctx.sendReplyHeaders(302, "Found", headers, null, 0);
        }

        public static void createN2NTMSendForm(HTMLNode pageNode,
-                       HTMLNode contentNode, ToadletContext ctx, HashMap peers)
+                       HTMLNode contentNode, ToadletContext ctx, 
HashMap<String, String> peers)
                        throws ToadletContextClosedException, IOException {
                HTMLNode infobox = contentNode.addChild("div", new String[] { 
"class",
                                "id" }, new String[] { "infobox", "n2nbox" });
@@ -245,8 +244,7 @@
                messageTargets.addChild("p", l10n("composingMessageLabel"));
                HTMLNode messageTargetList = messageTargets.addChild("ul");
                // Iterate peers
-               for (Iterator it = peers.values().iterator(); it.hasNext();) {
-                       String peer_name = (String) it.next();
+               for (String peer_name: peers.values()) {
                        messageTargetList.addChild("li", peer_name);
                }
                HTMLNode infoboxContent = infobox.addChild("div", "class",
@@ -254,8 +252,7 @@
                HTMLNode messageForm = ctx.addFormChild(infoboxContent, 
"/send_n2ntm/",
                                "sendN2NTMForm");
                // Iterate peers
-               for (Iterator it = peers.keySet().iterator(); it.hasNext();) {
-                       String peerNodeHash = (String) it.next();
+               for (String peerNodeHash : peers.keySet()) {
                        messageForm.addChild("input", new String[] { "type", 
"name",
                                        "value" }, new String[] { "hidden", 
"node_" + peerNodeHash,
                                        "1" });

Modified: trunk/freenet/src/freenet/clients/http/OpennetConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/OpennetConnectionsToadlet.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/OpennetConnectionsToadlet.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -115,7 +115,7 @@
        }

        @Override
-       protected Comparator comparator(String sortBy, boolean reversed) {
+       protected Comparator<PeerNodeStatus> comparator(String sortBy, boolean 
reversed) {
                return new OpennetComparator(sortBy, reversed);
        }


Modified: trunk/freenet/src/freenet/clients/http/PageMaker.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/PageMaker.java       2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/PageMaker.java       2008-11-06 
13:53:57 UTC (rev 23351)
@@ -5,7 +5,6 @@
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;

@@ -25,13 +24,15 @@
                BOXED("boxed", "Boxed", ""),
                CLEAN("clean", "Clean", "Mr. Proper"),
                GRAYANDBLUE("grayandblue", "Gray And Blue", ""),
-               SKY("sky", "Sky", "");
+               SKY("sky", "Sky", ""),
+                MINIMALBLUE("minimalblue", "Minimal Blue", "A minimalistic 
theme in blue");

                public static final String[] possibleValues = {
                        BOXED.code,
                        CLEAN.code,
                        GRAYANDBLUE.code,
-                       SKY.code
+                       SKY.code,
+                        MINIMALBLUE.code
                };

                public final String code;  // the internal name
@@ -64,13 +65,13 @@
        public static final int MODE_ADVANCED = 2;
        private THEME theme;
        private File override;
-       private final List navigationLinkTexts = new ArrayList();
-       private final List navigationLinkTextsNonFull = new ArrayList();
-       private final Map navigationLinkTitles = new HashMap();
-       private final Map navigationLinks = new HashMap();
-       private final Map contentNodes = new HashMap();
-       private final Map/*<HTMLNode, HTMLNode>*/ headNodes = new HashMap();
-       private final Map /* <String, LinkEnabledCallback> */ 
navigationLinkCallbacks = new HashMap();
+       private final List<String> navigationLinkTexts = new 
ArrayList<String>();
+       private final List<String> navigationLinkTextsNonFull = new 
ArrayList<String>();
+       private final Map<String, String> navigationLinkTitles = new 
HashMap<String, String>();
+       private final Map<String, String> navigationLinks = new HashMap<String, 
String>();
+       private final Map<HTMLNode, HTMLNode> contentNodes = new 
HashMap<HTMLNode, HTMLNode>();
+       private final Map<HTMLNode, HTMLNode> headNodes = new HashMap<HTMLNode, 
HTMLNode>();
+       private final Map<String, LinkEnabledCallback>  navigationLinkCallbacks 
= new HashMap<String, LinkEnabledCallback>();

        private final FredPluginL10n plugin; 
        private final boolean pluginMode;
@@ -126,7 +127,7 @@
        }

        public HTMLNode createBackLink(ToadletContext toadletContext, String 
name) {
-               String referer = (String) 
toadletContext.getHeaders().get("referer");
+               String referer = toadletContext.getHeaders().get("referer");
                if (referer != null) {
                        return new HTMLNode("a", new String[] { "href", "title" 
}, new String[] { referer, name }, name);
                }
@@ -160,12 +161,11 @@
                if (renderNavigationLinks) {
                        HTMLNode navbarDiv = pageDiv.addChild("div", "id", 
"navbar");
                        HTMLNode navbarUl = navbarDiv.addChild("ul", "id", 
"navlist");
-                       for (Iterator navigationLinkIterator = fullAccess ? 
navigationLinkTexts.iterator() : navigationLinkTextsNonFull.iterator(); 
navigationLinkIterator.hasNext();) {
-                               String navigationLink = (String) 
navigationLinkIterator.next();
-                               LinkEnabledCallback cb = (LinkEnabledCallback) 
navigationLinkCallbacks.get(navigationLink);
+                       for (String navigationLink :  fullAccess ? 
navigationLinkTexts : navigationLinkTextsNonFull) {
+                               LinkEnabledCallback cb = 
navigationLinkCallbacks.get(navigationLink);
                                if(cb != null && !cb.isEnabled()) continue;
-                               String navigationTitle = (String) 
navigationLinkTitles.get(navigationLink);
-                               String navigationPath = (String) 
navigationLinks.get(navigationLink);
+                               String navigationTitle = 
navigationLinkTitles.get(navigationLink);
+                               String navigationPath = 
navigationLinks.get(navigationLink);
                                HTMLNode listItem = navbarUl.addChild("li");
                                if (plugin != null)
                                        listItem.addChild("a", new String[] { 
"href", "title" }, new String[] { navigationPath, 
plugin.getString(navigationTitle) }, plugin.getString(navigationLink));
@@ -190,7 +190,7 @@
         *         already been called
         */
        public HTMLNode getHeadNode(HTMLNode pageNode) {
-               return (HTMLNode) headNodes.remove(pageNode);
+               return headNodes.remove(pageNode);
        }

        /**
@@ -207,7 +207,7 @@
         */
        public HTMLNode getContentNode(HTMLNode node) {
                headNodes.remove(node);
-               return (HTMLNode) contentNodes.remove(node);
+               return contentNodes.remove(node);
        }

        public HTMLNode getInfobox(String header) {

Modified: trunk/freenet/src/freenet/clients/http/PproxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/PproxyToadlet.java   2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/PproxyToadlet.java   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -48,7 +48,7 @@
        public void handlePost(URI uri, HTTPRequest request, ToadletContext ctx)
        throws ToadletContextClosedException, IOException {

-               MultiValueTable headers = new MultiValueTable();
+               MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();

                String pass = request.getPartAsString("formPassword", 32);
                if((pass == null) || !pass.equals(core.formPassword)) {
@@ -102,7 +102,7 @@
                        catch (DownloadPluginHTTPException e) {
                                // FIXME: maybe it ought to be defined like 
sendErrorPage : in toadlets

-                               MultiValueTable head = new MultiValueTable();
+                               MultiValueTable<String, String> head = new 
MultiValueTable<String, String>();
                                head.put("Content-Disposition", "attachment; 
filename=\"" + e.filename + '"');
                                
ctx.sendReplyHeaders(DownloadPluginHTTPException.CODE, "Found", head, 
e.mimeType, e.data.length);
                                ctx.writeData(e.data);
@@ -365,7 +365,7 @@
                } catch (DownloadPluginHTTPException e) {
                        // FIXME: maybe it ought to be defined like 
sendErrorPage : in toadlets

-                       MultiValueTable head = new MultiValueTable();
+                       MultiValueTable<String, String> head = new 
MultiValueTable<String, String>();
                        head.put("Content-Disposition", "attachment; 
filename=\"" + e.filename + '"');
                        ctx.sendReplyHeaders(DownloadPluginHTTPException.CODE, 
"Found", head, e.mimeType, e.data.length);
                        ctx.writeData(e.data);

Modified: trunk/freenet/src/freenet/clients/http/QueueToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/QueueToadlet.java    2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/QueueToadlet.java    2008-11-06 
13:53:57 UTC (rev 23351)
@@ -121,7 +121,7 @@
                                        }
                                }

-                               MultiValueTable responseHeaders = new 
MultiValueTable();
+                               MultiValueTable<String, String> responseHeaders 
= new MultiValueTable<String, String>();
                                responseHeaders.put("Location", 
"/files/?key="+insertURI.toACIIString());
                                ctx.sendReplyHeaders(302, "Found", 
responseHeaders, null, 0);
                                return;
@@ -129,7 +129,7 @@

                        String pass = request.getPartAsString("formPassword", 
32);
                        if ((pass.length() == 0) || 
!pass.equals(core.formPassword)) {
-                               MultiValueTable headers = new MultiValueTable();
+                               MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                                headers.put("Location", "/queue/");
                                ctx.sendReplyHeaders(302, "Found", headers, 
null, 0);
                                if(logMINOR) Logger.minor(this, "No 
formPassword: "+pass);
@@ -425,7 +425,7 @@
                                                                                
if ((System.currentTimeMillis() - forceDownloadTime) > 60 * 1000) {
                                                                                
        break loop;
                                                                                
}
-                                                                               
MultiValueTable responseHeaders = new MultiValueTable();
+                                                                               
MultiValueTable<String, String> responseHeaders = new MultiValueTable<String, 
String>();
                                                                                
responseHeaders.put("Content-Disposition", "attachment; filename=\"" + 
clientGet.getURI().getPreferredFilename() + '"');
                                                                                
writeReply(ctx, 200, "application/x-msdownload", "OK", responseHeaders, 
dataBucket);
                                                                                
return;
@@ -617,7 +617,7 @@
                                        }else if(sortBy.equals("size")){
                                                result = 
(firstRequest.getTotalBlocks() - secondRequest.getTotalBlocks()) < 0 ? -1 : 1;
                                        }else if(sortBy.equals("progress")){
-                                               result = 
firstRequest.getSuccessFraction() - secondRequest.getSuccessFraction() < 0 ? -1 
: 1;
+                                               result = 
(firstRequest.getFetchedBlocks() / firstRequest.getMinBlocks() - 
secondRequest.getFetchedBlocks() / secondRequest.getMinBlocks()) < 0 ? -1 : 1;
                                        }else
                                                isSet=false;
                                }else
@@ -854,7 +854,7 @@

                contentNode.addChild(createBulkDownloadForm(ctx, pageMaker));

-               MultiValueTable pageHeaders = new MultiValueTable();
+               MultiValueTable<String, String> pageHeaders = new 
MultiValueTable<String, String>();
                writeHTMLReply(ctx, 200, "OK", pageHeaders, 
pageNode.generate());
        }


Modified: trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java     
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java     
2008-11-06 13:53:57 UTC (rev 23351)
@@ -6,27 +6,19 @@
 import java.io.File;
 import java.io.IOException;
 import java.net.InetAddress;
-import java.net.JarURLConnection;
 import java.net.Socket;
 import java.net.SocketException;
 import java.net.SocketTimeoutException;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.List;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;

 import freenet.clients.http.PageMaker.THEME;
 import freenet.clients.http.bookmark.BookmarkManager;
 import freenet.config.EnumerableOptionCallback;
 import freenet.config.InvalidConfigValueException;
+import freenet.config.NodeNeedRestartException;
 import freenet.config.SubConfig;
 import freenet.crypt.SSL;
 import freenet.io.AllowedHosts;
@@ -46,8 +38,14 @@
 import freenet.support.api.StringCallback;
 import freenet.support.io.ArrayBucketFactory;

+/** 
+ * The Toadlet (HTTP) Server
+ * 
+ * Provide a HTTP server for FProxy
+ */
 public final class SimpleToadletServer implements ToadletContainer, Runnable {
-       
+       /** List of urlPrefix / Toadlet */ 
+       private final LinkedList<ToadletElement> toadlets;
        private static class ToadletElement {
                public ToadletElement(Toadlet t2, String urlPrefix) {
                        t = t2;
@@ -57,32 +55,42 @@
                String prefix;
        }

-       final int port;
-       String bindTo;
+       // Socket / Binding
+       private final int port;
+       private String bindTo;
        private String allowedHosts;
-       final AllowedHosts allowedFullAccess;
-       BucketFactory bf;
-       NetworkInterface networkInterface;
-       private final LinkedList toadlets;
+       private NetworkInterface networkInterface;
+       private boolean ssl = false;
+       public static final int DEFAULT_FPROXY_PORT = 8888;
+       
+       // ACL
+       private final AllowedHosts allowedFullAccess;
+       
+       // Theme 
        private THEME cssTheme;
        private File cssOverride;
-       private Thread myThread;
        private boolean advancedModeEnabled;
-       private boolean ssl = false;
-       private boolean fProxyJavascriptEnabled;
        private final PageMaker pageMaker;
-       private NodeClientCore core;
+       
+       // Control
+       private Thread myThread;
        private final Executor executor;
+       private BucketFactory bf;
+       private NodeClientCore core;
+       
+       // HTTP Option
        private boolean doRobots;
-       public BookmarkManager bookmarkManager;
        private boolean enablePersistentConnections;
        private boolean enableInlinePrefetch;

-       static boolean isPanicButtonToBeShown;
-       public static final int DEFAULT_FPROXY_PORT = 8888;
+       // Something does not really belongs to here
+       static boolean isPanicButtonToBeShown;                          // move 
to QueueToadlet ?
+       public BookmarkManager bookmarkManager;                         // move 
to WelcomeToadlet / BookmarkEditorToadlet ?
+       private volatile boolean fProxyJavascriptEnabled;       // ugh?
+       private volatile boolean fproxyHasCompletedWizard;      // hmmm..

-       class FProxySSLCallback extends BooleanCallback  {
-               
+       // Config Callbacks
+       private class FProxySSLCallback extends BooleanCallback  {
                @Override
                public Boolean get() {
                        return ssl;
@@ -103,8 +111,7 @@
                }
        }

-       static class FProxyPassthruMaxSize extends LongCallback {
-               
+       private static class FProxyPassthruMaxSize extends LongCallback {
                @Override
                public Long get() {
                        return FProxyToadlet.MAX_LENGTH;
@@ -118,27 +125,25 @@
                }
        }

-       class FProxyPortCallback extends IntCallback  {
-               
+       private class FProxyPortCallback extends IntCallback  {
+               private Integer savedPort;
                @Override
                public Integer get() {
-                       return port;
+                       if (savedPort == null)
+                               savedPort = port;
+                       return savedPort;
                }

                @Override
-               public void set(Integer newPort) throws 
InvalidConfigValueException {
-                       if(port != newPort)
-                               throw new 
InvalidConfigValueException(L10n.getString("cannotChangePortOnTheFly"));
-                       // FIXME
+               public void set(Integer newPort) throws 
NodeNeedRestartException {
+                       if(savedPort != (int)newPort) {
+                               savedPort = port;
+                               throw new NodeNeedRestartException("Port cannot 
change on the fly");
+                       }
                }
-               @Override
-               public boolean isReadOnly() {
-                       return true;
-               }
        }

-       class FProxyBindtoCallback extends StringCallback  {
-               
+       private class FProxyBindtoCallback extends StringCallback  {
                @Override
                public String get() {
                        return bindTo;
@@ -154,14 +159,12 @@
                                        // This is an advanced option for 
reasons of reducing clutter,
                                        // but it is expected to be used by 
regular users, not devs.
                                        // So we translate the error messages.
-                                       throw new 
InvalidConfigValueException(l10n("couldNotChangeBindTo", "error", 
e.getLocalizedMessage())); 
+                                       throw new 
InvalidConfigValueException(l10n("couldNotChangeBindTo", "error", 
e.getLocalizedMessage()));
                                }
                        }
                }
        }
-       
-       class FProxyAllowedHostsCallback extends StringCallback  {
-       
+       private class FProxyAllowedHostsCallback extends StringCallback  {
                @Override
                public String get() {
                        return networkInterface.getAllowedHosts();
@@ -174,9 +177,7 @@
                        }
                }
        }
-       
-       class FProxyCSSNameCallback extends StringCallback implements 
EnumerableOptionCallback {
-               
+       private class FProxyCSSNameCallback extends StringCallback implements 
EnumerableOptionCallback {
                @Override
                public String get() {
                        return cssTheme.code;
@@ -191,18 +192,12 @@
                        if (core.node.pluginManager != null)
                                
core.node.pluginManager.setFProxyTheme(cssTheme);
                }
-               
-               public void setPossibleValues(String[] val) {
-                       throw new NullPointerException("Should not happen!");
-               }
-               
+
                public String[] getPossibleValues() {
                        return THEME.possibleValues;
                }
        }
-       
-       class FProxyCSSOverrideCallback extends StringCallback  {
-
+       private class FProxyCSSOverrideCallback extends StringCallback  {
                @Override
                public String get() {
                        return (cssOverride == null ? "" : 
cssOverride.toString());
@@ -224,9 +219,7 @@
                        pageMaker.setOverride(cssOverride);
                }
        }
-       
-       class FProxyEnabledCallback extends BooleanCallback  {
-               
+       private class FProxyEnabledCallback extends BooleanCallback  {
                @Override
                public Boolean get() {
                        synchronized(SimpleToadletServer.this) {
@@ -252,26 +245,7 @@
                        myThread.start();
                }
        }
-       
-       private boolean haveCalledFProxy = false;
-       
-       public void createFproxy() {
-               synchronized(this) {
-                       if(haveCalledFProxy) return;
-                       haveCalledFProxy = true;
-               }
-               bookmarkManager = new BookmarkManager(core);
-               try {
-                       FProxyToadlet.maybeCreateFProxyEtc(core, core.node, 
core.node.config, this, bookmarkManager);
-               } catch (IOException e) {
-                       Logger.error(this, "Could not start fproxy: "+e, e);
-                       System.err.println("Could not start fproxy:");
-                       e.printStackTrace();
-               }
-       }
-       
        private static class FProxyAdvancedModeEnabledCallback extends 
BooleanCallback  {
-               
                private final SimpleToadletServer ts;

                FProxyAdvancedModeEnabledCallback(SimpleToadletServer ts){
@@ -290,7 +264,6 @@
                                ts.enableAdvancedMode(val);
                }
        }
-       
        private static class FProxyJavascriptEnabledCallback extends 
BooleanCallback  {

                private final SimpleToadletServer ts;
@@ -312,6 +285,25 @@
                }
        }

+       private boolean haveCalledFProxy = false;
+       
+       public void createFproxy() {
+               synchronized(this) {
+                       if(haveCalledFProxy) return;
+                       haveCalledFProxy = true;
+               }
+               bookmarkManager = new BookmarkManager(core);
+               try {
+                       FProxyToadlet.maybeCreateFProxyEtc(core, core.node, 
core.node.config, this, bookmarkManager);
+               } catch (IOException e) {
+                       Logger.error(this, "Could not start fproxy: "+e, e);
+                       System.err.println("Could not start fproxy:");
+                       e.printStackTrace();
+               }
+       }
+       
+
+       
        public synchronized void setCore(NodeClientCore core) {
                this.core = core;
        }
@@ -331,46 +323,6 @@

                boolean enabled = fproxyConfig.getBoolean("enabled");

-               List themes = new ArrayList();
-               try {
-                       URL url = getClass().getResource("staticfiles/themes/");
-                       URLConnection urlConnection = url.openConnection();
-                       if (url.getProtocol().equals("file")) {
-                               File themesDirectory = new 
File(URLDecoder.decode(url.getPath(), "ISO-8859-1").replaceAll("\\|", ":"));
-                               File[] themeDirectories = 
themesDirectory.listFiles();
-                               for (int themeIndex = 0; (themeDirectories != 
null) && (themeIndex < themeDirectories.length); themeIndex++) {
-                                       File themeDirectory = 
themeDirectories[themeIndex];
-                                       if (themeDirectory.isDirectory() && 
!themeDirectory.getName().startsWith(".")) {
-                                               
themes.add(themeDirectory.getName());
-                                       }
-                               }       
-                       } else if (urlConnection instanceof JarURLConnection) {
-                               JarURLConnection jarUrlConnection = 
(JarURLConnection) urlConnection;
-                               JarFile jarFile = jarUrlConnection.getJarFile();
-                               Enumeration entries = jarFile.entries();
-                               while (entries.hasMoreElements()) {
-                                       JarEntry entry = (JarEntry) 
entries.nextElement();
-                                       String name = entry.getName();
-                                       if 
(name.startsWith("freenet/clients/http/staticfiles/themes/")) {
-                                               name = 
name.substring("freenet/clients/http/staticfiles/themes/".length());
-                                               if (name.indexOf('/') != -1) {
-                                                       String themeName = 
name.substring(0, name.indexOf('/'));
-                                                       if 
(!themes.contains(themeName)) {
-                                                               
themes.add(themeName);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               } catch (IOException ioe1) {
-                       Logger.error(this, "error creating list of themes", 
ioe1);
-               } catch (NullPointerException npe) {
-                       Logger.error(this, "error creating list of themes", 
npe);
-               } finally {
-                       if (!themes.contains("clean")) {
-                               themes.add("clean");
-                       }
-               }
                fproxyConfig.register("ssl", false, configItemOrder++, true, 
true, "SimpleToadletServer.ssl", "SimpleToadletServer.sslLong",
                                new FProxySSLCallback());
                fproxyConfig.register("port", DEFAULT_FPROXY_PORT, 
configItemOrder++, true, true, "SimpleToadletServer.port", 
"SimpleToadletServer.portLong",
@@ -385,6 +337,21 @@
                                new FProxyAdvancedModeEnabledCallback(this));
                fproxyConfig.register("javascriptEnabled", false, 
configItemOrder++, true, false, "SimpleToadletServer.enableJS", 
"SimpleToadletServer.enableJSLong",
                                new FProxyJavascriptEnabledCallback(this));
+               fproxyConfig.register("hasCompletedWizard", false, 
configItemOrder++, true, false, "SimpleToadletServer.hasCompletedWizard", 
"SimpleToadletServer.hasCompletedWizardLong",
+                               new BooleanCallback() {
+                                       @Override
+                                       public Boolean get() {
+                                               return fproxyHasCompletedWizard;
+                                       }
+
+                                       @Override
+                                       public void set(Boolean val) throws 
InvalidConfigValueException, NodeNeedRestartException {
+                                               if(get().equals(val)) return;
+                                               fproxyHasCompletedWizard = val;
+                                       }
+               });
+               fproxyHasCompletedWizard = 
fproxyConfig.getBoolean("hasCompletedWizard");
+               
                fproxyConfig.register("showPanicButton", false, 
configItemOrder++, true, true, "SimpleToadletServer.panicButton", 
"SimpleToadletServer.panicButtonLong",
                                new BooleanCallback(){
                                @Override
@@ -493,13 +460,13 @@
                pageMaker = new PageMaker(cssTheme);

                if(!fproxyConfig.getOption("CSSOverride").isDefault()) {
-                       cssOverride = new 
File(fproxyConfig.getString("CSSOverride"));                  
+                       cssOverride = new 
File(fproxyConfig.getString("CSSOverride"));
                        pageMaker.setOverride(cssOverride);
                } else
                        cssOverride = null;

-               this.advancedModeEnabled = 
fproxyConfig.getBoolean("advancedModeEnabled");              
-               toadlets = new LinkedList();
+               this.advancedModeEnabled = 
fproxyConfig.getBoolean("advancedModeEnabled");
+               toadlets = new LinkedList<ToadletElement>();

                if(SSL.available()) {
                        ssl = fproxyConfig.getBoolean("ssl");
@@ -521,9 +488,9 @@
                StaticToadlet statictoadlet = new StaticToadlet();
                register(statictoadlet, "/static/", false, false);

+               // "Freenet is starting up..." page, to be removed at 
#removeStartupToadlet()
                startupToadlet = new StartupToadlet(statictoadlet);
                register(startupToadlet, "/", false, false);
-               
        }

        public StartupToadlet startupToadlet;
@@ -574,8 +541,8 @@
        }

        public synchronized void unregister(Toadlet t) {
-               for(Iterator i=toadlets.iterator();i.hasNext();) {
-                       ToadletElement e = (ToadletElement) i.next();
+               for(Iterator<ToadletElement> 
i=toadlets.iterator();i.hasNext();) {
+                       ToadletElement e = i.next();
                        if(e.t == t) {
                                i.remove();
                                return;
@@ -588,13 +555,23 @@
        }

        public Toadlet findToadlet(URI uri) throws PermanentRedirectException {
-               Iterator i = toadlets.iterator();
                String path = uri.getPath();
+
+               // Show the wizard until dismissed by the user (See bug #2624)
+               if(!fproxyHasCompletedWizard) {
+                       
if(!(path.startsWith(FirstTimeWizardToadlet.TOADLET_URL) ||
+                               path.startsWith(StaticToadlet.ROOT_URL)))
+                               try {
+                                       throw new 
PermanentRedirectException(new URI(FirstTimeWizardToadlet.TOADLET_URL));
+                               } catch(URISyntaxException e) { throw new 
Error(e); }
+               }
+
+               Iterator<ToadletElement> i = toadlets.iterator();
                while(i.hasNext()) {
-                       ToadletElement te = (ToadletElement) i.next();
-                       
+                       ToadletElement te = i.next();
+                                               
                        if(path.startsWith(te.prefix))
-                               return te.t;
+                                       return te.t;
                        if(te.prefix.length() > 0 && 
te.prefix.charAt(te.prefix.length()-1) == '/') {
                                if(path.equals(te.prefix.substring(0, 
te.prefix.length()-1))) {
                                        URI newURI;

Modified: trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -31,20 +31,7 @@
 public class StatisticsToadlet extends Toadlet {

        static final NumberFormat thousendPoint = NumberFormat.getInstance();
-       
-       static class MyComparator implements Comparator<Object[]> {
-               public int compare(Object[] row0, Object[] row1) {
-                       Integer stat0 = (Integer) row0[2];  // 2 = status
-                       Integer stat1 = (Integer) row1[2];
-                       int x = stat0.compareTo(stat1);
-                       if(x != 0) return x;
-                       String name0 = (String) row0[9];  // 9 = node name
-                       String name1 = (String) row1[9];
-                       return 
name0.toLowerCase().compareTo(name1.toLowerCase());
-               }

-       }
-
        private static class STMessageCount {
                public String messageName;
                public int messageCount;

Modified: trunk/freenet/src/freenet/clients/http/SymlinkerToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/SymlinkerToadlet.java        
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/SymlinkerToadlet.java        
2008-11-06 13:53:57 UTC (rev 23351)
@@ -4,7 +4,7 @@
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.HashMap;
-import java.util.Iterator;
+import java.util.Map;

 import freenet.client.HighLevelSimpleClient;
 import freenet.config.InvalidConfigValueException;
@@ -15,9 +15,13 @@
 import freenet.support.api.HTTPRequest;
 import freenet.support.api.StringArrCallback;

-public class SymlinkerToadlet extends Toadlet {
-       
-       private final HashMap linkMap = new HashMap();
+/**
+ * Symlinker Toadlet
+ * 
+ * Provide alias to other toadlet URLs by throwing {@link RedirectException}.
+ */
+public class SymlinkerToadlet extends Toadlet {        
+       private final HashMap<String, String> linkMap = new HashMap<String, 
String>();
        private final Node node;
        SubConfig tslconfig;

@@ -46,8 +50,8 @@

                String fns[] = tslconfig.getStringArr("symlinks");
                if (fns != null) {
-                       for (int i = 0 ; i < fns.length ; i++) {
-                               String tuple[] = fns[i].split("#");
+                       for (String fn : fns) {
+                               String tuple[] = fn.split("#");
                                if (tuple.length == 2)
                                        addLink(tuple[0], tuple[1], false);
                        }
@@ -90,11 +94,9 @@
        private String[] getConfigLoadString() {
                String retarr[] = new String[linkMap.size()];
                synchronized (linkMap) {
-                       Iterator it = linkMap.keySet().iterator();
                        int i = 0;
-                       while(it.hasNext()) {
-                               String key = (String)it.next();
-                               retarr[i++] = key + '#' + linkMap.get(key);
+                       for (Map.Entry<String,String> entry : 
linkMap.entrySet()) {
+                               retarr[i++] = entry.getKey() + '#' + 
entry.getValue();
                        }
                }
                return retarr;
@@ -112,12 +114,11 @@
                String foundkey = null;
                String foundtarget = null;
                synchronized (linkMap) {
-                       Iterator it = linkMap.keySet().iterator();
-                       while (it.hasNext()) {
-                               String key = (String)it.next();
+                       for (Map.Entry<String,String> entry : 
linkMap.entrySet()) {
+                               String key = entry.getKey();
                                if (path.startsWith(key)) {
                                        foundkey = key;
-                                       foundtarget = (String)linkMap.get(key);
+                                       foundtarget = entry.getValue();
                                }
                        }
                }

Modified: trunk/freenet/src/freenet/clients/http/Toadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/Toadlet.java 2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/clients/http/Toadlet.java 2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -38,6 +38,8 @@
  * the fetch on another (or this) thread. With no need to change any
  * APIs, and no danger of exploding memory use (unlike the traditional
  * NIO servlets approach).
+ * 
+ * FIXME Investigate servlet 3.0, which support continuations.  
  */
 public abstract class Toadlet {

@@ -60,13 +62,6 @@
                handleUnhandledRequest(uri, null, ctx);
        }

-       /**
-        * Likewise for a PUT request.
-        */
-       public void handlePut(URI uri, ToadletContext ctx) throws 
ToadletContextClosedException, IOException, RedirectException {
-               handleUnhandledRequest(uri, null, ctx);
-       }
-       
        public void handlePost(URI uri, HTTPRequest req, ToadletContext ctx) 
throws ToadletContextClosedException, IOException, RedirectException {
                handleUnhandledRequest(uri, null, ctx);
        }
@@ -79,7 +74,7 @@
                infobox.addChild("div", "class", "infobox-header", 
l10n("notSupportedTitle"));
                infobox.addChild("div", "class", "infobox-content", 
l10n("notSupportedWithClass", "class", getClass().getName()));

-               MultiValueTable hdrtbl = new MultiValueTable();
+               MultiValueTable<String, String> hdrtbl = new 
MultiValueTable<String, String>();
                hdrtbl.put("Allow", this.supportedMethods());

                StringBuilder pageBuffer = new StringBuilder();
@@ -138,7 +133,7 @@
                writeReply(ctx, code, mimeType, desc, null, data);
        }

-       protected void writeReply(ToadletContext context, int code, String 
mimeType, String desc, MultiValueTable headers, Bucket data) throws 
ToadletContextClosedException, IOException {
+       protected void writeReply(ToadletContext context, int code, String 
mimeType, String desc, MultiValueTable<String, String> headers, Bucket data) 
throws ToadletContextClosedException, IOException {
                context.sendReplyHeaders(code, desc, headers, mimeType, 
data.size());
                context.writeData(data);
        }
@@ -155,26 +150,26 @@
                writeReply(ctx, code, "text/plain; charset=utf-8", desc, null, 
reply);
        }

-       protected void writeHTMLReply(ToadletContext ctx, int code, String 
desc, MultiValueTable headers, String reply) throws 
ToadletContextClosedException, IOException {
+       protected void writeHTMLReply(ToadletContext ctx, int code, String 
desc, MultiValueTable<String, String> headers, String reply) throws 
ToadletContextClosedException, IOException {
                writeReply(ctx, code, "text/html; charset=utf-8", desc, 
headers, reply);
        }

-       protected void writeTextReply(ToadletContext ctx, int code, String 
desc, MultiValueTable headers, String reply) throws 
ToadletContextClosedException, IOException {
+       protected void writeTextReply(ToadletContext ctx, int code, String 
desc, MultiValueTable<String, String> headers, String reply) throws 
ToadletContextClosedException, IOException {
                writeReply(ctx, code, "text/plain; charset=utf-8", desc, 
headers, reply);
        }

-       protected void writeReply(ToadletContext context, int code, String 
mimeType, String desc, MultiValueTable headers, String reply) throws 
ToadletContextClosedException, IOException {
+       protected void writeReply(ToadletContext context, int code, String 
mimeType, String desc, MultiValueTable<String, String> headers, String reply) 
throws ToadletContextClosedException, IOException {
                byte[] buffer = reply.getBytes("UTF-8");
                writeReply(context, code, mimeType, desc, headers, buffer, 0, 
buffer.length);
        }

-       protected void writeReply(ToadletContext context, int code, String 
mimeType, String desc, MultiValueTable headers, byte[] buffer, int startIndex, 
int length) throws ToadletContextClosedException, IOException {
+       protected void writeReply(ToadletContext context, int code, String 
mimeType, String desc, MultiValueTable<String, String> headers, byte[] buffer, 
int startIndex, int length) throws ToadletContextClosedException, IOException {
                context.sendReplyHeaders(code, desc, headers, mimeType, length);
                context.writeData(buffer, startIndex, length);
        }

        static void writePermanentRedirect(ToadletContext ctx, String msg, 
String location) throws ToadletContextClosedException, IOException {
-               MultiValueTable mvt = new MultiValueTable();
+               MultiValueTable<String, String> mvt = new 
MultiValueTable<String, String>();
                mvt.put("Location", location);
                if(msg == null) msg = "";
                else msg = HTMLEncoder.encode(msg);
@@ -193,7 +188,7 @@
        }

        protected void writeTemporaryRedirect(ToadletContext ctx, String msg, 
String location) throws ToadletContextClosedException, IOException {
-               MultiValueTable mvt = new MultiValueTable();
+               MultiValueTable<String, String> mvt = new 
MultiValueTable<String, String>();
                mvt.put("Location", location);
                if(msg == null) msg = "";
                else msg = HTMLEncoder.encode(msg);

Modified: trunk/freenet/src/freenet/clients/http/ToadletContext.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ToadletContext.java  2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/ToadletContext.java  2008-11-06 
13:53:57 UTC (rev 23351)
@@ -23,9 +23,9 @@
         * @param length The length of the reply.
         * @param mTime The modification time of the data being sent or null 
for 'now' and disabling caching
         */
-       void sendReplyHeaders(int code, String desc, MultiValueTable mvt, 
String mimeType, long length, Date mTime) throws ToadletContextClosedException, 
IOException;
+       void sendReplyHeaders(int code, String desc, 
MultiValueTable<String,String> mvt, String mimeType, long length, Date mTime) 
throws ToadletContextClosedException, IOException;

-       void sendReplyHeaders(int code, String desc, MultiValueTable mvt, 
String mimeType, long length) throws ToadletContextClosedException, IOException;
+       void sendReplyHeaders(int code, String desc, 
MultiValueTable<String,String> mvt, String mimeType, long length) throws 
ToadletContextClosedException, IOException;

        /**
         * Write data. Note you must send reply headers first.
@@ -63,7 +63,7 @@

        BucketFactory getBucketFactory();

-       MultiValueTable getHeaders();
+       MultiValueTable<String, String> getHeaders();

        /**
         * Add a form node to an HTMLNode under construction. This will have 
the correct enctype and 

Modified: trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -38,7 +38,7 @@
  */
 public class ToadletContextImpl implements ToadletContext {

-       private final MultiValueTable headers;
+       private final MultiValueTable<String,String> headers;
        private final OutputStream sockOutputStream;
        private final PageMaker pagemaker;
        private final BucketFactory bf;
@@ -52,7 +52,7 @@
        private boolean closed;
        private boolean shouldDisconnect;

-       public ToadletContextImpl(Socket sock, MultiValueTable headers, 
BucketFactory bf, PageMaker pageMaker, ToadletContainer container) throws 
IOException {
+       public ToadletContextImpl(Socket sock, MultiValueTable<String,String> 
headers, BucketFactory bf, PageMaker pageMaker, ToadletContainer container) 
throws IOException {
                this.headers = headers;
                this.closed = false;
                sockOutputStream = sock.getOutputStream();
@@ -70,7 +70,7 @@

        private void sendMethodNotAllowed(String method, boolean 
shouldDisconnect) throws ToadletContextClosedException, IOException {
                if(closed) throw new ToadletContextClosedException();
-               MultiValueTable mvt = new MultiValueTable();
+               MultiValueTable<String,String> mvt = new 
MultiValueTable<String,String>();
                mvt.put("Allow", "GET, PUT");
                sendError(sockOutputStream, 405, "Method Not Allowed", 
l10n("methodNotAllowed"), shouldDisconnect, mvt);
        }
@@ -87,7 +87,7 @@
         * Send an error message. Caller provides the HTTP code, reason string, 
and a message, which
         * will become the title and the h1'ed contents of the error page. 
         */
-       private static void sendError(OutputStream os, int code, String 
httpReason, String message, boolean shouldDisconnect, MultiValueTable mvt) 
throws IOException {
+       private static void sendError(OutputStream os, int code, String 
httpReason, String message, boolean shouldDisconnect, 
MultiValueTable<String,String> mvt) throws IOException {
                sendHTMLError(os, code, httpReason, 
"<html><head><title>"+message+"</title></head><body><h1>"+message+"</h1></body>",
 shouldDisconnect, mvt);
        }

@@ -102,8 +102,8 @@
         * @param mvt Any additional headers.
         * @throws IOException If we could not send the error message.
         */
-       private static void sendHTMLError(OutputStream os, int code, String 
httpReason, String htmlMessage, boolean disconnect, MultiValueTable mvt) throws 
IOException {
-               if(mvt == null) mvt = new MultiValueTable();
+       private static void sendHTMLError(OutputStream os, int code, String 
httpReason, String htmlMessage, boolean disconnect, 
MultiValueTable<String,String> mvt) throws IOException {
+               if(mvt == null) mvt = new MultiValueTable<String,String>();
                byte[] messageBytes = htmlMessage.getBytes("UTF-8");
                sendReplyHeaders(os, code, httpReason, mvt, "text/html; 
charset=UTF-8", messageBytes.length, null, disconnect);
                os.write(messageBytes);
@@ -123,11 +123,11 @@
                sendHTMLError(os, 400, "Bad Request", message, 
shouldDisconnect, null);
        }

-       public void sendReplyHeaders(int replyCode, String replyDescription, 
MultiValueTable mvt, String mimeType, long contentLength) throws 
ToadletContextClosedException, IOException {
+       public void sendReplyHeaders(int replyCode, String replyDescription, 
MultiValueTable<String,String> mvt, String mimeType, long contentLength) throws 
ToadletContextClosedException, IOException {
                sendReplyHeaders(replyCode, replyDescription, mvt, mimeType, 
contentLength, null);
        }

-       public void sendReplyHeaders(int replyCode, String replyDescription, 
MultiValueTable mvt, String mimeType, long contentLength, Date mTime) throws 
ToadletContextClosedException, IOException {
+       public void sendReplyHeaders(int replyCode, String replyDescription, 
MultiValueTable<String,String> mvt, String mimeType, long contentLength, Date 
mTime) throws ToadletContextClosedException, IOException {
                if(closed) throw new ToadletContextClosedException();
                if(sentReplyHeaders) {
                        throw new IllegalStateException("Already sent 
headers!");
@@ -140,14 +140,14 @@
                return pagemaker;
        }

-       public MultiValueTable getHeaders() {
+       public MultiValueTable<String,String> getHeaders() {
                return headers;
        }

-       static void sendReplyHeaders(OutputStream sockOutputStream, int 
replyCode, String replyDescription, MultiValueTable mvt, String mimeType, long 
contentLength, Date mTime, boolean disconnect) throws IOException {
+       static void sendReplyHeaders(OutputStream sockOutputStream, int 
replyCode, String replyDescription, MultiValueTable<String,String> mvt, String 
mimeType, long contentLength, Date mTime, boolean disconnect) throws 
IOException {
                // Construct headers
                if(mvt == null)
-                       mvt = new MultiValueTable();
+                       mvt = new MultiValueTable<String,String>();
                if(mimeType != null)
                        if(mimeType.equalsIgnoreCase("text/html")){
                                mvt.put("content-type", mimeType+"; 
charset=UTF-8");
@@ -190,8 +190,8 @@
                buf.append(' ');
                buf.append(replyDescription);
                buf.append("\r\n");
-               for(Enumeration e = mvt.keys();e.hasMoreElements();) {
-                       String key = (String) e.nextElement();
+               for(Enumeration<String> e = mvt.keys();e.hasMoreElements();) {
+                       String key = e.nextElement();
                        Object[] list = mvt.getArray(key);
                        key = fixKey(key);
                        for(int i=0;i<list.length;i++) {
@@ -276,7 +276,7 @@

                                String method = split[0];

-                               MultiValueTable headers = new MultiValueTable();
+                               MultiValueTable<String,String> headers = new 
MultiValueTable<String,String>();

                                while(true) {
                                        String line = lis.readLine(32768, 128, 
false); // ISO-8859 or US-ASCII, not UTF-8
@@ -312,7 +312,7 @@
                                Bucket data;

                                if(method.equals("POST")) {
-                                       String slen = (String) 
headers.get("content-length");
+                                       String slen = 
headers.get("content-length");
                                        if(slen == null) {
                                                
sendError(sock.getOutputStream(), 400, "Bad Request", 
l10n("noContentLengthInPOST"), true, null);
                                                return;
@@ -364,9 +364,6 @@
                                                if(method.equals("GET")) {
                                                        t.handleGet(uri, req, 
ctx);
                                                        ctx.close();
-                                               } else if(method.equals("PUT")) 
{
-                                                       t.handlePut(uri, ctx);
-                                                       ctx.close();
                                                } else 
if(method.equals("POST")) {
                                                        t.handlePost(uri, req, 
ctx);
                                                } else {
@@ -414,8 +411,8 @@
         * @param headers Client headers.
         * @return True if the connection should be closed.
         */
-       private static boolean shouldDisconnectAfterHandled(boolean isHTTP10, 
MultiValueTable headers) {
-               String connection = (String) headers.get("connection");
+       private static boolean shouldDisconnectAfterHandled(boolean isHTTP10, 
MultiValueTable<String,String> headers) {
+               String connection = headers.get("connection");
                if(connection != null) {
                        if(connection.equalsIgnoreCase("close"))
                                return true;

Modified: trunk/freenet/src/freenet/clients/http/TranslationToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/TranslationToadlet.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/TranslationToadlet.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -49,7 +49,7 @@
                                return;
                        }
                        byte[] data = sfs.toOrderedString().getBytes("UTF-8");
-                       MultiValueTable head = new MultiValueTable();
+                       MultiValueTable<String, String> head = new 
MultiValueTable<String, String>();
                        head.put("Content-Disposition", "attachment; 
filename=\"" + L10n.getSelectedLanguage().l10nOverrideFilename+ '"');
                        ctx.sendReplyHeaders(200, "Found", head, "text/plain; 
charset=utf-8", data.length);
                        ctx.writeData(data);
@@ -244,7 +244,7 @@
        }

        private void redirectTo(ToadletContext ctx, String target) throws 
ToadletContextClosedException, IOException {
-               MultiValueTable headers = new MultiValueTable();
+               MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
                headers.put("Location", target);
                ctx.sendReplyHeaders(302, "Found", headers, null, 0);
                return;

Deleted: trunk/freenet/src/freenet/clients/http/TrivialToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/TrivialToadlet.java  2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/TrivialToadlet.java  2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,30 +0,0 @@
-package freenet.clients.http;
-
-import java.io.IOException;
-import java.net.URI;
-
-import freenet.client.HighLevelSimpleClient;
-import freenet.support.HTMLEncoder;
-import freenet.support.api.HTTPRequest;
-
-public class TrivialToadlet extends Toadlet {
-
-       TrivialToadlet(HighLevelSimpleClient client) {
-               super(client);
-       }
-
-       @Override
-       public void handleGet(URI uri, HTTPRequest req, ToadletContext ctx) 
throws ToadletContextClosedException, IOException {
-               String fetched = uri.toString();
-               String encFetched = HTMLEncoder.encode(fetched);
-               String reply = "<html><head><title>You requested "+encFetched+
-                       "</title></head><body>You fetched <a 
href=\""+encFetched+"\">"+
-                       encFetched+"</a>.</body></html>";
-               this.writeHTMLReply(ctx, 200, "OK", reply);
-       }
-       
-       @Override
-       public String supportedMethods() {
-               return "GET";
-       }
-}

Modified: trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java  2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java  2008-11-06 
13:53:57 UTC (rev 23351)
@@ -7,6 +7,7 @@
 import java.io.IOException;
 import java.net.URI;
 import java.util.HashSet;
+import java.util.List;

 import org.tanukisoftware.wrapper.WrapperManager;

@@ -14,10 +15,8 @@
 import freenet.client.HighLevelSimpleClient;
 import freenet.client.InsertBlock;
 import freenet.client.InsertException;
-import freenet.clients.http.bookmark.BookmarkCategories;
 import freenet.clients.http.bookmark.BookmarkCategory;
 import freenet.clients.http.bookmark.BookmarkItem;
-import freenet.clients.http.bookmark.BookmarkItems;
 import freenet.clients.http.bookmark.BookmarkManager;
 import freenet.clients.http.filter.GenericReadFilterCallback;
 import freenet.frost.message.FrostBoard;
@@ -51,14 +50,14 @@
     }

     void redirectToRoot(ToadletContext ctx) throws 
ToadletContextClosedException, IOException {
-        MultiValueTable headers = new MultiValueTable();
+        MultiValueTable<String, String> headers = new MultiValueTable<String, 
String>();
         headers.put("Location", "/");
         ctx.sendReplyHeaders(302, "Found", headers, null, 0);
         return;
     }

     private void addCategoryToList(BookmarkCategory cat, HTMLNode list, 
boolean noActiveLinks) {
-        BookmarkItems items = cat.getItems();
+        List<BookmarkItem> items = cat.getItems();
         if (items.size() > 0) {
             // FIXME CSS noborder ...
             HTMLNode table = list.addChild("li").addChild("table", new 
String[]{"border", "style"}, new String[]{"0", "border: none"});
@@ -79,7 +78,7 @@
             }
         }

-        BookmarkCategories cats = cat.getSubCategories();
+        List<BookmarkCategory> cats = cat.getSubCategories();
         for (int i = 0; i < cats.size(); i++) {
             list.addChild("li", "class", "cat", cats.get(i).getName());
             addCategoryToList(cats.get(i), list.addChild("li").addChild("ul"), 
noActiveLinks);
@@ -122,7 +121,7 @@
                 redirectToRoot(ctx);
                 return;
             }
-            MultiValueTable headers = new MultiValueTable();
+            MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
             String url = null;
             if ((request.getPartAsString("Go", 32).length() > 0)) {
                 url = 
request.getPartAsString(GenericReadFilterCallback.magicHTTPEscapeString, 
MAX_URL_LENGTH);
@@ -355,7 +354,7 @@
                 redirectToRoot(ctx);
                 return;
             }
-            MultiValueTable headers = new MultiValueTable();
+            MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
             headers.put("Location", "/?terminated&formPassword=" + 
core.formPassword);
             ctx.sendReplyHeaders(302, "Found", headers, null, 0);
             node.ps.queueTimedJob(new Runnable() {
@@ -371,7 +370,7 @@
                 return;
             }

-            MultiValueTable headers = new MultiValueTable();
+            MultiValueTable<String, String> headers = new 
MultiValueTable<String, String>();
             headers.put("Location", "/?restarted&formPassword=" + 
core.formPassword);
             ctx.sendReplyHeaders(302, "Found", headers, null, 0);
             node.ps.queueTimedJob(new Runnable() {
@@ -389,8 +388,8 @@

                String alertsToDump = request.getPartAsString("events", 
Integer.MAX_VALUE);
                String[] alertAnchors = alertsToDump.split(",");
-               HashSet toDump = new HashSet();
-               for(int i=0;i<alertAnchors.length;i++) 
toDump.add(alertAnchors[i]);
+               HashSet<String> toDump = new HashSet<String>();
+               for(String alertAnchor : alertAnchors) toDump.add(alertAnchor);
                core.alerts.dumpEvents(toDump);
                redirectToRoot(ctx);
         } else {
@@ -536,7 +535,7 @@
             testnetContent.addChild("#", l10n("testnetWarning"));
         }

-        String useragent = (String) ctx.getHeaders().get("user-agent");
+        String useragent = ctx.getHeaders().get("user-agent");

         if (useragent != null) {
             useragent = useragent.toLowerCase();
@@ -564,8 +563,7 @@

         HTMLNode bookmarkBoxContent = bookmarkBox.addChild("div", "class", 
"infobox-content");
         HTMLNode bookmarksList = bookmarkBoxContent.addChild("ul", "id", 
"bookmarks");
-       String userAgent = useragent.toLowerCase();
-        addCategoryToList(BookmarkManager.MAIN_CATEGORY, bookmarksList, 
useragent != null && userAgent.contains("khtml") && 
!userAgent.contains("chrome"));
+        addCategoryToList(BookmarkManager.MAIN_CATEGORY, bookmarksList, 
useragent != null && useragent.contains("khtml") && 
!useragent.contains("chrome"));

         // Fetch-a-key box
         HTMLNode fetchKeyBox = 
contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-normal", 
l10n("fetchKeyLabel")));

Deleted: trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategories.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategories.java     
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategories.java     
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,24 +0,0 @@
-package freenet.clients.http.bookmark;
-
-import java.util.Vector;
-
-public final class BookmarkCategories {
-       private final Vector categories = new Vector();
-
-       public BookmarkCategory get(int i) {
-               return (BookmarkCategory) categories.get(i);
-       }
-
-       public void add(BookmarkCategory bc) {
-               categories.add(bc);
-       }
-
-       protected void extend(BookmarkCategories bc) {
-               for (int i = 0; i < bc.size(); i++)
-                       add(bc.get(i));
-       }
-
-       public int size() {
-               return categories.size();
-       }
-}

Modified: trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,5 +1,6 @@
 package freenet.clients.http.bookmark;

+import java.util.List;
 import java.util.Vector;

 import freenet.node.FSParseException;
@@ -67,8 +68,8 @@
         return bookmarks.size();
     }

-    public BookmarkItems getItems() {
-        BookmarkItems items = new BookmarkItems();
+    public List<BookmarkItem> getItems() {
+       List<BookmarkItem>  items = new Vector<BookmarkItem>();
         for (int i = 0; i < size(); i++) {
             if (get(i) instanceof BookmarkItem) {
                 items.add((BookmarkItem) get(i));
@@ -78,18 +79,18 @@
         return items;
     }

-    public BookmarkItems getAllItems() {
-        BookmarkItems items = getItems();
-        BookmarkCategories subCategories = getSubCategories();
+    public List<BookmarkItem> getAllItems() {
+       List<BookmarkItem> items = getItems();
+        List<BookmarkCategory> subCategories = getSubCategories();

         for (int i = 0; i < subCategories.size(); i++) {
-            items.extend(subCategories.get(i).getAllItems());
+            items.addAll(subCategories.get(i).getAllItems());
         }
         return items;
     }

-    public BookmarkCategories getSubCategories() {
-        BookmarkCategories categories = new BookmarkCategories();
+    public List<BookmarkCategory> getSubCategories() {
+       List<BookmarkCategory> categories = new Vector<BookmarkCategory>();
         for (int i = 0; i < size(); i++) {
             if (get(i) instanceof BookmarkCategory) {
                 categories.add((BookmarkCategory) get(i));
@@ -99,12 +100,12 @@
         return categories;
     }

-    public BookmarkCategories getAllSubCategories() {
-        BookmarkCategories categories = getSubCategories();
-        BookmarkCategories subCategories = getSubCategories();
+    public List<BookmarkCategory> getAllSubCategories() {
+       List<BookmarkCategory> categories = getSubCategories();
+       List<BookmarkCategory> subCategories = getSubCategories();

         for (int i = 0; i < subCategories.size(); i++) {
-            categories.extend(subCategories.get(i).getAllSubCategories());
+            categories.addAll(subCategories.get(i).getAllSubCategories());
         }

         return categories;
@@ -118,8 +119,8 @@

     private Vector<String> toStrings(String prefix) {
         Vector<String> strings = new Vector<String>();
-        BookmarkItems items = getItems();
-        BookmarkCategories subCategories = getSubCategories();
+        List<BookmarkItem> items = getItems();
+        List<BookmarkCategory> subCategories = getSubCategories();
         prefix += this.name + "/";

         for (int i = 0; i < items.size(); i++) {

Deleted: trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItems.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItems.java  
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/bookmark/BookmarkItems.java  
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,24 +0,0 @@
-package freenet.clients.http.bookmark;
-
-import java.util.Vector;
-
-public class BookmarkItems {
-       private final Vector items = new Vector();
-
-       public BookmarkItem get(int i) {
-               return (BookmarkItem) items.get(i);
-       }
-
-       public void add(BookmarkItem bi) {
-               items.add(bi);
-       }
-
-       protected void extend(BookmarkItems bi) {
-               for (int i = 0; i < bi.size(); i++)
-                       add(bi.get(i));
-       }
-
-       public int size() {
-               return items.size();
-       }
-}

Modified: trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java        
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java        
2008-11-06 13:53:57 UTC (rev 23351)
@@ -10,6 +10,8 @@
 import java.net.MalformedURLException;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
+
 import freenet.client.async.USKCallback;
 import freenet.keys.FreenetURI;
 import freenet.keys.USK;
@@ -91,7 +93,7 @@
        private class USKUpdatedCallback implements USKCallback {

                public void onFoundEdition(long edition, USK key) {
-                       BookmarkItems items = MAIN_CATEGORY.getAllItems();
+                       List<BookmarkItem> items = MAIN_CATEGORY.getAllItems();
                        for(int i = 0; i < items.size(); i++) {
                                if(!"USK".equals(items.get(i).getKeyType()))
                                        continue;
@@ -247,7 +249,7 @@
        }

        public FreenetURI[] getBookmarkURIs() {
-               BookmarkItems items = MAIN_CATEGORY.getAllItems();
+               List<BookmarkItem> items = MAIN_CATEGORY.getAllItems();
                FreenetURI[] uris = new FreenetURI[items.size()];
                for(int i = 0; i < items.size(); i++)
                        uris[i] = items.get(i).getURI();
@@ -350,7 +352,7 @@

        public static SimpleFieldSet toSimpleFieldSet(BookmarkCategory cat) {
                SimpleFieldSet sfs = new SimpleFieldSet(true);
-               BookmarkCategories bc = cat.getSubCategories();
+               List<BookmarkCategory> bc = cat.getSubCategories();

                for(int i = 0; i < bc.size(); i++) {
                        BookmarkCategory currentCat = bc.get(i);
@@ -359,7 +361,7 @@
                sfs.put(BookmarkCategory.NAME, bc.size());


-               BookmarkItems bi = cat.getItems();
+               List<BookmarkItem> bi = cat.getItems();
                for(int i = 0; i < bi.size(); i++)
                        sfs.put(BookmarkItem.NAME + i, 
bi.get(i).getSimpleFieldSet());
                sfs.put(BookmarkItem.NAME, bi.size());

Modified: 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java
===================================================================
--- 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java    
    2008-11-06 13:50:42 UTC (rev 23350)
+++ 
trunk/freenet/src/freenet/clients/http/filter/GenericReadFilterCallback.java    
    2008-11-06 13:53:57 UTC (rev 23351)
@@ -3,8 +3,8 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.clients.http.filter;

-import java.net.MalformedURLException;
 import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URLEncoder;
@@ -14,7 +14,6 @@
 import freenet.clients.http.StaticToadlet;
 import freenet.keys.FreenetURI;
 import freenet.l10n.L10n;
-import freenet.node.StaticSwapRequestInterval;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
 import freenet.support.URIPreEncoder;

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/icon/bookmark-new.png
===================================================================
(Binary files differ)

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/icon/cut.png
===================================================================
(Binary files differ)

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/icon/delete.png
===================================================================
(Binary files differ)

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/icon/edit.png
===================================================================
(Binary files differ)

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/icon/folder-new.png
===================================================================
(Binary files differ)

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/icon/go-down.png
===================================================================
(Binary files differ)

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/icon/go-up.png
===================================================================
(Binary files differ)

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/icon/paste.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/background.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/logo.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/clean/logo.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/alert-16.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/alert.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/error-16.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/error.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/fail.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/information-16.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/information.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/logo.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/query.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/success.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/warning-16.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/warning.png
===================================================================
(Binary files differ)

Copied: trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue 
(from rev 23341, 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue)

Deleted: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue/theme.css
===================================================================
--- 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue/theme.css 
    2008-11-06 08:45:15 UTC (rev 23341)
+++ 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue/theme.css 
    2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,464 +0,0 @@
-/*****************/
-/* Global config */
-/*****************/
-
- at import url(/static/bookmark.css);
-
-body{
-width: 100%;
-margin: auto;
-padding-top: 5px;
-padding-bottom: 5px;
-color: #fff;
-background: #2573b8;
-}
-img{
-display: block;
-}
-a{
-text-decoration: none;
-color: #ddd;
-}
-a:hover{
-color: #fff;
-}
-
-table {
-border-collapse: collapse;
-}
-
-th {
-font-weight: bold;
-background-color: #156098;
-}
-
-th, td {
-margin: 0;
-padding: 5px;
-border: solid 1px white;
-}
-
-pre, textarea {
-font-family: Courier;
-font-weight: normal;
-font-size: 8pt;
-}
-
-pre#reference {
-overflow: auto;
-}
-
-table, pre {
-margin: 0 0 5px 0;
-padding: 0;
-}
-
-form {
-margin: 0 0 5px 0;
-padding: 0;
-}
-
-
-/************************/
-/* End of Global config */
-/************************/
-
-
-/*********************/
-/* Status bar config */
-/*********************/
-/*
-#status_bar{
-width: 90%;
-margin: auto;
-padding: 3px;
-}
-.blocking{
-background: red;
-}
-.non_blocking{
-background: #ff7100;
-}
-.ok{
-background: green;
-}
-p{
-text-align: center;
-font-size: 14px;
-}
-p, p a{
-color: #fff;
-}
-*/
-/****************************/
-/* End of Status bar config */
-/****************************/
-
-/***************/
-/* Menu config */
-/***************/
-
-#navbar a{
-color: #ddd;
-}
-#navbar a:hover{
-color: #fff;
-}
-
-#navbar{
-/*float: left;*/
-width: 100%;
-overflow:hidden;
-position:relative;
-top: 0px;
-background: #2573b8;
-}
-#navbar ul#navlist{
-clear:left;
-float:left;
-position:relative;
-left:50%;
-text-align:center;
-}
-#navbar ul, #navbar ul li{
-list-style:none;
-margin:0;
-padding: 0;
-}
-#navbar ul li{
-display:block;
-float:left;
-position:relative;
-right:50%;
-color: #ff7100;
-background: #156098;
-margin-left: 3px;
-}
-#navbar ul li.selected, #navbar ul li:hover{
-color: #0092a4;
-background: #035196;
-}
-#navbar ul li.selected a{
-color: #0092a4;
-cursor: default;
-padding: 5px;
-}
-#navbar ul li a{
-display:block;
-text-align:center;
-text-decoration:none;
-margin:auto;
-font-size: 12px;
-font-weight: bold;
-padding: 5px;
-padding-left: 4px;
-padding-right: 4px;
-}
-
-/**********************/
-/* End of Menu config */
-/**********************/
-
-#content{
-clear:both;
-color: #fff;
-width: 90%;
-margin: auto;
-background: #035196;
-border-bottom: solid 1px black;
-border-right: solid 1px black;
-padding: 0;
-padding-top: 20px;
-padding-bottom: 5px;
-}
-#topbar{
-width: 100%;;
-margin: auto;
-margin-top: 30px;
-margin-bottom: 50px;
-}
-#topbar h1{
-margin: auto;
-text-align: center;
-font-variant: small-caps;
-font-size: 300%;
-background: #035196;
-padding: 0;
-padding-top: 10px;
-padding-bottom: 10px;
-border-bottom: solid 1px black;
-}
-
-/* alerts */
-
-.alert-error {
-color: #ff0000;
-}
-
-.alert-warning {
-color: #ff4000;
-}
-
-.alert-minor {
-color: green;
-}
-
-/* infoboxes */
-
-div.infobox{
-margin: auto;
-padding: 0;
-margin-left:5px;
-margin-right:5px;
-background: #3573b8;
-}
-
-div.infobox .infobox-header{
-font-size: 200%;
-font-variant: small-caps;
-background: #035196;
-border-top: solid 1px white;
-border-left: solid 1px white;
-padding-left: 10px;
-width: 98%;
-margin: auto;
-}
-
-div.infobox .infobox-content{
-padding-left: 10px;
-padding-right: 10px;
-padding-bottom: 7px;
-margin-top: 7px;
-margin-bottom: 10px;
-overflow: auto;
-}
-
-div.infobox-warning div.infobox-header {
-background: #ff4000;
-}
-
-div.infobox-alert div.infobox-header {
-background-color: #ff0000;
-}
-/*
-div.infobox-error {
-background-color: #f0e8e8;
-}
-
-div.infobox-error div.infobox-header {
-background-color: #ffd0d0;
-}
-
-div.infobox-query div.infobox-header {
-background-color: #f0f0e8;
-}
-
-div.infobox-success div.infobox-header {
-background-color: #c8f0c8;
-}
-
-div.infobox-summary-status-content {
-padding: 0px;
-}
-*/
-
-ul.alert-summary {
-list-style-type: none;
-padding: 0;
-}
-
-ul.alert-summary li{
-margin: 0;
-}
-
-li.alert-summary-text-error {
-list-style: none;
-}
-
-li.alert-summary-text-alert {
-list-style: none;
-font-weight: bold;
-}
-
-li.alert-summary-text-alert a{
-color: #d92;
-}
-
-li.alert-summary-text-alert a:hover{
-color: #fa4;
-}
-
-li.alert-summary-text-warning {
-list-style: none;
-font-weight: bold;
-}
-
-li.alert-summary-text-warning a{
-color: #dd5;
-}
-
-li.alert-summary-text-warning a:hover{
-color: #ff7;
-}
-
-li.alert-summary-text-minor {
-list-style: none;
-}
-
-li.alert-summary-text-minor a{
-color: #ddd;
-}
-
-li.alert-summary-text-minor a:hover{
-color: #fff;
-}
-
-li.cat{
-font-size: 150%;
-font-weight: bold;
-}
-
-li{
-margin-left: -40px;
-list-style: none;
-}
-
-ul#bookmarks li{
-margin: 0;
-}
-
-.column th, .column td{
-border: none;
-}
-
-table.config_navigation {
-position: relative;
-left: -40px;
-}
-
-td.config_navigation, th.config_navigation{
-border: none;
-background: #035196;
-}
-
-.config_navigation li{
-list-style: none;
-padding: 0 0 0 40px;
-/*background: #035196;*/
-}
-
-.config_navigation li:hover{
-/*background: #035196;*/
-}
-
-ul.config li{
-list-style: none;
-clear: both;
-margin: 0 0 20px -20px;
-border-top: solid 1px white;
-padding-top: 3px;
-}
-
-div.configprefix {
-font-size: 150%;
-font-weight: bolder;
-}
-
-.configshortdesc{
-clear: both;
-font-size: 130%;
-}
-
-.configlongdesc{
-float: left;
-clear: both;
-font-weight: lighter;
-font-style: italic;
-color: #ddd;
-}
-
-#configForm input, #configForm select{
-margin: 0 0 0 10px;
-}
-
-#configForm input{
-width: 300px;
-}
-
-span.mark{
-color: #035196;
-}
-
-span.connected{
-color: #fff;
-}
-
-span.disconnected{
-color: #aaa;
-}
-
-div.histogramConnected{
-background: #fff;
-}
-
-div.histogramDisconnected{
-background: #aaa;
-}
-
-span.peer_connected {
-       color: #008000;
-}
-
-span.peer_backed_off {
-       color: #ff8c00;
-       font-weight: bold;
-}
-
-span.peer_too_new {
-       color: #ff0000;
-       font-weight: bold;
-}
-
-span.peer_too_old {
-       color: #d0a0d0;
-       font-weight: bold;
-}
-
-span.peer_disconnected {
-       color: #d0d0d0;
-}
-
-span.peer_routing_disabled {
-        color: #7b68ee;
-}
-
-span.peer_never_connected {
-       color: #a0a0a0;
-}
-
-span.peer_disabled {
-       color: #a0a0a0;
-}
-
-span.peer_bursting {
-       color: #a0a0a0;
-}
-
-span.peer_listening {
-       color: #a0a0a0;
-}
-
-span.peer_listen_only {
-       color: #a0a0a0;
-}
-
-span.peer_version_problem {
-       color: #d07070;
-       font-weight: bold;
-}
-
-span.peer_idle_old {
-       color: #d07070;
-       font-weight: bold;
-}
-

Copied: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue/theme.css 
(from rev 23341, 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue/theme.css)
===================================================================
--- 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue/theme.css 
                            (rev 0)
+++ 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/minimalblue/theme.css 
    2008-11-06 13:53:57 UTC (rev 23351)
@@ -0,0 +1,464 @@
+/*****************/
+/* Global config */
+/*****************/
+
+ at import url(/static/bookmark.css);
+
+body{
+width: 100%;
+margin: auto;
+padding-top: 5px;
+padding-bottom: 5px;
+color: #fff;
+background: #2573b8;
+}
+img{
+display: block;
+}
+a{
+text-decoration: none;
+color: #ddd;
+}
+a:hover{
+color: #fff;
+}
+
+table {
+border-collapse: collapse;
+}
+
+th {
+font-weight: bold;
+background-color: #156098;
+}
+
+th, td {
+margin: 0;
+padding: 5px;
+border: solid 1px white;
+}
+
+pre, textarea {
+font-family: Courier;
+font-weight: normal;
+font-size: 8pt;
+}
+
+pre#reference {
+overflow: auto;
+}
+
+table, pre {
+margin: 0 0 5px 0;
+padding: 0;
+}
+
+form {
+margin: 0 0 5px 0;
+padding: 0;
+}
+
+
+/************************/
+/* End of Global config */
+/************************/
+
+
+/*********************/
+/* Status bar config */
+/*********************/
+/*
+#status_bar{
+width: 90%;
+margin: auto;
+padding: 3px;
+}
+.blocking{
+background: red;
+}
+.non_blocking{
+background: #ff7100;
+}
+.ok{
+background: green;
+}
+p{
+text-align: center;
+font-size: 14px;
+}
+p, p a{
+color: #fff;
+}
+*/
+/****************************/
+/* End of Status bar config */
+/****************************/
+
+/***************/
+/* Menu config */
+/***************/
+
+#navbar a{
+color: #ddd;
+}
+#navbar a:hover{
+color: #fff;
+}
+
+#navbar{
+/*float: left;*/
+width: 100%;
+overflow:hidden;
+position:relative;
+top: 0px;
+background: #2573b8;
+}
+#navbar ul#navlist{
+clear:left;
+float:left;
+position:relative;
+left:50%;
+text-align:center;
+}
+#navbar ul, #navbar ul li{
+list-style:none;
+margin:0;
+padding: 0;
+}
+#navbar ul li{
+display:block;
+float:left;
+position:relative;
+right:50%;
+color: #ff7100;
+background: #156098;
+margin-left: 3px;
+}
+#navbar ul li.selected, #navbar ul li:hover{
+color: #0092a4;
+background: #035196;
+}
+#navbar ul li.selected a{
+color: #0092a4;
+cursor: default;
+padding: 5px;
+}
+#navbar ul li a{
+display:block;
+text-align:center;
+text-decoration:none;
+margin:auto;
+font-size: 12px;
+font-weight: bold;
+padding: 5px;
+padding-left: 4px;
+padding-right: 4px;
+}
+
+/**********************/
+/* End of Menu config */
+/**********************/
+
+#content{
+clear:both;
+color: #fff;
+width: 90%;
+margin: auto;
+background: #035196;
+border-bottom: solid 1px black;
+border-right: solid 1px black;
+padding: 0;
+padding-top: 20px;
+padding-bottom: 5px;
+}
+#topbar{
+width: 100%;;
+margin: auto;
+margin-top: 30px;
+margin-bottom: 50px;
+}
+#topbar h1{
+margin: auto;
+text-align: center;
+font-variant: small-caps;
+font-size: 300%;
+background: #035196;
+padding: 0;
+padding-top: 10px;
+padding-bottom: 10px;
+border-bottom: solid 1px black;
+}
+
+/* alerts */
+
+.alert-error {
+color: #ff0000;
+}
+
+.alert-warning {
+color: #ff4000;
+}
+
+.alert-minor {
+color: green;
+}
+
+/* infoboxes */
+
+div.infobox{
+margin: auto;
+padding: 0;
+margin-left:5px;
+margin-right:5px;
+background: #3573b8;
+}
+
+div.infobox .infobox-header{
+font-size: 200%;
+font-variant: small-caps;
+background: #035196;
+border-top: solid 1px white;
+border-left: solid 1px white;
+padding-left: 10px;
+width: 98%;
+margin: auto;
+}
+
+div.infobox .infobox-content{
+padding-left: 10px;
+padding-right: 10px;
+padding-bottom: 7px;
+margin-top: 7px;
+margin-bottom: 10px;
+overflow: auto;
+}
+
+div.infobox-warning div.infobox-header {
+background: #ff4000;
+}
+
+div.infobox-alert div.infobox-header {
+background-color: #ff0000;
+}
+/*
+div.infobox-error {
+background-color: #f0e8e8;
+}
+
+div.infobox-error div.infobox-header {
+background-color: #ffd0d0;
+}
+
+div.infobox-query div.infobox-header {
+background-color: #f0f0e8;
+}
+
+div.infobox-success div.infobox-header {
+background-color: #c8f0c8;
+}
+
+div.infobox-summary-status-content {
+padding: 0px;
+}
+*/
+
+ul.alert-summary {
+list-style-type: none;
+padding: 0;
+}
+
+ul.alert-summary li{
+margin: 0;
+}
+
+li.alert-summary-text-error {
+list-style: none;
+}
+
+li.alert-summary-text-alert {
+list-style: none;
+font-weight: bold;
+}
+
+li.alert-summary-text-alert a{
+color: #d92;
+}
+
+li.alert-summary-text-alert a:hover{
+color: #fa4;
+}
+
+li.alert-summary-text-warning {
+list-style: none;
+font-weight: bold;
+}
+
+li.alert-summary-text-warning a{
+color: #dd5;
+}
+
+li.alert-summary-text-warning a:hover{
+color: #ff7;
+}
+
+li.alert-summary-text-minor {
+list-style: none;
+}
+
+li.alert-summary-text-minor a{
+color: #ddd;
+}
+
+li.alert-summary-text-minor a:hover{
+color: #fff;
+}
+
+li.cat{
+font-size: 150%;
+font-weight: bold;
+}
+
+li{
+margin-left: -40px;
+list-style: none;
+}
+
+ul#bookmarks li{
+margin: 0;
+}
+
+.column th, .column td{
+border: none;
+}
+
+table.config_navigation {
+position: relative;
+left: -40px;
+}
+
+td.config_navigation, th.config_navigation{
+border: none;
+background: #035196;
+}
+
+.config_navigation li{
+list-style: none;
+padding: 0 0 0 40px;
+/*background: #035196;*/
+}
+
+.config_navigation li:hover{
+/*background: #035196;*/
+}
+
+ul.config li{
+list-style: none;
+clear: both;
+margin: 0 0 20px -20px;
+border-top: solid 1px white;
+padding-top: 3px;
+}
+
+div.configprefix {
+font-size: 150%;
+font-weight: bolder;
+}
+
+.configshortdesc{
+clear: both;
+font-size: 130%;
+}
+
+.configlongdesc{
+float: left;
+clear: both;
+font-weight: lighter;
+font-style: italic;
+color: #ddd;
+}
+
+#configForm input, #configForm select{
+margin: 0 0 0 10px;
+}
+
+#configForm input{
+width: 300px;
+}
+
+span.mark{
+color: #035196;
+}
+
+span.connected{
+color: #fff;
+}
+
+span.disconnected{
+color: #aaa;
+}
+
+div.histogramConnected{
+background: #fff;
+}
+
+div.histogramDisconnected{
+background: #aaa;
+}
+
+span.peer_connected {
+       color: #008000;
+}
+
+span.peer_backed_off {
+       color: #ff8c00;
+       font-weight: bold;
+}
+
+span.peer_too_new {
+       color: #ff0000;
+       font-weight: bold;
+}
+
+span.peer_too_old {
+       color: #d0a0d0;
+       font-weight: bold;
+}
+
+span.peer_disconnected {
+       color: #d0d0d0;
+}
+
+span.peer_routing_disabled {
+        color: #7b68ee;
+}
+
+span.peer_never_connected {
+       color: #a0a0a0;
+}
+
+span.peer_disabled {
+       color: #a0a0a0;
+}
+
+span.peer_bursting {
+       color: #a0a0a0;
+}
+
+span.peer_listening {
+       color: #a0a0a0;
+}
+
+span.peer_listen_only {
+       color: #a0a0a0;
+}
+
+span.peer_version_problem {
+       color: #d07070;
+       font-weight: bold;
+}
+
+span.peer_idle_old {
+       color: #d07070;
+       font-weight: bold;
+}
+

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/alert-16.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/error-16.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/information-16.png
===================================================================
(Binary files differ)

Modified: trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/logo.png
===================================================================
(Binary files differ)

Modified: 
trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/warning-16.png
===================================================================
(Binary files differ)

Modified: trunk/freenet/src/freenet/config/EnumerableOptionCallback.java
===================================================================
--- trunk/freenet/src/freenet/config/EnumerableOptionCallback.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/config/EnumerableOptionCallback.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -6,7 +6,6 @@

 public interface EnumerableOptionCallback {
        public String[] getPossibleValues();
-       public void setPossibleValues(String[] val);

        /** Return the current value */
        public String get();

Deleted: trunk/freenet/src/freenet/crypt/CipherInputStream.java
===================================================================
--- trunk/freenet/src/freenet/crypt/CipherInputStream.java      2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/crypt/CipherInputStream.java      2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,107 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.crypt;
-
-import java.io.*;
-
-/**
- * Implements a Java InputStream that is encrypted with any symmetric block
- * cipher (implementing the BlockCipher interface).
- * 
- * This stream operates in Periodic Cipher Feedback Mode (PCFB), allowing 
- * byte at a time encryption with no additional encryption workload.
- */
-
-public class CipherInputStream extends FilterInputStream {
-
-    private final PCFBMode ctx;
-    private boolean needIV = false;
-
-    public CipherInputStream(BlockCipher c, InputStream in) {
-        this(PCFBMode.create(c), in);
-    }
-
-    public CipherInputStream(BlockCipher c, InputStream in, boolean readIV) 
-        throws IOException {
-
-        this(PCFBMode.create(c), in);
-        if (readIV) ctx.readIV(this.in);
-    }
-
-    public boolean needIV() {
-        return needIV;
-    }
-    
-    /**
-     * This constructor causes the IV to be read of the connection the
-     * first time one of the read messages is read (if later is set).
-     */
-    public CipherInputStream(BlockCipher c, InputStream in, boolean readIV,
-                             boolean later) throws IOException {
-        this(PCFBMode.create(c), in);
-        if (readIV && later)
-            needIV = true;
-        else if (readIV)
-            ctx.readIV(this.in);
-    }
-
-    public CipherInputStream(BlockCipher c, InputStream in, byte[] iv) {
-        this(new PCFBMode(c, iv), in);
-    }
-
-    public CipherInputStream(PCFBMode ctx, InputStream in) {
-        super(in);
-        this.ctx = ctx;
-    }
-
-    //int read = 0;
-    @Override
-       public int read() throws IOException {
-        if (needIV) {
-            ctx.readIV(in);
-            needIV = false;
-        }
-        //System.err.println("CIS READING");
-        int rv=in.read();
-
-        //if ((read++ % 5) == 0)
-        //    System.err.println("CIS READ " + read);
-        return (rv==-1 ? -1 : ctx.decipher(rv));
-    }
-
-    @Override
-       public int read(byte[] b, int off, int len) throws IOException {
-        if (needIV) {
-            ctx.readIV(in);
-            needIV = false;
-        }
-        //System.err.println("CIS READING IN: " + in.toString() + " LEN: " + 
-        //                   len);
-        int rv=in.read(b, off, len);
-        //System.err.println("CIS READ " + (read += rv));
-        if (rv != -1) {
-            ctx.blockDecipher(b, off, rv);
-            return rv;
-        } else 
-            return -1;
-    }
-
-    @Override
-       public int available() throws IOException {
-        int r = in.available();
-        return (needIV ? Math.max(0, r - ctx.lengthIV()) : r);
-    }
-
-    public PCFBMode getCipher() {
-       return ctx;
-    }
-}
-
-
-
-
-
-
-
-

Deleted: trunk/freenet/src/freenet/crypt/CipherModes.java
===================================================================
--- trunk/freenet/src/freenet/crypt/CipherModes.java    2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/crypt/CipherModes.java    2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -1,15 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.crypt;
-
-public interface CipherModes {
-
-    public int 
-       ECB = 0,
-       CBC = 1,
-       CFB = 2;
-}
-
-       
-       

Deleted: trunk/freenet/src/freenet/crypt/CipherOutputStream.java
===================================================================
--- trunk/freenet/src/freenet/crypt/CipherOutputStream.java     2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/crypt/CipherOutputStream.java     2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,63 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.crypt;
-
-import java.io.*;
-
-/**
- * Implements a Java OutputStream that is encrypted with any symmetric block
- * cipher (implementing the BlockCipher interface).
- * 
- * This stream operates in Periodic Cipher Feedback Mode (PCFB), allowing 
- * byte at a time encryption with no additional encryption workload.
- */
-public class CipherOutputStream extends FilterOutputStream {
-
-    private final PCFBMode ctx;
-    
-    public PCFBMode getCipher() {
-       return ctx;
-    }
-    
-    public CipherOutputStream(BlockCipher c, OutputStream out) {
-        this(PCFBMode.create(c), out);
-    }
-
-    public CipherOutputStream(BlockCipher c, OutputStream out, byte[] iv) {
-        this(PCFBMode.create(c, iv), out);
-    }
-
-    public CipherOutputStream(PCFBMode ctx, OutputStream out) {
-        super(out);
-        this.ctx = ctx;
-    }
-
-    //int wrote = 0;            
-    @Override
-       public void write(int b) throws IOException {
-        //System.err.println("WRITING BYTE: " + wrote++);
-        out.write(ctx.encipher(b));
-    }
-
-    @Override
-       public void write(byte[] buf, int off, int len) throws IOException {
-        //System.err.println("WRITING BUF LENGTH : " + (wrote += len));
-        byte[] tmp = new byte[len];
-        System.arraycopy(buf, off, tmp, 0, len);
-        ctx.blockEncipher(tmp, 0, len);
-        out.write(tmp);
-    }
-    
-    // FOS will use write(int) to implement this if we don't override it!
-    @Override
-       public void write(byte[] buf) throws IOException {
-       write(buf, 0, buf.length);
-    }
-}
-
-
-
-
-
-

Modified: trunk/freenet/src/freenet/crypt/DSAGroup.java
===================================================================
--- trunk/freenet/src/freenet/crypt/DSAGroup.java       2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/crypt/DSAGroup.java       2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -5,10 +5,7 @@

 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.math.BigInteger;
-import java.util.Random;
-import java.util.Vector;

 import net.i2p.util.NativeBigInteger;
 import freenet.node.FSParseException;
@@ -24,16 +21,10 @@
 public class DSAGroup extends CryptoKey {
        private static final long serialVersionUID = -1;

-       public static final int Q_BIT_LENGTH = 256;
+       protected static final int Q_BIT_LENGTH = 256;

     private final BigInteger p, q, g;

-    // of the
-    // hexadecimal
-    // string
-    // representations
-    // of p,q and g
-
     public DSAGroup(BigInteger p, BigInteger q, BigInteger g) {
         this.p = p;
         this.q = q;
@@ -42,28 +33,6 @@
                throw new IllegalArgumentException();
     }

-    public DSAGroup(String pAsHexString, String qAsHexString,
-            String gAsHexString) throws NumberFormatException {
-        //Sanity check. Needed because of the Kaffe workaround further down
-        if ((pAsHexString == null) || (qAsHexString == null)
-                || (gAsHexString == null))
-                throw new NullPointerException("Invalid DSAGroup");
-
-        try {
-            this.p = new NativeBigInteger(pAsHexString, 16);
-            this.q = new NativeBigInteger(qAsHexString, 16);
-            this.g = new NativeBigInteger(gAsHexString, 16);
-        } catch (NullPointerException e) {
-            // yea, i know, don't catch NPEs .. but _some_ JVMs don't
-            // throw the NFE like they are supposed to (*cough* kaffe)
-            throw new NumberFormatException(e + " while converting "
-                    + pAsHexString + ',' + qAsHexString + " and "
-                    + gAsHexString + " to integers");
-        }
-        if(p.signum() != 1 || q.signum() != 1 || g.signum() != 1)
-               throw new IllegalArgumentException();
-    }
-
     /**
      * Parses a DSA Group from a string, where p, q, and g are in unsigned
      * hex-strings, separated by a commas
@@ -91,17 +60,6 @@
         }
     }

-    public void writeForWire(OutputStream out) throws IOException {
-        Util.writeMPI(p, out);
-        Util.writeMPI(q, out);
-        Util.writeMPI(g, out);
-    }
-
-    //    public void write(OutputStream out) throws IOException {
-    //         write(out, getClass().getName());
-    //         writeForWire(out);
-    //    }
-
     @Override
        public String keyType() {
         return "DSA.g-" + p.bitLength();
@@ -128,59 +86,6 @@
         return fingerprint(fp);
     }

-    static class QG extends Thread {
-
-        public Vector qs = new Vector();
-
-        protected Random r;
-
-        public QG(Random r) {
-            setDaemon(true);
-            this.r = r;
-        }
-
-        @Override
-               public void run() {
-            while (true) {
-                qs.addElement(makePrime(DSAGroup.Q_BIT_LENGTH, 80, r));
-                synchronized (this) {
-                    notifyAll();
-                }
-                while (qs.size() >= 3) {
-                    synchronized (this) {
-                        try {
-                            wait(50);
-                        } catch (InterruptedException ie) {
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    static BigInteger smallPrimes[] = new BigInteger[] { BigInteger.valueOf(3),
-            BigInteger.valueOf(5), BigInteger.valueOf(7),
-            BigInteger.valueOf(11), BigInteger.valueOf(13),
-            BigInteger.valueOf(17), BigInteger.valueOf(19),
-            BigInteger.valueOf(23), BigInteger.valueOf(29)};
-
-    public static BigInteger makePrime(int bits, int confidence, Random r) {
-        BigInteger rv;
-        do {
-            // FIXME: is this likely to get modPow()ed?
-            // I don't suppose it matters, there isn't much overhead
-            rv = new NativeBigInteger(bits, r).setBit(0).setBit(bits - 1);
-        } while (!isPrime(rv, confidence));
-        return rv;
-    }
-
-    public static boolean isPrime(BigInteger b, int confidence) {
-        for (int i = 0; i < smallPrimes.length; i++) {
-            if (b.mod(smallPrimes[i]).equals(BigInteger.ZERO)) return false;
-        }
-        return b.isProbablePrime(80);
-    }
-
     @Override
        public byte[] asBytes() {
         byte[] pb = Util.MPIbytes(p);

Deleted: trunk/freenet/src/freenet/crypt/DecipherOutputStream.java
===================================================================
--- trunk/freenet/src/freenet/crypt/DecipherOutputStream.java   2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/crypt/DecipherOutputStream.java   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,50 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.crypt;
-
-import java.io.*;
-
-/**
- * Implements a Java OutputStream that decrypts the data before writing
- * to the substream.
- * This differs from CipherOutputStream, which encrypts the data instead.
- * @author tavin
- */
-public class DecipherOutputStream extends FilterOutputStream {
-    
-    private PCFBMode ctx;
-
-    public DecipherOutputStream(OutputStream out, BlockCipher c) {
-        this(out, PCFBMode.create(c));
-    }
-
-    public DecipherOutputStream(OutputStream out, BlockCipher c, int bufSize) {
-        this(new BufferedOutputStream(out, bufSize), c);
-    }
-
-    public DecipherOutputStream(OutputStream out, PCFBMode ctx) {
-        super(out);
-        this.ctx = ctx;
-    }
-
-    public DecipherOutputStream(OutputStream out, PCFBMode ctx, int bufSize) {
-        this(new BufferedOutputStream(out, bufSize), ctx);
-    }
-
-    @Override
-       public void write(int b) throws IOException {
-        out.write(ctx.decipher(b));
-    }
-    
-    @Override
-       public void write(byte[] buf, int off, int len) throws IOException {
-        byte[] tmp = new byte[len];
-        System.arraycopy(buf, off, tmp, 0, len);
-        ctx.blockDecipher(tmp, 0, len);
-        out.write(tmp);
-    }
-}
-
-
-

Deleted: trunk/freenet/src/freenet/crypt/DecryptionFailedException.java
===================================================================
--- trunk/freenet/src/freenet/crypt/DecryptionFailedException.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/crypt/DecryptionFailedException.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,11 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.crypt;
-
-public class DecryptionFailedException extends Exception {
-       private static final long serialVersionUID = -1;
-    public DecryptionFailedException (String m) {
-       super(m);
-    }
-}

Modified: trunk/freenet/src/freenet/crypt/DiffieHellman.java
===================================================================
--- trunk/freenet/src/freenet/crypt/DiffieHellman.java  2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/crypt/DiffieHellman.java  2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -35,7 +35,7 @@

        private static Random r;
        private static DHGroup group = Global.DHgroupA;
-       private static Stack precalcBuffer = new Stack();
+       private static Stack<NativeBigInteger[]> precalcBuffer = new 
Stack<NativeBigInteger[]>();
        private static Object precalcerWaitObj = new Object();

        private static NativeThread precalcThread;
@@ -114,10 +114,10 @@
        public static NativeBigInteger[] getParams() {
                synchronized (precalcBuffer) {
                        //Ensure that we will have something to pop (at least 
pretty soon)
-                       askRefill(); 
+                       askRefill();

                        if(!precalcBuffer.isEmpty()) {
-                               return (NativeBigInteger[]) precalcBuffer.pop();
+                               return precalcBuffer.pop();
                        }

                }

Deleted: trunk/freenet/src/freenet/crypt/DigestInputStream.java
===================================================================
--- trunk/freenet/src/freenet/crypt/DigestInputStream.java      2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/crypt/DigestInputStream.java      2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,34 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.crypt;
-
-import java.io.*;
-
-public class DigestInputStream extends FilterInputStream {
-    protected Digest ctx;
-
-    public DigestInputStream(Digest d, InputStream in) {
-       super(in);
-       this.ctx=d;
-    }
-
-    @Override
-       public int read(byte[] b, int offset, int len) throws IOException {
-       int rl=super.read(b, offset, len);
-       if (rl>0) ctx.update(b, offset, rl);
-       return rl;
-    }
-
-    @Override
-       public int read() throws IOException {
-       int rv=super.read();
-       if (rv!=-1) ctx.update((byte)rv);
-       return rv;
-    }
-
-    public Digest getDigest() {
-       return ctx;
-    }
-}
-       

Deleted: trunk/freenet/src/freenet/crypt/DigestOutputStream.java
===================================================================
--- trunk/freenet/src/freenet/crypt/DigestOutputStream.java     2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/crypt/DigestOutputStream.java     2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,37 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.crypt;
-
-import java.io.*;
-
-public class DigestOutputStream extends FilterOutputStream {
-    protected Digest ctx;
-
-    public DigestOutputStream(Digest d, OutputStream out) {
-       super(out);
-       this.ctx=d;
-    }
-
-    @Override
-       public void write(byte[] b) throws IOException {
-       write(b, 0, b.length);
-    }
-
-    @Override
-       public void write(byte[] b, int offset, int len) throws IOException {
-       ctx.update(b, offset, len);
-       out.write(b, offset, len);
-    }
-
-    @Override
-       public void write(int b) throws IOException {
-       ctx.update((byte)b);
-       out.write(b);
-    }
-
-    public Digest getDigest() {
-       return ctx;
-    }
-}
-       

Deleted: trunk/freenet/src/freenet/crypt/EncipherInputStream.java
===================================================================
--- trunk/freenet/src/freenet/crypt/EncipherInputStream.java    2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/crypt/EncipherInputStream.java    2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,47 +0,0 @@
-package freenet.crypt;
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-
-import java.io.*;
-
-/**
- * Implements a Java InputStream that encrypts the substream on the way in.
- * This differs from CipherInputStream, which is decrypting an already
- * encrypted source
- */
-public class EncipherInputStream extends FilterInputStream {
-
-    protected PCFBMode ctx;
-
-    public EncipherInputStream(InputStream in, BlockCipher c) {
-        this(in, PCFBMode.create(c));
-    }
-
-    public EncipherInputStream(InputStream in, BlockCipher c, int bufSize) {
-        this(bufSize == 0 ? in : new BufferedInputStream(in, bufSize), c);
-    }
-
-    public EncipherInputStream(InputStream in, PCFBMode ctx) {
-        super(in);
-        this.ctx = ctx;
-    }
-
-    public EncipherInputStream(InputStream in, PCFBMode ctx, int bufSize) {
-        this(bufSize == 0 ? in : new BufferedInputStream(in, bufSize), ctx);
-    }
-
-    @Override
-       public int read() throws IOException {
-        int rv=in.read();
-        return (rv==-1 ? -1 : ctx.encipher(rv));
-    }
-
-    @Override
-       public int read(byte[] b, int off, int len) throws IOException {
-        int rv=in.read(b, off, len);
-        if (rv != -1) ctx.blockEncipher(b, off, rv);
-        return rv;
-    }
-}
-

Modified: trunk/freenet/src/freenet/crypt/HMAC.java
===================================================================
--- trunk/freenet/src/freenet/crypt/HMAC.java   2008-11-06 13:50:42 UTC (rev 
23350)
+++ trunk/freenet/src/freenet/crypt/HMAC.java   2008-11-06 13:53:57 UTC (rev 
23351)
@@ -45,7 +45,7 @@
                else {
                        // Step 2
                        if(K.length > B)
-                               K = Util.hashBytes(d, K);
+                               K0 = K = Util.hashBytes(d, K);

                        if(K.length < B) { // Step 3
                                K0 = new byte[B];

Deleted: trunk/freenet/src/freenet/crypt/KEProtocol.java
===================================================================
--- trunk/freenet/src/freenet/crypt/KEProtocol.java     2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/crypt/KEProtocol.java     2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -1,26 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.crypt;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Defines the interface that must be implemented by key-exchange protocols
- * such as RSA and Diffie-Hellman
- */
-public abstract class KEProtocol {
-    protected RandomSource randomSource;
-    protected EntropySource es;
-
-    public KEProtocol(RandomSource rs) {
-       randomSource=rs;
-       es=new EntropySource();
-    }
-
-    public abstract void negotiateKey(InputStream in, OutputStream out,
-                                     byte[] key, int offset, int len) 
-                                     throws IOException;
-}

Modified: trunk/freenet/src/freenet/crypt/RandomSource.java
===================================================================
--- trunk/freenet/src/freenet/crypt/RandomSource.java   2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/crypt/RandomSource.java   2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -10,6 +10,7 @@
  *
  * @author Scott G. Miller <scgmille at indiana.edu>
  */
+ at SuppressWarnings("serial")
 public abstract class RandomSource extends Random {

     /**
@@ -79,7 +80,5 @@
      * do so when this method is called
      */
     public abstract void close();
-
-
 }


Modified: trunk/freenet/src/freenet/crypt/SHA256.java
===================================================================
--- trunk/freenet/src/freenet/crypt/SHA256.java 2008-11-06 13:50:42 UTC (rev 
23350)
+++ trunk/freenet/src/freenet/crypt/SHA256.java 2008-11-06 13:53:57 UTC (rev 
23351)
@@ -76,7 +76,7 @@
                }
        }

-       static private final Vector digests = new Vector();
+       static private final Vector<MessageDigest> digests = new 
Vector<MessageDigest>();

        /**
         * Create a new SHA-256 MessageDigest
@@ -85,7 +85,7 @@
        public synchronized static MessageDigest getMessageDigest() {
                try {
                        if(!digests.isEmpty())
-                               return (MessageDigest) 
digests.remove(digests.size() - 1);
+                               return digests.remove(digests.size() - 1);
                        return MessageDigest.getInstance("SHA-256");
                } catch(NoSuchAlgorithmException e2) {
                        //TODO: maybe we should point to a HOWTO for freejvms

Deleted: trunk/freenet/src/freenet/crypt/UnsupportedDigestException.java
===================================================================
--- trunk/freenet/src/freenet/crypt/UnsupportedDigestException.java     
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/crypt/UnsupportedDigestException.java     
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,9 +0,0 @@
-package freenet.crypt;
-
-public class UnsupportedDigestException extends Exception {
-       private static final long serialVersionUID = -1;
-    public UnsupportedDigestException() {}
-    public UnsupportedDigestException(String s) {
-        super(s);
-    }
-}

Modified: trunk/freenet/src/freenet/crypt/Yarrow.java
===================================================================
--- trunk/freenet/src/freenet/crypt/Yarrow.java 2008-11-06 13:50:42 UTC (rev 
23350)
+++ trunk/freenet/src/freenet/crypt/Yarrow.java 2008-11-06 13:53:57 UTC (rev 
23351)
@@ -102,7 +102,7 @@
                slow_pool_reseed();
        }

-       public void seedFromExternalStuff(boolean canBlock) {
+       private void seedFromExternalStuff(boolean canBlock) {
                byte[] buf = new byte[32];
                if(File.separatorChar == '/') {
                        DataInputStream dis = null;
@@ -179,7 +179,7 @@
                EntropySource startupEntropy = new EntropySource();

                // Consume the system properties list
-               for(Enumeration enu = sys.propertyNames(); 
enu.hasMoreElements();) {
+               for(Enumeration<?> enu = sys.propertyNames(); 
enu.hasMoreElements();) {
                        String key = (String) enu.nextElement();
                        consumeString(key);
                        consumeString(sys.getProperty(key));
@@ -237,7 +237,7 @@
        }
        private long timeLastWroteSeed = -1;

-       public void write_seed(File filename) {
+       private void write_seed(File filename) {
                write_seed(filename, false);
        }

@@ -421,12 +421,12 @@
        private MessageDigest fast_pool,  slow_pool;
        private int fast_entropy,  slow_entropy;
        private boolean fast_select;
-       private Hashtable entropySeen;
+       private Hashtable<EntropySource, Integer> entropySeen;

        private void accumulator_init(String digest) throws 
NoSuchAlgorithmException {
                fast_pool = MessageDigest.getInstance(digest);
                slow_pool = MessageDigest.getInstance(digest);
-               entropySeen = new Hashtable();
+               entropySeen = new Hashtable<EntropySource, Integer>();
        }

        @Override
@@ -450,7 +450,7 @@
                return totalRealEntropy;
        }

-       public int acceptEntropy(
+       private int acceptEntropy(
                EntropySource source,
                long data,
                int entropyGuess,
@@ -489,7 +489,7 @@
                                slow_entropy += actualEntropy;

                                if(source != null) {
-                                       Integer contributedEntropy = (Integer) 
entropySeen.get(source);
+                                       Integer contributedEntropy = 
entropySeen.get(source);
                                        if(contributedEntropy == null)
                                                contributedEntropy = new 
Integer(actualEntropy);
                                        else
@@ -498,9 +498,9 @@

                                        if(slow_entropy >= (SLOW_THRESHOLD * 
2)) {
                                                int kc = 0;
-                                               for(Enumeration enu = 
entropySeen.keys(); enu.hasMoreElements();) {
+                                               for(Enumeration<EntropySource> 
enu = entropySeen.keys(); enu.hasMoreElements();) {
                                                        Object key = 
enu.nextElement();
-                                                       Integer v = (Integer) 
entropySeen.get(key);
+                                                       Integer v = 
entropySeen.get(key);
                                                        if(DEBUG)
                                                                
Logger.normal(this, "Key: <" + key + "> " + v);
                                                        if(v.intValue() > 
SLOW_THRESHOLD) {
@@ -636,9 +636,9 @@
                fast_pool_reseed();
                slow_entropy = 0;

-               Integer ZERO = new Integer(0);
-               for(Enumeration enu = entropySeen.keys(); 
enu.hasMoreElements();)
-                       entropySeen.put(enu.nextElement(), ZERO);
+               Integer ZERO = 0;
+               for(EntropySource src : entropySeen.keySet())
+                       entropySeen.put(src, ZERO);
        }
        /**
         * 5.4 Reseed Control parameters
@@ -768,16 +768,4 @@
                        slow_pool.update(bytes, 0, bytes.length);
                fast_select = !fast_select;
        }
-
-       public String getCheckpointName() {
-               return "Yarrow random number generator checkpoint";
-       }
-
-       public long nextCheckpoint() {
-               return System.currentTimeMillis() + 60 * 60 * 1000;
-       }
-
-       public void checkpoint() {
-               seedFromExternalStuff(true);
-       }
 }

Modified: trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Algorithm.java
===================================================================
--- trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Algorithm.java     
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Algorithm.java     
2008-11-06 13:53:57 UTC (rev 23351)
@@ -46,12 +46,7 @@
        private static void trace(boolean in, String s) {
                if (TRACE) err.println((in?"==> ":"<== ")+NAME+ '.' +s);
        }
-       private static void trace(String s) {
-               if (TRACE)
-                       err.println("<=> " + NAME + '.' + s);
-       }
-
-
+       
 //     Constants and variables
 //     
...........................................................................


Modified: trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Properties.java
===================================================================
--- trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Properties.java    
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/crypt/ciphers/Rijndael_Properties.java    
2008-11-06 13:53:57 UTC (rev 23351)
@@ -100,7 +100,7 @@
                out.println("# ----- Begin "+ALGORITHM+" properties -----");
                out.println("#");
                String key, value;
-               Enumeration enu = properties.propertyNames();
+               Enumeration<?> enu = properties.propertyNames();
                while (enu.hasMoreElements()) {
                        key = (String) enu.nextElement();
                        value = getProperty(key);
@@ -112,7 +112,7 @@

 //     public synchronized void load(InputStream in) throws IOException {}

-       public static Enumeration propertyNames() {
+       public static Enumeration<?> propertyNames() {
                return properties.propertyNames();
        }


Modified: trunk/freenet/src/freenet/io/AddressTracker.java
===================================================================
--- trunk/freenet/src/freenet/io/AddressTracker.java    2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/io/AddressTracker.java    2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -44,10 +44,10 @@
 public class AddressTracker {

        /** PeerAddressTrackerItem's by Peer */
-       private final HashMap peerTrackers;
+       private final HashMap<Peer, PeerAddressTrackerItem> peerTrackers;

        /** InetAddressAddressTrackerItem's by InetAddress */
-       private final HashMap ipTrackers;
+       private final HashMap<InetAddress, InetAddressAddressTrackerItem> 
ipTrackers;

        /** Maximum number of Item's of either type */
        static final int MAX_ITEMS = 1000;
@@ -55,7 +55,6 @@
        private long timeDefinitelyNoPacketsReceived;
        private long timeDefinitelyNoPacketsSent;

-       private boolean isBroken;
        private long brokenTime;

        public static AddressTracker create(long lastBootID, File nodeDir, int 
port) {
@@ -89,8 +88,8 @@
        private AddressTracker() {
                timeDefinitelyNoPacketsReceived = System.currentTimeMillis();
                timeDefinitelyNoPacketsSent = System.currentTimeMillis();
-               peerTrackers = new HashMap();
-               ipTrackers = new HashMap();
+               peerTrackers = new HashMap<Peer, PeerAddressTrackerItem>();
+               ipTrackers = new HashMap<InetAddress, 
InetAddressAddressTrackerItem>();
        }

        private AddressTracker(SimpleFieldSet fs, long lastBootID) throws 
FSParseException {
@@ -104,25 +103,25 @@
                //timeDefinitelyNoPacketsReceived = 
fs.getLong("TimeDefinitelyNoPacketsReceived");
                timeDefinitelyNoPacketsReceived = System.currentTimeMillis();
                timeDefinitelyNoPacketsSent = 
fs.getLong("TimeDefinitelyNoPacketsSent");
-               peerTrackers = new HashMap();
+               peerTrackers = new HashMap<Peer, PeerAddressTrackerItem>();
                SimpleFieldSet peers = fs.subset("Peers");
                if(peers != null) {
-               Iterator i = peers.directSubsetNameIterator();
+               Iterator<String> i = peers.directSubsetNameIterator();
                if(i != null) {
                while(i.hasNext()) {
-                       SimpleFieldSet peer = peers.subset((String)i.next());
+                       SimpleFieldSet peer = peers.subset(i.next());
                        PeerAddressTrackerItem item = new 
PeerAddressTrackerItem(peer);
                        peerTrackers.put(item.peer, item);
                }
                }
                }
-               ipTrackers = new HashMap();
+               ipTrackers = new HashMap<InetAddress, 
InetAddressAddressTrackerItem>();
                SimpleFieldSet ips = fs.subset("IPs");
                if(ips != null) {
-               Iterator i = ips.directSubsetNameIterator();
+               Iterator<String> i = ips.directSubsetNameIterator();
                if(i != null) {
                while(i.hasNext()) {
-                       SimpleFieldSet peer = ips.subset((String)i.next());
+                       SimpleFieldSet peer = ips.subset(i.next());
                        InetAddressAddressTrackerItem item = new 
InetAddressAddressTrackerItem(peer);
                        ipTrackers.put(item.addr, item);
                }
@@ -143,7 +142,7 @@
                InetAddress ip = peer.getAddress();
                long now = System.currentTimeMillis();
                synchronized(this) {
-                       PeerAddressTrackerItem peerItem = 
(PeerAddressTrackerItem) peerTrackers.get(peer);
+                       PeerAddressTrackerItem peerItem = 
peerTrackers.get(peer);
                        if(peerItem == null) {
                                peerItem = new 
PeerAddressTrackerItem(timeDefinitelyNoPacketsReceived, 
timeDefinitelyNoPacketsSent, peer);
                                if(peerTrackers.size() > MAX_ITEMS) {
@@ -158,7 +157,7 @@
                                peerItem.sentPacket(now);
                        else
                                peerItem.receivedPacket(now);
-                       InetAddressAddressTrackerItem ipItem = 
(InetAddressAddressTrackerItem) ipTrackers.get(ip);
+                       InetAddressAddressTrackerItem ipItem = 
ipTrackers.get(ip);
                        if(ipItem == null) {
                                ipItem = new 
InetAddressAddressTrackerItem(timeDefinitelyNoPacketsReceived, 
timeDefinitelyNoPacketsSent, ip);
                                if(ipTrackers.size() > MAX_ITEMS) {
@@ -186,12 +185,12 @@

        public synchronized PeerAddressTrackerItem[] 
getPeerAddressTrackerItems() {
                PeerAddressTrackerItem[] items = new 
PeerAddressTrackerItem[peerTrackers.size()];
-               return (PeerAddressTrackerItem[]) 
peerTrackers.values().toArray(items);
+               return peerTrackers.values().toArray(items);
        }

        public synchronized InetAddressAddressTrackerItem[] 
getInetAddressTrackerItems() {
                InetAddressAddressTrackerItem[] items = new 
InetAddressAddressTrackerItem[ipTrackers.size()];
-               return (InetAddressAddressTrackerItem[]) 
ipTrackers.values().toArray(items);
+               return ipTrackers.values().toArray(items);
        }

        public static final int DEFINITELY_PORT_FORWARDED = 2;

Modified: trunk/freenet/src/freenet/io/AllowedHosts.java
===================================================================
--- trunk/freenet/src/freenet/io/AllowedHosts.java      2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/io/AllowedHosts.java      2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -26,7 +26,7 @@
 /** Implementation of allowedHosts */
 public class AllowedHosts {

-       protected final List addressMatchers = new ArrayList();
+       protected final List<AddressMatcher> addressMatchers = new 
ArrayList<AddressMatcher>();

        public AllowedHosts(String allowedHosts) {
                setAllowedHosts(allowedHosts);
@@ -42,7 +42,7 @@
        public void setAllowedHosts(String allowedHosts) {
                 if(allowedHosts == null || allowedHosts.equals("")) 
allowedHosts = NetworkInterface.DEFAULT_BIND_TO;
                StringTokenizer allowedHostsTokens = new 
StringTokenizer(allowedHosts, ",");
-               List newAddressMatchers = new ArrayList();
+               List<AddressMatcher> newAddressMatchers = new 
ArrayList<AddressMatcher>();
                while (allowedHostsTokens.hasMoreTokens()) {
                        String allowedHost = 
allowedHostsTokens.nextToken().trim();
                        String hostname = allowedHost;
@@ -73,9 +73,7 @@
        }

        public synchronized boolean allowed(AddressType clientAddressType, 
InetAddress clientAddress) {
-               for(int i=0;i<addressMatchers.size();i++) {
-                       AddressMatcher matcher = (AddressMatcher) 
addressMatchers.get(i);
-                       
+               for(AddressMatcher matcher: addressMatchers) {
                        if (clientAddressType == matcher.getAddressType()) {
                                if(matcher.matches(clientAddress)) return true;
                        }
@@ -86,7 +84,7 @@
        public synchronized String getAllowedHosts() {
                StringBuilder sb = new StringBuilder();
                for(int i=0;i<addressMatchers.size();i++) {
-                       AddressMatcher matcher = (AddressMatcher) 
addressMatchers.get(i);
+                       AddressMatcher matcher = addressMatchers.get(i);
                        if(matcher instanceof EverythingMatcher) return "*";
                        if(i != 0) sb.append(',');
                        sb.append(matcher.getHumanRepresentation());

Modified: trunk/freenet/src/freenet/io/NetworkInterface.java
===================================================================
--- trunk/freenet/src/freenet/io/NetworkInterface.java  2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/io/NetworkInterface.java  2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -26,7 +26,6 @@
 import java.net.SocketException;
 import java.net.SocketTimeoutException;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 import java.util.StringTokenizer;

@@ -49,10 +48,10 @@
        protected final Object syncObject = new Object();

        /** Acceptors created by this interface. */
-       private final List/* <Acceptor> */acceptors = new ArrayList();
+       private final List<Acceptor>  acceptors = new ArrayList<Acceptor>();

        /** Queue of accepted client connections. */
-       protected final List/* <Socket> */acceptedSockets = new ArrayList();
+       protected final List<Socket> acceptedSockets = new ArrayList<Socket>();

        /** AllowedHosts structure */
        protected final AllowedHosts allowedHosts;
@@ -112,13 +111,13 @@
        public void setBindTo(String bindTo, boolean ignoreUnbindableIP6) 
throws IOException {
                 if(bindTo == null || bindTo.equals("")) bindTo = 
NetworkInterface.DEFAULT_BIND_TO;
                StringTokenizer bindToTokens = new StringTokenizer(bindTo, ",");
-               List bindToTokenList = new ArrayList();
+               List<String> bindToTokenList = new ArrayList<String>();
                while (bindToTokens.hasMoreTokens()) {
                        bindToTokenList.add(bindToTokens.nextToken().trim());
                }
                /* stop the old acceptors. */
                for (int acceptorIndex = 0, acceptorCount = acceptors.size(); 
acceptorIndex < acceptorCount; acceptorIndex++) {
-                       Acceptor acceptor = (Acceptor) 
acceptors.get(acceptorIndex);
+                       Acceptor acceptor = acceptors.get(acceptorIndex);
                        try {
                                acceptor.close();
                        } catch (IOException e) {
@@ -138,7 +137,7 @@
                        ServerSocket serverSocket = createServerSocket();
                        InetSocketAddress addr = null;
                        try {
-                               addr = new InetSocketAddress((String) 
bindToTokenList.get(serverSocketIndex), port);
+                               addr = new 
InetSocketAddress(bindToTokenList.get(serverSocketIndex), port);
                                serverSocket.setReuseAddress(true);
                                serverSocket.bind(addr);
                        } catch (SocketException e) {
@@ -152,9 +151,7 @@
                }
                setSoTimeout(timeout);
                synchronized (syncObject) {
-                       Iterator acceptors = this.acceptors.iterator();
-                       while (acceptors.hasNext()) {
-                               Acceptor acceptor=(Acceptor) acceptors.next();
+                       for (Acceptor acceptor : this.acceptors) {
                                executor.execute(acceptor, "Network Interface 
Acceptor for "+acceptor.serverSocket);
                        }
                }
@@ -174,9 +171,8 @@
         * @see ServerSocket#setSoTimeout(int)
         */
        public void setSoTimeout(int timeout) throws SocketException {
-               Iterator acceptors = this.acceptors.iterator();
-               while (acceptors.hasNext()) {
-                       ((Acceptor) acceptors.next()).setSoTimeout(timeout);
+               for (Acceptor acceptor : acceptors) {
+                       acceptor.setSoTimeout(timeout);
                }
        }

@@ -202,7 +198,7 @@
                                        throw new SocketTimeoutException();
                                }
                        }
-                       return (Socket) acceptedSockets.remove(0);
+                       return acceptedSockets.remove(0);
                }
        }

@@ -215,9 +211,7 @@
         */
        public void close() throws IOException {
                IOException exception = null;
-               Iterator acceptors = this.acceptors.iterator();
-               while (acceptors.hasNext()) {
-                       Acceptor acceptor = (Acceptor) acceptors.next();
+               for (Acceptor acceptor : acceptors) {
                        try {
                                acceptor.close();
                        } catch (IOException ioe1) {
@@ -225,7 +219,7 @@
                        }
                }
                if (exception != null) {
-                       throw (exception);
+                       throw exception;
                }
        }


Modified: trunk/freenet/src/freenet/io/comm/DMT.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/DMT.java  2008-11-06 13:50:42 UTC (rev 
23350)
+++ trunk/freenet/src/freenet/io/comm/DMT.java  2008-11-06 13:53:57 UTC (rev 
23351)
@@ -192,7 +192,7 @@
                addLinkedListField(MISSING, Integer.class);
        }};

-       public static final Message createMissingPacketNotification(long uid, 
LinkedList missing) {
+       public static final Message createMissingPacketNotification(long uid, 
LinkedList<Integer> missing) {
                Message msg = new Message(missingPacketNotification);
                msg.set(UID, uid);
                msg.set(MISSING, missing);

Deleted: trunk/freenet/src/freenet/io/comm/DumpDispatcher.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/DumpDispatcher.java       2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/io/comm/DumpDispatcher.java       2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,18 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.io.comm;
-
-/**
- * Dispatcher that just dumps everything received to stderr.
- */
-public class DumpDispatcher implements Dispatcher {
-
-    public DumpDispatcher() {
-    }
-
-    public boolean handleMessage(Message m) {
-        System.err.println("Received message: "+m);
-        return true;
-    }
-}

Modified: trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java   2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -46,7 +46,7 @@
                        ba = new byte[4];
                        dis.readFully(ba);
                } else {
-                       throw new IOException("Unknown type byte (old form? 
corrupt stream? too short/long prev field?): "+(int)firstByte);
+                       throw new IOException("Unknown type byte (old form? 
corrupt stream? too short/long prev field?): "+firstByte);
                }
                _address = InetAddress.getByAddress(ba);
                String name = null;
@@ -269,7 +269,7 @@
                if(logMINOR) Logger.minor(this, "hostname is null, returning 
"+_address);
                return _address;
            } else {
-               if(logMINOR) Logger.minor(this, "Looking up '"+hostname+"' in 
DNS");
+               if(logMINOR) Logger.minor(this, "Looking up '"+hostname+"' in 
DNS", new Exception("debug"));
                /* 
                 * Peers are constructed from an address once a
                 * handshake has been completed, so this lookup

Modified: trunk/freenet/src/freenet/io/comm/IOStatisticCollector.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/IOStatisticCollector.java 2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/io/comm/IOStatisticCollector.java 2008-11-06 
13:53:57 UTC (rev 23351)
@@ -5,7 +5,7 @@

 import java.util.Date;
 import java.util.LinkedHashMap;
-import java.util.Iterator;
+import java.util.Map;

 import freenet.support.Logger;

@@ -18,11 +18,11 @@
        private static boolean logDEBUG;
        private long totalbytesin;
        private long totalbytesout;
-       private final LinkedHashMap targets;
+       private final LinkedHashMap<String, StatisticEntry> targets;
        static boolean ENABLE_PER_ADDRESS_TRACKING = false;

        public IOStatisticCollector() {
-               targets = new LinkedHashMap();
+               targets = new LinkedHashMap<String, StatisticEntry>();
                // TODO: only for testing!!!!
                // This should only happen once
                //SNMPAgent.create();
@@ -43,7 +43,7 @@
        private void _addInfo(String key, int inbytes, int outbytes) {
                rotate();
                if(ENABLE_PER_ADDRESS_TRACKING) {
-                       StatisticEntry entry = (StatisticEntry)targets.get(key);
+                       StatisticEntry entry = targets.get(key);
                        if (entry == null) {
                                entry = new StatisticEntry();
                                targets.put(key, entry);
@@ -92,11 +92,9 @@
                        ret[i][0] = ret[i][1] = 0;
                }

-               Iterator it = targets.keySet().iterator();
-               while (it.hasNext()) {
-                       String key = (String)it.next();
-                       int inres[] = 
((StatisticEntry)targets.get(key)).getRecieved();
-                       int outres[] = 
((StatisticEntry)targets.get(key)).getSent();
+               for (Map.Entry<String,StatisticEntry> entry : 
targets.entrySet()) {
+                       int inres[] = entry.getValue().getRecieved();
+                       int outres[] = entry.getValue().getSent();
                        for (int i = 0 ; i < STATISTICS_ENTRIES ; i++) {
                                ret[i][1] += inres[i];
                                ret[i][0] += outres[i];
@@ -111,12 +109,11 @@
                //DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, 
Locale.FRANCE);
                //System.err.println(DateFormat.getDateInstance().format(new 
Date()));
                System.err.println(new Date());
-               Iterator it = targets.keySet().iterator();
                final double divby = STATISTICS_DURATION_S*1024; 
-               while (it.hasNext()) {
-                       String key = (String)it.next();
-                       int inres[] = 
((StatisticEntry)targets.get(key)).getRecieved();
-                       int outres[] = 
((StatisticEntry)targets.get(key)).getSent();
+               for (Map.Entry<String,StatisticEntry> entry : 
targets.entrySet()) {
+                       String key = entry.getKey();
+                       int inres[] = entry.getValue().getRecieved();
+                       int outres[] = entry.getValue().getSent();
                        System.err.print((key + "          ").substring(0,22) + 
": ");
                        int tin = 0;
                        int tout = 0;
@@ -146,7 +143,7 @@
                        if(keys == null) return; // Why aren't we iterating 
there ?
                        for(int i = 0 ; i < keys.length ; i++) {
                                Object key = keys[i];
-                               if 
(((StatisticEntry)(targets.get(key))).rotate() == false)
+                               if (targets.get(key).rotate() == false)
                                        targets.remove(key);
                        }
                        // FIXME: debugging

Modified: trunk/freenet/src/freenet/io/comm/Message.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/Message.java      2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/io/comm/Message.java      2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -24,10 +24,10 @@
 import java.io.EOFException;
 import java.io.IOException;
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.Vector;
+import java.util.List;

 import freenet.support.ByteBufferInputStream;
 import freenet.support.Fields;
@@ -45,10 +45,10 @@
     public static final String VERSION = "$Id: Message.java,v 1.11 2005/09/15 
18:16:04 amphibian Exp $";

        private final MessageType _spec;
-       private final WeakReference/*<PeerContext>*/ _sourceRef;
+       private final WeakReference<? extends PeerContext> _sourceRef;
        private final boolean _internal;
-       private final HashMap _payload = new HashMap(8, 1.0F); // REDFLAG at 
the moment memory is more of an issue than CPU so we use a high load factor
-       private Vector _subMessages;
+       private final HashMap<String, Object> _payload = new HashMap<String, 
Object>(8, 1.0F); // REDFLAG at the moment memory is more of an issue than CPU 
so we use a high load factor
+       private List<Message> _subMessages;
        public final long localInstantiationTime;
        final int _receivedByteCount;

@@ -75,12 +75,11 @@
                    return null; // silently discard internal-only messages
                Message m = new Message(mspec, peer, recvByteCount);
                try {
-                   for (Iterator i = mspec.getOrderedFields().iterator(); 
i.hasNext();) {
-                       String name = (String) i.next();
-                       Class<?> type = (Class<?>) mspec.getFields().get(name);
+                   for (String name : mspec.getOrderedFields()) {
+                       Class<?> type = mspec.getFields().get(name);
                        if (type.equals(LinkedList.class)) { // Special 
handling for LinkedList to deal with element type
                            m.set(name, Serializer
-                                               
.readListFromDataInputStream((Class<?>) mspec.getLinkedListTypes().get(name),
+                                               
.readListFromDataInputStream(mspec.getLinkedListTypes().get(name),
                                                bb));
                        } else {
                            m.set(name, 
Serializer.readFromDataInputStream(type, bb));
@@ -221,8 +220,7 @@
                DataOutputStream dos = new DataOutputStream(baos);
                try {
                        dos.writeInt(_spec.getName().hashCode());
-                       for (Iterator i = _spec.getOrderedFields().iterator(); 
i.hasNext();) {
-                               String name = (String) i.next();
+                       for (String name : _spec.getOrderedFields()) {
                                
Serializer.writeToDataOutputStream(_payload.get(name), dos, destination);
                        }
                        dos.flush();
@@ -233,7 +231,7 @@

                if(_subMessages != null && includeSubMessages) {
                        for(int i=0;i<_subMessages.size();i++) {
-                               byte[] temp = 
((Message)_subMessages.get(i)).encodeToPacket(destination, false, true);
+                               byte[] temp = 
_subMessages.get(i).encodeToPacket(destination, false, true);
                                try {
                                        dos.writeShort(temp.length);
                                        dos.write(temp);
@@ -255,9 +253,8 @@
                StringBuilder ret = new StringBuilder(1000);
                String comma = "";
         ret.append(_spec.getName()).append(" {");
-               for (Iterator i = _spec.getFields().keySet().iterator(); 
i.hasNext();) {
+               for (String name : _spec.getFields().keySet()) {
                        ret.append(comma);
-                       String name = (String) i.next();
             ret.append(name).append('=').append(_payload.get(name));
                        comma = ", ";
                }
@@ -313,14 +310,14 @@
        }

        public void addSubMessage(Message subMessage) {
-               if(_subMessages == null) _subMessages = new Vector();
+               if(_subMessages == null) _subMessages = new 
ArrayList<Message>();
                _subMessages.add(subMessage);
        }

        public Message getSubMessage(MessageType t) {
                if(_subMessages == null) return null;
                for(int i=0;i<_subMessages.size();i++) {
-                       Message m = (Message) _subMessages.get(i);
+                       Message m = _subMessages.get(i);
                        if(m.getSpec() == t) return m;
                }
                return null;
@@ -329,7 +326,7 @@
        public Message grabSubMessage(MessageType t) {
                if(_subMessages == null) return null;
                for(int i=0;i<_subMessages.size();i++) {
-                       Message m = (Message) _subMessages.get(i);
+                       Message m = _subMessages.get(i);
                        if(m.getSpec() == t) {
                                _subMessages.remove(i);
                                return m;

Modified: trunk/freenet/src/freenet/io/comm/MessageCore.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/MessageCore.java  2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/io/comm/MessageCore.java  2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -18,6 +18,7 @@
  */
 package freenet.io.comm;

+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.ListIterator;
@@ -35,7 +36,7 @@
        private static boolean logMINOR; 
        private Dispatcher _dispatcher;
        /** _filters serves as lock for both */
-       private final LinkedList _filters = new LinkedList();
+       private final LinkedList<MessageFilter> _filters = new 
LinkedList<MessageFilter>();
        private final LinkedList<Message> _unclaimed = new 
LinkedList<Message>();
        private static final int MAX_UNMATCHED_FIFO_SIZE = 50000;
        private static final long MAX_UNCLAIMED_FIFO_ITEM_LIFETIME = 
10*60*1000;  // 10 minutes; maybe this should be per message type??
@@ -48,7 +49,7 @@
        }

        public MessageCore() {
-               _timedOutFilters = new Vector(32);
+               _timedOutFilters = new Vector<MessageFilter>(32);
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
        }

@@ -71,7 +72,7 @@

     /** Only used by removeTimedOutFilters() - if future code uses this 
elsewhere, we need to
      * reconsider its locking. */
-    private final Vector _timedOutFilters;
+    private final Vector<MessageFilter> _timedOutFilters;

     public void start(final Ticker ticker) {
        synchronized(this) {
@@ -103,8 +104,8 @@
                if(logMINOR)
                        Logger.minor(this, "Removing timed out filters");
                synchronized (_filters) {
-                       for (ListIterator i = _filters.listIterator(); 
i.hasNext();) {
-                               MessageFilter f = (MessageFilter) i.next();
+                       for (ListIterator<MessageFilter> i = 
_filters.listIterator(); i.hasNext();) {
+                               MessageFilter f = i.next();
                                if (f.timedOut(tStart)) {
                                        if(logMINOR)
                                                Logger.minor(this, "Removing 
"+f);
@@ -115,12 +116,11 @@
                                // be timed out because their client callbacks 
say they should be.
                                // Also simplifies the logic significantly, 
we've had some major bugs here.

-                               // See also the end of waitFor() for another 
wierd case.
+                               // See also the end of waitFor() for another 
weird case.
                        }
                }

-               for(int i=0;i<_timedOutFilters.size();i++) {
-                       MessageFilter f = (MessageFilter) 
_timedOutFilters.get(i);
+               for(MessageFilter f : _timedOutFilters) {
                        f.setMessage(null);
                        f.onTimedOut();
                }
@@ -154,8 +154,8 @@
                }
                MessageFilter match = null;
                synchronized (_filters) {
-                       for (ListIterator i = _filters.listIterator(); 
i.hasNext();) {
-                               MessageFilter f = (MessageFilter) i.next();
+                       for (ListIterator<MessageFilter> i = 
_filters.listIterator(); i.hasNext();) {
+                               MessageFilter f = i.next();
                                if (f.matched()) {
                                        Logger.error(this, "removed pre-matched 
message filter found in _filters: "+f);
                                        i.remove();
@@ -209,8 +209,8 @@
                     */
                        synchronized (_filters) {
                                if(logMINOR) Logger.minor(this, "Rechecking 
filters and adding message");
-                               for (ListIterator i = _filters.listIterator(); 
i.hasNext();) {
-                                       MessageFilter f = (MessageFilter) 
i.next();
+                               for (ListIterator<MessageFilter> i = 
_filters.listIterator(); i.hasNext();) {
+                                       MessageFilter f = i.next();
                                        if (f.match(m)) {
                                                matched = true;
                                                match = f;
@@ -221,7 +221,7 @@
                                }
                                if(!matched) {
                                    while (_unclaimed.size() > 
MAX_UNMATCHED_FIFO_SIZE) {
-                                       Message removed = 
(Message)_unclaimed.removeFirst();
+                                       Message removed = 
_unclaimed.removeFirst();
                                        long messageLifeTime = 
System.currentTimeMillis() - removed.localInstantiationTime;
                                        if ((removed.getSource()) instanceof 
PeerNode) {
                                            Logger.normal(this, "Dropping 
unclaimed from "+removed.getSource().getPeer()+", lived 
"+TimeUtil.formatTime(messageLifeTime, 2, true)+" (quantity)"+": "+removed);
@@ -249,22 +249,21 @@

        /** IncomingPacketFilter should call this when a node is disconnected. 
*/
        public void onDisconnect(PeerContext ctx) {
-               Vector droppedFilters = null; // rare operation, we can waste 
objects for better locking
+               ArrayList<MessageFilter> droppedFilters = null; // rare 
operation, we can waste objects for better locking
            synchronized(_filters) {
-                       ListIterator i = _filters.listIterator();
+                       ListIterator<MessageFilter> i = _filters.listIterator();
                        while (i.hasNext()) {
-                           MessageFilter f = (MessageFilter) i.next();
+                           MessageFilter f = i.next();
                            if(f.matchesDroppedConnection(ctx)) {
                                if(droppedFilters == null)
-                                       droppedFilters = new Vector();
+                                       droppedFilters = new 
ArrayList<MessageFilter>();
                                droppedFilters.add(f);
                                i.remove();
                            }
                        }
            }
            if(droppedFilters != null) {
-               for(int i=0;i<droppedFilters.size();i++) {
-                       MessageFilter mf = (MessageFilter) 
droppedFilters.get(i);
+               for(MessageFilter mf : droppedFilters) {
                        mf.onDroppedConnection(ctx);
                }
            }
@@ -272,22 +271,21 @@

        /** IncomingPacketFilter should call this when a node connects with a 
new boot ID */
        public void onRestart(PeerContext ctx) {
-               Vector droppedFilters = null; // rare operation, we can waste 
objects for better locking
+               ArrayList<MessageFilter> droppedFilters = null; // rare 
operation, we can waste objects for better locking
            synchronized(_filters) {
-                       ListIterator i = _filters.listIterator();
+                       ListIterator<MessageFilter> i = _filters.listIterator();
                        while (i.hasNext()) {
-                           MessageFilter f = (MessageFilter) i.next();
+                           MessageFilter f = i.next();
                            if(f.matchesRestartedConnection(ctx)) {
                                if(droppedFilters == null)
-                                       droppedFilters = new Vector();
+                                       droppedFilters = new 
ArrayList<MessageFilter>();
                                droppedFilters.add(f);
                                i.remove();
                            }
                        }
            }
            if(droppedFilters != null) {
-               for(int i=0;i<droppedFilters.size();i++) {
-                       MessageFilter mf = (MessageFilter) 
droppedFilters.get(i);
+               for(MessageFilter mf : droppedFilters) {
                        mf.onRestartedConnection(ctx);
                }
            }
@@ -321,8 +319,8 @@
                                //but we are holding the _filters lock!
                        }
                        if(logMINOR) Logger.minor(this, "Checking _unclaimed");
-                       for (ListIterator i = _unclaimed.listIterator(); 
i.hasNext();) {
-                               Message m = (Message) i.next();
+                       for (ListIterator<Message> i = 
_unclaimed.listIterator(); i.hasNext();) {
+                               Message m = i.next();
                                if (filter.match(m)) {
                                        i.remove();
                                        ret = m;
@@ -341,14 +339,14 @@
                        if (ret == null) {
                                if(logMINOR) Logger.minor(this, "Not in 
_unclaimed");
                            // Insert filter into filter list in order of 
timeout
-                               ListIterator i = _filters.listIterator();
+                               ListIterator<MessageFilter> i = 
_filters.listIterator();
                                while (true) {
                                        if (!i.hasNext()) {
                                                i.add(filter);
                                                if(logMINOR) Logger.minor(this, 
"Added at end");
                                                break;
                                        }
-                                       MessageFilter mf = (MessageFilter) 
i.next();
+                                       MessageFilter mf = i.next();
                                        if (mf.getTimeout() > 
filter.getTimeout()) {
                                                i.previous();
                                                i.add(filter);
@@ -395,8 +393,8 @@
                long messageLifeTime = 0;
                synchronized (_filters) {
                        if(logMINOR) Logger.minor(this, "Checking _unclaimed");
-                       for (ListIterator i = _unclaimed.listIterator(); 
i.hasNext();) {
-                               Message m = (Message) i.next();
+                       for (ListIterator<Message> i = 
_unclaimed.listIterator(); i.hasNext();) {
+                               Message m = i.next();
                                if (filter.match(m)) {
                                        i.remove();
                                        ret = m;
@@ -415,14 +413,14 @@
                        if (ret == null) {
                                if(logMINOR) Logger.minor(this, "Not in 
_unclaimed");
                            // Insert filter into filter list in order of 
timeout
-                               ListIterator i = _filters.listIterator();
+                               ListIterator<MessageFilter> i = 
_filters.listIterator();
                                while (true) {
                                        if (!i.hasNext()) {
                                                i.add(filter);
                                                if(logMINOR) Logger.minor(this, 
"Added at end");
                                                break;
                                        }
-                                       MessageFilter mf = (MessageFilter) 
i.next();
+                                       MessageFilter mf = i.next();
                                        if (mf.getTimeout() > 
filter.getTimeout()) {
                                                i.previous();
                                                i.add(filter);

Modified: trunk/freenet/src/freenet/io/comm/MessageFilter.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/MessageFilter.java        2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/io/comm/MessageFilter.java        2008-11-06 
13:53:57 UTC (rev 23351)
@@ -19,7 +19,9 @@

 package freenet.io.comm;

-import java.util.*;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;

 import freenet.support.Logger;

@@ -36,8 +38,8 @@
     private boolean _matched;
     private PeerContext _droppedConnection;
        private MessageType _type;
-    private HashMap _fields = new HashMap();
-    private List _fieldList = new LinkedList();
+    private HashMap<String, Object> _fields = new HashMap<String, Object>();
+    private List<String> _fieldList = new LinkedList<String>();
     private PeerContext _source;
     private long _timeout;
     /** If true, timeouts are relative to the start of waiting, if false, they 
are relative to
@@ -177,9 +179,7 @@
                        return false;
                }
                synchronized (_fields) {
-                       ListIterator it = _fieldList.listIterator();
-                       while (it.hasNext()) {
-                               String fieldName = (String) it.next();
+                       for (String fieldName : _fieldList) {
                                if (!m.isSet(fieldName)) {
                                        return false;
                                }

Modified: trunk/freenet/src/freenet/io/comm/MessageType.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/MessageType.java  2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/io/comm/MessageType.java  2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -30,12 +30,12 @@

     public static final String VERSION = "$Id: MessageType.java,v 1.6 
2005/08/25 17:28:19 amphibian Exp $";

-       private static HashMap _specs = new HashMap();
+       private static HashMap<Integer, MessageType> _specs = new 
HashMap<Integer, MessageType>();

        private final String _name;
-       private final LinkedList _orderedFields = new LinkedList();
-       private final HashMap _fields = new HashMap();
-       private final HashMap _linkedListTypes = new HashMap();
+       private final LinkedList<String> _orderedFields = new 
LinkedList<String>();
+       private final HashMap<String, Class<?>> _fields = new HashMap<String, 
Class<?>>();
+       private final HashMap<String, Class<?>> _linkedListTypes = new 
HashMap<String, Class<?>>();
        private final boolean internalOnly;
        private final short priority;

@@ -83,7 +83,7 @@
                if (fieldValue == null) {
                        return false;
                }
-               Class<?> defClass = (Class<?>) (_fields.get(fieldName));
+               Class<?> defClass = _fields.get(fieldName);
                Class<?> valueClass = fieldValue.getClass();
                if(defClass == valueClass) return true;
                if(defClass.isAssignableFrom(valueClass)) return true;
@@ -91,7 +91,7 @@
        }

        public Class<?> typeOf(String field) {
-               return (Class<?>) _fields.get(new Integer(field.hashCode()));
+               return _fields.get(field);
        }

        @Override
@@ -114,22 +114,22 @@
                        Logger.error(MessageType.class, "Unrecognised message 
type received (" + specID + ')');
                        return null;
                }
-               return (MessageType) _specs.get(specID);
+               return _specs.get(specID);
        }

        public String getName() {
                return _name;
        }

-       public Map getFields() {
+       public Map<String, Class<?>> getFields() {
                return _fields;
        }

-       public LinkedList getOrderedFields() {
+       public LinkedList<String> getOrderedFields() {
                return _orderedFields;
        }

-       public Map getLinkedListTypes() {
+       public Map<String, Class<?>> getLinkedListTypes() {
                return _linkedListTypes;
        }


Modified: trunk/freenet/src/freenet/io/comm/PeerContext.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/PeerContext.java  2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/io/comm/PeerContext.java  2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -55,7 +55,7 @@

        /** Get a WeakReference to this context. Hopefully there is only one of 
these for the whole object; they are quite
         * expensive. */
-       WeakReference getWeakRef();
+       WeakReference<? extends PeerContext> getWeakRef();

        /** Compact toString() */
        String shortToString();

Modified: trunk/freenet/src/freenet/io/comm/UdpSocketHandler.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/UdpSocketHandler.java     2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/io/comm/UdpSocketHandler.java     2008-11-06 
13:53:57 UTC (rev 23351)
@@ -272,6 +272,7 @@
     public static final int UDP_HEADERS_LENGTH = 28;

     public static final int MIN_MTU = 1100;
+    private volatile boolean disableMTUDetection = false;

     /**
      * @return The maximum packet size supported by this SocketManager, not 
including transport (UDP/IP) headers.
@@ -280,8 +281,11 @@
        final int minAdvertisedMTU = node.ipDetector.getMinimumDetectedMTU();

        // We don't want the MTU detection thingy to prevent us to send 
PacketTransmits!
-       if(minAdvertisedMTU < MIN_MTU){
-               Logger.error(this, "It shouldn't happen : we disabled the MTU 
detection algorithm because the advertised MTU is smallish !! 
("+node.ipDetector.getMinimumDetectedMTU()+')');
+       if(disableMTUDetection || minAdvertisedMTU < MIN_MTU){
+               if(!disableMTUDetection) {
+                       Logger.error(this, "It shouldn't happen : we disabled 
the MTU detection algorithm because the advertised MTU is smallish !! 
("+node.ipDetector.getMinimumDetectedMTU()+')');
+                       disableMTUDetection = true;
+               }
                return MAX_ALLOWED_MTU - UDP_HEADERS_LENGTH;
        } else
                return Math.min(MAX_ALLOWED_MTU, minAdvertisedMTU) - 
UDP_HEADERS_LENGTH;

Modified: trunk/freenet/src/freenet/io/xfer/BlockReceiver.java
===================================================================
--- trunk/freenet/src/freenet/io/xfer/BlockReceiver.java        2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/io/xfer/BlockReceiver.java        2008-11-06 
13:53:57 UTC (rev 23351)
@@ -26,11 +26,11 @@
 import freenet.io.comm.DMT;
 import freenet.io.comm.DisconnectedException;
 import freenet.io.comm.Message;
+import freenet.io.comm.MessageCore;
 import freenet.io.comm.MessageFilter;
 import freenet.io.comm.NotConnectedException;
 import freenet.io.comm.PeerContext;
 import freenet.io.comm.RetrievalException;
-import freenet.io.comm.MessageCore;
 import freenet.support.BitArray;
 import freenet.support.Buffer;
 import freenet.support.Logger;
@@ -56,7 +56,7 @@
        long _uid;
        MessageCore _usm;
        /** packet : Integer -> reportTime : Long * */
-       HashMap _recentlyReportedMissingPackets = new HashMap();
+       HashMap<Integer, Long> _recentlyReportedMissingPackets = new 
HashMap<Integer, Long>();
        ByteCounter _ctr;
        boolean sentAborted;
        private MessageFilter discardFilter;
@@ -113,19 +113,19 @@
                                // Remove it from rrmp if its in there
                                _recentlyReportedMissingPackets.remove(new 
Integer(packetNo));
                                // Check that we have what the sender thinks we 
have
-                               LinkedList missing = new LinkedList();
+                               LinkedList<Integer> missing = new 
LinkedList<Integer>();
                                for (int x = 0; x < sent.getSize(); x++) {
                                        if (sent.bitAt(x) && 
!_prb.isReceived(x)) {
                                                // Sender thinks we have a 
block which we don't, but have we already
                                                // re-requested it recently?
-                                               Long resendTime = (Long) 
_recentlyReportedMissingPackets.get(new Integer(x));
+                                               Long resendTime = 
_recentlyReportedMissingPackets.get(x);
                                                if ((resendTime == null) || 
(System.currentTimeMillis() > resendTime.longValue())) {
                                                        // Make a note of the 
earliest time we should resend this, based on the number of other
                                                        // packets we are 
already waiting for
                                                        long resendWait = 
System.currentTimeMillis()
                                                                        + 
(MAX_ROUND_TRIP_TIME + (_recentlyReportedMissingPackets.size() * 
MAX_SEND_INTERVAL));
-                                                       
_recentlyReportedMissingPackets.put(new Integer(x), (new Long(resendWait)));
-                                                       missing.add(new 
Integer(x));
+                                                       
_recentlyReportedMissingPackets.put(x, resendWait);
+                                                       missing.add(x);
                                                }
                                        }
                                }
@@ -147,10 +147,10 @@
                                        throw new 
RetrievalException(RetrievalException.SENDER_DIED,
                                                        "Sender unresponsive to 
resend requests");
                                }
-                               LinkedList missing = new LinkedList();
+                               LinkedList<Integer> missing = new 
LinkedList<Integer>();
                                for (int x = 0; x < _prb.getNumPackets(); x++) {
                                        if (!_prb.isReceived(x)) {
-                                               missing.add(new Integer(x));
+                                               missing.add(x);
                                        }
                                }
                                Message mn = 
DMT.createMissingPacketNotification(_uid, missing);

Modified: trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java
===================================================================
--- trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java     2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/io/xfer/BlockTransmitter.java     2008-11-06 
13:53:57 UTC (rev 23351)
@@ -18,7 +18,6 @@
  */
 package freenet.io.xfer;

-import java.util.Iterator;
 import java.util.LinkedList;

 import freenet.io.comm.ByteCounter;
@@ -54,7 +53,7 @@
        private boolean _sendComplete;
        final long _uid;
        final PartiallyReceivedBlock _prb;
-       private LinkedList _unsent;
+       private LinkedList<Integer> _unsent;
        private Runnable _senderThread;
        private BitArray _sentPackets;
        final PacketThrottle throttle;
@@ -91,7 +90,7 @@
                                                                
if(_sendComplete) return;
                                                                
_senderThread.wait(10*1000);
                                                        }
-                                                       packetNo = ((Integer) 
_unsent.removeFirst()).intValue();
+                                                       packetNo = 
_unsent.removeFirst();
                                                }
                                        } catch (InterruptedException e) {
                                                Logger.error(this, 
"_senderThread interrupted");
@@ -161,7 +160,7 @@

                                        public void packetReceived(int 
packetNo) {
                                                synchronized(_senderThread) {
-                                                       _unsent.addLast(new 
Integer(packetNo));
+                                                       
_unsent.addLast(packetNo);
                                                        timeAllSent = -1;
                                                        
_sentPackets.setBit(packetNo, false);
                                                        
_senderThread.notifyAll();
@@ -207,17 +206,16 @@
                                                continue;
                                        }
                                } else if 
(msg.getSpec().equals(DMT.missingPacketNotification)) {
-                                       LinkedList missing = (LinkedList) 
msg.getObject(DMT.MISSING);
-                                       for (Iterator i = missing.iterator(); 
i.hasNext();) {
-                                               Integer packetNo = (Integer) 
i.next();
-                                               if 
(_prb.isReceived(packetNo.intValue())) {
+                                       LinkedList<Integer> missing = 
(LinkedList<Integer>) msg.getObject(DMT.MISSING);
+                                       for (int packetNo :missing) {
+                                               if (_prb.isReceived(packetNo)) {
                                                        
synchronized(_senderThread) {
                                                                if 
(_unsent.contains(packetNo)) {
                                                                        
Logger.minor(this, "already to transmit packet #"+packetNo);
                                                                } else {
                                                                
_unsent.addFirst(packetNo);
                                                                timeAllSent=-1;
-                                                               
_sentPackets.setBit(packetNo.intValue(), false);
+                                                               
_sentPackets.setBit(packetNo, false);
                                                                
_senderThread.notifyAll();
                                                                }
                                                        }

Modified: trunk/freenet/src/freenet/io/xfer/PacketThrottle.java
===================================================================
--- trunk/freenet/src/freenet/io/xfer/PacketThrottle.java       2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/io/xfer/PacketThrottle.java       2008-11-06 
13:53:57 UTC (rev 23351)
@@ -24,9 +24,7 @@
 import freenet.io.comm.NotConnectedException;
 import freenet.io.comm.Peer;
 import freenet.io.comm.PeerContext;
-import freenet.node.PeerNode;
 import freenet.node.SyncSendWaitedTooLongException;
-import freenet.support.DoubleTokenBucket;
 import freenet.support.Logger;

 public class PacketThrottle {

Modified: trunk/freenet/src/freenet/io/xfer/PartiallyReceivedBlock.java
===================================================================
--- trunk/freenet/src/freenet/io/xfer/PartiallyReceivedBlock.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/io/xfer/PartiallyReceivedBlock.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -18,7 +18,6 @@
  */
 package freenet.io.xfer;

-import java.util.Iterator;
 import java.util.LinkedList;

 import freenet.support.Buffer;
@@ -38,7 +37,7 @@
        boolean _aborted;
        int _abortReason;
        String _abortDescription;
-       LinkedList _packetReceivedListeners = new LinkedList();
+       LinkedList<PacketReceivedListener> _packetReceivedListeners = new 
LinkedList<PacketReceivedListener>();

        public PartiallyReceivedBlock(int packets, int packetSize, byte[] data) 
{
                if (data.length != packets * packetSize) {
@@ -61,15 +60,15 @@
                _packetSize = packetSize;
        }

-       public synchronized LinkedList addListener(PacketReceivedListener 
listener) throws AbortedException {
+       public synchronized LinkedList<Integer> 
addListener(PacketReceivedListener listener) throws AbortedException {
                if (_aborted) {
                        throw new AbortedException("Adding listener to aborted 
PRB");
                }
                _packetReceivedListeners.add(listener);
-               LinkedList ret = new LinkedList();
+               LinkedList<Integer> ret = new LinkedList<Integer>();
                for (int x = 0; x < _packets; x++) {
                        if (_received[x]) {
-                               ret.addLast(new Integer(x));
+                               ret.addLast(x);
                        }
                }
                return ret;
@@ -115,7 +114,7 @@
                        _received[position] = true;

                        // FIXME keep it as as an array
-                       prls = (PacketReceivedListener[]) 
_packetReceivedListeners.toArray(new 
PacketReceivedListener[_packetReceivedListeners.size()]);
+                       prls = _packetReceivedListeners.toArray(new 
PacketReceivedListener[_packetReceivedListeners.size()]);
                }


@@ -160,8 +159,7 @@
                _aborted = true;
                _abortReason = reason;
                _abortDescription = description;
-               for (Iterator i = _packetReceivedListeners.iterator(); 
i.hasNext();) {
-                       PacketReceivedListener prl = (PacketReceivedListener) 
i.next();
+               for (PacketReceivedListener prl : _packetReceivedListeners) {
                        prl.receiveAborted(reason, description);
                }
        }

Modified: trunk/freenet/src/freenet/io/xfer/WaitedTooLongException.java
===================================================================
--- trunk/freenet/src/freenet/io/xfer/WaitedTooLongException.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/io/xfer/WaitedTooLongException.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -7,6 +7,7 @@
  * Thrown when we wait too long to send a throttled packet.
  * @author toad
  */
+ at SuppressWarnings("serial")
 public class WaitedTooLongException extends Exception {

 }

Modified: trunk/freenet/src/freenet/keys/FreenetURI.java
===================================================================
--- trunk/freenet/src/freenet/keys/FreenetURI.java      2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/keys/FreenetURI.java      2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -539,6 +539,7 @@
                return toString(false, false);
        }

+       // FIXME: remove the typo in the function name.
        public String toACIIString() {
                return toString(true, true);
        }

Modified: trunk/freenet/src/freenet/keys/Key.java
===================================================================
--- trunk/freenet/src/freenet/keys/Key.java     2008-11-06 13:50:42 UTC (rev 
23350)
+++ trunk/freenet/src/freenet/keys/Key.java     2008-11-06 13:53:57 UTC (rev 
23351)
@@ -19,7 +19,7 @@
 import freenet.support.api.Bucket;
 import freenet.support.api.BucketFactory;
 import freenet.support.compress.CompressionOutputSizeException;
-import freenet.support.compress.Compressor;
+import freenet.support.compress.Compressor.COMPRESSOR_TYPE;
 import freenet.support.io.ArrayBucket;
 import freenet.support.io.ArrayBucketFactory;
 import freenet.support.io.BucketTools;
@@ -141,7 +141,7 @@
                        (output[3] & 0xff);
             if(len > maxLength)
                 throw new TooBigException("Invalid precompressed size: "+len + 
" maxlength="+maxLength);
-            Compressor decompressor = 
Compressor.getCompressionAlgorithmByMetadataID(compressionAlgorithm);
+            COMPRESSOR_TYPE decompressor = 
COMPRESSOR_TYPE.getCompressorByMetadataID(compressionAlgorithm);
             Bucket inputBucket = new SimpleReadOnlyArrayBucket(output, 
shortLength?2:4, outputLength-(shortLength?2:4));
             try {
                                return decompressor.decompress(inputBucket, bf, 
maxLength, -1, null);
@@ -184,9 +184,7 @@
                } else {
                        if (sourceData.size() > maxCompressedDataLength) {
                                        // Determine the best algorithm
-                                       for (int i = 0; i < 
Compressor.countCompressAlgorithms(); i++) {
-                                               Compressor comp = Compressor
-                                                               
.getCompressionAlgorithmByDifficulty(i);
+                                       for (COMPRESSOR_TYPE comp : 
COMPRESSOR_TYPE.values()) {
                                                ArrayBucket compressedData;
                                                try {
                                                        compressedData = 
(ArrayBucket) comp.compress(
@@ -197,8 +195,7 @@
                                                        continue;
                                                }
                                                if (compressedData.size() <= 
maxCompressedDataLength) {
-                                                       compressionAlgorithm = 
comp
-                                                                       
.codecNumberForMetadata();
+                                                       compressionAlgorithm = 
comp.metadataID;
                                                        sourceLength = 
sourceData.size();
                                                        try {
                                                                cbuf = 
BucketTools.toByteArray(compressedData);

Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.de.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.de.properties   2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.de.properties   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -435,7 +435,7 @@
 FirstTimeWizardToadlet.enableOpennet=Es ist auch sp?ter, wenn Sie genug 
Freunde hinzugef?gt haben, noch m?glich die Verbindung zu Fremden 
auszuschalten. Sie werden dann jedoch in der Zwischenzeit bereits ein paar 
Informationen an Fremde preisgegeben haben. Freenet ist immer noch 
experimentell und wir geben keine Garantie f?r die Sicherheit.
 FirstTimeWizardToadlet.fivePercentDisk=(= 5% des freien Speicherplatzes)
 
FirstTimeWizardToadlet.friendsSecurityPageTitle=Freenet-Einrichtungs-Assistent! 
- Freenet Sicherheitseinstellungen
-FirstTimeWizardToadlet.highNetworkThreatLevelCheckbox=Ich kenne mindestens 
eine Person, die Freenet benutzt (besser 3, 5-10 f?r ene ordentliche 
Geschwindigkeit). Ich werde sie auf der Freundesseite hinzuf?gen. Ich verstehe, 
dass Freenet nur funktionieren wird, wenn mindestens einer meiner Freunde 
online ist.
+FirstTimeWizardToadlet.highNetworkThreatLevelCheckbox=Ich kenne mindestens 
eine Person, die Freenet benutzt (besser 3, 5-10 f?r eine ordentliche 
Geschwindigkeit). Ich werde sie auf der Freundesseite hinzuf?gen. Ich verstehe, 
dass Freenet nur funktionieren wird, wenn mindestens einer meiner Freunde 
online ist.
 FirstTimeWizardToadlet.highNetworkThreatLevelWarning=${bold}WARNUNG${/bold}: 
Sie sind dabei, das Netzwerk Sicherheitslevel auf hoch  zu setzen. Dies 
bedeutet, dass sich ihr Knoten nicht verbinden kann, wenn sie nicht 
${bold}einige Verbindungen zu Freunden hinzuf?gen${/bold}. Diese Freunde 
sollten Menschen sein, die sie schon kennen und denen sie zumindest etwas 
vertrauen. Wenn sie niemanden kennen, der bereits Freenet benutzt, benutzen sie 
bitte das Netzwerk Sicherheitslevel NORMAL, so dass Freenet automatisch 
Verbindungen aufbaut. Das Hinzuf?gen von Fremden zu ihren Freunden wird ihre 
Sicherheit nicht erh?hen und wird der Geschwindigkeit schaden. Beachten sie 
auch, dass das Schutzlevel HOCH langsamer ist, besonders wenn sie wenige 
Freunde haben (sie ben?tigen mindestens 5-10 Freunde f?r eine ordentliche 
Geschwindigkeit).
 FirstTimeWizardToadlet.homepageTitle=Freenet-Einrichtungs-Assistent!
 FirstTimeWizardToadlet.iDoTrust=Trauen Sie Leuten die mit ${interface} (${ip}) 
verbunden sind?

Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties   2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -700,6 +700,8 @@
 Node.opennetEnabledLong=Enable insecure mode (aka opennet)? If this is 
enabled, the node will automatically exchange node references with other 
untrusted nodes (Strangers as opposed to Friends). But this means that the fact 
that you are running a node is no longer private, and many attacks are much 
easier. If you know enough people running Freenet, you should stick to trusted 
(Friends) connections to them, and turn this off.
 Node.outBWLimit=Output bandwidth limit (bytes per second)
 Node.outBWLimitLong=Hard output bandwidth limit (bytes/sec); the node should 
almost never exceed this
+Node.paddDataPackets=Padd data packets sent by the node with random-length 
content? (READ WARNING!)
+Node.paddDataPacketsLong=Padd data packets sent by the node with random-length 
content? For security, on a single node, this is bad; if a large part of the 
network starts doing it, we become very vulnerable to a passive attacker. 
However, it should improve performance, particularly the payload percentage. 
You have been warned!
 Node.passOpennetPeersThroughDarknet=Relay opennet noderefs through darknet 
peers?
 Node.passOpennetPeersThroughDarknetLong=If true, opennet noderefs (NEVER our 
own darknet noderef) will be relayed through our darknet peers. So a node (this 
node, or its peers) can get opennet peers from its darknet peers. This is 
useful because it allows us to bootstrap new opennet peers after having lost 
our peers due to downtime, for example. However, it may make traffic analysis 
slightly easier, so turn it off if you are paranoid.
 Node.port=FNP port number (UDP)
@@ -713,6 +715,8 @@
 Node.storeMaxMemTooHigh=Giving more than 80% of your ram to BDB is probably 
not what you want to do!
 Node.storePreallocate=Preallocate space for datastore
 Node.storePreallocateLong=Preallocate space for datastore
+Node.storeSaltHashResizeOnStart=Resize store on node start (salt-hash only)
+Node.storeSaltHashResizeOnStartLong=Resize store on node start (salt-hash 
only). If this is true, the node will complete resizing the datastore during 
startup. This will complete much faster than doing it "on the fly", but on the 
other hand the node will not be available for some time while it completes the 
resize.
 Node.storeSize=Store size in bytes
 Node.storeSizeLong=Store size in bytes
 Node.storeType=Store type (LEAVE THIS ALONE)
@@ -1127,6 +1131,8 @@
 SimpleToadletServer.enableInlinePrefetchLong=This may help if your browser 
only uses a small number of connections to talk to the node. On the other hand 
it may not.
 SimpleToadletServer.enablePersistentConnections=Enable persistent HTTP 
connections? (Read detailed description)
 SimpleToadletServer.enablePersistentConnectionsLong=Don't enable this unless 
your browser is configured to use lots of connections even if they are 
persistent.
+SimpleToadletServer.hasCompletedWizard=Have you completed the wizard yet?
+SimpleToadletServer.hasCompletedWizardLong=Have you completed the wizard yet? 
If not, fproxy will redirect all your requests to it.
 SimpleToadletServer.illegalCSSName=CSS name must not contain slashes or colons!
 SimpleToadletServer.panicButton=Show the panic button?
 SimpleToadletServer.panicButtonLong=Shows a 'panic button' on the queue page 
that will remove all requests with no confirmation.

Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.fi.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.fi.properties   2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.fi.properties   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -295,8 +295,28 @@
 GenericReadFilterCallback.malformedRelativeURL=Ep?muodostunut osoite 
(suhteellinen): ${error}
 GenericReadFilterCallback.protocolNotEscaped=Tuntematon protokolla: ${protocol}
 HTMLFilter.deletedUnknownStyle=tuntematon tyyli poistettu
+IPUndetectedUserAlert.detecting=Freenet yritt?? parhaillaan tunnistaa julkisen 
IP-osoitteesi. Jos t?m? ottaa enemm?n kuin muutaman minuutin, jotain on 
v??rin...
+IPUndetectedUserAlert.detectingShort=Freenet yritt?? parhaillaan tunnistaa 
julkisen IP-osoitteesi.
+IPUndetectedUserAlert.detectingWithConfigLink=Freenet yritt?? parhaillaan 
tunnistaa julkisen IP-osoitteesi. Jos t?m? ottaa enemm?n kuin muutaman 
minuutin, jotain on v??rin, jolloin voit k?ytt?? ty?kalua ${link}IP-osoitteen 
korvaus${link} auttaaksesi IP-osoitteen selvityst?.
+IPUndetectedUserAlert.suggestForwardPort=My?s UDP-portin{port1} avaaminen 
reitittimest?si tekisi yhdist?misen solmuusi helpoksi.
+IPUndetectedUserAlert.suggestForwardTwoPorts=My?s UDP-porttiesi ${port1} ja 
${port2] avaaminen reitittimest?si tekisi yhdist?misen solmuusi helpoksi.
+IPUndetectedUserAlert.unknownAddress=Freenet ei kyennyt tunnistamaan julkista 
IP-osoitettasi. Voit silti vaihtaa referenssej? muiden kanssa, mutta se ei 
toimi kuin k?ytt?jien, jotka eiv?t ole palomuurin tai NAT:n takana, kanssa. 
Heti kun olet yhdist?nyt edes yhteen k?ytt?j??n t?ll? tavalla, Freenet kykenee 
tunnistamaan julkisen IP-osoitteesi. Voit antaa solmulle k?sinm??ritetyn 
vihjeen ty?kalulla ${link}}V?liaikainen IP-osoitteen vihje${/link}.
+IPUndetectedUserAlert.unknownAddressShort=Freenet ei kyennyt tunnistamaan 
IP-osoitettasi. Sinulla voi olla ongelmia yhdistett?ess?.
+IPUndetectedUserAlert.unknownAddressTitle=Tuntematon julkinen osoite
+IPUndetectedUserAlert.unknownAddressWithConfigLink=Freenet ei kyennyt 
tunnistamaan julkista IP-osoitettasi (tai NAT-laitteesi/palomuurisi 
IP-osoitetta). Voit silti vaihtaa referenssej? muiden kanssa, mutta t?m? toimii 
vain, jos toinen k?ytt?j? ei ole palomuurin tai NAT:n takana. Heti kun olet 
yhdist?nyt yhteen toiseen k?ytt?j??n t?ll? tavalla, Freenet kykenee 
m??rittelem??n julkisen IP-osoitteesi. Voit my?s lis?t? julkisen IP-osoitteesi 
k?sin k?ytt?en ty?kalua ${link}IP-osoitteen korvaus${link}.
 JPEGFilter.tooShort=Tiedosto on liian lyhyt ollakseen JPEG.
 JPEGFilter.tooShortTitle=Liian lyhyt
+KnownUnsafeContentTypeException.dangerousInlines=T?m?ntyyppinen sis?lt?ss? voi 
olla sis?llytettyj? kuvia tai videoita, ja voi niiden avulla ladata sis?lt?? 
avoimesta verkosta, paljastaen n?in IP-osoitteesi.
+KnownUnsafeContentTypeException.dangerousInlinesLabel=Vaarallista 
sis?llytetty? sis?lt??:
+KnownUnsafeContentTypeException.dangerousLinks=T?m?ntyyppisess? sis?ll?ss? voi 
olla linkkej? avoimeen verkkoon. Jos klikkaat niit? (ja ne voivat olla 
naamioituneina), se voi paljastaa IP-osoitteesi.
+KnownUnsafeContentTypeException.dangerousLinksLabel=Vaarallisia linkkej?:
+KnownUnsafeContentTypeException.dangerousMetadata=T?m?ntyyppinen sis?lt? voi 
sis?lt?? metadataa ? joka voidaan n?ytt?? jonkin selaimen toimesta tai muun 
ohjelmiston ? jossa voi olla vaarallisia linkkej? tai sis?llytetty? sis?lt??.
+KnownUnsafeContentTypeException.dangerousMetadataLabel=Vaarallista metatietoa:
+KnownUnsafeContentTypeException.dangerousScripts=T?m?n tyyppinen sis?lt? voi 
sis?lt?? vaarallisia skriptej?, jotka suoritettaesssa voivat vaarantaa 
yksityisyytesi yhdist?m?ll? avoimeen verkkoon tai muutoin murtaa yksityisyytesi.
+KnownUnsafeContentTypeException.dangerousScriptsLabel=Vaarallista skriptausta:
+KnownUnsafeContentTypeException.knownUnsafe=T?m? on mahdollisesti vaarallinen 
MIME-tyyppi. Jos solmu p??st?? sen l?pi, selaimesi saattaa tehd? pahoja 
asioita, jotka vaarantavat yksityisyytesi, ja sivustosi saattaa n?ky? 
yhteydesss? t?h?n sivuun. Erityisesti:
+KnownUnsafeContentTypeException.noFilter=Koska t?lle datalle ei ole 
sis??nrakennettua filtteri?, sinun kannattaa olla erityisen varovainen!
+KnownUnsafeContentTypeException.title=Tunnettu vaarallinen tyyppi: ${type}
 LocalFileInsertToadlet.fileHeader=Tiedosto
 LocalFileInsertToadlet.insert=Lis??
 LocalFileInsertToadlet.sizeHeader=Koko
@@ -334,12 +354,34 @@
 Node.outBWLimitLong=Kova rajoitus l?hetysnopeudelle (tavua / sekunti). solmun 
ei pit?isi k?yt?nn?ss? koskaan ylitt?? t?t?.
 Node.storeSize=Varaston koko tavuissa
 Node.storeSizeLong=Varaston koko tavuissa
+NodeClientCore.downloadDirLong=Ladattavien tiedostojen oletustallennuspaikka
+NodeClientCore.encryptPersistentTempBuckets=Kryptaa sinnikk?iden 
v?liaikaistiedostot? ?L? KOSKE T?H?N!
+NodeClientCore.encryptTempBuckets=Kryptaa v?liaikaiset s?ili?t? ?L? KOSKE 
T?H?N!
+NodeClientCore.encryptTempBucketsLong=Kryptaa v?liaikaiset s?ili?t? Joissakin 
tapauksissa (jos k?yt?t kiintolevy- ja swap-kryptausta) ei kenties ole mit??n 
j?rke? kryptata v?liaikaisia s?ili?it?. ?L? KOSKE T?H?N JOS ET TIED?, MIT? OLET 
TKEM?SS?!
+NodeClientCore.fileForClientStats=Tiedosto, johon tallennetaan asiakasohjelman 
statistiikat
+NodeClientCore.maxArchiveSize=Maksimikoko arkistoille.
+NodeClientCore.maxArchiveSizeLong=Suurin sallittu koko mille tahansa arkistolle
+NodeClientCore.maxRAMBucketSize=Suurin sallittu koko k?ytt?muistis?ili?lle.
+NodeClientCore.maxUSKFetchersMustBeGreaterThanZero=T?ytyy olla suurempi kuin 
nolla
+NodeClientCore.persistentTempDir=Sinnikk?iden v?liaikaistiedostojen hakemisto
+NodeClientCore.persistentTempDirLong=Sinnikk?iden v?liaikaistiedostojen 
hakemiston nimi
+NodeClientCore.ramBucketPoolSize=V?liaikaistiedostoille varattu k?ytt?muisti
+NodeClientCore.ramBucketPoolSizeLong=V?liaikaisille s?ili?ille varattu RAM. 
Enemm?n muistia tarkoittaa pienemp?? levynk?ytt??.
+NodeClientCore.startingUpShort=Freenet on k?ynnistym?ss?, jotkin toiminnot 
eiv?t v?ltt?m?tt? toimi, ja solmu voi toimia hitaasti.
+NodeClientCore.startingUpTitle=Freenet on k?ynnistym?ss?
+NodeClientCore.tempDir=V?liaikaistiedostojen hakemisto
+NodeClientCore.tempDirLong=V?liaikaistiedostojen hakemiston nimi
+NodeClientCore.uploadAllowedDirs=Hakemistot, joista l?hett?minen on sallittu
 NodeIPDectector.inclLocalAddress=Sis?llyt? paikalliset osoitteet 
solmuviitteeseen
 NodeIPDectector.inclLocalAddressLong=M??ritt??, sis?llytet??nk? paikalliset 
osoitteet(LAN ja localhost) solmun viitteisiin. T?m? ei ole hy?dyllist?, 
elleiv?t molemmat puolet aseta kohtaa allowLocalAddresses=true toistensa 
referensseihin.
 NodeIPDectector.ipOverride=IP-osoitteen korvaus
 NodeIPDectector.ipOverrideLong=IP-osoitteen korvaus (yleens? turha) - aseta 
t?m?, jos sinulla on *staattinen* IP-osoite tai domain-nimi (esim. dyndns:n 
kautta) ja olet palomuurin takana.
 NodeIPDectector.tempAddressHint=V?liaikainen IP-osoitteen vihje
 NodeIPDectector.tempAddressHintLong=V?liaikainen vihje omasta IP:st?; 
poistetaan k?yt?n j?lkeen
+NodeIPDetector.maybeSymmetric=N?ytt?isi, ett? solmusi on symmetrisen NATin 
takana. Sinulla voi olla yhteysongelmia: jos olet symmetrisen NATin takana, 
luultavimmin kykenet yhdist?m??n vain vertaisiin, jotka ovat avoimena verkolle.
+NodeIPDetector.maybeSymmetricShort=Yhteysongelmia: saatat olla symmetrisen 
NATin takana.
+NodeIPDetector.maybeSymmetricTitle=Yhteysongelmia
+NodeIPDetector.unknownHostErrorInIPOverride=Tuntematon is?nt?: ${error}
 NodeUpdateManager.installNewVersions=Asenna automaattisesti uudet versiot.
 NodeUpdateManager.installNewVersionsLong=M??ritt??, asentaako solmu 
p?ivitykset automaattisesti, kysym?tt? sinulta.
 NotEnoughNiceLevelsUserAlert.content=Solmusi on huomannut, ett? se py?rii 
tavallista korkeammalla ?nice?-arvolla. Se ei voi suoriutua kunnolla, ellei 
sill? ole tarpeeksi tasoja j?ljell?. (Katso PRIORITY run.sh-tiedostosta ja 
alenna t?t? arvoa)! T?ll? hetkell? solmulla on ${available} tasoa j?ljell? kun 
se tarvitsisi ${required} tasoa.
@@ -490,24 +532,63 @@
 QueueToadlet.warningUnsafeContent=Mahdollisesti turvatonta sis?lt??
 QueueToadlet.wipD=Kesken: lataukset (${size})
 QueueToadlet.wipU=Kesken: l?hetykset (${size})
+RevocationKeyFoundUserAlert.text=Solmusi on l?yt?nyt automaattip?ivitt?j?n 
kumoamisavaimen verkosta. Se tarkoittaa, ett? todenn?k?isimmin j?rjestelm?mme 
on VAARANTUNUT! Siisp?, se on otettu pois k?yt?st? est??ksesti solmuasi 
asentamasta ?pahoja asioita?. Suosittelemme vahvasti tarkistamaan projektin 
kotisivu p?ivitysten varalta. Kannattaa varmistaa, ettei my?s kotisivu ole 
huijausta. Kumoamisviesti on seuraava: ${message}.
 RevocationKeyFoundUserAlert.title=Projektin yksityisen avaimen turvallisuus on 
heikentynyt!
+SecurityLevels.fewConnectedFriendsCheckbox=Olen varma, tulen lis??m??n lis?? 
yst?vi? ja/tai hyv?ksyn huonomman suorituskyvyn ja faktan, ettei Freenet 
kenties onnistu yhdist?m??n silloin kun yst?v?ni eiv?t ole paikalla.
 SecurityLevels.fewConnectedFriendsWarning=Sinulla on vain ${connected} 
yhteyden p??ss? olevaa solmua, ja olet lis?nnyt yhteens? ${added} yst?v??. Jos 
asetat verkon tietoturvatason korkeaksi tai maksimiksi, Freenet yhdist?? vain 
yst?viisi, joten solmusi suorituskyky voi n?ht?v?sti laskea, ja jos kaikki 
yst?v?si ovat poissa, olet kokonaan ulkona Freenetist?. Huomaa, ett? yst?viesi 
t?ytyy olla v?ke?, jonka tunnet, ja edes jossain m??rin luotat saadaksesi 
mink??nlaista tietoturvahy?ty?. Tarvitse my?s v?hint??n 5 yhdistetty? yst?v?? 
saadaksesi kelvollisen suorituskyvyn solmullesi. Oletko varma?
+SecurityLevels.friendsThreatLevel=Kuinka huolissasi olet yst?viesi yrityksist? 
seurata aktiviteettej?si joko tarkoituksellisesti tai heid?n oman huonon 
tietoturvansa takia? T?m? on vakiotaso ja useimmiten voidaan syrj?ytt?? 
tietyilt? yst?vilt?. Jos asetit verkon tietoturvatason korkeaksi yl?puolella, 
yst?vien tietoturvataso m??ritt?? suorituskyvyn, yst?vien lukum??r?n kanssa.
 SecurityLevels.friendsThreatLevelConfirmTitle=VAROITUS: asetetaan yst?vien 
tietoturvatasoksi ${mode}
 SecurityLevels.friendsThreatLevelShort=Suojaa, jos yst?v?si hy?kk??v?t 
anonyymiteettisi kimppuun
 SecurityLevels.highFriendsThreatLevelCheckbox=Olen varma, ett? tarvitsen 
korkean tason suojaa vaarallisia ja petollisia yst?v?solmuja vastaan.
 SecurityLevels.highFriendsThreatLevelWarning=Olet vaihtamassa yst?v?uhkatason 
korkeaksi. T?m? laskee Freenetin suorituskyky?, ja sen ei pit?isi olla 
useinkaan tarpeellista. Jos syy t?lle asetukselle on, ettet tunne yst?vi?si, 
sinun kannattaa harkita yhteyden katkaisua heihin ja verkkotason alentamista 
normaaliksi. Jos taas odotat hy?kk??j?n vaarantavan yst?viesi tietokoneet tai 
aktiivisesti yritt?v?n muuttaa heid?t sinua vastaan, t?m? voi olla j?rkev? 
varotoimi.
+SecurityLevels.maxSecurityYouNeedFriends=${bold}Sinun t?ytyy tuntea v?hint??n 
yksi Freenetti? k?ytt?v? henkil?${/bold}, mielell??n 3 ja 5-10 hyv??n 
suorituskykyyn. Sinun t?ytyy lis?t? ne Yst?v?t-sivulla. N?iden pit?isi olla 
henkil?it?, joihin luotat edes marginaalisesti.
 SecurityLevels.maximumNetworkThreatLevelCheckbox=Kyll?! Haluan varmasti ottaa 
k?ytt??n maksimiturvallisuuden, ja ymm?rr?n, ett? Freenet on viel? 
kehitysvaiheessa ja viel?kin voi olla mahdollista j?ljitt?? minut, ja t?m? 
asetus voi alentaa Freenetin suorituskyky? eritt?in paljon!
 SecurityLevels.maximumNetworkThreatLevelWarning=${bold}VAROITUS:${/bold} Olet 
asettamassa verkon tietoturvatasoksi maksimia! T?m? hidastaa 
${bold}huomattavasti${/bold} Freenetti?! ?l? aseta t?t? tasoa, ellet oikeasti 
tarvitse t?t? tietoturvaa.
+SecurityLevels.networkThreatLevel=Kuinka paljon tietoturvaa tarvitset 
internet-palveluntarjoajia, yrityksi?, hallituksia, tylsistyneit? lapsia jne. 
vastaan heid?n yrityksiss??n tarkkailla Freenet-k?ytt??si?
 SecurityLevels.networkThreatLevelConfirmTitle=VAROITUS: asetetaan verkon 
tietoturvatasoksi ${mode}
 SecurityLevels.networkThreatLevelLowCheckbox=Olen varma, ett? haluan enemm?n 
nopeutta, enk? v?lit? pystyyk? kukaan kertomaan, mit? teen Freenetiss?.
 SecurityLevels.networkThreatLevelLowWarning=Olet aikeissa laskea solmusi 
verkon tietoturvataso matalaksi. T?m? tarkoittaa, ett? muukalaiset voivat 
helposti hy?k?t? anonyymiteettisi kimppuun Internetin yli. Oletko varma?
 SecurityLevels.networkThreatLevelShort=Suojaa muukalaisen hy?kk?yksi? vastaan 
heid?n hy?k?tess? Internetin yli.
+SecurityLevels.noConnectedFriendsCheckbox=Olen varma, tulen lis??m??n lis?? 
yst?vi? tai/ja hyv?ksyn, ett? Freenet pystyy yhdist?m??n muihin solmuihin vain 
yst?vieni ollessa paikalla.
 SecurityLevels.noConnectedFriendsWarning=Et ole yhdistettyn? yhteenk??n 
yst?v??n, vaikka olet lis?nnyt ${added} yst?v??. Jos olet asettanut verkon 
tietoturvatason korkeaksi tai maksimiksi, kykenet yhdist?m??n Freenettiin vain, 
mik?li yst?v?si ovat paikalla, mit? he eiv?t ole t?ll? hetkell?. Sinun 
kannattaisi lis?t? uusia yst?vi?, k?ytt?? Freenetti? vain kun yst?v?si ovat 
yhdistett?viss?, tai olla k?ytt?m?tt? korkeaa tietoturvatasoa. Huomaa, ett? 
saadaksesi tietoturvaa yst?vist?si, yst?viesi t?ytyy olla v?ke?, johon voit 
edes marginaalisesti luottaa, ja hyv?? suorituskyky? varten tarvitset v?hint??n 
viisi yst?v?? samanaikaisesti. Oletko varma?
 SecurityLevels.noFriendsCheckbox=Olen varma, kytke korkea verkon 
tietoturvataso p??lle, lis??n joitakin yst?vi? mahdollisimman pian.
+SecurityLevels.noFriendsWarning=Et ole lis?nnyt yht??n yst?v??. Jos asetat 
verkon tietoturvatason korkeaksi tai maksimiksi, et kykene yhdist?m??n 
Freenettiin ennen kuin sinulla on v?hint??n yksi yhdistetty yst?v?! Huomaa, 
ett? saadaksesi tietoturvalis?? yst?vist?, yst?vien pit?isi olla tuntemiasi 
henkil?it? ja niit? pit?isi olla v?hint??n 5-10 kerralla yhdistettyn?. Oletko 
varma?
+SecurityLevels.physicalThreatLevel=Kuinka varuillaan olet tietokoneesi 
joutumisesta fyysisesti kaapatuksi ja tutkituksi?
 SecurityLevels.physicalThreatLevelShort=Suojaa, mik?li tietokoneesi kaapataan 
tai varastetaan
 SecurityLevels.title=Tietoturvatasot
+SecurityLevels.tooltip=Aseta solmun tietoturva-aste
+SecurityLevels.userAlertExtro=Voit muuttaa n?it? asetuksia 
${link}asetussivulla${/link}.
 SecurityLevels.userAlertFriendsThreatLevel=Suojaa, jos yst?v?si hy?kk??v?t 
anonyymiytt?si vastaan: ${level}
 SecurityLevels.userAlertNetworkThreatLevel=Suojaa muukalaisten hy?kk?yksilt? 
Internetin yli: ${level}
+SecurityLevels.userAlertPhysicalThreatLevel=Suojaa, jos tietokoneesi kaapataan 
tai varastetaan: ${level}
+SecurityLevels.userAlertShortText=Tietoturvatasot: Verkko: ${network}, 
Yst?v?t: ${friends}, Fyysinen: ${physical}
+SecurityLevels.friendsThreatLevel.choice.HIGH=Haluaisin Freenetin ottavan 
erityisi? varotoimenpiteit? v?ltt??kseen hy?kk?yksi? yst?vilt?.
+SecurityLevels.friendsThreatLevel.choice.LOW=En ole huolissani hy?kk?yksist? 
yst?vilt?. Luotan yst?viini ja heid?n tietokoneittensa tietoturvaominaisuuksiin.
+SecurityLevels.friendsThreatLevel.choice.NORMAL=En ole liian huolissani 
hy?kk?yksist? yst?vien suunnalta, mutta haluaisin Freenetin ottavan j?rkevi? 
varotoimenpiteit?.
+SecurityLevels.friendsThreatLevel.desc.HIGH=Freenet v?ltt?? jakamasta tietoa 
yst?villeen ja on n?in jonkin verran hitaampi kuin normaalissa tilassa.
+SecurityLevels.friendsThreatLevel.desc.LOW=Freenet jakaa paljon tietoa 
yst?viesi solmujen kanssa maksimoidakseen suorituskyvyn.
+SecurityLevels.friendsThreatLevel.desc.NORMAL=Freenet tulee jakamaan vain 
m??r?tyn m??r?n tietoa yst?villeen ja on hitaampi kuin matalalla 
tietoturvatasolla.
+SecurityLevels.friendsThreatLevel.name.HIGH=KORKEA
+SecurityLevels.friendsThreatLevel.name.LOW=MATALA
+SecurityLevels.friendsThreatLevel.name.NORMAL=NORMAALI
+SecurityLevels.networkThreatLevel.choice.HIGH=Haluaisin vaikeuttaa muiden 
yhteyksieni seurantaa reilusti, tai olen huolissani internet-palveluntarjoajan 
yrityksist? est?? Freenetti?.
+SecurityLevels.networkThreatLevel.choice.LOW=En v?lit? seurantayrityksist? ja 
haluan mahdollisimman suuren suorituskyvyn.
+SecurityLevels.networkThreatLevel.choice.MAXIMUM=Aion selata tietoa, joka 
voisi saada minut pid?tetyksi, vankilaan tai pahempaa. Ymm?rr?n, ett? Freenet 
on kokeellinen eik? voi taata tietoturvaa tiettyj? tunnettuja hy?kk?yksi? 
vastaan, mutta hyv?ksyn riskit verrattuna vaihtoehtoihin.
+SecurityLevels.networkThreatLevel.choice.NORMAL=El?n suhteellisen vapaassa 
maassa, mutta haluaisin vaikeuttaa muiden seurantaa koskien minun yhteyksi?.
+SecurityLevels.networkThreatLevel.desc.HIGH=Freenet yhdist?? vain yst?viisi, 
joten ${bold}sinula t?ytyy olla yst?vi? valitaksesi t?m?n tilan${/bold}. 
Freenet tule olemaan hidas ellei sinulla ole v?hint??n viitt? yst?v??, eik? 
toimi ollenkaan ellei sinulla ole v?hint??n yksi.
+SecurityLevels.networkThreatLevel.desc.LOW=Muut saattavat l?yt?? 
identiteettisi melko helposti!
+SecurityLevels.networkThreatLevel.desc.MAXIMUM=Freenet tulee olemaan 
${bold}huomattavasti${/bold} hitaampi korkealla tasolla, ja ${bold}sinulla 
t?ytyy olla yst?vi? k?ytt??ksesi t?t? muotoa${/bold}.
+SecurityLevels.networkThreatLevel.desc.NORMAL=Freenet tulee olemaan varovainen 
suojellakseen anonymiteetti?si, keskisuurella suorituskykyh?vi?ll?. Freenet 
automaattisesti yhdist?? tuntemattomiin solmuihin. Suosittelemme, ett? lis??t 
yst?vi?, jotka py?ritt?v?t Freenet-solmua ja muutat t?m?n tason korkeaksi.
+SecurityLevels.networkThreatLevel.name.HIGH=KORKEA
+SecurityLevels.networkThreatLevel.name.LOW=MATALA
+SecurityLevels.networkThreatLevel.name.MAXIMUM=MAKSIMI
+SecurityLevels.networkThreatLevel.name.NORMAL=NORMAALI
+SecurityLevels.physicalThreatLevel.choice.LOW=En ole huolestunut.
+SecurityLevels.physicalThreatLevel.choice.NORMAL=Olen huolestunut.
+SecurityLevels.physicalThreatLevel.desc.LOW=Freenet tulee v?ltt?m??n levyn 
salausta ja j?tt?? j?lki? freesite-vierailuistasi kiintolevyllesi nostaen 
suorituskyky?, mutta j?tt?en sinut turvattomaksi jos koneesi kaapataan.
+SecurityLevels.physicalThreatLevel.desc.NORMAL=Freenet salaa v?liaikaiset 
tiedostot jne. pienell? suorituskykyh?vi?ll?, mutta sinun kannattaa k?ytt?? 
muitakin varotoimenpiteit?, kuten selaimen v?limuistin ottamista pois k?yt?st? 
k?ytt?ess?si webbik?ytt?liittym??. Jos k?yt?t sinnikk?it? latauksia (useimmat 
ty?kalut k?ytt?v?t), sinun kannattaisi kryptata levy, jolla Freenet py?rii.
+SecurityLevels.physicalThreatLevel.name.LOW=MATALA
+SecurityLevels.physicalThreatLevel.name.NORMAL=NORMAALI
 SimpleToadletServer.advancedMode=K?yt? edistynytt? tilaa?
 SimpleToadletServer.cssName=K?ytt?liittym?n teema
 SimpleToadletServer.cssNameLong=Valitse teema Freenetin webbik?ytt?liittym?lle
@@ -561,7 +642,11 @@
 StatisticsToadlet.usedMemory=Javan k?ytt?m? muisti: ${memory}
 StatisticsToadlet.versionTitle=Solmun versiotieto
 StatisticsToadlet.waiting=Odottaa
+TestnetHandler.cannotEnableDisableOnTheFly=Testnet:n p??lle-/poiskytkent? 
lennosta on mahdotonta: k?ynnist? solmu uudelleen ja ota uudet yhteydet
+TestnetHandler.enable=K?ytet??nk? testnet-tilaa? (VAARALLINEN)
+TestnetHandler.enableLong=M??rittelee, onko testet-tila k?yt?ss? 
(VAARALLINEN!). Testnet-tila tuhoaa anonyymiteettisi antaen kuitenkin 
kehitt?jille suurta apua solmun vianm??rityksess?.
 TestnetHandler.port=Testnetin portti
+TestnetHandler.portLong=Testnetin portti (-1 = listenport + 1000)
 TextModeClientInterfaceServer.enabled=Salli TCMI
 TextModeClientInterfaceServer.enabledLong=M??ritt??, halutaanko TCMI sallia
 Toadlet.cancel=Peruuta
@@ -589,6 +674,8 @@
 TranslationToadlet.translationKeyLabel=K??nn?ksen avain
 TranslationToadlet.translationUpdateTitle=K??nn?sp?ivitys
 TranslationToadlet.translationUpdatedTitle=K??nn?s p?ivitetty!
+UnknownContentTypeException.explanation=Freenettisi ei tied? mit??n t?st? 
MIME-tyypist?. T?m? tarkoittaa, ett? selaimesi saattaa tehd? jotain vaarallista 
t?m?n latauksen takia. Esimerkiksi, monet tiedostomuodot voivat sis?lt?? 
sis?llytettyj? kuvia tai videoita, jotka ladataan www-sivulta; t?m? ei miss??n 
tapauksessa ole vaaratonta, sill? ne voivat tuhota anonyymiteettisi ja 
paljastaa IP-osoitteesi (jos hy?kk??j? py?ritt?? www-sivua tai p??see sen 
lokeihin). Linkit www-sivuille voi olla my?s uhka, melko pitk?lti samasta 
syyst?, kuten my?s erilaiset skriptit.
+UnknownContentTypeException.title=Tuntematon ja mahdollisesti vaarallinen 
sis?lt?tyyppi: ${type}
 UpdatedVersionAvailableUserAlert.clickToUpdateNow=Klikkaa t?st? p?ivitt??ksesi 
solmusi heti.
 UpdatedVersionAvailableUserAlert.title=Uusi vakaa versio Freenetist? on 
julkaista, sinun kannattaisi p?ivitt?? mahdollisimman nopeasti
 UpdatedVersionAvailableUserAlert.updateASAPButton=P?ivit? mahdollisimman 
nopeasti

Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.it.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.it.properties   2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.it.properties   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,9 +1,9 @@
 Announcer.announceAlertIntro=Il nodo sta cercando di connettersi con i 
seednode ed annunciare s? stesso all' OpenNet (network di Sconosciuti). Possono 
essere necessari alcuni minuti per completare l'operazione.
 Announcer.announceAlertNoSeednodes=Non e' stato trovato il file seednodes.fref 
e quindi il nodo non pu? connettersi automaticamente ad Opennet. Aggiungere 
alcuni nodi manualmente o scaricare il file seednodes da 
http://downloads.freenetproject.org/alpha/opennet/ .
-Announcer.announceAlertShort=Il nodo sta cercando di connettersi alla rete, 
nel frattempo sar? pi? lento.
+Announcer.announceAlertShort=Tentativo di connessione in corso: le prestazioni 
del nodo risulteranno ridotte fino a connessione avvenuta.
 Announcer.announceAlertTitle=Annuncio Nodo in corso
 Announcer.announceDetails=Il nodo ha recentemente inoltrato 
${recentSentAnnouncements} annunci, ${runningAnnouncements} dei quali ancora in 
corso, ed aggiunto ${addedNodes} nodi (${refusedNodes} nodi hanno rifiutato la 
connessione). In questo momento il nodo ? connesso a ${connectedSeednodes} 
seednode e sta cercando di connettersi ad altri ${disconnectedSeednodes}.
-Announcer.announceDisabledTooOld=Il software utilizzato dal nodo ? obsoleto ed 
inadatto alla connessione con la version corrente della rete Freenet. 
L'annuncio ? stato diabilitato in quanto comunque inutile. Si prega di 
aggiornare il nodo appena possibile (auto-aggiornamento potrebbe essere in 
attesa di input o disabilitato)
+Announcer.announceDisabledTooOld=Il software utilizzato dal nodo ? obsoleto ed 
inadatto alla connessione con la versione attuale della rete Freenet. 
L'annuncio ? stato diabilitato in quanto comunque inutile. Si prega di 
aggiornare il nodo appena possibile (auto-aggiornamento potrebbe essere in 
attesa di input o disabilitato)
 Announcer.announceDisabledTooOldShort=Il nodo non riesce a connettersi alla 
rete perch? la versione di Freenet utilizzata ? obsoleta. Si prega di eseguire 
l'aggiornamento.
 Announcer.announceDisabledTooOldTitle=Annuncio disabilitato (obsoleto)
 Announcer.announceLoading=Il nodo sta caricando il file seednodes per 
annunciarsi al resto della rete. Il completamento dell' operazione potrebbe 
richiedere diversi minuti.
@@ -166,7 +166,7 @@
 ContentFilter.textPlainWriteAdvice=Testo semplice (plain text) - non 
pericoloso a meno che l'utente vi includa informazioni compromettenti
 DarknetConnectionsToadlet.activityInserts=Inserzioni: ${totalSenders} totale 
senders, ${CHKhandlers} CHK handlers, ${SSKhandlers} SSK handlers
 DarknetConnectionsToadlet.activityRequests=Richieste: ${totalSenders} totale 
senders, ${CHKhandlers} CHK handlers, ${SSKhandlers} SSK handlers
-DarknetConnectionsToadlet.activityTitle=Attivit? Corrente
+DarknetConnectionsToadlet.activityTitle=Attivit? in Corso
 DarknetConnectionsToadlet.add=Aggiungi
 DarknetConnectionsToadlet.addPeerTitle=Aggiungi un peer
 DarknetConnectionsToadlet.alreadyInReferences=La referenza data ? gi? presente 
in lista.
@@ -266,7 +266,7 @@
 ExtOldAgeUserAlert.extTooOldShort=Il file freenet-ext.jar ? obsoleto. Si prega 
di aggiornarlo.
 ExtOldAgeUserAlert.extTooOldTitle=Freenet-ext obsoleto
 FProxyToadlet.abortToHomepage=Interrompi e ritorna alla homepage di FProxy
-FProxyToadlet.alerts=Messaggi dettagliati sullo stato del nodo
+FProxyToadlet.alerts=Messaggi dettagliati sullo stato del nodo e messaggi da 
parte di Amici
 FProxyToadlet.alertsTitle=Avvertenze
 FProxyToadlet.backToFProxy=${link}Clicca qui${/link} per andare alla homepage 
di FProxy
 FProxyToadlet.backToReferrer=${link}Clicca qui${/link} per tornare alla pagina 
referente.
@@ -330,7 +330,7 @@
 FProxyToadlet.translationTitle=Traduzione
 FProxyToadlet.unableToRetrieve=Non ? stato possibile richiamare questo file.
 FProxyToadlet.unknownMIMEType=MIME type: sconosciuto
-FProxyToadlet.welcome=homepage
+FProxyToadlet.welcome=esplora freenet
 FProxyToadlet.welcomeTitle=Esplora Freenet
 FcpServer.allowedHosts=Host abilitati (Leggere l'avvertenza)
 FcpServer.allowedHostsFullAccess=Host ai quali ? consentito accesso pieno
@@ -579,10 +579,10 @@
 InsertException.shortError.8=Non ? stato possibile inoltrare la richiesta
 InsertException.shortError.9=Conflitto con dati esistenti
 IntOption.parseError=Il valore specificato non pu? essere interpretato come 
32-bit integer : ${val}
-InvalidAddressOverrideUserAlert.unknownAddress=Freenet ha rilevato che il 
valore attualmente in uso per ipAddessOverride non ? valido in quanto non 
conforme alla sintassi appropriata per un hostname n? per un indirizzo IPv4 o 
IPv6 (in accordo con l'implementazione corrente della funzione che controlla la 
sintassi per indirizzi IPv6)
+InvalidAddressOverrideUserAlert.unknownAddress=Freenet ha rilevato che il 
valore attualmente in uso per ipAddessOverride non ? valido in quanto non 
conforme alla sintassi appropriata per un hostname n? per un indirizzo IPv4 o 
IPv6 (in accordo con l'attuale implementazione della funzione che controlla la 
sintassi per indirizzi IPv6)
 InvalidAddressOverrideUserAlert.unknownAddressShort=L' indirizzo IP impostato 
manualmente (ipAddressOverride) non funziona. si prega di correggerlo.
 InvalidAddressOverrideUserAlert.unknownAddressTitle=Valore Override Indirizzo 
non Valido
-InvalidAddressOverrideUserAlert.unknownAddressWithConfigLink=Freenet ha 
rilevato che il valore attualmente in uso per ipAddessOverride non ? valido in 
quanto non conforme alla sintassi appropriata per un hostname n? per un 
indirizzo IPv4 o IPv6 (in accordo con l'implementazione corrente della funzione 
che controlla la sintassi per indirizzi IPv6) E' possibile correggere l' 
Override indirizzo IP ${link}configuration parameter${/link}.
+InvalidAddressOverrideUserAlert.unknownAddressWithConfigLink=Freenet ha 
rilevato che il valore attualmente in uso per ipAddessOverride non ? valido in 
quanto non conforme alla sintassi appropriata per un hostname n? per un 
indirizzo IPv4 o IPv6 (in accordo con l'attuale implementazione della funzione 
che controlla la sintassi per indirizzi IPv6) E' possibile correggere il 
${link}parametro di configurazione${/link} dell' IP address override.
 JPEGFilter.notJpeg=Le dimensioni del file che si sta cercando di richiamare 
sono troppo ridotte perch? possa trattarsi di un'immagine JPEG. Potrebbe essere 
un file in un altro formato e il browser potrebbe fare qualcosa di sbagliato a 
causa della mancata corrispondenza; il file ? stato pertanto bloccato.
 JPEGFilter.tooShort=File troppo piccolo per un JPEG.
 JPEGFilter.tooShortTitle=Troppo corto
@@ -620,7 +620,7 @@
 LogConfigHandler.maxZippedLogsSize=Spazio massimo per vecchi log
 LogConfigHandler.maxZippedLogsSizeLong=Spazio massimo su disco utilizzabile da 
vecchi log.
 LogConfigHandler.minLoggingPriority=Priorit? minima dei messaggi da iscrivere 
nei log.
-LogConfigHandler.minLoggingPriorityLong=Minima priorit? dei messaggi che 
vengono iscritti nel log file. Le opzioni sono: minor, normal, error, 
nell'ordine dalla meno alla pi? verbosa.
+LogConfigHandler.minLoggingPriorityLong=Minima priorit? dei messaggi che 
vengono iscritti nel log file. Le opzioni sono: minor, normal, error, in ordine 
decrescente di verbosit?.
 LogConfigHandler.rotationInterval=Intervallo di rotazione dei log
 LogConfigHandler.rotationIntervalLong=Intervallo di rotazione dei log - 
Periodo di tempo allo scadere del quale i log vengono ruotati. Gli ultimi due 
log files vengono conservati (current.log e prev.log) insieme a diversi log 
file compressi fino al massimo impostato in maxZippedLogsSize
 LoggerHook.unrecognizedPriority=Nome di priorit? non riconosciuto: ${name}.
@@ -628,10 +628,10 @@
 MeaningfulNodeNameUserAlert.noNodeNick=Non ? stato possibile trovare il 
nickname da utilizzare. Usare qui un indirizzo e-mail o un nickname IRC ? 
generalmente una buona idea in quanto consente ai peer di identificare il nodo. 
(nota che soltanto i peer darknet elencati alla pagina Amici potranno vedere il 
nome del nodo, che resta invece invisibile ai peer Opennet)
 MeaningfulNodeNameUserAlert.noNodeNickShort=Nome nodo non definito.
 MeaningfulNodeNameUserAlert.noNodeNickTitle=Nome nodo non definito.
-N2NTMToadlet.composingMessageLabel=Messaggio N2NTM  da inviare ai seguenti 
nodi:
+N2NTMToadlet.composingMessageLabel=Composizione messaggio N2NTM  da inviare ai 
seguenti peer:
 N2NTMToadlet.delayed=Il nodo interressato sta temporaneamente respingendo 
richieste; il messaggio potrebbe giungere in lieve ritardo.
 N2NTMToadlet.delayedTitle=Differito
-N2NTMToadlet.failed=Il peer interessato non ? connesso in questo momento: non 
? stato possibile inviare il messaggio
+N2NTMToadlet.failed=Peer non connesso: messaggio non inviato.
 N2NTMToadlet.failedTitle=Fallito
 N2NTMToadlet.friends=Amici
 N2NTMToadlet.homepage=Homepage
@@ -650,7 +650,7 @@
 N2NTMToadlet.sent=Messaggio inviato al peer
 N2NTMToadlet.sentTitle=Inviato
 N2NTMToadlet.tooLong=I messaggi N2NTM possono contenere fino a un massimo di 
1024 caratteri
-N2NTMToadlet.tooLongTitle=Troppo Lungo
+N2NTMToadlet.tooLongTitle=Lunghezza eccessiva
 N2NTMToadlet.unauthorized=L'accesso a questa pagina ? interdetto
 N2NTMUserAlert.delete=Elimina
 N2NTMUserAlert.header=Da: ${from} (scritto ${composed} | inviato ${sent} | 
ricevuto ${received})
@@ -671,6 +671,7 @@
 Node.buggyJVMTitle=Avvertennza JVM soggetta a 'bug'
 Node.buggyJVMWithLink=La JVM in uso (${version}) ? notoriamente 
${link}difettosa${/link}. Pu? produrre errori tipo OutOfMemoryError anche con 
molta memoria ancora disponibile. Sarebbe auspicabile aggiornare almeno a Sun 
Java 1.4.2_13, 1.5.0_10 o 1.6 (quest'ultima ? la versione consigliata).
 Node.bwlimitMustBePositive=Il limite dell'ampiezza di banda deve essere 
positivo
+Node.connectToSeednodesCannotBeChangedMustDisableOpennetOrReboot=Impostazione 
delle connessioni a nodi seed. Non disabilitare mentre Opennet ? in funzione. 
Disabilitare Opennet prima di disabilitare questa opzione, quindi abilitare 
nuovamente Opennet o riavviare il nodo.
 Node.databaseMemory=Memoria massima utilizzabile dal datastore
 Node.databaseMemoryLong=Uso massimo della memoria del database contenente 
indici del magazzino dati (datastore). 0 significa nessun limite (non supera 
comunque il 30% circa della memoria massima)
 Node.deadlockTitle=Deadlocking probabilmente dovuto ad una combinazione di JVM 
e kernel che da luogo a "bug".
@@ -696,15 +697,15 @@
 Node.enableULPRDataPropagation=Abilita propagazione dati ULPR
 Node.enableULPRDataPropagationLong=Abilita propagazione rapida di chiavi 
richieste recentemente ai nodi che le hanno richieste quando i dati sono stati 
finalmente trovati? (Richieste Persistenti Ultra-Leggere)
 Node.errorApplyingConfig=Si ? verificato un errore durante l'applicazione 
della nuova configurazione : ${error}
-Node.extraPeerDir=Directory dei dati extra peer
+Node.extraPeerDir=Directory dei dati supplementari relativi ai peer
 Node.extraPeerDirLong=Nome della directory dove immagazzinare dati 
supplementari relativi ai peer
 Node.forceBigShrink=Esegui immediatamente grosse riduzioni di dimensione dello 
store
 Node.forceBigShrinkLong=Determina se eseguire immediatamente le riduzioni di 
dimensione in misura superiore al 10% del magazzino (store), piuttosto che 
aspettare il prossimo riavvio del nodo. Le riduzioni on-line non preservano i 
dati utilizzati per ultimi quindi l'uso di questa opzione non ? raccomandato; 
da usarsi solo nel caso in cui sia desiderabile un risultato immediato.
 Node.inBWLimit=Limite ampiezza di banda in entrata (bytes per secondo)
-Node.inBWLimitLong=Limite dell'ampiezza di banda in entrata (bytes/sec); il 
nodo cerca di non eccedere tale limite; -1 siglifica quattro volte il limite 
impostato per l'ampiezza di banda in uscita (outputBandwidthLimit)
+Node.inBWLimitLong=Limite dell'ampiezza di banda in entrata (bytes/sec); il 
nodo cerca di non eccedere tale limite; -1 = 4x outputBandwidthLimit (limite 
ampiezza di banda in uscita).
 Node.invalidStoreSize=Il datastore (magazzino dati) deve essere di dimensioni 
uguali o superiori a 32MB
-Node.l10nLanguage=Lingua dell' interfaccia grafica
-Node.l10nLanguageLong=Cambia la lingua in cui messaggi sono visualizzati. 
Alcune frasi e messaggi saranno visibili in versione tradotta solo dopo il 
prossimo riavvio del nodo.
+Node.l10nLanguage=La lingua in cui visualizzare messaggi e informazioni
+Node.l10nLanguageLong=Questa impostazione cambia la lingua dei messaggi 
visualizzati. Alcune frasi e messaggi saranno visibili in versione tradotta 
solo dopo il prossimo riavvio del nodo.
 Node.maxHTL=HTL massimo
 Node.maxHTLLong=HTL massimo (PER USO ESCLUSIVO DEGLI SVILUPPATORI!)
 Node.maxOpennetPeers=Numero massimo di peer Opennet
@@ -712,11 +713,11 @@
 Node.maxOpennetPeersMustBeTwentyOrLess=Il valore deve essere uguale o 
inferiore a 20
 Node.mustBePositive=Il valore deve essere positivo!
 Node.nodeDir=Directory del nodo
-Node.nodeDirLong=Directory contenente file relativi al nodo, per esempio la 
lista dei peer
+Node.nodeDirLong=Directory dove conservare file relativi al nodo, per esempio 
la lista dei peer
 Node.nodeName=Nome del nodo
-Node.nodeNameLong=Nome del nodo. E' visibile solo agli Amici (darknet peer), 
mentre gli Sconosciuti (opennet peer) non potranno vederlo.
+Node.nodeNameLong=Il nome del nodo ? visibile solo agli Amici
 Node.notUsingSunVM=E' stata rilevata una JVM ${vendor} ${version} che potrebbe 
influire sul corretto funzionamento del nodo. Se possibile, installare Sun java 
disponibile presso http://www.java.com/getjava
-Node.notUsingSunVMShort=Freenet sta attualmente utilizzando JVM (Java Virtual 
Machine) diversa da Sun, che ? quella raccomandata. Si prega di scaricare ed 
installare la versione corrente di Sun Java JRE (Java Runtime Environment)
+Node.notUsingSunVMShort=Freenet sta attualmente utilizzando JVM (Java Virtual 
Machine) diversa da Sun, che ? quella raccomandata. Si prega di scaricare ed 
installare l'ultima versione di Sun Java JRE (Java Runtime Environment)
 Node.notUsingSunVMTitle=Il nodo non sta usando una JVM della Sun
 Node.notUsingWrapper=Il nodo sta girando senza il wrapper. Ci? ? generalmente 
sconsigliabile. Il nodo non potr? riavviare s? stesso e quindi l'aggiornamento 
automatico non potr? funzionare. Inoltre, se la JVM se ne dovesse andare nel 
"limbo" non sar? possibile riavviare automaticamente nemmeno qiuella. Non 
verranno generati stack dump in alcuni posti e quindi debugging sar? pi? 
difficile.
 Node.notUsingWrapperShort=Freenet sta girando senza wrapper. Questo non ? 
raccomandato.
@@ -724,7 +725,7 @@
 Node.oneConnectionPerIP=Limita ad una connessione per indirizzo
 Node.oneConnectionPerIPLong=Permettere una sola connessione per indirizzo? Ci? 
rende leggermente pi? difficile un attacco eseguito connettendosi al nodo pi? 
volte con diverse identit? in modo da dominarne il routing o facilitare la 
raccolta di dati. Questa opzione impedisce che uno stesso peer sia connesso 
allo stesso tempo su darknet e su opennet.
 Node.opennetEnabled=Abilita modalit? insicura (connessioni automatiche a nodi 
non fid?ti)
-Node.opennetEnabledLong=Abilita Modalit? Insicura? (detta anche Opennet) 
Abilitando questa opzione il nodo scambier? automaticamente referenze on altri 
nodi. Ci? rende facilmente osservabile dall'esterno il fatto che su questo 
computer sta girando un nodo Freenet, facilitando attacchi di diversi tipi. 
Avendone la possibilit?, l'opzione migiore ? quella di connettersi soltanto ad 
utenti conosciuti ed addifabili (Darknet peer, vedi pagina Amici)
+Node.opennetEnabledLong=Abilita Modalit? Insicura? (Opennet) Abilitando questa 
opzione il nodo scambier? automaticamente referenze con altri nodi. Ci? rende 
la presenza di un nodo Freenet facilmente osservabile dall'esterno, facilitando 
attacchi di diversi tipi. Avendone la possibilit?, l'opzione migiore ? quella 
di connettersi soltanto ad utenti conosciuti ed addifabili (Amici) e 
disabilitare questa opzione.
 Node.outBWLimit=Limite ampiezza di banda in uscita (bytes per secondo)
 Node.outBWLimitLong=Limite "duro" dell' ampiezza di banda in uscita 
(bytes/sec); di solito il nodo non eccede questo limite
 Node.passOpennetPeersThroughDarknet=Trasmetti referenze opennet attraverso 
darknet peer
@@ -735,13 +736,17 @@
 Node.publishOurPeersLocationLong=Trasmettere ai peer la locazione dei nostri 
peer? Ci? facilita il routing ma fornisce informazioni ad un potenziale 
avversario.
 Node.routeAccordingToOurPeersLocation=Utilizza la locazione dei peer dei 
nostri peer per il routing
 Node.routeAccordingToOurPeersLocationLong=Usare per il routing la locazione 
dei peer dei nostri peer? Ci? facilita il routing ma potrebbe essere utile ad 
un potenziale avversario.
-Node.storeBloomFilterCounting=Usa filtro 'counting bloom'
-Node.storeBloomFilterCountingLong=Usare un filtro 'counting bloom' a 2 bit? 
(in caso di dubbio, non modificare)
-Node.storeBloomFilterSize=Dimensione del bloom filter size (totale) in bytes
+Node.storeBloomFilterCounting=Usa counting bloom filter
+Node.storeBloomFilterCountingLong=Usare counting bloom filter a 2 bit? (in 
caso di dubbio, non modificare)
+Node.storeBloomFilterSize=Dimensione del bloom filter (totale) in bytes
 Node.storeBloomFilterSizeLong=Dimensioni del filtro bloom in bytes. Di solito 
1/2048mo della dimensione del  datastore ? pi? che abbastanza. Impostare su 
zero per disabilitare il bloom filter. Impostare su -1 per tornare al default.
 Node.storeDirectory=Directory magazzino dati (store)
 Node.storeDirectoryLong=Directory contenente gli store file
 Node.storeMaxMemTooHigh=Impostare un valore superiore ad 80% della memoria RAM 
da destinare a BDB ? generalmente una pessima idea.
+Node.storePreallocate=Preallocare lo spazio per il datastore
+Node.storePreallocateLong=Preallocare spazio per il datastore
+Node.storeSaltHashResizeOnStart=Modifica dimensione del datastore al prossimo 
avvio del nodo (solo per salt-hash)
+Node.storeSaltHashResizeOnStartLong=Cambiamento dimensioni datastore all' 
avvio (solo per salt-hash). Se impostato su 'vero', il nodo completer? le 
modifiche delle dimensioni del datastore durante il processo di avvio. In 
questo modo il processo risulter? pi? rapido di quanto sarebbe se fosse 
eseguito 'al volo', ma durante il processo stesso il nodo non sara accessibile.
 Node.storeSize=Dimensioni in bytes del magazzino dati (store)
 Node.storeSizeLong=Dimensioni del magazzino (store) in bytes
 Node.storeType=Tipo di magazzino dati (store). NON MODIFICARE!!
@@ -757,7 +762,7 @@
 Node.withAnnouncementLong=Permettere che il nodo si auto-inserisca nella rete 
Freenet usando seednodes? Questa opzione ? abilitata di default per motivi 
tecnici ma ? intrinsecamente insicura
 NodeClientCore.couldNotFindOrCreateDir=Non ? stato possibile trovare o creare 
la directory
 NodeClientCore.downloadAllowedDirs=Directory dove il download ? consentito
-NodeClientCore.downloadAllowedDirsLong=Si pu? usare una lista di directory 
dove dove il download e' permesso, separate da 'punto e virgola' (;). 
"downloads" significa downloadsDir, vuoto (nessuna directory specificata) 
significa che il download su disco non e' permesso, "all" significa download 
permessi in tutte le directory AVVERTENZA; Se impostato su "all" ("tutte"), 
ogni utente potr? scaricare files  in qualsiasi directory.
+NodeClientCore.downloadAllowedDirsLong=Si pu? usare una lista di directory 
dove dove il download e' permesso, separate da 'punto e virgola' (;). 
"downloads" significa downloadsDir, vuoto (nessuna directory specificata) 
significa che il download su disco non e' permesso, "all" significa download 
permessi in tutte le directory AVVERTENZA; Se impostato su "all" ("tutte"), 
ogni utente potr? scaricare file  in qualsiasi directory.
 NodeClientCore.downloadDir=Directory predefinita per i download
 NodeClientCore.downloadDirLong=Directory predefinita dove salvare i file 
scaricati
 NodeClientCore.encryptPersistentTempBuckets=Abilita cifratura dei bucket di 
dati temporanei persistenti (NON MODIFICARE!)
@@ -788,11 +793,11 @@
 NodeClientCore.uploadAllowedDirs=Directory dalle quali l'upload e' consentito
 NodeClientCore.uploadAllowedDirsLong=Si pu? usare una lista di directory dove 
l'upload e' consentito, separate da 'punto e virgola' (;). Vuoto (nessuna 
directory specificata) significa che l'upload non e' permesso, "all" significa 
upload permesso da tutte le directory ATTENZIONE!; Se impostato su "all" 
("tutte"), ogni utente potr? inserire qualunque file da qualsiasi directory.
 NodeIPDectector.inclLocalAddress=Includi indirizzi locali nella referenza del 
nodo
-NodeIPDectector.inclLocalAddressLong=Specifica se includere l'indirizzo locale 
(LAN e localhost) nella referenza del nodo. Ci? non ? necessario a meno che 
entrambi i nodi che si vogliono collegare abbiano impostato 
allowLocalAddresses=true per le rispettive referenze (per impostare questa 
opzione, abilitare la modalit? avanzata e usare le opzioni disponibili alla 
pagina 'Connessioni ad Amici').
+NodeIPDectector.inclLocalAddressLong=Specifica se includere o meno l'indirizzo 
locale (LAN e localhost) nella referenza del nodo. Ci? ? utile soltanto se 
entrambi i nodi da collegare usano allowLocalAddresses=true per le rispettive 
referenze (opzione disponibile alla pagina 'Connessioni ad Amici' in modalit? 
avanzata).
 NodeIPDectector.ipOverride=Impostazione manuale indirizzo IP
 NodeIPDectector.ipOverrideLong=Impostazione manuale dell'indirizzo IP (di 
solito non ? necessario) - Utilizzare questa opzione se si ha un indirizzo IP 
statico o un domain name  (es. dyndns), e ci si trova dietro un firewall.
 NodeIPDectector.tempAddressHint=Suggerimento temporaneo indirizzo IP
-NodeIPDectector.tempAddressHintLong=Suggerisce temporaneamente l'indirizzo IP; 
viene eliminato dopo l'uso
+NodeIPDectector.tempAddressHintLong=Suggerisce temporaneamente l'indirizzo IP 
e viene eliminato dopo l'uso
 NodeIPDetector.maybeSymmetric=Sembra che il nodo sia dietro una NAT 
simmetrica. Potrebbe trattarsi di problemi di connessione: se ci si trova 
dietro una NAT simmetrica ci si potr? probabilmente connettere soltanto con i 
nodi che sono raggiungibili da interenet.
 NodeIPDetector.maybeSymmetricShort=Problema di connessione: il nodo potrebbe 
trovarsi dietro una NAT simmetrica.
 NodeIPDetector.maybeSymmetricTitle=Problemi di connessione
@@ -809,7 +814,7 @@
 NodeStat.memCheckLong=Abilita verifica della memoria (scrive un messaggio nel 
log file. La verifica della memoria deve essere abilitata perche' 
aggressiveGCModificator abbia effetto)
 NodeStat.statsPersister=File contenente le statistiche del nodo
 NodeStat.statsPersisterLong=File contenente statistiche: NON si tratta delle 
statistiche del client. Queste statistiche servono al nodo per decidere se 
accettare o rifiutare nuove richieste. Non eliminare!
-NodeStat.threadLimit=Limite thread
+NodeStat.threadLimit=Massimo numero di thread
 NodeStat.threadLimitLong=Il nodo respinge richieste per limitare l'uso di 
thread al valore specificato.
 NodeStats.mustBePercentValueNotFull=Questo valore deve essere espresso in 
precentuale, compresa tra 0 e 99.
 NodeStats.valueTooLow=Valore troppo basso per questa impostazione: ? 
necessario aumentarlo.
@@ -980,7 +985,7 @@
 QueueToadlet.delete=Elimina
 QueueToadlet.download=Scarica
 QueueToadlet.downloadFiles=Download multipli
-QueueToadlet.downloadFilesInstructions=E' possibile incollare una serie di 
chiavi da scaricare nello spazio sottostante (una per rigo)
+QueueToadlet.downloadFilesInstructions=Per download multipli, incollare una 
lista chiavi nello spazio sottostante, una per rigo.
 QueueToadlet.downloadSucceeded=Il file ${origlink}${filename}${/origlink} ? 
stato scaricato. ${link}Click qui${/link} per aprile il file (${size}).
 QueueToadlet.downloadSucceededTitle=Download completato: ${filename}
 QueueToadlet.emergency=urgenza estrema
@@ -1018,8 +1023,9 @@
 QueueToadlet.identifier=Identificazione
 QueueToadlet.insertAs=Inserisci come:
 QueueToadlet.insertFile=Inserisci File
-QueueToadlet.insertFileBrowseLabel=Esplora file su disco
-QueueToadlet.insertFileCompressLabel=Comprimi
+QueueToadlet.insertFileBrowseButton=Sfoglia
+QueueToadlet.insertFileBrowseLabel=Scegli un file dal disco rigido
+QueueToadlet.insertFileCompressLabel=Usa compressione
 QueueToadlet.insertFileInsertFileLabel=Inserisci File
 QueueToadlet.insertFileLabel=File
 QueueToadlet.insertFileResetForm=Annulla
@@ -1028,7 +1034,7 @@
 QueueToadlet.low=bassa
 QueueToadlet.medium=media
 QueueToadlet.mimeType=MIME type
-QueueToadlet.noTaskOnGlobalQueue=Nessuna operazione in attesa nella coda 
globale in questo momento.
+QueueToadlet.noTaskOnGlobalQueue=Nessuna operazione in coda globale al momento.
 QueueToadlet.none=nessuna
 QueueToadlet.notLoadedYet=Il nodo sta ancora caricando la lista delle 
richieste persistenti. Si prega di pazientare.
 QueueToadlet.notLoadedYetTitle=La Coda non ? stata ancora caricata.
@@ -1095,25 +1101,25 @@
 SaltedHashFreenetStore.longResizeProgress=Ridimensionamento del 
datastore(${name}) in corso: ${processed}/${total}. Il nodo potrebbe risultare 
pi? lento durante questa operazione. Evitare di riavviare il nodo durante il 
processo.
 SaltedHashFreenetStore.shortRebuildProgress=Manutenzione del 
datastore(${name}) in corso: ${processed}/${total}
 SaltedHashFreenetStore.shortResizeProgress=Ridimensionamento del 
datastore(${name}) in corso: ${processed}/${total}
-SecurityLevels.fewConnectedFriendsCheckbox=Si sono sicuro, aggiunger? altri 
Amici e/o accetto il costo in prestazioni e il fatto che Freenet potrebbe 
disconnettersi quando gli Amici non sono on-line.
-SecurityLevels.fewConnectedFriendsWarning=Soltanto ${connected} Connessioni ad 
Amici sono attualmente attive, su un totale di ${added}. Impostando il livello 
di sucurezza in rete MASSIMO, Freenet si connetter? esclusivamente agli Amici, 
cio? peer affidabili aggiunti manualmente. Ci? potrebbe provocare un 
abbassamento nelle prestazioni generali dovuto alla riduzione del numero di 
connessioni. Se tutti gli Amici si trovassero ad essere 'off line' allo stesso 
tempo, il nodo si ritroverebbe completamente disconnesso dalla rete. E' bene 
ricordare che gli Amici devono essere persone conosciute e delle quali ci si 
fida almeno parzialmente; in mancanza di questa condizione, l'uso esclusivo di 
connessioni ad Amici non produce alcun vantaggio. Inoltre, per un corretto 
funzionamento di Freenet ? necessario che il nodo possa in qualsiasi momento 
connettersi ad almeno 5-10 peer. Prima di procedere, verificare l'esistenza di 
tutte le condizioni di cui sopra.
+SecurityLevels.fewConnectedFriendsCheckbox=Si sono sicuro, aggiunger? altri 
Amici e/o accetto il costo in prestazioni e il fatto che il nodo sarebbe 
impossibilitato a connettersi alla rete Freenet qualora nessuno degli Amici vi 
fosse connesso.
+SecurityLevels.fewConnectedFriendsWarning=Soltanto ${connected} Connessioni ad 
Amici sono attualmente attive su un totale di ${added}. Impostando il livello 
di sicurezza in rete su ALTO o MASSIMO, Freenet potr? connettersi soltanto agli 
Amici, migliorando la sicurezza ma pagando un prezzo in prestazioni. Inoltre, 
se tutti gli Amici si trovassero ad essere contemporaneamente disconnessi, il 
nodo di troverebbe impossibilitato a ragguingere la rete. Per ottenere un 
effettivo incremento della sicurezza, gli Amici devono essere persone 
conosciute e delle quali sia possibile fidarsi almeno parzialmente. Per un 
corretto funzionamento ? necessario che il nodo possa sempre connettersi ad 
almeno 5-10 peer. Verificare l'esistenza di tutte le suddette condizioni prima 
di procedere.
 SecurityLevels.friendsThreatLevel=Quanto sarebbe preoccupante, se le persone i 
cui nodi sono connessi come Amici spiassero la nostra attivit?, deliberatamente 
o come risultato di una compromissione? (Questa ? una configurazione di default 
che pu? essre impostata separatamente per ognuno degli Amici). Impostando il 
livello di Sicurezza Rete su ALTO, le prestazioni di Freenet verrano 
influenzate dai livelli di Sicurezza Amici, oltre che dal numero di Connessioni 
ad Amici.
 SecurityLevels.friendsThreatLevelConfirmTitle=ATTENZIONE: Il livello di 
Sicurezza Amici verr? impostato su: ${mode}
 SecurityLevels.friendsThreatLevelShort=Protezione contro attacchi all' 
anonimato da parte di Amici
-SecurityLevels.highFriendsThreatLevelCheckbox=Si sono sicuro; ho bisogno di un 
alto livello di protezione contro i nodi di Amici doppiogiochisti o i cui nodi 
sono stati compromessi.
-SecurityLevels.highFriendsThreatLevelWarning=Il livello di sicurezza ver? 
impostato su ALTO. Questa impostazione causa una diminuzione delle prestazioni 
di Freenet, e il pi? delle volte non ? necessario farne uso. Se il motivo 
dietro il cambiamento ? la preoccupazione causata dall' avere aggiunto degli 
sconosciuti alle Connessioni ad Amici (peer affidabili), sarebbe bene prendere 
in considerazione l'idea di disconnetterli e riportare il livello di sicurezza 
su NORMALE. D'altro canto se ci si aspetta degli attachi o ci si aspetta che i 
computer di alcuni Amici potrebbero venire compromessi, innalzare il livello di 
sicurezza come precauzione non ? una cattiva idea.
-SecurityLevels.maxSecurityYouNeedFriends=${bold}E' necessario conoscere almeno 
una persona che gi? usa Freenett${/bold}, possibilmente 3, e tra 5 e 10 per 
ottenere buone prestazioni. Tali utenti vanno aggiunti alle 'Connessioni ad 
Amici', ma solo se si tratta di persone conosciute ed almeno parzialmente 
affidabili.
-SecurityLevels.maximumNetworkThreatLevelCheckbox=Si voglio abilitare il 
livello MASSIMO di Sicurezza Rete MASSIMO. Mi rendo conto che Freenet ? un 
programma sperimentale e che nonostante le precauzioni potrebbe essere 
possibile essere rintracciati, e del fatto che questa impostazione ridurr? 
sensibilmente le prestazioni di Freenet.
-SecurityLevels.maximumNetworkThreatLevelWarning=${bold}ATTENZIONE:${/bold} Il 
livello di Sicurezza Rete sta per essere impostato su MASSIMO. Ci? ridurr? 
${bold}notevolmente${/bold} la velocit? di trasferimento di file da e per 
questo nodo! Si prega di non utilizzare questa impostazione se non in caso di 
effettiva necessit?.
+SecurityLevels.highFriendsThreatLevelCheckbox=Si sono sicuro; ho bisogno di un 
alto livello di protezione nei confronti di Amici doppiogiochisti o i cui nodi 
siano stati compromessi.
+SecurityLevels.highFriendsThreatLevelWarning=Il livello di sicurezza ver? 
impostato su ALTO. Ci? causer? una diminuzione delle prestazioni di Freenet, e 
il pi? delle volte non ? necessario. Se la scelta ? dettata dalla 
preoccupazione dell' avere aggiunto dei perfetti sconosciuti alle Connessioni 
ad Amici, sarebbe bene considerare la possibilit? di disconnetterli e ritornare 
il livello di sicurezza NORMALE. D'altro canto, se ci si aspetta degli attacchi 
o si sospetta che i computer di alcuni Amici potrebbero essere stati 
compromessi, innalzare il livello di sicurezza come precauzione non ? una 
cattiva idea.
+SecurityLevels.maxSecurityYouNeedFriends=${bold}E' necessario conoscere almeno 
una persona che gi? usa Freenet${/bold}, possibilmente 3, e tra 5 e 10 per 
ottenere buone prestazioni. Tali utenti vanno aggiunti alle 'Connessioni ad 
Amici', ma solo se si tratta di persone conosciute ed almeno parzialmente 
affidabili.
+SecurityLevels.maximumNetworkThreatLevelCheckbox=Si, sono sicuro: voglio 
abilitare il livello MASSIMO di Sicurezza Rete MASSIMO. Mi rendo conto che 
Freenet ? un programma sperimentale, che essere rintracciati nonostante le 
precauzioni NON ? impossibile, e che questa impostazione ridurr? sensibilmente 
le prestazioni di Freenet.
+SecurityLevels.maximumNetworkThreatLevelWarning=${bold}ATTENZIONE:${/bold} Il 
livello di Sicurezza Rete sta per essere impostato su MASSIMO. Ci? ridurr? 
${bold}notevolmente${/bold} le prestazioni del nodo Freenet. Si prega di non 
utilizzare questa modalit? se non in caso di effettiva necessit?.
 SecurityLevels.networkThreatLevel=Quanto ? necessario difendersi da Internet 
Service Providers, corporazioni, governi, ragazzini annoiati ecc. che cercano 
di monitorare l'utilizzo di Freenet da parte dell' Utente?
 SecurityLevels.networkThreatLevelConfirmTitle=ATTENZIONE: Il livello di 
sicurezza in rete verr? impostato su ${mode}
-SecurityLevels.networkThreatLevelLowCheckbox=Si sono sicuro, voglio 
prestazioni migliori e non mi importa di chi pu? vedere quello che faccio con 
Freenet
-SecurityLevels.networkThreatLevelLowWarning=Il livello di sicurezza in rete 
verr? impostato du livello BASSO. Ci? facilita attacchi all' anonimato da parte 
di sconosciuti attraverso internet. Conferma di voler eseguire l'operazione?
+SecurityLevels.networkThreatLevelLowCheckbox=Si sono sicuro, voglio 
prestazioni migliori anche rischiando che la mia attivit? su Freenet possa 
essere monitorata.
+SecurityLevels.networkThreatLevelLowWarning=Il livello di sicurezza in rete 
verr? impostato su livello BASSO. Ci? facilita attacchi all' anonimato da parte 
di sconosciuti attraverso internet. Conferma di voler eseguire l'operazione?
 SecurityLevels.networkThreatLevelShort=Protezione contro attacchi da parte di 
sconosciuti attraverso internet
 SecurityLevels.noConnectedFriendsCheckbox=Si sono sicuro, aggiunger? altri 
Amici e/o accetto che Freenet sar? on-line soltanto quando gli Amici 
attualmente in lista sono connessi.
-SecurityLevels.noConnectedFriendsWarning=Nonostante ${added} Amici siano stati 
aggiunti alla lista, nessuno di essi risulta attualmente collegato. Impostando 
il livello di sicurezza in rete su ALTO o MASSIMO, non sar? possibile 
connettersi ad altri che ai nodi gestiti da Amici, dei quali nessuno reperibile 
in questo momento. Le possibilit? a diposizione sono: aggiungere altri Amici, 
usare Freenet solo quando gli Amici sono connessi, o evitare di usare alti 
livelli di sicurezza. Per ottenere un vantaggio reale, gli Amici devono essere 
persone conosiute ed affidabili; per ottenere buone prestazioni ? necessario 
che in ogni dato momento siano connessi almeno 5-10 Amici. Conferma il cambio 
impostazioni di sicurezza?
-SecurityLevels.noFriendsCheckbox=Si sono sicuro, desidero abilitare livello 
ALTO di Sicurezza Rete; aggiunger? delle Connessioni ad Amici appena possibile.
-SecurityLevels.noFriendsWarning=Nessun nodo ? stato aggiunto agli Amici. 
Configurando il livello di sicurezza in rete su ALTO o MASSIMO, non sar? 
possibile connettersi a Freenet finch? non sar? aperta almeno una connessione 
ad Amici. Perch? ci? comporti un effettivo vantaggio, ? necessario che le 
persone in questione siano conosciute ed almeno parzialmente affidabili; per 
ottenere delle buone prestazioni, ? necessario che almeno 5-10 connessioni 
siano aperte in ogni momento. Conferma la modifica delle impostazioni di 
sicurezza?
+SecurityLevels.noConnectedFriendsWarning=Nonostante ${added} Amici siano stati 
aggiunti, nessuno di essi risulta attualmente connesso. Con un livello di 
sicurezza in rete impostato su ALTO o MASSIMO, il nodo potr? connettersi alla 
rete Freenet soltanto quando degli Amici sono connessi, e in questo momento non 
lo sono. Sarebbe bene aggiungere ulteriori Amici o evitare di usare i livelli 
di sicurezza pi? alti; o al limite rassegnarsi a non usare Freenet quando non 
ci sono Amici connessi. Gli Amici devono essere persone conosiute ed 
affidabili! Aggiungere dei perfetti sconosciuti alle Connessioni ad Amici NON 
migliora la sicurezza, ma la peggiora! Per ottenere buone prestazioni ? 
necessario che in ogni dato momento vi siano almeno 5-10 connessioni attive. 
Conferma il cambiamento nelle impostazioni di sicurezza?
+SecurityLevels.noFriendsCheckbox=Si sono sicuro, desidero abilitare il livello 
ALTO di Sicurezza in Rete; aggiunger? delle Connessioni ad Amici appena 
possibile.
+SecurityLevels.noFriendsWarning=Non sono state aggiunte Connessioni ad Amici. 
Con un livello di sicurezza in rete ALTO o MASSIMO, non sar? possibile 
connettersi a Freenet finch? non sar? disponibile almeno una Connessione ad 
Amici funzionante. Per un effettivo vantaggio in termini di sicurezza, le 
persone che gestiscono i nodi aggiunti alle Connessioni ad Amici devono essere 
conosciute ed almeno parzialmente affidabili. Per ottenere delle buone 
prestazioni, ? necessario che almeno 5-10 connessioni siano aperte in ogni 
momento. Conferma modifica impostazioni di sicurezza?
 SecurityLevels.physicalThreatLevel=Ci sarebbe da preoccuparsi se il computer 
venisse rubato o sottoposto a sequestro giudiziario ed esaminato?
 SecurityLevels.physicalThreatLevelShort=Protezione in caso di furto o 
sequestro giudiziario del computer
 SecurityLevels.title=Livelli di Sicurezza
@@ -1128,7 +1134,7 @@
 SecurityLevels.friendsThreatLevel.choice.NORMAL=Gli attacchi da parte di Amici 
non mi preoccupano pi? di tanto ma vorrei comunque che Freenet prendesse 
precauzioni ragionevoli.
 SecurityLevels.friendsThreatLevel.desc.HIGH=Freenet non condivider? 
informazioni con gli Amici, risultando quindi leggermente pi? lento di come 
sarebbe in modalit? NORMALE
 SecurityLevels.friendsThreatLevel.desc.LOW=Freenet condivider? moltissime 
informazioni con gli Amici massimizzando le prestazioni.
-SecurityLevels.friendsThreatLevel.desc.NORMAL=Freenet condivider? una quantit? 
limitata di informazioni con gli Amici, e sar? pi? sento di come sarebbe a 
livello BASSO.
+SecurityLevels.friendsThreatLevel.desc.NORMAL=Freenet condivider? una quantit? 
limitata di informazioni con gli Amici, e sar? pi? lento di come sarebbe usando 
il livello BASSO.
 SecurityLevels.friendsThreatLevel.name.HIGH=ALTO
 SecurityLevels.friendsThreatLevel.name.LOW=BASSO
 SecurityLevels.friendsThreatLevel.name.NORMAL=NORMALE
@@ -1146,13 +1152,13 @@
 SecurityLevels.networkThreatLevel.name.NORMAL=NORMALE
 SecurityLevels.physicalThreatLevel.choice.LOW=Non preoccupante.
 SecurityLevels.physicalThreatLevel.choice.NORMAL=Preoccupante.
-SecurityLevels.physicalThreatLevel.desc.LOW=Freenet non user? la cifratura del 
disco e lascer? tracce dell' attivit? dell' Utente sul disco rigido. Ci? 
migliorerr? le prestazioni di Freenet pagando un prezzo in termini di minore 
sicurezza nel caso che il computer venisse rubato o sottoposto a sequesto 
guidiziario.
+SecurityLevels.physicalThreatLevel.desc.LOW=Freenet non user? cifratura e 
lascer? tracce di attivit? sul disco, migliorando le prestazioni del nodo a 
discapito della sicurezza nel caso che il computer venisse rubato o sottoposto 
a sequesto giudiziario.
 SecurityLevels.physicalThreatLevel.desc.NORMAL=Freenet provveder? alla 
cifratura dei file temporanei  ad un piccolo prezzo in prestazioni, ma sarebbe 
bene perndere ulteriori precauzioni come per esempio disabilitare la cache del 
web browser quando si usa L'interfaccia web. Se si fa uso di download 
persistenti (la maggioranza delle utilit? Freenet li usa), ? buona norma 
provvedere alla cifratura del drive di Freenet.
 SecurityLevels.physicalThreatLevel.name.LOW=BASSO
 SecurityLevels.physicalThreatLevel.name.NORMAL=NORMALE
 ShortOption.parseError=Il valore specificato non pu? essere interpretato come 
16-bit integer : ${val}
 SimpleToadletServer.advancedMode=Abilita modalit? avanzata
-SimpleToadletServer.advancedModeLong=Mostra informazioni cho possono 
interessare solo utenti avanzati o sviluppatori. Nella maggioranza dei casi 
dovrebbe essere impostata su 'falso'
+SimpleToadletServer.advancedModeLong=Mostra informazioni che possono 
interessare solo utenti avanzati o sviluppatori. Nella maggioranza dei casi 
dovrebbe essere impostata su 'falso'.
 SimpleToadletServer.allowedFullAccess=Host ai quali ? consentito pieno accesso 
a FProxy (leggere l'avvertenza)
 SimpleToadletServer.allowedFullAccessLong=Host ai quali ? consentito accesso 
pieno al nodo (cambiare impostazioni di configurazione, riavviare, ecc). 
AVVERTENZA: Usare cautela nel decidere a chi consentire accesso pieno!
 SimpleToadletServer.allowedHosts=Nomi host o indirizzi IP ai quali e' 
consentito connettersi a FProxy
@@ -1167,7 +1173,7 @@
 SimpleToadletServer.cssOverrideCantRead=Non ? stato possibile leggere il file 
di sovrascrittura CSS fornito: ${filename}
 SimpleToadletServer.cssOverrideLong=Questa impostazione permette di utilizzare 
un CSS personalizzato invece di quello normalmente usato. AVVERTENZA: i CSS 
possono essere pericolosi, e *non* vengono filtrati: utilizzare a proprio 
rischio. Per includerli nella distribuzione principale e-mail devl at 
freenetroject.org
 SimpleToadletServer.cssOverrideNotInUploads=Non ? possibile usare questa 
impostazione: "${filename} non ? una directory dalla quale sono permessi gli 
upload.
-SimpleToadletServer.doRobots=Usare robots.txt per escludere i robot?
+SimpleToadletServer.doRobots=Usa robots.txt per escludere i robot
 SimpleToadletServer.doRobotsLong=Pubblica un file /robots.txt allo scopo di 
tenere lontano Google, spiders, Wget, etc.
 SimpleToadletServer.enableInlinePrefetch=Abilita pre-ricezione (prefetching) 
di immagini inlinea (inline)
 SimpleToadletServer.enableInlinePrefetchLong=Questo potrebbe essere utile se 
il browser utilizza un numero ridotto di connessioni per comunicare con il 
nodo. D'altra parte potrebbe non esserlo.
@@ -1176,7 +1182,9 @@
 SimpleToadletServer.enablePersistentConnections=Abilita connessioni HTTP 
persistenti(Leggere la descrizione)
 SimpleToadletServer.enablePersistentConnectionsLong=Non abilitare questa 
opzione tranne nel caso in cui il browser sia configurato per usare molte 
connessioni anche se sono persistenti.
 SimpleToadletServer.enabled=Abilita FProxy
-SimpleToadletServer.enabledLong=Abilita FProxy e relativi servizi HTTP
+SimpleToadletServer.enabledLong=Abilitare FProxy e relativi servizi HTTP?
+SimpleToadletServer.hasCompletedWizard=E' gi? stata completata la 
configurazione automatica?
+SimpleToadletServer.hasCompletedWizardLong=Se la configurazione automatica di 
Freenet non ? ancora stata completata, FProxy rediriger? tutte le richieste 
alla pagina apposita.
 SimpleToadletServer.illegalCSSName=Il nome CSS non pu? contenere i catarreri 
"barra" (/ slash) e "due punti" ( : colon)
 SimpleToadletServer.panicButton=Mostra bottone Emergenza
 SimpleToadletServer.panicButtonLong=Mostra il bottone Emergenza nella pagina 
della Coda. Se usato, Il bottone Emergenza rimuove tutte le richieste che non 
hanno ricevuto conferma.
@@ -1203,7 +1211,7 @@
 StatisticsToadlet.bandwidthTitle=Ampiezza di banda
 StatisticsToadlet.cpus=Numero CPU: ${count}
 StatisticsToadlet.debuggingBytes=Debugging bytes: ${netColoring} colorazione 
rete, ${ping} ping, ${probe} richieste probe, ${routed} messaggi di testo 
instradati.
-StatisticsToadlet.fullTitle=Statistiche del nodo: ${name}
+StatisticsToadlet.fullTitle=Statistiche di ${name}
 StatisticsToadlet.getLogs=Scarica il pi? recente logfile del nodo
 StatisticsToadlet.inputRate=Input: ${rate}/second (of ${max}/second)
 StatisticsToadlet.insertOutput=Output inserzioni (carico utile escluso): CHK 
${chk} SSK ${ssk}.
@@ -1220,7 +1228,7 @@
 StatisticsToadlet.osArch=Architettura OS: ${arch}
 StatisticsToadlet.osName=Sistema Operativo: ${name}
 StatisticsToadlet.osVersion=Versione Sistema Operativo: ${version}
-StatisticsToadlet.outputRate=Output: ${rate} al secondo (di ${max} al secondo)
+StatisticsToadlet.outputRate=Output: ${rate}/second (of ${max}/second)
 StatisticsToadlet.payloadOutput=Output Carico Utile: ${total} (${rate}/second) 
(${percent}%)
 StatisticsToadlet.peerStatsTitle=Statistiche peer
 StatisticsToadlet.priority=Priorit?
@@ -1232,8 +1240,8 @@
 StatisticsToadlet.statisticGatheringTitle=Raccolta Statistiche
 StatisticsToadlet.swapOutput=Output Scambio: ${total}.
 StatisticsToadlet.threadDumpButton=Genera Thread Dump
-StatisticsToadlet.threads=Threads correnti: ${running}/${max}
-StatisticsToadlet.threadsByPriority=Thread in ordine di prorit?
+StatisticsToadlet.threads=Thread in uso: ${running}/${max}
+StatisticsToadlet.threadsByPriority=Pooled threads in ordine di prorit?
 StatisticsToadlet.totalInput=Input Totale: ${total} (${rate}/second)
 StatisticsToadlet.totalOutput=Output Totale: ${total} (${rate}/second)
 StatisticsToadlet.totalOverhead=Totale overhead di non-richieste: ${rate}/sec 
(${percent}%).
@@ -1297,7 +1305,7 @@
 TranslationToadlet.bracketUpdateTranslation=(aggiorna traduzione)
 TranslationToadlet.confirmRemoveOverride=Conferma: elimina chiave di 
traduzione : (${key} - ${value}) ?
 TranslationToadlet.contributingToLabelWithLang=Stai contribuendo alla 
traduzione: ${lang}:
-TranslationToadlet.currentTranslationLabel=Traduzione corrente
+TranslationToadlet.currentTranslationLabel=Traduzione attuale
 TranslationToadlet.downloadTranslationsFile=Scarica il file della traduzione
 TranslationToadlet.gotoNext=Vai alla prossima stringa non tradotta?
 TranslationToadlet.hideAlreadyTranslated=Nascondi stringhe tradotte
@@ -1313,8 +1321,8 @@
 TranslationToadlet.translationUpdateTitle=Aggiornamento traduzione
 TranslationToadlet.translationUpdatedTitle=Traduzione aggiornata!
 TranslationToadlet.updateTranslationCommand=Aggiorna traduzione
-UnknownContentTypeException.explanation=Il nodo non ha informazioni su questo 
MIME type. Ci? potrebbe comportare una reazione pericolosa da parte del browser 
in risposta al download di questo file. Per esempio, molti formati possono 
contenere immagini o video inclusi (embedded) che vengono scaricati dal web: 
ci? espone l'utente al rischio di rivelare il proprio indirizzo IP ad un 
eventuale avversario (per esempio un avversario che gestisca il il sito web dal 
quale le immagini o video ecc. vengono scaricati, o uno che abbia in qualche 
modo ottenuto accesso ai log del sito stesso). Hyperlinks e scripting sono 
entrambi ugualmente pericolosi, per lo stesso motivo, ed anche per alcuni altri.
-UnknownContentTypeException.title=Tipo di contenuto (content type) sconosciuto 
e pertanto potenzialmente pericoloso: ${type}
+UnknownContentTypeException.explanation=Il nodo non ha informazioni su questo 
MIME type. Ci? potrebbe comportare una reazione pericolosa da parte del browser 
in risposta al download di questo file. Per esempio, molti formati possono 
contenere immagini o video inclusi (embedded) che vengono scaricati dal web: 
ci? espone l'utente al rischio di rivelare il proprio indirizzo IP ad un 
eventuale avversario (per esempio un avversario che gestisca il il sito web dal 
quale le immagini o video ecc. vengono scaricati, o uno che abbia in qualche 
modo ottenuto accesso ai log del sito stesso). Hyperlinks e scripting sono 
entrambi ugualmente pericolosi per lo stesso motivo, oltre che per alcuni altri.
+UnknownContentTypeException.title=Contenuto di tipo sconosciuto e 
potenzialmente pericoloso: ${type}
 UpdateDeployContext.cannotUpdateNoExtJar=Freenet-ext.jar non trovata in 
wrapper.conf: (freenet.jar trovata: ${mainFilename})
 UpdateDeployContext.cannotUpdateNoJars=Non ? stato possibile trovare i file 
jar di Freenet in wrapper.conf
 UpdateDeployContext.cannotUpdateNoMainJar=Non ? stato possibile trovare 
freenet.jar in wrapper.conf (freenet-ext.jar non trovata: ${extFilename})
@@ -1352,7 +1360,7 @@
 UserAlertManager.minorCountLabel=Minori:
 UserAlertManager.totalLabel=Totale:
 UserAlertManager.warningCountLabel=Avvertenze:
-UserAlertsToadlet.titleWithName=Avvertenze per ${name}
+UserAlertsToadlet.titleWithName=Messaggi di stato del nodo ${name}
 WelcomeToadlet.activityTitle=Attivit? in corso
 WelcomeToadlet.alertsSummary=Sommario avvertenze
 WelcomeToadlet.arkFetchCount=ARK Fetchers: ${total}

Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties        
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties        
2008-11-06 13:53:57 UTC (rev 23351)
@@ -653,6 +653,7 @@
 Node.buggyJVMTitle=JVM ????
 Node.buggyJVMWithLink=????? JVM ??(${version})???${link}??${/link}. ????????, 
?????? OutOfMemoryError ??. ?????? Sun ???? Java 1.4.2_13 ?, 1.5.0_10 ?, ?? 1.6 
?(????).
 Node.bwlimitMustBePositive=?????????
+Node.connectToSeednodesCannotBeChangedMustDisableOpennetOrReboot=????????: 
???????(opennet)?????, ??????????????, ???????.
 Node.databaseMemory=????????????
 Node.databaseMemoryLong=????????????????????. 0 ??????(????? 30% ??????)
 Node.deadlockTitle=???????? JVM ???????????
@@ -724,6 +725,10 @@
 Node.storeDirectory=????
 Node.storeDirectoryLong=???????????
 Node.storeMaxMemTooHigh=????????? 80% ???? BDB ???!
+Node.storePreallocate=???????????
+Node.storePreallocateLong=???????????
+Node.storeSaltHashResizeOnStart=???????????(??? salt-hash)
+Node.storeSaltHashResizeOnStartLong=??????????????(??? salt-hash). ?????, 
??????????????????. ?????"????"?????????, ???????????????????????.
 Node.storeSize=?????????
 Node.storeSizeLong=?????????
 Node.storeType=????(????)
@@ -735,8 +740,8 @@
 Node.tooSmallMTU=MTU ??
 Node.tooSmallMTULong=?????????????(MTU)??? ${mtu} ???. Freenet ??? MTU ?? 
${minMTU} ???????????: Freenet ??????, ????????. ?????????????.
 Node.tooSmallMTUShort=????: ????? MTU ??, Freenet ??????. ???????.
-Node.withAnnouncement=??????????????????
-Node.withAnnouncementLong=???????????????????? ???????????, ???????????.
+Node.withAnnouncement=??????????????????(????????????, ?????)
+Node.withAnnouncementLong=???????????????????? ?????????(opennet, ??????, 
?????????????, ????? Freenet ??), ???? Freenet ????????????????, ?????????. 
????, ??????, ???????????, ????????: ???????????????, ??????????????, 
??????????????(NAT)??, ????????????. ???????????, ??????????, ????????????.
 NodeClientCore.couldNotFindOrCreateDir=?????????
 NodeClientCore.downloadAllowedDirs=?????????
 NodeClientCore.downloadAllowedDirsLong=?????????????, ??????. ???? downloads 
?????????, ???????????????????, ??? all ??????????????. ??! ????? all ??, 
?????????????????, ??????????????!
@@ -817,7 +822,7 @@
 NotEnoughNiceLevelsUserAlert.short=???????????! ?????????????? Freenet.
 NotEnoughNiceLevelsUserAlert.title=???????????!
 OpennetConnectionsToadlet.fullTitle=${name} ? ${counts} ????(??????)
-OpennetConnectionsToadlet.peersListTitle=??????????(???????????????????)
+OpennetConnectionsToadlet.peersListTitle=??????????(?????????????, 
????????????)
 OpennetConnectionsToadlet.successTime=?????????????? CHK ???
 OpennetConnectionsToadlet.successTimeTitle=??????
 OpennetUserAlert.warning=Freenet ????????????. ????????????? Freenet, 
?????????????. ???????????????, ????????????????????, ????????????. ????? 5 ? 
10 ???????(??????????????, ???????????????), ???????????, ?? Freenet 
????????????????.
@@ -998,10 +1003,11 @@
 QueueToadlet.identifier=???
 QueueToadlet.insertAs=???:
 QueueToadlet.insertFile=????? Freenet
-QueueToadlet.insertFileBrowseLabel=?????????
+QueueToadlet.insertFileBrowseButton=????
+QueueToadlet.insertFileBrowseLabel=??????????
 QueueToadlet.insertFileCompressLabel=??
 QueueToadlet.insertFileInsertFileLabel=????
-QueueToadlet.insertFileLabel=??????????(???!)
+QueueToadlet.insertFileLabel=??????????(??!)
 QueueToadlet.insertFileResetForm=????
 QueueToadlet.key=??
 QueueToadlet.legend=??
@@ -1153,6 +1159,8 @@
 SimpleToadletServer.enablePersistentConnectionsLong=?????????, 
??????????????????? HTTP ??, ????????.
 SimpleToadletServer.enabled=???? FProxy?
 SimpleToadletServer.enabledLong=????? FProxy ???? HTTP ??
+SimpleToadletServer.hasCompletedWizard=????????????
+SimpleToadletServer.hasCompletedWizardLong=???????????? ?????, fproxy 
????????????????.
 SimpleToadletServer.illegalCSSName=CSS ???????????!
 SimpleToadletServer.panicButton=?????????
 SimpleToadletServer.panicButtonLong=???????'????', ????????????????, ?????????.

Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties        
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties        
2008-11-06 13:53:57 UTC (rev 23351)
@@ -652,6 +652,7 @@
 Node.buggyJVMTitle=JVM ????
 Node.buggyJVMWithLink=????? JVM ??(${version})???${link}??${/link}. ?????????, 
?????? OutOfMemoryError ??. ?????? Sun ???? Java 1.4.2_13 ?, 1.5.0_10 ?, ?? 1.6 
?(????).
 Node.bwlimitMustBePositive=?????????
+Node.connectToSeednodesCannotBeChangedMustDisableOpennetOrReboot=????????: 
???????(opennet)?????, ??????????????, ???????.
 Node.databaseMemory=?????????????
 Node.databaseMemoryLong=?????????????????????. 0 ??????(????? 30% ???????)
 Node.deadlockTitle=???????? JVM ???????????
@@ -723,6 +724,10 @@
 Node.storeDirectory=????
 Node.storeDirectoryLong=???????????
 Node.storeMaxMemTooHigh=????????? 80% ????? BDB ???!
+Node.storePreallocate=???????????
+Node.storePreallocateLong=???????????
+Node.storeSaltHashResizeOnStart=???????????(??? salt-hash)
+Node.storeSaltHashResizeOnStartLong=??????????????(??? salt-hash). ?????, 
??????????????????. ?????"????"?????????, ???????????????????????.
 Node.storeSize=?????????
 Node.storeSizeLong=?????????
 Node.storeType=????(????)
@@ -734,8 +739,8 @@
 Node.tooSmallMTU=MTU ??
 Node.tooSmallMTULong=?????????????(MTU)??? ${mtu} ????. Freenet ??? MTU ?? 
${minMTU} ????????????: Freenet ??????, ????????. ?????????????.
 Node.tooSmallMTUShort=????: ????? MTU ??, Freenet ??????. ???????.
-Node.withAnnouncement=??????????????????
-Node.withAnnouncementLong=???????????????????? ???????????, ???????????.
+Node.withAnnouncement=??????????????????(????????????, ?????)
+Node.withAnnouncementLong=???????????????????? ?????????(opennet, ??????, 
?????????????, ????? Freenet ??), ???? Freenet ????????????????, ?????????. 
????, ??????, ???????????, ????????: ???????????????, ??????????????, 
??????????????(NAT)??, ?????????????. ???????????, ??????????, ????????????.
 NodeClientCore.couldNotFindOrCreateDir=?????????
 NodeClientCore.downloadAllowedDirs=?????????
 NodeClientCore.downloadAllowedDirsLong=?????????????, ??????. ???? downloads 
?????????, ???????????????????, ??? all ??????????????. ??! ????? all ??, 
?????????????????, ?????????????!
@@ -816,7 +821,7 @@
 NotEnoughNiceLevelsUserAlert.short=???????????! ?????????????? Freenet.
 NotEnoughNiceLevelsUserAlert.title=???????????!
 OpennetConnectionsToadlet.fullTitle=${name} ? ${counts} ????(??????)
-OpennetConnectionsToadlet.peersListTitle=??????????(???????????????????)
+OpennetConnectionsToadlet.peersListTitle=??????????(?????????????, 
????????????)
 OpennetConnectionsToadlet.successTime=?????????????? CHK ???
 OpennetConnectionsToadlet.successTimeTitle=??????
 OpennetUserAlert.warning=Freenet ????????????. ????????????? Freenet, 
?????????????. ???????????????, ????????????????????, ????????????. ????? 5 ? 
10 ???????(??????????????, ???????????????), ???????????, ?? Freenet 
????????????????.
@@ -997,10 +1002,11 @@
 QueueToadlet.identifier=???
 QueueToadlet.insertAs=???:
 QueueToadlet.insertFile=????? Freenet
-QueueToadlet.insertFileBrowseLabel=?????????
+QueueToadlet.insertFileBrowseButton=????
+QueueToadlet.insertFileBrowseLabel=??????????
 QueueToadlet.insertFileCompressLabel=??
 QueueToadlet.insertFileInsertFileLabel=????
-QueueToadlet.insertFileLabel=??????????(???!)
+QueueToadlet.insertFileLabel=??????????(??!)
 QueueToadlet.insertFileResetForm=????
 QueueToadlet.key=??
 QueueToadlet.legend=??
@@ -1152,6 +1158,8 @@
 SimpleToadletServer.enablePersistentConnectionsLong=?????????, 
??????????????????? HTTP ??, ????????.
 SimpleToadletServer.enabled=???? FProxy?
 SimpleToadletServer.enabledLong=????? FProxy ???? HTTP ??
+SimpleToadletServer.hasCompletedWizard=????????????
+SimpleToadletServer.hasCompletedWizardLong=???????????? ?????, fproxy 
????????????????.
 SimpleToadletServer.illegalCSSName=CSS ???????????!
 SimpleToadletServer.panicButton=?????????
 SimpleToadletServer.panicButtonLong=???????'????', ????????????????, ?????????.

Modified: trunk/freenet/src/freenet/node/Announcer.java
===================================================================
--- trunk/freenet/src/freenet/node/Announcer.java       2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/Announcer.java       2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -11,7 +11,9 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.InetAddress;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Vector;

 import freenet.io.comm.PeerParseException;
@@ -33,7 +35,6 @@
  * @author toad
  */
 public class Announcer {
-
        private static boolean logMINOR;
        private final Node node;
        private final OpennetManager om;
@@ -47,7 +48,7 @@
        private int sentAnnouncements;
        private long startTime;
        private long timeAddedSeeds;
-       static final long MIN_ADDED_SEEDS_INTERVAL = 60*1000;
+       private static final long MIN_ADDED_SEEDS_INTERVAL = 60*1000;
        /** After we have sent 3 announcements, wait for 30 seconds before 
sending 3 more if we still have no connections. */
        static final int COOLING_OFF_PERIOD = 30*1000;
        /** Identities of nodes we have announced to */
@@ -55,7 +56,7 @@
        /** IPs of nodes we have announced to. Maybe this should be 
first-two-bytes, but I'm not sure how to do that with IPv6. */
        private final HashSet<InetAddress> announcedToIPs;
        /** How many nodes to connect to at once? */
-       static final int CONNECT_AT_ONCE = 15;
+       private static final int CONNECT_AT_ONCE = 15;
        /** Do not announce if there are more than this many opennet peers 
connected */
        private static final int MIN_OPENNET_CONNECTED_PEERS = 10;
        private static final long NOT_ALL_CONNECTED_DELAY = 60*1000;
@@ -75,7 +76,7 @@
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
        }

-       public void start() {
+       protected void start() {
                if(!node.isOpennetEnabled()) return;
                registerAlert();
                int darkPeers = node.peers.getDarknetPeers().length;
@@ -118,7 +119,7 @@
                boolean announceNow = false;
                if(logMINOR)
                        Logger.minor(this, "Connecting some seednodes...");
-               Vector/*<SimpleFieldSet>*/ seeds = 
Announcer.readSeednodes(node.nodeDir);
+               List<SimpleFieldSet> seeds = 
Announcer.readSeednodes(node.nodeDir);
                long now = System.currentTimeMillis();
                synchronized(this) {
                        if(now - timeAddedSeeds < MIN_ADDED_SEEDS_INTERVAL) 
return;
@@ -180,13 +181,13 @@
        }

        // Synchronize to protect announcedToIdentities and prevent running in 
parallel.
-       private synchronized int connectSomeNodesInner(Vector seeds) {
+       private synchronized int connectSomeNodesInner(List<SimpleFieldSet> 
seeds) {
                if(logMINOR)
                        Logger.minor(this, "Connecting some seednodes from 
"+seeds.size());
                int count = 0;
                while(count < CONNECT_AT_ONCE) {
                        if(seeds.size() == 0) break;
-                       SimpleFieldSet fs = (SimpleFieldSet) 
seeds.remove(node.random.nextInt(seeds.size()));
+                       SimpleFieldSet fs = 
seeds.remove(node.random.nextInt(seeds.size()));
                        try {
                                SeedServerPeerNode seed =
                                        new SeedServerPeerNode(fs, node, 
om.crypto, node.peers, false, om.crypto.packetMangler);
@@ -220,9 +221,9 @@
                return count;
        }

-       public static Vector readSeednodes(File nodeDir) {
+       public static List<SimpleFieldSet> readSeednodes(File nodeDir) {
                File file = new File(nodeDir, "seednodes.fref");
-               Vector<SimpleFieldSet> list = new Vector<SimpleFieldSet>();
+               List<SimpleFieldSet> list = new ArrayList<SimpleFieldSet>();
                FileInputStream fis = null;
                try {
                        fis = new FileInputStream(file);
@@ -245,7 +246,7 @@
                }
        }

-       public void stop() {
+       protected void stop() {
                // Do nothing at present
        }

@@ -303,9 +304,9 @@
        }

        private boolean ignoreIPUndetected;
-       static final int FORCE_ANNOUNCEMENT_NO_IP = 120*1000;
+       private static final int FORCE_ANNOUNCEMENT_NO_IP = 120*1000;
        /** 1 minute after we have enough peers, remove all seednodes left 
(presumably disconnected ones) */
-       static final int FINAL_DELAY = 60*1000;
+       private static final int FINAL_DELAY = 60*1000;
        /** But if we don't have enough peers at that point, wait another 
minute and if the situation has not improved, reannounce. */
        static final int RETRY_DELAY = 60*1000;
        private boolean started = false;
@@ -313,7 +314,7 @@
        private long toldUserNoIP = -1;
        private boolean dontKnowOurIPAddress;

-       public void maybeSendAnnouncement() {
+       protected void maybeSendAnnouncement() {
                synchronized(this) {
                        if(!started) return;
                }
@@ -437,8 +438,8 @@
        }

        private synchronized void addAnnouncedIPs(InetAddress[] addrs) {
-               for(int i=0;i<addrs.length;i++)
-                       announcedToIPs.add(addrs[i]);
+               for (InetAddress addr : addrs)
+               announcedToIPs.add(addr);
        }

        /**
@@ -461,7 +462,7 @@
                return !hasNonLocalAddresses;
        }

-       public void sendAnnouncement(final SeedServerPeerNode seed) {
+       protected void sendAnnouncement(final SeedServerPeerNode seed) {
                if(!node.isOpennetEnabled()) {
                        if(logMINOR)
                                Logger.minor(this, "Not announcing to "+seed+" 
because opennet is disabled");
@@ -536,8 +537,7 @@
                node.executor.execute(sender, "Announcer to "+seed);
        }

-       public class AnnouncementUserAlert implements UserAlert {
-
+       class AnnouncementUserAlert implements UserAlert {
                public String dismissButtonText() {
                        return L10n.getString("UserAlert.hide");
                }
@@ -582,9 +582,8 @@
                                        runningAnnouncements = 
Announcer.this.runningAnnouncements;

                                }
-                               Vector nodes = 
node.peers.getSeedServerPeersVector();
-                               for(int i=0;i<nodes.size();i++) {
-                                       SeedServerPeerNode seed = 
(SeedServerPeerNode) nodes.get(i);
+                               List<SeedServerPeerNode> nodes = 
node.peers.getSeedServerPeersVector();
+                               for(SeedServerPeerNode seed : nodes) {
                                        if(seed.isConnected())
                                                connectedSeednodes++;
                                        else
@@ -593,7 +592,7 @@
                                if(dontKnowAddress) {
                                        sb.append(l10n("dontKnowAddress"));
                                } else {
-                                       sb.append(l10n("announceDetails", 
+                                       sb.append(l10n("announceDetails",
                                                        new String[] { 
"addedNodes", "refusedNodes", "recentSentAnnouncements", 
"runningAnnouncements", "connectedSeednodes", "disconnectedSeednodes" },
                                                        new String[] {
                                                        
Integer.toString(addedNodes),
@@ -658,12 +657,11 @@
                return L10n.getString("Announcer."+key);
        }

-       public String l10n(String key, String[] patterns, String[] values) {
+       protected String l10n(String key, String[] patterns, String[] values) {
                return L10n.getString("Announcer."+key, patterns, values);
        }

-       public String l10n(String key, String pattern, String value) {
+       private String l10n(String key, String pattern, String value) {
                return L10n.getString("Announcer."+key, pattern, value);
        }
-
 }

Copied: trunk/freenet/src/freenet/node/BandwidthUsageHistory.java (from rev 
23341, trunk/freenet/src/freenet/node/BandwidthUsageHistory.java)
===================================================================
--- trunk/freenet/src/freenet/node/BandwidthUsageHistory.java                   
        (rev 0)
+++ trunk/freenet/src/freenet/node/BandwidthUsageHistory.java   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -0,0 +1,234 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.node;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * A fixed-size list of bandwidth usage measurements.
+ * 
+ * @author xor
+ * 
+ */
+public class BandwidthUsageHistory implements 
Iterable<BandwidthUsageHistory.BandwidthUsageSample> {
+
+       public class BandwidthUsageSample {
+               private float value;
+               private long time;
+
+               public BandwidthUsageSample(float newValue, long newTime) {
+                       value = newValue;
+                       time = newTime;
+               }
+
+               public float getValue() {
+                       return (value);
+               }
+
+               public float setValue(float newValue, long newTime) {
+                       time = newTime;
+                       return (value = newValue);
+               }
+
+               public long getTime() {
+                       return (time);
+               }
+       }
+
+       protected final BandwidthUsageSample[] data;
+       protected int slot;
+
+       public BandwidthUsageHistory(int numberOfSamples) {
+               data = new BandwidthUsageSample[numberOfSamples];
+               slot = 0;
+       }
+
+       /**
+        * Create a new BandWidthUsageHistory from an existing array of 
BandwidthUsageSample. 
+        * @param newData The data for the new object.
+        * @param bNextSlotIsNotIndex0 If set to false, the new object assumes 
that slot 0 is the oldest sample. If set to true, the next slot is searched 
(time expensive!).
+        */
+       protected BandwidthUsageHistory(BandwidthUsageSample[] newData, boolean 
bNextSlotIsNotIndex0) {
+               if (newData == null)
+                       throw new IllegalArgumentException("newData == null");
+
+               data = newData;
+
+               /* TODO: Remove if it is not needed by any caller. */
+               if(bNextSlotIsNotIndex0)
+                       slot = getNextFreeSlot();
+               else {
+                       slot = 0;
+                       assert(getNextFreeSlot() == slot);      /* Catch wrong 
use of this constructor. */
+               }
+       }
+       
+       protected BandwidthUsageHistory(BandwidthUsageSample[] newData, int 
newSlot) {
+               if (newData == null)
+                       throw new IllegalArgumentException("newData == null");
+               if (newSlot < 0 || newSlot >= newData.length)
+                       throw new IllegalArgumentException("newSlot invalid: " 
+ newSlot);
+
+               data = newData;
+               slot = newSlot;
+               
+               assert (getNextFreeSlot() == slot); /* Catch wrong use of this 
constructor. */
+       }
+
+       public int getSampleCount() {
+               return(data.length);
+       }
+       
+       /**
+        * Creates a new BandwidthUsageHistory with the same sample data but 
different space for samples.
+        * @param newSampleCount The amount of samples for the new object. If 
<code>newSampleCount</code> is less than the current sample count, the oldest 
samples are dropped.
+        */
+       public synchronized BandwidthUsageHistory clone(int newSampleCount) {
+               if(newSampleCount < 1)
+                       throw new IllegalArgumentException("newSampleCount < 
1");
+               
+               BandwidthUsageSample[] newData = new 
BandwidthUsageSample[newSampleCount];
+               int newIdx = 0;
+               
+               for(int idx = newSampleCount >= data.length ? 0 : (data.length 
- newSampleCount); idx < data.length; idx++) {
+                       newData[newIdx++] = getSample(idx);
+               }
+               newIdx %= newData.length;
+               
+               return (new BandwidthUsageHistory(newData, newIdx));
+       }
+
+       public synchronized void putValue(float value, long time) {
+               slot = (slot + 1) % data.length;
+
+               if (data[slot] == null)
+                       data[slot] = new BandwidthUsageSample(value, time);
+               else
+                       data[slot].setValue(value, time);
+       }
+
+       /**
+        * Returns the <code>BandwidthUsageSample</code> with index 
<code>idx</code> from this object. The index is zero based, index 0 being the
+        * oldest bandwidth sample.
+        * Do not modify it, the original object is returned instead of a copy 
to prevent creation of large amounts of BandwidthUsageSample-objects.
+        * @param idx The index of the sample, index 0 being the oldest 
bandwidth sample.
+        * @return The BandwidthUsageSample with the desired index, null if 
there is no such element yet.
+        */
+       public synchronized BandwidthUsageSample getSample(int idx) {
+               /* It should not be necessary for clients of this class to use 
values of idx greater than data.length, it will work however. */
+               assert (idx >= 0 && idx < data.length);
+               return(data[(slot + idx) % data.length]);
+       }
+
+       public synchronized float getAverage() {
+               float sum = 0.0f;
+               int count = 0;
+               for (int idx = 0; idx < data.length; ++idx) {
+                       if (data[slot] != null) {
+                               sum += data[slot].getValue();
+                               ++count;
+                       }
+               }
+               return(count != 0 ? (sum / count) : 0.0f);
+       }
+
+       /**
+        * Calculates a new <code>BandwidthUsageHistory</code> with a smaller 
amount of samples. Each sample in the new
+        * <code>BandwidthUsageHistory</code> will be calculated as an average 
value over <code>this.getSampleCount() / numberOfSamples</code>
+        * samples. If <code>numberOfSamples</code> does not divide 
<code>this.getSampleCount()</code> then the oldest remaining samples from this
+        * object will not be included in the calculation.
+        * 
+        * @param numberOfSamples
+        *            The number of samples which the new
+        *            <code>BandwidthUsageHistory</code> should have.
+        * @return The new <code>BandwidthUsageHistory</code>.
+        */
+       public synchronized BandwidthUsageHistory 
getHistoryWithReducedSampleAmount(int numberOfSamples) {
+               if (numberOfSamples > data.length)
+                       throw new IllegalArgumentException("numberOfSamples > 
this.data.length");
+
+               BandwidthUsageSample[] newData = new 
BandwidthUsageSample[numberOfSamples];
+               int samplesPerValue = data.length / numberOfSamples;
+               
+               float value = 0.0f;
+               long startTime = -1; 
+               int cnt = 0;
+               int newIdx = 0;
+
+               /* Start at data.length % numberOfSamples to drop the oldest 
remaining samples, see JavaDoc of this function */ 
+               for (int idx = data.length % numberOfSamples; idx < data.length 
&& data[idx] != null; ++idx) {
+                       BandwidthUsageSample s = getSample(idx);
+                       value += s.getValue();
+                       if(startTime < 0)
+                               startTime = s.getTime();
+               
+                       if(++cnt == samplesPerValue) {
+                               long endTime = s.getTime();
+                               assert(newIdx < newData.length); /* If this 
loop is constructed correctly we do not have to check newIdx. */ 
+                               newData[newIdx++] = new 
BandwidthUsageSample(value/samplesPerValue, startTime + (endTime-startTime) / 
2);
+                               cnt = 0;
+                               startTime = -1;
+                       }
+               }
+
+               return(new BandwidthUsageHistory(newData, false));
+       }
+
+       /**
+        * You HAVE TO use <code>synchronized(){}</code> on the 
BandwidthUsageHistory object when you use iterator()!
+        */
+       public Iterator<BandwidthUsageSample> iterator() {
+               return new Iterator<BandwidthUsageSample>() {
+                       int idx = 0;
+
+                       public boolean hasNext() {
+                               return(idx != data.length);
+                       }
+
+                       /**
+                        * Returns the next BandwidthUsageSample from this 
object. Do not modify it, the original object is returned instead of a copy to
+                        * prevent creation of large amounts of 
BandwidthUsageSample-objects.
+                        */
+                       public BandwidthUsageSample next() {
+                               if (!hasNext())
+                                       throw new NoSuchElementException();
+
+                               BandwidthUsageSample result = getSample(idx);
+                               ++idx;
+                               return(result);
+                       }
+
+                       /**
+                        * This cannot be used: The BandwidthUsageHistory 
contains a fixed amount of elements.
+                        */
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+
+               };
+       }
+       
+       /**
+        * Uses O(data.length) time! Should be avoided by passing over 
calculated values to constructors!
+        * Should be used in assert() statements.
+        * @return The index of the oldest sample in the data if the array was 
full, the next empty slot otherwise.
+        */
+       protected int getNextFreeSlot() {
+               int oldest = 0;
+               long oldestTime = Long.MAX_VALUE;
+
+               for (int idx = 0; idx < data.length; ++idx) {
+                       if (data[idx] == null) {
+                               oldest = idx;
+                               break;
+                       }
+                       else if (data[idx] != null && data[idx].getTime() < 
oldestTime) {
+                               oldest = idx;
+                       }
+               }
+               
+               return(oldest);
+       }
+}

Modified: trunk/freenet/src/freenet/node/CHKInsertSender.java
===================================================================
--- trunk/freenet/src/freenet/node/CHKInsertSender.java 2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/CHKInsertSender.java 2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -722,7 +722,7 @@
                        BackgroundTransfer[] transfers;
                        synchronized(backgroundTransfers) {
                                transfers = new 
BackgroundTransfer[backgroundTransfers.size()];
-                               transfers = (BackgroundTransfer[]) 
backgroundTransfers.toArray(transfers);
+                               transfers = 
backgroundTransfers.toArray(transfers);
                        }

                        // Wait for the outgoing transfers to complete.

Deleted: trunk/freenet/src/freenet/node/CPUAdjustingSwapRequestInterval.java
===================================================================
--- trunk/freenet/src/freenet/node/CPUAdjustingSwapRequestInterval.java 
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/CPUAdjustingSwapRequestInterval.java 
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,73 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.node;
-
-import freenet.support.Logger;
-import freenet.support.io.NativeThread;
-
-/**
- * @author amphibian
- * 
- * Start at a given default value, adjust up or down according to
- * CPU usage for a given target % usage.
- */
-public final class CPUAdjustingSwapRequestInterval implements 
SwapRequestInterval, Runnable {
-
-    double currentValue;
-    int targetCPUUsage;
-    CPUUsageMonitor m;
-    static final double mulPerSecond = 1.05;
-    static final double max = Double.MAX_VALUE / mulPerSecond;
-    static final double min = Double.MIN_VALUE;
-    
-    CPUAdjustingSwapRequestInterval(double initialValue, int targetCPUUsage) {
-        currentValue = initialValue;
-        this.targetCPUUsage = targetCPUUsage;
-        m = new CPUUsageMonitor();
-    }
-
-    public void start() {
-        NativeThread t = new NativeThread(this, 
"CPUAdjustingSwapRequestInterval", NativeThread.MAX_PRIORITY, false);
-        t.setDaemon(true);
-        t.start();
-    }
-    
-    public synchronized int getValue() {
-        return (int)currentValue;
-    }
-
-    public void run() {
-        while(true) {
-            try {
-                long now = System.currentTimeMillis();
-                try {
-                    Thread.sleep(1000);
-                } catch (InterruptedException e) {
-                }
-                int cpuUsage = m.getCPUUsage();
-                long endSleepTime = System.currentTimeMillis();
-                double mul = Math.pow(mulPerSecond, 
((double)(endSleepTime-now))/1000);
-                if(cpuUsage == -1) {
-                    Logger.error(this, "Cannot auto-adjust based on CPU 
usage");
-                    return;
-                }
-                synchronized(this) {
-                    if(cpuUsage > targetCPUUsage) {
-                        if(currentValue < max)
-                            currentValue *= mul; // 5% slower per second
-                    } else if(cpuUsage < targetCPUUsage) {
-                        if(currentValue > min)
-                            currentValue /= mul; // 5% faster per second
-                    }
-                    if(currentValue < min) currentValue = min;
-                    if(currentValue > max) currentValue = max;
-                    if(Logger.shouldLog(Logger.MINOR, this))
-                       Logger.minor(this, "CPU usage: "+cpuUsage+" target 
"+targetCPUUsage+" current value: "+currentValue);
-                }
-            } catch (Throwable t) {
-                Logger.error(this, "Caught "+t+" in "+this, t);
-            }
-        }
-    }
-}

Deleted: trunk/freenet/src/freenet/node/CPUUsageMonitor.java
===================================================================
--- trunk/freenet/src/freenet/node/CPUUsageMonitor.java 2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/CPUUsageMonitor.java 2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -1,160 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.node;
-
-import java.io.BufferedReader;
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-import freenet.support.Logger;
-
-/**
- * @author amphibian
- * 
- * Class to determine the current CPU usage.
- */
-public class CPUUsageMonitor {
-
-    static class TickStat {
-
-        long user;
-
-        long nice;
-
-        long system;
-
-        long spare;
-
-        boolean reportedFailedProcOpen = false;
-        boolean reportedFailedProcParse = false;
-        
-        boolean read(File f) {
-            String firstline;
-            FileInputStream fis = null;
-            try {
-                fis = new FileInputStream(f);
-                InputStreamReader ris = new InputStreamReader(fis);
-                BufferedReader br = new BufferedReader(ris);
-                firstline = br.readLine();
-                if(firstline == null) throw new EOFException();
-                ris.close();
-                br.close();
-            } catch (IOException e) {
-                if(!reportedFailedProcOpen)
-                    Logger.error(this, "Failed to open /proc/stat: "+e, e);
-                reportedFailedProcOpen = true;
-                if(fis != null) try {
-                    fis.close();
-                } catch (IOException e1) {
-                    Logger.error(this, "Failed to close /proc/stat: "+e, e);
-                }
-                return false;
-            }
-            Logger.debug(this, "Read first line: " + firstline);
-            if (!firstline.startsWith("cpu")) return false;
-            firstline = firstline.substring("cpu".length()).trim();
-            String[] split = firstline.split(" ");
-
-            long[] numbers = new long[split.length];
-            for(int i=0;i<split.length;i++) {
-                try {
-                    numbers[i] = Long.parseLong(split[i]);
-                } catch (NumberFormatException e) {
-                    if(!reportedFailedProcParse)
-                        Logger.error(this, "Failed to parse /proc: "+e, e);
-                    reportedFailedProcParse = true;
-                    return false;
-                }
-            }
-            
-            if(split.length == 4) {
-                // Linux 2.4/2.2
-                user = numbers[0];
-                nice = numbers[1];
-                system = numbers[2];
-                spare = numbers[3];
-            } else if(split.length == 8) {
-                // Linux 2.6
-                // user, nice, system, idle, iowait, irq, softirq, steal
-                // No idea what steal is and it's 0 on my box anyway
-                user = numbers[0];
-                system = numbers[2] + numbers[5] + numbers[6];
-                nice = numbers[1];
-                spare = numbers[3] + numbers[4];
-            } else {
-                if(!reportedFailedProcParse)
-                    Logger.error(this, "Failed to parse /proc: unrecognized 
number of elements: "+split.length);
-                reportedFailedProcParse = true;
-                return false;
-            }
-            Logger.debug(this, "Read from file: user " + user + " nice " + nice
-                    + " system " + system + " spare " + spare);
-            return true;
-        }
-
-        int calculate(TickStat old) {
-            long userdiff = user - old.user;
-            long nicediff = nice - old.nice;
-            long systemdiff = system - old.system;
-            long sparediff = spare - old.spare;
-
-            if (userdiff + nicediff + systemdiff + sparediff <= 0) return 0;
-            Logger.debug(this, "User changed by " + userdiff + ", Nice: "
-                    + nicediff + ", System: " + systemdiff + ", Spare: "
-                    + sparediff);
-            int usage = (int) ((100 * (userdiff + nicediff + systemdiff)) / 
(userdiff
-                    + nicediff + systemdiff + sparediff));
-            Logger.debug(this, "CPU usage: " + usage);
-            return usage;
-        }
-
-        void copyFrom(TickStat old) {
-            user = old.user;
-            nice = old.nice;
-            system = old.system;
-            spare = old.spare;
-        }
-    }
-
-    int lastCPULoadEstimate = 0;
-
-    long lastCPULoadEstimateTime = 0;
-
-    File proc = File.separator.equals("/") ? new File("/proc/stat") : null;
-
-    TickStat tsOld = new TickStat();
-
-    TickStat tsNew = null;
-
-    public int getCPUUsage() {
-        if(File.separatorChar != '/')
-            return -1;
-        long now = System.currentTimeMillis();
-        if (now - lastCPULoadEstimateTime > 1000) {
-            try {
-                lastCPULoadEstimateTime = now;
-                if (tsNew == null) {
-                    tsOld.read(proc);
-                    tsNew = new TickStat();
-                } else {
-                    if (!tsNew.read(proc)) {
-                       if(Logger.shouldLog(Logger.MINOR, this))
-                               Logger.minor(this, "Failed to parse /proc");
-                        return -1;
-                    }
-                    lastCPULoadEstimate = tsNew.calculate(tsOld);
-                    tsOld.copyFrom(tsNew);
-                }
-            } catch (Throwable t) {
-                lastCPULoadEstimate = -1;
-                Logger.normal(this, "Failed real-CPU-load estimation: "
-                        + t, t);
-            }
-        }
-        return lastCPULoadEstimate;
-    }
-}
\ No newline at end of file

Deleted: trunk/freenet/src/freenet/node/DSAPublicKeyDatabase.java
===================================================================
--- trunk/freenet/src/freenet/node/DSAPublicKeyDatabase.java    2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/DSAPublicKeyDatabase.java    2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,20 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.node;
-
-import freenet.crypt.DSAPublicKey;
-
-/**
- * Interface for a DSA public key lookup service.
- */
-public interface DSAPublicKeyDatabase {
-       
-       /**
-        * Lookup a key by its hash.
-        * @param hash
-        * @return The key, or null.
-        */
-       public DSAPublicKey lookupKey(byte[] hash);
-
-}

Modified: trunk/freenet/src/freenet/node/DarknetPeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/DarknetPeerNode.java 2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/DarknetPeerNode.java 2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -121,7 +121,7 @@
        /**
         * 
         * Normally this is the address that packets have been received from 
from this node.
-        * However, if ignoreSourcePort is set, we will search for a similar 
address with a different port 
+        * However, if ignoreSourcePort is set, we will search for a similar 
address with a different port
         * number in the node reference.
         */
        @Override
@@ -131,8 +131,7 @@
                        FreenetInetAddress addr = detectedPeer == null ? null : 
detectedPeer.getFreenetAddress();
                        int port = detectedPeer == null ? -1 : 
detectedPeer.getPort();
                        if(nominalPeer == null) return detectedPeer;
-                       for(int i=0;i<nominalPeer.size();i++) {
-                               Peer p = (Peer) nominalPeer.get(i);
+                       for(Peer p : nominalPeer) {
                                if(p.getPort() != port && 
p.getFreenetAddress().equals(addr)) {
                                        return p;
                                }
@@ -202,7 +201,7 @@
                        return PeerManager.PEER_NODE_STATUS_DISABLED;
                }
                int status = super.getPeerNodeStatus(now, backedOffUntil);
-               if(status == PeerManager.PEER_NODE_STATUS_CONNECTED || 
+               if(status == PeerManager.PEER_NODE_STATUS_CONNECTED ||
                                status == 
PeerManager.PEER_NODE_STATUS_CLOCK_PROBLEM ||
                                status == 
PeerManager.PEER_NODE_STATUS_ROUTING_BACKED_OFF ||
                                status == 
PeerManager.PEER_NODE_STATUS_CONN_ERROR ||
@@ -361,10 +360,10 @@
                }
                boolean gotError = false;
                boolean readResult = false;
-               for (int i = 0; i < extraPeerDataFiles.length; i++) {
+               for (File extraPeerDataFile : extraPeerDataFiles) {
                        Integer fileNumber;
                        try {
-                               fileNumber = new 
Integer(extraPeerDataFiles[i].getName());
+                               fileNumber = new 
Integer(extraPeerDataFile.getName());
                        } catch (NumberFormatException e) {
                                gotError = true;
                                continue;
@@ -372,7 +371,7 @@
                        synchronized(extraPeerDataFileNumbers) {
                                extraPeerDataFileNumbers.add(fileNumber);
                        }
-                       readResult = 
readExtraPeerDataFile(extraPeerDataFiles[i], fileNumber.intValue());
+                       readResult = readExtraPeerDataFile(extraPeerDataFile, 
fileNumber.intValue());
                        if(!readResult) {
                                gotError = true;
                        }
@@ -560,13 +559,13 @@
                int nextFileNumber = 0;
                synchronized(extraPeerDataFileNumbers) {
                        // Find the first free slot
-                       localFileNumbers = (Integer[]) 
extraPeerDataFileNumbers.toArray(new Integer[extraPeerDataFileNumbers.size()]);
+                       localFileNumbers = extraPeerDataFileNumbers.toArray(new 
Integer[extraPeerDataFileNumbers.size()]);
                        Arrays.sort(localFileNumbers);
-                       for (int i = 0; i < localFileNumbers.length; i++) {
-                               if(localFileNumbers[i].intValue() > 
nextFileNumber) {
+                       for (int localFileNumber : localFileNumbers) {
+                               if(localFileNumber > nextFileNumber) {
                                        break;
                                }
-                               nextFileNumber = localFileNumbers[i].intValue() 
+ 1;
+                               nextFileNumber = localFileNumber + 1;
                        }
                        extraPeerDataFileNumbers.add(nextFileNumber);
                }
@@ -647,10 +646,10 @@
                }
                Integer[] localFileNumbers;
                synchronized(extraPeerDataFileNumbers) {
-                       localFileNumbers = (Integer[]) 
extraPeerDataFileNumbers.toArray(new Integer[extraPeerDataFileNumbers.size()]);
+                       localFileNumbers = extraPeerDataFileNumbers.toArray(new 
Integer[extraPeerDataFileNumbers.size()]);
                }
-               for (int i = 0; i < localFileNumbers.length; i++) {
-                       deleteExtraPeerDataFile(localFileNumbers[i].intValue());
+               for (Integer localFileNumber : localFileNumbers) {
+                       deleteExtraPeerDataFile(localFileNumber.intValue());
                }
                extraPeerDataPeerDir.delete();
        }
@@ -744,11 +743,11 @@
                        Logger.minor(this, "Sending queued N2NMs for 
"+shortToString());
                Integer[] localFileNumbers;
                synchronized(queuedToSendN2NMExtraPeerDataFileNumbers) {
-                       localFileNumbers = (Integer[]) 
queuedToSendN2NMExtraPeerDataFileNumbers.toArray(new 
Integer[queuedToSendN2NMExtraPeerDataFileNumbers.size()]);
+                       localFileNumbers = 
queuedToSendN2NMExtraPeerDataFileNumbers.toArray(new 
Integer[queuedToSendN2NMExtraPeerDataFileNumbers.size()]);
                }
                Arrays.sort(localFileNumbers);
-               for (int i = 0; i < localFileNumbers.length; i++) {
-                       rereadExtraPeerDataFile(localFileNumbers[i].intValue());
+               for (Integer localFileNumber : localFileNumbers) {
+                       rereadExtraPeerDataFile(localFileNumber.intValue());
                }
        }

@@ -1199,10 +1198,10 @@
                                        form.addChild("input", new String[] { 
"type", "name", "value" },
                                                        new String[] { 
"hidden", "id", Long.toString(uid) });

-                                       form.addChild("input", new String[] { 
"type", "name", "value" }, 
+                                       form.addChild("input", new String[] { 
"type", "name", "value" },
                                                        new String[] { 
"submit", "acceptTransfer", l10n("acceptTransferButton") });

-                                       form.addChild("input", new String[] { 
"type", "name", "value" }, 
+                                       form.addChild("input", new String[] { 
"type", "name", "value" },
                                                        new String[] { 
"submit", "rejectTransfer", l10n("rejectTransferButton") });

                                        return div;

Modified: trunk/freenet/src/freenet/node/FNPPacketMangler.java
===================================================================
--- trunk/freenet/src/freenet/node/FNPPacketMangler.java        2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/FNPPacketMangler.java        2008-11-06 
13:53:57 UTC (rev 23351)
@@ -3,12 +3,11 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.node;

-import freenet.io.AddressTracker;
-import freenet.io.comm.SocketHandler;
-
+import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
 import java.security.MessageDigest;
 import java.util.Arrays;
-import java.util.Iterator;
+import java.util.HashMap;
 import java.util.LinkedList;

 import net.i2p.util.NativeBigInteger;
@@ -25,6 +24,7 @@
 import freenet.crypt.SHA256;
 import freenet.crypt.UnsupportedCipherException;
 import freenet.crypt.ciphers.Rijndael;
+import freenet.io.AddressTracker;
 import freenet.io.comm.AsyncMessageCallback;
 import freenet.io.comm.DMT;
 import freenet.io.comm.FreenetInetAddress;
@@ -32,14 +32,15 @@
 import freenet.io.comm.Message;
 import freenet.io.comm.MessageCore;
 import freenet.io.comm.NotConnectedException;
+import freenet.io.comm.PacketSocketHandler;
+import freenet.io.comm.Peer;
+import freenet.io.comm.PeerContext;
 import freenet.io.comm.PeerParseException;
 import freenet.io.comm.ReferenceSignatureVerificationException;
+import freenet.io.comm.SocketHandler;
 import freenet.io.comm.Peer.LocalAddressException;
+import freenet.support.ByteArrayWrapper;
 import freenet.support.Fields;
-import freenet.io.comm.PacketSocketHandler;
-import freenet.io.comm.Peer;
-import freenet.io.comm.PeerContext;
-import freenet.support.ByteArrayWrapper;
 import freenet.support.HexUtil;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
@@ -47,10 +48,6 @@
 import freenet.support.WouldBlockException;
 import freenet.support.io.NativeThread;

-import java.io.UnsupportedEncodingException;
-import java.math.BigInteger;
-import java.util.HashMap;
-
 /**
  * @author amphibian
  * 
@@ -61,7 +58,6 @@
  * changes in IncomingPacketFilter).
  */
 public class FNPPacketMangler implements OutgoingPacketMangler, 
IncomingPacketFilter {
-
        private static boolean logMINOR;
        private static boolean logDEBUG;
        private final Node node;
@@ -75,7 +71,7 @@
         * The messages are cached in hashmaps because the message retrieval 
from the cache 
         * can be performed in constant time( given the key)
         */
-       private final HashMap authenticatorCache;
+       private final HashMap<ByteArrayWrapper, byte[]> authenticatorCache;
        /** The following is used in the HMAC calculation of JFK message3 and 
message4 */
        private static final byte[] JFK_PREFIX_INITIATOR, JFK_PREFIX_RESPONDER;
        static {
@@ -99,7 +95,7 @@
        * The FIFO itself
        * Get a lock on dhContextFIFO before touching it!
        */
-       private final LinkedList dhContextFIFO = new LinkedList();
+       private final LinkedList<DiffieHellmanLightContext> dhContextFIFO = new 
LinkedList<DiffieHellmanLightContext>();
        /* The element which is about to be prunned from the FIFO */
        private DiffieHellmanLightContext dhContextToBePrunned = null;
        private long jfkDHLastGenerationTimestamp = 0;
@@ -164,7 +160,7 @@
                this.sock = sock;
                fnpTimingSource = new EntropySource();
                myPacketDataSource = new EntropySource();
-               authenticatorCache = new HashMap();
+               authenticatorCache = new HashMap<ByteArrayWrapper, byte[]>();

                fullHeadersLengthMinimum = HEADERS_LENGTH_MINIMUM + 
sock.getHeadersLength();
                fullHeadersLengthOneMessage = HEADERS_LENGTH_ONE_MESSAGE + 
sock.getHeadersLength();
@@ -946,7 +942,7 @@
                // sanity check
                byte[] myNi;
                synchronized (pn) {
-                       myNi = (byte[]) pn.jfkNoncesSent.get(replyTo);
+                       myNi = pn.jfkNoncesSent.get(replyTo);
                }
                // We don't except such a message;
                if(myNi == null) {
@@ -2352,41 +2348,51 @@
                1 + // no forgotten packets
                length; // the payload !

-               if(logMINOR) Logger.minor(this, "Pre-padding length: 
"+packetLength);
-               
-               // Padding
-               // This will do an adequate job of disguising the contents, and 
a poor (but not totally
-               // worthless) job of disguising the traffic. FIXME!!!!!
-               // Ideally we'd mimic the size profile - and the session bytes! 
- of a common protocol.
+               boolean paddThisPacket = crypto.config.paddDataPackets();
+               int paddedLen;
+               if(paddThisPacket) {
+                       if(logMINOR)
+                               Logger.minor(this, "Pre-padding length: " + 
packetLength);

-               int paddedLen;
-               
-               if(packetLength < 64) {
-                       // Up to 37 bytes of payload (after base overhead above 
of 27 bytes), padded size 96-128 bytes.
-                       // Most small messages, and most ack only packets.
-                       paddedLen = 64 + node.fastWeakRandom.nextInt(32);
+                       // Padding
+                       // This will do an adequate job of disguising the 
contents, and a poor (but not totally
+                       // worthless) job of disguising the traffic. FIXME!!!!!
+                       // Ideally we'd mimic the size profile - and the 
session bytes! - of a common protocol.
+
+                       if(packetLength < 64)
+                               // Up to 37 bytes of payload (after base 
overhead above of 27 bytes), padded size 96-128 bytes.
+                               // Most small messages, and most ack only 
packets.
+                               paddedLen = 64 + 
node.fastWeakRandom.nextInt(32);
+                       else {
+                               // Up to 69 bytes of payload, final size 
128-192 bytes (CHK request, CHK insert, opennet announcement, CHK offer, swap 
reply) 
+                               // Up to 133 bytes of payload, final size 
192-256 bytes (SSK request, get offered CHK, offer SSK[, SSKInsertRequestNew], 
get offered SSK)
+                               // Up to 197 bytes of payload, final size 
256-320 bytes (swap commit/complete[, SSKDataFoundNew, SSKInsertRequestAltNew])
+                               // Up to 1093 bytes of payload, final size 
1152-1216 bytes (bulk transmit, block transmit, time deltas, SSK pubkey[, 
SSKData, SSKDataInsert])
+                               packetLength += 32;
+                               paddedLen = ((packetLength + 63) / 64) * 64;
+                               paddedLen += node.fastWeakRandom.nextInt(64);
+                               // FIXME get rid of this, we shouldn't be 
sending packets anywhere near this size unless
+                               // we've done PMTU...
+                               if(packetLength <= 1280 && paddedLen > 1280)
+                                       paddedLen = 1280;
+                               int maxPacketSize = sock.getMaxPacketSize();
+                               if(packetLength <= maxPacketSize && paddedLen > 
maxPacketSize)
+                                       paddedLen = maxPacketSize;
+                               packetLength -= 32;
+                               paddedLen -= 32;
+                       }
                } else {
-                       // Up to 69 bytes of payload, final size 128-192 bytes 
(CHK request, CHK insert, opennet announcement, CHK offer, swap reply) 
-                       // Up to 133 bytes of payload, final size 192-256 bytes 
(SSK request, get offered CHK, offer SSK[, SSKInsertRequestNew], get offered 
SSK)
-                       // Up to 197 bytes of payload, final size 256-320 bytes 
(swap commit/complete[, SSKDataFoundNew, SSKInsertRequestAltNew])
-                       // Up to 1093 bytes of payload, final size 1152-1216 
bytes (bulk transmit, block transmit, time deltas, SSK pubkey[, SSKData, 
SSKDataInsert])
-                       packetLength += 32;
-                       paddedLen = ((packetLength + 63) / 64) * 64;
-                       paddedLen += node.fastWeakRandom.nextInt(64);
-                       // FIXME get rid of this, we shouldn't be sending 
packets anywhere near this size unless
-                       // we've done PMTU...
-                       if(packetLength <= 1280 && paddedLen > 1280) paddedLen 
= 1280;
-                       int maxPacketSize = sock.getMaxPacketSize();
-                       if(packetLength <= maxPacketSize && paddedLen > 
maxPacketSize) paddedLen = maxPacketSize;
-                       packetLength -= 32;
-                       paddedLen -= 32;
+                       if(logMINOR)
+                               Logger.minor(this, "Don't padd the packet: we 
have been asked not to.");
+                       paddedLen = packetLength;
                }

                byte[] padding = new byte[paddedLen - packetLength];
-               node.fastWeakRandom.nextBytes(padding);
-
-               packetLength = paddedLen;
-
+               if(paddThisPacket) {
+                       node.fastWeakRandom.nextBytes(padding);
+                       packetLength = paddedLen;
+               }
+               
                if(logMINOR) Logger.minor(this, "Packet length: 
"+packetLength+" ("+length+")");

                byte[] plaintext = new byte[packetLength];
@@ -2496,8 +2502,10 @@
                System.arraycopy(buf, offset, plaintext, ptr, length);
                ptr += length;

-               System.arraycopy(padding, 0, plaintext, ptr, padding.length);
-               ptr += padding.length;
+               if(paddThisPacket) {
+                       System.arraycopy(padding, 0, plaintext, ptr, 
padding.length);
+                       ptr += padding.length;
+               }

                if(ptr != plaintext.length) {
                        Logger.error(this, "Inconsistent length: 
"+plaintext.length+" buffer but "+(ptr)+" actual");
@@ -2671,12 +2679,10 @@
        private void _fillJFKDHFIFO() {
                synchronized (dhContextFIFO) {
                        if(dhContextFIFO.size() + 1 > DH_CONTEXT_BUFFER_SIZE) {
-                               DiffieHellmanLightContext result = null, tmp;
+                               DiffieHellmanLightContext result = null;
                                long oldestSeen = Long.MAX_VALUE;

-                               Iterator it = dhContextFIFO.iterator();
-                               while(it.hasNext()) {
-                                       tmp = (DiffieHellmanLightContext) 
it.next();
+                               for (DiffieHellmanLightContext tmp: 
dhContextFIFO) {
                                        if(tmp.lifetime < oldestSeen) {
                                                oldestSeen = tmp.lifetime;
                                                result = tmp;
@@ -2699,9 +2705,8 @@
                DiffieHellmanLightContext result = null;

                synchronized (dhContextFIFO) {
+                       result = dhContextFIFO.removeFirst();

-                       result = (DiffieHellmanLightContext) 
dhContextFIFO.removeFirst();
-                       
                        // Shall we replace one element of the queue ?
                        if((jfkDHLastGenerationTimestamp + 
DH_GENERATION_INTERVAL) < now) {
                                jfkDHLastGenerationTimestamp = now;
@@ -2724,11 +2729,8 @@
         * @return the corresponding DiffieHellmanLightContext with the right 
exponent
         */
        private DiffieHellmanLightContext findContextByExponential(BigInteger 
exponential) {
-               DiffieHellmanLightContext result = null;
                synchronized (dhContextFIFO) {
-                       Iterator it = dhContextFIFO.iterator();
-                       while(it.hasNext()) {
-                               result = (DiffieHellmanLightContext) it.next();
+                       for (DiffieHellmanLightContext result : dhContextFIFO) {
                                if(exponential.equals(result.myExponential)) {
                                        return result;
                                }

Modified: trunk/freenet/src/freenet/node/FailureTable.java
===================================================================
--- trunk/freenet/src/freenet/node/FailureTable.java    2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/FailureTable.java    2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -97,7 +97,7 @@
                long now = System.currentTimeMillis();
                FailureTableEntry entry;
                synchronized(this) {
-                       entry = (FailureTableEntry) entriesByKey.get(key);
+                       entry = entriesByKey.get(key);
                        if(entry == null)
                                entry = new FailureTableEntry(key);
                        entriesByKey.push(key, entry);
@@ -111,7 +111,7 @@
                long now = System.currentTimeMillis();
                FailureTableEntry entry;
                synchronized(this) {
-                       entry = (FailureTableEntry) entriesByKey.get(key);
+                       entry = entriesByKey.get(key);
                        if(entry == null)
                                entry = new FailureTableEntry(key);
                        entriesByKey.push(key, entry);
@@ -194,7 +194,7 @@
        static final class BlockOffer {
                final long offeredTime;
                /** Either offered by or offered to this node */
-               final WeakReference nodeRef;
+               final WeakReference<PeerNode> nodeRef;
                /** Authenticator */
                final byte[] authenticator;
                /** Boot ID when the offer was made */
@@ -208,7 +208,7 @@
                }

                public PeerNode getPeerNode() {
-                       return (PeerNode) nodeRef.get();
+                       return nodeRef.get();
                }

                public boolean isExpired(long now) {
@@ -230,7 +230,7 @@
                if(key == null) throw new NullPointerException();
                FailureTableEntry entry;
                synchronized(this) {
-                       entry = (FailureTableEntry) entriesByKey.get(key);
+                       entry = entriesByKey.get(key);
                        if(entry == null) return; // Nobody cares
                        entriesByKey.removeKey(key);
                        blockOfferListByKey.removeKey(key);
@@ -256,7 +256,7 @@
                        Logger.minor(this, "Offered key "+key+" by peer "+peer);
                FailureTableEntry entry;
                synchronized(this) {
-                       entry = (FailureTableEntry) entriesByKey.get(key);
+                       entry = entriesByKey.get(key);
                        if(entry == null) {
                                if(logMINOR) Logger.minor(this, "We didn't ask 
for the key");
                                return; // we haven't asked for it
@@ -285,7 +285,7 @@
                FailureTableEntry entry;
                long now = System.currentTimeMillis();
                synchronized(this) {
-                       entry = (FailureTableEntry) entriesByKey.get(key);
+                       entry = entriesByKey.get(key);
                        if(entry == null) {
                                if(logMINOR) Logger.minor(this, "We didn't ask 
for the key");
                                return; // we haven't asked for it
@@ -338,10 +338,9 @@

                // Add to offers list

-               synchronized(this) {
-                       
+               synchronized(this) {                    
                        if(logMINOR) Logger.minor(this, "Valid offer");
-                       BlockOfferList bl = (BlockOfferList) 
blockOfferListByKey.get(key);
+                       BlockOfferList bl = blockOfferListByKey.get(key);
                        BlockOffer offer = new BlockOffer(peer, now, 
authenticator, peer.getBootID());
                        if(bl == null) {
                                bl = new BlockOfferList(entry, offer);
@@ -533,11 +532,11 @@
                        }
                        if(!recentOffers.isEmpty()) {
                                int x = 
node.random.nextInt(recentOffers.size());
-                               return lastOffer = (BlockOffer) 
recentOffers.remove(x);
+                               return lastOffer = recentOffers.remove(x);
                        }
                        if(!expiredOffers.isEmpty()) {
                                int x = 
node.random.nextInt(expiredOffers.size());
-                               return lastOffer = (BlockOffer) 
expiredOffers.remove(x);
+                               return lastOffer = expiredOffers.remove(x);
                        }
                        // No more offers.
                        return null;
@@ -565,7 +564,7 @@
                if(!node.enableULPRDataPropagation) return null;
                BlockOfferList bl;
                synchronized(this) {
-                       bl = (BlockOfferList) blockOfferListByKey.get(key);
+                       bl = blockOfferListByKey.get(key);
                        if(bl == null) return null;
                }
                return new OfferList(bl);
@@ -580,7 +579,7 @@
        public TimedOutNodesList getTimedOutNodesList(Key key) {
                if(!node.enablePerNodeFailureTables) return null;
                synchronized(this) {
-                       return (FailureTableEntry) entriesByKey.get(key);
+                       return entriesByKey.get(key);
                }
        }

@@ -618,13 +617,12 @@
                        long endTime = System.currentTimeMillis();
                        if(logMINOR) Logger.minor(this, "Finished FailureTable 
cleanup took "+(endTime-startTime)+"ms");
                }
-
        }

        public boolean peersWantKey(Key key) {
                FailureTableEntry entry;
                synchronized(this) {
-                       entry = (FailureTableEntry) entriesByKey.get(key);
+                       entry = entriesByKey.get(key);
                        if(entry == null) return false; // Nobody cares
                }
                return entry.othersWant(null);

Modified: trunk/freenet/src/freenet/node/FailureTableEntry.java
===================================================================
--- trunk/freenet/src/freenet/node/FailureTableEntry.java       2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/FailureTableEntry.java       2008-11-06 
13:53:57 UTC (rev 23351)
@@ -4,11 +4,11 @@
 package freenet.node;

 import java.lang.ref.WeakReference;
+import java.util.Arrays;
 import java.util.HashSet;

 import freenet.keys.Key;
 import freenet.support.Logger;
-import java.util.Arrays;

 class FailureTableEntry implements TimedOutNodesList {

@@ -21,7 +21,7 @@
        /** Time we last received a DNF after sending a request for a key */
        long sentTime;
        /** WeakReference's to PeerNode's who have requested the key */
-       WeakReference[] requestorNodes;
+       WeakReference<PeerNode>[] requestorNodes;
        /** Times at which they requested it */
        long[] requestorTimes;
        /** Boot ID when they requested it. We don't send it to restarted 
nodes, as a 
@@ -32,7 +32,7 @@
        // FIXME also we don't have accurate times for when we routed to them - 
we only 
        // have the terminal time for the request.
        /** WeakReference's to PeerNode's we have requested it from */
-       WeakReference[] requestedNodes;
+       WeakReference<PeerNode>[] requestedNodes;
        /** Their locations when we requested it */
        double[] requestedLocs;
        long[] requestedBootIDs;
@@ -50,7 +50,8 @@
         public static final long[] EMPTY_LONG_ARRAY = new long[0];
         public static final short[] EMPTY_SHORT_ARRAY = new short[0];
         public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
-        public static final WeakReference[] EMPTY_WEAK_REFERENCE = new 
WeakReference[0];
+        @SuppressWarnings("unchecked")
+        public static final WeakReference<PeerNode>[] EMPTY_WEAK_REFERENCE = 
new WeakReference[0];

        FailureTableEntry(Key key) {
                this.key = key;
@@ -151,14 +152,15 @@
                                }
                        }
                }
-               WeakReference[] newRequestorNodes = new 
WeakReference[requestorNodes.length+notIncluded-nulls];
+        @SuppressWarnings("unchecked")
+               WeakReference<PeerNode>[] newRequestorNodes = new 
WeakReference[requestorNodes.length+notIncluded-nulls];
                long[] newRequestorTimes = new 
long[requestorNodes.length+notIncluded-nulls];
                long[] newRequestorBootIDs = new 
long[requestorNodes.length+notIncluded-nulls];
                int toIndex = 0;

                for(int i=0;i<requestorNodes.length;i++) {
-                       WeakReference ref = requestorNodes[i];
-                       PeerNode pn = (PeerNode) (ref == null ? null : 
ref.get());
+                       WeakReference<PeerNode> ref = requestorNodes[i];
+                       PeerNode pn = ref == null ? null : ref.get();
                        if(pn == null) continue;
                        if(pn == requestor) ret = toIndex;
                        newRequestorNodes[toIndex] = requestorNodes[i];
@@ -177,7 +179,8 @@

                for(int i=toIndex;i<newRequestorNodes.length;i++) 
newRequestorNodes[i] = null;
                if(toIndex > newRequestorNodes.length + 2) {
-                       WeakReference[] newNewRequestorNodes = new 
WeakReference[toIndex];
+                       @SuppressWarnings("unchecked")
+                       WeakReference<PeerNode>[] newNewRequestorNodes = new 
WeakReference[toIndex];
                        long[] newNewRequestorTimes = new long[toIndex];
                        long[] newNewRequestorBootIDs = new long[toIndex];
                        System.arraycopy(newRequestorNodes, 0, 
newNewRequestorNodes, 0, toIndex);
@@ -229,7 +232,8 @@
                                }
                        }
                }
-               WeakReference[] newRequestedNodes = new 
WeakReference[requestedNodes.length+notIncluded-nulls];
+               @SuppressWarnings("unchecked")
+               WeakReference<PeerNode>[] newRequestedNodes = new 
WeakReference[requestedNodes.length+notIncluded-nulls];
                double[] newRequestedLocs = new 
double[requestedNodes.length+notIncluded-nulls];
                long[] newRequestedBootIDs = new 
long[requestedNodes.length+notIncluded-nulls];
                long[] newRequestedTimes = new 
long[requestedNodes.length+notIncluded-nulls];
@@ -238,8 +242,8 @@

                int toIndex = 0;
                for(int i=0;i<requestedNodes.length;i++) {
-                       WeakReference ref = requestedNodes[i];
-                       PeerNode pn = (PeerNode) (ref == null ? null : 
ref.get());
+                       WeakReference<PeerNode> ref = requestedNodes[i];
+                       PeerNode pn = ref == null ? null : ref.get();
                        if(pn == null) continue;
                        if(pn == requestedFrom) ret = toIndex;
                        newRequestedNodes[toIndex] = requestedNodes[i];
@@ -265,7 +269,8 @@

                for(int i=toIndex;i<newRequestedNodes.length;i++) 
newRequestedNodes[i] = null;
                if(toIndex > newRequestedNodes.length + 2) {
-                       WeakReference[] newNewRequestedNodes = new 
WeakReference[toIndex];
+               @SuppressWarnings("unchecked")
+                       WeakReference<PeerNode>[] newNewRequestedNodes = new 
WeakReference[toIndex];
                        double[] newNewRequestedLocs = new double[toIndex];
                        long[] newNewRequestedBootIDs = new long[toIndex];
                        long[] newNewRequestedTimes = new long[toIndex];
@@ -300,9 +305,9 @@
                HashSet<PeerNode> set = new HashSet<PeerNode>();
                if(logMINOR) Logger.minor(this, "Sending offers to nodes which 
requested the key from us:");
                for(int i=0;i<requestorNodes.length;i++) {
-                       WeakReference ref = requestorNodes[i];
+                       WeakReference<PeerNode> ref = requestorNodes[i];
                        if(ref == null) continue;
-                       PeerNode pn = (PeerNode) ref.get();
+                       PeerNode pn = ref.get();
                        if(pn == null) continue;
                        if(pn.getBootID() != requestorBootIDs[i]) continue;
                        if(!set.add(pn)) {
@@ -312,9 +317,9 @@
                }
                if(logMINOR) Logger.minor(this, "Sending offers to nodes which 
we sent the key to:");
                for(int i=0;i<requestedNodes.length;i++) {
-                       WeakReference ref = requestedNodes[i];
+                       WeakReference<PeerNode> ref = requestedNodes[i];
                        if(ref == null) continue;
-                       PeerNode pn = (PeerNode) ref.get();
+                       PeerNode pn = ref.get();
                        if(pn == null) continue;
                        if(pn.getBootID() != requestedBootIDs[i]) continue;
                        if(set.contains(pn)) continue;
@@ -328,9 +333,9 @@
        public synchronized boolean othersWant(PeerNode peer) {
                boolean anyValid = false;
                for(int i=0;i<requestorNodes.length;i++) {
-                       WeakReference ref = requestorNodes[i];
+                       WeakReference<PeerNode> ref = requestorNodes[i];
                        if(ref == null) continue;
-                       PeerNode pn = (PeerNode) ref.get();
+                       PeerNode pn = ref.get();
                        if(pn == null) {
                                requestorNodes[i] = null;
                                continue;
@@ -356,9 +361,9 @@
                boolean anyValid = false;
                boolean ret = false;
                for(int i=0;i<requestorNodes.length;i++) {
-                       WeakReference ref = requestorNodes[i];
+                       WeakReference<PeerNode> ref = requestorNodes[i];
                        if(ref == null) continue;
-                       PeerNode pn = (PeerNode) ref.get();
+                       PeerNode pn = ref.get();
                        if(pn == null) {
                                requestorNodes[i] = null;
                                continue;
@@ -387,9 +392,9 @@
                boolean anyValid = false;
                boolean ret = false;
                for(int i=0;i<requestedNodes.length;i++) {
-                       WeakReference ref = requestedNodes[i];
+                       WeakReference<PeerNode> ref = requestedNodes[i];
                        if(ref == null) continue;
-                       PeerNode pn = (PeerNode) ref.get();
+                       PeerNode pn = ref.get();
                        if(pn == null) {
                                requestedNodes[i] = null;
                                continue;
@@ -421,7 +426,7 @@

        public synchronized long getTimeoutTime(PeerNode peer) {
                for(int i=0;i<requestedNodes.length;i++) {
-                       WeakReference ref = requestedNodes[i];
+                       WeakReference<PeerNode> ref = requestedNodes[i];
                        if(ref != null && ref.get() == peer) {
                                return requestedTimeouts[i];
                        }
@@ -434,9 +439,9 @@
                int x = 0;
                long now = System.currentTimeMillis(); // don't pass in as a 
pass over the whole FT may take a while. get it in the method.
                for(int i=0;i<requestorNodes.length;i++) {
-                       WeakReference ref = requestorNodes[i];
+                       WeakReference<PeerNode> ref = requestorNodes[i];
                        if(ref == null) continue;
-                       PeerNode pn = (PeerNode) ref.get();
+                       PeerNode pn = ref.get();
                        if(pn == null) continue;
                        long bootID = pn.getBootID();
                        if(bootID != requestorBootIDs[i]) continue;
@@ -449,7 +454,8 @@
                        x++;
                }
                if(x < requestorNodes.length) {
-                       WeakReference[] newRequestorNodes = new 
WeakReference[x];
+                       @SuppressWarnings("unchecked")
+                       WeakReference<PeerNode>[] newRequestorNodes = new 
WeakReference[x];
                        long[] newRequestorTimes = new long[x];
                        long[] newRequestorBootIDs = new long[x];
                        System.arraycopy(requestorNodes, 0, newRequestorNodes, 
0, x);
@@ -461,9 +467,9 @@
                }
                x = 0;
                for(int i=0;i<requestedNodes.length;i++) {
-                       WeakReference ref = requestedNodes[i];
+                       WeakReference<PeerNode> ref = requestedNodes[i];
                        if(ref == null) continue;
-                       PeerNode pn = (PeerNode) ref.get();
+                       PeerNode pn = ref.get();
                        if(pn == null) continue;
                        long bootID = pn.getBootID();
                        if(bootID != requestedBootIDs[i]) continue;
@@ -483,7 +489,8 @@
                        x++;
                }
                if(x < requestedNodes.length) {
-                       WeakReference[] newRequestedNodes = new 
WeakReference[x];
+                       @SuppressWarnings("unchecked")
+                       WeakReference<PeerNode>[] newRequestedNodes = new 
WeakReference[x];
                        long[] newRequestedTimes = new long[x];
                        long[] newRequestedBootIDs = new long[x];
                        long[] newRequestedTimeouts = new long[x];

Modified: trunk/freenet/src/freenet/node/GlobalProbe.java
===================================================================
--- trunk/freenet/src/freenet/node/GlobalProbe.java     2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/GlobalProbe.java     2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -3,9 +3,10 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.node;

-import freenet.support.Logger;
 import java.util.Arrays;

+import freenet.support.Logger;
+
 public class GlobalProbe implements Runnable {

        double lastLocation = 0.0;
@@ -98,7 +99,7 @@
        }

        private void output(double loc, int hops) {
-               double estimatedNodes = ((double) (ctr+1)) / loc;
+               double estimatedNodes = (ctr + 1.0) / loc;
                Logger.error(this, "LOCATION "+ctr+": " + loc+" - estimated 
nodes: "+estimatedNodes+" ("+hops+" hops)");
                System.err.println("LOCATION "+ctr+": " + loc+" - estimated 
nodes: "+estimatedNodes+" ("+hops+" hops)");
        }

Modified: trunk/freenet/src/freenet/node/IPDetectorPluginManager.java
===================================================================
--- trunk/freenet/src/freenet/node/IPDetectorPluginManager.java 2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/IPDetectorPluginManager.java 2008-11-06 
13:53:57 UTC (rev 23351)
@@ -3,7 +3,6 @@
 import java.net.InetAddress;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.Vector;
@@ -374,7 +373,7 @@
                        }
                        plugins = newPlugins;
                        // Will be removed when returns in the DetectorRunner
-                       runningDetector = (DetectorRunner) runners.get(d);
+                       runningDetector = runners.get(d);
                }
                 if(runningDetector != null)
                     runningDetector.kill();
@@ -413,8 +412,8 @@
         * (To detect new IP address)
         */ 

-       private HashMap /*<FredIPDetectorPlugin,DetectorRunner>*/ runners = new 
HashMap();
-       private HashSet /*<FredIPDetectorPlugin>*/ failedRunners = new 
HashSet();
+       private HashMap<FredPluginIPDetector,DetectorRunner> runners = new 
HashMap<FredPluginIPDetector,DetectorRunner>();
+       private HashSet<FredPluginIPDetector> failedRunners = new 
HashSet<FredPluginIPDetector>();
        private long lastDetectAttemptEndedTime;
        private long firstTimeUrgent;

@@ -608,10 +607,9 @@
                if(logMINOR) Logger.minor(this, "Checking whether should detect 
despite real IP...");
                // Now, if we have two nodes with unique IPs which aren't ours
                // connected, we don't need to detect.
-               HashSet addressesConnected = null;
+               HashSet<InetAddress> addressesConnected = null;
                boolean hasOldPeers = false;
-               for(int i=0;i<peers.length;i++) {
-                       PeerNode p = peers[i];
+               for(PeerNode p : peers) {
                        if(p.isConnected() || (now - p.lastReceivedPacketTime() 
< 24*60*60*1000)) {
                                // Has been connected in the last 24 hours.
                                // Unique IP address?
@@ -632,7 +630,7 @@
                                                if(!internal) {
                                                        // Real IP address
                                                        if(addressesConnected 
== null)
-                                                               
addressesConnected = new HashSet();
+                                                               
addressesConnected = new HashSet<InetAddress>();
                                                        
addressesConnected.add(addr);
                                                        
if(addressesConnected.size() > 2) {
                                                                // 3 connected 
addresses, lets assume we have connectivity.
@@ -696,7 +694,7 @@
                public void realRun() {
                        if(logMINOR) Logger.minor(this, "Running plugin 
detection");
                        try {
-                               Vector v = new Vector();
+                               Vector<DetectedIP> v = new Vector<DetectedIP>();
                                DetectedIP[] detected = null;
                                try {
                                        detected = plugin.getAddress();
@@ -715,8 +713,7 @@
                                                failed = true;
                                        } else {
                                                failed = true;
-                                               for(int i=0;i<v.size();i++) {
-                                                       DetectedIP ip = 
(DetectedIP) v.get(i);
+                                               for(DetectedIP ip : v) {
                                                        if(logMINOR) 
Logger.minor(this, "Detected IP: "+ip+" for "+plugin);
                                                        if(!((ip.publicAddress 
== null) || !IPUtil.isValidAddress(ip.publicAddress, false))) {
                                                                if(logMINOR) 
Logger.minor(this, "Address checked out");
@@ -756,7 +753,7 @@
 //                                     }
 //                             }
 //                             DetectedIP[] list = (DetectedIP[]) 
map.values().toArray(new DetectedIP[map.size()]);
-                               DetectedIP[] list = (DetectedIP[]) 
v.toArray(new DetectedIP[v.size()]);
+                               DetectedIP[] list = v.toArray(new 
DetectedIP[v.size()]);
                                int countOpen = 0;
                                int countFullCone = 0;
                                int countRestricted = 0;
@@ -880,7 +877,7 @@
                }
        }

-       void notifyPortChange(final Set newPorts) {
+       void notifyPortChange(final Set<ForwardPort> newPorts) {
                FredPluginPortForward[] plugins;
                synchronized(this) {
                        plugins = portForwardPlugins;
@@ -901,12 +898,10 @@
                }
        }

-       public void portForwardStatus(Map statuses) {
-               Set currentPorts = node.getPublicInterfacePorts();
-               Iterator i = currentPorts.iterator();
-               while(i.hasNext()) {
-                       ForwardPort p = (ForwardPort) i.next();
-                       ForwardPortStatus status = (ForwardPortStatus) 
statuses.get(p);
+       public void portForwardStatus(Map<ForwardPort, ForwardPortStatus> 
statuses) {
+               Set<ForwardPort> currentPorts = node.getPublicInterfacePorts();
+               for(ForwardPort p : currentPorts) {
+                       ForwardPortStatus status = statuses.get(p);
                        if(status == null) continue;
                        if(status.status == ForwardPortStatus.DEFINITE_SUCCESS) 
{
                                Logger.normal(this, "Succeeded forwarding 
"+p.name+" port "+p.portNumber+" for "+p.protocol+" - port forward definitely 
succeeded "+status.reasonString);

Modified: trunk/freenet/src/freenet/node/KeyTracker.java
===================================================================
--- trunk/freenet/src/freenet/node/KeyTracker.java      2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/KeyTracker.java      2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -53,13 +53,13 @@
         * and when they become urgent. We always add to the end,
         * and we always remove from the beginning, so should always
         * be consistent. */
-       private final List ackQueue;
+       private final List<QueuedAck> ackQueue;
        /** Serial numbers of packets that we have forgotten. Usually
         * when we have forgotten a packet it just means that it has 
         * been shifted to another KeyTracker because this one was
         * deprecated; the messages will get through in the end.
         */
-       private final List forgottenQueue;
+       private final List<QueuedForgotten> forgottenQueue;
        /** The highest incoming serial number we have ever seen
         * from the other side. Includes actual packets and resend
         * requests (provided they are within range). */
@@ -76,7 +76,7 @@
        private final UpdatableSortedLinkedListWithForeignIndex ackRequestQueue;
        /** Numbered packets that we need to send to the other side
         * because they asked for them. Just contains the numbers. */
-       private final HashSet packetsToResend;
+       private final HashSet<Integer> packetsToResend;
        /** Ranges of packet numbers we have received from the other
         * side. */
        private final ReceivedPacketNumbers packetNumbersReceived;
@@ -91,14 +91,14 @@
                this.pn = pn;
                this.sessionCipher = cipher;
                this.sessionKey = sessionKey;
-               ackQueue = new LinkedList();
-               forgottenQueue = new LinkedList();
+               ackQueue = new LinkedList<QueuedAck>();
+               forgottenQueue = new LinkedList<QueuedForgotten>();
                highestSeenIncomingSerialNumber = -1;
                // give some leeway
                sentPacketsContents = new LimitedRangeIntByteArrayMap(128);
                resendRequestQueue = new 
UpdatableSortedLinkedListWithForeignIndex();
                ackRequestQueue = new 
UpdatableSortedLinkedListWithForeignIndex();
-               packetsToResend = new HashSet();
+               packetsToResend = new HashSet<Integer>();
                packetNumbersReceived = new ReceivedPacketNumbers(512);
                isDeprecated = false;
                nextPacketNumber = pn.node.random.nextInt(100 * 1000);
@@ -653,9 +653,7 @@
         */
        private boolean queuedAck(int packetNumber) {
                synchronized(ackQueue) {
-                       Iterator it = ackQueue.iterator();
-                       while(it.hasNext()) {
-                               QueuedAck qa = (QueuedAck) it.next();
+                       for ( QueuedAck qa :ackQueue ) {
                                if(qa.packetNumber == packetNumber)
                                        return true;
                        }
@@ -779,9 +777,9 @@
                        int length = ackQueue.size();
                        acks = new int[length];
                        int i = 0;
-                       Iterator it = ackQueue.iterator();
+                       Iterator<QueuedAck> it = ackQueue.iterator();
                        while(it.hasNext()) {
-                               QueuedAck ack = (QueuedAck) it.next();
+                               QueuedAck ack = it.next();
                                acks[i++] = ack.packetNumber;
                                if(logMINOR)
                                        Logger.minor(this, "Grabbing ack " + 
ack.packetNumber + " from " + this);
@@ -887,7 +885,7 @@
                long earliestTime = Long.MAX_VALUE;
                synchronized(ackQueue) {
                        if(!ackQueue.isEmpty()) {
-                               QueuedAck qa = (QueuedAck) ackQueue.get(0);
+                               QueuedAck qa = ackQueue.get(0);
                                earliestTime = qa.urgentTime;
                        }
                }
@@ -936,7 +934,7 @@
        }

        /**
-        * Clear the KeyTracker. Deprecate it, clear all resend, ack, 
request-ack etc queues.
+        * Clear the KeyTracker. Depreciate it, clear all resend, ack, 
request-ack etc queues.
         * Return the messages we still had in flight. The caller will then 
either add them to
         * another KeyTracker, or call their callbacks to indicate failure.
         */
@@ -1018,7 +1016,7 @@
         * Not a very nice API, but it saves a load of allocations, and at
         * least it's documented!
         */
-       public int[] grabResendPackets(Vector rpiTemp, int[] numbers) {
+       public int[] grabResendPackets(Vector<ResendPacketItem> rpiTemp, int[] 
numbers) {
                rpiTemp.clear();
                long now = System.currentTimeMillis();
                long fourRTTs = twoRTTs();
@@ -1027,8 +1025,8 @@
                        int len = packetsToResend.size();
                        if(numbers.length < len)
                                numbers = new int[len * 2];
-                       for(Iterator it = packetsToResend.iterator(); 
it.hasNext();) {
-                               int packetNo = ((Integer) it.next()).intValue();
+                       for(Iterator<Integer> it = packetsToResend.iterator(); 
it.hasNext();) {
+                               int packetNo = it.next();
                                long resentTime = 
sentPacketsContents.getReaddedTime(packetNo);
                                if(now - resentTime > fourRTTs) {
                                        // Either never resent, or resent at 
least 4 RTTs ago

Modified: trunk/freenet/src/freenet/node/LocationManager.java
===================================================================
--- trunk/freenet/src/freenet/node/LocationManager.java 2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/LocationManager.java 2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -8,13 +8,13 @@
 import java.io.IOException;
 import java.security.MessageDigest;
 import java.text.DateFormat;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.Vector;

 import freenet.crypt.RandomSource;
 import freenet.crypt.SHA256;
@@ -93,7 +93,7 @@
         sender = new SwapRequestSender();
         this.r = r;
         this.node = node;
-        recentlyForwardedIDs = new Hashtable();
+        recentlyForwardedIDs = new Hashtable<Long, RecentlyForwardedItem>();
         // FIXME persist to disk!
         averageSwapTime = new 
BootstrappingDecayingRunningAverage(SEND_SWAP_INTERVAL, 0, Integer.MAX_VALUE, 
20, null);
         timeLocSet = System.currentTimeMillis();
@@ -709,7 +709,7 @@

         // Otherwise, stay locked, and start the next one from the queue.

-        nextMessage = (Message) incomingMessageQueue.removeFirst();
+        nextMessage = incomingMessageQueue.removeFirst();
         lockedTime = System.currentTimeMillis();

        }
@@ -814,7 +814,7 @@

     static final double SWAP_ACCEPT_PROB = 0.25;

-    final Hashtable recentlyForwardedIDs;
+    final Hashtable<Long, RecentlyForwardedItem> recentlyForwardedIDs;

     static class RecentlyForwardedItem {
         final long incomingID; // unnecessary?
@@ -837,7 +837,7 @@
     }

     /** Queue of swap requests to handle after this one. */
-    private final LinkedList incomingMessageQueue = new LinkedList();
+    private final LinkedList<Message> incomingMessageQueue = new 
LinkedList<Message>();

     static final int MAX_INCOMING_QUEUE_LENGTH = 10;

@@ -849,7 +849,7 @@
                Message first;
                synchronized(this) {
                        if(incomingMessageQueue.isEmpty()) return;
-                       first = (Message) incomingMessageQueue.getFirst();
+                       first = incomingMessageQueue.getFirst();
                        if(first.age() < MAX_TIME_ON_INCOMING_QUEUE) return;
                        incomingMessageQueue.removeFirst();
                        if(logMINOR) Logger.minor(this, "Cancelling queued 
item: "+first+" - too long on queue, maybe circular waiting?");
@@ -883,7 +883,7 @@
          * twice or more. However, if we get a request with either the 
incoming or the outgoing 
          * UID, we can safely kill it as it's clearly the result of a bug.
          */
-        RecentlyForwardedItem item = (RecentlyForwardedItem) 
recentlyForwardedIDs.get(oldID);
+        RecentlyForwardedItem item = recentlyForwardedIDs.get(oldID);
         if(item != null) {
                if(logMINOR) Logger.minor(this, "Rejecting - same ID as 
previous request");
             // Reject
@@ -1042,7 +1042,7 @@
      */
     public boolean handleSwapReply(Message m, PeerNode source) {
         final long uid = m.getLong(DMT.UID);
-               RecentlyForwardedItem item = (RecentlyForwardedItem) 
recentlyForwardedIDs.get(uid);
+               RecentlyForwardedItem item = recentlyForwardedIDs.get(uid);
         if(item == null) {
             Logger.error(this, "Unrecognized SwapReply: ID "+uid);
             return false;
@@ -1078,7 +1078,7 @@
      */
     public boolean handleSwapRejected(Message m, PeerNode source) {
         final long uid = m.getLong(DMT.UID);
-               RecentlyForwardedItem item = (RecentlyForwardedItem) 
recentlyForwardedIDs.get(uid);
+               RecentlyForwardedItem item = recentlyForwardedIDs.get(uid);
         if(item == null) return false;
         if(item.requestSender == null){
                if(logMINOR) Logger.minor(this, "Got a FNPSwapRejected without 
any requestSender set! we can't and won't claim it! UID="+uid);
@@ -1112,7 +1112,7 @@
      */
     public boolean handleSwapCommit(Message m, PeerNode source) {
         final long uid = m.getLong(DMT.UID);
-               RecentlyForwardedItem item = (RecentlyForwardedItem) 
recentlyForwardedIDs.get(uid);
+               RecentlyForwardedItem item = recentlyForwardedIDs.get(uid);
         if(item == null) return false;
         if(item.routedTo == null) return false;
         if(source != item.requestSender) {
@@ -1140,7 +1140,7 @@
     public boolean handleSwapComplete(Message m, PeerNode source) {
         final long uid = m.getLong(DMT.UID);
         if(logMINOR) Logger.minor(this, "handleSwapComplete("+uid+ ')');
-        RecentlyForwardedItem item = (RecentlyForwardedItem) 
recentlyForwardedIDs.get(uid);
+        RecentlyForwardedItem item = recentlyForwardedIDs.get(uid);
         if(item == null) {
                if(logMINOR) Logger.minor(this, "Item not found: "+uid+": "+m);
             return false;
@@ -1231,7 +1231,7 @@
             RecentlyForwardedItem[] items = new 
RecentlyForwardedItem[recentlyForwardedIDs.size()];
             if(items.length < 1)
                return;
-            items = (RecentlyForwardedItem[]) 
recentlyForwardedIDs.values().toArray(items);
+            items = recentlyForwardedIDs.values().toArray(items);
             for(int i=0;i<items.length;i++) {
                 if(now - items[i].lastMessageTime > (TIMEOUT*2)) {
                     removeRecentlyForwardedItem(items[i]);
@@ -1244,15 +1244,12 @@
      * We lost the connection to a node, or it was restarted.
      */
     public void lostOrRestartedNode(PeerNode pn) {
-        Vector v = new Vector();
+        List<RecentlyForwardedItem> v = new ArrayList<RecentlyForwardedItem>();
         synchronized(recentlyForwardedIDs) {
-               Set entrySet = recentlyForwardedIDs.entrySet();
-                       Iterator it = entrySet.iterator();
-                       while (it.hasNext()) {
-                               Map.Entry entry = (Map.Entry) it.next();
-                               Long l = (Long) entry.getKey();
-
-                               RecentlyForwardedItem item = 
(RecentlyForwardedItem) entry.getValue();
+               Set<Map.Entry<Long, RecentlyForwardedItem>> entrySet = 
recentlyForwardedIDs.entrySet();
+                       for (Map.Entry<Long, RecentlyForwardedItem> entry : 
entrySet) {
+                               Long l = entry.getKey();
+                               RecentlyForwardedItem item = entry.getValue();

                 if(item == null) {
                        Logger.error(this, "Key is "+l+" but no value on 
recentlyForwardedIDs - shouldn't be possible");
@@ -1265,15 +1262,13 @@
             }

                        // remove them
-                       Iterator it2 = v.iterator();
-                       while (it2.hasNext())
-                               
removeRecentlyForwardedItem((RecentlyForwardedItem) it2.next());
+                       for (RecentlyForwardedItem item : v)
+                               removeRecentlyForwardedItem(item);
         }
                int dumped=v.size();
                if (dumped!=0 && logMINOR)
                        Logger.minor(this, "lostOrRestartedNode dumping 
"+dumped+" swap requests for "+pn.getPeer());
-        for(int i=0;i<dumped;i++) {
-            RecentlyForwardedItem item = (RecentlyForwardedItem) v.get(i);
+        for(RecentlyForwardedItem item : v) {
             // Just reject it to avoid locking problems etc
             Message msg = DMT.createFNPSwapRejected(item.incomingID);
             if(logMINOR) Logger.minor(this, "Rejecting in lostOrRestartedNode: 
"+item.incomingID+ " from "+item.requestSender);

Modified: trunk/freenet/src/freenet/node/LoggingConfigHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/LoggingConfigHandler.java    2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/LoggingConfigHandler.java    2008-11-06 
13:53:57 UTC (rev 23351)
@@ -45,10 +45,6 @@
                public String[] getPossibleValues() {
                        return possibleValues;
                }
-
-               public void setPossibleValues(String[] val) {
-                       throw new NullPointerException("Should not happen!");
-                }
        }

        protected static final String LOG_PREFIX = "freenet";

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2008-11-06 13:50:42 UTC (rev 
23350)
+++ trunk/freenet/src/freenet/node/Node.java    2008-11-06 13:53:57 UTC (rev 
23351)
@@ -203,14 +203,9 @@
                public String[] getPossibleValues() {
                        return new String[] { "bdb-index", "salt-hash", "ram" };
                }
-
-               public void setPossibleValues(String[] val) {
-                       throw new UnsupportedOperationException();
-               }
        }

        private static class L10nCallback extends StringCallback implements 
EnumerableOptionCallback {
-               
                @Override
                public String get() {
                        return L10n.getSelectedLanguage().fullName;
@@ -227,10 +222,6 @@
                        PluginManager.setLanguage(L10n.getSelectedLanguage());
                }

-               public void setPossibleValues(String[] val) {
-                       throw new NullPointerException("Should not happen!");
-               }
-               
                public String[] getPossibleValues() {
                        return L10n.LANGUAGE.valuesWithFullNames();
                }
@@ -307,6 +298,7 @@
        private final String storeType;
        private int storeBloomFilterSize;
        private final boolean storeBloomFilterCounting;
+       private boolean storeSaltHashResizeOnStart;

        /** The number of bytes per key total in all the different datastores. 
All the datastores
         * are always the same size in number of keys. */
@@ -1572,6 +1564,20 @@

                storeBloomFilterCounting = 
nodeConfig.getBoolean("storeBloomFilterCounting");

+               nodeConfig.register("storeSaltHashResizeOnStart", true, 
sortOrder++, true, false,
+                               "Node.storeSaltHashResizeOnStart", 
"Node.storeSaltHashResizeOnStartLong", new BooleanCallback() {
+                       @Override
+                       public Boolean get() {
+                               return storeSaltHashResizeOnStart;
+                       }
+
+                       @Override
+                       public void set(Boolean val) throws 
InvalidConfigValueException, NodeNeedRestartException {
+                               storeSaltHashResizeOnStart = val;
+                       }
+               });
+               storeSaltHashResizeOnStart = 
nodeConfig.getBoolean("storeSaltHashResizeOnStart");
+
                nodeConfig.register("storeDir", "datastore", sortOrder++, true, 
true, "Node.storeDirectory", "Node.storeDirectoryLong", 
                                new StringCallback() {
                                        @Override
@@ -1792,32 +1798,32 @@
                        System.out.println("Initializing CHK Datastore (" + 
maxStoreKeys + " keys)");
                        chkDatastore = new CHKStore();
                        SaltedHashFreenetStore chkDataFS = 
SaltedHashFreenetStore.construct(storeDir, "CHK-store", chkDatastore,
-                               random, maxStoreKeys, bloomFilterSizeInM, 
storeBloomFilterCounting, shutdownHook, storePreallocate);
+                               random, maxStoreKeys, bloomFilterSizeInM, 
storeBloomFilterCounting, shutdownHook, storePreallocate, 
storeSaltHashResizeOnStart);
                        Logger.normal(this, "Initializing CHK Datacache");
                        System.out.println("Initializing CHK Datacache (" + 
maxCacheKeys + ':' + maxCacheKeys + " keys)");
                        chkDatacache = new CHKStore();
                        SaltedHashFreenetStore chkCacheFS = 
SaltedHashFreenetStore.construct(storeDir, "CHK-cache", chkDatacache,
-                               random, maxCacheKeys, bloomFilterSizeInM, 
storeBloomFilterCounting, shutdownHook, storePreallocate);
+                               random, maxCacheKeys, bloomFilterSizeInM, 
storeBloomFilterCounting, shutdownHook, storePreallocate, 
storeSaltHashResizeOnStart);
                        Logger.normal(this, "Initializing pubKey Datastore");
                        System.out.println("Initializing pubKey Datastore");
                        pubKeyDatastore = new PubkeyStore();
                        SaltedHashFreenetStore pubkeyDataFS = 
SaltedHashFreenetStore.construct(storeDir, "PUBKEY-store",
-                               pubKeyDatastore, random, maxStoreKeys, 
bloomFilterSizeInM, storeBloomFilterCounting, shutdownHook, storePreallocate);
+                               pubKeyDatastore, random, maxStoreKeys, 
bloomFilterSizeInM, storeBloomFilterCounting, shutdownHook, storePreallocate, 
storeSaltHashResizeOnStart);
                        Logger.normal(this, "Initializing pubKey Datacache");
                        System.out.println("Initializing pubKey Datacache (" + 
maxCacheKeys + " keys)");
                        pubKeyDatacache = new PubkeyStore();
                        SaltedHashFreenetStore pubkeyCacheFS = 
SaltedHashFreenetStore.construct(storeDir, "PUBKEY-cache",
-                               pubKeyDatacache, random, maxCacheKeys, 
bloomFilterSizeInM, storeBloomFilterCounting, shutdownHook, storePreallocate);
+                               pubKeyDatacache, random, maxCacheKeys, 
bloomFilterSizeInM, storeBloomFilterCounting, shutdownHook, storePreallocate, 
storeSaltHashResizeOnStart);
                        Logger.normal(this, "Initializing SSK Datastore");
                        System.out.println("Initializing SSK Datastore");
                        sskDatastore = new SSKStore(this);
                        SaltedHashFreenetStore sskDataFS = 
SaltedHashFreenetStore.construct(storeDir, "SSK-store", sskDatastore,
-                               random, maxStoreKeys, bloomFilterSizeInM, 
storeBloomFilterCounting, shutdownHook, storePreallocate);
+                               random, maxStoreKeys, bloomFilterSizeInM, 
storeBloomFilterCounting, shutdownHook, storePreallocate, 
storeSaltHashResizeOnStart);
                        Logger.normal(this, "Initializing SSK Datacache");
                        System.out.println("Initializing SSK Datacache (" + 
maxCacheKeys + " keys)");
                        sskDatacache = new SSKStore(this);
                        SaltedHashFreenetStore sskCacheFS = 
SaltedHashFreenetStore.construct(storeDir, "SSK-cache", sskDatacache,
-                               random, maxCacheKeys, bloomFilterSizeInM, 
storeBloomFilterCounting, shutdownHook, storePreallocate);
+                               random, maxCacheKeys, bloomFilterSizeInM, 
storeBloomFilterCounting, shutdownHook, storePreallocate, 
storeSaltHashResizeOnStart);

                        File migrationFile = new File(storeDir, "migrated");
                        if (!migrationFile.exists()) {

Modified: trunk/freenet/src/freenet/node/NodeCryptoConfig.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeCryptoConfig.java        2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/NodeCryptoConfig.java        2008-11-06 
13:53:57 UTC (rev 23351)
@@ -3,6 +3,7 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.node;

+import freenet.config.NodeNeedRestartException;
 import java.net.UnknownHostException;

 import freenet.config.InvalidConfigValueException;
@@ -54,6 +55,9 @@
        /** If true, include local addresses on noderefs */
        public boolean includeLocalAddressesInNoderefs;

+       /** If false we won't make any effort do disguise the length of packets 
*/
+       private boolean paddDataPackets;
+       
        NodeCryptoConfig(SubConfig config, int sortOrder, boolean isOpennet, 
SecurityLevels securityLevels) throws NodeInitException {
                this.isOpennet = isOpennet;

@@ -231,6 +235,34 @@

                includeLocalAddressesInNoderefs = 
config.getBoolean("includeLocalAddressesInNoderefs");

+               // enable/disable Padding of outgoing packets (won't affect 
auth-packets)
+               
+               config.register("paddDataPackets", true, sortOrder++, true, 
false, "Node.paddDataPackets", "Node.paddDataPacketsLong", new 
BooleanCallback() {
+
+                       @Override
+                       public Boolean get() {
+                               return paddDataPackets;
+                       }
+
+                       @Override
+                       public void set(Boolean val) throws 
InvalidConfigValueException, NodeNeedRestartException {
+                               if(val == get()) return;
+                               paddDataPackets = val;
+                       }
+               });
+               
+               paddDataPackets = config.getBoolean("paddDataPackets");
+               securityLevels.addNetworkThreatLevelListener(new 
SecurityLevelListener<NETWORK_THREAT_LEVEL>() {
+
+                       public void onChange(NETWORK_THREAT_LEVEL oldLevel, 
NETWORK_THREAT_LEVEL newLevel) {
+                               // Might be useful for nodes which are running 
with a tight bandwidth quota to minimize the overhead,
+                               // so turn it off for LOW. Otherwise is 
sensible.
+                               if(newLevel == NETWORK_THREAT_LEVEL.LOW)
+                                       paddDataPackets = false;
+                               if(oldLevel == NETWORK_THREAT_LEVEL.LOW)
+                                       paddDataPackets = true;
+                       }
+               });
        }

        /** The number of config options i.e. the amount to increment sortOrder 
by */
@@ -303,5 +335,8 @@
        public boolean includeLocalAddressesInNoderefs() {
                return includeLocalAddressesInNoderefs;
        }
-
+       
+       public boolean paddDataPackets() {
+               return paddDataPackets;
+       }
 }

Modified: trunk/freenet/src/freenet/node/NodeIPDetector.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeIPDetector.java  2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/NodeIPDetector.java  2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -7,6 +7,7 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;

 import freenet.config.InvalidConfigValueException;
 import freenet.config.SubConfig;
@@ -128,7 +129,7 @@
                synchronized(this) {
                        hasValidIP = addedValidIP;
                }
-               lastIPAddress = (FreenetInetAddress[]) addresses.toArray(new 
FreenetInetAddress[addresses.size()]);
+               lastIPAddress = addresses.toArray(new 
FreenetInetAddress[addresses.size()]);
                if(dumpLocalAddresses) {
                        ArrayList<FreenetInetAddress> filtered = new 
ArrayList<FreenetInetAddress>(lastIPAddress.length);
                        for(int i=0;i<lastIPAddress.length;i++) {
@@ -139,7 +140,7 @@
                                else 
if(IPUtil.isValidAddress(lastIPAddress[i].getAddress(), false))
                                        filtered.add(lastIPAddress[i]);
                        }
-                       return (FreenetInetAddress[]) filtered.toArray(new 
FreenetInetAddress[filtered.size()]);
+                       return filtered.toArray(new 
FreenetInetAddress[filtered.size()]);
                }
                return lastIPAddress;
        }
@@ -209,17 +210,27 @@
                        HashMap<FreenetInetAddress,Integer> countsByPeer = new 
HashMap<FreenetInetAddress,Integer>();
                        // FIXME use a standard mutable int object, we have one 
somewhere
                        for(int i=0;i<peerList.length;i++) {
-                               if(!peerList[i].isConnected()) continue;
+                               if(!peerList[i].isConnected()) {
+                                       if(logMINOR) Logger.minor(this, "Not 
connected");
+                                       continue;
+                               }
                                if(!peerList[i].isRealConnection()) {
                                        // Only let seed server connections 
through.
                                        // We have to trust them anyway.
                                        if(!(peerList[i] instanceof 
SeedServerPeerNode)) continue;
+                                       if(logMINOR) Logger.minor(this, "Not a 
real connection and not a seed node: "+peerList[i]);
                                }
+                               if(logMINOR) Logger.minor(this, "Maybe a usable 
connection for IP: "+peerList[i]);
                                Peer p = peerList[i].getRemoteDetectedPeer();
+                               if(logMINOR) Logger.minor(this, "Remote 
detected peer: "+p);
                                if(p == null || p.isNull()) continue;
                                FreenetInetAddress addr = p.getFreenetAddress();
+                               if(logMINOR) Logger.minor(this, "Address: 
"+addr);
                                if(addr == null) continue;
-                               
if(!IPUtil.isValidAddress(addr.getAddress(false), false)) continue;
+                               
if(!IPUtil.isValidAddress(addr.getAddress(false), false)) {
+                                       if(logMINOR) Logger.minor(this, 
"Address not valid");
+                                       continue;
+                               }
                                if(logMINOR)
                                        Logger.minor(this, "Peer 
"+peerList[i].getPeer()+" thinks we are "+addr);
                                if(countsByPeer.containsKey(addr)) {
@@ -229,8 +240,8 @@
                                }
                        }
                        if(countsByPeer.size() == 1) {
-                               Iterator it = countsByPeer.keySet().iterator();
-                               FreenetInetAddress addr = (FreenetInetAddress) 
(it.next());
+                               Iterator<FreenetInetAddress> it = 
countsByPeer.keySet().iterator();
+                               FreenetInetAddress addr = it.next();
                                Logger.minor(this, "Everyone agrees we are 
"+addr);
                                if(!addresses.contains(addr)) {
                                        if(addr.isRealInternetAddress(false, 
false, false))
@@ -238,15 +249,14 @@
                                        addresses.add(addr);
                                }
                        } else if(countsByPeer.size() > 1) {
-                               Iterator it = countsByPeer.keySet().iterator();
                                // Take two most popular addresses.
                                FreenetInetAddress best = null;
                                FreenetInetAddress secondBest = null;
                                int bestPopularity = 0;
                                int secondBestPopularity = 0;
-                               while(it.hasNext()) {
-                                       FreenetInetAddress cur = 
(FreenetInetAddress) (it.next());
-                                       int curPop = ((Integer) 
(countsByPeer.get(cur))).intValue();
+                               for(Map.Entry<FreenetInetAddress,Integer> entry 
: countsByPeer.entrySet()) {
+                                       FreenetInetAddress cur = entry.getKey();
+                                       int curPop = entry.getValue();
                                        Logger.minor(this, "Detected peer: 
"+cur+" popularity "+curPop);
                                        if(curPop >= bestPopularity) {
                                                secondBestPopularity = 
bestPopularity;

Modified: trunk/freenet/src/freenet/node/NodeIPPortDetector.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeIPPortDetector.java      2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/NodeIPPortDetector.java      2008-11-06 
13:53:57 UTC (rev 23351)
@@ -7,6 +7,7 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;

 import freenet.io.comm.FreenetInetAddress;
 import freenet.io.comm.Peer;
@@ -90,22 +91,21 @@
                                }
                        }
                        if(countsByPeer.size() == 1) {
-                               Iterator it = countsByPeer.keySet().iterator();
-                               Peer p = (Peer) (it.next());
+                               Iterator<Peer> it = 
countsByPeer.keySet().iterator();
+                               Peer p = (it.next());
                                Logger.minor(this, "Everyone agrees we are "+p);
                                if(!addresses.contains(p)) {
                                        addresses.add(p);
                                }
                        } else if(countsByPeer.size() > 1) {
-                               Iterator it = countsByPeer.keySet().iterator();
                                // Take two most popular addresses.
                                Peer best = null;
                                Peer secondBest = null;
                                int bestPopularity = 0;
                                int secondBestPopularity = 0;
-                               while(it.hasNext()) {
-                                       Peer cur = (Peer) (it.next());
-                                       int curPop = ((Integer) 
(countsByPeer.get(cur))).intValue();
+                               for (Map.Entry<Peer,Integer> entry : 
countsByPeer.entrySet()) {
+                                       Peer cur = entry.getKey();
+                                       int curPop = entry.getValue();
                                        Logger.normal(this, "Detected peer: 
"+cur+" popularity "+curPop);
                                        if(curPop >= bestPopularity) {
                                                secondBestPopularity = 
bestPopularity;
@@ -141,7 +141,7 @@
                                }
                        }
                }
-               lastPeers = (Peer[]) addresses.toArray(new 
Peer[addresses.size()]);
+               lastPeers = addresses.toArray(new Peer[addresses.size()]);
                if(logMINOR)
                        Logger.minor(this, "Returning for port 
"+crypto.portNumber+" : "+Arrays.toString(lastPeers));
                return lastPeers;

Modified: trunk/freenet/src/freenet/node/PacketSender.java
===================================================================
--- trunk/freenet/src/freenet/node/PacketSender.java    2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/PacketSender.java    2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -3,6 +3,8 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.node;

+import java.util.ArrayList;
+import java.util.List;
 import java.util.TreeMap;
 import java.util.Vector;

@@ -36,7 +38,7 @@
         * this many milliseconds. */
        static final int MIN_OLD_OPENNET_CONNECT_DELAY = 60 * 1000;
        /** ~= Ticker :) */
-       private final TreeMap timedJobsByTime;
+       private final TreeMap<Long, Object> timedJobsByTime;
        final NativeThread myThread;
        final Node node;
        NodeStats stats;
@@ -46,7 +48,7 @@
        /** For watchdog. 32-bit to avoid locking. */
        volatile int lastTimeInSeconds;
        private long timeLastSentOldOpennetConnectAttempt;
-       private Vector rpiTemp;
+       private Vector<ResendPacketItem> rpiTemp;
        private int[] rpiIntTemp;
        private boolean started = false;

@@ -60,13 +62,13 @@
        }

        PacketSender(Node node) {
-               timedJobsByTime = new TreeMap();
+               timedJobsByTime = new TreeMap<Long, Object>();
                this.node = node;
                myThread = new NativeThread(this, "PacketSender thread for " + 
node.getDarknetPortNumber(), NativeThread.MAX_PRIORITY, false);
                myThread.setDaemon(true);
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
                logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
-               rpiTemp = new Vector();
+               rpiTemp = new Vector<ResendPacketItem>();
                rpiIntTemp = new int[64];
        }

@@ -328,14 +330,14 @@
                if((now - oldNow) > (10 * 1000))
                        Logger.error(this, "now is more than 10 seconds past 
oldNow (" + (now - oldNow) + ") in PacketSender");

-               Vector jobsToRun = null;
+               List<Job> jobsToRun = null;

                synchronized(timedJobsByTime) {
                        while(!timedJobsByTime.isEmpty()) {
-                               Long tRun = (Long) timedJobsByTime.firstKey();
+                               Long tRun = timedJobsByTime.firstKey();
                                if(tRun.longValue() <= now) {
                                        if(jobsToRun == null)
-                                               jobsToRun = new Vector();
+                                               jobsToRun = new 
ArrayList<Job>();
                                        Object o = timedJobsByTime.remove(tRun);
                                        if(o instanceof Job[]) {
                                                Job[] r = (Job[]) o;
@@ -354,8 +356,7 @@
                }

                if(jobsToRun != null)
-                       for(int i = 0; i < jobsToRun.size(); i++) {
-                               Job r = (Job) jobsToRun.get(i);
+                       for(Job r : jobsToRun) {
                                if(logMINOR)
                                        Logger.minor(this, "Running " + r);
                                if(r.job instanceof FastRunnable)

Modified: trunk/freenet/src/freenet/node/PeerManager.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerManager.java     2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/PeerManager.java     2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -17,6 +17,7 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.Vector;

@@ -69,11 +70,11 @@
        /** PeerNode status summary log interval (milliseconds) */
        private static final long peerNodeStatusLogInterval = 5000;
        /** PeerNode statuses, by status */
-       private final HashMap peerNodeStatuses;
+       private final HashMap<Integer, HashSet<PeerNode>> peerNodeStatuses;
        /** DarknetPeerNode statuses, by status */
-       private final HashMap peerNodeStatusesDarknet;
+       private final HashMap<Integer, HashSet<PeerNode>> 
peerNodeStatusesDarknet;
        /** PeerNode routing backoff reasons, by reason */
-       private final HashMap peerNodeRoutingBackoffReasons;
+       private final HashMap<String, HashSet<PeerNode>> 
peerNodeRoutingBackoffReasons;
        /** Next time to update routableConnectionStats */
        private long nextRoutableConnectionStatsUpdateTime = -1;
        /** routableConnectionStats update interval (milliseconds) */
@@ -118,9 +119,9 @@
        public PeerManager(Node node) {
                Logger.normal(this, "Creating PeerManager");
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
-               peerNodeStatuses = new HashMap();
-               peerNodeStatusesDarknet = new HashMap();
-               peerNodeRoutingBackoffReasons = new HashMap();
+               peerNodeStatuses = new HashMap<Integer, HashSet<PeerNode>>();
+               peerNodeStatusesDarknet = new HashMap<Integer, 
HashSet<PeerNode>>();
+               peerNodeRoutingBackoffReasons = new HashMap<String, 
HashSet<PeerNode>>();
                System.out.println("Creating PeerManager");
                myPeers = new PeerNode[0];
                connectedPeers = new PeerNode[0];
@@ -302,7 +303,6 @@
                        if(pn instanceof DarknetPeerNode)
                                ((DarknetPeerNode) pn).removeExtraPeerDataDir();
                        if(isInPeers) {
-
                                int peerNodeStatus = pn.getPeerNodeStatus();
                                if(pn.recordStatus())
                                        removePeerNodeStatus(peerNodeStatus, 
pn, !isInPeers);
@@ -311,22 +311,22 @@
                                        
removePeerNodeRoutingBackoffReason(peerNodePreviousRoutingBackoffReason, pn);

                                // removing from connectedPeers
-                               ArrayList a = new ArrayList();
-                               for(int i = 0; i < myPeers.length; i++) {
-                                       if((myPeers[i] != pn) && 
myPeers[i].isConnected() && myPeers[i].isRealConnection())
-                                               a.add(myPeers[i]);
+                               ArrayList<PeerNode> a = new 
ArrayList<PeerNode>();
+                               for(PeerNode mp : myPeers) {
+                                       if((mp != pn) && mp.isConnected() && 
mp.isRealConnection())
+                                               a.add(mp);
                                }

                                PeerNode[] newConnectedPeers = new 
PeerNode[a.size()];
-                               newConnectedPeers = (PeerNode[]) 
a.toArray(newConnectedPeers);
+                               newConnectedPeers = 
a.toArray(newConnectedPeers);
                                connectedPeers = newConnectedPeers;

                                // removing from myPeers
                                PeerNode[] newMyPeers = new 
PeerNode[myPeers.length - 1];
                                int positionInNewArray = 0;
-                               for(int i = 0; i < myPeers.length; i++) {
-                                       if(myPeers[i] != pn) {
-                                               newMyPeers[positionInNewArray] 
= myPeers[i];
+                               for(PeerNode mp : myPeers) {
+                                       if(mp != pn) {
+                                               newMyPeers[positionInNewArray] 
= mp;
                                                positionInNewArray++;
                                        }
                                }
@@ -364,13 +364,13 @@
                        if(!isInPeers)
                                return false;
                        // removing from connectedPeers
-                       ArrayList a = new ArrayList();
-                       for(int i = 0; i < myPeers.length; i++) {
-                               if((myPeers[i] != pn) && 
myPeers[i].isRoutable())
-                                       a.add(myPeers[i]);
+                       ArrayList<PeerNode> a = new ArrayList<PeerNode>();
+                       for(PeerNode mp : myPeers) {
+                               if((mp != pn) && mp.isRoutable())
+                                       a.add(mp);
                        }
                        PeerNode[] newConnectedPeers = new PeerNode[a.size()];
-                       newConnectedPeers = (PeerNode[]) 
a.toArray(newConnectedPeers);
+                       newConnectedPeers = a.toArray(newConnectedPeers);
                        connectedPeers = newConnectedPeers;
                }
                updatePMUserAlert();
@@ -550,8 +550,7 @@
                }
        };

-       protected static class LocationUIDPair implements Comparable {
-
+       protected static class LocationUIDPair implements 
Comparable<LocationUIDPair> {
                double location;
                long uid;

@@ -560,9 +559,8 @@
                        uid = pn.swapIdentifier;
                }

-               public int compareTo(Object arg0) {
+               public int compareTo(LocationUIDPair p) {
                        // Compare purely on location, so result is the same as 
getPeerLocationDoubles()
-                       LocationUIDPair p = (LocationUIDPair) arg0;
                        if(p.location > location)
                                return 1;
                        if(p.location < location)
@@ -642,9 +640,8 @@
                                        return pn;
                        }
                        //could not easily find a good random one... filter the 
ones which are acceptable
-                       ArrayList l = new ArrayList();
-                       for(int i = 0; i < connectedPeers.length; i++) {
-                               PeerNode pn = connectedPeers[i];
+                       ArrayList<PeerNode> l = new ArrayList<PeerNode>();
+                       for(PeerNode pn : connectedPeers) {
                                if(pn == exclude)
                                        continue;
                                if(node.netid.inSeparateNetworks(pn, exclude))
@@ -656,7 +653,7 @@
                        //Are there any acceptable peers?
                        if(l.size() == 0)
                                return null;
-                       return (PeerNode) l.get(node.random.nextInt(l.size()));
+                       return l.get(node.random.nextInt(l.size()));
                }
        }

@@ -679,10 +676,9 @@
                // Move the un-connected ones out
                // This is safe as they will add themselves when they
                // reconnect, and they can't do it yet as we are synchronized.
-               Vector v = new Vector(connectedPeers.length);
+               ArrayList<PeerNode> v = new 
ArrayList<PeerNode>(connectedPeers.length);
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
-               for(int i = 0; i < myPeers.length; i++) {
-                       PeerNode pn = myPeers[i];
+               for(PeerNode pn : myPeers) {
                        if(pn == exclude)
                                continue;
                        if(pn.isRoutable())
@@ -695,7 +691,7 @@
                if((exclude != null) && exclude.isRoutable())
                        v.add(exclude);
                PeerNode[] newConnectedPeers = new PeerNode[v.size()];
-               newConnectedPeers = (PeerNode[]) v.toArray(newConnectedPeers);
+               newConnectedPeers = v.toArray(newConnectedPeers);
                if(logMINOR)
                        Logger.minor(this, "Connected peers (in getRandomPeer): 
" + newConnectedPeers.length + " was " + connectedPeers.length);
                connectedPeers = newConnectedPeers;
@@ -814,8 +810,8 @@
                return closestDist < nodeDist;
        }

-       public PeerNode closerPeer(PeerNode pn, Set routedTo, double loc, 
boolean ignoreSelf, boolean calculateMisrouting,
-               int minVersion, Vector addUnpickedLocsTo, Key key) {
+       public PeerNode closerPeer(PeerNode pn, Set<PeerNode> routedTo, double 
loc, boolean ignoreSelf, boolean calculateMisrouting,
+               int minVersion, List<Double> addUnpickedLocsTo, Key key) {
                return closerPeer(pn, routedTo, loc, ignoreSelf, 
calculateMisrouting, minVersion, addUnpickedLocsTo, 2.0, key);
        }

@@ -831,8 +827,8 @@
         * @param key The original key, if we have it, and if we want to 
consult with the FailureTable
         * to avoid routing to nodes which have recently failed for the same 
key.
         */
-       public PeerNode closerPeer(PeerNode pn, Set routedTo, double target, 
boolean ignoreSelf,
-               boolean calculateMisrouting, int minVersion, Vector 
addUnpickedLocsTo, double maxDistance, Key key) {
+       public PeerNode closerPeer(PeerNode pn, Set<PeerNode> routedTo, double 
target, boolean ignoreSelf,
+               boolean calculateMisrouting, int minVersion, List<Double> 
addUnpickedLocsTo, double maxDistance, Key key) {
                PeerNode[] peers;
                synchronized(this) {
                        peers = connectedPeers;
@@ -1441,11 +1437,11 @@
                        addPeerNodeStatuses(pnStatus, peerNode, peerNodeStatus, 
peerNodeStatusesDarknet, noLog);
        }

-       private void addPeerNodeStatuses(int pnStatus, PeerNode peerNode, 
Integer peerNodeStatus, HashMap statuses, boolean noLog) {
-               HashSet statusSet = null;
+       private void addPeerNodeStatuses(int pnStatus, PeerNode peerNode, 
Integer peerNodeStatus, HashMap<Integer, HashSet<PeerNode>> statuses, boolean 
noLog) {
+               HashSet<PeerNode> statusSet = null;
                synchronized(statuses) {
                        if(statuses.containsKey(peerNodeStatus)) {
-                               statusSet = (HashSet) 
statuses.get(peerNodeStatus);
+                               statusSet = statuses.get(peerNodeStatus);
                                if(statusSet.contains(peerNode)) {
                                        if(!noLog)
                                                Logger.error(this, 
"addPeerNodeStatus(): node already in peerNodeStatuses: " + peerNode + " status 
" + PeerNode.getPeerNodeStatusString(peerNodeStatus.intValue()));
@@ -1453,7 +1449,7 @@
                                }
                                statuses.remove(peerNodeStatus);
                        } else
-                               statusSet = new HashSet();
+                               statusSet = new HashSet<PeerNode>();
                        if(logMINOR)
                                Logger.minor(this, "addPeerNodeStatus(): adding 
PeerNode for '" + peerNode.getIdentityString() + "' with status '" + 
PeerNode.getPeerNodeStatusString(peerNodeStatus.intValue()) + "'");
                        statusSet.add(peerNode);
@@ -1467,13 +1463,13 @@
         */
        public int getPeerNodeStatusSize(int pnStatus, boolean darknet) {
                Integer peerNodeStatus = new Integer(pnStatus);
-               HashSet statusSet = null;
-               HashMap statuses = darknet ? peerNodeStatusesDarknet : 
this.peerNodeStatuses;
+               HashSet<PeerNode> statusSet = null;
+               HashMap<Integer, HashSet<PeerNode>> statuses = darknet ? 
peerNodeStatusesDarknet : this.peerNodeStatuses;
                synchronized(statuses) {
                        if(statuses.containsKey(peerNodeStatus))
-                               statusSet = (HashSet) 
statuses.get(peerNodeStatus);
+                               statusSet = statuses.get(peerNodeStatus);
                        else
-                               statusSet = new HashSet();
+                               statusSet = new HashSet<PeerNode>();
                        return statusSet.size();
                }
        }
@@ -1489,11 +1485,11 @@
                        removePeerNodeStatus(pnStatus, peerNodeStatus, 
peerNode, peerNodeStatusesDarknet, noLog);
        }

-       private void removePeerNodeStatus(int pnStatus, Integer peerNodeStatus, 
PeerNode peerNode, HashMap statuses, boolean noLog) {
-               HashSet statusSet = null;
+       private void removePeerNodeStatus(int pnStatus, Integer peerNodeStatus, 
PeerNode peerNode, HashMap<Integer, HashSet<PeerNode>> statuses, boolean noLog) 
{
+               HashSet<PeerNode> statusSet = null;
                synchronized(statuses) {
                        if(statuses.containsKey(peerNodeStatus)) {
-                               statusSet = (HashSet) 
statuses.get(peerNodeStatus);
+                               statusSet = statuses.get(peerNodeStatus);
                                if(!statusSet.contains(peerNode)) {
                                        if(!noLog)
                                                Logger.error(this, 
"removePeerNodeStatus(): identity '" + peerNode.getIdentityString() + " for " + 
peerNode.shortToString() + "' not in peerNodeStatuses with status '" + 
PeerNode.getPeerNodeStatusString(peerNodeStatus.intValue()) + "'", new 
Exception("debug"));
@@ -1502,7 +1498,7 @@
                                if(statuses.isEmpty())
                                        statuses.remove(peerNodeStatus);
                        } else
-                               statusSet = new HashSet();
+                               statusSet = new HashSet<PeerNode>();
                        if(logMINOR)
                                Logger.minor(this, "removePeerNodeStatus(): 
removing PeerNode for '" + peerNode.getIdentityString() + "' with status '" + 
PeerNode.getPeerNodeStatusString(peerNodeStatus.intValue()) + "'");
                        if(statusSet.contains(peerNode))
@@ -1515,16 +1511,16 @@
         */
        public void addPeerNodeRoutingBackoffReason(String 
peerNodeRoutingBackoffReason, PeerNode peerNode) {
                synchronized(peerNodeRoutingBackoffReasons) {
-                       HashSet reasonSet = null;
+                       HashSet<PeerNode> reasonSet = null;
                        
if(peerNodeRoutingBackoffReasons.containsKey(peerNodeRoutingBackoffReason)) {
-                               reasonSet = (HashSet) 
peerNodeRoutingBackoffReasons.get(peerNodeRoutingBackoffReason);
+                               reasonSet = 
peerNodeRoutingBackoffReasons.get(peerNodeRoutingBackoffReason);
                                if(reasonSet.contains(peerNode)) {
                                        Logger.error(this, 
"addPeerNodeRoutingBackoffReason(): identity '" + peerNode.getIdentityString() 
+ "' already in peerNodeRoutingBackoffReasons as " + peerNode.getPeer() + " 
with status code " + peerNodeRoutingBackoffReason);
                                        return;
                                }
                                
peerNodeRoutingBackoffReasons.remove(peerNodeRoutingBackoffReason);
                        } else
-                               reasonSet = new HashSet();
+                               reasonSet = new HashSet<PeerNode>();
                        if(logMINOR)
                                Logger.minor(this, 
"addPeerNodeRoutingBackoffReason(): adding PeerNode for '" + 
peerNode.getIdentityString() + "' with status code " + 
peerNodeRoutingBackoffReason);
                        reasonSet.add(peerNode);
@@ -1538,7 +1534,7 @@
        public String[] getPeerNodeRoutingBackoffReasons() {
                String[] reasonStrings;
                synchronized(peerNodeRoutingBackoffReasons) {
-                       reasonStrings = (String[]) 
peerNodeRoutingBackoffReasons.keySet().toArray(new 
String[peerNodeRoutingBackoffReasons.size()]);
+                       reasonStrings = 
peerNodeRoutingBackoffReasons.keySet().toArray(new 
String[peerNodeRoutingBackoffReasons.size()]);
                }
                Arrays.sort(reasonStrings);
                return reasonStrings;
@@ -1548,10 +1544,10 @@
         * How many PeerNodes have a particular routing backoff reason?
         */
        public int getPeerNodeRoutingBackoffReasonSize(String 
peerNodeRoutingBackoffReason) {
-               HashSet reasonSet = null;
+               HashSet<PeerNode> reasonSet = null;
                synchronized(peerNodeRoutingBackoffReasons) {
                        
if(peerNodeRoutingBackoffReasons.containsKey(peerNodeRoutingBackoffReason)) {
-                               reasonSet = (HashSet) 
peerNodeRoutingBackoffReasons.get(peerNodeRoutingBackoffReason);
+                               reasonSet = 
peerNodeRoutingBackoffReasons.get(peerNodeRoutingBackoffReason);
                                return reasonSet.size();
                        } else
                                return 0;
@@ -1562,17 +1558,17 @@
         * Remove a PeerNode routing backoff reason from the map
         */
        public void removePeerNodeRoutingBackoffReason(String 
peerNodeRoutingBackoffReason, PeerNode peerNode) {
-               HashSet reasonSet = null;
+               HashSet<PeerNode> reasonSet = null;
                synchronized(peerNodeRoutingBackoffReasons) {
                        
if(peerNodeRoutingBackoffReasons.containsKey(peerNodeRoutingBackoffReason)) {
-                               reasonSet = (HashSet) 
peerNodeRoutingBackoffReasons.get(peerNodeRoutingBackoffReason);
+                               reasonSet = 
peerNodeRoutingBackoffReasons.get(peerNodeRoutingBackoffReason);
                                if(!reasonSet.contains(peerNode)) {
                                        Logger.error(this, 
"removePeerNodeRoutingBackoffReason(): identity '" + 
peerNode.getIdentityString() + "' not in peerNodeRoutingBackoffReasons with 
status code " + peerNodeRoutingBackoffReason, new Exception("debug"));
                                        return;
                                }
                                
peerNodeRoutingBackoffReasons.remove(peerNodeRoutingBackoffReason);
                        } else
-                               reasonSet = new HashSet();
+                               reasonSet = new HashSet<PeerNode>();
                        if(logMINOR)
                                Logger.minor(this, 
"removePeerNodeRoutingBackoffReason(): removing PeerNode for '" + 
peerNode.getIdentityString() + "' with status code " + 
peerNodeRoutingBackoffReason);
                        if(reasonSet.contains(peerNode))
@@ -1640,12 +1636,12 @@
                        peers = myPeers;
                }
                // FIXME optimise! Maybe maintain as a separate list?
-               Vector v = new Vector(myPeers.length);
+               Vector<PeerNode> v = new Vector<PeerNode>(myPeers.length);
                for(int i = 0; i < peers.length; i++) {
                        if(peers[i] instanceof DarknetPeerNode)
                                v.add(peers[i]);
                }
-               return (DarknetPeerNode[]) v.toArray(new 
DarknetPeerNode[v.size()]);
+               return v.toArray(new DarknetPeerNode[v.size()]);
        }

        public Vector<SeedServerPeerNode> 
getConnectedSeedServerPeersVector(HashSet<ByteArrayWrapper> exclude) {
@@ -1655,34 +1651,35 @@
                }
                // FIXME optimise! Maybe maintain as a separate list?
                Vector<SeedServerPeerNode> v = new 
Vector<SeedServerPeerNode>(myPeers.length);
-               for(int i = 0; i < peers.length; i++) {
-                       if(peers[i] instanceof SeedServerPeerNode) {
-                               if(exclude != null && exclude.contains(new 
ByteArrayWrapper(peers[i].getIdentity()))) {
+               for(PeerNode p : peers) {
+                       if(p instanceof SeedServerPeerNode) {
+                               SeedServerPeerNode sspn = (SeedServerPeerNode) 
p;
+                               if(exclude != null && exclude.contains(new 
ByteArrayWrapper(sspn.getIdentity()))) {
                                        if(logMINOR)
-                                               Logger.minor(this, "Not 
including in getConnectedSeedServerPeersVector() as in exclude set: " + 
peers[i].userToString());
+                                               Logger.minor(this, "Not 
including in getConnectedSeedServerPeersVector() as in exclude set: " + 
sspn.userToString());
                                        continue;
                                }
-                               if(!peers[i].isConnected()) {
+                               if(!sspn.isConnected()) {
                                        if(logMINOR)
-                                               Logger.minor(this, "Not 
including in getConnectedSeedServerPeersVector() as disconnected: " + 
peers[i].userToString());
+                                               Logger.minor(this, "Not 
including in getConnectedSeedServerPeersVector() as disconnected: " + 
sspn.userToString());
                                        continue;
                                }
-                               v.add((SeedServerPeerNode)peers[i]);
+                               v.add(sspn);
                        }
                }
                return v;
        }

-       public Vector getSeedServerPeersVector() {
+       public List<SeedServerPeerNode> getSeedServerPeersVector() {
                PeerNode[] peers;
                synchronized(this) {
                        peers = myPeers;
                }
                // FIXME optimise! Maybe maintain as a separate list?
-               Vector v = new Vector(myPeers.length);
-               for(int i = 0; i < peers.length; i++) {
-                       if(peers[i] instanceof SeedServerPeerNode)
-                               v.add(peers[i]);
+               List<SeedServerPeerNode> v = new 
ArrayList<SeedServerPeerNode>(myPeers.length);
+               for(PeerNode peer : peers) {
+                       if(peer instanceof SeedServerPeerNode)
+                               v.add((SeedServerPeerNode)peer);
                }
                return v;
        }
@@ -1696,12 +1693,12 @@
                        peers = myPeers;
                }
                // FIXME optimise! Maybe maintain as a separate list?
-               Vector v = new Vector(myPeers.length);
+               Vector<PeerNode> v = new Vector<PeerNode>(myPeers.length);
                for(int i = 0; i < peers.length; i++) {
                        if(peers[i] instanceof OpennetPeerNode)
                                v.add(peers[i]);
                }
-               return (OpennetPeerNode[]) v.toArray(new 
OpennetPeerNode[v.size()]);
+               return v.toArray(new OpennetPeerNode[v.size()]);
        }

        public boolean anyConnectedPeerHasAddress(FreenetInetAddress addr, 
PeerNode pn) {
@@ -1725,18 +1722,17 @@

        public void removeOpennetPeers() {
                synchronized(this) {
-                       Vector keep = new Vector();
-                       Vector conn = new Vector();
-                       for(int i = 0; i < myPeers.length; i++) {
-                               PeerNode pn = myPeers[i];
+                       ArrayList<PeerNode> keep = new ArrayList<PeerNode>();
+                       ArrayList<PeerNode> conn = new ArrayList<PeerNode>();
+                       for(PeerNode pn : myPeers) {
                                if(pn instanceof OpennetPeerNode)
                                        continue;
                                keep.add(pn);
                                if(pn.isConnected())
                                        conn.add(pn);
                        }
-                       myPeers = (PeerNode[]) keep.toArray(new 
PeerNode[keep.size()]);
-                       connectedPeers = (PeerNode[]) keep.toArray(new 
PeerNode[conn.size()]);
+                       myPeers = keep.toArray(new PeerNode[keep.size()]);
+                       connectedPeers = keep.toArray(new 
PeerNode[conn.size()]);
                }
                updatePMUserAlert();
        }

Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java        2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/PeerNode.java        2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -8,6 +8,7 @@
 import java.io.Writer;
 import java.lang.ref.WeakReference;
 import java.math.BigInteger;
+import java.net.InetAddress;
 import java.net.MalformedURLException;
 import java.net.UnknownHostException;
 import java.security.MessageDigest;
@@ -16,9 +17,6 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.ListIterator;
 import java.util.Vector;
 import java.util.zip.DataFormatException;
 import java.util.zip.Inflater;
@@ -64,7 +62,6 @@
 import freenet.support.Fields;
 import freenet.support.HexUtil;
 import freenet.support.IllegalBase64Exception;
-import freenet.support.LRUHashtable;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
 import freenet.support.TimeUtil;
@@ -74,7 +71,6 @@
 import freenet.support.math.TimeDecayingRunningAverage;
 import freenet.support.transport.ip.HostnameSyntaxException;
 import freenet.support.transport.ip.IPUtil;
-import java.net.InetAddress;

 /**
  * @author amphibian
@@ -569,7 +565,7 @@
                        Logger.normal(this, "No IP addresses found for identity 
'" + Base64.encode(identity) + "', possibly at location '" + 
Double.toString(currentLocation) + ": " + userToString());
                        detectedPeer = null;
                } else {
-                       detectedPeer = (Peer) nominalPeer.firstElement();
+                       detectedPeer = nominalPeer.firstElement();
                }
                updateShortToString();

@@ -821,7 +817,7 @@
                HashSet<Peer> ret = new HashSet<Peer>();
                for(int i = 0; i < localHandshakeIPs.length; i++)
                        ret.add(localHandshakeIPs[i]);
-               return (Peer[]) ret.toArray(new Peer[ret.size()]);
+               return ret.toArray(new Peer[ret.size()]);
        }

        /**
@@ -847,7 +843,7 @@

                // Don't synchronize while doing lookups which may take a long 
time!
                synchronized(this) {
-                       myNominalPeer = (Peer[]) nominalPeer.toArray(new 
Peer[nominalPeer.size()]);
+                       myNominalPeer = nominalPeer.toArray(new 
Peer[nominalPeer.size()]);
                }

                Peer[] localHandshakeIPs;
@@ -911,7 +907,7 @@
                        peers.add(p);
                }

-               localHandshakeIPs = (Peer[]) peers.toArray(new 
Peer[peers.size()]);
+               localHandshakeIPs = peers.toArray(new Peer[peers.size()]);
                localHandshakeIPs = updateHandshakeIPs(localHandshakeIPs, 
ignoreHostnames);
                synchronized(this) {
                        handshakeIPs = localHandshakeIPs;
@@ -2325,13 +2321,13 @@
                                        Logger.minor(this, "Invalid or null 
location, waiting for FNPLocChangeNotification: " + e);
                        }
                }
-               Vector oldNominalPeer = nominalPeer;
+               Vector<Peer> oldNominalPeer = nominalPeer;

                if(nominalPeer == null)
                        nominalPeer = new Vector<Peer>();
                nominalPeer.removeAllElements();

-               Peer[] oldPeers = (Peer[]) nominalPeer.toArray(new 
Peer[nominalPeer.size()]);
+               Peer[] oldPeers = nominalPeer.toArray(new 
Peer[nominalPeer.size()]);

                boolean refHadPhysicalUDP = false;

@@ -2631,7 +2627,7 @@
        * Requeue ResendPacketItem[]s if they are not sent.
        * @param resendItems
        */
-       public void requeueResendItems(Vector resendItems) {
+       public void requeueResendItems(Vector<ResendPacketItem> resendItems) {
                KeyTracker cur,
                 prev,
                 unv;
@@ -2640,8 +2636,7 @@
                        prev = previousTracker;
                        unv = unverifiedTracker;
                }
-               for(int i = 0; i < resendItems.size(); i++) {
-                       ResendPacketItem item = (ResendPacketItem) 
resendItems.get(i);
+               for(ResendPacketItem item : resendItems) {
                        if(item.pn != this)
                                throw new IllegalArgumentException("item.pn != 
this!");
                        KeyTracker kt = cur;
@@ -2878,7 +2873,6 @@
        // We want to get reasonably early feedback if it's dropping all of 
them...

        final static int MAX_PINGS = 5;
-       final LRUHashtable pingsSentTimes = new LRUHashtable();
        long pingNumber;
        private final RunningAverage pingAverage;

@@ -2935,7 +2929,7 @@
                messageSpecName = m.getSpec().getName();
                // Synchronize to make increments atomic.
                synchronized(this) {
-                       count = (Long) 
localNodeSentMessageTypes.get(messageSpecName);
+                       count = localNodeSentMessageTypes.get(messageSpecName);
                        if(count == null)
                                count = 1L;
                        else
@@ -2951,7 +2945,7 @@
                messageSpecName = m.getSpec().getName();
                // Synchronize to make increments atomic.
                synchronized(localNodeReceivedMessageTypes) {
-                       count = (Long) 
localNodeReceivedMessageTypes.get(messageSpecName);
+                       count = 
localNodeReceivedMessageTypes.get(messageSpecName);
                        if(count == null)
                                count = 1L;
                        else
@@ -3749,7 +3743,7 @@
                return -1;
        }

-       public WeakReference getWeakRef() {
+       public WeakReference<PeerNode> getWeakRef() {
                return myRef;
        }

@@ -3799,12 +3793,12 @@
                if(validIPs.isEmpty()) {
                        ret = null;
                } else if(validIPs.size() == 1) {
-                       ret = (Peer) validIPs.get(0);
+                       ret = validIPs.get(0);
                } else {
                        synchronized(this) {
                                if(handshakeIPAlternator >= validIPs.size())
                                        handshakeIPAlternator = 0;
-                               ret = (Peer) 
validIPs.get(handshakeIPAlternator);
+                               ret = validIPs.get(handshakeIPAlternator);
                                handshakeIPAlternator++;
                        }
                }
@@ -4017,7 +4011,7 @@
         * @param rpiTemp
         * @param rpiTemp
         */
-       public boolean maybeSendPacket(long now, Vector rpiTemp, int[] 
rpiIntTemp) {
+       public boolean maybeSendPacket(long now, Vector<ResendPacketItem> 
rpiTemp, int[] rpiIntTemp) {
                // If there are any urgent notifications, we must send a packet.
                boolean mustSend = false;
                if(mustSendNotificationsNow(now)) {
@@ -4041,7 +4035,7 @@
                                continue;
                        rpiIntTemp = tmp;
                        for(int k = 0; k < rpiTemp.size(); k++) {
-                               ResendPacketItem item = (ResendPacketItem) 
rpiTemp.get(k);
+                               ResendPacketItem item = rpiTemp.get(k);
                                if(item == null)
                                        continue;
                                try {

Modified: trunk/freenet/src/freenet/node/PeerNodeStatus.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNodeStatus.java  2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/PeerNodeStatus.java  2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -5,10 +5,10 @@

 import java.util.Map;

+import freenet.clients.http.DarknetConnectionsToadlet;
 import freenet.io.comm.Peer;
 import freenet.io.xfer.PacketThrottle;
 import freenet.support.Logger;
-import java.util.SortedSet;

 /**
  * Contains various status information for a {@link PeerNode}. Used e.g. in
@@ -65,9 +65,9 @@

        private long peerAddedTime;

-       private Map localMessagesReceived;
+       private Map<String,Long> localMessagesReceived;

-       private Map localMessagesSent;
+       private Map<String,Long> localMessagesSent;

        private final int hashCode;

@@ -156,14 +156,14 @@
        /**
         * @return the localMessagesReceived
         */
-       public Map getLocalMessagesReceived() {
+       public Map<String, Long> getLocalMessagesReceived() {
                return localMessagesReceived;
        }

        /**
         * @return the localMessagesSent
         */
-       public Map getLocalMessagesSent() {
+       public Map<String, Long> getLocalMessagesSent() {
                return localMessagesSent;
        }


Modified: trunk/freenet/src/freenet/node/RequestSender.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestSender.java   2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/RequestSender.java   2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -5,7 +5,6 @@

 import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.Iterator;

 import freenet.crypt.CryptFormatException;
 import freenet.crypt.DSAPublicKey;
@@ -78,7 +77,7 @@
     /** If true, only try to fetch the key from nodes which have offered it */
     private boolean tryOffersOnly;

-       private ArrayList listeners=new ArrayList();
+       private ArrayList<Listener> listeners=new ArrayList<Listener>();

     // Terminal status
     // Always set finished AFTER setting the reason flag
@@ -446,7 +445,7 @@

                int routeAttempts=0;
                int rejectOverloads=0;
-        HashSet nodesRoutedTo = new HashSet();
+        HashSet<PeerNode> nodesRoutedTo = new HashSet<PeerNode>();
         PeerNode next = null;
         while(true) {
             /*
@@ -1317,9 +1316,7 @@
                synchronized (listeners) {
                        if(sentReceivedRejectOverload) return;
                        sentReceivedRejectOverload = true;
-                       Iterator i=listeners.iterator();
-                       while (i.hasNext()) {
-                               Listener l=(Listener)i.next();
+                       for (Listener l : listeners) {
                                try {
                                        l.onReceivedRejectOverload();
                                } catch (Throwable t) {
@@ -1334,9 +1331,7 @@
        private void fireCHKTransferBegins() {
                synchronized (listeners) {
                        sentCHKTransferBegins = true;
-                       Iterator i=listeners.iterator();
-                       while (i.hasNext()) {
-                               Listener l=(Listener)i.next();
+                       for (Listener l : listeners) {
                                try {
                                        l.onCHKTransferBegins();
                                } catch (Throwable t) {
@@ -1351,9 +1346,7 @@
        private void fireRequestSenderFinished(int status) {
                synchronized (listeners) {
                        sentRequestSenderFinished = true;
-                       Iterator i=listeners.iterator();
-                       while (i.hasNext()) {
-                               Listener l=(Listener)i.next();
+                       for (Listener l : listeners) {
                                try {
                                        l.onRequestSenderFinished(status);
                                } catch (Throwable t) {

Modified: trunk/freenet/src/freenet/node/RequestStarter.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestStarter.java  2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/RequestStarter.java  2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -73,7 +73,7 @@
                this.averageInputBytesPerRequest = averageInputBytesPerRequest;
                this.isInsert = isInsert;
                this.isSSK = isSSK;
-               if(!isInsert) keysFetching = new HashSet();
+               if(!isInsert) keysFetching = new HashSet<Key>();
        }

        void setScheduler(RequestScheduler sched) {
@@ -181,7 +181,7 @@
         * we'd move this to node but only track keys we are fetching at max 
HTL.
         * LOCKING: Always lock this LAST.
         */
-       private HashSet keysFetching;
+       private HashSet<Key> keysFetching;

        private boolean startRequest(SendableRequest req, boolean logMINOR) {
                // Create a thread to handle starting the request, and the 
resulting feedback

Modified: trunk/freenet/src/freenet/node/RequestStarterGroup.java
===================================================================
--- trunk/freenet/src/freenet/node/RequestStarterGroup.java     2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/RequestStarterGroup.java     2008-11-06 
13:53:57 UTC (rev 23351)
@@ -201,9 +201,9 @@
                MyRequestThrottle throttle = getThrottle(isSSK, isInsert);
                sb.append(TimeUtil.formatTime((long)throttle.getRTT(), 2, 
true));
                sb.append(" delay=");
-               sb.append(TimeUtil.formatTime((long)throttle.getDelay(), 2, 
true));
+               sb.append(TimeUtil.formatTime(throttle.getDelay(), 2, true));
                sb.append(" bw=");
-               sb.append((long)throttle.getRate());
+               sb.append(throttle.getRate());
                sb.append("B/sec");
                return sb.toString();
        }

Modified: trunk/freenet/src/freenet/node/ResettingHTLProbeRequestSender.java
===================================================================
--- trunk/freenet/src/freenet/node/ResettingHTLProbeRequestSender.java  
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/ResettingHTLProbeRequestSender.java  
2008-11-06 13:53:57 UTC (rev 23351)
@@ -5,7 +5,6 @@

 import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.Iterator;

 import freenet.io.comm.ByteCounter;
 import freenet.io.comm.DMT;
@@ -50,7 +49,7 @@
     final PeerNode source;
     private boolean hasForwarded;

-       private ArrayList listeners=new ArrayList();
+       private ArrayList<Listener> listeners=new ArrayList<Listener>();

     private static boolean logMINOR;

@@ -100,7 +99,7 @@
     private void realRun() {
                int routeAttempts=0;
                int rejectOverloads=0;
-        HashSet nodesRoutedTo = new HashSet();
+        HashSet<PeerNode> nodesRoutedTo = new HashSet<PeerNode>();
         while(true) {
             if(logMINOR) Logger.minor(this, "htl="+htl);
             if(htl == 0) {
@@ -358,9 +357,7 @@
                uniqueCounter = (short) (uniqueCounter + this.uniqueCounter);
                linearCounter = (short) (linearCounter + this.linearCounter);
                synchronized (listeners) {
-                       Iterator i=listeners.iterator();
-                       while (i.hasNext()) {
-                               Listener l=(Listener)i.next();
+                       for (Listener l : listeners) {
                                try {
                                        l.onTrace(uid, nearest, best, htl, 
counter, uniqueCounter, location, myUID,
                                                        peerLocs, peerUIDs, 
(short)0, linearCounter, reason, prevUID);
@@ -477,9 +474,7 @@

        private void fireReceivedRejectOverload(double nearest, double best, 
short counter, short uniqueCounter, short linearCounter, String reason) {
                synchronized (listeners) {
-                       Iterator i=listeners.iterator();
-                       while (i.hasNext()) {
-                               Listener l=(Listener)i.next();
+                       for (Listener l : listeners) {
                                try {
                                        l.onReceivedRejectOverload(nearest, 
best, counter, uniqueCounter, linearCounter, reason);
                                } catch (Throwable t) {
@@ -491,9 +486,7 @@

        private void fireCompletion() {
                synchronized (listeners) {
-                       Iterator i=listeners.iterator();
-                       while (i.hasNext()) {
-                               Listener l=(Listener)i.next();
+                       for (Listener l : listeners) {
                                try {
                                        l.onCompletion(nearestLoc, best, 
counter, uniqueCounter, linearCounter);
                                } catch (Throwable t) {
@@ -505,9 +498,7 @@

     private void fireRNF() {
                synchronized (listeners) {
-                       Iterator i=listeners.iterator();
-                       while (i.hasNext()) {
-                               Listener l=(Listener)i.next();
+                       for (Listener l : listeners) {
                                try {
                                        l.onRNF(htl, nearestLoc, best, counter, 
uniqueCounter, linearCounter);
                                } catch (Throwable t) {
@@ -519,9 +510,7 @@

     private void fireTimeout(String reason) {
                synchronized (listeners) {
-                       Iterator i=listeners.iterator();
-                       while (i.hasNext()) {
-                               Listener l=(Listener)i.next();
+                       for (Listener l : listeners) {
                                try {
                                        l.onTimeout(nearestLoc, best, counter, 
uniqueCounter, linearCounter, reason);
                                } catch (Throwable t) {
@@ -533,9 +522,9 @@

        private void updateBest() {
                PeerNode[] nodes = node.peers.myPeers;
-               for(int i=0;i<nodes.length;i++) {
-                       if(!nodes[i].isConnected()) continue;
-                       double loc = nodes[i].getLocation();
+               for(PeerNode node : nodes) {
+                       if(!node.isConnected()) continue;
+                       double loc = node.getLocation();
                        if(loc < target)
                                continue;
                        if(loc > target && loc < best)

Modified: trunk/freenet/src/freenet/node/SSKInsertSender.java
===================================================================
--- trunk/freenet/src/freenet/node/SSKInsertSender.java 2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/SSKInsertSender.java 2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -120,7 +120,7 @@
        }

     private void realRun() {
-        HashSet nodesRoutedTo = new HashSet();
+        HashSet<PeerNode> nodesRoutedTo = new HashSet<PeerNode>();

         PeerNode next = null;
         while(true) {

Modified: trunk/freenet/src/freenet/node/SecurityLevels.java
===================================================================
--- trunk/freenet/src/freenet/node/SecurityLevels.java  2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/SecurityLevels.java  2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -218,10 +218,6 @@
                        listeners.add(listener);
                }

-               public void setPossibleValues(String[] val) {
-                       throw new UnsupportedOperationException();
-               }
-               
                @Override
                public void set(String val) throws InvalidConfigValueException, 
NodeNeedRestartException {
                        T oldLevel = getValue();

Modified: trunk/freenet/src/freenet/node/SeedServerPeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/SeedServerPeerNode.java      2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/SeedServerPeerNode.java      2008-11-06 
13:53:57 UTC (rev 23351)
@@ -4,7 +4,7 @@
 package freenet.node;

 import java.net.InetAddress;
-import java.util.Vector;
+import java.util.ArrayList;

 import freenet.io.comm.Peer;
 import freenet.io.comm.PeerParseException;
@@ -91,13 +91,13 @@

        public InetAddress[] getInetAddresses() {
                Peer[] peers = getHandshakeIPs();
-               Vector v = new Vector();
+               ArrayList<InetAddress> v = new ArrayList<InetAddress>();
                for(int i=0;i<peers.length;i++) {
                        InetAddress ia = 
peers[i].getFreenetAddress().dropHostname().getAddress();
                        if(v.contains(ia)) continue;
                        v.add(ia);
                }
-               return (InetAddress[]) v.toArray(new InetAddress[v.size()]);
+               return v.toArray(new InetAddress[v.size()]);
        }

        @Override

Modified: trunk/freenet/src/freenet/node/SemiOrderedShutdownHook.java
===================================================================
--- trunk/freenet/src/freenet/node/SemiOrderedShutdownHook.java 2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/SemiOrderedShutdownHook.java 2008-11-06 
13:53:57 UTC (rev 23351)
@@ -5,12 +5,12 @@
 public class SemiOrderedShutdownHook extends Thread {

        private static final int TIMEOUT = 100*1000;
-       private final ArrayList earlyJobs;
-       private final ArrayList lateJobs;
+       private final ArrayList<Thread> earlyJobs;
+       private final ArrayList<Thread> lateJobs;

        public SemiOrderedShutdownHook() {
-               earlyJobs = new ArrayList();
-               lateJobs = new ArrayList();
+               earlyJobs = new ArrayList<Thread>();
+               lateJobs = new ArrayList<Thread>();
        }

        public synchronized void addEarlyJob(Thread r) {
@@ -25,12 +25,10 @@
        public void run() {
                // First run early jobs, all at once, and wait for them to all 
complete.

-               for(int i=0;i<earlyJobs.size();i++) {
-                       Thread r = (Thread) earlyJobs.get(i);
+               for(Thread r : earlyJobs) {
                        r.start();
                }
-               for(int i=0;i<earlyJobs.size();i++) {
-                       Thread r = (Thread) earlyJobs.get(i);
+               for(Thread r : earlyJobs) {
                        try {
                                r.join(TIMEOUT);
                        } catch (InterruptedException e) {
@@ -40,12 +38,10 @@
                }

                // Then run late jobs, all at once, and wait for them to all 
complete (JVM will exit when we return).
-               for(int i=0;i<lateJobs.size();i++) {
-                       Thread r = (Thread) lateJobs.get(i);
+               for(Thread r : lateJobs) {
                        r.start();
                }
-               for(int i=0;i<lateJobs.size();i++) {
-                       Thread r = (Thread) lateJobs.get(i);
+               for(Thread r : lateJobs) {
                        try {
                                r.join(TIMEOUT);
                        } catch (InterruptedException e) {

Deleted: trunk/freenet/src/freenet/node/StaticSwapRequestInterval.java
===================================================================
--- trunk/freenet/src/freenet/node/StaticSwapRequestInterval.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/StaticSwapRequestInterval.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,21 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.node;
-
-public class StaticSwapRequestInterval implements SwapRequestInterval {
-
-    int fixedInterval;
-    
-    public StaticSwapRequestInterval(int d) {
-        fixedInterval = d;
-    }
-    
-    public int getValue() {
-        return fixedInterval;
-    }
-
-       public void set(int val) {
-               this.fixedInterval = val;
-       }
-}

Deleted: trunk/freenet/src/freenet/node/SwapRequestInterval.java
===================================================================
--- trunk/freenet/src/freenet/node/SwapRequestInterval.java     2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/SwapRequestInterval.java     2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,11 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.node;
-
-/**
- * Interface to get the current swap request interval
- */
-public interface SwapRequestInterval {
-    int getValue();
-}

Modified: trunk/freenet/src/freenet/node/SyncSendWaitedTooLongException.java
===================================================================
--- trunk/freenet/src/freenet/node/SyncSendWaitedTooLongException.java  
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/SyncSendWaitedTooLongException.java  
2008-11-06 13:53:57 UTC (rev 23351)
@@ -6,6 +6,7 @@
  * from bandwidth limiting and don't get it within a timeout period.
  * @author toad
  */
+ at SuppressWarnings("serial")
 public class SyncSendWaitedTooLongException extends Exception {

 }

Modified: trunk/freenet/src/freenet/node/TextModeClientInterface.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterface.java 2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/TextModeClientInterface.java 2008-11-06 
13:53:57 UTC (rev 23351)
@@ -20,8 +20,8 @@
 import java.net.URL;
 import java.net.URLConnection;
 import java.text.NumberFormat;
+import java.util.Arrays;
 import java.util.HashMap;
-import java.util.Hashtable;

 import freenet.client.ClientMetadata;
 import freenet.client.DefaultMIMETypes;
@@ -50,7 +50,6 @@
 import freenet.support.io.ArrayBucketFactory;
 import freenet.support.io.BucketTools;
 import freenet.support.io.FileBucket;
-import java.util.Arrays;

 /**
  * @author amphibian
@@ -65,7 +64,6 @@
     final Node n;
     final NodeClientCore core;
     final HighLevelSimpleClient client;
-    final Hashtable streams;
     final File downloadsDir;
     final InputStream in;
     final OutputStream out;
@@ -76,7 +74,6 @@
        this.core = server.n.clientCore;
        this.r = server.r;
         client = core.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS, 
true);
-       this.streams = new Hashtable();
        this.downloadsDir = server.downloadsDir;
        this.in = in;
        this.out = out;
@@ -88,7 +85,6 @@
        this.r = n.random;
        this.core = n.clientCore;
        this.client = c;
-       this.streams = new Hashtable();
        this.downloadsDir = downloadDir;
        this.in = in;
        this.out = out;
@@ -405,9 +401,9 @@
                return true;
         } else if(uline.startsWith("MEMSTAT")) {
                Runtime rt = Runtime.getRuntime();
-               float freeMemory = (float) rt.freeMemory();
-               float totalMemory = (float) rt.totalMemory();
-               float maxMemory = (float) rt.maxMemory();
+               float freeMemory = rt.freeMemory();
+               float totalMemory = rt.totalMemory();
+               float maxMemory = rt.maxMemory();

                long usedJavaMem = (long)(totalMemory - freeMemory);
                long allocatedJavaMem = (long)totalMemory;
@@ -520,7 +516,7 @@
                        }
                }

-               HashMap bucketsByName =
+               HashMap<String, Object> bucketsByName =
                        makeBucketsByName(line);

                if(defaultFile == null) {
@@ -991,7 +987,7 @@
      * Create a map of String -> Bucket for every file in a directory
      * and its subdirs.
      */
-    private HashMap makeBucketsByName(String directory) {
+    private HashMap<String, Object> makeBucketsByName(String directory) {

        if (!directory.endsWith("/"))
                directory = directory + '/';
@@ -999,7 +995,7 @@

        System.out.println("Listing dir: "+thisdir);

-       HashMap ret = new HashMap();
+       HashMap<String, Object> ret = new HashMap<String, Object>();

        File filelist[] = thisdir.listFiles();
        if(filelist == null)
@@ -1015,7 +1011,7 @@

                        ret.put(f.getName(), bucket);
                } else if(filelist[i].isDirectory()) {
-                       HashMap subdir = makeBucketsByName(directory + 
filelist[i].getName());
+                       HashMap<String, Object> subdir = 
makeBucketsByName(directory + filelist[i].getName());
                        ret.put(filelist[i].getName(), subdir);
                }
                }

Modified: trunk/freenet/src/freenet/node/TextModeClientInterfaceServer.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterfaceServer.java   
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/TextModeClientInterfaceServer.java   
2008-11-06 13:53:57 UTC (rev 23351)
@@ -10,7 +10,6 @@
 import java.net.Socket;
 import java.net.SocketException;
 import java.net.SocketTimeoutException;
-import java.util.Hashtable;

 import freenet.client.HighLevelSimpleClient;
 import freenet.config.Config;
@@ -30,8 +29,6 @@
     final RandomSource r;
     final Node n;
     final NodeClientCore core;
-//    final HighLevelSimpleClient client;
-    final Hashtable streams;
     final File downloadsDir;
     int port;
     String bindTo;
@@ -44,7 +41,6 @@
        this.n = node;
        this.core = n.clientCore;
         this.r = n.random;
-        streams = new Hashtable();
         this.downloadsDir = core.downloadDir;
         this.port=port;
         this.bindTo=bindTo;

Modified: trunk/freenet/src/freenet/node/UptimeEstimator.java
===================================================================
--- trunk/freenet/src/freenet/node/UptimeEstimator.java 2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/UptimeEstimator.java 2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -101,8 +101,7 @@
        public void run() {
                synchronized(this) {
                        wasOnline[slot] = true;
-                       slot++;
-                       if(slot == wasOnline.length) slot = 0;
+                       slot = (slot + 1) % wasOnline.length;
                }
                long now = System.currentTimeMillis();
                if(logFile.length() > wasOnline.length*4L) {

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2008-11-06 13:50:42 UTC (rev 
23350)
+++ trunk/freenet/src/freenet/node/Version.java 2008-11-06 13:53:57 UTC (rev 
23351)
@@ -24,17 +24,17 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       private static final int buildNumber = 1169;
+       private static final int buildNumber = 1168;

        /** Oldest build of Fred we will talk to */
-       private static final int oldLastGoodBuild = 1168;
-       private static final int newLastGoodBuild = 1169;
+       private static final int oldLastGoodBuild = 1165;
+       private static final int newLastGoodBuild = 1168;
        static final long transitionTime;

        static {
                final Calendar _cal = 
Calendar.getInstance(TimeZone.getTimeZone("GMT"));
                // year, month - 1 (or constant), day, hour, minute, second
-               _cal.set( 2008, Calendar.NOVEMBER, 10, 0, 0, 0 );
+               _cal.set( 2008, Calendar.OCTOBER, 31, 0, 0, 0 );
                transitionTime = _cal.getTimeInMillis();
        }


Modified: trunk/freenet/src/freenet/node/fcp/ClientGet.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientGet.java   2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/fcp/ClientGet.java   2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -150,8 +150,9 @@
                fctx.maxTempLength = message.maxTempSize;

                if(message.allowedMIMETypes != null) {
-                       fctx.allowedMIMETypes = new HashSet();
-                       for(int i=0;i<message.allowedMIMETypes.length;i++) 
fctx.allowedMIMETypes.add(message.allowedMIMETypes[i]);
+                       fctx.allowedMIMETypes = new HashSet<String>();
+                       for(String mime : message.allowedMIMETypes) 
+                               fctx.allowedMIMETypes.add(mime);
                }

                this.returnType = message.returnType;
@@ -577,7 +578,8 @@
                fs.putSingle("Finished", Boolean.toString(finished));
                fs.putSingle("Succeeded", Boolean.toString(succeeded));
                if(fctx.allowedMIMETypes != null)
-                       fs.putOverwrite("AllowedMIMETypes", (String[]) 
fctx.allowedMIMETypes.toArray(new String[fctx.allowedMIMETypes.size()]));
+                       fs.putOverwrite("AllowedMIMETypes", (String[]) 
+                                       fctx.allowedMIMETypes.toArray(new 
String[fctx.allowedMIMETypes.size()]));
                if(finished) {
                        if(succeeded) {
                                fs.putSingle("FoundDataLength", 
Long.toString(foundDataLength));

Modified: trunk/freenet/src/freenet/node/fcp/ClientPut.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPut.java   2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/node/fcp/ClientPut.java   2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -119,11 +119,11 @@
                Bucket tempData = data;
                ClientMetadata cm = new ClientMetadata(mimeType);
                boolean isMetadata = false;
-               boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
+               logMINOR = Logger.shouldLog(Logger.MINOR, this);
                if(logMINOR) Logger.minor(this, "data = "+tempData+", 
uploadFrom = "+ClientPutMessage.uploadFromString(uploadFrom));
                if(uploadFrom == ClientPutMessage.UPLOAD_FROM_REDIRECT) {
                        this.targetURI = redirectTarget;
-                       Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
targetURI, cm);
+                       Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
null, null, targetURI, cm);
                        byte[] d;
                        try {
                                d = m.writeToByteArray();
@@ -205,7 +205,7 @@
                if(logMINOR) Logger.minor(this, "data = "+tempData+", 
uploadFrom = "+ClientPutMessage.uploadFromString(uploadFrom));
                if(uploadFrom == ClientPutMessage.UPLOAD_FROM_REDIRECT) {
                        this.targetURI = message.redirectTarget;
-                       Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
targetURI, cm);
+                       Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
null, null, targetURI, cm);
                        byte[] d;
                        try {
                                d = m.writeToByteArray();
@@ -326,7 +326,7 @@
                        targetURI = new FreenetURI(target);
                        if(logMINOR)
                                Logger.minor(this, "Uploading from redirect for 
"+this+" : "+targetURI);
-                       Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
targetURI, cm);
+                       Metadata m = new Metadata(Metadata.SIMPLE_REDIRECT, 
null, null, targetURI, cm);
                        byte[] d;
                        try {
                                d = m.writeToByteArray();

Modified: trunk/freenet/src/freenet/node/fcp/NodeHelloMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/NodeHelloMessage.java    2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/fcp/NodeHelloMessage.java    2008-11-06 
13:53:57 UTC (rev 23351)
@@ -42,7 +42,7 @@
                sfs.put("ExtBuild", NodeStarter.extBuildNumber);
                sfs.putSingle("ExtRevision", NodeStarter.extRevisionNumber);
                sfs.putSingle("Testnet", Boolean.toString(node == null ? false 
: node.isTestnetEnabled()));
-               sfs.putSingle("CompressionCodecs", 
Integer.toString(Compressor.countCompressAlgorithms()));
+               sfs.putSingle("CompressionCodecs", 
Integer.toString(Compressor.COMPRESSOR_TYPE.values().length));
                sfs.putSingle("ConnectionIdentifier", id);
                sfs.putSingle("NodeLanguage", 
L10n.getSelectedLanguage().toString());
                return sfs;

Modified: trunk/freenet/src/freenet/node/fcp/StartedCompressionMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/StartedCompressionMessage.java   
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/fcp/StartedCompressionMessage.java   
2008-11-06 13:53:57 UTC (rev 23351)
@@ -5,15 +5,16 @@

 import freenet.node.Node;
 import freenet.support.SimpleFieldSet;
+import freenet.support.compress.Compressor.COMPRESSOR_TYPE;

 public class StartedCompressionMessage extends FCPMessage {

        final String identifier;
        final boolean global;

-       final int codec;
+       final COMPRESSOR_TYPE codec;

-       public StartedCompressionMessage(String identifier, boolean global, int 
codec) {
+       public StartedCompressionMessage(String identifier, boolean global, 
COMPRESSOR_TYPE codec) {
                this.identifier = identifier;
                this.codec = codec;
                this.global = global;
@@ -23,7 +24,7 @@
        public SimpleFieldSet getFieldSet() {
                SimpleFieldSet fs = new SimpleFieldSet(true);
                fs.putSingle("Identifier", identifier);
-               fs.put("Codec", codec);
+               fs.putSingle("Codec", codec.name);
                if(global) fs.putSingle("Global", "true");
                return fs;
        }

Modified: trunk/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java
===================================================================
--- trunk/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java 
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java 
2008-11-06 13:53:57 UTC (rev 23351)
@@ -76,7 +76,7 @@
         os.close();
         System.out.println("Inserting test data.");
         HighLevelSimpleClient client = node.clientCore.makeClient((short)0);
-        InsertBlock block = new InsertBlock(data, new ClientMetadata(null), 
FreenetURI.EMPTY_CHK_URI);
+        InsertBlock block = new InsertBlock(data, new ClientMetadata(), 
FreenetURI.EMPTY_CHK_URI);
         long startInsertTime = System.currentTimeMillis();
         FreenetURI uri;
         try {

Modified: trunk/freenet/src/freenet/node/simulator/SeednodePingTest.java
===================================================================
--- trunk/freenet/src/freenet/node/simulator/SeednodePingTest.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/simulator/SeednodePingTest.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -3,6 +3,18 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.node.simulator;

+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+
 import freenet.crypt.RandomSource;
 import freenet.io.comm.NotConnectedException;
 import freenet.io.comm.PeerParseException;
@@ -19,21 +31,10 @@
 import freenet.support.Executor;
 import freenet.support.Logger;
 import freenet.support.PooledExecutor;
-import freenet.support.LoggerHook.InvalidThresholdException;
 import freenet.support.SimpleFieldSet;
 import freenet.support.TimeUtil;
+import freenet.support.LoggerHook.InvalidThresholdException;

-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.util.EnumMap;
-import java.util.Map;
-import java.util.Vector;
-
 /**
  * @author Florent Daigni&egrave;re &lt;nextgens at freenetproject.org&gt;
  */
@@ -52,8 +53,8 @@
         Executor executor = new PooledExecutor();
        node = NodeStarter.createTestNode(5000, 5001, "seednode-pingtest", 
true, false, false, Node.DEFAULT_MAX_HTL, 0, random, executor, 1000, 
5*1024*1024, true, false, false, false, false, false, false, 0, false, false, 
null);
        // Connect & ping
-       Vector<SeedServerTestPeerNode> seedNodes = new 
Vector<SeedServerTestPeerNode>();
-       Vector<SimpleFieldSet> seedNodesAsSFS = Announcer.readSeednodes(new 
File("/tmp/"));
+       List<SeedServerTestPeerNode> seedNodes = new 
ArrayList<SeedServerTestPeerNode>();
+       List<SimpleFieldSet> seedNodesAsSFS = Announcer.readSeednodes(new 
File("/tmp/"));
        int numberOfNodesInTheFile = 0;
        for(SimpleFieldSet sfs : seedNodesAsSFS) {
                numberOfNodesInTheFile++;

Deleted: 
trunk/freenet/src/freenet/node/updater/PrivkeyHasBeenBlownException.java
===================================================================
--- trunk/freenet/src/freenet/node/updater/PrivkeyHasBeenBlownException.java    
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/updater/PrivkeyHasBeenBlownException.java    
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,16 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.node.updater;
-
-import freenet.support.HTMLEncoder;
-
-public class PrivkeyHasBeenBlownException extends Exception{   
-       private static final long serialVersionUID = -1;
-       
-       PrivkeyHasBeenBlownException(String msg) {
-               super("The project's private key has been blown, meaning that 
it has been compromized"+
-                         "and shouldn't be trusted anymore. Please get a new 
build by hand and verify CAREFULLY"+
-                         "its signature and CRC. Here is the revocation 
message: "+HTMLEncoder.encode(msg));
-       }
-}

Deleted: trunk/freenet/src/freenet/node/useralerts/OpennetUserAlert.java
===================================================================
--- trunk/freenet/src/freenet/node/useralerts/OpennetUserAlert.java     
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/node/useralerts/OpennetUserAlert.java     
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,21 +0,0 @@
-package freenet.node.useralerts;
-
-import freenet.l10n.L10n;
-import freenet.node.Node;
-import freenet.support.HTMLNode;
-
-public class OpennetUserAlert extends AbstractUserAlert {
-
-       private final Node node;
-       
-       public OpennetUserAlert(Node node) {
-               super(true, L10n.getString("OpennetUserAlert.warningTitle"), 
L10n.getString("OpennetUserAlert.warning"), 
L10n.getString("OpennetUserAlert.warningShort"), new HTMLNode("#", 
L10n.getString("OpennetUserAlert.warning")), UserAlert.WARNING, true, 
L10n.getString("UserAlert.hide"), false, null);
-               this.node = node;
-       }
-       
-       @Override
-       public boolean isValid() {
-               return node.isOpennetEnabled() && valid;
-       }
-
-}

Deleted: trunk/freenet/src/freenet/plugin/api/FreenetPlugin.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/FreenetPlugin.java     2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/FreenetPlugin.java     2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,41 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.plugin.api;
-
-/**
- * A Freenet plugin. Base interface, must be implemented by all plugins.
- * Other interfaces provide for e.g. HTTP access. FreenetPluginManager provides
- * access to variables, factories etc.
- */
-public interface FreenetPlugin {
-
-       /** The plugin's short name (shouldn't usually have spaces, 
punctuation, author etc; one to three words StuckTogetherLikeThis) */
-       public String shortName();
-       
-       /** The plugin's description or long name (can have spaces, mention 
author or purpose, etc) */
-       public String description();
-       
-       /** Minimum build number of host node for this plugin to function */
-       public long minimumNodeVersion();
-       
-       /** The plugin's version number. MUST BE AT LEAST INCREMENTED ON EVERY 
RELEASE. */
-       public long version();
-       
-       /** The plugin's internal version number e.g. SVN revision number. 
Plugins hosted
-        * by FPI will have this as SVN revision number and auto-updated. */
-       public long internalVersion();
-       
-       /** 
-        * Start the plugin. This will run on a separate thread unless 
FreenetPluginThreadless is
-        * implemented.
-        * @param manager The parent FreenetPluginManager. Any variables or 
functions the plugin
-        * needs to access will be exposed by the FreenetPluginManager.
-        */
-       public void start(FreenetPluginManager manager);
-       
-       /**
-        * Stop the plugin. Perform an orderly shutdown and return in a 
reasonable period of time.
-        */
-       public void stop();
-}

Deleted: trunk/freenet/src/freenet/plugin/api/FreenetPluginManager.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/FreenetPluginManager.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/FreenetPluginManager.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,23 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.plugin.api;
-
-import java.util.Random;
-
-/**
- * The plugin's interface to the Freenet node.
- */
-public interface FreenetPluginManager {
-
-       /** Node version */
-       public long version();
-       
-       /** Node SVN version, if known, otherwise -1 */
-       public long internalVersion();
-       
-       /** Random number generator */
-       public Random random();
-       
-       
-}

Deleted: trunk/freenet/src/freenet/plugin/api/NeedsConfig.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/NeedsConfig.java       2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/NeedsConfig.java       2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,22 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.plugin.api;
-
-import freenet.support.api.BaseSubConfig;
-
-/**
- * Indicates that the plugin wants to use (read, write) persistent config 
settings. These will be saved to the 
- * freenet.ini file under the plugin's entry.
- */
-public interface NeedsConfig {
-
-       /**
-        * Called by the node when loading the plugin. Allows the plugin to 
register persistent config settings, and
-        * read their current values. Note that config settings only persist if 
the plugin is still loaded; once it is
-        * unloaded, they are lost.
-        * @param config A BaseSubConfig object on which the plugin can 
register config settings.
-        */
-       public void register(BaseSubConfig config);
-
-}

Deleted: trunk/freenet/src/freenet/plugin/api/NeedsSimpleKeyFetch.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/NeedsSimpleKeyFetch.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/NeedsSimpleKeyFetch.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,16 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.plugin.api;
-
-/**
- * Indicates that the plugin requires the ability to fetch keys.
- * Simple version of the interface. Once the plugin is loaded, the
- * node will call register() and thus provide the means to fetch keys.
- * So the plugin author will not forget to implement this interface! :)
- */
-public interface NeedsSimpleKeyFetch {
-
-       public void register(ProvidesSimpleKeyFetch fetcher);
-       
-}

Deleted: trunk/freenet/src/freenet/plugin/api/NeedsTempBuckets.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/NeedsTempBuckets.java  2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/NeedsTempBuckets.java  2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,18 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.plugin.api;
-
-import freenet.support.api.BucketFactory;
-
-/**
- * A plugin must implement this interface if it will need to create temporary 
buckets.
- */
-public interface NeedsTempBuckets {
-
-       /** How much space does the plugin require, at most? */
-       public long spaceRequired();
-       
-       public void register(BucketFactory provider);
-       
-}

Deleted: trunk/freenet/src/freenet/plugin/api/NeedsWebInterfaceGeneric.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/NeedsWebInterfaceGeneric.java  
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/NeedsWebInterfaceGeneric.java  
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,31 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.plugin.api;
-
-import java.net.URI;
-
-import freenet.support.api.HTTPReply;
-import freenet.support.api.HTTPRequest;
-
-/**
- * Flexible interface for plugins to return data to the browser, of any type 
and of any amount.
- */
-public interface NeedsWebInterfaceGeneric {
-
-       /** 
-        * Called when the plugin is registered.
-        * @param prefix The absolute path to the plugin's location on the web 
interface.
-        */
-       public void onRegister(URI prefix);
-       
-       /**
-        * Called to ask the plugin to handle an HTTP GET request.
-        * @param request The request to be handled.
-        * @return An HTTPReply containing the data and MIME type to be 
returned to the browser.
-        */
-       public HTTPReply handleGet(HTTPRequest request);
-       
-       public HTTPReply handlePost(HTTPRequest request);
-       
-}

Deleted: trunk/freenet/src/freenet/plugin/api/NeedsWebInterfaceHTMLString.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/NeedsWebInterfaceHTMLString.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/NeedsWebInterfaceHTMLString.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,35 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.plugin.api;
-
-import java.net.URI;
-
-import freenet.support.api.HTTPRequest;
-
-/**
- * Simple interface for plugins that only need to return a small amount of 
HTML to the web interface.
- */
-public interface NeedsWebInterfaceHTMLString {
-
-       /** 
-        * Called when the plugin is registered.
-        * @param prefix The absolute path to the plugin's location on the web 
interface.
-        */
-       public void onRegister(URI prefix);
-       
-       /**
-        * Handle an HTTP GET request.
-        * @param req The request to be handled.
-        * @return A String containing HTML to be returned to the browser.
-        */
-       public String handleGet(HTTPRequest req);
-       
-       /**
-        * Handle an HTTP POST request.
-        * @param req The request to be handled.
-        * @return A String containing HTML to be returned to the browser.
-        */
-       public String handlePost(HTTPRequest req);
-       
-}

Deleted: trunk/freenet/src/freenet/plugin/api/PluginFetchException.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/PluginFetchException.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/PluginFetchException.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,12 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.plugin.api;
-
-/**
- * Base class of exceptions thrown when a plugin fetch fails.
- */
- at SuppressWarnings("serial")
-public abstract class PluginFetchException extends Exception {
-
-}

Deleted: trunk/freenet/src/freenet/plugin/api/PluginFetchResult.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/PluginFetchResult.java 2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/PluginFetchResult.java 2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,22 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.plugin.api;
-
-import java.io.InputStream;
-
-public interface PluginFetchResult {
-       
-       /** MIME type of fetched data */
-       public String getMIMEType();
-       
-       /** Get an InputStream for the data */
-       public InputStream getInputStream();
-       
-       /** Get the size of the data */
-       public long size();
-       
-       /** Finished with the data, can free it */
-       public void free();
-
-}

Deleted: trunk/freenet/src/freenet/plugin/api/PluginFreenetURI.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/PluginFreenetURI.java  2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/PluginFreenetURI.java  2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,15 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.plugin.api;
-
-/**
- * Base interface of FreenetURI.
- * Provides an interface for plugins.
- * Anything inside the node should use FreenetURI directly.
- * Any dangerous methods should be left out of this interface.
- * BaseFreenetURI's are constructed via FreenetPluginManager.
- */
-public interface PluginFreenetURI {
-
-}

Deleted: trunk/freenet/src/freenet/plugin/api/ProvidesSimpleKeyFetch.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/ProvidesSimpleKeyFetch.java    
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/ProvidesSimpleKeyFetch.java    
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,14 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.plugin.api;
-
-/**
- * Provides an interface to the client for it to fetch keys from.
- * Simple version of the interface.
- */
-public interface ProvidesSimpleKeyFetch {
-
-       public PluginFetchResult fetch(PluginFreenetURI uri) throws 
PluginFetchException;
-       
-}

Deleted: trunk/freenet/src/freenet/plugin/api/package-info.java
===================================================================
--- trunk/freenet/src/freenet/plugin/api/package-info.java      2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/plugin/api/package-info.java      2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,11 +0,0 @@
-/**
- * Provides the API necessary to write a plugin for Freenet. Freenet plugins 
run in
- * the same JVM as the node, but they can only access it through a limited 
API. All
- * plugins must implement the FreenetPlugin interface, and zero or more of the 
- * Needs* interfaces depending on what services they require from the node. 
These 
- * interfaces indicate to the node what services are required by the plugin; 
the node
- * may ask the user whether (s)he wants to allow the plugin to use these 
services.
- * 
- * @see freenet.support.api
- */
-package freenet.plugin.api;
\ No newline at end of file

Modified: trunk/freenet/src/freenet/pluginmanager/FredPluginHTTP.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/FredPluginHTTP.java 2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/pluginmanager/FredPluginHTTP.java 2008-11-06 
13:53:57 UTC (rev 23351)
@@ -6,10 +6,7 @@
 import freenet.support.api.HTTPRequest;

 public interface FredPluginHTTP {
-       
        // Let them return null if unhandled
-
        public String handleHTTPGet(HTTPRequest request) throws 
PluginHTTPException;
-       public String handleHTTPPut(HTTPRequest request) throws 
PluginHTTPException;
        public String handleHTTPPost(HTTPRequest request) throws 
PluginHTTPException;
 }

Deleted: trunk/freenet/src/freenet/pluginmanager/FredPluginToadlet.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/FredPluginToadlet.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/pluginmanager/FredPluginToadlet.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,13 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.pluginmanager;
-
-/**
- * Meta Interface for plugins to be well integrated in to node ui look &amp; 
feel
- * 
- * @author saces
- */
-public interface FredPluginToadlet extends FredPluginHTTP, FredPluginL10n, 
FredPluginThemed, FredPluginVersioned {
-       
-}

Deleted: trunk/freenet/src/freenet/pluginmanager/PluginSecurityException.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/PluginSecurityException.java        
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/pluginmanager/PluginSecurityException.java        
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,39 +0,0 @@
-package freenet.pluginmanager;
-
-public class PluginSecurityException extends Exception {
-       private static final long serialVersionUID = -1;
-
-       /**
-        * 
-        */
-       public PluginSecurityException() {
-               super();
-               // TODO Auto-generated constructor stub
-       }
-
-       /**
-        * @param arg0
-        * @param arg1
-        */
-       public PluginSecurityException(String arg0, Throwable arg1) {
-               super(arg0, arg1);
-               // TODO Auto-generated constructor stub
-       }
-
-       /**
-        * @param arg0
-        */
-       public PluginSecurityException(String arg0) {
-               super(arg0);
-               // TODO Auto-generated constructor stub
-       }
-
-       /**
-        * @param arg0
-        */
-       public PluginSecurityException(Throwable arg0) {
-               super(arg0);
-               // TODO Auto-generated constructor stub
-       }
-
-}

Modified: trunk/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java
===================================================================
--- trunk/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/store/saltedhash/SaltedHashFreenetStore.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -84,14 +84,14 @@
        private boolean preallocate = true;

        public static SaltedHashFreenetStore construct(File baseDir, String 
name, StoreCallback callback, Random random,
-               long maxKeys, int bloomFilterSize, boolean bloomCounting, 
SemiOrderedShutdownHook shutdownHook, boolean preallocate)
+               long maxKeys, int bloomFilterSize, boolean bloomCounting, 
SemiOrderedShutdownHook shutdownHook, boolean preallocate, boolean 
resizeOnStart)
                throws IOException {
                return new SaltedHashFreenetStore(baseDir, name, callback, 
random, maxKeys, bloomFilterSize, bloomCounting,
-                       shutdownHook, preallocate);
+                       shutdownHook, preallocate, resizeOnStart);
        }

        private SaltedHashFreenetStore(File baseDir, String name, StoreCallback 
callback, Random random, long maxKeys,
-               int bloomFilterSize, boolean bloomCounting, 
SemiOrderedShutdownHook shutdownHook, boolean preallocate) throws IOException {
+               int bloomFilterSize, boolean bloomCounting, 
SemiOrderedShutdownHook shutdownHook, boolean preallocate, boolean 
resizeOnStart) throws IOException {
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
                logDEBUG = Logger.shouldLog(Logger.DEBUG, this);

@@ -146,7 +146,7 @@
                cleanerStatusUserAlert = new 
CleanerStatusUserAlert(cleanerThread);

                // finish all resizing before continue
-               if (prevStoreSize != 0 && cleanerGlobalLock.tryLock()) {
+               if (resizeOnStart && prevStoreSize != 0 && 
cleanerGlobalLock.tryLock()) {
                        System.out.println("Resizing datastore (" + name + ")");
                        try {
                                cleanerThread.resizeStore(prevStoreSize, false);
@@ -154,7 +154,8 @@
                                cleanerGlobalLock.unlock();
                        }
                        writeConfigFile();
-               } else if (bloomFilter.needRebuild() && !newStore) {
+               } 
+               if (bloomFilter.needRebuild() && !newStore) {
                        // Bloom filter resized?
                        flags |= FLAG_REBUILD_BLOOM;
                        checkBloom = false;
@@ -644,12 +645,12 @@
                                }
                                headerFile.delete();
                                dataFile.delete();
-                               setStoreFileSize(storeFileSize);
+                               setStoreFileSize(storeFileSize, true);
                        }
                }

                WrapperManager.signalStarting(10 * 60 * 1000); // 10minutes, 
for filesystem that support no sparse file.
-               setStoreFileSize(storeFileSize);
+               setStoreFileSize(storeFileSize, true);

                return newStore;
        }
@@ -783,7 +784,7 @@
         * 
         * @param storeFileSize
         */
-       private void setStoreFileSize(long storeFileSize) {
+       private void setStoreFileSize(long storeFileSize, boolean starting) {
                try {
                        long oldMetaLen = metaRAF.length();
                        long oldHdLen = hdRAF.length();
@@ -820,6 +821,8 @@
                                        if(oldHdLen % (1024*1024*1024L) == 0) {
                                                random.nextBytes(seed);
                                                mt = new MersenneTwister(seed);
+                                               if(starting)
+                                                       
WrapperManager.signalStarting(5*60*1000);
                                        }
                                }
                        }
@@ -1055,7 +1058,7 @@

                                public void init() {
                                        if (storeSize > _prevStoreSize)
-                                               setStoreFileSize(storeSize);
+                                               setStoreFileSize(storeSize, 
false);

                                        optimialK = 
BloomFilter.optimialK(bloomFilterSize, storeSize);
                                        configLock.writeLock().lock();
@@ -1117,7 +1120,7 @@

                                        // shrink data file to current size
                                        if (storeSize < _prevStoreSize)
-                                               
setStoreFileSize(Math.max(storeSize, entriesLeft));
+                                               
setStoreFileSize(Math.max(storeSize, entriesLeft), false);

                                        // try to resolve the list
                                        ListIterator<Entry> it = 
oldEntryList.listIterator();

Deleted: trunk/freenet/src/freenet/support/DoubleTokenBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/DoubleTokenBucket.java    2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/DoubleTokenBucket.java    2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,56 +0,0 @@
-package freenet.support;
-
-/**
- * A TokenBucket where forceGrab() may only use up to some proportion of the 
total limit. Beyond that,
- * we ignore it. So the last X% may be used by blocking grabs, even if the 
forceGrab() traffic is over
- * the limit. This is implemented by using a secondary TokenBucket to track 
what is allowed.
- */
-public class DoubleTokenBucket extends TokenBucket {
-       
-       private static boolean logMINOR;
-       private final TokenBucket grabbedBytesLimiter;
-       private final double forceGrabLimit;
-       
-       public DoubleTokenBucket(long max, long nanosPerTick, long 
initialValue, double forceGrabLimit) {
-               super(max, nanosPerTick, initialValue);
-               if(forceGrabLimit > 1.0) throw new IllegalArgumentException();
-               logMINOR = Logger.shouldLog(Logger.MINOR, this);
-               grabbedBytesLimiter = new TokenBucket((long)(max * 
forceGrabLimit), (long)(nanosPerTick / forceGrabLimit), (long)(initialValue * 
forceGrabLimit));
-               this.forceGrabLimit = forceGrabLimit;
-       }
-       
-       @Override
-       public synchronized void forceGrab(long tokens) {
-               logMINOR = Logger.shouldLog(Logger.MINOR, this);
-               long maxTokens = grabbedBytesLimiter.partialInstantGrab(tokens);
-               if(maxTokens < tokens) {
-                       if(logMINOR) Logger.minor(this, "Limiting forceGrab of 
"+tokens+" to "+maxTokens);
-               }
-               if(maxTokens > 0)
-                       super.forceGrab(maxTokens);
-       }
-
-       /**
-        * Change the number of nanos per tick.
-        * @param nanosPerTick The new number of nanos per tick.
-        */
-       @Override
-       public synchronized void changeNanosPerTick(long nanosPerTick) {
-               super.changeNanosPerTick(nanosPerTick);
-               grabbedBytesLimiter.changeNanosPerTick((long)(nanosPerTick * 
forceGrabLimit));
-       }
-       
-       @Override
-       public synchronized void changeBucketSize(long newMax) {
-               super.changeBucketSize(newMax);
-               grabbedBytesLimiter.changeBucketSize((long)(newMax * 
forceGrabLimit));
-       }
-       
-       @Override
-       public synchronized void changeNanosAndBucketSize(long nanosPerTick, 
long newMax) {
-               super.changeNanosAndBucketSize(nanosPerTick, newMax);
-               
grabbedBytesLimiter.changeNanosAndBucketSize((long)(nanosPerTick * 
forceGrabLimit),
-                               (long)(newMax * forceGrabLimit));
-       }
-       
-}

Modified: trunk/freenet/src/freenet/support/DoublyLinkedList.java
===================================================================
--- trunk/freenet/src/freenet/support/DoublyLinkedList.java     2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/DoublyLinkedList.java     2008-11-06 
13:53:57 UTC (rev 23351)
@@ -6,7 +6,7 @@
  * Framework for managing a doubly linked list.
  * @author tavin
  */
-public interface DoublyLinkedList<T> {
+public interface DoublyLinkedList<T> extends Iterable<T> {
     public abstract DoublyLinkedList<T> clone();

     /**
@@ -47,7 +47,13 @@
     /** Get a {@link Enumeration} of {@link DoublyLinkedList.Item}. */
     Enumeration elements();   // for consistency w/ typical Java API

+    
     /**
+     * Returns true if the passed item is contained in the list.
+     */
+    public boolean contains(DoublyLinkedList.Item<T> item);
+    
+    /**
      * Returns the first item.
      * @return  the item at the head of the list, or <code>null</code> if empty
      */

Modified: trunk/freenet/src/freenet/support/DoublyLinkedListImpl.java
===================================================================
--- trunk/freenet/src/freenet/support/DoublyLinkedListImpl.java 2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/DoublyLinkedListImpl.java 2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,6 +1,7 @@
 package freenet.support;

 import java.util.Enumeration;
+import java.util.Iterator;
 import java.util.NoSuchElementException;

 /**
@@ -115,6 +116,14 @@
         return forwardElements();
     }

+    public boolean contains(DoublyLinkedList.Item<T> item) {
+       for(T i : this) {
+               if(i == item)
+                       return true;
+       }
+       return false;
+    }
+    
     /**
      * {@inheritDoc}
      */
@@ -420,4 +429,26 @@
                        return old;
                }
     }
+
+       public Iterator<T> iterator() {
+               return new Iterator<T>() {
+                       private Enumeration<T> e = forwardElements();
+
+                       public boolean hasNext() {
+                               return e.hasMoreElements();
+                       }
+
+                       public T next() {
+                               if(!hasNext())
+                                       throw new NoSuchElementException();
+                               
+                               return e.nextElement();
+                       }
+
+                       public void remove() {
+                               throw new UnsupportedOperationException();
+                       }
+                       
+               };
+       }
 }
\ No newline at end of file

Modified: trunk/freenet/src/freenet/support/FileLoggerHook.java
===================================================================
--- trunk/freenet/src/freenet/support/FileLoggerHook.java       2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/FileLoggerHook.java       2008-11-06 
13:53:57 UTC (rev 23351)
@@ -218,7 +218,6 @@
                        long startTime;
                        long nextHour = -1;
                        GregorianCalendar gc = null;
-                       String filename = null;
                        if (baseFilename != null) {
                                latestFile = new 
File(baseFilename+"-latest.log");
                                previousFile = new 
File(baseFilename+"-previous.log");
@@ -244,8 +243,7 @@
                                        int x = gc.get(INTERVAL);
                                        gc.set(INTERVAL, (x / 
INTERVAL_MULTIPLIER) * INTERVAL_MULTIPLIER);
                                }
-                               filename = getHourLogName(gc, true);
-                               currentFilename = new File(filename);
+                               currentFilename = new File(getHourLogName(gc, 
true));
                                synchronized(logFiles) {
                                        if ((!logFiles.isEmpty()) && 
logFiles.getLast().filename.equals(currentFilename)) {
                                                logFiles.removeLast();
@@ -268,49 +266,11 @@
                                        thisTime = System.currentTimeMillis();
                                        if (baseFilename != null) {
                                                if ((thisTime > nextHour) || 
switchedBaseFilename) {
-                                                       // Switch logs
-                                                       try {
-                                                               
logStream.flush();
-                                                               if(altLogStream 
!= null) altLogStream.flush();
-                                                       } catch (IOException e) 
{
-                                                               
System.err.println(
-                                                                       
"Flushing on change caught " + e);
-                                                       }
-                                                       try {
-                                                               
logStream.close();
-                                                       } catch (IOException e) 
{
-                                                               
System.err.println(
-                                                                               
"Closing on change caught " + e);
-                                                       }
-                                                       long length = 
currentFilename.length();
-                                                       OldLogFile olf = new 
OldLogFile(currentFilename, lastTime, nextHour, length);
-                                                       lastTime = nextHour;
-                                                       synchronized(logFiles) {
-                                                               
logFiles.addLast(olf);
-                                                       }
-                                                       
oldLogFilesDiskSpaceUsage += length;
-                                                       trimOldLogFiles();
-                                                       // Rotate primary log 
stream
-                                                       filename = 
getHourLogName(gc, true);
-                                                       currentFilename = new 
File(filename);
-                                                       logStream = 
openNewLogFile(new File(filename), true);
-                                                       if(latestFile != null) {
-                                                               try {
-                                                                       
altLogStream.close();
-                                                               } catch 
(IOException e) {
-                                                                       
System.err.println(
-                                                                               
        "Closing alt on change caught " + e);
-                                                               }
-                                                               if(previousFile 
!= null && previousFile.exists())
-                                                                       
FileUtil.renameTo(latestFile, previousFile);
-                                                               
latestFile.delete();
-                                                               altLogStream = 
openNewLogFile(latestFile, false);
-                                                       }
-                                                       
//System.err.println("Rotated log files: "+filename);
-                                                       
//System.err.println("Almost rotated");
+                                                       currentFilename = 
rotateLog(currentFilename, lastTime, nextHour, gc);
+
                                                        gc.add(INTERVAL, 
INTERVAL_MULTIPLIER);
                                                        nextHour = 
gc.getTimeInMillis();
-                                                       
//System.err.println("Rotated");
+
                                                        
if(switchedBaseFilename) {
                                                                
synchronized(FileLoggerHook.class) {
                                                                        
switchedBaseFilename = false;
@@ -354,6 +314,46 @@
                        }
                }

+               private File rotateLog(File currentFilename, long lastTime, 
long nextHour, GregorianCalendar gc) {
+               // Switch logs
+               try {
+                       logStream.flush();
+                       if(altLogStream != null) altLogStream.flush();
+               } catch (IOException e) {
+                       System.err.println(
+                               "Flushing on change caught " + e);
+               }
+               try {
+                       logStream.close();
+               } catch (IOException e) {
+                       System.err.println(
+                                       "Closing on change caught " + e);
+               }
+               long length = currentFilename.length();
+               OldLogFile olf = new OldLogFile(currentFilename, lastTime, 
nextHour, length);
+               synchronized(logFiles) {
+                       logFiles.addLast(olf);
+               }
+               oldLogFilesDiskSpaceUsage += length;
+               trimOldLogFiles();
+               // Rotate primary log stream
+               currentFilename = new File(getHourLogName(gc, true));
+               logStream = openNewLogFile(currentFilename, true);
+               if(latestFile != null) {
+                       try {
+                               altLogStream.close();
+                       } catch (IOException e) {
+                               System.err.println(
+                                               "Closing alt on change caught " 
+ e);
+                       }
+                       if(previousFile != null && previousFile.exists())
+                               FileUtil.renameTo(latestFile, previousFile);
+                       latestFile.delete();
+                       altLogStream = openNewLogFile(latestFile, false);
+               }
+               return currentFilename;
+        }
+
                // Check every minute
                static final int maxSleepTime = 60 * 1000;
                /**
@@ -820,8 +820,8 @@
                }
                sb.append('\n');

+               // Write stacktrace if available
                for(int j=0;j<20 && e != null;j++) {
-
                        sb.append(e.toString());

                        StackTraceElement[] trace = e.getStackTrace();
@@ -865,6 +865,7 @@
                                                ss = list.removeFirst();
                                        } catch (NoSuchElementException e) {
                                                // Yes I know this is 
impossible but it happens with 1.6 with heap profiling enabled
+                                               // This is a bug in 
sun/netbeans profiler around 2006 era
                                                noElementCount++;
                                                if(noElementCount > 1000) {
                                                        
System.err.println("Lost log line because of constant 
NoSuchElementException's");
@@ -879,7 +880,7 @@
                                String err =
                                        "GRRR: ERROR: Logging too fast, chopped 
"
                                                + x
-                                               + " lines, "
+                                               + " entries, "
                                                + listBytes
                                                + " bytes in memory\n";
                                byte[] buf = err.getBytes();

Modified: trunk/freenet/src/freenet/support/MultiValueTable.java
===================================================================
--- trunk/freenet/src/freenet/support/MultiValueTable.java      2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/MultiValueTable.java      2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,14 +1,15 @@
 package freenet.support;
-import java.util.*;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
 /**
  * A hashtable that can store several values for each entry.
  *
  * @author oskar
  */

-public class MultiValueTable {
-
-    private Hashtable table;
+public class MultiValueTable<K,V> {
+    private Hashtable<K, Vector<V>> table;
     private int ies;

     public MultiValueTable() {
@@ -20,15 +21,15 @@
     }

     public MultiValueTable(int initialSize, int initialEntrySize) {
-        table = new Hashtable(initialSize);
+        table = new Hashtable<K, Vector<V>>(initialSize);
         ies = initialEntrySize;
     }

-    public void put(Object key, Object value) {
+    public void put(K key, V value) {
         synchronized (table) {
-            Vector v = (Vector) table.get(key);
+            Vector<V> v = table.get(key);
             if (v == null) {
-                v = new Vector(ies);
+                v = new Vector<V>(ies);
                 table.put(key, v);
             }
             v.addElement(value);
@@ -38,24 +39,24 @@
     /**
      * Returns the first element for this key.
      */
-    public Object get(Object key) {
+    public V get(K key) {
         synchronized (table) {
-            Vector v = (Vector) table.get(key);
+            Vector<V> v = table.get(key);
             return (v == null ?
                     null :
                     v.firstElement());
         }
     }

-    public boolean containsKey(Object key) {
+    public boolean containsKey(K key) {
                synchronized (table) {
                        return table.containsKey(key);
                }
     }

-    public boolean containsElement(Object key, Object value) {
+    public boolean containsElement(K key, V value) {
         synchronized (table) {
-            Vector v = (Vector) table.get(key);
+            Vector<V> v = table.get(key);
             return (v != null) && v.contains(value);
         }
     }
@@ -63,20 +64,20 @@
     /**
      * Users will have to handle synchronizing.
      */
-    public Enumeration getAll(Object key) {
-       Vector v;
+    public Enumeration<V> getAll(K key) {
+       Vector<V> v;
                synchronized (table) {
-                       v = (Vector) table.get(key);
+                       v = table.get(key);
                }
         return (v == null ?
-                new LimitedEnumeration(null) :
+                new LimitedEnumeration<V>(null) :
                 v.elements());
     }

-    public int countAll(Object key) {
-       Vector v;
+    public int countAll(K key) {
+       Vector<V> v;
                synchronized (table) {
-                       v = (Vector)table.get(key);
+                       v = table.get(key);
                }
        if(v != null) 
                return v.size();
@@ -84,26 +85,26 @@
                return 0;
     }

-    public Object getSync(Object key) {
+    public Object getSync(K key) {
                synchronized (table) {
                        return table.get(key);
                }
     }

-    public Object[] getArray(Object key) {
+    public Object[] getArray(K key) {
         synchronized (table) {
-            Vector v = (Vector) table.get(key);
+            Vector<V> v = table.get(key);
             if (v == null)
                 return null;
             else {
-                Object[] r = new Object[v.size()];
+               Object[] r = new Object[v.size()];
                 v.copyInto(r);
                 return r;
             }
         }
     }

-    public void remove(Object key) {
+    public void remove(K key) {
                synchronized (table) {
                        table.remove(key);
                }
@@ -121,9 +122,9 @@
                }
     }

-    public boolean removeElement(Object key, Object value) {
+    public boolean removeElement(K key, V value) {
         synchronized (table) {
-            Vector v = (Vector) table.get(key);
+            Vector<V> v = table.get(key);
             if (v == null)
                 return false;
             else {
@@ -135,43 +136,43 @@
         }
     }

-    public Enumeration keys() {
+    public Enumeration<K> keys() {
                synchronized (table) {
                        return table.keys();
                }
     }

-    public Enumeration elements() {
+    public Enumeration<V> elements() {
                synchronized (table) {
                        if (table.isEmpty())
-                               return new LimitedEnumeration(null);
+                               return new LimitedEnumeration<V>(null);
                        else 
                                return new MultiValueEnumeration();
                }
     }

-    private class MultiValueEnumeration implements Enumeration {
-        private Enumeration current;
-        private Enumeration global;
+    private class MultiValueEnumeration implements Enumeration<V> {
+        private Enumeration<V> current;
+        private Enumeration< Vector<V>> global;
         public MultiValueEnumeration() {
                        synchronized (table) {
                                global = table.elements();
                        }
-            current = ((Vector) global.nextElement()).elements();
+            current =  global.nextElement().elements();
             step();
         }

         public final void step() {
             while (!current.hasMoreElements() && global.hasMoreElements())
-                current = ((Vector) global.nextElement()).elements();
+                current = global.nextElement().elements();
         }

         public final boolean hasMoreElements() {
             return global.hasMoreElements(); // || current.hasMoreElements();
         }

-        public final Object nextElement() {
-            Object o = current.nextElement();
+        public final V nextElement() {
+            V o = current.nextElement();
             step();
             return o;
         }

Deleted: trunk/freenet/src/freenet/support/NumberedItem.java
===================================================================
--- trunk/freenet/src/freenet/support/NumberedItem.java 2008-11-06 13:50:42 UTC 
(rev 23350)
+++ trunk/freenet/src/freenet/support/NumberedItem.java 2008-11-06 13:53:57 UTC 
(rev 23351)
@@ -1,12 +0,0 @@
-package freenet.support;
-
-/**
- * An object with a number.
- * 
- * @see IntNumberedItem
- */
-public interface NumberedItem {
-
-    long getNumber();
-    
-}

Deleted: trunk/freenet/src/freenet/support/NumberedItemComparator.java
===================================================================
--- trunk/freenet/src/freenet/support/NumberedItemComparator.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/NumberedItemComparator.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,55 +0,0 @@
-package freenet.support;
-
-import java.util.Comparator;
-
-public class NumberedItemComparator implements Comparator<Object> {
-
-       public NumberedItemComparator(boolean wrap) {
-               this.wrapAround = wrap;
-       }
-       
-       final boolean wrapAround;
-       
-    public int compare(Object o1, Object o2) {
-        // Nulls at the end of the list
-        if((o1 == null) && (o2 == null))
-            return 0; // null == null
-        if((o1 != null) && (o2 == null))
-            return 1; // anything > null
-        if((o2 != null) && (o1 == null))
-            return -1;
-        long i1, i2;
-        if(o1 instanceof NumberedItem)
-            i1 = ((NumberedItem)o1).getNumber();
-        else if(o1 instanceof Long)
-            i1 = ((Long)o1).longValue();
-        else throw new ClassCastException(o1.toString());
-        if(o2 instanceof NumberedItem)
-            i2 = ((NumberedItem)o2).getNumber();
-        else if(o2 instanceof Long)
-            i2 = ((Long)o2).longValue();
-        else throw new ClassCastException(o2.toString());
-        if(i1 == i2) return 0;
-        if(!wrapAround) {
-            if(i1 > i2) return 1;
-            else return -1;
-        } else {
-            long firstDistance, secondDistance;
-            if(i1 > i2) {
-                firstDistance = i1 - i2; // smaller => i1 > i2
-                secondDistance = i2 + Long.MAX_VALUE - i1; // smaller => i2 > 
i1
-            } else {
-                secondDistance = i2 - i1; // smaller => i2 > i1
-                firstDistance = i1 + Long.MAX_VALUE - i2; // smaller => i1 > i2
-            }
-            // REDFLAG: base must be odd, so we never get ==
-                       assert firstDistance != secondDistance && firstDistance 
!= -secondDistance;
-            
-            if(Math.abs(firstDistance) < Math.abs(secondDistance)) {
-                return 1; // i1>i2
-            } else //if(Math.abs(secondDistance) < Math.abs(firstDistance)) {
-                return -1; // i2>i1
-        }
-    }
-    
-}

Deleted: trunk/freenet/src/freenet/support/NumberedRecentItems.java
===================================================================
--- trunk/freenet/src/freenet/support/NumberedRecentItems.java  2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/NumberedRecentItems.java  2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,114 +0,0 @@
-package freenet.support;
-
-import java.util.Arrays;
-import java.util.Comparator;
-
-/**
- * Keep the last N NumberedItem's by number. Supports fetching
- * by number, fetching all items with number greater than a
- * certain value, and inserting an item with a given number.
- * Any items that don't fit are dropped from the end with the
- * lower numerical value. 
- */
-public class NumberedRecentItems {
-
-    private NumberedItem[] items;
-    private int count;
-    private Comparator<Object> myComparator;
-    /**
-     * Create a NumberedRecentItems list.
-     * @param maxSize The maximum number of NumberedItems to keep.
-     * @param wrap If true, comparisons are modulo 2^63-1.
-     * We calculate the direct and wrapped distance, and use
-     * whichever is shorter to determine the direction.
-     */
-    public NumberedRecentItems(int maxSize, boolean wrap) {
-        items = new NumberedItem[maxSize];
-        count = 0;
-        myComparator = new NumberedItemComparator(wrap);
-    }
-
-    public synchronized NumberedItem get(int num) {
-        int x = Arrays.binarySearch(items, num, myComparator);
-        if(x >= 0) return items[x];
-        return null;
-    }
-    
-    /**
-     * Add an item.
-     * @return True if we added a new item. Must return false if
-     * it was already present. Also returns false if the data is
-     * so old that we don't want it.
-     */
-    public synchronized boolean add(NumberedItem item) {
-        long num = item.getNumber();
-        int x = Arrays.binarySearch(items, num, myComparator);
-        if(Logger.shouldLog(Logger.MINOR, this))
-               Logger.minor(this, "Search pos: "+x);
-        if(x >= 0) return false; // already present
-        count++;
-        if(x == -1) {
-            // insertion point = 0
-            // [0] > item
-            // do nothing
-            return false;
-//            if(count < items.length) {
-//                
-//                System.arraycopy(items, 0, items, 1, items.length);
-//                items[0] = item;
-//            } else {
-//                // [0] is greater than item, drop it
-//                return false;
-//            }
-        }
-        if(x == -(items.length)-1) {
-            // All items less than this item
-            // Shift back one, then set last item
-            System.arraycopy(items, 1, items, 0, items.length-1);
-            items[items.length-1] = item;
-        } else if(x == -2) {
-            // [1] is greater than item, [0] is less
-            items[0] = item;
-        } else {
-            // In the middle somewhere
-            int firstGreaterItem = (-x)-1;
-            // [firstGreaterItem]...[size-1] remain constant
-            // move the rest back one
-            System.arraycopy(items, 1, items, 0, firstGreaterItem-1);
-            items[firstGreaterItem-1] = item;
-        }
-        // FIXME: remove when confident
-        checkSorted();
-        return true;
-    }
-
-    private synchronized void checkSorted() {
-        long prevNum = -1;
-        for(int i=0;i<Math.min(count, items.length);i++) {
-            NumberedItem item = items[i];
-            long num = item == null ? -1 : item.getNumber();
-            if((item != null) && (num < 0))
-                throw new IllegalStateException("getNumber() must return 
positive numbers");
-            if((num < prevNum) || ((num != -1) && (num == prevNum))) {
-                throw new IllegalStateException("Must be higher than prev: 
"+num+ ' ' +prevNum);
-            }
-            prevNum = num;
-        }
-    }
-    
-    public synchronized NumberedItem[] getAfter(long target) {
-        int x = Arrays.binarySearch(items, target, myComparator);
-        if(x == items.length-1) return null;
-        if(x >= 0) {
-            NumberedItem[] out = new NumberedItem[items.length-x-1];
-            System.arraycopy(items, x+1, out, 0, items.length-x-1);
-            return out;
-        }
-        // Otherwise is not an exact match
-        if(x == -items.length-1) return null;
-        int firstGreater = (-x)-1;
-        NumberedItem[] out = new NumberedItem[items.length-firstGreater];
-        System.arraycopy(items, firstGreater, out, 0, 
items.length-firstGreater);
-        return out;
-    }
-}

Deleted: trunk/freenet/src/freenet/support/RandomGrabArrayWithInt.java
===================================================================
--- trunk/freenet/src/freenet/support/RandomGrabArrayWithInt.java       
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/RandomGrabArrayWithInt.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,18 +0,0 @@
-package freenet.support;
-
-import freenet.crypt.RandomSource;
-
-public class RandomGrabArrayWithInt extends RandomGrabArray implements 
IntNumberedItem {
-
-       private final int number;
-
-       public RandomGrabArrayWithInt(RandomSource rand, int no) {
-               super(rand);
-               number = no;
-       }
-       
-       public int getNumber() {
-               return number;
-       }
-
-}

Modified: trunk/freenet/src/freenet/support/UpdatableSortedLinkedList.java
===================================================================
--- trunk/freenet/src/freenet/support/UpdatableSortedLinkedList.java    
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/UpdatableSortedLinkedList.java    
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,6 +1,8 @@
 package freenet.support;

 import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.NoSuchElementException;

 /**
  * @author amphibian
@@ -9,7 +11,7 @@
  * and provides an update() function to move an item when its
  * value has changed. Allows duplicates.
  */
-public class UpdatableSortedLinkedList {
+public class UpdatableSortedLinkedList implements Iterable {
        boolean debug = false;
        protected boolean killed = false;
        private static boolean logMINOR;
@@ -216,6 +218,13 @@
     }

     /**
+     * @return Does the list contain that item?
+     */
+    public synchronized boolean contains(UpdatableSortedLinkedListItem item) {
+       return list.contains(item);
+    }
+    
+    /**
      * @return Is the list empty?
      */
     public synchronized boolean isEmpty() {
@@ -253,4 +262,8 @@
                        dest.add(item);
                }
        }
+
+       public synchronized Iterator iterator() {
+               return list.iterator();
+       }
 }

Modified: 
trunk/freenet/src/freenet/support/UpdatableSortedLinkedListItemImpl.java
===================================================================
--- trunk/freenet/src/freenet/support/UpdatableSortedLinkedListItemImpl.java    
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/UpdatableSortedLinkedListItemImpl.java    
2008-11-06 13:53:57 UTC (rev 23351)
@@ -29,4 +29,20 @@
         prev = i;
         return old;
     }
+    
+    /*
+     * FIXME: DoublyLinkedList says that this is only for debugging purposes.
+     * Maybe it should be removed completely?
+     */
+    
+    private DoublyLinkedList parentList;
+
+       public DoublyLinkedList getParent() {
+               return parentList;
+       }
+
+       public DoublyLinkedList setParent(DoublyLinkedList l) {
+               return parentList;
+       }
+    
 }

Modified: 
trunk/freenet/src/freenet/support/UpdatableSortedLinkedListWithForeignIndex.java
===================================================================
--- 
trunk/freenet/src/freenet/support/UpdatableSortedLinkedListWithForeignIndex.java
    2008-11-06 13:50:42 UTC (rev 23350)
+++ 
trunk/freenet/src/freenet/support/UpdatableSortedLinkedListWithForeignIndex.java
    2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,6 +1,7 @@
 package freenet.support;

 import java.util.HashMap;
+import java.util.Iterator;

 /**
  * UpdatableSortedLinkedList plus a hashtable. Each item has
@@ -41,10 +42,18 @@
         
map.remove(((IndexableUpdatableSortedLinkedListItem)item).indexValue());
         return super.remove(item);
     }
+    
+       public synchronized IndexableUpdatableSortedLinkedListItem get(Object 
key) {
+               return (IndexableUpdatableSortedLinkedListItem)map.get(key);
+       }

-    public synchronized boolean containsKey(Object o) {
-        return map.containsKey(o);
+    public synchronized boolean containsKey(Object key) {
+        return map.containsKey(key);
     }
+    
+    public synchronized boolean 
contains(IndexableUpdatableSortedLinkedListItem item) {
+       return containsKey(item.indexValue());
+    }

     /**
      * Remove an element from the list by its key.

Deleted: trunk/freenet/src/freenet/support/api/BaseSubConfig.java
===================================================================
--- trunk/freenet/src/freenet/support/api/BaseSubConfig.java    2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/api/BaseSubConfig.java    2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,76 +0,0 @@
-package freenet.support.api;
-
-import freenet.config.InvalidConfigValueException;
-
-public interface BaseSubConfig {
-
-       public void register(String optionName, int defaultValue, int sortOrder,
-                       boolean expert, boolean forceWrite, String shortDesc,
-                       String longDesc, IntCallback cb);
-
-       public void register(String optionName, long defaultValue, int 
sortOrder,
-                       boolean expert, boolean forceWrite, String shortDesc,
-                       String longDesc, LongCallback cb);
-
-       public void register(String optionName, String defaultValueString,
-                       int sortOrder, boolean expert, boolean forceWrite,
-                       String shortDesc, String longDesc, IntCallback cb);
-
-       public void register(String optionName, String defaultValueString,
-                       int sortOrder, boolean expert, boolean forceWrite,
-                       String shortDesc, String longDesc, LongCallback cb);
-
-       public void register(String optionName, boolean defaultValue,
-                       int sortOrder, boolean expert, boolean forceWrite,
-                       String shortDesc, String longDesc, BooleanCallback cb);
-
-       public void register(String optionName, String defaultValue, int 
sortOrder,
-                       boolean expert, boolean forceWrite, String shortDesc,
-                       String longDesc, StringCallback cb);
-
-       public void register(String optionName, short defaultValue, int 
sortOrder,
-                       boolean expert, boolean forceWrite, String shortDesc,
-                       String longDesc, ShortCallback cb);
-
-       public void register(String optionName, String[] defaultValue,
-                       int sortOrder, boolean expert, boolean forceWrite,
-                       String shortDesc, String longDesc, StringArrCallback 
cb);
-
-       public int getInt(String optionName);
-
-       public long getLong(String optionName);
-
-       public boolean getBoolean(String optionName);
-
-       public String getString(String optionName);
-
-       public String[] getStringArr(String optionName);
-
-       public short getShort(String optionName);
-
-       /**
-        * Has the object we are attached to finished initialization?
-        */
-       public boolean hasFinishedInitialization();
-
-       /**
-        * Called when the object we are attached to has finished init.
-        * After this point, the callbacks are authoritative for values of
-        * config variables, and will be called when values are changed by
-        * the user.
-        */
-       public void finishedInitialization();
-
-       /**
-        * Force an option to be updated even if it hasn't changed.
-        * @throws InvalidConfigValueException 
-        */
-       public void forceUpdate(String optionName)
-                       throws InvalidConfigValueException;
-
-       public void set(String name, String value)
-                       throws InvalidConfigValueException;
-
-       public void fixOldDefault(String name, String value);
-
-}
\ No newline at end of file

Deleted: trunk/freenet/src/freenet/support/api/HTTPReply.java
===================================================================
--- trunk/freenet/src/freenet/support/api/HTTPReply.java        2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/api/HTTPReply.java        2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,27 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.support.api;
-
-/**
- * An HTTP response.
- */
-public final class HTTPReply {
-
-       private final String mimeType;
-       private final Bucket data;
-       
-       public HTTPReply(String mimeType, Bucket data) {
-               this.mimeType = mimeType;
-               this.data = data;
-       }
-       
-       public final String getMIMEType() {
-               return mimeType;
-       }
-       
-       public final Bucket getData() {
-               return data;
-       }
-
-}

Copied: trunk/freenet/src/freenet/support/compress/Bzip2Compressor.java (from 
rev 23341, trunk/freenet/src/freenet/support/compress/Bzip2Compressor.java)
===================================================================
--- trunk/freenet/src/freenet/support/compress/Bzip2Compressor.java             
                (rev 0)
+++ trunk/freenet/src/freenet/support/compress/Bzip2Compressor.java     
2008-11-06 13:53:57 UTC (rev 23351)
@@ -0,0 +1,117 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+* Public License, version 2 (or at your option any later version). See
+* http://www.gnu.org/ for further details of the GPL. */
+package freenet.support.compress;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import freenet.support.Logger;
+import freenet.support.api.Bucket;
+import freenet.support.api.BucketFactory;
+import org.apache.tools.bzip2.CBZip2InputStream;
+import org.apache.tools.bzip2.CBZip2OutputStream;
+
+public class Bzip2Compressor implements Compressor {
+
+       public Bucket compress(Bucket data, BucketFactory bf, long maxLength) 
throws IOException, CompressionOutputSizeException {
+               if(maxLength <= 0)
+                       throw new IllegalArgumentException();
+               Bucket output = bf.makeBucket(maxLength);
+               InputStream is = null;
+               OutputStream os = null;
+               CBZip2OutputStream bz2os = null;
+               try {
+                       is = data.getInputStream();
+                       os = output.getOutputStream();
+                       bz2os = new CBZip2OutputStream(os);
+                       long written = 0;
+                       // Bigger input buffer, so can compress all at once.
+                       // Won't hurt on I/O either, although most OSs will 
only return a page at a time.
+                       byte[] buffer = new byte[32768];
+                       while(true) {
+                               int l = (int) Math.min(buffer.length, maxLength 
- written);
+                               int x = is.read(buffer, 0, buffer.length);
+                               if(l < x) {
+                                       throw new 
CompressionOutputSizeException();
+                               }
+                               if(x <= -1) break;
+                               if(x == 0) throw new IOException("Returned zero 
from read()");
+                               bz2os.write(buffer, 0, x);
+                               written += x;
+                       }
+                       bz2os.flush();
+                       bz2os.close();
+                       os = null;
+               } finally {
+                       if(is != null) is.close();
+                       if(os != null) os.close();
+               }
+               return output;
+       }
+
+       public Bucket decompress(Bucket data, BucketFactory bf, long maxLength, 
long maxCheckSizeLength, Bucket preferred) throws IOException, 
CompressionOutputSizeException {
+               Bucket output;
+               if(preferred != null)
+                       output = preferred;
+               else
+                       output = bf.makeBucket(maxLength);
+               InputStream is = data.getInputStream();
+               OutputStream os = output.getOutputStream();
+               decompress(is, os, maxLength, maxCheckSizeLength);
+               os.close();
+               is.close();
+               return output;
+       }
+
+       private long decompress(InputStream is, OutputStream os, long 
maxLength, long maxCheckSizeBytes) throws IOException, 
CompressionOutputSizeException {
+               CBZip2InputStream bz2is = new CBZip2InputStream(is);
+               long written = 0;
+               byte[] buffer = new byte[4096];
+               while(true) {
+                       int l = (int) Math.min(buffer.length, maxLength - 
written);
+                       // We can over-read to determine whether we have 
over-read.
+                       // We enforce maximum size this way.
+                       // FIXME there is probably a better way to do this!
+                       int x = bz2is.read(buffer, 0, buffer.length);
+                       if(l < x) {
+                               Logger.normal(this, "l="+l+", x="+x+", 
written="+written+", maxLength="+maxLength+" throwing a 
CompressionOutputSizeException");
+                               if(maxCheckSizeBytes > 0) {
+                                       written += x;
+                                       while(true) {
+                                               l = (int) 
Math.min(buffer.length, maxLength + maxCheckSizeBytes - written);
+                                               x = bz2is.read(buffer, 0, l);
+                                               if(x <= -1) throw new 
CompressionOutputSizeException(written);
+                                               if(x == 0) throw new 
IOException("Returned zero from read()");
+                                               written += x;
+                                       }
+                               }
+                               throw new CompressionOutputSizeException();
+                       }
+                       if(x <= -1) return written;
+                       if(x == 0) throw new IOException("Returned zero from 
read()");
+                       os.write(buffer, 0, x);
+                       written += x;
+               }
+       }
+
+       public int decompress(byte[] dbuf, int i, int j, byte[] output) throws 
CompressionOutputSizeException {
+               // Didn't work with Inflater.
+               // FIXME fix sometimes to use Inflater - format issue?
+               ByteArrayInputStream bais = new ByteArrayInputStream(dbuf, i, 
j);
+               ByteArrayOutputStream baos = new 
ByteArrayOutputStream(output.length);
+               int bytes = 0;
+               try {
+                       bytes = (int)decompress(bais, baos, output.length, -1);
+               } catch (IOException e) {
+                       // Impossible
+                       throw new Error("Got IOException: " + e.getMessage(), 
e);
+               }
+               byte[] buf = baos.toByteArray();
+               System.arraycopy(buf, 0, output, 0, bytes);
+               return bytes;
+       }
+}

Copied: trunk/freenet/src/freenet/support/compress/CompressJob.java (from rev 
23341, trunk/freenet/src/freenet/support/compress/CompressJob.java)
===================================================================
--- trunk/freenet/src/freenet/support/compress/CompressJob.java                 
        (rev 0)
+++ trunk/freenet/src/freenet/support/compress/CompressJob.java 2008-11-06 
13:53:57 UTC (rev 23351)
@@ -0,0 +1,9 @@
+package freenet.support.compress;
+
+import freenet.client.InsertException;
+import freenet.client.async.ClientPutState;
+
+public interface CompressJob {
+       public abstract void tryCompress() throws InsertException;
+       public abstract void onFailure(InsertException e, ClientPutState c);
+}

Modified: trunk/freenet/src/freenet/support/compress/Compressor.java
===================================================================
--- trunk/freenet/src/freenet/support/compress/Compressor.java  2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/compress/Compressor.java  2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,19 +1,86 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+* Public License, version 2 (or at your option any later version). See
+* http://www.gnu.org/ for further details of the GPL. */
 package freenet.support.compress;

+import freenet.support.Logger;
 import java.io.IOException;

-import freenet.client.Metadata;
 import freenet.support.api.Bucket;
 import freenet.support.api.BucketFactory;
+import freenet.support.io.NativeThread;
+import java.util.concurrent.Semaphore;

 /**
  * A data compressor. Contains methods to get all data compressors.
  * This is for single-file compression (gzip, bzip2) as opposed to archives.
  */
-public abstract class Compressor {
+public interface Compressor {

-    public static final Compressor GZIP = new GzipCompressor();
+       public enum COMPRESSOR_TYPE implements Compressor {
+               // They will be tried in order: put the less resource consuming 
first
+               GZIP("GZIP", new GzipCompressor(), (short) 0),
+               BZIP2("BZIP2", new Bzip2Compressor(), (short) 1),
+               LZMA("LZMA", new LZMACompressor(), (short)2);
+               
+               public final String name;
+               public final Compressor compressor;
+               public final short metadataID;
+               
+               COMPRESSOR_TYPE(String name, Compressor c, short metadataID) {
+                       this.name = name;
+                       this.compressor = c;
+                       this.metadataID = metadataID;
+               }
+               
+               public static COMPRESSOR_TYPE getCompressorByMetadataID(short 
id) {
+                       COMPRESSOR_TYPE[] values = values();
+                       for(COMPRESSOR_TYPE current : values)
+                               if(current.metadataID == id)
+                                       return current;
+                       return null;
+               }

+               public Bucket compress(Bucket data, BucketFactory bf, long 
maxLength) throws IOException, CompressionOutputSizeException {
+                       return compressor.compress(data, bf, maxLength);
+               }
+
+               public Bucket decompress(Bucket data, BucketFactory 
bucketFactory, long maxLength, long maxEstimateSizeLength, Bucket preferred) 
throws IOException, CompressionOutputSizeException {
+                       return compressor.decompress(data, bucketFactory, 
maxLength, maxEstimateSizeLength, preferred);
+               }
+
+               public int decompress(byte[] dbuf, int i, int j, byte[] output) 
throws CompressionOutputSizeException {
+                       return compressor.decompress(dbuf, i, j, output);
+               }
+               
+               
+               public static final Semaphore compressorSemaphore = new 
Semaphore(getMaxRunningCompressionThreads());
+               
+               private static int getMaxRunningCompressionThreads() {
+                       int maxRunningThreads = 1;
+                       
+                       String osName = System.getProperty("os.name");
+                       if(osName.indexOf("Windows") == -1 && 
(osName.toLowerCase().indexOf("mac os x") > 0) || 
(!NativeThread.usingNativeCode()))
+                               // OS/X niceness is really weak, so we don't 
want any more background CPU load than necessary
+                               // Also, on non-Windows, we need the native 
threads library to be working.
+                               maxRunningThreads = 1;
+                       else {
+                               // Most other OSs will have reasonable 
niceness, so go by RAM.
+                               Runtime r = Runtime.getRuntime();
+                               int max = r.availableProcessors(); // FIXME 
this may change in a VM, poll it
+                               long maxMemory = r.maxMemory();
+                               if(maxMemory < 128 * 1024 * 1024)
+                                       max = 1;
+                               else
+                                       // one compressor thread per (128MB of 
ram + available core)
+                                       max = Math.min(max, (int) 
(Math.min(Integer.MAX_VALUE, maxMemory / (128 * 1024 * 1024))));
+                               maxRunningThreads = max;
+                       }
+                       Logger.minor(COMPRESSOR_TYPE.class, "Maximum Compressor 
threads: " + maxRunningThreads);
+                       return maxRunningThreads;
+               }
+       }
+
        public abstract Bucket compress(Bucket data, BucketFactory bf, long 
maxLength) throws IOException, CompressionOutputSizeException;

        /**
@@ -29,28 +96,6 @@
         */
        public abstract Bucket decompress(Bucket data, BucketFactory 
bucketFactory, long maxLength, long maxEstimateSizeLength, Bucket preferred) 
throws IOException, CompressionOutputSizeException;

-       public abstract short codecNumberForMetadata();
-
-       /** Count the number of distinct compression algorithms currently 
supported. */
-       public static int countCompressAlgorithms() {
-               // FIXME we presently only support gzip. This should change in 
future.
-               return 1;
-       }
-
-       public static Compressor getCompressionAlgorithmByDifficulty(int i) {
-               if(i == 0)
-            return GZIP;
-               // FIXME when we get more compression algos, put them here.
-               return null;
-       }
-
-       public static Compressor getCompressionAlgorithmByMetadataID(short 
algo) {
-               if(algo == Metadata.COMPRESS_GZIP)
-            return GZIP;
-               // FIXME when we get more compression algos, put them here.
-               return null;
-       }
-       
        /** Decompress in RAM only.
         * @param dbuf Input buffer.
         * @param i Offset to start reading from.
@@ -61,5 +106,4 @@
         * @returns The number of bytes actually written.
         */
        public abstract int decompress(byte[] dbuf, int i, int j, byte[] 
output) throws CompressionOutputSizeException;
-
 }

Deleted: trunk/freenet/src/freenet/support/compress/DecompressException.java
===================================================================
--- trunk/freenet/src/freenet/support/compress/DecompressException.java 
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/compress/DecompressException.java 
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,12 +0,0 @@
-package freenet.support.compress;
-
-/**
- * Exception thrown when there is a permanent failure in decompression due to 
e.g. a format error.
- */
-public class DecompressException extends Exception {
-       private static final long serialVersionUID = 1L;
-       public DecompressException(String msg) {
-               super(msg);
-       }
-
-}

Modified: trunk/freenet/src/freenet/support/compress/GzipCompressor.java
===================================================================
--- trunk/freenet/src/freenet/support/compress/GzipCompressor.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/compress/GzipCompressor.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,6 +1,5 @@
 package freenet.support.compress;

-import freenet.client.Metadata;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -13,9 +12,8 @@
 import freenet.support.api.Bucket;
 import freenet.support.api.BucketFactory;

-public class GzipCompressor extends Compressor {
+public class GzipCompressor implements Compressor {

-       @Override
        public Bucket compress(Bucket data, BucketFactory bf, long maxLength) 
throws IOException, CompressionOutputSizeException {
                if(maxLength <= 0)
                        throw new IllegalArgumentException();
@@ -51,7 +49,6 @@
                return output;
        }

-       @Override
        public Bucket decompress(Bucket data, BucketFactory bf, long maxLength, 
long maxCheckSizeLength, Bucket preferred) throws IOException, 
CompressionOutputSizeException {
                Bucket output;
                if(preferred != null)
@@ -97,7 +94,6 @@
                }
        }

-       @Override
        public int decompress(byte[] dbuf, int i, int j, byte[] output) throws 
CompressionOutputSizeException {
                // Didn't work with Inflater.
                // FIXME fix sometimes to use Inflater - format issue?
@@ -114,9 +110,4 @@
                System.arraycopy(buf, 0, output, 0, bytes);
                return bytes;
        }
-       
-       @Override
-       public short codecNumberForMetadata() {
-               return Metadata.COMPRESS_GZIP;
-       }
 }

Copied: trunk/freenet/src/freenet/support/compress/LZMACompressor.java (from 
rev 23341, trunk/freenet/src/freenet/support/compress/LZMACompressor.java)
===================================================================
--- trunk/freenet/src/freenet/support/compress/LZMACompressor.java              
                (rev 0)
+++ trunk/freenet/src/freenet/support/compress/LZMACompressor.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -0,0 +1,117 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+* Public License, version 2 (or at your option any later version). See
+* http://www.gnu.org/ for further details of the GPL. */
+package freenet.support.compress;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import freenet.support.Logger;
+import freenet.support.api.Bucket;
+import freenet.support.api.BucketFactory;
+import net.contrapunctus.lzma.LzmaInputStream;
+import net.contrapunctus.lzma.LzmaOutputStream;
+
+public class LZMACompressor implements Compressor {
+
+       public Bucket compress(Bucket data, BucketFactory bf, long maxLength) 
throws IOException, CompressionOutputSizeException {
+               if(maxLength <= 0)
+                       throw new IllegalArgumentException();
+               Bucket output = bf.makeBucket(maxLength);
+               InputStream is = null;
+               OutputStream os = null;
+               LzmaOutputStream lzmaOS = null;
+               try {
+                       is = data.getInputStream();
+                       os = output.getOutputStream();
+                       lzmaOS = new LzmaOutputStream(os);
+                       long written = 0;
+                       // Bigger input buffer, so can compress all at once.
+                       // Won't hurt on I/O either, although most OSs will 
only return a page at a time.
+                       byte[] buffer = new byte[32768];
+                       while(true) {
+                               int l = (int) Math.min(buffer.length, maxLength 
- written);
+                               int x = is.read(buffer, 0, buffer.length);
+                               if(l < x) {
+                                       throw new 
CompressionOutputSizeException();
+                               }
+                               if(x <= -1) break;
+                               if(x == 0) throw new IOException("Returned zero 
from read()");
+                               lzmaOS.write(buffer, 0, x);
+                               written += x;
+                       }
+                       lzmaOS.flush();
+                       lzmaOS.close();
+                       os = null;
+               } finally {
+                       if(is != null) is.close();
+                       if(os != null) os.close();
+               }
+               return output;
+       }
+
+       public Bucket decompress(Bucket data, BucketFactory bf, long maxLength, 
long maxCheckSizeLength, Bucket preferred) throws IOException, 
CompressionOutputSizeException {
+               Bucket output;
+               if(preferred != null)
+                       output = preferred;
+               else
+                       output = bf.makeBucket(maxLength);
+               InputStream is = data.getInputStream();
+               OutputStream os = output.getOutputStream();
+               decompress(is, os, maxLength, maxCheckSizeLength);
+               os.close();
+               is.close();
+               return output;
+       }
+
+       private long decompress(InputStream is, OutputStream os, long 
maxLength, long maxCheckSizeBytes) throws IOException, 
CompressionOutputSizeException {
+               LzmaInputStream lzmaIS = new LzmaInputStream(is);
+               long written = 0;
+               byte[] buffer = new byte[4096];
+               while(true) {
+                       int l = (int) Math.min(buffer.length, maxLength - 
written);
+                       // We can over-read to determine whether we have 
over-read.
+                       // We enforce maximum size this way.
+                       // FIXME there is probably a better way to do this!
+                       int x = lzmaIS.read(buffer, 0, buffer.length);
+                       if(l < x) {
+                               Logger.normal(this, "l="+l+", x="+x+", 
written="+written+", maxLength="+maxLength+" throwing a 
CompressionOutputSizeException");
+                               if(maxCheckSizeBytes > 0) {
+                                       written += x;
+                                       while(true) {
+                                               l = (int) 
Math.min(buffer.length, maxLength + maxCheckSizeBytes - written);
+                                               x = lzmaIS.read(buffer, 0, l);
+                                               if(x <= -1) throw new 
CompressionOutputSizeException(written);
+                                               if(x == 0) throw new 
IOException("Returned zero from read()");
+                                               written += x;
+                                       }
+                               }
+                               throw new CompressionOutputSizeException();
+                       }
+                       if(x <= -1) return written;
+                       if(x == 0) throw new IOException("Returned zero from 
read()");
+                       os.write(buffer, 0, x);
+                       written += x;
+               }
+       }
+
+       public int decompress(byte[] dbuf, int i, int j, byte[] output) throws 
CompressionOutputSizeException {
+               // Didn't work with Inflater.
+               // FIXME fix sometimes to use Inflater - format issue?
+               ByteArrayInputStream bais = new ByteArrayInputStream(dbuf, i, 
j);
+               ByteArrayOutputStream baos = new 
ByteArrayOutputStream(output.length);
+               int bytes = 0;
+               try {
+                       bytes = (int)decompress(bais, baos, output.length, -1);
+               } catch (IOException e) {
+                       // Impossible
+                       throw new Error("Got IOException: " + e.getMessage(), 
e);
+               }
+               byte[] buf = baos.toByteArray();
+               System.arraycopy(buf, 0, output, 0, bytes);
+               return bytes;
+       }
+}

Copied: trunk/freenet/src/freenet/support/compress/RealCompressor.java (from 
rev 23341, trunk/freenet/src/freenet/support/compress/RealCompressor.java)
===================================================================
--- trunk/freenet/src/freenet/support/compress/RealCompressor.java              
                (rev 0)
+++ trunk/freenet/src/freenet/support/compress/RealCompressor.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -0,0 +1,86 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.support.compress;
+
+import freenet.client.InsertException;
+import freenet.node.PrioRunnable;
+import freenet.support.Executor;
+import freenet.support.Logger;
+import freenet.support.OOMHandler;
+import freenet.support.io.NativeThread;
+import java.util.LinkedList;
+
+public class RealCompressor implements PrioRunnable {
+       
+       private final Executor exec;
+       private static final LinkedList<CompressJob> _awaitingJobs = new 
LinkedList<CompressJob>();
+       
+       public RealCompressor(Executor e) {
+               this.exec = e;
+       }
+
+       public int getPriority() {
+               return NativeThread.HIGH_PRIORITY;
+       }
+       
+       public synchronized void enqueueNewJob(CompressJob j) {
+               _awaitingJobs.add(j);
+               notifyAll();
+       }
+
+       public void run() {
+               Logger.normal(this, "Starting RealCompressor");
+               while(true) {
+                       CompressJob currentJob = null;
+                       try {
+                               synchronized(this) {
+                                       wait();
+                                       currentJob = _awaitingJobs.poll();
+                               }
+                               if(currentJob == null)
+                                       continue;
+                               
Compressor.COMPRESSOR_TYPE.compressorSemaphore.acquire(); 
+                       } catch(InterruptedException e) {
+                               Logger.error(this, "caught: "+e.getMessage(), 
e);
+                               continue;
+                       }
+                       
+                       final CompressJob finalJob = currentJob;
+                       exec.execute(new PrioRunnable() {
+                               public void run() {
+                                       
freenet.support.Logger.OSThread.logPID(this);
+                                       try {
+                                               while(true) {
+                                                       try {
+                                                               
finalJob.tryCompress();
+                                                       } catch(InsertException 
e) {
+                                                               
finalJob.onFailure(e, null);
+                                                       } 
catch(OutOfMemoryError e) {
+                                                               
OOMHandler.handleOOM(e);
+                                                               
System.err.println("OffThreadCompressor thread above failed.");
+                                                               // Might not be 
heap, so try anyway
+                                                               
finalJob.onFailure(new InsertException(InsertException.INTERNAL_ERROR, e, 
null), null);
+                                                       } catch(Throwable t) {
+                                                               
Logger.error(this, "Caught in OffThreadCompressor: " + t, t);
+                                                               
System.err.println("Caught in OffThreadCompressor: " + t);
+                                                               
t.printStackTrace();
+                                                               // Try to fail 
gracefully
+                                                               
finalJob.onFailure(new InsertException(InsertException.INTERNAL_ERROR, t, 
null), null);
+                                                       }
+
+                                               }
+                                       } catch(Throwable t) {
+                                               Logger.error(this, "Caught " + 
t + " in " + this, t);
+                                       } finally {
+                                               
Compressor.COMPRESSOR_TYPE.compressorSemaphore.release();
+                                       }
+                               }
+
+                               public int getPriority() {
+                                       return NativeThread.MIN_PRIORITY;
+                               }
+                       }, "Compressor thread for " + currentJob);
+               }
+       }
+}
\ No newline at end of file

Modified: trunk/freenet/src/freenet/support/io/ArrayBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/ArrayBucket.java       2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/io/ArrayBucket.java       2008-11-06 
13:53:57 UTC (rev 23351)
@@ -5,8 +5,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Iterator;

 import freenet.support.api.Bucket;

@@ -18,8 +16,7 @@
  * @author oskar
  */
 public class ArrayBucket implements Bucket {
-
-       private final ArrayList<byte[]> data;
+       private volatile byte[] data;
        private String name;
        private boolean readOnly;

@@ -29,11 +26,11 @@

        public ArrayBucket(byte[] initdata) {
                this("ArrayBucket");
-               data.add(initdata);
+               data = initdata;
        }

        public ArrayBucket(String name) {
-               data = new ArrayList<byte[]>();
+               data = new byte[0];
                this.name = name;
        }

@@ -43,34 +40,16 @@
        }

        public InputStream getInputStream() {
-               return new ArrayBucketInputStream();
+               return new ByteArrayInputStream(data);
        }

        @Override
        public String toString() {
-               StringBuilder s = new StringBuilder(250);
-               for (byte[] b : data) {
-                       s.append(new String(b));
-               }
-               return s.toString();
+               return new String(data);
        }

-       public void read(InputStream in) throws IOException {
-               OutputStream out = new ArrayBucketOutputStream();
-               int i;
-               byte[] b = new byte[8 * 1024];
-               while ((i = in.read(b)) != -1) {
-                       out.write(b, 0, i);
-               }
-               out.close();
-       }
-
        public long size() {
-               long size = 0;
-               for (byte[] b : data) {
-                       size += b.length;
-               }
-               return size;
+               return data.length;
        }

        public String getName() {
@@ -87,85 +66,13 @@
                @Override
                public synchronized void close() throws IOException {
                        if(hasBeenClosed) return;
-                       data.add(super.toByteArray());
+                       data = super.toByteArray();
                        if(readOnly) throw new IOException("Read only");
                        // FIXME maybe we should throw on write instead? :)
                        hasBeenClosed = true;
                }
        }

-       private class ArrayBucketInputStream extends InputStream {
-               
-               private Iterator<byte[]> i;
-               private ByteArrayInputStream in;
-
-               public ArrayBucketInputStream() {
-                       i = data.iterator();
-               }
-
-               @Override
-               public int read() {
-                       return priv_read();
-               }
-
-               private int priv_read() {
-                       if (in == null) {
-                               if (i.hasNext()) {
-                                       in = new ByteArrayInputStream(i.next());
-                               } else {
-                                       return -1;
-                               }
-                       }
-                       int i = in.read();
-                       if (i == -1) {
-                               in = null;
-                               return priv_read();
-                       } else {
-                               return i;
-                       }
-               }
-
-               @Override
-               public int read(byte[] b) {
-                       return priv_read(b, 0, b.length);
-               }
-
-               @Override
-               public int read(byte[] b, int off, int len) {
-                       return priv_read(b, off, len);
-               }
-
-               private int priv_read(byte[] b, int off, int len) {
-                       if (in == null) {
-                               if (i.hasNext()) {
-                                       in = new ByteArrayInputStream(i.next());
-                               } else {
-                                       return -1;
-                               }
-                       }
-                       int i = in.read(b, off, len);
-                       if (i == -1) {
-                               in = null;
-                               return priv_read(b, off, len);
-                       } else {
-                               return i;
-                       }
-               }
-
-               @Override
-               public int available() {
-                       if (in == null) {
-                               if (i.hasNext()) {
-                                       in = new ByteArrayInputStream(i.next());
-                               } else {
-                                       return 0;
-                               }
-                       }
-                       return in.available();
-               }
-
-       }
-
        public boolean isReadOnly() {
                return readOnly;
        }
@@ -175,7 +82,7 @@
        }

        public void free() {
-               data.clear();
+               data = new byte[0];
                // Not much else we can do.
        }

@@ -183,13 +90,7 @@
                long sz = size();
                int size = (int)sz;
                byte[] buf = new byte[size];
-               int index = 0;
-               for (byte[] obuf : data) {                      
-                       System.arraycopy(obuf, 0, buf, index, obuf.length);
-                       index += obuf.length;
-               }
-               if(index != buf.length)
-                       throw new IllegalStateException();
+               System.arraycopy(data, 0, buf, 0, size);
                return buf;
        }
 }

Modified: trunk/freenet/src/freenet/support/io/FileBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/FileBucket.java        2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/io/FileBucket.java        2008-11-06 
13:53:57 UTC (rev 23351)
@@ -23,8 +23,6 @@
        // JVM caches File.size() and there is no way to flush the cache, so we
        // need to track it ourselves

-       protected static String tempDir = null;
-
        /**
         * Creates a new FileBucket.
         * 

Modified: trunk/freenet/src/freenet/support/io/NullBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/NullBucket.java        2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/io/NullBucket.java        2008-11-06 
13:53:57 UTC (rev 23351)
@@ -35,13 +35,6 @@
     public InputStream getInputStream() { return nullIn; }

     /**
-     * If resetWrite() is called on the object, the next getOutputStream
-     * should overwrite any other data in the bucket from the beginning,
-     * otherwise it should append it.
-     **/
-    public void resetWrite() {}
-
-    /**
      * Returns the amount of data currently in this bucket.
      **/
     public long size() {

Modified: trunk/freenet/src/freenet/support/io/NullPersistentFileTracker.java
===================================================================
--- trunk/freenet/src/freenet/support/io/NullPersistentFileTracker.java 
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/io/NullPersistentFileTracker.java 
2008-11-06 13:53:57 UTC (rev 23351)
@@ -8,6 +8,16 @@
 import freenet.support.api.Bucket;

 public class NullPersistentFileTracker implements PersistentFileTracker {
+       private static NullPersistentFileTracker instance;
+       
+       public static synchronized NullPersistentFileTracker getInstance() {
+               if (instance == null)
+                       instance = new NullPersistentFileTracker();
+               return instance;
+       }
+       
+       private NullPersistentFileTracker() {           
+       }

        public void register(File file) {
                // Do nothing
@@ -33,5 +43,4 @@
        public long getID(File file) {
                return 0;
        }
-
 }

Modified: 
trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java  
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java  
2008-11-06 13:53:57 UTC (rev 23351)
@@ -143,8 +143,8 @@
                        if(closed) throw new IOException("Already closed!");
                        if(streamNumber != lastOutputStream)
                                throw new IllegalStateException("Writing to old 
stream in "+getName());
-                       if((b < 0) || (b > 255))
-                               throw new IllegalArgumentException();
+                       //if((b < 0) || (b > 255))
+                       //      throw new IllegalArgumentException();
                        int toWrite = pcfb.encipher(b);
                        synchronized(PaddedEphemerallyEncryptedBucket.this) {
                                out.write(toWrite);
@@ -225,7 +225,7 @@

                @Override
                public int read() throws IOException {
-                       if(ptr > dataLength) return -1;
+                       if(ptr >= dataLength) return -1;
                        int x = in.read();
                        if(x == -1) return x;
                        ptr++;

Deleted: trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java
===================================================================
--- trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java      
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java      
2008-11-06 13:53:57 UTC (rev 23351)
@@ -1,237 +0,0 @@
-package freenet.support.math;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.BitSet;
-
-import freenet.support.HexUtil;
-import freenet.support.Logger;
-
-/**
- * Simple running average for binary (0.0/1.0) values.
- * Keeps the last 1000 values and generates a probability of
- * the next value being 1.0.
- * @author amphibian
- * Created on May 14, 2004
- */
-public class SimpleBinaryRunningAverage implements RunningAverage {
-       private static final long serialVersionUID = -1;
-
-    @Override
-       public Object clone() {
-        return new SimpleBinaryRunningAverage(this);
-    }
-    
-       static final int MAGIC = 0x4281;
-       
-       final int maximumSize;
-       int totalZeros;
-       int totalOnes;
-       int index;
-       long totalReported;
-       final double defaultValue;
-       final BitSet ba;
-       boolean logDEBUG;
-
-       private synchronized final int baSize() {
-               return Math.min((int)totalReported, maximumSize);
-       }
-       
-       public SimpleBinaryRunningAverage(int maxSize, double start) {
-               maximumSize = maxSize;
-               ba = new BitSet(maxSize);
-               totalZeros = totalOnes = index = 0;
-               totalReported = 0;
-               if((start < 0.0) || (start > 1.0)) {
-                   Logger.error(this, "Illegal default value: "+start+" on 
"+this,
-                           new Exception("debug"));
-                   start = Math.max(1.0, Math.min(0.0, start));
-               }
-               defaultValue = start;
-               logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
-       }
-       
-       public synchronized double currentValue() {
-           if((totalZeros < 0) || (totalOnes < 0)) {
-               Logger.error(this, "Argh in currentValue(): "+this,
-                       new Exception("debug"));
-               calculateTotalOnesZeros();
-           }
-               if((totalZeros == 0) && (totalOnes == 0))
-                       return defaultValue;
-               return ((double)totalOnes) / (double)(totalZeros + totalOnes);
-       }
-       
-       public void report(double d) {
-               report(convert(d));
-       }
-       
-       public void report(long d) {
-               report((double)d);
-       }
-       
-       public synchronized void report(boolean value) {
-               if(logDEBUG)
-                       Logger.debug(this, "Reporting: "+value+" on "+this);
-               totalReported++;
-               if(totalReported > maximumSize) {
-                       // Remove the value, that is to be overwritten, from 
the calculations 
-                       boolean valueOverwriting = ba.get(index);
-                       if(valueOverwriting)
-                               totalOnes--;
-                       else
-                               totalZeros--;
-               }
-               ba.set(index, value);
-               index++;
-               if(index >= maximumSize) index = 0;
-               if(value)
-                       totalOnes++;
-               else
-                       totalZeros++;
-               if(logDEBUG)
-                       Logger.debug(this, "Reported: "+value+" on "+this);
-           if((totalZeros < 0) || (totalOnes < 0)) {
-               Logger.error(this, "Argh in report("+value+"): "+this,
-                       new Exception("debug"));
-               calculateTotalOnesZeros();
-           }
-       }
-       
-       // Compute what the resulting average -would be- if (value) were
-       // reported, WITHOUT ACTUALLY UPDATING THE STATE OF THIS OBJECT.
-       public double valueIfReported(boolean value) {
-               int to, tz;
-               synchronized(this) {
-                       to = totalOnes;
-                       tz = totalZeros;
-                       if( (totalReported+1) > maximumSize ) {
-                               // account for the bit that would be dropped
-                               boolean valueOverwriting = ba.get(index);
-                               if(valueOverwriting)
-                                       to--;
-                               else
-                                       tz--;
-                       }
-               }
-               if(value)
-                       to++;
-               else
-                       tz++;
-               return ((double)to) / (double)(tz + to);
-       }
-       
-       public synchronized  String extraToString() {
-               return Integer.toString(totalZeros) + " 0s, "+
-                       totalOnes + " 1s, "+(totalZeros+totalOnes)+
-                       " total";
-       }
-       
-       @Override
-       public synchronized String toString() {
-               return super.toString() + " ("+extraToString()+ ')' +
-                       ", init="+defaultValue+", index="+index+", 
totalReported="+
-                       totalReported;
-       }
-       
-       public synchronized void writeDataTo(DataOutputStream out) throws 
IOException {
-               out.writeInt(MAGIC); // magic for this class
-               out.writeInt(1);
-               out.writeInt(baSize());
-               out.writeInt(index);
-               out.writeLong(totalReported);
-               out.write(HexUtil.bitsToBytes(ba, baSize()));
-       }
-       
-       public SimpleBinaryRunningAverage(int maxSize, DataInputStream dis) 
throws IOException {
-               logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
-               int magic = dis.readInt();
-               if(magic != MAGIC) throw new IOException("Invalid magic 
"+magic+" should be "+MAGIC+" - format change?");
-               int ver = dis.readInt();
-               if(ver != 1)
-                   throw new IOException("Invalid version: "+ver);
-               int size = dis.readInt();
-               if(size < 0) throw new IOException("Invalid size "+size);
-               if(size > maxSize) throw new IOException("Too big "+size);
-               index = dis.readInt();
-               if(index > size) throw new IOException("Invalid index");
-               totalReported = dis.readLong();
-               if(totalReported < 0) throw new IOException("Negative 
totalReported");
-               if(totalReported < size) throw new IOException("Invalid 
totalReported: "+totalReported+", size: "+size);
-               ba = new BitSet(maxSize);
-               maximumSize = maxSize;
-               byte[] b = new byte[HexUtil.countBytesForBits(size)];
-               dis.readFully(b);
-               HexUtil.bytesToBits(b, ba, size);
-               calculateTotalOnesZeros();
-               defaultValue = 0.5; // not used
-               if(logDEBUG)
-                       Logger.debug(this, "Created: "+this+" from "+dis);
-       }
-
-    public SimpleBinaryRunningAverage(SimpleBinaryRunningAverage a) {
-        this.ba = (BitSet) a.ba.clone();
-        this.defaultValue = a.defaultValue;
-        this.index = a.index;
-        this.maximumSize = a.maximumSize;
-        this.totalOnes = a.totalOnes;
-        this.totalReported = a.totalReported;
-        this.totalZeros = a.totalZeros;
-    }
-
-       private synchronized void calculateTotalOnesZeros() {
-               StringBuilder sb = new StringBuilder();
-               int tones = 0;
-               int tzeros = 0;
-               for(int i=0;i<baSize();i++) {
-                       if(ba.get(i)) {
-                               tones++;
-                               sb.append('1');
-                       } else {
-                               tzeros++;
-                               sb.append('0');
-                       }
-               }
-               totalOnes = tones;
-               totalZeros = tzeros;
-               if(Logger.shouldLog(Logger.DEBUG, this))
-                       Logger.debug(this, "Returning: "+totalZeros+" zeros, 
"+totalOnes+
-                                       " ones, binary: "+sb.toString());
-       }
-
-       protected String checkOnesZeros() {
-           StringBuilder sb = new StringBuilder();
-               int tones = 0;
-               int tzeros = 0;
-               for(int i=0;i<baSize();i++) {
-                       if(ba.get(i)) {
-                               tones++;
-                               sb.append('1');
-                       } else {
-                               tzeros++;
-                               sb.append('0');
-                       }
-               }
-               return "bits: " + sb.toString() + "counted " + tones + " ones 
and " + tzeros + " zeros"; 
-       }
-       
-       public int getDataLength() {
-               return 4 + 4 + 4 + 4 + 8 + HexUtil.countBytesForBits(baSize());
-       }
-
-       public boolean convert(double d) {
-               if((d > 1.0) || (d < 0.0)) throw new 
IllegalArgumentException("invalid : "+d);
-               if(d > 0.9) return true;
-               if(d < 0.1) return false;
-               throw new IllegalArgumentException("not one or other extreme!");
-       }
-       
-       public double valueIfReported(double d) {
-               return valueIfReported(convert(d));
-       }
-
-    public synchronized long countReports() {
-        return totalReported;
-    }
-}

Modified: trunk/freenet/src/freenet/support/math/SimpleRunningAverage.java
===================================================================
--- trunk/freenet/src/freenet/support/math/SimpleRunningAverage.java    
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/src/freenet/support/math/SimpleRunningAverage.java    
2008-11-06 13:53:57 UTC (rev 23351)
@@ -4,6 +4,7 @@
 package freenet.support.math;

 import java.io.DataOutputStream;
+
 import freenet.support.Logger;

 /**
@@ -46,7 +47,7 @@
         this.curLen = a.curLen;
         this.initValue = a.initValue;
         this.nextSlotPtr = a.nextSlotPtr;
-        this.refs = (double[]) a.refs.clone();
+        this.refs = a.refs.clone();
         this.total = a.total;
         this.totalReports = a.totalReports;
     }

Copied: trunk/freenet/src/net (from rev 23341, trunk/freenet/src/net)

Copied: trunk/freenet/src/net/i2p (from rev 23341, trunk/freenet/src/net/i2p)

Copied: trunk/freenet/src/net/i2p/util (from rev 23341, 
trunk/freenet/src/net/i2p/util)

Deleted: trunk/freenet/src/net/i2p/util/NativeBigInteger.java
===================================================================
--- trunk/freenet/src/net/i2p/util/NativeBigInteger.java        2008-11-06 
08:45:15 UTC (rev 23341)
+++ trunk/freenet/src/net/i2p/util/NativeBigInteger.java        2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,493 +0,0 @@
-package net.i2p.util;
-/*
- * 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.math.BigInteger;
-import java.util.Random;
-import java.net.URL;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.FileNotFoundException;
-import java.io.File;
-
-import freenet.support.HexUtil;
-import freenet.support.Logger;
-import freenet.support.CPUInformation.AMDCPUInfo;
-import freenet.support.CPUInformation.CPUID;
-import freenet.support.CPUInformation.CPUInfo;
-import freenet.support.CPUInformation.IntelCPUInfo;
-import freenet.support.CPUInformation.UnknownCPUException;
-import freenet.support.io.Closer;
-
-/**
- * <p>BigInteger that takes advantage of the jbigi library for the modPow 
operation,
- * which accounts for a massive segment of the processing cost of asymmetric 
- * crypto. It also takes advantage of the jbigi library for converting a 
BigInteger
- * value to a double. Sun's implementation of the 'doubleValue()' method is 
_very_ lousy.
- * 
- * The jbigi library itself is basically just a JNI wrapper around the 
- * GMP library - a collection of insanely efficient routines for dealing with 
- * big numbers.</p>
- *
- * There are three environmental properties for configuring this component: 
<ul>
- * <li><b>jbigi.enable</b>: whether to use the native library (defaults to 
"true")</li>
- * <li><b>jbigi.impl</b>: select which resource to use as the native 
implementation</li>
- * <li><b>jbigi.ref</b>: the file specified in this parameter may contain a 
resource
- *                       name to override jbigi.impl (defaults to 
"jbigi.cfg")</li>
- * </ul>
- *
- * <p>If jbigi.enable is set to false, this class won't even attempt to use 
the 
- * native library, but if it is set to true (or is not specified), it will 
first 
- * check the platform specific library path for the "jbigi" library, as 
defined by 
- * {@link Runtime#loadLibrary} - e.g. C:\windows\jbigi.dll or 
/lib/libjbigi.so.  
- * If that fails, it reviews the jbigi.impl environment property - if that is 
set,
- * it checks all of the components in the CLASSPATH for the file specified and
- * attempts to load it as the native library.  If jbigi.impl is not set, if 
there
- * is no matching resource, or if that resource is not a valid OS/architecture
- * specific library, the NativeBigInteger will revert to using the pure java 
- * implementation.</p>
- * 
- * <p>That means <b>NativeBigInteger will not attempt to guess the correct 
- * platform/OS/whatever</b> - applications using this class should define that 
- * property prior to <i>referencing</i> the NativeBigInteger (or before loading
- * the JVM, of course).  Alternately, people with custom built jbigi 
implementations
- * in their OS's standard search path (LD_LIBRARY_PATH, etc) needn't 
bother.</p>
- *
- * <p>One way to deploy the native library is to create a jbigi.jar file 
containing 
- * all of the native implementations with filenames such as "win-athlon", 
"linux-p2",
- * "freebsd-sparcv4", where those files are the OS specific libraries (the 
contents of
- * the DLL or .so file built for those OSes / architectures).  The user would 
then
- * simply specify -Djbigi.impl=win-athlon and this component would pick up 
that 
- * library.</p>
- *
- * <p>Another way is to create a seperate jbigi.jar file for each platform 
containing
- * one file - "native", where that file is the OS / architecture specific 
library 
- * implementation, as above.  This way the user would download the correct 
jbigi.jar
- * (and not all of the libraries for platforms/OSes they don't need) and would 
specify
- * -Djbigi.impl=native.</p>
- *
- * <p>Running this class by itself does a basic unit test and benchmarks the
- * NativeBigInteger.modPow/doubleValue vs. the BigInteger.modPow/doubleValue 
by running a 2Kbit op 100
- * times.  At the end of each test, if the native implementation is loaded 
this will output 
- * something like:</p>
- * <pre>
- *  native run time:        6090ms (60ms each)
- *  java run time:          68067ms (673ms each)
- *  native = 8.947066860593239% of pure java time
- * </pre>
- * 
- * <p>If the native implementation is not loaded, it will start by saying:</p>
- * <pre>
- *  WARN: Native BigInteger library jbigi not loaded - using pure java
- * </pre>
- * <p>Then go on to run the test, finally outputting:</p>
- * <pre>
- *  java run time:  64653ms (640ms each)
- *  However, we couldn't load the native library, so this doesn't test much
- * </pre>
- *
- */
-public class NativeBigInteger extends BigInteger {
-
-       /** did we load the native lib correctly? */
-       private static boolean _nativeOk = false;
-       /** 
-        * do we want to dump some basic success/failure info to stderr during 
-        * initialization?  this would otherwise use the Log component, but 
this makes
-        * it easier for other systems to reuse this class
-        */
-       private static final boolean _doLog = true;
-       private final static String JBIGI_OPTIMIZATION_K6 = "k6";
-       private final static String JBIGI_OPTIMIZATION_K6_2 = "k62";
-       private final static String JBIGI_OPTIMIZATION_K6_3 = "k63";
-       private final static String JBIGI_OPTIMIZATION_ATHLON = "athlon";
-       private final static String JBIGI_OPTIMIZATION_X86_64 = "x86_64";
-       private final static String JBIGI_OPTIMIZATION_X86_64_32 = "x86_64_32";
-       private final static String JBIGI_OPTIMIZATION_PENTIUM = "pentium";
-       private final static String JBIGI_OPTIMIZATION_PENTIUMMMX = 
"pentiummmx";
-       private final static String JBIGI_OPTIMIZATION_PENTIUM2 = "pentium2";
-       private final static String JBIGI_OPTIMIZATION_PENTIUM3 = "pentium3";
-       private final static String JBIGI_OPTIMIZATION_PENTIUM4 = "pentium4";
-       private final static String JBIGI_OPTIMIZATION_PPC = "ppc";
-       private final static String sCPUType; //The CPU Type to optimize for 
(one of the above strings)
-       private static final long serialVersionUID = 0xc5392a97bb283dd2L;
-
-       static {
-               sCPUType = resolveCPUType();
-               loadNative();
-       }
-
-       /** Tries to resolve the best type of CPU that we have an optimized 
jbigi-dll/so for.
-        * @return A string containing the CPU-type or null if CPU type is 
unknown
-        */
-       private static String resolveCPUType() {
-               try {
-                       
if(System.getProperty("os.arch").toLowerCase().matches("(i?[x0-9]86_64|amd64)"))
-                               return JBIGI_OPTIMIZATION_X86_64;
-                       else 
if(System.getProperty("os.arch").toLowerCase().matches("(ppc)")) {
-                               System.out.println("Detected PowerPC!");
-                               return JBIGI_OPTIMIZATION_PPC;
-                       } else {
-                               CPUInfo c = CPUID.getInfo();
-                               if(c instanceof AMDCPUInfo) {
-                                       AMDCPUInfo amdcpu = (AMDCPUInfo) c;
-                                       if(amdcpu.IsAthlon64Compatible())
-                                               return 
JBIGI_OPTIMIZATION_X86_64_32;
-                                       if(amdcpu.IsAthlonCompatible())
-                                               return 
JBIGI_OPTIMIZATION_ATHLON;
-                                       if(amdcpu.IsK6_3_Compatible())
-                                               return JBIGI_OPTIMIZATION_K6_3;
-                                       if(amdcpu.IsK6_2_Compatible())
-                                               return JBIGI_OPTIMIZATION_K6_2;
-                                       if(amdcpu.IsK6Compatible())
-                                               return JBIGI_OPTIMIZATION_K6;
-                               } else
-                                       if(c instanceof IntelCPUInfo) {
-                                               IntelCPUInfo intelcpu = 
(IntelCPUInfo) c;
-                                               
if(intelcpu.IsPentium4Compatible())
-                                                       return 
JBIGI_OPTIMIZATION_PENTIUM4;
-                                               
if(intelcpu.IsPentium3Compatible())
-                                                       return 
JBIGI_OPTIMIZATION_PENTIUM3;
-                                               
if(intelcpu.IsPentium2Compatible())
-                                                       return 
JBIGI_OPTIMIZATION_PENTIUM2;
-                                               
if(intelcpu.IsPentiumMMXCompatible())
-                                                       return 
JBIGI_OPTIMIZATION_PENTIUMMMX;
-                                               
if(intelcpu.IsPentiumCompatible())
-                                                       return 
JBIGI_OPTIMIZATION_PENTIUM;
-                                       }
-                       }
-                       return null;
-               } catch(UnknownCPUException e) {
-                       return null; //TODO: Log something here maybe..
-               }
-       }
-
-       /**
-        * calculate (base ^ exponent) % modulus.
-        * 
-        * @param base
-        *            big endian twos complement representation of the base 
(but it must be positive)
-        * @param exponent
-        *            big endian twos complement representation of the exponent
-        * @param modulus
-        *            big endian twos complement representation of the modulus
-        * @return big endian twos complement representation of (base ^ 
exponent) % modulus
-        */
-       public native static byte[] nativeModPow(byte base[], byte exponent[], 
byte modulus[]);
-
-       /**
-        * Converts a BigInteger byte-array to a 'double'
-        * @param ba Big endian twos complement representation of the 
BigInteger to convert to a double
-        * @return The plain double-value represented by 'ba'
-        */
-       public native static double nativeDoubleValue(byte ba[]);
-       private byte[] cachedBa = null;
-
-       public NativeBigInteger(byte val[]) {
-               super(val);
-       // Takes up too much RAM
-//        int targetLength = bitLength() / 8 + 1;
-//        if(val.length == targetLength)
-//            cachedBa = val;
-       }
-
-       public NativeBigInteger(int signum, byte magnitude[]) {
-               super(signum, magnitude);
-       }
-
-       public NativeBigInteger(int bitlen, int certainty, Random rnd) {
-               super(bitlen, certainty, rnd);
-       }
-
-       public NativeBigInteger(int numbits, Random rnd) {
-               super(numbits, rnd);
-       }
-
-       public NativeBigInteger(String val) {
-               super(val);
-       }
-
-       public NativeBigInteger(String val, int radix) {
-               super(val, radix);
-       }
-
-       /**Creates a new NativeBigInteger with the same value
-        *  as the supplied BigInteger. Warning!, not very efficent
-        */
-       public NativeBigInteger(BigInteger integer) {
-               //Now, why doesn't sun provide a constructor
-               //like this one in BigInteger?
-               this(integer.toByteArray());
-       }
-
-       @Override
-       public BigInteger modPow(BigInteger exponent, BigInteger m) {
-               if(_nativeOk)
-                       return new NativeBigInteger(nativeModPow(toByteArray(), 
exponent.toByteArray(), m.toByteArray()));
-               else
-                       return new NativeBigInteger(super.modPow(exponent, m));
-       }
-
-       @Override
-       public byte[] toByteArray() {
-               if(cachedBa == null) //Since we are immutable it is safe to 
never update the cached ba after it has initially been generated
-                       cachedBa = super.toByteArray();
-               return cachedBa;
-       }
-
-       @Override
-       public String toString(int radix) {
-               if(radix == 16)
-                       return toHexString();
-               return super.toString(radix);
-       }
-
-       public String toHexString() {
-               byte[] buf = toByteArray();
-               return HexUtil.bytesToHex(buf);
-       }
-
-       @Override
-       public double doubleValue() {
-               if(_nativeOk)
-                       return nativeDoubleValue(toByteArray());
-               else
-                       return super.doubleValue();
-       }
-
-       /**
-        * 
-        * @return True iff native methods will be used by this class
-        */
-       public static boolean isNative() {
-               return _nativeOk;
-       }
-       /**
-        * <p>Do whatever we can to load up the native library backing this 
BigInteger's native methods.
-        * If it can find a custom built jbigi.dll / libjbigi.so, it'll use 
that.  Otherwise
-        * it'll try to look in the classpath for the correct library (see 
loadFromResource).
-        * If the user specifies -Djbigi.enable=false it'll skip all of 
this.</p>
-        *
-        */
-       private static final void loadNative() {
-               try {
-                       String wantedProp = System.getProperty("jbigi.enable", 
"true");
-                       boolean wantNative = 
"true".equalsIgnoreCase(wantedProp);
-                       if(wantNative) {
-                               boolean loaded = loadFromResource(true);
-                               if(loaded) {
-                                       _nativeOk = true;
-                                       if(_doLog)
-                                               System.err.println("INFO: 
Optimized native BigInteger library '" + getResourceName(true) + "' loaded from 
resource");
-                               } else {
-                                       loaded = loadGeneric(true);
-                                       if(loaded) {
-                                               _nativeOk = true;
-                                               if(_doLog)
-                                                       
System.err.println("INFO: Optimized native BigInteger library '" + 
getMiddleName(true) + "' loaded from somewhere in the path");
-                                       } else {
-                                               loaded = 
loadFromResource(false);
-                                               if(loaded) {
-                                                       _nativeOk = true;
-                                                       if(_doLog)
-                                                               
System.err.println("INFO: Non-optimized native BigInteger library '" + 
getResourceName(false) + "' loaded from resource");
-                                               } else {
-                                                       loaded = 
loadGeneric(false);
-                                                       if(loaded) {
-                                                               _nativeOk = 
true;
-                                                               if(_doLog)
-                                                                       
System.err.println("INFO: Non-optimized native BigInteger library '" + 
getMiddleName(false) + "' loaded from somewhere in the path");
-                                                       } else
-                                                               _nativeOk = 
false;
-                                               }
-                                       }
-                               }
-                       }
-                       if(_doLog && !_nativeOk)
-                               System.err.println("INFO: Native BigInteger 
library jbigi not loaded - using pure java");
-               } catch(Throwable e) {
-                       if(_doLog)
-                               System.err.println("INFO: Native BigInteger 
library jbigi not loaded, reason: '" + e.getMessage() + "' - using pure java");
-               }
-       }
-
-       /** 
-        * <p>Try loading it from an explictly build jbigi.dll / libjbigi.so 
first, before 
-        * looking into a jbigi.jar for any other libraries.</p>
-        *
-        * @return true if it was loaded successfully, else false
-        *
-        */
-       private static final boolean loadGeneric(boolean optimized) {
-               try {
-                       String name = getMiddleName(optimized);
-                       if(name == null)
-                               return false;
-                       System.loadLibrary(name);
-                       return true;
-               } catch(UnsatisfiedLinkError ule) {
-                       return false;
-               }
-       }
-
-       /**
-        * A helper function to make loading the native library easier.
-        * @param f The File to which to write the library
-        * @param URL The URL of the resource
-        * @return True is the library was loaded, false on error
-        * @throws FileNotFoundException If the library could not be read from 
the reference
-        * @throws UnsatisfiedLinkError If and only if the library is 
incompatible with this system
-        */
-       private static final boolean tryLoadResource(File f, URL resource)
-               throws FileNotFoundException, UnsatisfiedLinkError {
-               InputStream is;
-               try {
-                       is = resource.openStream();
-               } catch(IOException e) {
-                       f.delete();
-                       throw new FileNotFoundException();
-               }
-
-               FileOutputStream fos = null;
-               try {
-                       f.deleteOnExit();
-                       fos = new FileOutputStream(f);
-                       byte[] buf = new byte[4096 * 1024];
-                       int read;
-                       while((read = is.read(buf)) > 0) {
-                               fos.write(buf, 0, read);
-                       }
-                       fos.close();
-                       fos = null;
-                       System.load(f.getAbsolutePath());
-                       return true;
-               } catch(IOException e) {
-               } catch(UnsatisfiedLinkError ule) {
-                       // likely to be "noexec" 
-                       if(ule.toString().toLowerCase().indexOf("not 
permitted") == -1)
-                               throw ule;
-               } finally {
-                       Closer.close(fos);
-                       f.delete();
-               }
-
-               return false;
-       }
-
-       /**
-        * <p>Check all of the jars in the classpath for the file specified by 
the 
-        * environmental property "jbigi.impl" and load it as the native 
library 
-        * implementation.  For instance, a windows user on a p4 would define
-        * -Djbigi.impl=win-686 if there is a jbigi.jar in the classpath 
containing the 
-        * files "win-686", "win-athlon", "freebsd-p4", "linux-p3", where each 
-        * of those files contain the correct binary file for a native library 
(e.g.
-        * windows DLL, or a *nix .so).  </p>
-        * 
-        * <p>This is a pretty ugly hack, using the general technique 
illustrated by the
-        * onion FEC libraries.  It works by pulling the resource, writing out 
the 
-        * byte stream to a temporary file, loading the native library from 
that file,
-        * then deleting the file.</p>
-        *
-        * @return true if it was loaded successfully, else false
-        *
-        */
-       private static final boolean loadFromResource(boolean optimized) {
-               String resourceName = getResourceName(optimized);
-               if(resourceName == null)
-                       return false;
-               URL resource = 
NativeBigInteger.class.getClassLoader().getResource(resourceName);
-               if(resource == null) {
-                       if(_doLog)
-                               System.err.println("NOTICE: Resource name [" + 
getResourceName(true) + "] was not found");
-                       return false;
-               }
-               File temp = null;
-               try {
-                       try {
-                               temp = File.createTempFile("jbigi", "lib.tmp");
-                               if(tryLoadResource(temp, resource))
-                                       return true;
-                       } catch(IOException e) {
-                       } finally {
-                               if(temp != null) temp.delete();
-                       }
-                       Logger.error(NativeBigInteger.class, "Can't load from " 
+ System.getProperty("java.io.tmpdir"));
-                       System.err.println("Can't load from " + 
System.getProperty("java.io.tmpdir"));
-                       temp = new File("jbigi-lib.tmp");
-                       if(tryLoadResource(temp, resource))
-                               return true;
-               } catch(Exception fnf) {
-                       Logger.error(NativeBigInteger.class, "Error reading 
jbigi resource", fnf);
-                       System.err.println("Error reading jbigi resource");
-               } catch(UnsatisfiedLinkError ule) {
-                       Logger.error(NativeBigInteger.class, "Library " + 
resourceName + " is not appropriate for this system.");
-                       System.err.println("Library " + resourceName + " is not 
appropriate for this system.");
-               } finally {
-                       if(temp != null) temp.delete();
-               }
-
-               return false;
-       }
-
-       private static final String getResourceName(boolean optimized) {
-               String pname = 
NativeBigInteger.class.getPackage().getName().replace('.', '/');
-               String pref = getLibraryPrefix();
-               String middle = getMiddleName(optimized);
-               String suff = getLibrarySuffix();
-               if((pref == null) || (middle == null) || (suff == null))
-                       return null;
-               return pname + '/' + pref + middle + '.' + suff;
-       }
-
-       private static final String getMiddleName(boolean optimized) {
-
-               String sAppend;
-               if(optimized)
-                       if(sCPUType == null)
-                               return null;
-                       else
-                               sAppend = '-' + sCPUType;
-               else
-                       sAppend = "-none";
-
-               boolean isWindows = 
(System.getProperty("os.name").toLowerCase().indexOf("windows") != -1);
-               boolean isLinux = 
(System.getProperty("os.name").toLowerCase().indexOf("linux") != -1);
-               boolean isFreebsd = 
(System.getProperty("os.name").toLowerCase().indexOf("freebsd") != -1);
-               boolean isMacOS = 
(System.getProperty("os.name").toLowerCase().indexOf("mac os x") != -1);
-               if(isWindows)
-                       return "jbigi-windows" + sAppend; // The convention on 
Windows
-               if(isLinux)
-                       return "jbigi-linux" + sAppend; // The convention on 
linux...
-               if(isFreebsd)
-                       return "jbigi-freebsd" + sAppend; // The convention on 
freebsd...
-               if(isMacOS)
-                       return "jbigi-osx" + sAppend; // The convention on Mac 
OS X...
-               throw new RuntimeException("Dont know jbigi library name for os 
type '" + System.getProperty("os.name") + '\'');
-       }
-
-       private static final String getLibrarySuffix() {
-               boolean isWindows = 
System.getProperty("os.name").toLowerCase().indexOf("windows") != -1;
-               boolean isMacOS = 
(System.getProperty("os.name").toLowerCase().indexOf("mac os x") != -1);
-               if(isWindows)
-                       return "dll";
-               else if(isMacOS)
-                       return "jnilib";
-               else
-                       return "so";
-       }
-
-       private static final String getLibraryPrefix() {
-               boolean isWindows = 
System.getProperty("os.name").toLowerCase().indexOf("windows") != -1;
-               if(isWindows)
-                       return "";
-               else
-                       return "lib";
-       }
-}

Copied: trunk/freenet/src/net/i2p/util/NativeBigInteger.java (from rev 23341, 
trunk/freenet/src/net/i2p/util/NativeBigInteger.java)
===================================================================
--- trunk/freenet/src/net/i2p/util/NativeBigInteger.java                        
        (rev 0)
+++ trunk/freenet/src/net/i2p/util/NativeBigInteger.java        2008-11-06 
13:53:57 UTC (rev 23351)
@@ -0,0 +1,493 @@
+package net.i2p.util;
+/*
+ * 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.math.BigInteger;
+import java.util.Random;
+import java.net.URL;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.File;
+
+import freenet.support.HexUtil;
+import freenet.support.Logger;
+import freenet.support.CPUInformation.AMDCPUInfo;
+import freenet.support.CPUInformation.CPUID;
+import freenet.support.CPUInformation.CPUInfo;
+import freenet.support.CPUInformation.IntelCPUInfo;
+import freenet.support.CPUInformation.UnknownCPUException;
+import freenet.support.io.Closer;
+
+/**
+ * <p>BigInteger that takes advantage of the jbigi library for the modPow 
operation,
+ * which accounts for a massive segment of the processing cost of asymmetric 
+ * crypto. It also takes advantage of the jbigi library for converting a 
BigInteger
+ * value to a double. Sun's implementation of the 'doubleValue()' method is 
_very_ lousy.
+ * 
+ * The jbigi library itself is basically just a JNI wrapper around the 
+ * GMP library - a collection of insanely efficient routines for dealing with 
+ * big numbers.</p>
+ *
+ * There are three environmental properties for configuring this component: 
<ul>
+ * <li><b>jbigi.enable</b>: whether to use the native library (defaults to 
"true")</li>
+ * <li><b>jbigi.impl</b>: select which resource to use as the native 
implementation</li>
+ * <li><b>jbigi.ref</b>: the file specified in this parameter may contain a 
resource
+ *                       name to override jbigi.impl (defaults to 
"jbigi.cfg")</li>
+ * </ul>
+ *
+ * <p>If jbigi.enable is set to false, this class won't even attempt to use 
the 
+ * native library, but if it is set to true (or is not specified), it will 
first 
+ * check the platform specific library path for the "jbigi" library, as 
defined by 
+ * {@link Runtime#loadLibrary} - e.g. C:\windows\jbigi.dll or 
/lib/libjbigi.so.  
+ * If that fails, it reviews the jbigi.impl environment property - if that is 
set,
+ * it checks all of the components in the CLASSPATH for the file specified and
+ * attempts to load it as the native library.  If jbigi.impl is not set, if 
there
+ * is no matching resource, or if that resource is not a valid OS/architecture
+ * specific library, the NativeBigInteger will revert to using the pure java 
+ * implementation.</p>
+ * 
+ * <p>That means <b>NativeBigInteger will not attempt to guess the correct 
+ * platform/OS/whatever</b> - applications using this class should define that 
+ * property prior to <i>referencing</i> the NativeBigInteger (or before loading
+ * the JVM, of course).  Alternately, people with custom built jbigi 
implementations
+ * in their OS's standard search path (LD_LIBRARY_PATH, etc) needn't 
bother.</p>
+ *
+ * <p>One way to deploy the native library is to create a jbigi.jar file 
containing 
+ * all of the native implementations with filenames such as "win-athlon", 
"linux-p2",
+ * "freebsd-sparcv4", where those files are the OS specific libraries (the 
contents of
+ * the DLL or .so file built for those OSes / architectures).  The user would 
then
+ * simply specify -Djbigi.impl=win-athlon and this component would pick up 
that 
+ * library.</p>
+ *
+ * <p>Another way is to create a seperate jbigi.jar file for each platform 
containing
+ * one file - "native", where that file is the OS / architecture specific 
library 
+ * implementation, as above.  This way the user would download the correct 
jbigi.jar
+ * (and not all of the libraries for platforms/OSes they don't need) and would 
specify
+ * -Djbigi.impl=native.</p>
+ *
+ * <p>Running this class by itself does a basic unit test and benchmarks the
+ * NativeBigInteger.modPow/doubleValue vs. the BigInteger.modPow/doubleValue 
by running a 2Kbit op 100
+ * times.  At the end of each test, if the native implementation is loaded 
this will output 
+ * something like:</p>
+ * <pre>
+ *  native run time:        6090ms (60ms each)
+ *  java run time:          68067ms (673ms each)
+ *  native = 8.947066860593239% of pure java time
+ * </pre>
+ * 
+ * <p>If the native implementation is not loaded, it will start by saying:</p>
+ * <pre>
+ *  WARN: Native BigInteger library jbigi not loaded - using pure java
+ * </pre>
+ * <p>Then go on to run the test, finally outputting:</p>
+ * <pre>
+ *  java run time:  64653ms (640ms each)
+ *  However, we couldn't load the native library, so this doesn't test much
+ * </pre>
+ *
+ */
+public class NativeBigInteger extends BigInteger {
+
+       /** did we load the native lib correctly? */
+       private static boolean _nativeOk = false;
+       /** 
+        * do we want to dump some basic success/failure info to stderr during 
+        * initialization?  this would otherwise use the Log component, but 
this makes
+        * it easier for other systems to reuse this class
+        */
+       private static final boolean _doLog = true;
+       private final static String JBIGI_OPTIMIZATION_K6 = "k6";
+       private final static String JBIGI_OPTIMIZATION_K6_2 = "k62";
+       private final static String JBIGI_OPTIMIZATION_K6_3 = "k63";
+       private final static String JBIGI_OPTIMIZATION_ATHLON = "athlon";
+       private final static String JBIGI_OPTIMIZATION_X86_64 = "x86_64";
+       private final static String JBIGI_OPTIMIZATION_X86_64_32 = "x86_64_32";
+       private final static String JBIGI_OPTIMIZATION_PENTIUM = "pentium";
+       private final static String JBIGI_OPTIMIZATION_PENTIUMMMX = 
"pentiummmx";
+       private final static String JBIGI_OPTIMIZATION_PENTIUM2 = "pentium2";
+       private final static String JBIGI_OPTIMIZATION_PENTIUM3 = "pentium3";
+       private final static String JBIGI_OPTIMIZATION_PENTIUM4 = "pentium4";
+       private final static String JBIGI_OPTIMIZATION_PPC = "ppc";
+       private final static String sCPUType; //The CPU Type to optimize for 
(one of the above strings)
+       private static final long serialVersionUID = 0xc5392a97bb283dd2L;
+
+       static {
+               sCPUType = resolveCPUType();
+               loadNative();
+       }
+
+       /** Tries to resolve the best type of CPU that we have an optimized 
jbigi-dll/so for.
+        * @return A string containing the CPU-type or null if CPU type is 
unknown
+        */
+       private static String resolveCPUType() {
+               try {
+                       
if(System.getProperty("os.arch").toLowerCase().matches("(i?[x0-9]86_64|amd64)"))
+                               return JBIGI_OPTIMIZATION_X86_64;
+                       else 
if(System.getProperty("os.arch").toLowerCase().matches("(ppc)")) {
+                               System.out.println("Detected PowerPC!");
+                               return JBIGI_OPTIMIZATION_PPC;
+                       } else {
+                               CPUInfo c = CPUID.getInfo();
+                               if(c instanceof AMDCPUInfo) {
+                                       AMDCPUInfo amdcpu = (AMDCPUInfo) c;
+                                       if(amdcpu.IsAthlon64Compatible())
+                                               return 
JBIGI_OPTIMIZATION_X86_64_32;
+                                       if(amdcpu.IsAthlonCompatible())
+                                               return 
JBIGI_OPTIMIZATION_ATHLON;
+                                       if(amdcpu.IsK6_3_Compatible())
+                                               return JBIGI_OPTIMIZATION_K6_3;
+                                       if(amdcpu.IsK6_2_Compatible())
+                                               return JBIGI_OPTIMIZATION_K6_2;
+                                       if(amdcpu.IsK6Compatible())
+                                               return JBIGI_OPTIMIZATION_K6;
+                               } else
+                                       if(c instanceof IntelCPUInfo) {
+                                               IntelCPUInfo intelcpu = 
(IntelCPUInfo) c;
+                                               
if(intelcpu.IsPentium4Compatible())
+                                                       return 
JBIGI_OPTIMIZATION_PENTIUM4;
+                                               
if(intelcpu.IsPentium3Compatible())
+                                                       return 
JBIGI_OPTIMIZATION_PENTIUM3;
+                                               
if(intelcpu.IsPentium2Compatible())
+                                                       return 
JBIGI_OPTIMIZATION_PENTIUM2;
+                                               
if(intelcpu.IsPentiumMMXCompatible())
+                                                       return 
JBIGI_OPTIMIZATION_PENTIUMMMX;
+                                               
if(intelcpu.IsPentiumCompatible())
+                                                       return 
JBIGI_OPTIMIZATION_PENTIUM;
+                                       }
+                       }
+                       return null;
+               } catch(UnknownCPUException e) {
+                       return null; //TODO: Log something here maybe..
+               }
+       }
+
+       /**
+        * calculate (base ^ exponent) % modulus.
+        * 
+        * @param base
+        *            big endian twos complement representation of the base 
(but it must be positive)
+        * @param exponent
+        *            big endian twos complement representation of the exponent
+        * @param modulus
+        *            big endian twos complement representation of the modulus
+        * @return big endian twos complement representation of (base ^ 
exponent) % modulus
+        */
+       public native static byte[] nativeModPow(byte base[], byte exponent[], 
byte modulus[]);
+
+       /**
+        * Converts a BigInteger byte-array to a 'double'
+        * @param ba Big endian twos complement representation of the 
BigInteger to convert to a double
+        * @return The plain double-value represented by 'ba'
+        */
+       public native static double nativeDoubleValue(byte ba[]);
+       private byte[] cachedBa = null;
+
+       public NativeBigInteger(byte val[]) {
+               super(val);
+       // Takes up too much RAM
+//        int targetLength = bitLength() / 8 + 1;
+//        if(val.length == targetLength)
+//            cachedBa = val;
+       }
+
+       public NativeBigInteger(int signum, byte magnitude[]) {
+               super(signum, magnitude);
+       }
+
+       public NativeBigInteger(int bitlen, int certainty, Random rnd) {
+               super(bitlen, certainty, rnd);
+       }
+
+       public NativeBigInteger(int numbits, Random rnd) {
+               super(numbits, rnd);
+       }
+
+       public NativeBigInteger(String val) {
+               super(val);
+       }
+
+       public NativeBigInteger(String val, int radix) {
+               super(val, radix);
+       }
+
+       /**Creates a new NativeBigInteger with the same value
+        *  as the supplied BigInteger. Warning!, not very efficent
+        */
+       public NativeBigInteger(BigInteger integer) {
+               //Now, why doesn't sun provide a constructor
+               //like this one in BigInteger?
+               this(integer.toByteArray());
+       }
+
+       @Override
+       public BigInteger modPow(BigInteger exponent, BigInteger m) {
+               if(_nativeOk)
+                       return new NativeBigInteger(nativeModPow(toByteArray(), 
exponent.toByteArray(), m.toByteArray()));
+               else
+                       return new NativeBigInteger(super.modPow(exponent, m));
+       }
+
+       @Override
+       public byte[] toByteArray() {
+               if(cachedBa == null) //Since we are immutable it is safe to 
never update the cached ba after it has initially been generated
+                       cachedBa = super.toByteArray();
+               return cachedBa;
+       }
+
+       @Override
+       public String toString(int radix) {
+               if(radix == 16)
+                       return toHexString();
+               return super.toString(radix);
+       }
+
+       public String toHexString() {
+               byte[] buf = toByteArray();
+               return HexUtil.bytesToHex(buf);
+       }
+
+       @Override
+       public double doubleValue() {
+               if(_nativeOk)
+                       return nativeDoubleValue(toByteArray());
+               else
+                       return super.doubleValue();
+       }
+
+       /**
+        * 
+        * @return True iff native methods will be used by this class
+        */
+       public static boolean isNative() {
+               return _nativeOk;
+       }
+       /**
+        * <p>Do whatever we can to load up the native library backing this 
BigInteger's native methods.
+        * If it can find a custom built jbigi.dll / libjbigi.so, it'll use 
that.  Otherwise
+        * it'll try to look in the classpath for the correct library (see 
loadFromResource).
+        * If the user specifies -Djbigi.enable=false it'll skip all of 
this.</p>
+        *
+        */
+       private static final void loadNative() {
+               try {
+                       String wantedProp = System.getProperty("jbigi.enable", 
"true");
+                       boolean wantNative = 
"true".equalsIgnoreCase(wantedProp);
+                       if(wantNative) {
+                               boolean loaded = loadFromResource(true);
+                               if(loaded) {
+                                       _nativeOk = true;
+                                       if(_doLog)
+                                               System.err.println("INFO: 
Optimized native BigInteger library '" + getResourceName(true) + "' loaded from 
resource");
+                               } else {
+                                       loaded = loadGeneric(true);
+                                       if(loaded) {
+                                               _nativeOk = true;
+                                               if(_doLog)
+                                                       
System.err.println("INFO: Optimized native BigInteger library '" + 
getMiddleName(true) + "' loaded from somewhere in the path");
+                                       } else {
+                                               loaded = 
loadFromResource(false);
+                                               if(loaded) {
+                                                       _nativeOk = true;
+                                                       if(_doLog)
+                                                               
System.err.println("INFO: Non-optimized native BigInteger library '" + 
getResourceName(false) + "' loaded from resource");
+                                               } else {
+                                                       loaded = 
loadGeneric(false);
+                                                       if(loaded) {
+                                                               _nativeOk = 
true;
+                                                               if(_doLog)
+                                                                       
System.err.println("INFO: Non-optimized native BigInteger library '" + 
getMiddleName(false) + "' loaded from somewhere in the path");
+                                                       } else
+                                                               _nativeOk = 
false;
+                                               }
+                                       }
+                               }
+                       }
+                       if(_doLog && !_nativeOk)
+                               System.err.println("INFO: Native BigInteger 
library jbigi not loaded - using pure java");
+               } catch(Throwable e) {
+                       if(_doLog)
+                               System.err.println("INFO: Native BigInteger 
library jbigi not loaded, reason: '" + e.getMessage() + "' - using pure java");
+               }
+       }
+
+       /** 
+        * <p>Try loading it from an explictly build jbigi.dll / libjbigi.so 
first, before 
+        * looking into a jbigi.jar for any other libraries.</p>
+        *
+        * @return true if it was loaded successfully, else false
+        *
+        */
+       private static final boolean loadGeneric(boolean optimized) {
+               try {
+                       String name = getMiddleName(optimized);
+                       if(name == null)
+                               return false;
+                       System.loadLibrary(name);
+                       return true;
+               } catch(UnsatisfiedLinkError ule) {
+                       return false;
+               }
+       }
+
+       /**
+        * A helper function to make loading the native library easier.
+        * @param f The File to which to write the library
+        * @param URL The URL of the resource
+        * @return True is the library was loaded, false on error
+        * @throws FileNotFoundException If the library could not be read from 
the reference
+        * @throws UnsatisfiedLinkError If and only if the library is 
incompatible with this system
+        */
+       private static final boolean tryLoadResource(File f, URL resource)
+               throws FileNotFoundException, UnsatisfiedLinkError {
+               InputStream is;
+               try {
+                       is = resource.openStream();
+               } catch(IOException e) {
+                       f.delete();
+                       throw new FileNotFoundException();
+               }
+
+               FileOutputStream fos = null;
+               try {
+                       f.deleteOnExit();
+                       fos = new FileOutputStream(f);
+                       byte[] buf = new byte[4096 * 1024];
+                       int read;
+                       while((read = is.read(buf)) > 0) {
+                               fos.write(buf, 0, read);
+                       }
+                       fos.close();
+                       fos = null;
+                       System.load(f.getAbsolutePath());
+                       return true;
+               } catch(IOException e) {
+               } catch(UnsatisfiedLinkError ule) {
+                       // likely to be "noexec" 
+                       if(ule.toString().toLowerCase().indexOf("not 
permitted") == -1)
+                               throw ule;
+               } finally {
+                       Closer.close(fos);
+                       f.delete();
+               }
+
+               return false;
+       }
+
+       /**
+        * <p>Check all of the jars in the classpath for the file specified by 
the 
+        * environmental property "jbigi.impl" and load it as the native 
library 
+        * implementation.  For instance, a windows user on a p4 would define
+        * -Djbigi.impl=win-686 if there is a jbigi.jar in the classpath 
containing the 
+        * files "win-686", "win-athlon", "freebsd-p4", "linux-p3", where each 
+        * of those files contain the correct binary file for a native library 
(e.g.
+        * windows DLL, or a *nix .so).  </p>
+        * 
+        * <p>This is a pretty ugly hack, using the general technique 
illustrated by the
+        * onion FEC libraries.  It works by pulling the resource, writing out 
the 
+        * byte stream to a temporary file, loading the native library from 
that file,
+        * then deleting the file.</p>
+        *
+        * @return true if it was loaded successfully, else false
+        *
+        */
+       private static final boolean loadFromResource(boolean optimized) {
+               String resourceName = getResourceName(optimized);
+               if(resourceName == null)
+                       return false;
+               URL resource = 
NativeBigInteger.class.getClassLoader().getResource(resourceName);
+               if(resource == null) {
+                       if(_doLog)
+                               System.err.println("NOTICE: Resource name [" + 
getResourceName(true) + "] was not found");
+                       return false;
+               }
+               File temp = null;
+               try {
+                       try {
+                               temp = File.createTempFile("jbigi", "lib.tmp");
+                               if(tryLoadResource(temp, resource))
+                                       return true;
+                       } catch(IOException e) {
+                       } finally {
+                               if(temp != null) temp.delete();
+                       }
+                       Logger.error(NativeBigInteger.class, "Can't load from " 
+ System.getProperty("java.io.tmpdir"));
+                       System.err.println("Can't load from " + 
System.getProperty("java.io.tmpdir"));
+                       temp = new File("jbigi-lib.tmp");
+                       if(tryLoadResource(temp, resource))
+                               return true;
+               } catch(Exception fnf) {
+                       Logger.error(NativeBigInteger.class, "Error reading 
jbigi resource", fnf);
+                       System.err.println("Error reading jbigi resource");
+               } catch(UnsatisfiedLinkError ule) {
+                       Logger.error(NativeBigInteger.class, "Library " + 
resourceName + " is not appropriate for this system.");
+                       System.err.println("Library " + resourceName + " is not 
appropriate for this system.");
+               } finally {
+                       if(temp != null) temp.delete();
+               }
+
+               return false;
+       }
+
+       private static final String getResourceName(boolean optimized) {
+               String pname = 
NativeBigInteger.class.getPackage().getName().replace('.', '/');
+               String pref = getLibraryPrefix();
+               String middle = getMiddleName(optimized);
+               String suff = getLibrarySuffix();
+               if((pref == null) || (middle == null) || (suff == null))
+                       return null;
+               return pname + '/' + pref + middle + '.' + suff;
+       }
+
+       private static final String getMiddleName(boolean optimized) {
+
+               String sAppend;
+               if(optimized)
+                       if(sCPUType == null)
+                               return null;
+                       else
+                               sAppend = '-' + sCPUType;
+               else
+                       sAppend = "-none";
+
+               boolean isWindows = 
(System.getProperty("os.name").toLowerCase().indexOf("windows") != -1);
+               boolean isLinux = 
(System.getProperty("os.name").toLowerCase().indexOf("linux") != -1);
+               boolean isFreebsd = 
(System.getProperty("os.name").toLowerCase().indexOf("freebsd") != -1);
+               boolean isMacOS = 
(System.getProperty("os.name").toLowerCase().indexOf("mac os x") != -1);
+               if(isWindows)
+                       return "jbigi-windows" + sAppend; // The convention on 
Windows
+               if(isLinux)
+                       return "jbigi-linux" + sAppend; // The convention on 
linux...
+               if(isFreebsd)
+                       return "jbigi-freebsd" + sAppend; // The convention on 
freebsd...
+               if(isMacOS)
+                       return "jbigi-osx" + sAppend; // The convention on Mac 
OS X...
+               throw new RuntimeException("Dont know jbigi library name for os 
type '" + System.getProperty("os.name") + '\'');
+       }
+
+       private static final String getLibrarySuffix() {
+               boolean isWindows = 
System.getProperty("os.name").toLowerCase().indexOf("windows") != -1;
+               boolean isMacOS = 
(System.getProperty("os.name").toLowerCase().indexOf("mac os x") != -1);
+               if(isWindows)
+                       return "dll";
+               else if(isMacOS)
+                       return "jnilib";
+               else
+                       return "so";
+       }
+
+       private static final String getLibraryPrefix() {
+               boolean isWindows = 
System.getProperty("os.name").toLowerCase().indexOf("windows") != -1;
+               if(isWindows)
+                       return "";
+               else
+                       return "lib";
+       }
+}

Modified: trunk/freenet/test/freenet/support/MultiValueTableTest.java
===================================================================
--- trunk/freenet/test/freenet/support/MultiValueTableTest.java 2008-11-06 
13:50:42 UTC (rev 23350)
+++ trunk/freenet/test/freenet/support/MultiValueTableTest.java 2008-11-06 
13:53:57 UTC (rev 23351)
@@ -77,7 +77,7 @@
         * @param isRandom true if the maxValueNumber is an upper bound, false 
if it is the actual value
         * @return the sample MultiValueTable created
         */
-       private MultiValueTable createSampleMultiValueTable(int keyNumber, int 
maxValueNumber, boolean isRandom) {
+       private MultiValueTable<Object, Object> createSampleMultiValueTable(int 
keyNumber, int maxValueNumber, boolean isRandom) {
                Object[][] sampleObjects = 
createSampleKeyMultiVal(keyNumber,maxValueNumber,isRandom);
                return fillMultiValueTable(sampleObjects);
        }
@@ -87,7 +87,7 @@
         * @param anEnumeration
         * @return the number of present objects
         */
-       private int enumerationSize(Enumeration anEnumeration) {
+       private int enumerationSize(Enumeration<Object> anEnumeration) {
                int counter = 0;
                while(anEnumeration.hasMoreElements()) {
                        anEnumeration.nextElement();
@@ -102,11 +102,12 @@
         * @param sampleObjects Object[][] array, with [i][0] as key and [i][1] 
as list of values
         * @return the created MultiValueTable
         */
-       private MultiValueTable fillMultiValueTable(Object[][] sampleObjects) {
-               MultiValueTable methodMVTable = new MultiValueTable();
-               Iterator itr;
+       @SuppressWarnings("unchecked")
+    private MultiValueTable<Object, Object> fillMultiValueTable(Object[][] 
sampleObjects) {
+               MultiValueTable<Object, Object> methodMVTable = new 
MultiValueTable<Object, Object>();
+               Iterator<Object> itr;
                for(int i=0;i<sampleKeyNumber;i++) {
-                       itr = ((List)(sampleObjects[i][1])).iterator();
+                       itr = ((List<Object>)(sampleObjects[i][1])).iterator();
                        while( itr.hasNext())
                                methodMVTable.put(sampleObjects[i][0], 
itr.next());
                }
@@ -127,14 +128,15 @@
         * Tests get(Object) method with both
         * present keys and not present
         */
-       public void testGet() {
-               MultiValueTable methodMVTable = new MultiValueTable();
+       @SuppressWarnings("unchecked")
+    public void testGet() {
+               MultiValueTable<Object, Object> methodMVTable = new 
MultiValueTable<Object, Object>();
                assertNull(methodMVTable.get(new Object()));
                Object[][] sampleObjects = 
                        
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
                methodMVTable = fillMultiValueTable(sampleObjects);
                for(int i=0;i<sampleObjects.length;i++)
-                       
assertEquals(methodMVTable.get(sampleObjects[i][0]),((List)sampleObjects[i][1]).get(0));
+                       
assertEquals(methodMVTable.get(sampleObjects[i][0]),((List<Object>)sampleObjects[i][1]).get(0));
        }

        /**
@@ -144,7 +146,7 @@
         * MultiValueTable and not present keys, too.
         */
        public void testContainsKey() {
-               MultiValueTable methodMVTable = new MultiValueTable();
+               MultiValueTable<Object, Object> methodMVTable = new 
MultiValueTable<Object, Object>();
                assertFalse(methodMVTable.containsKey(new Object()));
                Object[][] sampleObjects = 
                        
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
@@ -161,15 +163,16 @@
         * It verifies the correct behavior with empty
         * MultiValueTable and not present Elements, too.
         */
-       public void testContainsElement() {
-               MultiValueTable methodMVTable = new MultiValueTable();
+       @SuppressWarnings("unchecked")
+    public void testContainsElement() {
+               MultiValueTable<Object, Object> methodMVTable = new 
MultiValueTable<Object, Object>();
                assertFalse(methodMVTable.containsElement(new Object(),new 
Object()));
                Object[][] sampleObjects = 
                        
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
                methodMVTable = fillMultiValueTable(sampleObjects);
-               Iterator iter;
+               Iterator<Object> iter;
                for(int i=0;i<sampleObjects.length;i++) {
-                       iter = ((List)(sampleObjects[i][1])).iterator();
+                       iter = ((List<Object>)(sampleObjects[i][1])).iterator();
                        
assertFalse(methodMVTable.containsElement(sampleObjects[i][0],new Object()));
                        while(iter.hasNext())
                                
assertTrue(methodMVTable.containsElement(sampleObjects[i][0],iter.next()));
@@ -179,17 +182,18 @@
        /**
         * Tests getAll() method
         */
-       public void testGetAll() {
-               MultiValueTable methodMVTable = new MultiValueTable();
+       @SuppressWarnings("unchecked")
+    public void testGetAll() {
+               MultiValueTable<Object, Object> methodMVTable = new 
MultiValueTable<Object, Object>();
                //TODO: verifies if an Exception is necessary
                methodMVTable.getAll(new Object());
                Object[][] sampleObjects = 
                        
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
                methodMVTable = fillMultiValueTable(sampleObjects);
-               Iterator iter;
-               Enumeration methodEnumeration;
+               Iterator<Object> iter;
+               Enumeration<Object> methodEnumeration;
                for(int i=0;i<sampleObjects.length;i++) {
-                       iter = ((List)(sampleObjects[i][1])).iterator();
+                       iter = ((List<Object>)(sampleObjects[i][1])).iterator();
                        methodEnumeration = 
methodMVTable.getAll(sampleObjects[i][0]);
                        while(iter.hasNext())
                                
assertEquals(methodEnumeration.nextElement(),iter.next());
@@ -199,42 +203,45 @@
        /**
         * Tests countAll() method
         */
-       public void testCountAll() {
-               MultiValueTable methodMVTable = new MultiValueTable();
+       @SuppressWarnings("unchecked")
+    public void testCountAll() {
+               MultiValueTable<Object, Object> methodMVTable = new 
MultiValueTable<Object, Object>();
                assertEquals(methodMVTable.countAll(new Object()),0);
                Object[][] sampleObjects = 
                        
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
                methodMVTable = fillMultiValueTable(sampleObjects);
                for(int i=0;i<sampleObjects.length;i++)
-                       
assertEquals(((List)(sampleObjects[i][1])).size(),methodMVTable.countAll(sampleObjects[i][0]));
+                       
assertEquals(((List<Object>)(sampleObjects[i][1])).size(),methodMVTable.countAll(sampleObjects[i][0]));
        }

        /**
         * Tests getSync(Object) method fetching
         * both present and not present keys
         */
-       public void testGetSync() {
-               MultiValueTable methodMVTable = new MultiValueTable();
+       @SuppressWarnings({ "cast", "unchecked" })
+    public void testGetSync() {
+               MultiValueTable<Object, Object> methodMVTable = new 
MultiValueTable<Object, Object>();
                assertNull(methodMVTable.getSync(new Object()));
                Object[][] sampleObjects = 
                        
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
                methodMVTable = fillMultiValueTable(sampleObjects);
                for(int i=0;i<sampleObjects.length;i++)
-                       
assertEquals(methodMVTable.getSync(sampleObjects[i][0]),((List)sampleObjects[i][1]));
+                       
assertEquals(methodMVTable.getSync(sampleObjects[i][0]),((List<Object>)sampleObjects[i][1]));
        }

        /**
         * Tests getArray(Object) method both
         * with a present key and a not present key
         */
-       public void testGetArray() {
-               MultiValueTable methodMVTable = new MultiValueTable();
+       @SuppressWarnings("unchecked")
+    public void testGetArray() {
+               MultiValueTable<Object, Object> methodMVTable = new 
MultiValueTable<Object, Object>();
                assertNull(methodMVTable.getArray(new Object()));
                Object[][] sampleObjects = 
                        
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
                methodMVTable = fillMultiValueTable(sampleObjects);
                for(int i=0;i<sampleObjects.length;i++)
-                       
assertTrue(Arrays.equals(((List)(sampleObjects[i][1])).toArray(),methodMVTable.getArray(sampleObjects[i][0])));
+                       
assertTrue(Arrays.equals(((List<Object>)(sampleObjects[i][1])).toArray(),methodMVTable.getArray(sampleObjects[i][0])));
        }

        /**
@@ -244,7 +251,7 @@
         * key, too.
         */
        public void testRemove() {
-               MultiValueTable methodMVTable = new MultiValueTable();
+               MultiValueTable<Object, Object> methodMVTable = new 
MultiValueTable<Object, Object>();
                //TODO: shouldn't it raise an exception?
                methodMVTable.remove(new Object());
                Object[][] sampleObjects = 
@@ -260,7 +267,7 @@
         * after putting objects and after removing all of them.
         */
        public void testIsEmpty() {
-               MultiValueTable methodMVTable = new MultiValueTable();
+               MultiValueTable<Object, Object> methodMVTable = new 
MultiValueTable<Object, Object>();
                assertTrue(methodMVTable.isEmpty());
                Object[][] sampleObjects = 
                        
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
@@ -279,7 +286,7 @@
        public void testClear() {
                Object[][] sampleObjects = 
                        
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
-               MultiValueTable methodMVTable = 
fillMultiValueTable(sampleObjects);
+               MultiValueTable<Object, Object> methodMVTable = 
fillMultiValueTable(sampleObjects);
                methodMVTable.clear();
                for(int i=0;i<sampleObjects.length;i++)
                        
assertFalse(methodMVTable.containsKey(sampleObjects[i][0]));
@@ -291,14 +298,15 @@
         * a sample MultiValueTable, and verifying if they are correctly
         * removed and if the result of isEmpty() method is correct.
         */
-       public void testRemoveElement() {
+       @SuppressWarnings("unchecked")
+    public void testRemoveElement() {
                Object[][] sampleObjects = 
                        
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
-               MultiValueTable methodMVTable = 
fillMultiValueTable(sampleObjects);
+               MultiValueTable<Object, Object> methodMVTable = 
fillMultiValueTable(sampleObjects);
                Object methodValue;
-               Iterator iter;
+               Iterator<Object> iter;
                for(int i=0;i<sampleObjects.length;i++) {
-                       iter = ((List)(sampleObjects[i][1])).iterator();
+                       iter = ((List<Object>)(sampleObjects[i][1])).iterator();
                        
assertFalse(methodMVTable.removeElement(sampleObjects[i][0],new Object()));
                        while(iter.hasNext()) {
                                methodValue = iter.next();
@@ -316,10 +324,10 @@
        public void testKeys() {
                Object[][] sampleObjects = 
                        
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
-               MultiValueTable methodMVTable = 
fillMultiValueTable(sampleObjects);
+               MultiValueTable<Object, Object> methodMVTable = 
fillMultiValueTable(sampleObjects);
                //TODO: shouldn't it respect keys order?
                int j = sampleObjects.length-1;
-               Enumeration methodEnumeration = methodMVTable.keys();
+               Enumeration<Object> methodEnumeration = methodMVTable.keys();
                while(methodEnumeration.hasMoreElements()) {
                        
assertEquals(sampleObjects[j][0],methodEnumeration.nextElement());
                        j--;}
@@ -332,7 +340,7 @@
         */
        public void testDifferentKeysSameElement() {
                int keysNumber = 2;
-               MultiValueTable methodMVTable = new MultiValueTable();
+               MultiValueTable<Object, Object> methodMVTable = new 
MultiValueTable<Object, Object>();
                String sampleValue = "sampleValue";
                //putting the same value for different keys
                for(int i=0;i<keysNumber;i++)

Copied: trunk/freenet/test/freenet/support/compress/Bzip2CompressorTest.java 
(from rev 23341, 
trunk/freenet/test/freenet/support/compress/Bzip2CompressorTest.java)
===================================================================
--- trunk/freenet/test/freenet/support/compress/Bzip2CompressorTest.java        
                        (rev 0)
+++ trunk/freenet/test/freenet/support/compress/Bzip2CompressorTest.java        
2008-11-06 13:53:57 UTC (rev 23351)
@@ -0,0 +1,200 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+* Public License, version 2 (or at your option any later version). See
+* http://www.gnu.org/ for further details of the GPL. */
+package freenet.support.compress;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import junit.framework.TestCase;
+import freenet.support.api.Bucket;
+import freenet.support.api.BucketFactory;
+import freenet.support.io.ArrayBucket;
+import freenet.support.io.ArrayBucketFactory;
+
+/**
+ * Test case for {@link freenet.support.compress.Bzip2Compressor} class.
+ */
+public class Bzip2CompressorTest extends TestCase {
+
+       private static final String UNCOMPRESSED_DATA_1 = 
GzipCompressorTest.UNCOMPRESSED_DATA_1;
+
+       private static final byte[] COMPRESSED_DATA_1 = { 
+               104,57,49,65,89,38,83,89,-18,-87,-99,-74,0,0,33,-39,-128,0,8,16,
+               0,58,64,52,-7,-86,0,48,0,-69,65,76,38,-102,3,76,65,-92,-12,-43,
+               61,71,-88,-51,35,76,37,52,32,19,-44,67,74,-46,-9,17,14,-35,55,
+               100,-10,73,-75,121,-34,83,56,-125,15,32,-118,35,66,124,-120,-39,
+               119,-104,-108,66,101,-56,94,-71,-41,-43,68,51,65,19,-44,-118,4,
+               -36,-117,33,-101,-120,-49,-10,17,-51,-19,28,76,-57,-112,-68,-50,
+               -66,-60,-43,-81,127,-51,-10,58,-92,38,18,45,102,117,-31,-116,
+               -114,-6,-87,-59,-43,-106,41,-30,-63,-34,-39,-117,-104,-114,100,
+               -115,36,-112,23,104,-110,71,-45,-116,-23,-85,-36,-24,-61,14,32,
+               105,55,-105,-31,-4,93,-55,20,-31,66,67,-70,-90,118,-40
+       };
+
+       /**
+        * test BZIP2 compressor's identity and functionality
+        */
+       public void testBzip2Compressor() {
+               Compressor.COMPRESSOR_TYPE bz2compressor = 
Compressor.COMPRESSOR_TYPE.BZIP2;
+               Compressor compressorZero = 
Compressor.COMPRESSOR_TYPE.getCompressorByMetadataID((short)1);
+
+               // check BZIP2 is the second compressor
+               assertEquals(bz2compressor, compressorZero);
+       }
+
+       public void testCompress() {
+
+               // do bzip2 compression
+               byte[] compressedData = 
doCompress(UNCOMPRESSED_DATA_1.getBytes());
+
+               // output size same as expected?
+               //assertEquals(compressedData.length, COMPRESSED_DATA_1.length);
+
+               // check each byte is exactly as expected
+               for (int i = 0; i < compressedData.length; i++) {
+                       assertEquals(COMPRESSED_DATA_1[i], compressedData[i]);
+               }
+       }
+
+       public void testBucketDecompress() {
+               
+               byte[] compressedData = COMPRESSED_DATA_1;
+               
+               // do bzip2 decompression with buckets
+               byte[] uncompressedData = doBucketDecompress(compressedData);
+               
+               // is the (round-tripped) uncompressed string the same as the 
original?
+               String uncompressedString = new String(uncompressedData);
+               assertEquals(uncompressedString, UNCOMPRESSED_DATA_1);
+       }
+
+       public void testByteArrayDecompress() {
+               
+        // build 5k array 
+               byte[] originalUncompressedData = new byte[5 * 1024];
+               for(int i = 0; i < originalUncompressedData.length; i++) {
+                       originalUncompressedData[i] = 1;
+               }
+               
+               byte[] compressedData = doCompress(originalUncompressedData);
+               byte[] outUncompressedData = new byte[5 * 1024];
+               
+               int writtenBytes = 0;
+               
+               try {
+                       writtenBytes = 
Compressor.COMPRESSOR_TYPE.BZIP2.decompress(compressedData, 0, 
compressedData.length, outUncompressedData);
+               } catch (CompressionOutputSizeException e) {
+                       fail("unexpected exception thrown : " + e.getMessage());
+               }
+               
+               assertEquals(writtenBytes, originalUncompressedData.length);
+               assertEquals(originalUncompressedData.length, 
outUncompressedData.length);
+               
+        // check each byte is exactly as expected
+               for (int i = 0; i < outUncompressedData.length; i++) {
+                       assertEquals(originalUncompressedData[i], 
outUncompressedData[i]);
+               }
+       }
+
+       public void testCompressException() {
+               
+               byte[] uncompressedData = UNCOMPRESSED_DATA_1.getBytes();
+               Bucket inBucket = new ArrayBucket(uncompressedData);
+               BucketFactory factory = new ArrayBucketFactory();
+
+               try {
+                       Compressor.COMPRESSOR_TYPE.BZIP2.compress(inBucket, 
factory, 32);
+               } catch (IOException e) {
+                       fail("unexpected exception thrown : " + e.getMessage());
+               } catch (CompressionOutputSizeException e) {
+                       // expect this
+               }               
+       }
+
+       public void testDecompressException() {
+               
+               // build 5k array
+               byte[] uncompressedData = new byte[5 * 1024];
+               for(int i = 0; i < uncompressedData.length; i++) {
+                       uncompressedData[i] = 1;
+               }
+               
+               byte[] compressedData = doCompress(uncompressedData);
+               
+               Bucket inBucket = new ArrayBucket(compressedData);
+               BucketFactory factory = new ArrayBucketFactory();
+
+               try {
+                       Compressor.COMPRESSOR_TYPE.BZIP2.decompress(inBucket, 
factory, 4096 + 10, 4096 + 20, null);
+               } catch (IOException e) {
+                       fail("unexpected exception thrown : " + e.getMessage());
+               } catch (CompressionOutputSizeException e) {
+                       // expect this
+               }
+       }
+       
+       private byte[] doBucketDecompress(byte[] compressedData) {
+
+               Bucket inBucket = new ArrayBucket(compressedData);
+               BucketFactory factory = new ArrayBucketFactory();
+               Bucket outBucket = null;
+
+               try {
+                       outBucket = 
Compressor.COMPRESSOR_TYPE.BZIP2.decompress(inBucket, factory, 32768, 32768 * 
2, null);
+               } catch (IOException e) {
+                       fail("unexpected exception thrown : " + e.getMessage());
+               } catch (CompressionOutputSizeException e) {
+                       fail("unexpected exception thrown : " + e.getMessage());
+               }
+
+               InputStream in = null;
+
+               try {
+                       in = outBucket.getInputStream();
+               } catch (IOException e1) {
+                       fail("unexpected exception thrown : " + 
e1.getMessage());
+               }
+               long size = outBucket.size();
+               byte[] outBuf = new byte[(int) size];
+
+               try {
+                       in.read(outBuf);
+               } catch (IOException e) {
+                       fail("unexpected exception thrown : " + e.getMessage());
+               }
+
+               return outBuf;          
+       }
+
+       private byte[] doCompress(byte[] uncompressedData) {
+               Bucket inBucket = new ArrayBucket(uncompressedData);
+               BucketFactory factory = new ArrayBucketFactory();
+               Bucket outBucket = null;
+
+               try {
+                       outBucket = 
Compressor.COMPRESSOR_TYPE.BZIP2.compress(inBucket, factory, 32768);
+               } catch (IOException e) {
+                       fail("unexpected exception thrown : " + e.getMessage());
+               } catch (CompressionOutputSizeException e) {
+                       fail("unexpected exception thrown : " + e.getMessage());
+               }
+
+               InputStream in = null;
+               try {
+                       in = outBucket.getInputStream();
+               } catch (IOException e1) {
+                       fail("unexpected exception thrown : " + 
e1.getMessage());
+               }
+               long size = outBucket.size();
+               byte[] outBuf = new byte[(int) size];
+
+               try {
+                       in.read(outBuf);
+               } catch (IOException e) {
+                       fail("unexpected exception thrown : " + e.getMessage());
+               }
+
+               return outBuf;
+       }
+}

Modified: trunk/freenet/test/freenet/support/compress/GzipCompressorTest.java
===================================================================
--- trunk/freenet/test/freenet/support/compress/GzipCompressorTest.java 
2008-11-06 13:50:42 UTC (rev 23350)
+++ trunk/freenet/test/freenet/support/compress/GzipCompressorTest.java 
2008-11-06 13:53:57 UTC (rev 23351)
@@ -32,7 +32,7 @@
  */
 public class GzipCompressorTest extends TestCase {

-       private static final String UNCOMPRESSED_DATA_1 = 
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+       public static final String UNCOMPRESSED_DATA_1 = 
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
                        + 
"aksjdhaskjsdhaskjdhaksjdhkajsdhkasdhkqhdioqahdkashdkashdnkashdnaskdhnkasjhdnkasjhdnkasjhdnkasjhdnkasjhdnkashdnkasjhdnkasjhdnkasjhndkasjhdna"
                        + 
"djjjjjjjjjjjjjjj3j12j312j312j312j31j23hj123niah1ia3h1iu2b321uiab31ugb312gba38gab23igb12i3ag1b2ig3bi1g3bi1gba3iu12ba3iug1bi3ug1b2i3gab1i2ua3";

@@ -47,8 +47,8 @@
         * test GZIP compressor's identity and functionality
         */
        public void testGzipCompressor() {
-               GzipCompressor gzipCompressor = (GzipCompressor) 
Compressor.GZIP;
-               Compressor compressorZero = 
Compressor.getCompressionAlgorithmByMetadataID((short) 0);
+               Compressor.COMPRESSOR_TYPE gzipCompressor = 
Compressor.COMPRESSOR_TYPE.GZIP;
+               Compressor compressorZero = 
Compressor.COMPRESSOR_TYPE.getCompressorByMetadataID((short)0);

                // check GZIP is the first compressor
                assertEquals(gzipCompressor, compressorZero);
@@ -94,7 +94,7 @@
                int writtenBytes = 0;

                try {
-                       writtenBytes = 
Compressor.GZIP.decompress(compressedData, 0, compressedData.length, 
outUncompressedData);
+                       writtenBytes = 
Compressor.COMPRESSOR_TYPE.GZIP.decompress(compressedData, 0, 
compressedData.length, outUncompressedData);
                } catch (CompressionOutputSizeException e) {
                        fail("unexpected exception thrown : " + e.getMessage());
                }
@@ -115,7 +115,7 @@
                BucketFactory factory = new ArrayBucketFactory();

                try {
-                       Compressor.GZIP.compress(inBucket, factory, 32);
+                       Compressor.COMPRESSOR_TYPE.GZIP.compress(inBucket, 
factory, 32);
                } catch (IOException e) {
                        fail("unexpected exception thrown : " + e.getMessage());
                } catch (CompressionOutputSizeException e) {
@@ -137,7 +137,7 @@
                BucketFactory factory = new ArrayBucketFactory();

                try {
-                       Compressor.GZIP.decompress(inBucket, factory, 4096 + 
10, 4096 + 20, null);
+                       Compressor.COMPRESSOR_TYPE.GZIP.decompress(inBucket, 
factory, 4096 + 10, 4096 + 20, null);
                } catch (IOException e) {
                        fail("unexpected exception thrown : " + e.getMessage());
                } catch (CompressionOutputSizeException e) {
@@ -152,7 +152,7 @@
                Bucket outBucket = null;

                try {
-                       outBucket = Compressor.GZIP.decompress(inBucket, 
factory, 32768, 32768 * 2, null);
+                       outBucket = 
Compressor.COMPRESSOR_TYPE.GZIP.decompress(inBucket, factory, 32768, 32768 * 2, 
null);
                } catch (IOException e) {
                        fail("unexpected exception thrown : " + e.getMessage());
                } catch (CompressionOutputSizeException e) {
@@ -184,7 +184,7 @@
                Bucket outBucket = null;

                try {
-                       outBucket = Compressor.GZIP.compress(inBucket, factory, 
32768);
+                       outBucket = 
Compressor.COMPRESSOR_TYPE.GZIP.compress(inBucket, factory, 32768);
                } catch (IOException e) {
                        fail("unexpected exception thrown : " + e.getMessage());
                } catch (CompressionOutputSizeException e) {

Copied: trunk/freenet/test/freenet/support/io/ArrayBucketTest.java (from rev 
23341, trunk/freenet/test/freenet/support/io/ArrayBucketTest.java)
===================================================================
--- trunk/freenet/test/freenet/support/io/ArrayBucketTest.java                  
        (rev 0)
+++ trunk/freenet/test/freenet/support/io/ArrayBucketTest.java  2008-11-06 
13:53:57 UTC (rev 23351)
@@ -0,0 +1,22 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.support.io;
+
+import java.io.IOException;
+
+import freenet.support.api.Bucket;
+
+public class ArrayBucketTest extends BucketTestBase {
+       public ArrayBucketFactory abf = new ArrayBucketFactory();
+
+       @Override
+       protected Bucket makeBucket(long size) throws IOException {
+               return abf.makeBucket(size);
+       }
+
+       @Override
+       protected void freeBucket(Bucket bucket) throws IOException {
+               bucket.free();
+       }
+}

Copied: trunk/freenet/test/freenet/support/io/BucketTestBase.java (from rev 
23341, trunk/freenet/test/freenet/support/io/BucketTestBase.java)
===================================================================
--- trunk/freenet/test/freenet/support/io/BucketTestBase.java                   
        (rev 0)
+++ trunk/freenet/test/freenet/support/io/BucketTestBase.java   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -0,0 +1,198 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.support.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import junit.framework.TestCase;
+import freenet.support.ByteArrayWrapper;
+import freenet.support.api.Bucket;
+
+public abstract class BucketTestBase extends TestCase {
+       protected byte[] DATA1 = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 
0x05, 0x06, 0x07, 0x08 };
+       protected byte[] DATA2 = new byte[] { 0x70, (byte) 0x81, (byte) 0x92, 
(byte) 0xa3, (byte) 0xb4, (byte) 0xc5,
+               (byte) 0xd6, (byte) 0xe7, (byte) 0xf8 };
+
+       protected abstract Bucket makeBucket(long size) throws IOException;
+
+       protected abstract void freeBucket(Bucket bucket) throws IOException;
+
+       public void testReadEmpty() throws IOException {
+               Bucket bucket = makeBucket(3);
+               try {
+                       assertEquals("Size-0", 0, bucket.size());
+                       // Read byte[]
+                       InputStream is = bucket.getInputStream();
+                       byte[] data = new byte[10];
+                       int read = is.read(data, 0, 10);
+                       is.close();
+
+                       assertEquals("Read-Empty", -1, read);
+               } finally {
+                       freeBucket(bucket);
+               }
+       }
+
+       public void testReadExcess() throws IOException {
+               Bucket bucket = makeBucket(Math.max(DATA1.length, 
DATA2.length));
+               try {
+                       assertEquals("Size-0", 0, bucket.size());
+
+                       // Write
+                       OutputStream os = bucket.getOutputStream();
+                       os.write(new byte[] { 5 });
+                       os.close();
+
+                       assertEquals("Read-Excess-Size", 1, bucket.size());
+
+                       // Read byte[]
+                       InputStream is = bucket.getInputStream();
+                       byte[] data = new byte[10];
+                       int read = is.read(data, 0, 10);
+                       assertEquals("Read-Excess", 1, read);
+                       assertEquals("Read-Excess-5", 5, data[0]);
+
+                       read = is.read(data, 0, 10);
+                       assertEquals("Read-Excess-EOF", -1, read);
+
+                       is.close();
+               } finally {
+                       freeBucket(bucket);
+               }
+       }
+
+       public void testReadWrite() throws IOException {
+               Bucket bucket = makeBucket(Math.max(DATA1.length, 
DATA2.length));
+               try {
+                       assertEquals("Size-0", 0, bucket.size());
+
+                       // Write
+                       OutputStream os = bucket.getOutputStream();
+                       os.write(DATA1);
+                       os.close();
+
+                       assertEquals("Size-1", DATA1.length, bucket.size());
+
+                       // Read byte[]
+                       InputStream is = bucket.getInputStream();
+                       byte[] data = new byte[DATA1.length];
+                       int read = is.read(data, 0, DATA1.length);
+                       is.close();
+
+                       assertEquals("SimpleRead-1-SIZE", DATA1.length, read);
+                       assertEquals("SimpleRead-1", new 
ByteArrayWrapper(DATA1), new ByteArrayWrapper(data));
+
+                       // Read byte
+                       is = bucket.getInputStream();
+                       for (byte b : DATA1)
+                               assertEquals("SimpleRead-2", b, (byte) 
is.read());
+
+                       // EOF
+                       assertEquals("SimpleRead-EOF0", -1, is.read(new 
byte[4]));
+                       assertEquals("SimpleRead-EOF1", -1, is.read());
+                       assertEquals("SimpleRead-EOF2", -1, is.read());
+
+                       is.close();
+               } finally {
+                       freeBucket(bucket);
+               }
+       }
+
+       // Write twice -- should overwrite, not append
+       public void testReuse() throws IOException {
+               Bucket bucket = makeBucket(Math.max(DATA1.length, 
DATA2.length));
+               try {
+                       // Write
+                       OutputStream os = bucket.getOutputStream();
+                       os.write(DATA1);
+                       os.close();
+
+                       // Read byte[]
+                       InputStream is = bucket.getInputStream();
+                       byte[] data = new byte[DATA1.length];
+                       int read = is.read(data, 0, DATA1.length);
+                       is.close();
+
+                       assertEquals("Read-1-SIZE", DATA1.length, read);
+                       assertEquals("Read-1", new ByteArrayWrapper(DATA1), new 
ByteArrayWrapper(data));
+
+                       // Write again
+                       os = bucket.getOutputStream();
+                       os.write(DATA2);
+                       os.close();
+
+                       // Read byte[]
+                       is = bucket.getInputStream();
+                       data = new byte[DATA2.length];
+                       read = is.read(data, 0, DATA2.length);
+                       is.close();
+
+                       assertEquals("Read-2-SIZE", DATA2.length, read);
+                       assertEquals("Read-2", new ByteArrayWrapper(DATA2), new 
ByteArrayWrapper(data));
+               } finally {
+                       freeBucket(bucket);
+               }
+       }
+
+       public void testNegative() throws IOException {
+               Bucket bucket = makeBucket(Math.max(DATA1.length, 
DATA2.length));
+               try {
+                       // Write
+                       OutputStream os = bucket.getOutputStream();
+                       os.write(0);
+                       os.write(-1);
+                       os.write(-2);
+                       os.write(123);
+                       os.close();
+
+                       // Read byte[]
+                       InputStream is = bucket.getInputStream();
+                       assertEquals("Write-0", 0xff & (byte) 0, is.read());
+                       assertEquals("Write-1", 0xff & (byte) -1, is.read());
+                       assertEquals("Write-2", 0xff & (byte) -2, is.read());
+                       assertEquals("Write-123", 0xff & (byte) 123, is.read());
+                       assertEquals("EOF", -1, is.read());
+                       is.close();
+               } finally {
+                       freeBucket(bucket);
+               }
+       }
+
+       protected static byte[] DATA_LONG;
+       static {
+               DATA_LONG = new byte[32768 + 1]; // 32K + 1
+               for (int i = 0; i < DATA_LONG.length; i++)
+                       DATA_LONG[i] = (byte) i;
+       }
+
+       public void testLargeData() throws IOException {
+
+               Bucket bucket = makeBucket(DATA_LONG.length * 16);
+               try {
+                       // Write
+                       OutputStream os = bucket.getOutputStream();
+                       for (int i = 0; i < 16; i++)
+                               os.write(DATA_LONG);
+                       os.close();
+
+                       // Read byte[]
+                       InputStream is = bucket.getInputStream();
+                       for (int i = 0; i < 16; i++) {
+                               byte[] buf = new byte[DATA_LONG.length];
+                               int read = is.read(buf);
+                               assertEquals("Read-Long-Size", 
DATA_LONG.length, read);
+                               assertEquals("Read-Long", new 
ByteArrayWrapper(DATA_LONG), new ByteArrayWrapper(buf));
+                       }
+
+                       int read = is.read(new byte[1]);
+                       assertEquals("Read-Long-Size", -1, read);
+
+                       is.close();
+               } finally {
+                       freeBucket(bucket);
+               }
+       }
+}

Copied: 
trunk/freenet/test/freenet/support/io/PaddedEphemerallyEncryptedBucketTest.java 
(from rev 23341, 
trunk/freenet/test/freenet/support/io/PaddedEphemerallyEncryptedBucketTest.java)
===================================================================
--- 
trunk/freenet/test/freenet/support/io/PaddedEphemerallyEncryptedBucketTest.java 
                            (rev 0)
+++ 
trunk/freenet/test/freenet/support/io/PaddedEphemerallyEncryptedBucketTest.java 
    2008-11-06 13:53:57 UTC (rev 23351)
@@ -0,0 +1,30 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.support.io;
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.spaceroots.mantissa.random.MersenneTwister;
+
+import freenet.crypt.RandomSource;
+import freenet.crypt.Yarrow;
+import freenet.support.api.Bucket;
+
+public class PaddedEphemerallyEncryptedBucketTest extends BucketTestBase {
+       private RandomSource strongPRNG = new Yarrow();
+       private Random weakPRNG = new MersenneTwister();
+
+       @Override
+       protected Bucket makeBucket(long size) throws IOException {
+               FilenameGenerator filenameGenerator = new 
FilenameGenerator(weakPRNG, false, null, "junit");
+               TempFileBucket fileBucket = new 
TempFileBucket(filenameGenerator.makeRandomFilename(), filenameGenerator);
+               return new PaddedEphemerallyEncryptedBucket(fileBucket, 1024, 
strongPRNG, weakPRNG);
+       }
+
+       @Override
+       protected void freeBucket(Bucket bucket) throws IOException {
+               bucket.free();
+       }
+}
\ No newline at end of file

Copied: trunk/freenet/test/freenet/support/io/TempFileBucketTest.java (from rev 
23341, trunk/freenet/test/freenet/support/io/TempFileBucketTest.java)
===================================================================
--- trunk/freenet/test/freenet/support/io/TempFileBucketTest.java               
                (rev 0)
+++ trunk/freenet/test/freenet/support/io/TempFileBucketTest.java       
2008-11-06 13:53:57 UTC (rev 23351)
@@ -0,0 +1,37 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.support.io;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Random;
+
+import org.spaceroots.mantissa.random.MersenneTwister;
+
+import freenet.support.api.Bucket;
+
+public class TempFileBucketTest extends BucketTestBase {
+       private Random weakPRNG = new MersenneTwister();
+
+       @Override
+       protected Bucket makeBucket(long size) throws IOException {
+               FilenameGenerator filenameGenerator = new 
FilenameGenerator(weakPRNG, false, null, "junit");
+               BaseFileBucket bfb = new 
TempFileBucket(filenameGenerator.makeRandomFilename(), filenameGenerator);
+
+               assertTrue("deleteOnExit", bfb.deleteOnExit());
+               assertTrue("deleteOnFree", bfb.deleteOnFree());
+               assertTrue("deleteOnFinalize", bfb.deleteOnFinalize());
+
+               return bfb;
+       }
+
+       @Override
+       protected void freeBucket(Bucket bucket) throws IOException {
+               File file = ((BaseFileBucket) bucket).getFile();
+               if (bucket.size() != 0)
+                       assertTrue("TempFile not exist", file.exists());
+               bucket.free();
+               assertFalse("TempFile not deleted", file.exists());
+       }
+}

Copied: trunk/freenet/test/net (from rev 23341, trunk/freenet/test/net)

Copied: trunk/freenet/test/net/i2p (from rev 23341, trunk/freenet/test/net/i2p)

Copied: trunk/freenet/test/net/i2p/util (from rev 23341, 
trunk/freenet/test/net/i2p/util)

Deleted: trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java
===================================================================
--- trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java   2008-11-06 
08:45:15 UTC (rev 23341)
+++ trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -1,114 +0,0 @@
-package net.i2p.util;
-
-import java.math.BigInteger;
-import java.security.SecureRandom;
-
-import junit.framework.TestCase;
-
-public class NativeBigIntegerTest extends TestCase {
-       // Run with <code>ant -Dbenchmark=true</code> to do benchmark 
-       private static final boolean BENCHMARK = 
Boolean.getBoolean("benchmark");
-       private static int numRuns = BENCHMARK ? 200 : 5;
-
-       /*
-        * the sample numbers are elG generator/prime so we can test with 
reasonable
-        * numbers
-        */
-       private final static byte[] _sampleGenerator = new 
BigInteger("2").toByteArray();
-       private final static byte[] _samplePrime = new 
BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
-               + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + 
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
-               + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + 
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
-               + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + 
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
-               + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + 
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
-               + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + 
"15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
-               .toByteArray();
-
-       private SecureRandom rand;
-       private int runsProcessed;
-
-       private BigInteger jg;
-       private BigInteger jp;
-
-       private long totalTime = 0;
-       private long javaTime = 0;
-
-       protected void setUp() throws Exception {
-               if (!NativeBigInteger.isNative())
-                       printError("can't load native code");
-
-               printInfo("DEBUG: Warming up the random number generator...");
-               rand = new SecureRandom();
-               rand.nextBoolean();
-               printInfo("DEBUG: Random number generator warmed up");
-
-               jg = new BigInteger(_sampleGenerator);
-               jp = new BigInteger(_samplePrime);
-
-               totalTime = javaTime = 0;
-       }
-
-       protected void tearDown() throws Exception {
-               printInfo("INFO: run time: " + totalTime + "ms (" + (totalTime 
/ (runsProcessed + 1)) + "ms each)");
-               if (numRuns == runsProcessed)
-                       printInfo("INFO: " + runsProcessed + " runs complete 
without any errors");
-               else
-                       printError("ERROR: " + runsProcessed + " runs until we 
got an error");
-
-               printInfo("native run time: \t" + totalTime + "ms (" + 
(totalTime / (runsProcessed + 1)) + "ms each)");
-               printInfo("java run time:   \t" + javaTime + "ms (" + (javaTime 
/ (runsProcessed + 1)) + "ms each)");
-               printInfo("native = " + ((totalTime * 100.0d) / (double) 
javaTime) + "% of pure java time");
-       }
-
-       public void testModPow() {
-               for (runsProcessed = 0; runsProcessed < numRuns; 
runsProcessed++) {
-                       BigInteger bi = new BigInteger(2048, rand);
-                       NativeBigInteger g = new 
NativeBigInteger(_sampleGenerator);
-                       NativeBigInteger p = new NativeBigInteger(_samplePrime);
-                       NativeBigInteger k = new NativeBigInteger(1, 
bi.toByteArray());
-
-                       long beforeModPow = System.currentTimeMillis();
-                       BigInteger myValue = g.modPow(k, p);
-                       long afterModPow = System.currentTimeMillis();
-                       BigInteger jval = jg.modPow(bi, jp);
-                       long afterJavaModPow = System.currentTimeMillis();
-
-                       totalTime += (afterModPow - beforeModPow);
-                       javaTime += (afterJavaModPow - afterModPow);
-
-                       assertEquals(jval, myValue);
-               }
-       }
-
-       public void testDoubleValue() {
-               BigInteger jg = new BigInteger(_sampleGenerator);
-
-               int MULTIPLICATOR = 50000; //Run the doubleValue() calls within 
a loop since they are pretty fast.. 
-               for (runsProcessed = 0; runsProcessed < numRuns; 
runsProcessed++) {
-                       NativeBigInteger g = new 
NativeBigInteger(_sampleGenerator);
-                       long beforeDoubleValue = System.currentTimeMillis();
-                       double dNative = 0;
-                       for (int mult = 0; mult < MULTIPLICATOR; mult++)
-                               dNative = g.doubleValue();
-                       long afterDoubleValue = System.currentTimeMillis();
-                       double jval = 0;
-                       for (int mult = 0; mult < MULTIPLICATOR; mult++)
-                               jval = jg.doubleValue();
-                       long afterJavaDoubleValue = System.currentTimeMillis();
-
-                       totalTime += (afterDoubleValue - beforeDoubleValue);
-                       javaTime += (afterJavaDoubleValue - afterDoubleValue);
-
-                       assertEquals(jval, dNative, 0);
-               }
-       }
-
-       private static void printInfo(String info) {
-               if (BENCHMARK)
-                       System.out.println(info);
-       }
-
-       private static void printError(String info) {
-               if (BENCHMARK)
-                       System.err.println(info);
-       }
-}

Copied: trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java (from rev 
23341, trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java)
===================================================================
--- trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java                   
        (rev 0)
+++ trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java   2008-11-06 
13:53:57 UTC (rev 23351)
@@ -0,0 +1,114 @@
+package net.i2p.util;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+
+public class NativeBigIntegerTest extends TestCase {
+       // Run with <code>ant -Dbenchmark=true</code> to do benchmark 
+       private static final boolean BENCHMARK = 
Boolean.getBoolean("benchmark");
+       private static int numRuns = BENCHMARK ? 200 : 5;
+
+       /*
+        * the sample numbers are elG generator/prime so we can test with 
reasonable
+        * numbers
+        */
+       private final static byte[] _sampleGenerator = new 
BigInteger("2").toByteArray();
+       private final static byte[] _samplePrime = new 
BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+               + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + 
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+               + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + 
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+               + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + 
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+               + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + 
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+               + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + 
"15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
+               .toByteArray();
+
+       private SecureRandom rand;
+       private int runsProcessed;
+
+       private BigInteger jg;
+       private BigInteger jp;
+
+       private long totalTime = 0;
+       private long javaTime = 0;
+
+       protected void setUp() throws Exception {
+               if (!NativeBigInteger.isNative())
+                       printError("can't load native code");
+
+               printInfo("DEBUG: Warming up the random number generator...");
+               rand = new SecureRandom();
+               rand.nextBoolean();
+               printInfo("DEBUG: Random number generator warmed up");
+
+               jg = new BigInteger(_sampleGenerator);
+               jp = new BigInteger(_samplePrime);
+
+               totalTime = javaTime = 0;
+       }
+
+       protected void tearDown() throws Exception {
+               printInfo("INFO: run time: " + totalTime + "ms (" + (totalTime 
/ (runsProcessed + 1)) + "ms each)");
+               if (numRuns == runsProcessed)
+                       printInfo("INFO: " + runsProcessed + " runs complete 
without any errors");
+               else
+                       printError("ERROR: " + runsProcessed + " runs until we 
got an error");
+
+               printInfo("native run time: \t" + totalTime + "ms (" + 
(totalTime / (runsProcessed + 1)) + "ms each)");
+               printInfo("java run time:   \t" + javaTime + "ms (" + (javaTime 
/ (runsProcessed + 1)) + "ms each)");
+               printInfo("native = " + ((totalTime * 100.0d) / (double) 
javaTime) + "% of pure java time");
+       }
+
+       public void testModPow() {
+               for (runsProcessed = 0; runsProcessed < numRuns; 
runsProcessed++) {
+                       BigInteger bi = new BigInteger(2048, rand);
+                       NativeBigInteger g = new 
NativeBigInteger(_sampleGenerator);
+                       NativeBigInteger p = new NativeBigInteger(_samplePrime);
+                       NativeBigInteger k = new NativeBigInteger(1, 
bi.toByteArray());
+
+                       long beforeModPow = System.currentTimeMillis();
+                       BigInteger myValue = g.modPow(k, p);
+                       long afterModPow = System.currentTimeMillis();
+                       BigInteger jval = jg.modPow(bi, jp);
+                       long afterJavaModPow = System.currentTimeMillis();
+
+                       totalTime += (afterModPow - beforeModPow);
+                       javaTime += (afterJavaModPow - afterModPow);
+
+                       assertEquals(jval, myValue);
+               }
+       }
+
+       public void testDoubleValue() {
+               BigInteger jg = new BigInteger(_sampleGenerator);
+
+               int MULTIPLICATOR = 50000; //Run the doubleValue() calls within 
a loop since they are pretty fast.. 
+               for (runsProcessed = 0; runsProcessed < numRuns; 
runsProcessed++) {
+                       NativeBigInteger g = new 
NativeBigInteger(_sampleGenerator);
+                       long beforeDoubleValue = System.currentTimeMillis();
+                       double dNative = 0;
+                       for (int mult = 0; mult < MULTIPLICATOR; mult++)
+                               dNative = g.doubleValue();
+                       long afterDoubleValue = System.currentTimeMillis();
+                       double jval = 0;
+                       for (int mult = 0; mult < MULTIPLICATOR; mult++)
+                               jval = jg.doubleValue();
+                       long afterJavaDoubleValue = System.currentTimeMillis();
+
+                       totalTime += (afterDoubleValue - beforeDoubleValue);
+                       javaTime += (afterJavaDoubleValue - afterDoubleValue);
+
+                       assertEquals(jval, dNative, 0);
+               }
+       }
+
+       private static void printInfo(String info) {
+               if (BENCHMARK)
+                       System.out.println(info);
+       }
+
+       private static void printError(String info) {
+               if (BENCHMARK)
+                       System.err.println(info);
+       }
+}


Reply via email to