Author: toad
Date: 2008-09-24 20:42:20 +0000 (Wed, 24 Sep 2008)
New Revision: 22823

Added:
   branches/db4o/freenet/src/freenet/config/ConfigException.java
   branches/db4o/freenet/src/freenet/config/NodeNeedRestartException.java
   branches/db4o/freenet/src/freenet/node/simulator/BootstrapPullTest.java
   branches/db4o/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java
   branches/db4o/freenet/src/freenet/node/simulator/BootstrapSeedTest.java
   
branches/db4o/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java
   branches/db4o/freenet/test/freenet/crypt/YarrowTest.java
   branches/db4o/freenet/test/freenet/support/io/
   branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java
Removed:
   branches/db4o/freenet/src/freenet/client/TempStoreElement.java
   branches/db4o/freenet/src/freenet/clients/http/PluginToadlet.java
   branches/db4o/freenet/src/freenet/crypt/DigestFactory.java
   branches/db4o/freenet/src/freenet/crypt/SHA1Factory.java
   branches/db4o/freenet/src/freenet/oldplugins/
   branches/db4o/freenet/src/freenet/support/StringArray.java
   
branches/db4o/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java
   
branches/db4o/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java
   branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java
Modified:
   branches/db4o/freenet/src/freenet/client/ArchiveManager.java
   branches/db4o/freenet/src/freenet/client/FECCodec.java
   branches/db4o/freenet/src/freenet/client/HighLevelSimpleClient.java
   branches/db4o/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
   branches/db4o/freenet/src/freenet/client/RealArchiveStoreItem.java
   branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
   branches/db4o/freenet/src/freenet/client/async/ClientContext.java
   branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java
   branches/db4o/freenet/src/freenet/client/async/SimpleManifestPutter.java
   branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java
   branches/db4o/freenet/src/freenet/clients/http/ConfigToadlet.java
   branches/db4o/freenet/src/freenet/clients/http/ConnectionsToadlet.java
   branches/db4o/freenet/src/freenet/clients/http/FProxyToadlet.java
   branches/db4o/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java
   branches/db4o/freenet/src/freenet/clients/http/HTTPRequestImpl.java
   branches/db4o/freenet/src/freenet/clients/http/PageMaker.java
   branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java
   branches/db4o/freenet/src/freenet/clients/http/SimpleToadletServer.java
   branches/db4o/freenet/src/freenet/clients/http/StatisticsToadlet.java
   branches/db4o/freenet/src/freenet/clients/http/SymlinkerToadlet.java
   branches/db4o/freenet/src/freenet/clients/http/Toadlet.java
   branches/db4o/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java
   
branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat
   
branches/db4o/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css
   branches/db4o/freenet/src/freenet/config/BooleanOption.java
   branches/db4o/freenet/src/freenet/config/Config.java
   branches/db4o/freenet/src/freenet/config/ConfigCallback.java
   branches/db4o/freenet/src/freenet/config/IntOption.java
   branches/db4o/freenet/src/freenet/config/InvalidConfigValueException.java
   branches/db4o/freenet/src/freenet/config/LongOption.java
   branches/db4o/freenet/src/freenet/config/NullBooleanCallback.java
   branches/db4o/freenet/src/freenet/config/NullIntCallback.java
   branches/db4o/freenet/src/freenet/config/NullLongCallback.java
   branches/db4o/freenet/src/freenet/config/NullShortCallback.java
   branches/db4o/freenet/src/freenet/config/NullStringCallback.java
   branches/db4o/freenet/src/freenet/config/Option.java
   branches/db4o/freenet/src/freenet/config/PersistentConfig.java
   branches/db4o/freenet/src/freenet/config/ShortOption.java
   branches/db4o/freenet/src/freenet/config/StringArrOption.java
   branches/db4o/freenet/src/freenet/config/StringOption.java
   branches/db4o/freenet/src/freenet/config/SubConfig.java
   branches/db4o/freenet/src/freenet/config/WrapperConfig.java
   branches/db4o/freenet/src/freenet/crypt/DiffieHellman.java
   branches/db4o/freenet/src/freenet/crypt/SSL.java
   branches/db4o/freenet/src/freenet/crypt/Yarrow.java
   branches/db4o/freenet/src/freenet/io/AddressIdentifier.java
   branches/db4o/freenet/src/freenet/io/NetworkInterface.java
   branches/db4o/freenet/src/freenet/io/comm/DMT.java
   branches/db4o/freenet/src/freenet/io/comm/FreenetInetAddress.java
   branches/db4o/freenet/src/freenet/io/comm/UdpSocketHandler.java
   branches/db4o/freenet/src/freenet/l10n/L10n.java
   branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties
   branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties
   branches/db4o/freenet/src/freenet/l10n/freenet.l10n.fr.properties
   branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties
   branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties
   branches/db4o/freenet/src/freenet/node/ConfigurablePersister.java
   branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java
   branches/db4o/freenet/src/freenet/node/FailureTable.java
   branches/db4o/freenet/src/freenet/node/FailureTableEntry.java
   branches/db4o/freenet/src/freenet/node/GlobalProbe.java
   branches/db4o/freenet/src/freenet/node/IPDetectorPluginManager.java
   branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java
   branches/db4o/freenet/src/freenet/node/Node.java
   branches/db4o/freenet/src/freenet/node/NodeClientCore.java
   branches/db4o/freenet/src/freenet/node/NodeCrypto.java
   branches/db4o/freenet/src/freenet/node/NodeCryptoConfig.java
   branches/db4o/freenet/src/freenet/node/NodeDispatcher.java
   branches/db4o/freenet/src/freenet/node/NodeIPDetector.java
   branches/db4o/freenet/src/freenet/node/NodeInitException.java
   branches/db4o/freenet/src/freenet/node/NodeStarter.java
   branches/db4o/freenet/src/freenet/node/NodeStats.java
   branches/db4o/freenet/src/freenet/node/PeerManager.java
   branches/db4o/freenet/src/freenet/node/PeerNode.java
   branches/db4o/freenet/src/freenet/node/PeerNodeStatus.java
   branches/db4o/freenet/src/freenet/node/SeedClientPeerNode.java
   branches/db4o/freenet/src/freenet/node/TestnetHandler.java
   branches/db4o/freenet/src/freenet/node/TextModeClientInterface.java
   branches/db4o/freenet/src/freenet/node/TextModeClientInterfaceServer.java
   branches/db4o/freenet/src/freenet/node/UptimeEstimator.java
   branches/db4o/freenet/src/freenet/node/fcp/ClientGet.java
   branches/db4o/freenet/src/freenet/node/fcp/ClientPutMessage.java
   branches/db4o/freenet/src/freenet/node/fcp/ClientRequest.java
   branches/db4o/freenet/src/freenet/node/fcp/ConfigData.java
   branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionHandler.java
   branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java
   branches/db4o/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java
   branches/db4o/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java
   
branches/db4o/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java
   branches/db4o/freenet/src/freenet/node/simulator/SeednodePingTest.java
   branches/db4o/freenet/src/freenet/node/updater/NodeUpdateManager.java
   
branches/db4o/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java
   branches/db4o/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java
   branches/db4o/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
   branches/db4o/freenet/src/freenet/pluginmanager/PluginManager.java
   branches/db4o/freenet/src/freenet/store/RAMFreenetStore.java
   branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java
   branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java
   branches/db4o/freenet/src/freenet/support/Fields.java
   branches/db4o/freenet/src/freenet/support/FileLoggerHook.java
   branches/db4o/freenet/src/freenet/support/HTMLEncoder.java
   branches/db4o/freenet/src/freenet/support/HTMLNode.java
   branches/db4o/freenet/src/freenet/support/LRUHashtable.java
   branches/db4o/freenet/src/freenet/support/OOMHandler.java
   branches/db4o/freenet/src/freenet/support/PooledExecutor.java
   branches/db4o/freenet/src/freenet/support/SimpleFieldSet.java
   branches/db4o/freenet/src/freenet/support/SizeUtil.java
   branches/db4o/freenet/src/freenet/support/SortedLongSet.java
   branches/db4o/freenet/src/freenet/support/TimeSortedHashtable.java
   branches/db4o/freenet/src/freenet/support/WeakHashSet.java
   branches/db4o/freenet/src/freenet/support/api/BooleanCallback.java
   branches/db4o/freenet/src/freenet/support/api/IntCallback.java
   branches/db4o/freenet/src/freenet/support/api/LongCallback.java
   branches/db4o/freenet/src/freenet/support/api/ShortCallback.java
   branches/db4o/freenet/src/freenet/support/api/StringArrCallback.java
   branches/db4o/freenet/src/freenet/support/api/StringCallback.java
   branches/db4o/freenet/src/freenet/support/compress/GzipCompressor.java
   branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java
   branches/db4o/freenet/src/freenet/support/io/BaseFileBucket.java
   branches/db4o/freenet/src/freenet/support/io/BucketTools.java
   branches/db4o/freenet/src/freenet/support/io/Closer.java
   branches/db4o/freenet/src/freenet/support/io/DelayedFreeBucket.java
   branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java
   branches/db4o/freenet/src/freenet/support/io/NativeThread.java
   branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
   branches/db4o/freenet/src/freenet/support/io/RandomAccessThing.java
   branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java
   branches/db4o/freenet/test/freenet/support/BufferTest.java
   branches/db4o/freenet/test/freenet/support/ByteArrayWrapperTest.java
   branches/db4o/freenet/test/freenet/support/MultiValueTableTest.java
Log:
Merge 1155 into db4o branch. All changes from 21652 to 21939.


Modified: branches/db4o/freenet/src/freenet/client/ArchiveManager.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/ArchiveManager.java        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/client/ArchiveManager.java        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -3,7 +3,6 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.client;

-import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.Arrays;
@@ -20,11 +19,8 @@
 import freenet.support.Logger;
 import freenet.support.MutableBoolean;
 import freenet.support.api.Bucket;
+import freenet.support.api.BucketFactory;
 import freenet.support.io.BucketTools;
-import freenet.support.io.FilenameGenerator;
-import freenet.support.io.PaddedEphemerallyEncryptedBucket;
-import freenet.support.io.TempFileBucket;
-import java.util.Random;

 import com.db4o.ObjectContainer;

@@ -41,9 +37,7 @@

        public static final String METADATA_NAME = ".metadata";
        private static boolean logMINOR;
-       
-       final RandomSource strongPRNG;
-       final Random weakPRNG;
+
        final long maxArchiveSize;
        final long maxArchivedFileSize;

@@ -60,8 +54,8 @@
        private long cachedData;
        /** Map from ArchiveKey to ArchiveStoreElement */
        private final LRUHashtable storedData;
-       /** Filename generator */
-       private final FilenameGenerator filenameGenerator;
+       /** Bucket Factory */
+       private final BucketFactory tempBucketFactory;

        /**
         * Create an ArchiveManager.
@@ -78,7 +72,7 @@
         * @param random A cryptographicaly secure random source
         * @param weakRandom A weak and cheap random source
         */
-       public ArchiveManager(int maxHandlers, long maxCachedData, long 
maxArchiveSize, long maxArchivedFileSize, int maxCachedElements, RandomSource 
random, Random weakRandom, FilenameGenerator filenameGenerator) {
+       public ArchiveManager(int maxHandlers, long maxCachedData, long 
maxArchiveSize, long maxArchivedFileSize, int maxCachedElements, BucketFactory 
tempBucketFactory) {
                maxArchiveHandlers = maxHandlers;
                archiveHandlers = new LRUHashtable();
                this.maxCachedElements = maxCachedElements;
@@ -86,9 +80,7 @@
                storedData = new LRUHashtable();
                this.maxArchiveSize = maxArchiveSize;
                this.maxArchivedFileSize = maxArchivedFileSize;
-               this.strongPRNG = random;
-               this.weakPRNG = weakRandom;
-               this.filenameGenerator = filenameGenerator;
+               this.tempBucketFactory = tempBucketFactory;
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
        }

@@ -253,8 +245,7 @@
                                } else {
                                        // Read the element
                                        long realLen = 0;
-                                       TempStoreElement temp = 
makeTempStoreBucket(size);
-                                       Bucket output = temp.bucket;
+                                       Bucket output = 
tempBucketFactory.makeBucket(size);
                                        OutputStream out = 
output.getOutputStream();

                                        int readBytes;
@@ -264,7 +255,7 @@
                                                if(readBytes > 
maxArchivedFileSize) {
                                                        addErrorElement(ctx, 
key, name, "File too big: "+maxArchivedFileSize+" greater than current archived 
file size limit "+maxArchivedFileSize);
                                                        out.close();
-                                                       temp.close();
+                                                       output.free();
                                                        continue outer;
                                                }
                                        }
@@ -272,7 +263,7 @@
                                        out.close();
                                        if(name.equals(".metadata"))
                                                gotMetadata = true;
-                                       addStoreElement(ctx, key, name, temp, 
gotElement, element, callback, container, context);
+                                       addStoreElement(ctx, key, name, output, 
gotElement, element, callback, container, context);
                                        names.add(name);
                                        trimStoredData();
                                }
@@ -328,18 +319,19 @@
                        addToDirectory(dir, name, "");
                }
                Metadata metadata = new Metadata(dir, "");
-               TempStoreElement element = makeTempStoreBucket(-1);
                int x = 0;
+               Bucket bucket = null;
                while(true) {
                        try {
+                               bucket = 
tempBucketFactory.makeBucket(Metadata.MAX_SPLITFILE_PARAMS_LENGTH);
                                byte[] buf = metadata.writeToByteArray();
-                               OutputStream os = 
element.bucket.getOutputStream();
+                               OutputStream os = bucket.getOutputStream();
                                os.write(buf);
                                os.close();
-                               return addStoreElement(ctx, key, ".metadata", 
element, gotElement, element2, callback, container, context);
+                               return addStoreElement(ctx, key, ".metadata", 
bucket, gotElement, element2, callback, container, context);
                        } catch (MetadataUnresolvedException e) {
                                try {
-                                       x = resolve(e, x, element, ctx, key, 
gotElement, element2, callback, container, context);
+                                       x = resolve(e, x, bucket, ctx, key, 
gotElement, element2, callback, container, context);
                                } catch (IOException e1) {
                                        throw new 
ArchiveFailureException("Failed to create metadata: "+e1, e1);
                                }
@@ -350,17 +342,17 @@
                }
        }

-       private int resolve(MetadataUnresolvedException e, int x, 
TempStoreElement element, ArchiveStoreContext ctx, FreenetURI key, 
MutableBoolean gotElement, String element2, ArchiveExtractCallback callback, 
ObjectContainer container, ClientContext context) throws IOException, 
ArchiveFailureException {
+       private int resolve(MetadataUnresolvedException e, int x, Bucket 
bucket, ArchiveStoreContext ctx, FreenetURI key, MutableBoolean gotElement, 
String element2, ArchiveExtractCallback callback, ObjectContainer container, 
ClientContext context) throws IOException, ArchiveFailureException {
                Metadata[] m = e.mustResolve;
                for(int i=0;i<m.length;i++) {
                        try {
                                byte[] buf = m[i].writeToByteArray();
-                               OutputStream os = 
element.bucket.getOutputStream();
+                               OutputStream os = bucket.getOutputStream();
                                os.write(buf);
                                os.close();
-                               addStoreElement(ctx, key, ".metadata-"+(x++), 
element, gotElement, element2, callback, container, context);
+                               addStoreElement(ctx, key, ".metadata-"+(x++), 
bucket, gotElement, element2, callback, container, context);
                        } catch (MetadataUnresolvedException e1) {
-                               x = resolve(e, x, element, ctx, key, 
gotElement, element2, callback, container, context);
+                               x = resolve(e, x, bucket, ctx, key, gotElement, 
element2, callback, container, context);
                        }
                }
                return x;
@@ -428,7 +420,7 @@
         * @throws ArchiveFailureException If a failure occurred resulting in 
the data not being readable. Only happens if
         * callback != null.
         */
-       private ArchiveStoreItem addStoreElement(ArchiveStoreContext ctx, 
FreenetURI key, String name, TempStoreElement temp, MutableBoolean gotElement, 
String callbackName, ArchiveExtractCallback callback, ObjectContainer 
container, ClientContext context) throws ArchiveFailureException {
+       private ArchiveStoreItem addStoreElement(ArchiveStoreContext ctx, 
FreenetURI key, String name, Bucket temp, MutableBoolean gotElement, String 
callbackName, ArchiveExtractCallback callback, ObjectContainer container, 
ClientContext context) throws ArchiveFailureException {
                RealArchiveStoreItem element = new RealArchiveStoreItem(ctx, 
key, name, temp);
                if(logMINOR) Logger.minor(this, "Adding store element: 
"+element+" ( "+key+ ' ' +name+" size "+element.spaceUsed()+" )");
                ArchiveStoreItem oldItem;
@@ -479,23 +471,6 @@
                }
        }

-       /** 
-        * Create a file Bucket in the store directory, encrypted using an 
ethereal key.
-        * This is not yet associated with a name, so will be deleted when it 
goes out
-        * of scope. Not counted towards allocated data as will be short-lived 
and will not
-        * go over the maximum size. Will obviously keep its key when we move 
it to main.
-        */
-       private TempStoreElement makeTempStoreBucket(long size) {
-               long id = filenameGenerator.makeRandomFilename();
-               File myFile = filenameGenerator.getFilename(id);
-               TempFileBucket fb = new TempFileBucket(id, filenameGenerator);
-               
-               byte[] cipherKey = new byte[32];
-               strongPRNG.nextBytes(cipherKey);
-               PaddedEphemerallyEncryptedBucket encryptedBucket = new 
PaddedEphemerallyEncryptedBucket(fb, 1024, strongPRNG, weakPRNG);
-               return new TempStoreElement(myFile, fb, encryptedBucket);
-       }
-
        /**
         * Is the given MIME type an archive type that we can deal with?
         */

Modified: branches/db4o/freenet/src/freenet/client/FECCodec.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/FECCodec.java      2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/client/FECCodec.java      2008-09-24 
20:42:20 UTC (rev 22823)
@@ -196,7 +196,7 @@
                for(int i = 0; i < dataBlockStatus.length; i++) {
                        Bucket data = buckets[i];
                        if(data.size() != blockLength)
-                               throw new IllegalStateException("Block " + i + 
": " + data + " : " + dataBlockStatus[i] + " length " + data.size());
+                               throw new IllegalStateException("Block " + i + 
": " + data + " : " + dataBlockStatus[i] + " length " + data.size() + " whereas 
blockLength="+blockLength);
                        dataBlockStatus[i].setData(data);
                }
        }

Modified: branches/db4o/freenet/src/freenet/client/HighLevelSimpleClient.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/HighLevelSimpleClient.java 
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/client/HighLevelSimpleClient.java 
2008-09-24 20:42:20 UTC (rev 22823)
@@ -7,6 +7,8 @@
 import java.util.Set;

 import freenet.client.async.ClientCallback;
+import freenet.client.async.ClientGetter;
+import freenet.client.async.ClientPutter;
 import freenet.client.events.ClientEventListener;
 import freenet.keys.FreenetURI;
 import freenet.node.RequestClient;
@@ -42,7 +44,7 @@
        /**
         * Non-blocking fetch of a URI with a configurable max-size, context 
object, callback and context.
         */
-       public void fetch(FreenetURI uri, long maxSize, RequestClient context, 
ClientCallback callback, FetchContext fctx) throws FetchException;
+       public ClientGetter fetch(FreenetURI uri, long maxSize, RequestClient 
context, ClientCallback callback, FetchContext fctx) throws FetchException;

        /**
         * Blocking insert.
@@ -54,7 +56,7 @@
        /**
         * Non-blocking insert.
         */
-       public void insert(InsertBlock insert, boolean getCHKOnly, String 
filenameHint, boolean isMetadata, InsertContext ctx, ClientCallback cb) throws 
InsertException;
+       public ClientPutter insert(InsertBlock insert, boolean getCHKOnly, 
String filenameHint, boolean isMetadata, InsertContext ctx, ClientCallback cb) 
throws InsertException;

        /**
         * Blocking insert of a redirect.

Modified: 
branches/db4o/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2008-09-24 20:42:20 UTC (rev 22823)
@@ -92,7 +92,7 @@
                curMaxTempLength = Long.MAX_VALUE;
                curMaxMetadataLength = 1024 * 1024;
                this.cacheLocalRequests = cacheLocalRequests;
-               this.persistentBucketFactory = 
node.persistentEncryptedTempBucketFactory;
+               this.persistentBucketFactory = node.persistentTempBucketFactory;
        }

        public void setMaxLength(long maxLength) {
@@ -128,10 +128,11 @@
                return fw.waitForCompletion();
        }

-       public void fetch(FreenetURI uri, long maxSize, RequestClient 
clientContext, ClientCallback callback, FetchContext fctx) throws 
FetchException {
+       public ClientGetter fetch(FreenetURI uri, long maxSize, RequestClient 
clientContext, ClientCallback callback, FetchContext fctx) throws 
FetchException {
                if(uri == null) throw new NullPointerException();
                ClientGetter get = new ClientGetter(callback, 
core.requestStarters.chkFetchScheduler, core.requestStarters.sskFetchScheduler, 
uri, fctx, priorityClass, clientContext, null, null);
                core.clientContext.start(get);
+               return get;
        }

        public FreenetURI insert(InsertBlock insert, boolean getCHKOnly, String 
filenameHint) throws InsertException {
@@ -148,11 +149,12 @@
                return pw.waitForCompletion();
        }

-       public void insert(InsertBlock insert, boolean getCHKOnly, String 
filenameHint, boolean isMetadata, InsertContext ctx, ClientCallback cb) throws 
InsertException {
+       public ClientPutter insert(InsertBlock insert, boolean getCHKOnly, 
String filenameHint, boolean isMetadata, InsertContext ctx, ClientCallback cb) 
throws InsertException {
                ClientPutter put = new ClientPutter(cb, insert.getData(), 
insert.desiredURI, insert.clientMetadata, 
                                ctx, core.requestStarters.chkPutScheduler, 
core.requestStarters.sskPutScheduler, priorityClass, 
                                getCHKOnly, isMetadata, this, null, 
filenameHint, false);
                core.clientContext.start(put, false);
+               return put;
        }

        public FreenetURI insertRedirect(FreenetURI insertURI, FreenetURI 
targetURI) throws InsertException {

Modified: branches/db4o/freenet/src/freenet/client/RealArchiveStoreItem.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/RealArchiveStoreItem.java  
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/client/RealArchiveStoreItem.java  
2008-09-24 20:42:20 UTC (rev 22823)
@@ -3,16 +3,12 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.client;

-import java.io.File;
-
 import freenet.keys.FreenetURI;
 import freenet.support.api.Bucket;
-import freenet.support.io.FileUtil;
 import freenet.support.io.MultiReaderBucket;

 class RealArchiveStoreItem extends ArchiveStoreItem {

-       private final File myFilename;
        private final MultiReaderBucket mb;
        private final Bucket bucket;
        private final long spaceUsed;
@@ -24,13 +20,12 @@
         * @param temp The TempStoreElement currently storing the data.
         * @param manager The parent ArchiveManager within which this item is 
stored.
         */
-       RealArchiveStoreItem(ArchiveStoreContext ctx, FreenetURI key2, String 
realName, TempStoreElement temp) {
+       RealArchiveStoreItem(ArchiveStoreContext ctx, FreenetURI key2, String 
realName, Bucket bucket) {
                super(new ArchiveKey(key2, realName), ctx);
-               mb = new MultiReaderBucket(temp.bucket);
+               mb = new MultiReaderBucket(bucket);
                this.bucket = mb.getReaderBucket();
-               temp.underBucket.setReadOnly();
-               this.myFilename = temp.underBucket.getFile();
-               spaceUsed = FileUtil.estimateUsage(myFilename, 
temp.underBucket.size());
+               bucket.setReadOnly();
+               spaceUsed = bucket.size();
        }

        /**
@@ -54,6 +49,7 @@
                return spaceUsed;
        }

+       @Override
        void innerClose() {
                bucket.free();
        }

Deleted: branches/db4o/freenet/src/freenet/client/TempStoreElement.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/TempStoreElement.java      
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/client/TempStoreElement.java      
2008-09-24 20:42:20 UTC (rev 22823)
@@ -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;
-
-import java.io.File;
-
-import freenet.support.io.PaddedEphemerallyEncryptedBucket;
-import freenet.support.io.TempFileBucket;
-
-class TempStoreElement {
-       final File myFilename;
-       final PaddedEphemerallyEncryptedBucket bucket;
-       final TempFileBucket underBucket;
-       
-       TempStoreElement(File myFile, TempFileBucket fb, 
PaddedEphemerallyEncryptedBucket encryptedBucket) {
-               this.myFilename = myFile;
-               this.underBucket = fb;
-               this.bucket = encryptedBucket;
-       }
-       
-       public void close() {
-               underBucket.free();
-       }
-}
\ No newline at end of file

Modified: 
branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -18,6 +18,7 @@
 import freenet.node.RequestClient;
 import freenet.node.RequestScheduler;
 import freenet.node.SendableGet;
+import freenet.support.Executor;
 import freenet.support.Logger;

 public abstract class BaseSingleFileFetcher extends SendableGet implements 
HasKeyListener {
@@ -109,11 +110,10 @@
                                        if(persistent)
                                                container.deactivate(key, 5);
                                }
-                               return true; // We will retry, just not yet. 
See requeueAfterCooldown(Key).
                        } else {
                                reschedule(container, context);
                        }
-                       return true;
+                       return true; // We will retry in any case, maybe not 
just not yet. See requeueAfterCooldown(Key).
                }
                return false;
        }

Modified: branches/db4o/freenet/src/freenet/client/async/ClientContext.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/ClientContext.java   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/client/async/ClientContext.java   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -58,7 +58,7 @@
                this.backgroundBlockEncoder = core.backgroundBlockEncoder;
                this.random = core.random;
                archiveManager = core.archiveManager;
-               this.persistentBucketFactory = 
core.persistentEncryptedTempBucketFactory;
+               this.persistentBucketFactory = core.persistentTempBucketFactory;
                this.tempBucketFactory = core.tempBucketFactory;
                this.healingQueue = core.getHealingQueue();
                this.uskManager = core.uskManager;

Modified: 
branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java  
2008-09-24 20:42:20 UTC (rev 22823)
@@ -48,7 +48,7 @@

        private static boolean logMINOR;

-       public static class PrioritySchedulerCallback implements 
StringCallback, EnumerableOptionCallback {
+       public static class PrioritySchedulerCallback extends StringCallback 
implements EnumerableOptionCallback {
                final ClientRequestScheduler cs;
                private final String[] possibleValues = new String[]{ 
ClientRequestScheduler.PRIORITY_HARD, ClientRequestScheduler.PRIORITY_SOFT };


Modified: 
branches/db4o/freenet/src/freenet/client/async/SimpleManifestPutter.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/SimpleManifestPutter.java    
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/client/async/SimpleManifestPutter.java    
2008-09-24 20:42:20 UTC (rev 22823)
@@ -474,7 +474,7 @@
                                // FIXME support formats other than .zip.
                                // Only the *decoding* is generic at present.

-                               Bucket zipBucket = 
context.getBucketFactory(persistent()).makeBucket(-1);
+                               Bucket zipBucket = 
context.getBucketFactory(persistent()).makeBucket(baseMetadata.dataLength());
                                OutputStream os = new 
BufferedOutputStream(zipBucket.getOutputStream());
                                ZipOutputStream zos = new ZipOutputStream(os);
                                ZipEntry ze;

Modified: 
branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java 
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java 
2008-09-24 20:42:20 UTC (rev 22823)
@@ -373,7 +373,7 @@
                                        }
                                }
                        }
-                       decodedData = 
context.getBucketFactory(persistent).makeBucket(-1);
+                       decodedData = 
context.getBucketFactory(persistent).makeBucket(maxBlockLength * 
dataBuckets.length);
                        if(logMINOR) Logger.minor(this, "Copying data from 
"+dataBuckets.length+" data blocks");
                        OutputStream os = decodedData.getOutputStream();
                        for(int i=0;i<dataBuckets.length;i++) {

Modified: branches/db4o/freenet/src/freenet/clients/http/ConfigToadlet.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/ConfigToadlet.java   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/ConfigToadlet.java   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -10,14 +10,18 @@
 import freenet.client.HighLevelSimpleClient;
 import freenet.config.BooleanOption;
 import freenet.config.Config;
+import freenet.config.ConfigCallback;
 import freenet.config.EnumerableOptionCallback;
 import freenet.config.InvalidConfigValueException;
+import freenet.config.NodeNeedRestartException;
 import freenet.config.Option;
 import freenet.config.SubConfig;
 import freenet.config.WrapperConfig;
 import freenet.l10n.L10n;
 import freenet.node.Node;
 import freenet.node.NodeClientCore;
+import freenet.node.useralerts.AbstractUserAlert;
+import freenet.node.useralerts.UserAlert;
 import freenet.support.HTMLNode;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
@@ -32,7 +36,64 @@
        private final Config config;
        private final NodeClientCore core;
        private final Node node;
-       
+       private boolean needRestart = false;
+       private NeedRestartUserAlert needRestartUserAlert;
+
+       private class NeedRestartUserAlert extends AbstractUserAlert {
+               @Override
+               public String getTitle() {
+                       return l10n("needRestartTitle");
+               }
+
+               @Override
+               public String getText() {
+                       return getHTMLText().toString();
+               }
+
+               @Override
+               public String getShortText() {
+                       return l10n("needRestartShort");
+               }
+
+               @Override
+               public HTMLNode getHTMLText() {
+                       HTMLNode alertNode = new HTMLNode("div");
+                       alertNode.addChild("#", l10n("needRestart"));
+
+                       if (node.isUsingWrapper()) {
+                               alertNode.addChild("br");
+                               HTMLNode restartForm = 
alertNode.addChild("form", //
+                                               new String[] { "action", 
"method" },//
+                                       new String[] { "/", "get" });
+                               restartForm.addChild("div");
+                               restartForm.addChild("input",//
+                                               new String[] { "type", "name" 
},//
+                                               new String[] { "hidden", 
"restart" });
+                               restartForm.addChild("input", //
+                                               new String[] { "type", "name", 
"value" },//
+                                               new String[] { "submit", 
"restart2",//
+                                               l10n("restartNode") });
+                       }
+
+                       return alertNode;
+               }
+
+               @Override
+               public short getPriorityClass() {
+                       return UserAlert.WARNING;
+               }
+
+               @Override
+               public boolean isValid() {
+                       return needRestart;
+               }
+
+               @Override
+               public boolean userCanDismiss() {
+                       return false;
+               }
+       }
+
        ConfigToadlet(HighLevelSimpleClient client, Config conf, Node node, 
NodeClientCore core) {
                super(client);
                config=conf;
@@ -40,7 +101,9 @@
                this.node = node;
        }

-       public void handlePost(URI uri, HTTPRequest request, ToadletContext 
ctx) throws ToadletContextClosedException, IOException {
+       
+       @Override
+    public void handlePost(URI uri, HTTPRequest request, ToadletContext ctx) 
throws ToadletContextClosedException, IOException {
                StringBuffer errbuf = new StringBuffer();
                SubConfig[] sc = config.getConfigs();

@@ -60,7 +123,7 @@
                boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);

                for(int i=0; i<sc.length ; i++){
-                       Option[] o = sc[i].getOptions();
+                       Option<?>[] o = sc[i].getOptions();
                        String prefix = sc[i].getPrefix();
                        String configName;

@@ -68,7 +131,7 @@
                                configName=o[j].getName();
                                if(logMINOR) Logger.minor(this, "Setting 
"+prefix+ '.' +configName);

-                               // we ignore unreconized parameters 
+                               // we ignore unreconized parameters
                                if(request.isPartSet(prefix+ '.' +configName)) {
                                        String value = 
request.getPartAsString(prefix+ '.' +configName, MAX_PARAM_VALUE_SIZE);
                                        
if(!(o[j].getValueString().equals(value))){
@@ -77,6 +140,8 @@
                                                        o[j].setValue(value);
                                                } catch 
(InvalidConfigValueException e) {
                                                        
errbuf.append(o[j].getName()).append(' ').append(e.getMessage()).append('\n');
+                                               } catch 
(NodeNeedRestartException e) {
+                                                       needRestart = true;
                                                } catch (Exception e){
                             errbuf.append(o[j].getName()).append(' 
').append(e).append('\n');
                                                        Logger.error(this, 
"Caught "+e, e);
@@ -102,7 +167,32 @@

                if (errbuf.length() == 0) {
                        HTMLNode infobox = 
contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-success", 
l10n("appliedTitle")));
-                       
ctx.getPageMaker().getContentNode(infobox).addChild("#", 
l10n("appliedSuccess"));
+                       HTMLNode content = 
ctx.getPageMaker().getContentNode(infobox);
+                       content.addChild("#", l10n("appliedSuccess"));
+                       
+                       if (needRestart) {
+                               content.addChild("br");
+                               content.addChild("#", l10n("needRestart"));
+
+                               if (node.isUsingWrapper()) {
+                                       content.addChild("br");
+                                       HTMLNode restartForm = 
content.addChild("form",//
+                                               new String[] { "action", 
"method" }, new String[] { "/", "get" }//
+                                               ).addChild("div");
+                                       restartForm.addChild("input",//
+                                               new String[] { "type", "name" 
},//
+                                               new String[] { "hidden", 
"restart" });
+                                       restartForm.addChild("input", //
+                                               new String[] { "type", "name", 
"value" },//
+                                               new String[] { "submit", 
"restart2",//
+                                                       l10n("restartNode") });
+                               }
+                               
+                               if (needRestartUserAlert == null) {
+                                       needRestartUserAlert = new 
NeedRestartUserAlert();
+                                       
node.clientCore.alerts.register(needRestartUserAlert);
+                               }
+                       }
                } else {
                        HTMLNode infobox = 
contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-error", 
l10n("appliedFailureTitle")));
                        HTMLNode content = 
ctx.getPageMaker().getContentNode(infobox).addChild("div", "class", 
"infobox-content");
@@ -125,7 +215,8 @@
                return L10n.getString("ConfigToadlet." + string);
        }

-       public void handleGet(URI uri, HTTPRequest req, ToadletContext ctx) 
throws ToadletContextClosedException, IOException {
+       @Override
+    public void handleGet(URI uri, HTTPRequest req, ToadletContext ctx) throws 
ToadletContextClosedException, IOException {

                if(!ctx.isAllowedFullAccess()) {
                        super.sendErrorPage(ctx, 403, 
L10n.getString("Toadlet.unauthorizedTitle"), 
L10n.getString("Toadlet.unauthorized"));
@@ -171,7 +262,7 @@
                        String defaultValue = "128";
                        String curValue = 
WrapperConfig.getWrapperProperty(configName);
                        item.addChild("span", new String[]{ "class", "title", 
"style" },
-                                       new String[]{ "configshortdesc", 
L10n.getString("ConfigToadlet.defaultIs", new String[] { "default" }, new 
String[] { defaultValue }), 
+                                       new String[]{ "configshortdesc", 
L10n.getString("ConfigToadlet.defaultIs", new String[] { "default" }, new 
String[] { defaultValue }),
                                        "cursor: help;" 
}).addChild(L10n.getHTMLNode("WrapperConfig."+configName+".short"));
                        item.addChild("span", "class", 
"config").addChild("input", new String[] { "type", "class", "name", "value" }, 
new String[] { "text", "config", configName, curValue });
                        item.addChild("span", "class", 
"configlongdesc").addChild(L10n.getHTMLNode("WrapperConfig."+configName+".long"));
@@ -180,7 +271,7 @@
                for(int i=0; i<sc.length;i++){
                        short displayedConfigElements = 0;

-                       Option[] o = sc[i].getOptions();
+                       Option<?>[] o = sc[i].getOptions();
                        HTMLNode configGroupUlNode = new HTMLNode("ul", 
"class", "config");

                        for(int j=0; j<o.length; j++){
@@ -190,20 +281,31 @@

                                        HTMLNode configItemNode = 
configGroupUlNode.addChild("li");
                                        configItemNode.addChild("span", new 
String[]{ "class", "title", "style" },
-                                                       new String[]{ 
"configshortdesc", L10n.getString("ConfigToadlet.defaultIs", new String[] { 
"default" }, new String[] { o[j].getDefault() }) + (mode >= 
PageMaker.MODE_ADVANCED ? " ["+sc[i].getPrefix() + '.' + o[j].getName() + ']' : 
""), 
+                                                       new String[]{ 
"configshortdesc", L10n.getString("ConfigToadlet.defaultIs", new String[] { 
"default" }, new String[] { o[j].getDefault() }) + (mode >= 
PageMaker.MODE_ADVANCED ? " ["+sc[i].getPrefix() + '.' + o[j].getName() + ']' : 
""),
                                                        "cursor: help;" 
}).addChild(L10n.getHTMLNode(o[j].getShortDesc()));
                                        HTMLNode configItemValueNode = 
configItemNode.addChild("span", "class", "config");
                                        if(o[j].getValueString() == null){
                                                Logger.error(this, 
sc[i].getPrefix() + configName + "has returned null from config!);");
-                                               continue; 
+                                               continue;
                                        }

-                                       if(o[j].getCallback() instanceof 
EnumerableOptionCallback)
-                                               
configItemValueNode.addChild(addComboBox((EnumerableOptionCallback)o[j].getCallback(),
 sc[i], configName));
-                                       else if(o[j].getCallback() instanceof 
BooleanCallback)
-                                               
configItemValueNode.addChild(addBooleanComboBox(((BooleanOption)o[j]).getValue(),
 sc[i], configName));
+                                       ConfigCallback<?> callback = 
o[j].getCallback();
+                                       if(callback instanceof 
EnumerableOptionCallback)
+                                               
configItemValueNode.addChild(addComboBox((EnumerableOptionCallback) callback, 
sc[i],
+                                                       configName, 
callback.isReadOnly()));
+                                       else if(callback instanceof 
BooleanCallback)
+                                               
configItemValueNode.addChild(addBooleanComboBox(((BooleanOption) 
o[j]).getValue(), sc[i],
+                                                       configName, 
callback.isReadOnly()));
+                                       else if (callback.isReadOnly())
+                                               
configItemValueNode.addChild("input", //
+                                                       new String[] { "type", 
"class", "disabled", "alt", "name", "value" }, //
+                                                       new String[] { "text", 
"config", "disabled", o[j].getShortDesc(),
+                                                               
sc[i].getPrefix() + '.' + configName, o[j].getValueString() });
                                        else
-                                               
configItemValueNode.addChild("input", new String[] { "type", "class", "alt", 
"name", "value" }, new String[] { "text", "config", o[j].getShortDesc(), 
sc[i].getPrefix() + '.' + configName, o[j].getValueString() });
+                                               
configItemValueNode.addChild("input",//
+                                                       new String[] { "type", 
"class", "alt", "name", "value" }, //
+                                                       new String[] { "text", 
"config", o[j].getShortDesc(),
+                                                               
sc[i].getPrefix() + '.' + configName, o[j].getValueString() });

                                        configItemNode.addChild("span", 
"class", "configlongdesc").addChild(L10n.getHTMLNode(o[j].getLongDesc()));
                                }
@@ -222,12 +324,20 @@
                this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
        }

-       public String supportedMethods() {
+       @Override
+    public String supportedMethods() {
                return "GET, POST";
        }

-       private HTMLNode addComboBox(EnumerableOptionCallback o, SubConfig sc, 
String name) {
-               HTMLNode result = new HTMLNode("select", "name", sc.getPrefix() 
+ '.' + name);
+       private HTMLNode addComboBox(EnumerableOptionCallback o, SubConfig sc, 
String name, boolean disabled) {
+               HTMLNode result;
+               if (disabled)
+                       result = new HTMLNode("select", //
+                               new String[] { "name", "disabled" }, //
+                               new String[] { sc.getPrefix() + '.' + name, 
"disabled" });
+               else
+                       result = new HTMLNode("select", "name", sc.getPrefix() 
+ '.' + name);
+               
                String[] possibleValues = o.getPossibleValues();
                for(int i=0; i<possibleValues.length; i++) {
                        if(possibleValues[i].equals(o.get()))
@@ -239,17 +349,23 @@
                return result;
        }

-       private HTMLNode addBooleanComboBox(boolean value, SubConfig sc, String 
name) {
-               HTMLNode result = new HTMLNode("select", "name", sc.getPrefix() 
+ '.' + name);
-               
-               if(value) {
-                       result.addChild("option", new String[] { "value", 
"selected" }, new String[] {
-                                       "true", "selected" }, l10n("true"));
+       private HTMLNode addBooleanComboBox(boolean value, SubConfig sc, String 
name, boolean disabled) {
+               HTMLNode result;
+               if (disabled)
+                       result = new HTMLNode("select", //
+                               new String[] { "name", "disabled" }, //
+                               new String[] { sc.getPrefix() + '.' + name, 
"disabled" });
+               else
+                       result = new HTMLNode("select", "name", sc.getPrefix() 
+ '.' + name);
+
+               if (value) {
+                       result.addChild("option", new String[] { "value", 
"selected" }, new String[] { "true", "selected" },
+                               l10n("true"));
                        result.addChild("option", "value", "false", 
l10n("false"));
                } else {
                        result.addChild("option", "value", "true", 
l10n("true"));
-                       result.addChild("option", new String[] { "value", 
"selected" }, new String[] {
-                                       "false", "selected" }, l10n("false"));
+                       result.addChild("option", new String[] { "value", 
"selected" }, new String[] { "false", "selected" },
+                               l10n("false"));
                }

                return result;

Modified: branches/db4o/freenet/src/freenet/clients/http/ConnectionsToadlet.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/ConnectionsToadlet.java      
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/ConnectionsToadlet.java      
2008-09-24 20:42:20 UTC (rev 22823)
@@ -120,7 +120,8 @@
                                long total2 = 
secondNode.getTotalInputBytes()+secondNode.getTotalOutputBytes();
                                return compareLongs(total1, total2);
                        }else if(sortBy.equals("selection_percentage")){
-                               return 
compareLongs(firstNode.getNumberOfSelections(), 
secondNode.getNumberOfSelections());
+                               long sinceWhen = System.currentTimeMillis() - 
PeerNode.SELECTION_SAMPLING_PERIOD;
+                               return 
compareInts(firstNode.getNumberOfSelections().headSet(sinceWhen).size(), 
secondNode.getNumberOfSelections().headSet(sinceWhen).size());
                        }else if(sortBy.equals("time_delta")){
                                return compareLongs(firstNode.getClockDelta(), 
secondNode.getClockDelta());
                        }else if(sortBy.equals(("uptime"))){
@@ -418,9 +419,8 @@
                                        }
                                }

-                               long numberOfSelectionSamples = 
peers.getNumberOfSelectionSamples();
-                               for (int peerIndex = 0, peerCount = 
peerNodeStatuses.length; peerIndex < peerCount; peerIndex++) {
-                                       
+                               int numberOfSelectionSamples = 
peers.getNumberOfSelectionSamples().tailSet(now - 
PeerNode.SELECTION_SAMPLING_PERIOD).size();
+                               for (int peerIndex = 0, peerCount = 
peerNodeStatuses.length; peerIndex < peerCount; peerIndex++) {                  
                    
                                        PeerNodeStatus peerNodeStatus = 
peerNodeStatuses[peerIndex];
                                        drawRow(peerTable, peerNodeStatus, mode 
>= PageMaker.MODE_ADVANCED, fProxyJavascriptEnabled, now, path, 
enablePeerActions, endCols, drawMessageTypes, numberOfSelectionSamples);

@@ -693,9 +693,11 @@

        abstract protected SimpleFieldSet getNoderef();

-       private void drawRow(HTMLNode peerTable, PeerNodeStatus peerNodeStatus, 
boolean advancedModeEnabled, boolean fProxyJavascriptEnabled, long now, String 
path, boolean enablePeerActions, SimpleColumn[] endCols, boolean 
drawMessageTypes, long numberOfSelectionSamples) {
-               HTMLNode peerRow = peerTable.addChild("tr");
-
+       private void drawRow(HTMLNode peerTable, PeerNodeStatus peerNodeStatus, 
boolean advancedModeEnabled, boolean fProxyJavascriptEnabled, long now, String 
path, boolean enablePeerActions, SimpleColumn[] endCols, boolean 
drawMessageTypes, int numberOfSelectionSamples) {
+               int peerSelectionCount = 
peerNodeStatus.getNumberOfSelections().tailSet(now - 
PeerNode.SELECTION_SAMPLING_PERIOD).size();
+               int peerSelectionPercentage = (numberOfSelectionSamples > 0 ? 
(peerSelectionCount*100/numberOfSelectionSamples) : 0);
+               HTMLNode peerRow = peerTable.addChild("tr", "class", 
"darknet_connections_"+(peerSelectionPercentage > 
PeerNode.SELECTION_PERCENTAGE_WARNING ? "warning" : "normal"));
+               
                if(enablePeerActions) {
                        // check box column
                        peerRow.addChild("td", "class", 
"peer-marker").addChild("input", new String[] { "type", "name" }, new String[] 
{ "checkbox", "node_" + peerNodeStatus.hashCode() });
@@ -775,7 +777,7 @@
                        // percent of time connected column
                        peerRow.addChild("td", "class", "peer-idle" /* FIXME 
*/).addChild("#", 
fix1.format(peerNodeStatus.getPercentTimeRoutableConnection()));
                        // selection stats
-                       peerRow.addChild("td", "class", "peer-idle" /* FIXME 
*/).addChild("#", (numberOfSelectionSamples > 0 ? 
((peerNodeStatus.getNumberOfSelections()*100/numberOfSelectionSamples)+"%") : 
"N/A"));
+                       peerRow.addChild("td", "class", "peer-idle" /* FIXME 
*/).addChild("#", (numberOfSelectionSamples > 0 ? (peerSelectionPercentage+"%") 
: "N/A"));
                        // total traffic column
                        peerRow.addChild("td", "class", "peer-idle" /* FIXME 
*/).addChild("#", SizeUtil.formatSize(peerNodeStatus.getTotalInputBytes())+" / 
"+SizeUtil.formatSize(peerNodeStatus.getTotalOutputBytes())+"/"+SizeUtil.formatSize(peerNodeStatus.getResendBytesSent()));
                        // congestion control

Modified: branches/db4o/freenet/src/freenet/clients/http/FProxyToadlet.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/FProxyToadlet.java   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/FProxyToadlet.java   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -56,7 +56,7 @@
        // ?force= links become invalid after 2 hours.
        private static final long FORCE_GRAIN_INTERVAL = 60*60*1000;
        /** Maximum size for transparent pass-through, should be a config 
option */
-       static final long MAX_LENGTH = 2*1024*1024; // 2MB
+       static long MAX_LENGTH = 2*1024*1024; // 2MB

        static final URI welcome;
        static {
@@ -95,6 +95,7 @@
                return "GET";
        }

+       @Override
        public void handlePost(URI uri, HTTPRequest req, ToadletContext ctx) 
throws ToadletContextClosedException, IOException, RedirectException {
                String ks = uri.getPath();

@@ -320,9 +321,10 @@
                return false;
        }

+       @Override
        public void handleGet(URI uri, HTTPRequest httprequest, ToadletContext 
ctx) 
                        throws ToadletContextClosedException, IOException, 
RedirectException {
-               //String ks = uri.toString();
+
                String ks = uri.getPath();

                boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
@@ -446,7 +448,7 @@
                        String referer = sanitizeReferer(ctx);


-                       handleDownload(ctx, data, ctx.getBucketFactory(), 
mimeType, requestedMimeType, httprequest.getParam("force", null), 
httprequest.isParameterSet("forcedownload"), "/", key, maxSize != MAX_LENGTH ? 
"&max-size="+maxSize : "", referer, true, ctx, core);
+                       handleDownload(ctx, data, ctx.getBucketFactory(), 
mimeType, requestedMimeType, httprequest.getParam("force", null), 
httprequest.isParameterSet("forcedownload"), "/", key, maxSize != MAX_LENGTH ? 
"&max-size="+SizeUtil.formatSizeWithoutSpace(maxSize) : "", referer, true, ctx, 
core);

                } catch (FetchException e) {
                        String msg = e.getMessage();
@@ -574,7 +576,7 @@
                        fileInformationList.addChild("li", l10n("sizeUnknown"));
                }
                if(mime != null) {
-                       fileInformationList.addChild("li", 
L10n.getString("FProxyToadlet."+(finalized ? "mimeType" : "expectedMimeType"), 
new String[] { "mime" }, new String[] { mime }));;
+                       fileInformationList.addChild("li", 
L10n.getString("FProxyToadlet."+(finalized ? "mimeType" : "expectedMimeType"), 
new String[] { "mime" }, new String[] { mime }));
                } else {
                        fileInformationList.addChild("li", 
l10n("unknownMIMEType"));
                }
@@ -667,9 +669,6 @@
                WelcomeToadlet welcometoadlet = new WelcomeToadlet(client, 
core, node, bookmarks);
                server.register(welcometoadlet, "/welcome/", true, false);

-               PluginToadlet pluginToadlet = new PluginToadlet(client, 
node.pluginManager2, core);
-               server.register(pluginToadlet, "/plugin/", true, true);
-               
                ConfigToadlet configtoadlet = new ConfigToadlet(client, config, 
node, core);
                server.register(configtoadlet, "/config/", true, 
"FProxyToadlet.configTitle", "FProxyToadlet.config", true, null);


Modified: 
branches/db4o/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java  
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java  
2008-09-24 20:42:20 UTC (rev 22823)
@@ -10,11 +10,14 @@

 import freenet.client.HighLevelSimpleClient;
 import freenet.config.Config;
+import freenet.config.ConfigException;
 import freenet.config.InvalidConfigValueException;
+import freenet.config.NodeNeedRestartException;
 import freenet.config.WrapperConfig;
 import freenet.l10n.L10n;
 import freenet.node.Node;
 import freenet.node.NodeClientCore;
+import freenet.pluginmanager.FredPluginBandwidthIndicator;
 import freenet.support.Fields;
 import freenet.support.HTMLNode;
 import freenet.support.Logger;
@@ -25,15 +28,23 @@
 /**
  * A first time wizard aimed to ease the configuration of the node.
  * 
- * @author Florent Daigni&egrave;re &lt;nextgens at freenetproject.org&gt;
- * 
- * TODO: a choose your CSS step ?
+ * TODO: a choose your CSS step?
  */
 public class FirstTimeWizardToadlet extends Toadlet {
        private final NodeClientCore core;
        private final Config config;

+       private enum WIZARD_STEP {
+               WELCOME,
+               OPENNET,
+               NAME_SELECTION,
+               BANDWIDTH,
+               DATASTORE_SIZE,
+               MEMORY,
+               CONGRATZ;
+       }

+       
        FirstTimeWizardToadlet(HighLevelSimpleClient client, Node node, 
NodeClientCore core) {
                super(client);
                this.core = core;
@@ -42,15 +53,16 @@

        public static final String TOADLET_URL = "/wizard/";

+       @Override
        public void handleGet(URI uri, HTTPRequest request, ToadletContext ctx) 
throws ToadletContextClosedException, IOException {
                if(!ctx.isAllowedFullAccess()) {
                        super.sendErrorPage(ctx, 403, "Unauthorized", 
L10n.getString("Toadlet.unauthorized"));
                        return;
                }

-               int currentStep = request.getIntParam("step");
+               WIZARD_STEP currentStep = 
WIZARD_STEP.valueOf(request.getParam("step", WIZARD_STEP.WELCOME.toString()));

-               if(currentStep == 1) {
+               if(currentStep == WIZARD_STEP.OPENNET) {
                        HTMLNode pageNode = 
ctx.getPageMaker().getPageNode(l10n("step1Title"), false, ctx);
                        HTMLNode contentNode = 
ctx.getPageMaker().getContentNode(pageNode);

@@ -66,14 +78,16 @@
                        opennetDiv.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "radio", "enableOpennet", "true" }, 
l10n("opennetYes"));
                        opennetDiv.addChild("br");
                        opennetDiv.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "radio", "enableOpennet", "false" }, 
l10n("opennetNo"));
-                       HTMLNode para = opennetForm.addChild("p");
-                       para.addChild("b", l10n("warningTitle")+' ');
-                       L10n.addL10nSubstitution(para, 
"FirstTimeWizardToadlet.opennetWarning", new String[] { "bold", "/bold" }, new 
String[] { "<b>", "</b>" });
                        opennetForm.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "submit", "opennetF", 
L10n.getString("FirstTimeWizardToadlet.continue")});
                        opennetForm.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "submit", "cancel", 
L10n.getString("Toadlet.cancel")});
                        this.writeHTMLReply(ctx, 200, "OK", 
pageNode.generate());
                        return;
-               } else if(currentStep == 2) {
+               } else if(currentStep == WIZARD_STEP.NAME_SELECTION) {
+                       // Attempt to skip one step if possible: opennet nodes 
don't need a name
+                       if(Boolean.valueOf(request.getParam("opennet"))) {
+                               super.writeTemporaryRedirect(ctx, "step3", 
TOADLET_URL+"?step="+WIZARD_STEP.BANDWIDTH);
+                               return;
+                       }
                        HTMLNode pageNode = 
ctx.getPageMaker().getPageNode(l10n("step2Title"), false, ctx);
                        HTMLNode contentNode = 
ctx.getPageMaker().getContentNode(pageNode);

@@ -90,7 +104,12 @@
                        nnameForm.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "submit", "cancel", 
L10n.getString("Toadlet.cancel")});
                        this.writeHTMLReply(ctx, 200, "OK", 
pageNode.generate());
                        return;
-               } else if(currentStep == 3) {
+               } else if(currentStep == WIZARD_STEP.BANDWIDTH) {
+                       // Attempt to skip one step if possible
+                       if(canAutoconfigureBandwidth()){
+                               super.writeTemporaryRedirect(ctx, "step4", 
TOADLET_URL+"?step="+WIZARD_STEP.DATASTORE_SIZE);
+                               return;
+                       }
                        HTMLNode pageNode = 
ctx.getPageMaker().getPageNode(l10n("step3Title"), false, ctx);
                        HTMLNode contentNode = 
ctx.getPageMaker().getContentNode(pageNode);

@@ -103,6 +122,7 @@
                        HTMLNode bandwidthForm = 
ctx.addFormChild(bandwidthInfoboxContent, ".", "bwForm");
                        HTMLNode result = bandwidthForm.addChild("select", 
"name", "bw");

+                       // don't forget to update handlePost too if you change 
that!
                        result.addChild("option", "value", "8K", 
l10n("bwlimitLowerSpeed"));
                        // Special case for 128kbps to increase performance at 
the cost of some link degradation. Above that we use 50% of the limit.
                        result.addChild("option", "value", "12K", "512+/128 
kbps");
@@ -115,7 +135,12 @@
                        bandwidthForm.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "submit", "cancel", 
L10n.getString("Toadlet.cancel")});
                        this.writeHTMLReply(ctx, 200, "OK", 
pageNode.generate());
                        return;
-               } else if(currentStep == 4) {
+               } else if(currentStep == WIZARD_STEP.DATASTORE_SIZE) {
+                       // Attempt to skip one step if possible
+                       if(canAutoconfigureDatastoreSize()) {
+                               super.writeTemporaryRedirect(ctx, "step4", 
TOADLET_URL+"?step="+WIZARD_STEP.MEMORY);
+                               return;
+                       }
                        HTMLNode pageNode = 
ctx.getPageMaker().getPageNode(l10n("step4Title"), false, ctx);
                        HTMLNode contentNode = 
ctx.getPageMaker().getContentNode(pageNode);

@@ -127,57 +152,7 @@
                        bandwidthInfoboxContent.addChild("#", 
l10n("datastoreSizeLong"));
                        HTMLNode bandwidthForm = 
ctx.addFormChild(bandwidthInfoboxContent, ".", "dsForm");
                        HTMLNode result = bandwidthForm.addChild("select", 
"name", "ds");
-                       
-                       // Use JNI to find out the free space on this partition.

-                       long freeSpace = -1;
-                       File dir = 
FileUtil.getCanonicalFile(core.node.getNodeDir());
-                       try {
-                               Class c = dir.getClass();
-                               Method m = c.getDeclaredMethod("getFreeSpace", 
new Class[0]);
-                               if(m != null) {
-                                       Long lFreeSpace = (Long) m.invoke(dir, 
new Object[0]);
-                                       if(lFreeSpace != null) {
-                                               freeSpace = 
lFreeSpace.longValue();
-                                               System.err.println("Found free 
space on node's partition: "+freeSpace+" on "+dir+" = 
"+SizeUtil.formatSize(freeSpace));
-                                       }
-                               }
-                       } catch (NoSuchMethodException e) {
-                               // Ignore
-                               freeSpace = -1;
-                       } catch (Throwable t) {
-                               System.err.println("Trying to access 1.6 
getFreeSpace(), caught "+t);
-                               freeSpace = -1;
-                       }
-                       
-                       if(freeSpace <= 0) {
-                               result.addChild("option", new String[] { 
"value", "selected" }, new String[] { "1G", "selected" }, "1GiB");
-                       } else {
-                               if(freeSpace / 10 > 1024*1024*1024) {
-                                       // If 10GB+ free, default to 10% of 
available disk space.
-                                       String size = 
SizeUtil.formatSize(freeSpace/10);
-                                       String shortSize = 
SizeUtil.stripBytesEtc(size);
-                                       result.addChild("option", new String[] 
{ "value", "selected" }, new String[] { shortSize, "selected" }, size+" 
"+l10n("tenPercentDisk"));
-                                       if(freeSpace / 20 > 1024*1024*1024) {
-                                               // If 20GB+ free, also offer 5% 
of available disk space.
-                                               size = 
SizeUtil.formatSize(freeSpace/20);
-                                               shortSize = 
SizeUtil.stripBytesEtc(size);
-                                               result.addChild("option", 
"value", shortSize, size+" "+l10n("fivePercentDisk"));
-                                       }
-                                       result.addChild("option", "value", 
"1G", "1GiB");
-                               } else if(freeSpace < 1024*1024*1024) {
-                                       // If less than 1GB free, default to 
256MB and also offer 512MB.
-                                       result.addChild("option", new String[] 
{ "value", "selected" }, new String[] { "256M", "selected" }, "256MiB");
-                                       result.addChild("option", "value", 
"512M", "512MiB");
-                               } else if(freeSpace < 5*1024*1024*1024) {
-                                       // If less than 5GB free, default to 
512MB
-                                       result.addChild("option", new String[] 
{ "value", "selected" }, new String[] { "512M", "selected" }, "512MiB");        
                                 
-                                       result.addChild("option", "value", 
"1G", "1GiB");
-                               } else {
-                                       // If unknown, or 5-10GB free, default 
to 1GB.
-                                       result.addChild("option", new String[] 
{ "value", "selected" }, new String[] { "1G", "selected" }, "1GiB");
-                               }
-                       }
                        result.addChild("option", "value", "2G", "2GiB");
                        result.addChild("option", "value", "3G", "3GiB");
                        result.addChild("option", "value", "5G", "5GiB");
@@ -191,7 +166,13 @@
                        bandwidthForm.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "submit", "cancel", 
L10n.getString("Toadlet.cancel")});
                        this.writeHTMLReply(ctx, 200, "OK", 
pageNode.generate());
                        return;
-               } else if(currentStep == 6) {
+               } else if(currentStep == WIZARD_STEP.MEMORY) {
+                       // FIXME: Get rid of it when the db4o branch is merged 
or auto-detect it (be careful of classpath's bug @see <freenet.Node>)
+                       // Attempt to skip one step if possible
+                       if(!WrapperConfig.canChangeProperties()) {
+                               super.writeTemporaryRedirect(ctx, "step6", 
TOADLET_URL+"?step="+WIZARD_STEP.CONGRATZ);
+                               return;
+                       }
                        HTMLNode pageNode = 
ctx.getPageMaker().getPageNode(l10n("step6Title"), false, ctx);
                        HTMLNode contentNode = 
ctx.getPageMaker().getContentNode(pageNode);

@@ -215,7 +196,7 @@
                        this.writeHTMLReply(ctx, 200, "OK", 
pageNode.generate());
                        return;

-               }else if(currentStep == 7) {
+               }else if(currentStep == WIZARD_STEP.CONGRATZ) {
                        HTMLNode pageNode = 
ctx.getPageMaker().getPageNode(l10n("step7Title"), true, ctx);
                        HTMLNode contentNode = 
ctx.getPageMaker().getContentNode(pageNode);

@@ -243,7 +224,7 @@
                HTMLNode firstParagraph = welcomeInfoboxContent.addChild("p");
                firstParagraph.addChild("#", l10n("welcomeInfoboxContent1"));
                HTMLNode secondParagraph = welcomeInfoboxContent.addChild("p");
-               secondParagraph.addChild("a", "href", "?step=1").addChild("#", 
L10n.getString("FirstTimeWizardToadlet.clickContinue"));
+               secondParagraph.addChild("a", "href", 
"?step="+WIZARD_STEP.OPENNET).addChild("#", 
L10n.getString("FirstTimeWizardToadlet.clickContinue"));

                HTMLNode thirdParagraph = welcomeInfoboxContent.addChild("p");
                thirdParagraph.addChild("a", "href", "/").addChild("#", 
l10n("skipWizard"));
@@ -251,6 +232,7 @@
                this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
        }

+       @Override
        public void handlePost(URI uri, HTTPRequest request, ToadletContext 
ctx) throws ToadletContextClosedException, IOException {

                if(!ctx.isAllowedFullAccess()) {
@@ -274,51 +256,39 @@
                                enable = Fields.stringToBool(isOpennetEnabled);
                        } catch (NumberFormatException e) {
                                Logger.error(this, "Invalid opennetEnabled: 
"+isOpennetEnabled, e);
-                               super.writeTemporaryRedirect(ctx, "step1", 
TOADLET_URL+"?step=1");
+                               super.writeTemporaryRedirect(ctx, "step1", 
TOADLET_URL+"?step="+WIZARD_STEP.OPENNET);
                                return;
                        }
                        try {
                                config.get("node.opennet").set("enabled", 
enable);
                        } catch (InvalidConfigValueException e) {
-                               Logger.error(this, "Should not happen setting 
opennet.enabled="+enable+" please repot: "+e, e);
-                               super.writeTemporaryRedirect(ctx, "step1", 
TOADLET_URL+"?step=1");
+                               Logger.error(this, "Should not happen setting 
opennet.enabled=" + enable + " please report: " + e, e);
+                               super.writeTemporaryRedirect(ctx, "step1", 
TOADLET_URL+"?step="+WIZARD_STEP.OPENNET);
                                return;
+                       } catch (NodeNeedRestartException e) {
+                               Logger.error(this, "Should not happen setting 
opennet.enabled=" + enable + " please report: " + e, e);
+                               super.writeTemporaryRedirect(ctx, "step1", 
TOADLET_URL + "?step=" + WIZARD_STEP.OPENNET);
+                               return;
                        }
-                       super.writeTemporaryRedirect(ctx, "step1", 
TOADLET_URL+"?step=2");
+                       super.writeTemporaryRedirect(ctx, "step1", 
TOADLET_URL+"?step="+WIZARD_STEP.NAME_SELECTION+"&opennet="+enable);
                        return;
                } else if(request.isPartSet("nnameF")) {
                        String selectedNName = request.getPartAsString("nname", 
128);
-                       
                        try {
                                config.get("node").set("name", selectedNName);
                                Logger.normal(this, "The node name has been set 
to "+ selectedNName);
-                       } catch (InvalidConfigValueException e) {
+                       } catch (ConfigException e) {
                                Logger.error(this, "Should not happen, please 
report!" + e, e);
                        }
-                       super.writeTemporaryRedirect(ctx, "step3", 
TOADLET_URL+"?step=3");
+                       super.writeTemporaryRedirect(ctx, "step3", 
TOADLET_URL+"?step="+WIZARD_STEP.BANDWIDTH);
                        return;
                } else if(request.isPartSet("bwF")) {
-                       String selectedUploadSpeed 
=request.getPartAsString("bw", 6);
-                       
-                       try {
-                               config.get("node").set("outputBandwidthLimit", 
selectedUploadSpeed);
-                               Logger.normal(this, "The outputBandwidthLimit 
has been set to "+ selectedUploadSpeed);
-                       } catch (InvalidConfigValueException e) {
-                               Logger.error(this, "Should not happen, please 
report!" + e, e);
-                       }
-                       super.writeTemporaryRedirect(ctx, "step4", 
TOADLET_URL+"?step=4");
+                       
_setUpstreamBandwidthLimit(request.getPartAsString("bw", 6));
+                       super.writeTemporaryRedirect(ctx, "step4", 
TOADLET_URL+"?step="+WIZARD_STEP.DATASTORE_SIZE);
                        return;
                } else if(request.isPartSet("dsF")) {
-                       String selectedStoreSize =request.getPartAsString("ds", 
6);
-                       
-                       try {
-                               config.get("node").set("storeSize", 
selectedStoreSize);
-                               Logger.normal(this, "The storeSize has been set 
to "+ selectedStoreSize);
-                       } catch (InvalidConfigValueException e) {
-                               Logger.error(this, "Should not happen, please 
report!" + e, e);
-                       }
-                       boolean canDoStepSix = 
WrapperConfig.canChangeProperties();
-                       super.writeTemporaryRedirect(ctx, "step5", 
TOADLET_URL+"?step="+(canDoStepSix?"6":"7"));
+                       _setDatastoreSize(request.getPartAsString("ds", 6));
+                       super.writeTemporaryRedirect(ctx, "step5", 
TOADLET_URL+"?step="+WIZARD_STEP.MEMORY);
                        return;
                } else if(request.isPartSet("memoryF")) {
                        String selectedMemorySize = 
request.getPartAsString("memoryF", 6);
@@ -327,7 +297,7 @@
                        if(memorySize >= 0) {
                                
WrapperConfig.setWrapperProperty("wrapper.java.maxmemory", selectedMemorySize);
                        }
-                       super.writeTemporaryRedirect(ctx, "step5", 
TOADLET_URL+"?step=7");
+                       super.writeTemporaryRedirect(ctx, "step6", 
TOADLET_URL+"?step="+WIZARD_STEP.CONGRATZ);
                        return;
                }

@@ -341,4 +311,99 @@
        public String supportedMethods() {
                return "GET, POST";
        }
+       
+       private void _setDatastoreSize(String selectedStoreSize) {
+               try {
+                       config.get("node").set("storeSize", selectedStoreSize);
+                       Logger.normal(this, "The storeSize has been set to " + 
selectedStoreSize);
+               } catch(ConfigException e) {
+                       Logger.error(this, "Should not happen, please report!" 
+ e, e);
+               }
+       }
+       
+       private void _setUpstreamBandwidthLimit(String selectedUploadSpeed) {
+               try {
+                       config.get("node").set("outputBandwidthLimit", 
selectedUploadSpeed);
+                       Logger.normal(this, "The outputBandwidthLimit has been 
set to " + selectedUploadSpeed);
+               } catch (ConfigException e) {
+                       Logger.error(this, "Should not happen, please report!" 
+ e, e);
+               }
+       }
+       
+       private void _setDownstreamBandwidthLimit(String selectedDownloadSpeed) 
{
+               try {
+                       config.get("node").set("inputBandwidthLimit", 
selectedDownloadSpeed);
+                       Logger.normal(this, "The inputBandwidthLimit has been 
set to " + selectedDownloadSpeed);
+               } catch(ConfigException e) {
+                       Logger.error(this, "Should not happen, please report!" 
+ e, e);
+               }
+       }
+       
+       private boolean canAutoconfigureBandwidth() {
+               FredPluginBandwidthIndicator bwIndicator = 
core.node.ipDetector.getBandwidthIndicator();
+               if(bwIndicator == null)
+                       return false;
+               
+               int downstreamBWLimit = bwIndicator.getDownstreamMaxBitRate();
+               if(downstreamBWLimit > 0) {
+                       int bytes = (downstreamBWLimit / 8) - 1;
+                       String downstreamBWLimitString = 
SizeUtil.formatSize(bytes * 2 / 3);
+                       _setDownstreamBandwidthLimit(downstreamBWLimitString);
+                       Logger.normal(this, "The node has a bandwidthIndicator: 
it has reported downstream=" + downstreamBWLimit + "bits/sec... we will use " + 
downstreamBWLimitString + " and skip the bandwidth selection step of the 
wizard.");
+               }
+               
+               // We don't mind if the downstreamBWLimit couldn't be set, but 
upstreamBWLimit is important
+               int upstreamBWLimit = bwIndicator.getUpstramMaxBitRate();
+               if(upstreamBWLimit > 0) {
+                       int bytes = (upstreamBWLimit / 8) - 1;
+                       String upstreamBWLimitString = (bytes < 16384 ? "8K" : 
SizeUtil.formatSize(bytes / 2));
+                       _setUpstreamBandwidthLimit(upstreamBWLimitString);
+                       Logger.normal(this, "The node has a bandwidthIndicator: 
it has reported upstream=" + upstreamBWLimit + "bits/sec... we will use " + 
upstreamBWLimitString + " and skip the bandwidth selection step of the 
wizard.");
+                       return true;
+               }else
+                       return false;
+       }
+       
+       private boolean canAutoconfigureDatastoreSize() {
+               // Use JNI to find out the free space on this partition.
+               long freeSpace = -1;
+               File dir = FileUtil.getCanonicalFile(core.node.getNodeDir());
+               try {
+                       Class c = dir.getClass();
+                       Method m = c.getDeclaredMethod("getFreeSpace", new 
Class[0]);
+                       if(m != null) {
+                               Long lFreeSpace = (Long) m.invoke(dir, new 
Object[0]);
+                               if(lFreeSpace != null) {
+                                       freeSpace = lFreeSpace.longValue();
+                                       System.err.println("Found free space on 
node's partition: on " + dir + " = " + SizeUtil.formatSize(freeSpace));
+                               }
+                       }
+               } catch(NoSuchMethodException e) {
+                       // Ignore
+                       freeSpace = -1;
+               } catch(Throwable t) {
+                       System.err.println("Trying to access 1.6 
getFreeSpace(), caught " + t);
+                       freeSpace = -1;
+               }
+               
+               if(freeSpace <= 0)
+                       return false;
+               else {
+                       String shortSize = null;
+                       if(freeSpace / 20 > 1024 * 1024 * 1024) {
+                               // If 20GB+ free, 5% of available disk space.
+                               shortSize = SizeUtil.formatSize(freeSpace / 20);
+                       }else if(freeSpace / 10 > 1024 * 1024 * 1024) {
+                               // If 10GB+ free, 10% of available disk space.
+                               shortSize = SizeUtil.formatSize(freeSpace / 10);
+                       }else if(freeSpace / 5 > 1024 * 1024 * 1024) {
+                               // If 5GB+ free, default to 512MB
+                               shortSize = "512MB";
+                       }else
+                               shortSize = "256MB";
+                       
+                       _setDatastoreSize(shortSize);
+                       return true;
+               }
+       }
 }

Modified: branches/db4o/freenet/src/freenet/clients/http/HTTPRequestImpl.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/HTTPRequestImpl.java 
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/HTTPRequestImpl.java 
2008-09-24 20:42:20 UTC (rev 22823)
@@ -3,6 +3,7 @@
  * 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;
@@ -619,7 +620,7 @@
                }
                String value = this.getParameterValue(name);
                try {
-                       return Long.parseLong(value);
+                       return Fields.parseLong(value);
                } catch (NumberFormatException e) {
                        return defaultValue;
                }

Modified: branches/db4o/freenet/src/freenet/clients/http/PageMaker.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/PageMaker.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/PageMaker.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -202,11 +202,11 @@
         * 
         * @return An {@link ArrayList} containing the names of all available 
themes
         */
-       public List getThemes() {
+       public List<String> getThemes() {
                if (jarThemesCache != null) {
                        return jarThemesCache;
                }
-               List themes = new ArrayList();
+               List<String> themes = new ArrayList<String>();
                try {
                        URL url = getClass().getResource("staticfiles/themes/");
                        URLConnection urlConnection = url.openConnection();

Deleted: branches/db4o/freenet/src/freenet/clients/http/PluginToadlet.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/PluginToadlet.java   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/PluginToadlet.java   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -1,295 +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.clients.http;
-
-import java.io.IOException;
-import java.net.URI;
-
-import freenet.client.HighLevelSimpleClient;
-import freenet.l10n.L10n;
-import freenet.node.NodeClientCore;
-import freenet.oldplugins.plugin.HttpPlugin;
-import freenet.oldplugins.plugin.Plugin;
-import freenet.oldplugins.plugin.PluginManager;
-import freenet.support.HTMLNode;
-import freenet.support.MultiValueTable;
-import freenet.support.api.HTTPRequest;
-
-/**
- * Toadlet for the plugin manager.
- * 
- * @author David 'Bombe' Roden &lt;bombe at freenetproject.org&gt;
- * @version $Id$
- */
-public class PluginToadlet extends Toadlet {
-
-       private static final int MAX_PLUGIN_NAME_LENGTH = 1024;
-       /** The plugin manager backing this toadlet. */
-       private final PluginManager pluginManager;
-       private final NodeClientCore core;
-
-       /**
-        * Creates a new toadlet.
-        * 
-        * @param client
-        *            The high-level client to use
-        * @param pluginManager
-        *            The plugin manager to use
-        */
-       protected PluginToadlet(HighLevelSimpleClient client, PluginManager 
pluginManager, NodeClientCore core) {
-               super(client);
-               this.pluginManager = pluginManager;
-               this.core = core;
-       }
-
-       /**
-        * This toadlet support GET and POST operations.
-        * 
-        * @see freenet.clients.http.Toadlet#supportedMethods()
-        * @return "GET,POST"
-        */
-       public String supportedMethods() {
-               return "GET,POST";
-       }
-
-       /**
-        * Handles a GET request.
-        * 
-        * @see freenet.clients.http.Toadlet#handleGet(java.net.URI,
-        *      freenet.clients.http.ToadletContext)
-        * @param uri
-        *            The URI that was requested
-        * @param ctx
-        *            The context of this toadlet
-        */
-       public void handleGet(URI uri, HTTPRequest httpRequest, ToadletContext 
ctx) throws ToadletContextClosedException, IOException, RedirectException {
-               String uriPath = uri.getPath();
-               String pluginName = uriPath.substring(uriPath.lastIndexOf('/') 
+ 1);
-
-               if (pluginName.length() > 0) {
-                       Plugin plugin = findPlugin(pluginName);
-                       if (plugin != null) {
-                               if (plugin instanceof HttpPlugin) {
-                                       ((HttpPlugin) 
plugin).handleGet(httpRequest, ctx);
-                               } else {
-                                       writeHTMLReply(ctx, 220, "OK", 
createBox(ctx, l10n("noWebInterfaceTitle"), l10n("noWebInterface")).toString());
-                               }
-                               return;
-                       }
-                       writeHTMLReply(ctx, 220, "OK", createBox(ctx, 
l10n("pluginNotFoundTitle"), l10n("pluginNotFound")).toString());
-                       return;
-               }
-
-               if(!ctx.isAllowedFullAccess()) {
-                       super.sendErrorPage(ctx, 403, "Unauthorized", 
l10n("unauthorized"));
-                       return;
-               }
-               
-               String action = httpRequest.getParam("action");
-               if (action.length() == 0) {
-                       writePermanentRedirect(ctx, "Plugin list", 
"?action=list");
-                       return;
-               }
-
-               StringBuffer replyBuffer = new StringBuffer();
-               if ("list".equals(action)) {
-                       replyBuffer.append(listPlugins(ctx));
-               } else {
-                       writeHTMLReply(ctx, 220, "OK", createBox(ctx, 
l10n("unsupportedMethodTitle"), l10n("unsupportedMethod")).toString());
-                       return;
-               }
-               writeHTMLReply(ctx, 220, "OK", replyBuffer.toString());
-       }
-       
-       private String l10n(String key) {
-               return L10n.getString("PluginToadlet."+key);
-       }
-
-       /**
-        * @see freenet.clients.http.Toadlet#handlePost(java.net.URI, 
freenet.support.api.Bucket, freenet.clients.http.ToadletContext)
-        */
-       public void handlePost(URI uri, HTTPRequest httpRequest, ToadletContext 
ctx) throws ToadletContextClosedException, IOException, RedirectException {
-               String uriPath = uri.getPath();
-               String pluginName = uriPath.substring(uriPath.lastIndexOf('/') 
+ 1);
-               
-               if (pluginName.length() > 0) {
-                       Plugin plugin = findPlugin(pluginName);
-                       if (plugin != null) {
-                               if (plugin instanceof HttpPlugin) {
-                                       ((HttpPlugin) 
plugin).handlePost(httpRequest, ctx);
-                               } else {
-                                       writeHTMLReply(ctx, 220, "OK", 
createBox(ctx, l10n("noWebInterfaceTitle"), l10n("noWebInterface")).toString());
-                               }
-                               return;
-                       }
-                       writeHTMLReply(ctx, 220, "OK", createBox(ctx, 
l10n("pluginNotFoundTitle") , l10n("pluginNotFound")).toString());
-                       return;
-               }
-               
-               if(!ctx.isAllowedFullAccess()) {
-                       super.sendErrorPage(ctx, 403, "Unauthorized", 
l10n("unauthorized"));
-                       return;
-               }
-               
-               String pass = httpRequest.getPartAsString("formPassword", 32);
-               if((pass == null) || !pass.equals(core.formPassword)) {
-                       MultiValueTable headers = new MultiValueTable();
-                       headers.put("Location", "/plugin/");
-                       ctx.sendReplyHeaders(302, "Found", headers, null, 0);
-                       return;
-               }
-               
-               String action = httpRequest.getPartAsString("action", 32);
-               if (action.length() == 0) {
-                       writePermanentRedirect(ctx, l10n("pluginList"), 
"?action=list");
-                       return;
-               }
-
-               StringBuffer replyBuffer = new StringBuffer();
-               if ("add".equals(action)) {
-                       pluginName = httpRequest.getPartAsString("pluginName", 
MAX_PLUGIN_NAME_LENGTH);
-
-                       boolean added = false;
-                       try {
-                               pluginManager.addPlugin(pluginName, true);
-                               added = true;
-                       } catch (IllegalArgumentException iae1) {
-                               super.sendErrorPage(ctx, 
l10n("failedToLoadPluginTitle"), l10n("failedToLoadPlugin"), iae1);
-                               return;
-                       }
-                       if (added) {
-                               writePermanentRedirect(ctx, l10n("pluginList"), 
"?action=list");
-                               return;
-                       }
-                       replyBuffer.append(createBox(ctx, 
l10n("failedToLoadPluginTitle"), l10n("failedToLoadPluginCheckClass")));
-               } else if ("reload".equals(action)) {
-                       pluginName = httpRequest.getPartAsString("pluginName", 
MAX_PLUGIN_NAME_LENGTH);
-                       Plugin plugin = findPlugin(pluginName);
-                       pluginManager.removePlugin(plugin, false);
-                       pluginManager.addPlugin(plugin.getClass().getName(), 
false);
-                       writePermanentRedirect(ctx, l10n("pluginList"), 
"?action=list");
-                       return;
-               } else if ("unload".equals(action)) {
-                       pluginName = httpRequest.getPartAsString("pluginName", 
MAX_PLUGIN_NAME_LENGTH);
-                       Plugin plugin = findPlugin(pluginName);
-                       pluginManager.removePlugin(plugin, true);
-                       writePermanentRedirect(ctx, l10n("pluginList"), 
"?action=list");
-                       return;
-               }
-               writeHTMLReply(ctx, 220, "OK", replyBuffer.toString());
-       }
-
-       /**
-        * Searches the currently installed plugins for the plugin with the
-        * specified internal name.
-        * 
-        * @param internalPluginName
-        *            The internal name of the wanted plugin
-        * @return The wanted plugin, or <code>null</code> if no plugin could be
-        *         found
-        */
-       private Plugin findPlugin(String internalPluginName) {
-               Plugin[] plugins = pluginManager.getPlugins();
-               for (int pluginIndex = 0, pluginCount = plugins.length; 
pluginIndex < pluginCount; pluginIndex++) {
-                       Plugin plugin = plugins[pluginIndex];
-                       String pluginName = plugin.getClass().getName() + '@' + 
pluginIndex;
-                       if (pluginName.equals(internalPluginName)) {
-                               return plugin;
-                       }
-               }
-               return null;
-       }
-
-       /**
-        * Creates a complete HTML page containing a list of all plugins.
-        * 
-        * @param context
-        *            The toadlet context
-        * @return A StringBuffer containing the HTML page
-        */
-       private String listPlugins(ToadletContext context) {
-               Plugin[] plugins = pluginManager.getPlugins();
-               PageMaker pageMaker = context.getPageMaker();
-               HTMLNode pageNode = pageMaker.getPageNode( 
l10n("pluginListTitle"), context);
-               HTMLNode contentNode = pageMaker.getContentNode(pageNode);
-
-               HTMLNode infobox = contentNode.addChild("div", "class", 
"infobox");
-               infobox.addChild("div", "class", "infobox-header", 
l10n("pluginList"));
-               HTMLNode table = infobox.addChild("div", "class", 
"infobox-content").addChild("table", "class", "plugintable");
-               HTMLNode headerRow = table.addChild("tr");
-               headerRow.addChild("th", l10n("pluginNameTitle"));
-               headerRow.addChild("th", l10n("internalNameTitle"));
-               headerRow.addChild("th", "colspan", "3");
-               for (int pluginIndex = 0, pluginCount = plugins.length; 
pluginIndex < pluginCount; pluginIndex++) {
-                       Plugin plugin = plugins[pluginIndex];
-                       String internalName = plugin.getClass().getName() + '@' 
+ pluginIndex;
-                       HTMLNode tableRow = table.addChild("tr");
-                       tableRow.addChild("td", plugin.getPluginName());
-                       tableRow.addChild("td", internalName);
-                       if (plugin instanceof HttpPlugin) {
-                               tableRow.addChild("td").addChild("form", new 
String[] { "action", "method", "target" }, new String[] { internalName, "get", 
"_new" }).addChild("div").addChild("input", new String[] { "type", "value" }, 
new String[] { "submit", l10n("visit") });
-                       } else {
-                               tableRow.addChild("td");
-                       }
-                       HTMLNode reloadForm = context.addFormChild(tableRow, 
".", "pluginReloadForm"); 
-                       reloadForm.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "hidden", "action", "reload" });
-                       reloadForm.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "hidden", "pluginName", internalName });
-                       reloadForm.addChild("input", new String[] { "type", 
"value" }, new String[] { "submit", "Reload" });
-                       HTMLNode unloadForm = context.addFormChild(tableRow, 
".", "pluginUnloadForm");
-                       unloadForm.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "hidden", "action", "unload" });
-                       unloadForm.addChild("input", new String[] { "type", 
"name", "value" }, new String[] { "hidden", "pluginName", internalName });
-                       unloadForm.addChild("input", new String[] { "type", 
"value" }, new String[] { "submit", "Unload" });
-               }
-
-               contentNode.addChild(createAddPluginBox(context));
-
-               return pageNode.generate();
-       }
-
-       /**
-        * Creates an alert box with the specified title and message. A link to 
the
-        * plugin list is added after the message.
-        * 
-        * @param context
-        *            The toadlet context
-        * @param title
-        *            The title of the box
-        * @param message
-        *            The content of the box
-        * @return A StringBuffer containing the complete page
-        */
-       private StringBuffer createBox(ToadletContext context, String title, 
String message) {
-               PageMaker pageMaker = context.getPageMaker();
-               HTMLNode pageNode = pageMaker.getPageNode(title, context);
-               HTMLNode contentNode = pageMaker.getContentNode(pageNode);
-               HTMLNode infobox = contentNode.addChild("div", "class", 
"infobox infobox-alert");
-               infobox.addChild("div", "class", "infobox-header", title);
-               HTMLNode infoboxContent = infobox.addChild("div", "class", 
"infobox-content");
-               infoboxContent.addChild("#", message);
-               infoboxContent.addChild("br");
-               L10n.addL10nSubstitution(infoboxContent, 
"PluginToadlet.returnToPluginsWithLinks", new String[] { "link", "/link" }, 
-                               new String[] { "<a href=\"?action=list\">", 
"</a>" });
-               StringBuffer pageBuffer = new StringBuffer();
-               pageNode.generate(pageBuffer);
-               return pageBuffer;
-       }
-
-       /**
-        * Appends the HTML code for the &ldquo;add plugin&rdquo; box to the 
given
-        * StringBuffer.
-        * 
-        * @param outputBuffer
-        *            The StringBuffer to append the HTML code to
-        */
-       private HTMLNode createAddPluginBox(ToadletContext ctx) {
-               HTMLNode addPluginBox = new HTMLNode("div", "class", "infobox");
-               addPluginBox.addChild("div", "class", "infobox-header", 
l10n("addPluginTitle"));
-               HTMLNode addForm = 
ctx.addFormChild(addPluginBox.addChild("div", "class", "infobox-content"), ".", 
"addPluginBox");
-               addForm.addChild("input", new String[] { "type", "name", 
"value" }, new String[] { "hidden", "action", "add" });
-               addForm.addChild("input", new String[] { "type", "name", 
"value", "size" }, new String[] { "text", "pluginName", "", "40" });
-               addForm.addChild("input", new String[] { "type", "value" }, new 
String[] { "submit", l10n("loadPluginCommand")});
-               return addPluginBox;
-       }
-
-}

Modified: branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java    
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java    
2008-09-24 20:42:20 UTC (rev 22823)
@@ -296,7 +296,7 @@
                                else
                                        fnam = null;
                                /* copy bucket data */
-                               Bucket copiedBucket = 
core.persistentEncryptedTempBucketFactory.makeBucket(file.getData().size());
+                               Bucket copiedBucket = 
core.persistentTempBucketFactory.makeBucket(file.getData().size());
                                BucketTools.copy(file.getData(), copiedBucket);
                                final ClientPut clientPut;
                                try {

Modified: 
branches/db4o/freenet/src/freenet/clients/http/SimpleToadletServer.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/SimpleToadletServer.java     
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/SimpleToadletServer.java     
2008-09-24 20:42:20 UTC (rev 22823)
@@ -38,10 +38,10 @@
 import freenet.support.HTMLNode;
 import freenet.support.Logger;
 import freenet.support.OOMHandler;
-import freenet.support.StringArray;
 import freenet.support.api.BooleanCallback;
 import freenet.support.api.BucketFactory;
 import freenet.support.api.IntCallback;
+import freenet.support.api.LongCallback;
 import freenet.support.api.StringCallback;
 import freenet.support.io.ArrayBucketFactory;

@@ -80,12 +80,12 @@
        static boolean isPanicButtonToBeShown;
        public static final int DEFAULT_FPROXY_PORT = 8888;

-       class FProxySSLCallback implements BooleanCallback {
+       class FProxySSLCallback extends BooleanCallback  {

-               public boolean get() {
+               public Boolean get() {
                        return ssl;
                }
-               public void set(boolean val) throws InvalidConfigValueException 
{
+               public void set(Boolean val) throws InvalidConfigValueException 
{
                        if(val == get()) return;
                        if(!SSL.available()) {
                                throw new InvalidConfigValueException("Enable 
SSL support before use ssl with Fproxy");
@@ -93,22 +93,42 @@
                        ssl = val;
                        throw new InvalidConfigValueException("Cannot change 
SSL on the fly, please restart freenet");
                }
+               @Override
+               public boolean isReadOnly() {
+                       return true;
+               }
        }
+       
+       class FProxyPassthruMaxSize extends LongCallback  {
+               
+               public Long get() {
+                       return FProxyToadlet.MAX_LENGTH;
+               }
+               
+               public void set(Long val) throws InvalidConfigValueException {
+                       if(val == get()) return;
+                       FProxyToadlet.MAX_LENGTH = val;
+               }
+       }

-       class FProxyPortCallback implements IntCallback {
+       class FProxyPortCallback extends IntCallback  {

-               public int get() {
+               public Integer get() {
                        return port;
                }

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

-       class FProxyBindtoCallback implements StringCallback {
+       class FProxyBindtoCallback extends StringCallback  {

                public String get() {
                        return bindTo;
@@ -129,7 +149,7 @@
                }
        }

-       class FProxyAllowedHostsCallback implements StringCallback {
+       class FProxyAllowedHostsCallback extends StringCallback  {

                public String get() {
                        return networkInterface.getAllowedHosts();
@@ -140,10 +160,9 @@
                                networkInterface.setAllowedHosts(allowedHosts);
                        }
                }
-               
        }

-       class FProxyCSSNameCallback implements StringCallback, 
EnumerableOptionCallback {
+       class FProxyCSSNameCallback extends StringCallback implements 
EnumerableOptionCallback {

                public String get() {
                        return cssName;
@@ -161,11 +180,11 @@
                }

                public String[] getPossibleValues() {
-                       return 
StringArray.toArray(pageMaker.getThemes().toArray());
+                       return pageMaker.getThemes().toArray(new String[0]);
                }
        }

-       class FProxyCSSOverrideCallback implements StringCallback {
+       class FProxyCSSOverrideCallback extends StringCallback  {

                public String get() {
                        return (cssOverride == null ? "" : 
cssOverride.toString());
@@ -187,14 +206,14 @@
                }
        }

-       class FProxyEnabledCallback implements BooleanCallback {
+       class FProxyEnabledCallback extends BooleanCallback  {

-               public boolean get() {
+               public Boolean get() {
                        synchronized(SimpleToadletServer.this) {
                                return myThread != null;
                        }
                }
-               public void set(boolean val) throws InvalidConfigValueException 
{
+               public void set(Boolean val) throws InvalidConfigValueException 
{
                        if(val == get()) return;
                        synchronized(SimpleToadletServer.this) {
                                if(val) {
@@ -229,7 +248,7 @@
                }
        }

-       private static class FProxyAdvancedModeEnabledCallback implements 
BooleanCallback {
+       private static class FProxyAdvancedModeEnabledCallback extends 
BooleanCallback  {

                private final SimpleToadletServer ts;

@@ -237,17 +256,17 @@
                        this.ts = ts;
                }

-               public boolean get() {
+               public Boolean get() {
                        return ts.isAdvancedModeEnabled();
                }

-               public void set(boolean val) throws InvalidConfigValueException 
{
+               public void set(Boolean val) throws InvalidConfigValueException 
{
                        if(val == get()) return;
                                ts.enableAdvancedMode(val);
                }
        }

-       private static class FProxyJavascriptEnabledCallback implements 
BooleanCallback {
+       private static class FProxyJavascriptEnabledCallback extends 
BooleanCallback  {

                private final SimpleToadletServer ts;

@@ -255,11 +274,11 @@
                        this.ts = ts;
                }

-               public boolean get() {
+               public Boolean get() {
                        return ts.isFProxyJavascriptEnabled();
                }

-               public void set(boolean val) throws InvalidConfigValueException 
{
+               public void set(Boolean val) throws InvalidConfigValueException 
{
                        if(val == get()) return;
                                ts.enableFProxyJavascript(val);
                }
@@ -340,11 +359,11 @@
                                new FProxyJavascriptEnabledCallback(this));
                fproxyConfig.register("showPanicButton", false, 
configItemOrder++, true, true, "SimpleToadletServer.panicButton", 
"SimpleToadletServer.panicButtonLong",
                                new BooleanCallback(){
-                               public boolean get(){
+                               public Boolean get() {
                                        return 
SimpleToadletServer.isPanicButtonToBeShown;
                                }

-                               public void set(boolean value){
+                               public void set(Boolean value) {
                                        if(value == 
SimpleToadletServer.isPanicButtonToBeShown) return;
                                        else    
SimpleToadletServer.isPanicButtonToBeShown = value;
                                }
@@ -358,13 +377,13 @@
                fproxyConfig.register("enablePersistentConnections", false, 
configItemOrder++, true, false, 
"SimpleToadletServer.enablePersistentConnections", 
"SimpleToadletServer.enablePersistentConnectionsLong",
                                new BooleanCallback() {

-                                       public boolean get() {
+                                       public Boolean get() {
                                                
synchronized(SimpleToadletServer.this) {
                                                        return 
enablePersistentConnections;
                                                }
                                        }

-                                       public void set(boolean val) throws 
InvalidConfigValueException {
+                                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                                
synchronized(SimpleToadletServer.this) {
                                                        
enablePersistentConnections = val;
                                                }
@@ -381,13 +400,13 @@
                fproxyConfig.register("enableInlinePrefetch", false, 
configItemOrder++, true, false, "SimpleToadletServer.enableInlinePrefetch", 
"SimpleToadletServer.enableInlinePrefetchLong",
                                new BooleanCallback() {

-                                       public boolean get() {
+                                       public Boolean get() {
                                                
synchronized(SimpleToadletServer.this) {
                                                        return 
enableInlinePrefetch;
                                                }
                                        }

-                                       public void set(boolean val) throws 
InvalidConfigValueException {
+                                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                                
synchronized(SimpleToadletServer.this) {
                                                        enableInlinePrefetch = 
val;
                                                }
@@ -395,6 +414,9 @@
                });
                enableInlinePrefetch = 
fproxyConfig.getBoolean("enableInlinePrefetch");

+               fproxyConfig.register("passthroughMaxSize", 2L*1024*1024, 
configItemOrder++, true, false, "SimpleToadletServer.passthroughMaxSize", 
"SimpleToadletServer.passthroughMaxSizeLong", new FProxyPassthruMaxSize());
+               FProxyToadlet.MAX_LENGTH = 
fproxyConfig.getLong("passthroughMaxSize");
+               
                fproxyConfig.register("allowedHosts", 
"127.0.0.1,0:0:0:0:0:0:0:1", configItemOrder++, true, true, 
"SimpleToadletServer.allowedHosts", "SimpleToadletServer.allowedHostsLong",
                                new FProxyAllowedHostsCallback());
                fproxyConfig.register("allowedHostsFullAccess", 
"127.0.0.1,0:0:0:0:0:0:0:1", configItemOrder++, true, true, 
"SimpleToadletServer.allowedFullAccess", 
@@ -413,10 +435,10 @@
                allowedFullAccess = new 
AllowedHosts(fproxyConfig.getString("allowedHostsFullAccess"));
                fproxyConfig.register("doRobots", false, configItemOrder++, 
true, false, "SimpleToadletServer.doRobots", "SimpleToadletServer.doRobotsLong",
                                new BooleanCallback() {
-                                       public boolean get() {
+                                       public Boolean get() {
                                                return doRobots;
                                        }
-                                       public void set(boolean val) throws 
InvalidConfigValueException {
+                                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                                doRobots = val;
                                        }
                });

Modified: branches/db4o/freenet/src/freenet/clients/http/StatisticsToadlet.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/StatisticsToadlet.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/StatisticsToadlet.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -119,6 +119,7 @@
                return count;
        }

+       @Override
        public void handleGet(URI uri, HTTPRequest request, ToadletContext ctx) 
throws ToadletContextClosedException, IOException, RedirectException {

                if(!ctx.isAllowedFullAccess()) {
@@ -348,25 +349,15 @@
                        int[] outgoingLocalRequestCountArray = new int[1];
                        int[] outgoingLocalRequestLocation = 
stats.getOutgoingLocalRequestLocation(outgoingLocalRequestCountArray);
                        int outgoingLocalRequestsCount = 
outgoingLocalRequestCountArray[0];
-                       
-                       if(outgoingLocalRequestsCount > 0) {
-                               HTMLNode nodeSpecialisationInfobox = 
nextTableCell.addChild("div", "class", "infobox");
-                               nodeSpecialisationInfobox.addChild("div", 
"class", "infobox-header", 
"Outgoing\u00a0Local\u00a0Request\u00a0Distribution");
-                               HTMLNode nodeSpecialisationTable = 
nodeSpecialisationInfobox.addChild("div", "class", 
"infobox-content").addChild("table");
-                               addSpecialisation(nodeSpecialisationTable, 
myLocation, outgoingLocalRequestsCount, outgoingLocalRequestLocation);
-                       }
-                       
-                       overviewTableRow = overviewTable.addChild("tr");
-                       nextTableCell = overviewTableRow.addChild("td", 
"class", "first");
                        int[] outgoingRequestCountArray = new int[1];
                        int[] outgoingRequestLocation = 
stats.getOutgoingRequestLocation(outgoingRequestCountArray);
                        int outgoingRequestsCount = 
outgoingRequestCountArray[0];

-                       if(outgoingRequestsCount > 0) {
+                       if(outgoingLocalRequestsCount > 0 && 
outgoingRequestsCount > 0) {
                                HTMLNode nodeSpecialisationInfobox = 
nextTableCell.addChild("div", "class", "infobox");
                                nodeSpecialisationInfobox.addChild("div", 
"class", "infobox-header", "Outgoing\u00a0Request\u00a0Distribution");
                                HTMLNode nodeSpecialisationTable = 
nodeSpecialisationInfobox.addChild("div", "class", 
"infobox-content").addChild("table");
-                               addSpecialisation(nodeSpecialisationTable, 
myLocation, outgoingRequestsCount, outgoingRequestLocation);
+                               
addCombinedSpecialisation(nodeSpecialisationTable, myLocation, 
outgoingLocalRequestsCount, outgoingLocalRequestLocation, 
outgoingRequestsCount, outgoingRequestLocation);
                        }
                }

@@ -680,13 +671,13 @@
                        locationSwapList.addChild("li", 
"locChangePerSwap:\u00a0" + fix1p6sci.format(locChangeSession/swaps));
                }
                if ((swaps > 0.0) && (nodeUptimeSeconds >= 60)) {
-                       locationSwapList.addChild("li", 
"locChangePerMinute:\u00a0" + 
fix1p6sci.format(locChangeSession/(double)(nodeUptimeSeconds/60.0)));
+                       locationSwapList.addChild("li", 
"locChangePerMinute:\u00a0" + 
fix1p6sci.format(locChangeSession/(nodeUptimeSeconds/60.0)));
                }
                if ((swaps > 0.0) && (nodeUptimeSeconds >= 60)) {
-                       locationSwapList.addChild("li", "swapsPerMinute:\u00a0" 
+ fix1p6sci.format(swaps/(double)(nodeUptimeSeconds/60.0)));
+                       locationSwapList.addChild("li", "swapsPerMinute:\u00a0" 
+ fix1p6sci.format(swaps/(nodeUptimeSeconds/60.0)));
                }
                if ((noSwaps > 0.0) && (nodeUptimeSeconds >= 60)) {
-                       locationSwapList.addChild("li", 
"noSwapsPerMinute:\u00a0" + 
fix1p6sci.format(noSwaps/(double)(nodeUptimeSeconds/60.0)));
+                       locationSwapList.addChild("li", 
"noSwapsPerMinute:\u00a0" + fix1p6sci.format(noSwaps/(nodeUptimeSeconds/60.0)));
                }
                if ((swaps > 0.0) && (noSwaps > 0.0)) {
                        locationSwapList.addChild("li", 
"swapsPerNoSwaps:\u00a0" + fix1p6sci.format(swaps/noSwaps));
@@ -1024,6 +1015,7 @@
                overviewList.addChild("li", "backedOffPercent:\u00a0" + 
fix3p1pct.format(backedOffPercent));
                overviewList.addChild("li", "pInstantReject:\u00a0" + 
fix3p1pct.format(stats.pRejectIncomingInstantly()));
                overviewList.addChild("li", "unclaimedFIFOSize:\u00a0" + 
node.getUnclaimedFIFOSize());
+               overviewList.addChild("li", "RAMBucketPoolSize:\u00a0" + 
SizeUtil.formatSize(core.tempBucketFactory.getRamUsed())+ " / "+ 
SizeUtil.formatSize(core.tempBucketFactory.getMaxRamUsed()));
                overviewList.addChild("li", "uptimeAverage:\u00a0" + 
fix3p1pct.format(node.uptime.getUptime()));

        }
@@ -1141,6 +1133,7 @@
                        strength = 1 - ((double) age / MAX_CIRCLE_AGE_THRESHOLD 
);
                        histogramIndex = (int) 
(Math.floor(location.doubleValue() * HISTOGRAM_LENGTH));
                        histogram[histogramIndex]++;
+                       
                        nodeCircleInfoboxContent.addChild("span", new String[] 
{ "style", "class" }, new String[] { 
generatePeerCircleStyleString(location.doubleValue(), false, strength), 
"connected" }, "x");
                }
                nodeCircleInfoboxContent.addChild("span", new String[] { 
"style", "class" }, new String[] { generatePeerCircleStyleString(myLocation, 
true, 1.0), "me" }, "x");
@@ -1150,9 +1143,10 @@
                        nodeHistogramLegendCell = 
nodeHistogramLegendTableRow.addChild("td");
                        nodeHistogramGraphCell = 
nodeHistogramGraphTableRow.addChild("td", "style", "height: 100px;");
                        nodeHistogramLegendCell.addChild("div", "class", 
"histogramLabel").addChild("#", fix1p1.format(((double) i) / HISTOGRAM_LENGTH 
));
-                       //
                        histogramPercent = ((double) histogram[ i ] ) / 
nodeCount;
-                       nodeHistogramGraphCell.addChild("div", new String[] { 
"class", "style" }, new String[] { "histogramConnected", "height: " + 
fix3pctUS.format(histogramPercent) + "; width: 100%;" }, "\u00a0");
+                       
+                       // Don't use HTMLNode here to speed things up
+                       nodeHistogramGraphCell.addChild("%", "<div 
class=\"histogramConnected\" style=\"height: " + 
fix3pctUS.format(histogramPercent) + "; width: 100%;\">\u00a0</div>");
                }
        }

@@ -1169,8 +1163,34 @@
                        nodeHistogramGraphCell2.addChild("#", 
fix1p1.format(((double) i) / incomingRequestLocation.length ));
                        nodeHistogramGraphCell.addChild("div", new String[] { 
"class", "style" }, new String[] { "histogramConnected", "height: " + 
fix3pctUS.format(((double)incomingRequestLocation[i]) / incomingRequestsCount) 
+ "; width: 100%;" }, "\u00a0");
                }
-
        }
+       
+       private void addCombinedSpecialisation(HTMLNode table, double 
peerLocation, int locallyOriginatingRequestsCount, int[] 
locallyOriginatingRequests, int remotelyOriginatingRequestsCount, int[] 
remotelyOriginatingRequests) {
+               assert(locallyOriginatingRequests.length == 
remotelyOriginatingRequests.length);
+               HTMLNode nodeHistogramLegendTableRow = table.addChild("tr");
+               HTMLNode nodeHistogramGraphTableRow = table.addChild("tr");
+               int myIndex = (int)(peerLocation * 
locallyOriginatingRequests.length);
+               for (int i = 0; i<locallyOriginatingRequests.length; i++) {
+                       HTMLNode nodeHistogramLegendCell = 
nodeHistogramLegendTableRow.addChild("td");
+                       HTMLNode nodeHistogramGraphCell = 
nodeHistogramGraphTableRow.addChild("td", "style", "height: 100px;");
+                       HTMLNode nodeHistogramGraphCell2 = 
nodeHistogramLegendCell.addChild("div", "class", "histogramLabel");
+                       if(i == myIndex)
+                                nodeHistogramGraphCell2 = 
nodeHistogramGraphCell2.addChild("span", "class", "me");
+                       nodeHistogramGraphCell2.addChild("#", 
fix1p1.format(((double) i) / locallyOriginatingRequests.length ));
+                       nodeHistogramGraphCell.addChild("div",
+                               new String[] { "class", "style" },
+                               new String[] { "histogramConnected", "height: " 
+
+                                       
fix3pctUS.format(((double)locallyOriginatingRequests[i]) / 
locallyOriginatingRequestsCount) +
+                                       "; width: 100%;" },
+                               "\u00a0");
+                       nodeHistogramGraphCell.addChild("div",
+                               new String[] { "class", "style" },
+                               new String[] { "histogramDisconnected", 
"height: " +
+                                       
fix3pctUS.format(((double)remotelyOriginatingRequests[i]) / 
remotelyOriginatingRequestsCount) +
+                                       "; width: 100%;" },
+                               "\u00a0");
+               }
+       }

        private void addPeerCircle (HTMLNode circleTable, PeerNodeStatus[] 
peerNodeStatuses, double myLocation) {
                int[] histogramConnected = new int[HISTOGRAM_LENGTH];

Modified: branches/db4o/freenet/src/freenet/clients/http/SymlinkerToadlet.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/SymlinkerToadlet.java        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/SymlinkerToadlet.java        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -35,6 +35,10 @@
                                // FIXME
                                throw new InvalidConfigValueException("Cannot 
set the plugins that's loaded.");
                        }
+
+                               public boolean isReadOnly() {
+                                       return true;
+                               }
                });

                String fns[] = tslconfig.getStringArr("symlinks");

Modified: branches/db4o/freenet/src/freenet/clients/http/Toadlet.java
===================================================================
--- branches/db4o/freenet/src/freenet/clients/http/Toadlet.java 2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/clients/http/Toadlet.java 2008-09-24 
20:42:20 UTC (rev 22823)
@@ -83,7 +83,7 @@
                MultiValueTable hdrtbl = new MultiValueTable();
                hdrtbl.put("Allow", this.supportedMethods());

-               StringBuffer pageBuffer = new StringBuffer();
+               StringBuilder pageBuffer = new StringBuilder();
                pageNode.generate(pageBuffer);
                toadletContext.sendReplyHeaders(405, "Operation not Supported", 
hdrtbl, "text/html; charset=utf-8", pageBuffer.length());
                
toadletContext.writeData(pageBuffer.toString().getBytes("UTF-8"));

Modified: 
branches/db4o/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java   
    2008-09-24 19:52:19 UTC (rev 22822)
+++ 
branches/db4o/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java   
    2008-09-24 20:42:20 UTC (rev 22823)
@@ -4,8 +4,6 @@
 import freenet.support.SimpleFieldSet;
 import java.util.Vector;

-import freenet.support.StringArray;
-
 public class BookmarkCategory extends Bookmark {
     public static final String NAME = "BookmarkCategory";

@@ -112,13 +110,13 @@
     }

     public String[] toStrings() {
-        return StringArray.toArray(toStrings("").toArray());
+        return toStrings("").toArray(new String[0]);
     }

     // Iternal use only

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

Modified: 
branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat
===================================================================
--- 
branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat 
    2008-09-24 19:52:19 UTC (rev 22822)
+++ 
branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat 
    2008-09-24 20:42:20 UTC (rev 22823)
@@ -7,19 +7,19 @@
 BookmarkCategory0.Content.Bookmark0.Name=The Ultimate FreeNet Index
 BookmarkCategory0.Content.Bookmark0.Description=A new one-page index with a 
menu including categories
 BookmarkCategory0.Content.Bookmark0.hasAnActivelink=true
-BookmarkCategory0.Content.Bookmark0.URI=USK at 
0I8gctpUE32CM0iQhXaYpCMvtPPGfT4pjXm01oid5Zc,3dAcn4fX2LyxO6uCnWFTx-2HKZ89uruurcKwLSCxbZ4,AQACAAE/Ultimate-Freenet-Index/25/
+BookmarkCategory0.Content.Bookmark0.URI=USK at 
0I8gctpUE32CM0iQhXaYpCMvtPPGfT4pjXm01oid5Zc,3dAcn4fX2LyxO6uCnWFTx-2HKZ89uruurcKwLSCxbZ4,AQACAAE/Ultimate-Freenet-Index/28/
 BookmarkCategory0.Content.Bookmark3.Name=Index des sites Fran?ais
 BookmarkCategory0.Content.Bookmark3.Description=A small French index with 
descriptions
 BookmarkCategory0.Content.Bookmark3.hasAnActivelink=true
-BookmarkCategory0.Content.Bookmark3.URI=USK at 
RJnh1EnvOSPwOWVRS2nyhC4eIQkKoNE5hcTv7~yY-sM,pOloLxnKWM~AL24iDMHOAvTvCqMlB-p2BO9zK96TOZA,AQACAAE/index_fr/54/
+BookmarkCategory0.Content.Bookmark3.URI=USK at 
RJnh1EnvOSPwOWVRS2nyhC4eIQkKoNE5hcTv7~yY-sM,pOloLxnKWM~AL24iDMHOAvTvCqMlB-p2BO9zK96TOZA,AQACAAE/index_fr/61/
 BookmarkCategory0.Content.Bookmark2.Name=Freenet Activelink Index (SLOW: 
graphical index, preloads all the sites, so takes *ages* to load)
 BookmarkCategory0.Content.Bookmark2.hasAnActivelink=true
 BookmarkCategory0.Content.Bookmark2.Description=A graphical freenet index 
(this will take a long time to load as it preloads the sites)
-BookmarkCategory0.Content.Bookmark2.URI=USK at 
qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index/67/
+BookmarkCategory0.Content.Bookmark2.URI=USK at 
qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index/78/
 BookmarkCategory0.Content.Bookmark1.Name=Freenet Activelink Index Text Version 
(a quick-loading non-graphical index site, no porn)
 BookmarkCategory0.Content.Bookmark1.hasAnActivelink=true
 BookmarkCategory0.Content.Bookmark1.Description=Text version of the Activelink 
Index
-BookmarkCategory0.Content.Bookmark1.URI=USK at 
qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index-text/30/
+BookmarkCategory0.Content.Bookmark1.URI=USK at 
qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index-text/39/
 BookmarkCategory1.Name=Freenet devel's flogs
 BookmarkCategory1.Content.BookmarkCategory=0
 BookmarkCategory1.Content.Bookmark=5
@@ -34,7 +34,7 @@
 BookmarkCategory1.Content.Bookmark2.Name=Bombe
 BookmarkCategory1.Content.Bookmark2.Description=Bombe's flog
 BookmarkCategory1.Content.Bookmark2.hasAnActivelink=true
-BookmarkCategory1.Content.Bookmark2.URI=USK at 
e3myoFyp5avg6WYN16ImHri6J7Nj8980Fm~aQe4EX1U,QvbWT0ImE0TwLODTl7EoJx2NBnwDxTbLTE6zkB-eGPs,AQACAAE/bombe/41/
+BookmarkCategory1.Content.Bookmark2.URI=USK at 
e3myoFyp5avg6WYN16ImHri6J7Nj8980Fm~aQe4EX1U,QvbWT0ImE0TwLODTl7EoJx2NBnwDxTbLTE6zkB-eGPs,AQACAAE/bombe/42/
 BookmarkCategory1.Content.Bookmark1.Name=Nextgen$
 BookmarkCategory1.Content.Bookmark1.Description=NextGen$' flog
 BookmarkCategory1.Content.Bookmark1.hasAnActivelink=true
@@ -49,7 +49,7 @@
 BookmarkCategory2.Content.Bookmark0.Name=Freenet Message System
 BookmarkCategory2.Content.Bookmark0.Description=The official freesite of FMS, 
a spam resistant message board system for Freenet
 BookmarkCategory2.Content.Bookmark0.hasAnActivelink=true
-BookmarkCategory2.Content.Bookmark0.URI=USK at 
0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/62/
+BookmarkCategory2.Content.Bookmark0.URI=USK at 
0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/78/
 BookmarkCategory2.Content.Bookmark1.Name=Freemail
 BookmarkCategory2.Content.Bookmark1.Description=The official site for Freemail 
- email over Freenet
 BookmarkCategory2.Content.Bookmark1.hasAnActivelink=true

Modified: 
branches/db4o/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css
===================================================================
--- 
branches/db4o/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css
   2008-09-24 19:52:19 UTC (rev 22822)
+++ 
branches/db4o/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css
   2008-09-24 20:42:20 UTC (rev 22823)
@@ -378,6 +378,10 @@
        text-align: center;
 }

+tr.darknet_connections_warning {
+       background-color: #ffff00;
+}
+
 table.sentmessagetypes {
        display: inline;
 }

Modified: branches/db4o/freenet/src/freenet/config/BooleanOption.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/BooleanOption.java 2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/BooleanOption.java 2008-09-24 
20:42:20 UTC (rev 22823)
@@ -6,65 +6,25 @@
 import freenet.l10n.L10n;
 import freenet.support.api.BooleanCallback;

-public class BooleanOption extends Option {
-       
-       final boolean defaultValue;
-       final BooleanCallback cb;
-       private boolean currentValue;
-       
+public class BooleanOption extends Option<Boolean> {
        public BooleanOption(SubConfig conf, String optionName, boolean 
defaultValue, int sortOrder, 
                        boolean expert, boolean forceWrite, String shortDesc, 
String longDesc, BooleanCallback cb) {
-               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DATA_TYPE_BOOLEAN);
+               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DataType.BOOLEAN);
                this.defaultValue = defaultValue;
-               this.cb = cb;
                this.currentValue = defaultValue;
        }

-       /** Get the current value. This is the value in use if we have finished
-        * initialization, otherwise it is the value set at startup (possibly 
the default). */
-       public boolean getValue() {
-               if(config.hasFinishedInitialization())
-                       return currentValue = cb.get();
-               else return currentValue;
-       }
-
-       public void setValue(String val) throws InvalidConfigValueException {
+       public Boolean parseString(String val) throws 
InvalidConfigValueException {
                if(val.equalsIgnoreCase("true") || val.equalsIgnoreCase("yes")) 
{
-                       set(true);
+                       return true;
                } else if(val.equalsIgnoreCase("false") || 
val.equalsIgnoreCase("no")) {
-                       set(false);
+                       return false;
                } else
                        throw new 
OptionFormatException(L10n.getString("BooleanOption.parseError", "val", val));
        }
-       
-       public void set(boolean b) throws InvalidConfigValueException {
-               cb.set(b);
-               currentValue = b;
-       }
-       
-       public String getValueString() {
-               return Boolean.toString(getValue());
-       }

-       public void setInitialValue(String val) throws 
InvalidConfigValueException {
-               if(val.equalsIgnoreCase("true") || val.equalsIgnoreCase("yes")) 
{
-                       currentValue = true;
-               } else if(val.equalsIgnoreCase("false") || 
val.equalsIgnoreCase("no")) {
-                       currentValue = false;
-               } else
-                       throw new 
OptionFormatException(L10n.getString("BooleanOption.parseError", "val", val));
+       @Override
+       protected String toString(Boolean val) {
+               return val.toString();
        }
-
-       public boolean isDefault() {
-               getValue();
-               return currentValue == defaultValue;
-       }
-       
-       public String getDefault() {
-               return Boolean.toString(defaultValue);
-       }
-
-       public void setDefault() {
-               currentValue = defaultValue;
-       }
 }

Modified: branches/db4o/freenet/src/freenet/config/Config.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/Config.java        2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/Config.java        2008-09-24 
20:42:20 UTC (rev 22823)
@@ -3,26 +3,21 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.config;

+import java.io.IOException;
 import java.util.LinkedHashMap;

 /** Global configuration object for a node. SubConfig's register here.
  * Handles writing to a file etc.
  */
 public class Config {
+       public static enum RequestType {
+               CURRENT_SETTINGS, DEFAULT_SETTINGS, SORT_ORDER, EXPERT_FLAG, 
FORCE_WRITE_FLAG, SHORT_DESCRIPTION, LONG_DESCRIPTION, DATA_TYPE
+       };

-    public static final int CONFIG_REQUEST_TYPE_CURRENT_SETTINGS = 1;
-    public static final int CONFIG_REQUEST_TYPE_DEFAULT_SETTINGS = 2;
-    public static final int CONFIG_REQUEST_TYPE_SORT_ORDER = 3;
-    public static final int CONFIG_REQUEST_TYPE_EXPERT_FLAG = 4;
-    public static final int CONFIG_REQUEST_TYPE_FORCE_WRITE_FLAG = 5;
-    public static final int CONFIG_REQUEST_TYPE_SHORT_DESCRIPTION = 6;
-    public static final int CONFIG_REQUEST_TYPE_LONG_DESCRIPTION = 7;
-    public static final int CONFIG_REQUEST_TYPE_DATA_TYPE = 8;
-
-       protected final LinkedHashMap configsByPrefix;
+       protected final LinkedHashMap<String, SubConfig> configsByPrefix;

        public Config() {
-               configsByPrefix = new LinkedHashMap();
+               configsByPrefix = new LinkedHashMap<String, SubConfig>();
        }

        public void register(SubConfig sc) {
@@ -50,10 +45,10 @@

        /** Fetch all the SubConfig's. Used by user-facing config thingies. */
        public synchronized SubConfig[] getConfigs() {
-               return (SubConfig[]) configsByPrefix.values().toArray(new 
SubConfig[configsByPrefix.size()]);
+               return configsByPrefix.values().toArray(new 
SubConfig[configsByPrefix.size()]);
        }

        public synchronized SubConfig get(String subConfig){
-               return (SubConfig)configsByPrefix.get(subConfig);
+               return configsByPrefix.get(subConfig);
        }
 }

Modified: branches/db4o/freenet/src/freenet/config/ConfigCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/ConfigCallback.java        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/ConfigCallback.java        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -3,6 +3,23 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.config;

-public interface ConfigCallback {
-       /** Nothing usefull here */
+public abstract class ConfigCallback<T> {
+       /**
+        * Get the current, used value of the config variable.
+        */
+       public abstract T get();
+
+       /**
+        * Set the config variable to a new value.
+        * 
+        * @param val
+        *            The new value.
+        * @throws InvalidConfigOptionException
+        *             If the new value is invalid for this particular option.
+        */
+       public abstract void set(T val) throws InvalidConfigValueException, 
NodeNeedRestartException;
+       
+       public boolean isReadOnly() {
+               return false;
+       } 
 }

Copied: branches/db4o/freenet/src/freenet/config/ConfigException.java (from rev 
21939, trunk/freenet/src/freenet/config/ConfigException.java)
===================================================================
--- branches/db4o/freenet/src/freenet/config/ConfigException.java               
                (rev 0)
+++ branches/db4o/freenet/src/freenet/config/ConfigException.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -0,0 +1,15 @@
+/* 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.config;
+
+/**
+ * Usefull if you want to catch all exceptions the config framework can return;
+ */
+public abstract class ConfigException extends Exception {
+       private static final long serialVersionUID = -1;
+       
+       public ConfigException(String msg) {
+               super(msg);
+       }
+}
\ No newline at end of file

Modified: branches/db4o/freenet/src/freenet/config/IntOption.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/IntOption.java     2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/IntOption.java     2008-09-24 
20:42:20 UTC (rev 22823)
@@ -8,89 +8,37 @@
 import freenet.support.api.IntCallback;

 /** Integer config variable */
-public class IntOption extends Option {
-
-       final int defaultValue;
-       final IntCallback cb;
-       private int currentValue;
-       // Cache it mostly so that we can keep SI units
-       private String cachedStringValue;
+public class IntOption extends Option<Integer> {
+       public IntOption(SubConfig conf, String optionName, String 
defaultValueString, int sortOrder, boolean expert,
+               boolean forceWrite, String shortDesc, String longDesc, 
IntCallback cb) {
+               this(conf, optionName, Fields.parseInt(defaultValueString), 
sortOrder, expert, forceWrite, shortDesc, longDesc,
+                       cb);
+       }

-       public IntOption(SubConfig conf, String optionName, int defaultValue, 
String defaultValueString,
-                       int sortOrder, boolean expert, boolean forceWrite, 
String shortDesc, String longDesc, IntCallback cb) {
-               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DATA_TYPE_NUMBER);
+       public IntOption(SubConfig conf, String optionName, Integer 
defaultValue, int sortOrder, boolean expert,
+               boolean forceWrite, String shortDesc, String longDesc, 
IntCallback cb) {
+               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DataType.NUMBER);
                this.defaultValue = defaultValue;
-               this.cb = cb;
                this.currentValue = defaultValue;
-               this.cachedStringValue = defaultValueString;
        }

-       public IntOption(SubConfig conf, String optionName, String 
defaultValueString,
-                       int sortOrder, boolean expert, boolean forceWrite, 
String shortDesc, String longDesc, IntCallback cb) {
-               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DATA_TYPE_NUMBER);
-               this.defaultValue = Fields.parseSIInt(defaultValueString);
-               this.cb = cb;
-               this.currentValue = defaultValue;
-               this.cachedStringValue = defaultValueString;
-       }
-
-       /** Get the current value. This is the value in use if we have finished
-        * initialization, otherwise it is the value set at startup (possibly 
the default). */
-       public int getValue() {
-               if(config.hasFinishedInitialization()) {
-                       int val = cb.get();
-                       if(currentValue != val) {
-                               currentValue = val;
-                               cachedStringValue = null;
-                       }
-               }
-               return currentValue;
-       }
-
-       public void setValue(String val) throws InvalidConfigValueException {
-               int x;
-               try{
-                       x = Fields.parseSIInt(val);
+       @Override
+       protected Integer parseString(String val) throws 
InvalidConfigValueException {
+               Integer x;
+               try {
+                       x = Fields.parseInt(val);
                } catch (NumberFormatException e) {
                        throw new 
InvalidConfigValueException(l10n("parseError", "val", val));
                }
-               cb.set(x);
-               cachedStringValue = val;
-               currentValue = x;
+               return x;
        }
-       
-       public void setInitialValue(String val) throws 
InvalidConfigValueException {
-               int x;
-               try{
-                       x = Fields.parseSIInt(val);
-               } catch (NumberFormatException e) {
-                       throw new 
InvalidConfigValueException(l10n("parseError", "val", val));
-               }
-               cachedStringValue = val;
-               currentValue = x;
-       }

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

-       public String getValueString() {
-               int val = getValue();
-               if(cachedStringValue != null) return cachedStringValue;
-               return Integer.toString(val);
+       @Override
+       protected String toString(Integer val) {
+               return Fields.intToString(val);
        }
-       
-       public String getDefault(){
-               return Integer.toString(defaultValue);
-       }
-
-       public boolean isDefault() {
-               getValue();
-               return currentValue == defaultValue;
-       }
-       
-       public void setDefault() {
-               currentValue = defaultValue;
-       }
-       
 }

Modified: 
branches/db4o/freenet/src/freenet/config/InvalidConfigValueException.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/InvalidConfigValueException.java   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/InvalidConfigValueException.java   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -10,11 +10,9 @@
  * it merely means that there are no immediately detectable problems with 
  * it.
  */
-public class InvalidConfigValueException extends Exception {
-       private static final long serialVersionUID = -1;
+public class InvalidConfigValueException extends ConfigException {

        public InvalidConfigValueException(String msg) {
                super(msg);
        }
-
 }

Modified: branches/db4o/freenet/src/freenet/config/LongOption.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/LongOption.java    2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/LongOption.java    2008-09-24 
20:42:20 UTC (rev 22823)
@@ -8,91 +8,37 @@
 import freenet.support.api.LongCallback;

 /** Long config variable */
-public class LongOption extends Option {
-
-       final long defaultValue;
-       final LongCallback cb;
-       private long currentValue;
-       // Cache it mostly so that we can keep SI units
-       private String cachedStringValue;
-
-       public LongOption(SubConfig conf, String optionName, long defaultValue, 
String defaultValueString, 
-                       int sortOrder, boolean expert, boolean forceWrite, 
String shortDesc, String longDesc, LongCallback cb) {
-               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DATA_TYPE_NUMBER);
-               this.defaultValue = defaultValue;
-               this.cb = cb;
-               this.currentValue = defaultValue;
-               this.cachedStringValue = defaultValueString;
+public class LongOption extends Option<Long> {
+       public LongOption(SubConfig conf, String optionName, String 
defaultValueString, int sortOrder, boolean expert,
+               boolean forceWrite, String shortDesc, String longDesc, 
LongCallback cb) {
+               this(conf, optionName, Fields.parseLong(defaultValueString), 
sortOrder, expert, forceWrite, shortDesc,
+                       longDesc, cb);
        }

-       public LongOption(SubConfig conf, String optionName, String 
defaultValueString, 
-                       int sortOrder, boolean expert, boolean forceWrite, 
String shortDesc, String longDesc, LongCallback cb) {
-               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DATA_TYPE_NUMBER);
-               this.defaultValue = Fields.parseSILong(defaultValueString);
-               this.cb = cb;
+       public LongOption(SubConfig conf, String optionName, Long defaultValue, 
int sortOrder, boolean expert,
+               boolean forceWrite, String shortDesc, String longDesc, 
LongCallback cb) {
+               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DataType.NUMBER);
+               this.defaultValue = defaultValue;
                this.currentValue = defaultValue;
-               this.cachedStringValue = defaultValueString;
        }
-       
-       /** Get the current value. This is the value in use if we have finished
-        * initialization, otherwise it is the value set at startup (possibly 
the default). */
-       public long getValue() {
-               if(config.hasFinishedInitialization()) {
-                       long val = cb.get();
-                       if(currentValue != val) {
-                               currentValue = val;
-                               cachedStringValue = null;
-                       }
-               }
-               return currentValue;
-       }
-       
-       public void setValue(String val) throws InvalidConfigValueException {
-               long x;
-               try{
-                       x = Fields.parseSILong(val);
-               }catch (NumberFormatException e) {
-                       throw new 
InvalidConfigValueException(l10n("parseError", "val", val));
-               }
-               cb.set(x);
-               cachedStringValue = val;
-               currentValue = x;
-       }
-       
-       public String getValueString() {
-               long l = getValue();
-               if(cachedStringValue != null) 
-                       return cachedStringValue;
-               else 
-                       return Long.toString(l);
-       }

-       public void setInitialValue(String val) throws 
InvalidConfigValueException {
-               long x;
-               try{
-                       x = Fields.parseSILong(val);
-               }catch (NumberFormatException e) {
+       @Override
+       protected Long parseString(String val) throws 
InvalidConfigValueException {
+               Long x;
+               try {
+                       x = Fields.parseLong(val);
+               } catch (NumberFormatException e) {
                        throw new 
InvalidConfigValueException(l10n("parseError", "val", val));
                }
-               cachedStringValue = val;
-               currentValue = x;
+               return x;
        }
-
+       
        private String l10n(String key, String pattern, String value) {
-               return L10n.getString("LongOption."+key, pattern, value);
+               return L10n.getString("LongOption." + key, pattern, value);
        }
-
-       public boolean isDefault() {
-               getValue();
-               return currentValue == defaultValue;
-       }

-       public String getDefault() {
-               return Long.toString(defaultValue);
+       @Override
+       protected String toString(Long val) {
+               return Fields.longToString(val);
        }
-
-       public void setDefault() {
-               currentValue = defaultValue;
-       }
-       
 }

Copied: branches/db4o/freenet/src/freenet/config/NodeNeedRestartException.java 
(from rev 21939, trunk/freenet/src/freenet/config/NodeNeedRestartException.java)
===================================================================
--- branches/db4o/freenet/src/freenet/config/NodeNeedRestartException.java      
                        (rev 0)
+++ branches/db4o/freenet/src/freenet/config/NodeNeedRestartException.java      
2008-09-24 20:42:20 UTC (rev 22823)
@@ -0,0 +1,19 @@
+/* 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.config;
+
+/**
+ * Thrown when the node refuses to set a config variable to a particular
+ * value because it is invalid. Just because this is not thrown does not
+ * necessarily mean that there are no problems with the value defined,
+ * it merely means that there are no immediately detectable problems with 
+ * it.
+ */
+public class NodeNeedRestartException extends ConfigException {
+
+       public NodeNeedRestartException(String msg) {
+               super(msg);
+       }
+
+}

Modified: branches/db4o/freenet/src/freenet/config/NullBooleanCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/NullBooleanCallback.java   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/NullBooleanCallback.java   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -2,13 +2,13 @@

 import freenet.support.api.BooleanCallback;

-public class NullBooleanCallback implements BooleanCallback {
+public class NullBooleanCallback extends BooleanCallback {

-       public boolean get() {
+       public Boolean get() {
                return false;
        }

-       public void set(boolean val) throws InvalidConfigValueException {
+       public void set(Boolean val) throws InvalidConfigValueException {
                // Ignore
        }


Modified: branches/db4o/freenet/src/freenet/config/NullIntCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/NullIntCallback.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/NullIntCallback.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -2,13 +2,13 @@

 import freenet.support.api.IntCallback;

-public class NullIntCallback implements IntCallback {
+public class NullIntCallback extends IntCallback {

-       public int get() {
+       public Integer get() {
                return 0;
        }

-       public void set(int val) throws InvalidConfigValueException {
+       public void set(Integer val) throws InvalidConfigValueException {
                // Ignore
        }


Modified: branches/db4o/freenet/src/freenet/config/NullLongCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/NullLongCallback.java      
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/NullLongCallback.java      
2008-09-24 20:42:20 UTC (rev 22823)
@@ -2,13 +2,13 @@

 import freenet.support.api.LongCallback;

-public class NullLongCallback implements LongCallback {
+public class NullLongCallback extends LongCallback {

-       public long get() {
-               return 0;
+       public Long get() {
+               return 0L;
        }

-       public void set(long val) throws InvalidConfigValueException {
+       public void set(Long val) throws InvalidConfigValueException {
                // Ignore
        }


Modified: branches/db4o/freenet/src/freenet/config/NullShortCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/NullShortCallback.java     
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/NullShortCallback.java     
2008-09-24 20:42:20 UTC (rev 22823)
@@ -2,13 +2,13 @@

 import freenet.support.api.ShortCallback;

-public class NullShortCallback implements ShortCallback {
+public class NullShortCallback extends ShortCallback {

-       public short get() {
+       public Short get() {
                return 0;
        }

-       public void set(short val) throws InvalidConfigValueException {
+       public void set(Short val) throws InvalidConfigValueException {
                // Ignore
        }


Modified: branches/db4o/freenet/src/freenet/config/NullStringCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/NullStringCallback.java    
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/NullStringCallback.java    
2008-09-24 20:42:20 UTC (rev 22823)
@@ -2,7 +2,7 @@

 import freenet.support.api.StringCallback;

-public class NullStringCallback implements StringCallback {
+public class NullStringCallback extends StringCallback {

        public String get() {
                return "";

Modified: branches/db4o/freenet/src/freenet/config/Option.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/Option.java        2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/Option.java        2008-09-24 
20:42:20 UTC (rev 22823)
@@ -3,11 +3,11 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.config;

+
 /**
  * A config option.
  */
-public abstract class Option {
-
+public abstract class Option<T> {
        /** The parent SubConfig object */
        protected final SubConfig config;
        /** The option name */
@@ -23,17 +23,20 @@
        /** Long description of value e.g. "The TCP port to listen for FCP 
connections on" */
        protected final String longDesc;
        /** The configCallback associated to the Option */
-       protected final ConfigCallback cb;
+       protected final ConfigCallback<T> cb;

-       public final static int DATA_TYPE_STRING = 0;
-       public final static int DATA_TYPE_NUMBER = 1;
-       public final static int DATA_TYPE_BOOLEAN = 2;
-       public final static int DATA_TYPE_STRING_ARRAY = 3;
+       protected T defaultValue;
+       protected T currentValue;

+       public static enum DataType {
+               STRING, NUMBER, BOOLEAN, STRING_ARRAY
+       };
+       
        /** Data type : used to make it possible to make user inputs more 
friendly in FCP apps */
-       final int dataType;
+       final DataType dataType;

-       Option(SubConfig config, String name, ConfigCallback cb, int sortOrder, 
boolean expert, boolean forceWrite, String shortDesc, String longDesc, int 
dataType) {
+       Option(SubConfig config, String name, ConfigCallback<T> cb, int 
sortOrder, boolean expert, boolean forceWrite,
+               String shortDesc, String longDesc, DataType dataType) {
                this.config = config;
                this.name = name;
                this.cb = cb;
@@ -46,27 +49,47 @@
        }

        /**
-        * Set this option's current value to a string. Will call the callback. 
Does not care 
-        * whether the value of the option has changed.
+        * Set this option's current value to a string. Will call the callback. 
Does not care whether
+        * the value of the option has changed.
         */
-       public abstract void setValue(String val) throws 
InvalidConfigValueException;
+       public final void setValue(String val) throws 
InvalidConfigValueException, NodeNeedRestartException {
+               T x = parseString(val);
+               set(x);
+       }

+       protected abstract T parseString(String val) throws 
InvalidConfigValueException; 
+       protected abstract String toString(T val);
+
+       protected final void set(T val) throws InvalidConfigValueException, 
NodeNeedRestartException {
+               try {
+                       cb.set(val);
+                       currentValue = val;
+               } catch (NodeNeedRestartException e) {
+                       currentValue = val;
+                       throw e;
+               }
+       }
+       
        /**
         * Get the current value of the option as a string.
         */
-       public abstract String getValueString();
+       public final String getValueString() {
+               return toString(currentValue);
+       }

        /** Set to a value from the config file; this is not passed on to the 
callback, as we
         * expect the client-side initialization to check the value. The 
callback is not valid
         * until the client calls finishedInitialization().
         * @throws InvalidConfigValueException 
         */
-       public abstract void setInitialValue(String val) throws 
InvalidConfigValueException;
+       public final void setInitialValue(String val) throws 
InvalidConfigValueException {
+               currentValue = parseString(val);
+       }

        /**
         * Call the callback with the current value of the option.
         */
-       public void forceUpdate() throws InvalidConfigValueException {
+       public void forceUpdate() throws InvalidConfigValueException, 
NodeNeedRestartException {
                setValue(getValueString());
        }

@@ -94,31 +117,56 @@
                return sortOrder;
        }

-       public int getDataType() {
+       public DataType getDataType() {
                return dataType;
        }

        public String getDataTypeStr() {
                switch(dataType) {
-               case(DATA_TYPE_STRING): return "string";
-               case(DATA_TYPE_NUMBER): return "number";
-               case(DATA_TYPE_BOOLEAN): return "boolean";
-               case(DATA_TYPE_STRING_ARRAY): return "stringArray";
+               case STRING:
+                       return "string";
+               case NUMBER:
+                       return "number";
+               case BOOLEAN:
+                       return "boolean";
+               case STRING_ARRAY:
+                       return "stringArray";
                default: return null;
                }
        }

        /**
+        * Get the current value. This is the value in use if we have finished 
initialization, otherwise
+        * it is the value set at startup (possibly the default).
+        */
+       public final T getValue() {
+               if (config.hasFinishedInitialization())
+                       return currentValue = cb.get();
+               else
+                       return currentValue;
+       }
+       
+       /**
         * Is this option set to the default?
         */
-       public abstract boolean isDefault();
+       public boolean isDefault() {
+               getValue();
+               return (currentValue == null ? false : 
currentValue.equals(defaultValue));
+       }
+
+       /**
+        * Set to the default. Don't use after completed initialization, as 
this does not call the
+        * callback.
+        */
+       public final void setDefault() {
+               currentValue = defaultValue;
+       }

-       /** Set to the default. Don't use after completed initialization, as 
this does not call the callback. FIXME fix this? */
-       public abstract void setDefault();
-       
-       public abstract String getDefault();
+       public final String getDefault() {
+               return toString(defaultValue);
+       }

-       public ConfigCallback getCallback() {
+       public final ConfigCallback<T> getCallback() {
                return cb;
        }
 }

Modified: branches/db4o/freenet/src/freenet/config/PersistentConfig.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/PersistentConfig.java      
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/PersistentConfig.java      
2008-09-24 20:42:20 UTC (rev 22823)
@@ -36,15 +36,15 @@
        }

        public SimpleFieldSet exportFieldSet(boolean withDefaults) {
-               return 
exportFieldSet(Config.CONFIG_REQUEST_TYPE_CURRENT_SETTINGS, withDefaults);
+               return exportFieldSet(Config.RequestType.CURRENT_SETTINGS, 
withDefaults);
        }

-       public SimpleFieldSet exportFieldSet(int configRequestType, boolean 
withDefaults) {
+       public SimpleFieldSet exportFieldSet(Config.RequestType 
configRequestType, boolean withDefaults) {
                SimpleFieldSet fs = new SimpleFieldSet(true);
                SubConfig[] configs;
                synchronized(this) {
                        // FIXME maybe keep a cache of this?
-                       configs = (SubConfig[]) 
configsByPrefix.values().toArray(new SubConfig[configsByPrefix.size()]);
+                       configs = configsByPrefix.values().toArray(new 
SubConfig[configsByPrefix.size()]);
                }
                SubConfig current;
                for(int i=0;i<configs.length;i++) {

Modified: branches/db4o/freenet/src/freenet/config/ShortOption.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/ShortOption.java   2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/ShortOption.java   2008-09-24 
20:42:20 UTC (rev 22823)
@@ -4,68 +4,31 @@
 import freenet.support.Fields;
 import freenet.support.api.ShortCallback;

-public class ShortOption extends Option {
-       
-       final short defaultValue;
-       final ShortCallback cb;
-       private short currentValue;
-       
+public class ShortOption extends Option<Short> {
        public ShortOption(SubConfig conf, String optionName, short 
defaultValue, int sortOrder, 
                        boolean expert, boolean forceWrite, String shortDesc, 
String longDesc, ShortCallback cb) {
-               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DATA_TYPE_NUMBER);
+               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DataType.NUMBER);
                this.defaultValue = defaultValue;
-               this.cb = cb;
                this.currentValue = defaultValue;
        }
-       
-       /** Get the current value. This is the value in use if we have finished
-        * initialization, otherwise it is the value set at startup (possibly 
the default). */
-       public short getValue() {
-               if(config.hasFinishedInitialization())
-                       return currentValue = cb.get();
-               else return currentValue;
+
+       private String l10n(String key, String pattern, String value) {
+               return L10n.getString("ShortOption."+key, pattern, value);
        }

-       public void setValue(String val) throws InvalidConfigValueException {
+       @Override
+       protected Short parseString(String val) throws 
InvalidConfigValueException {
                short x;
-               try{
-                       x= Fields.parseSIShort(val);
+               try {
+                       x = Fields.parseShort(val);
                } catch (NumberFormatException e) {
                        throw new 
InvalidConfigValueException(l10n("unrecognisedShort", "val", val));
                }
-               cb.set(x);
-               currentValue = x;
+               return x;
        }

-       public String getValueString() {
-               return Short.toString(getValue());
-       }
-
-       public void setInitialValue(String val) throws 
InvalidConfigValueException {
-               short x;
-               try{
-                       x = Fields.parseSIShort(val);
-               } catch (NumberFormatException e) {
-                       throw new 
InvalidConfigValueException(l10n("unrecognisedShort", "val", val));
-               }
-               currentValue = x;
-       }
-
-       private String l10n(String key, String pattern, String value) {
-               return L10n.getString("ShortOption."+key, pattern, value);
-       }
-
-       public boolean isDefault() {
-               getValue();
-               return currentValue == defaultValue;
-       }
-       
-       public String getDefault() {
-               return Short.toString(defaultValue);
-       }
-       
-       public void setDefault() {
-               currentValue = defaultValue;
-       }
-       
+       @Override
+       protected String toString(Short val) {
+               return Fields.shortToString(val);
+       }       
 }

Modified: branches/db4o/freenet/src/freenet/config/StringArrOption.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/StringArrOption.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/StringArrOption.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -8,80 +8,45 @@
 import freenet.support.URLEncoder;
 import freenet.support.api.StringArrCallback;

-public class StringArrOption extends Option {
-
-    private final String[] defaultValue;
-    private final StringArrCallback cb;
-    private String[] currentValue;
-       
+public class StringArrOption extends Option<String[]> {
     public static final String delimiter = ";";

        public StringArrOption(SubConfig conf, String optionName, String[] 
defaultValue, int sortOrder, 
                        boolean expert, boolean forceWrite, String shortDesc, 
String longDesc, StringArrCallback cb) {
-               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DATA_TYPE_STRING_ARRAY);
+               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DataType.STRING_ARRAY);
                this.defaultValue = (defaultValue==null)?new 
String[0]:defaultValue;
-               this.cb = cb;
                this.currentValue = (defaultValue==null)?new 
String[0]:defaultValue;
        }
-       
-       /** Get the current value. This is the value in use if we have finished
-        * initialization, otherwise it is the value set at startup (possibly 
the default). */
-       public String[] getValue() {
-               if(config.hasFinishedInitialization())
-                       currentValue = cb.get();

-               return currentValue;
-       }
+       public String[] parseString(String val) throws 
InvalidConfigValueException {
+               if(val.length() == 0) return new String[0];
+               String[] out = val.split(delimiter);

-       public void setValue(String[] val) throws InvalidConfigValueException {
-               setInitialValue(val);
-               cb.set(this.currentValue);
-       }
-       
-       public void setValue(String val) throws InvalidConfigValueException {
                try {
-                       setValue(stringToArray(val));
+                       for (int i = 0; i < out.length; i++) {
+                               if (out[i].equals(":"))
+                                       out[i] = "";
+                               else
+                                       out[i] = URLDecoder.decode(out[i], true 
/* FIXME false */);
+                       }
                } catch (URLEncodedFormatException e) {
                        throw new 
InvalidConfigValueException(l10n("parseError", "error", 
e.getLocalizedMessage()));
                }
-       }
-       
-       public static String[] stringToArray(String val) throws 
URLEncodedFormatException {
-               if(val.length() == 0) return new String[0];
-               String[] out = val.split(delimiter);
-               for(int i=0;i<out.length;i++) {
-                       if(out[i].equals(":"))
-                               out[i] = "";
-                       else
-                               out[i] = URLDecoder.decode(out[i], true /* 
FIXME false */);
-               }
                return out;
        }
-
-       public String getValueString() {
-               return arrayToString(getValue());
-       }

        public void setInitialValue(String[] val) throws 
InvalidConfigValueException {
                this.currentValue = val;
        }

-       public void setInitialValue(String val) throws 
InvalidConfigValueException {
-               try {
-                       this.currentValue = stringToArray(val);
-               } catch (URLEncodedFormatException e) {
-                       throw new 
InvalidConfigValueException(l10n("parseError", "error", 
e.getLocalizedMessage()));
-               }
-       }
-       
        private String l10n(String key, String pattern, String value) {
                return L10n.getString("StringArrOption."+key, pattern, value);
        }

-       public static String arrayToString(String[] arr) {
+       public String toString(String[] arr) {
                if (arr == null)
                        return null;
-               StringBuffer sb = new StringBuffer();
+               StringBuilder sb = new StringBuilder();
                for (int i = 0 ; i < arr.length ; i++) {
                        String val = arr[i];
                        if(val.length() == 0)
@@ -101,17 +66,8 @@
                }
        }

-       public String getDefault() {
-               return arrayToString(defaultValue);
-       }
-
        public boolean isDefault() {
-               getValueString();
+               getValue();
                return currentValue == null ? false : 
Arrays.equals(currentValue, defaultValue);
        }
-       
-       public void setDefault() {
-               currentValue = defaultValue;
-       }
-       
 }

Modified: branches/db4o/freenet/src/freenet/config/StringOption.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/StringOption.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/StringOption.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -5,51 +5,21 @@

 import freenet.support.api.StringCallback;

-public class StringOption extends Option {
-
-       final String defaultValue;
-       final StringCallback cb;
-       private String currentValue;
-       
+public class StringOption extends Option<String> {
        public StringOption(SubConfig conf, String optionName, String 
defaultValue, int sortOrder, 
                        boolean expert, boolean forceWrite, String shortDesc, 
String longDesc, StringCallback cb) {
-               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DATA_TYPE_STRING);
+               super(conf, optionName, cb, sortOrder, expert, forceWrite, 
shortDesc, longDesc, Option.DataType.STRING);
                this.defaultValue = defaultValue;
-               this.cb = cb;
                this.currentValue = defaultValue;
        }
-       
-       /** Get the current value. This is the value in use if we have finished
-        * initialization, otherwise it is the value set at startup (possibly 
the default). */
-       public String getValue() {
-               if(config.hasFinishedInitialization())
-                       return currentValue = cb.get();
-               else return currentValue;
-       }

-       public void setValue(String val) throws InvalidConfigValueException {
-               cb.set(val);
-               this.currentValue = val; // Callbacks are in charge of ensuring 
it matches with possibleValues
+       @Override
+       protected String parseString(String val) throws 
InvalidConfigValueException {
+               return val;
        }
-       
-       public String getValueString() {
-               return getValue();
-       }

-       public void setInitialValue(String val) throws 
InvalidConfigValueException {
-               this.currentValue = val;
+       @Override
+       protected String toString(String val) {
+               return val;
        }
-
-       public boolean isDefault() {
-               getValue();
-               return (currentValue == null ? false : 
currentValue.equals(defaultValue));
-       }
-       
-       public void setDefault() {
-               currentValue = defaultValue;
-       }
-       
-       public String getDefault(){
-               return defaultValue;
-       }
 }

Modified: branches/db4o/freenet/src/freenet/config/SubConfig.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/SubConfig.java     2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/SubConfig.java     2008-09-24 
20:42:20 UTC (rev 22823)
@@ -3,8 +3,8 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.config;

+import java.util.Iterator;
 import java.util.LinkedHashMap;
-import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.Map.Entry;
@@ -22,9 +22,9 @@
 /**
  * A specific configuration block.
  */
-public class SubConfig implements Comparable {
+public class SubConfig implements Comparable<SubConfig> {

-       private final LinkedHashMap map;
+       private final LinkedHashMap<String, Option<?>> map;
        public final Config config;
        final String prefix;
        private boolean hasInitialized;
@@ -32,7 +32,7 @@
        public SubConfig(String prefix, Config config) {
                this.config = config;
                this.prefix = prefix;
-               map = new LinkedHashMap();
+               map = new LinkedHashMap<String, Option<?>>();
                hasInitialized = false;
                config.register(this);
        }
@@ -41,15 +41,15 @@
         * Return all the options registered. Each includes its name.
         * Used by e.g. webconfig.
         */
-       public synchronized Option[] getOptions() {
-               return (Option[]) map.values().toArray(new Option[map.size()]);
+       public synchronized Option<?>[] getOptions() {
+               return map.values().toArray(new Option[map.size()]);
        }

-       public synchronized Option getOption(String option){
-               return (Option)map.get(option);
+       public synchronized Option<?> getOption(String option) {
+               return map.get(option);
        }

-       public void register(Option o) {
+       public void register(Option<?> o) {
                synchronized(this) {
                        if(o.name.indexOf(SimpleFieldSet.MULTI_LEVEL_CHAR) != 
-1)
                                throw new IllegalArgumentException("Option 
names must not contain "+SimpleFieldSet.MULTI_LEVEL_CHAR);
@@ -63,13 +63,13 @@
        public void register(String optionName, int defaultValue, int sortOrder,
                        boolean expert, boolean forceWrite, String shortDesc, 
String longDesc, IntCallback cb) {
                if(cb == null) cb = new NullIntCallback();
-               register(new IntOption(this, optionName, defaultValue, null, 
sortOrder, expert, forceWrite, shortDesc, longDesc, cb));
+               register(new IntOption(this, optionName, defaultValue, 
sortOrder, expert, forceWrite, shortDesc, longDesc, cb));
        }

        public void register(String optionName, long defaultValue, int 
sortOrder,
                        boolean expert, boolean forceWrite, String shortDesc, 
String longDesc, LongCallback cb) {
                if(cb == null) cb = new NullLongCallback();
-               register(new LongOption(this, optionName, defaultValue, null, 
sortOrder, expert, forceWrite, shortDesc, longDesc, cb));
+               register(new LongOption(this, optionName, defaultValue, 
sortOrder, expert, forceWrite, shortDesc, longDesc, cb));
        }

        public void register(String optionName, String defaultValueString, int 
sortOrder,
@@ -178,12 +178,12 @@
         * Set options from a SimpleFieldSet. Once we process an option, we 
must remove it.
         */
        public void setOptions(SimpleFieldSet sfs) {
-               Set entrySet = map.entrySet();
-               Iterator i = entrySet.iterator();
+               Set<Map.Entry<String, Option<?>>> entrySet = map.entrySet();
+               Iterator<Entry<String, Option<?>>> i = entrySet.iterator();
                while(i.hasNext()) {
-                       Map.Entry entry = (Map.Entry) i.next();
-                       String key = (String) entry.getKey();
-                       Option o = (Option) entry.getValue();
+                       Entry<String, Option<?>> entry = i.next();
+                       String key = entry.getKey();
+                       Option<?> o = entry.getValue();
                        String val = sfs.get(key);
                        if(val != null) {
                                try {
@@ -192,6 +192,11 @@
                                        String msg = "Invalid config value: 
"+prefix+SimpleFieldSet.MULTI_LEVEL_CHAR+key+" = "+val+" : error: "+e;
                                        Logger.error(this, msg, e);
                                        System.err.println(msg); // might be 
about logging?
+                               } catch (NodeNeedRestartException e) {
+                                       // Impossible
+                                       String msg = "Impossible: " + prefix + 
SimpleFieldSet.MULTI_LEVEL_CHAR + key + " = " + val
+                                               + " : error: " + e;
+                                       Logger.error(this, msg, e);
                                }
                        }
                }
@@ -202,53 +207,55 @@
        }

        public SimpleFieldSet exportFieldSet(boolean withDefaults) {
-               return 
exportFieldSet(Config.CONFIG_REQUEST_TYPE_CURRENT_SETTINGS, withDefaults);
+               return exportFieldSet(Config.RequestType.CURRENT_SETTINGS, 
withDefaults);
        }

-       public SimpleFieldSet exportFieldSet(int configRequestType, boolean 
withDefaults) {
+    public SimpleFieldSet exportFieldSet(Config.RequestType configRequestType, 
boolean withDefaults) {
                SimpleFieldSet fs = new SimpleFieldSet(true);
+               @SuppressWarnings("unchecked")
+               Map.Entry<String, Option<?>>[] entries = new 
Map.Entry[map.size()];
                // FIXME is any locking at all necessary here? After it has 
finished init, it's constant...
-               Map.Entry[] entries;
                synchronized(this) {
-                       entries = (Entry[]) map.entrySet().toArray(new 
Map.Entry[map.size()]);
+                       entries = map.entrySet().toArray(entries);
                }
                boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
                if(logMINOR)
                        Logger.minor(this, "Prefix="+prefix);
                for(int i=0;i<entries.length;i++) {
-                       Map.Entry entry = (Map.Entry) entries[i];
-                       String key = (String) entry.getKey();
-                       Option o = (Option) entry.getValue();
-//                     if(logMINOR)
-//                             Logger.minor(this, "Key="+key+" 
value="+o.getValueString()+" default="+o.isDefault());
-                       if(configRequestType == 
Config.CONFIG_REQUEST_TYPE_CURRENT_SETTINGS && (!withDefaults) && o.isDefault() 
&& (!o.forceWrite)) {
+                       Map.Entry<String, Option<?>> entry = entries[i];
+                       String key = entry.getKey();
+                       Option<?> o = entry.getValue();
+                       if(logMINOR)
+                               Logger.minor(this, "Key="+key+" 
value="+o.getValueString()+" default="+o.isDefault());
+                       if (configRequestType == 
Config.RequestType.CURRENT_SETTINGS && (!withDefaults) && o.isDefault()
+                               && (!o.forceWrite)) {
                                if(logMINOR)
                                        Logger.minor(this, "Skipping "+key+" - 
"+o.isDefault());
                                continue;
                        }
                        switch (configRequestType) {
-                               case 
Config.CONFIG_REQUEST_TYPE_CURRENT_SETTINGS:
+                               case CURRENT_SETTINGS:
                                        fs.putSingle(key, o.getValueString());
                                        break;
-                               case 
Config.CONFIG_REQUEST_TYPE_DEFAULT_SETTINGS:
+                               case DEFAULT_SETTINGS:
                                        fs.putSingle(key, o.getDefault());
                                        break;
-                               case Config.CONFIG_REQUEST_TYPE_SORT_ORDER:
+                               case SORT_ORDER:
                                        fs.put(key, o.getSortOrder());
                                        break;
-                               case Config.CONFIG_REQUEST_TYPE_EXPERT_FLAG:
+                               case EXPERT_FLAG:
                                        fs.put(key, o.isExpert());
                                        break;
-                               case 
Config.CONFIG_REQUEST_TYPE_FORCE_WRITE_FLAG:
+                               case FORCE_WRITE_FLAG:
                                        fs.put(key, o.isForcedWrite());
                                        break;
-                               case 
Config.CONFIG_REQUEST_TYPE_SHORT_DESCRIPTION:
+                               case SHORT_DESCRIPTION:
                                        fs.putSingle(key, 
L10n.getString(o.getShortDesc()));
                                        break;
-                               case 
Config.CONFIG_REQUEST_TYPE_LONG_DESCRIPTION:
+                               case LONG_DESCRIPTION:
                                        fs.putSingle(key, 
L10n.getString(o.getLongDesc()));
                                        break;
-                               case Config.CONFIG_REQUEST_TYPE_DATA_TYPE:
+                               case DATA_TYPE:
                                        fs.putSingle(key, o.getDataTypeStr());
                                        break;
                                default:
@@ -263,19 +270,21 @@

        /**
         * Force an option to be updated even if it hasn't changed.
-        * @throws InvalidConfigValueException 
+        * 
+        * @throws InvalidConfigValueException
+        * @throws NodeNeedRestartException
         */
-       public void forceUpdate(String optionName) throws 
InvalidConfigValueException {
-               Option o = (Option) map.get(optionName);
+       public void forceUpdate(String optionName) throws 
InvalidConfigValueException, NodeNeedRestartException {
+               Option<?> o = map.get(optionName);
                o.forceUpdate();
        }

-       public void set(String name, String value) throws 
InvalidConfigValueException {
-               Option o = (Option) map.get(name);
+       public void set(String name, String value) throws 
InvalidConfigValueException, NodeNeedRestartException {
+               Option<?> o = map.get(name);
                o.setValue(value);
        }

-       public void set(String name, boolean value) throws 
InvalidConfigValueException {
+       public void set(String name, boolean value) throws 
InvalidConfigValueException, NodeNeedRestartException {
                BooleanOption o = (BooleanOption) map.get(name);
                o.set(value);
        }
@@ -288,7 +297,7 @@
         * @param value The value of the option.
         */
        public void fixOldDefault(String name, String value) {
-               Option o = (Option) map.get(name);
+               Option<?> o = map.get(name);
                if(o.getValueString().equals(value))
                        o.setDefault();
        }
@@ -301,7 +310,7 @@
         * @param value The value of the option.
         */
        public void fixOldDefaultRegex(String name, String value) {
-               Option o = (Option) map.get(name);
+               Option<?> o = map.get(name);
                if(o.getValueString().matches(value))
                        o.setDefault();
        }
@@ -310,15 +319,11 @@
                return prefix;
        }

-       public int compareTo(Object o){
-               if((o == null) || !(o instanceof SubConfig)) return 0;
-               else{
-                       SubConfig second = (SubConfig) o;
-                       if(this.getPrefix().compareTo(second.getPrefix())>0)
-                               return 1;
-                       else
-                               return -1;
-               }
+       public int compareTo(SubConfig second) {
+               if (this.getPrefix().compareTo(second.getPrefix()) > 0)
+                       return 1;
+               else
+                       return -1;
        }

        public String getRawOption(String name) {

Modified: branches/db4o/freenet/src/freenet/config/WrapperConfig.java
===================================================================
--- branches/db4o/freenet/src/freenet/config/WrapperConfig.java 2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/config/WrapperConfig.java 2008-09-24 
20:42:20 UTC (rev 22823)
@@ -24,12 +24,12 @@
  */
 public class WrapperConfig {

-       private static HashMap overrides = new HashMap();
+       private static HashMap<String, String> overrides = new HashMap<String, 
String>();

        public static String getWrapperProperty(String name) {
                synchronized(WrapperConfig.class) {
                        if(overrides.containsKey(name))
-                               return (String) overrides.get(name);
+                               return overrides.get(name);
                }
                return WrapperManager.getProperties().getProperty(name, null);
        }

Modified: branches/db4o/freenet/src/freenet/crypt/DiffieHellman.java
===================================================================
--- branches/db4o/freenet/src/freenet/crypt/DiffieHellman.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/crypt/DiffieHellman.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -6,6 +6,7 @@

 package freenet.crypt;

+import freenet.node.FNPPacketMangler;
 import java.math.BigInteger;
 import java.util.Random;
 import java.util.Stack;
@@ -20,10 +21,10 @@
         * When the number of precalculations falls below this threshold 
generation
         * starts up to make more.
         */
-       private static final int PRECALC_RESUME = 150;
+       private static final int PRECALC_RESUME = 
FNPPacketMangler.DH_CONTEXT_BUFFER_SIZE;

        /** Maximum number of precalculations to create. */
-       private static final int PRECALC_MAX = 300;
+       private static final int PRECALC_MAX = 
FNPPacketMangler.DH_CONTEXT_BUFFER_SIZE * 2;

        /**
         * How often to wake up and make sure the precalculation buffer is full
@@ -49,7 +50,7 @@
        private static class PrecalcBufferFill extends NativeThread {

                public PrecalcBufferFill() {
-                       super("Diffie-Hellman-Precalc", 
NativeThread.LOW_PRIORITY, false);
+                       super("Diffie-Hellman-Precalc", 
NativeThread.MIN_PRIORITY, false);
                        setDaemon(true);
                }

@@ -119,6 +120,7 @@
                        }

                }
+               Logger.normal(DiffieHellman.class, "DiffieHellman had to 
generate a parameter on thread! (report if that happens often)");
                return genParams();
        }


Deleted: branches/db4o/freenet/src/freenet/crypt/DigestFactory.java
===================================================================
--- branches/db4o/freenet/src/freenet/crypt/DigestFactory.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/crypt/DigestFactory.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -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;
-
-/*
- * @deprecated Digests should be able to reinitialize themselves instead
- * Re-precated since I need to create many digests at the same time for the 
- * serial hash.
- **/
-public interface DigestFactory {
-    
-    public Digest getInstance();
-
-}

Deleted: branches/db4o/freenet/src/freenet/crypt/SHA1Factory.java
===================================================================
--- branches/db4o/freenet/src/freenet/crypt/SHA1Factory.java    2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/crypt/SHA1Factory.java    2008-09-24 
20:42:20 UTC (rev 22823)
@@ -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.crypt;
-
-public class SHA1Factory implements DigestFactory {
-
-    public Digest getInstance() {
-       return SHA1.getInstance();
-    }
-    
-}

Modified: branches/db4o/freenet/src/freenet/crypt/SSL.java
===================================================================
--- branches/db4o/freenet/src/freenet/crypt/SSL.java    2008-09-24 19:52:19 UTC 
(rev 22822)
+++ branches/db4o/freenet/src/freenet/crypt/SSL.java    2008-09-24 20:42:20 UTC 
(rev 22823)
@@ -23,16 +23,18 @@
 import java.security.Key;
 import java.security.KeyStore;
 import java.security.cert.Certificate;
+
 import javax.net.ServerSocketFactory;
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;

+import com.sleepycat.je.utilint.NotImplementedYetException;
+
 import freenet.config.InvalidConfigValueException;
 import freenet.config.SubConfig;
 import freenet.support.Logger;
 import freenet.support.api.BooleanCallback;
 import freenet.support.api.StringCallback;
-
 import freenet.support.io.Closer;

 public class SSL {
@@ -64,11 +66,11 @@
                sslConfig.register("sslEnable", false, configItemOrder++, true, 
true, "SSL.enable", "SSL.enableLong",
                        new BooleanCallback() {

-                               public boolean get() {
+                               public Boolean get() {
                                        return enable;
                                }

-                               public void set(boolean newValue) throws 
InvalidConfigValueException {
+                               public void set(Boolean newValue) throws 
InvalidConfigValueException {
                                        if(newValue != get()) {
                                                enable = newValue;
                                                if(enable)

Modified: branches/db4o/freenet/src/freenet/crypt/Yarrow.java
===================================================================
--- branches/db4o/freenet/src/freenet/crypt/Yarrow.java 2008-09-24 19:52:19 UTC 
(rev 22822)
+++ branches/db4o/freenet/src/freenet/crypt/Yarrow.java 2008-09-24 20:42:20 UTC 
(rev 22823)
@@ -61,14 +61,18 @@
        public final File seedfile; //A file to which seed data should be 
dumped periodically

        public Yarrow() {
-               this("prng.seed", "SHA1", "Rijndael", true);
+               this("prng.seed", "SHA1", "Rijndael", true, true);
        }
+       
+       public Yarrow(boolean canBlock) {
+               this("prng.seed", "SHA1", "Rijndael", true, canBlock);
+       }

-       public Yarrow(String seed, String digest, String cipher, boolean 
updateSeed) {
-               this(new File(seed), digest, cipher, updateSeed);
+       public Yarrow(String seed, String digest, String cipher, boolean 
updateSeed, boolean canBlock) {
+               this(new File(seed), digest, cipher, updateSeed, canBlock);
        }

-       public Yarrow(File seed, String digest, String cipher, boolean 
updateSeed) {
+       public Yarrow(File seed, String digest, String cipher, boolean 
updateSeed, boolean canBlock) {
                SecureRandom s;
                try {
                        s = SecureRandom.getInstance("SHA1PRNG");
@@ -85,7 +89,7 @@
                        throw new RuntimeException("Cannot initialize Yarrow!: 
" + e, e);
                }
                entropy_init(seed);
-               seedFromExternalStuff(true);
+               seedFromExternalStuff(canBlock);
                if(updateSeed && !(seed.toString()).equals("/dev/urandom")) 
//Dont try to update the seedfile if we know that it wont be possible anyways 
                        seedfile = seed;
                else
@@ -646,7 +650,7 @@
         * Test routine
         */
        public static void main(String[] args) throws Exception {
-               Yarrow r = new Yarrow(new File("/dev/urandom"), "SHA1", 
"Rijndael", true);
+               Yarrow r = new Yarrow(new File("/dev/urandom"), "SHA1", 
"Rijndael", true, false);

                byte[] b = new byte[1024];


Modified: branches/db4o/freenet/src/freenet/io/AddressIdentifier.java
===================================================================
--- branches/db4o/freenet/src/freenet/io/AddressIdentifier.java 2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/io/AddressIdentifier.java 2008-09-24 
20:42:20 UTC (rev 22823)
@@ -46,23 +46,9 @@
                ipv6PatternWithPercentScopeID = 
Pattern.compile(ipv6AddressRegex + percentScopeIDRegex);
                ipv6ISATAPPattern = Pattern.compile(ipv6ISATAPAddressRegex);
        }
-
-       public static class AddressType {
-
-               public static final AddressType OTHER = new 
AddressType("Other");
-               public static final AddressType IPv4 = new AddressType("IPv4");
-               public static final AddressType IPv6 = new AddressType("IPv6");
-
-               private final String name;
-
-               private AddressType(String name) {
-                       this.name = name;
-               }
-
-               public String toString() {
-                       return name;
-               }
-
+       
+       public enum AddressType {
+               OTHER, IPv4, IPv6;
        }

        /**

Modified: branches/db4o/freenet/src/freenet/io/NetworkInterface.java
===================================================================
--- branches/db4o/freenet/src/freenet/io/NetworkInterface.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/io/NetworkInterface.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -16,6 +16,7 @@

 package freenet.io;

+import java.io.Closeable;
 import java.io.IOException;
 import java.net.Inet6Address;
 import java.net.InetAddress;
@@ -40,7 +41,7 @@
  * @author David Roden &lt;droden at gmail.com&gt;
  * @version $Id$
  */
-public class NetworkInterface {
+public class NetworkInterface implements Closeable {

         public static final String DEFAULT_BIND_TO = 
"127.0.0.1,0:0:0:0:0:0:0:1";

@@ -138,6 +139,7 @@
                        InetSocketAddress addr = null;
                        try {
                                addr = new InetSocketAddress((String) 
bindToTokenList.get(serverSocketIndex), port);
+                               serverSocket.setReuseAddress(true);
                                serverSocket.bind(addr);
                        } catch (SocketException e) {
                                if(ignoreUnbindableIP6 && addr != null && 
addr.getAddress() instanceof Inet6Address)

Modified: branches/db4o/freenet/src/freenet/io/comm/DMT.java
===================================================================
--- branches/db4o/freenet/src/freenet/io/comm/DMT.java  2008-09-24 19:52:19 UTC 
(rev 22822)
+++ branches/db4o/freenet/src/freenet/io/comm/DMT.java  2008-09-24 20:42:20 UTC 
(rev 22823)
@@ -1206,18 +1206,6 @@
                msg.set(DATA, new ShortBuffer(buf));
                return msg;
        }
-
-       @Deprecated
-       public static final MessageType FNPLocChangeNotification = new 
MessageType("FNPLocationChangeNotification", PRIORITY_LOW) {{
-               addField(LOCATION, Double.class);
-       }};
-       
-       @Deprecated
-       public static final Message createFNPLocChangeNotification(double 
newLoc) {
-               Message msg = new Message(FNPLocChangeNotification);
-               msg.set(LOCATION, newLoc);
-               return msg;
-       }

        public static final MessageType FNPLocChangeNotificationNew = new 
MessageType("FNPLocationChangeNotification2", PRIORITY_LOW) {{
                addField(LOCATION, Double.class);

Modified: branches/db4o/freenet/src/freenet/io/comm/FreenetInetAddress.java
===================================================================
--- branches/db4o/freenet/src/freenet/io/comm/FreenetInetAddress.java   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/io/comm/FreenetInetAddress.java   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -141,7 +141,7 @@
         AddressIdentifier.AddressType addressType = 
AddressIdentifier.getAddressType(host);
         boolean logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
         if(logDEBUG) Logger.debug(this, "Address type of '"+host+"' appears to 
be '"+addressType+ '\'');
-        if(!addressType.toString().equals("Other")) {
+        if(addressType != AddressIdentifier.AddressType.OTHER) {
             try {
                 addr = InetAddress.getByName(host);
             } catch (UnknownHostException e) {

Modified: branches/db4o/freenet/src/freenet/io/comm/UdpSocketHandler.java
===================================================================
--- branches/db4o/freenet/src/freenet/io/comm/UdpSocketHandler.java     
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/io/comm/UdpSocketHandler.java     
2008-09-24 20:42:20 UTC (rev 22823)
@@ -64,6 +64,7 @@
                        _sock.setReceiveBufferSize(65536);
                try {
                        // Exit reasonably quickly
+                       _sock.setReuseAddress(true);
                        _sock.setSoTimeout(1000);
                } catch (SocketException e) {
                        throw new RuntimeException(e);
@@ -158,7 +159,6 @@

        private void realRun(DatagramPacket packet) {
                // Single receiving thread
-               logDEBUG = Logger.shouldLog(Logger.MINOR, this);
                boolean gotPacket = getPacket(packet);
                long now = System.currentTimeMillis();
                if (gotPacket) {

Modified: branches/db4o/freenet/src/freenet/l10n/L10n.java
===================================================================
--- branches/db4o/freenet/src/freenet/l10n/L10n.java    2008-09-24 19:52:19 UTC 
(rev 22822)
+++ branches/db4o/freenet/src/freenet/l10n/L10n.java    2008-09-24 20:42:20 UTC 
(rev 22823)
@@ -290,7 +290,7 @@
        private static String quoteReplacement(String s) {
                if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1))
                        return s;
-               StringBuffer sb = new StringBuffer();
+               StringBuilder sb = new StringBuilder();
                for (int i=0; i<s.length(); i++) {
                        char c = s.charAt(i);
                        if (c == '\\') {

Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties
===================================================================
--- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -280,6 +280,7 @@
 FProxyToadlet.notEnoughMetaStrings=Nicht genug Meta-Zeichenfolgen
 FProxyToadlet.notFoundTitle=Nicht gefunden
 FProxyToadlet.openAsText=${link}Klicken Sie hier${/link} um die Datei als 
Flie?text zu ?ffnen (dies sollte nicht gef?hrlich, k?nnte allerdings 
durcheinander/unleserlich sein).
+FProxyToadlet.openAsThawIndex=${link}Hier klicken${/link} um die Datei mit dem 
Thaw Index Browser zu ?ffnen (lesen Sie die obige Warnung!).
 FProxyToadlet.openForce=${link}Klicken Sie hier${/link} um die Datei als 
${mime} zu ?ffnen (lesen Sie die obenstehende Warnung!).
 FProxyToadlet.openForceDisk=${link}Klicken Sie hier${/link} um Ihren Browser 
zu zwingen, die Datei auf einen Datentr?ger herunterzuladen.
 FProxyToadlet.openPossRSSAsPlainText=${link}Klicken Sie hier${/link} um die 
Datei als Flie?text zu ?ffnen (dies ${bold}kann gef?hrlich sein${/bold} wenn 
Sie Internet Explorer 7 oder Firefox 2 benutzen).
@@ -693,8 +694,8 @@
 Node.passOpennetPeersThroughDarknetLong=Wenn aktiviert, werden 
Opennet-Knotenreferenzen (NIEMALS unsere eigene Darknet-Knotenreferenz) ?ber 
unsere Darknet-Partner weitergeleitet. Sodass ein Knoten (dieser Knoten oder 
seine Partner) Opennet-Partner von seinen Darknet-Partnern bekommen kann. Dies 
ist n?tzlich, da es uns erlaubt einen Bootstrap (Erlangung neuer Quellen ohne 
vorher welche zu haben) nach neuen Opennet-Partnern durchzuf?hren nachdem wir 
unsere Partner, zum Beispiel durch Ausfallzeiten, verloren haben. Jedoch kann 
es eine Traffic(Verkehrs)-Analyse etwas erleichtern, deshalb sollten Sie es 
ausschalten wenn Sie paranoid sind.
 Node.port=FNP-Port Nummer (UDP)
 Node.portLong=UDP-Port f?r Knoten-zu-Knoten Kommunikationen 
(Freenet-Knoten-Protokoll)
-Node.publishOurPeersLocation=Sollen wir die Position unserer Partner an unsere 
Partner weitergeben?
-Node.publishOurPeersLocationLong=Sollen wir die Position unserer Partner an 
unsere Partner weitergeben? Dies zu tun, hilft dem Routing gibt aber 
Informationen an potenzielle Angreifer preis.
+Node.publishOurPeersLocation=Sollen wir die Positionen unserer Partner an 
unsere Partner weitergeben?
+Node.publishOurPeersLocationLong=Sollen wir die Positionen unserer Partner an 
unsere Partner weitergeben? Dies zu tun, hilft dem Routing gibt aber 
Informationen an potenzielle Angreifer preis.
 Node.routeAccordingToOurPeersLocation=Sollen wir die Positionen der Partner 
unserer Partner zu Routing-Zwecken ber?cksichtigen?
 Node.routeAccordingToOurPeersLocationLong=Sollen wir die Positionen der 
Partner unserer Partner zu Routing-Zwecken ber?cksichtigen? Dies zu tun 
verbessert das Routing, k?nnte aber einem potenziellen Angreifer helfen.
 Node.storeDirectory=Speicher-Verzeichnis
@@ -711,6 +712,8 @@
 Node.tooSmallMTU=MTU zu niedrig
 Node.tooSmallMTULong=Die MTU ihrer Verbindung scheint ${mtu} Bytes zu sein. 
Freenet wird mit einer MTU unter ${minMTU} Bytes nicht gut funktionieren: 
Verbindungen werden unzuverl?ssig und wom?glich langsam sein. Bitte beheben Sie 
dieses Problem, wenn m?glich.
 Node.tooSmallMTUShort=Verbindungsprobleme: Die MTU Ihrer Verbindung ist zu 
klein damit Freenet gut funktioniert. Es sind Probleme zu erwarten.
+Node.withAnnouncement=Dem Knoten erlauben sich mit Hilfe von Seednodes 
automatisch zu verbinden?
+Node.withAnnouncementLong=Dem Knoten erlauben sich mit Hilfe von Seednodes 
(Saatknoten) automatisch zu verbinden? Obwohl dies die Standard-Einstellung 
darstellt, ist es prinzip-bedingt unsicher.
 NodeClientCore.couldNotFindOrCreateDir=Das Verzeichnis konnte weder gefunden 
noch angelegt werden
 NodeClientCore.downloadAllowedDirs=Verzeichnisse in welche das Herunterladen 
erlaubt ist
 NodeClientCore.downloadAllowedDirsLong=Per Semikolon getrennte Liste von 
Verzeichnissen, in welche das Herunterladen erlaubt ist. "downloads" steht f?r 
das Download-Verzeichnis, wenn das Feld leer ist bedeutet dies, dass keine 
Dateien auf Datentr?ger heruntergeladen werden d?rfen, "all" erlaubt das 
Herunterladen ?berall hin. WARNUNG! Wenn diese Option auf "all" gesetzt wird, 
kann jeder Benutzer jede Datei an jeden Ort auf Ihrem Computer herunterladen!
@@ -828,6 +831,10 @@
 PeersSayKeyBlownAlert.intro=Ein oder mehrere Ihrer Partner melden, dass der 
Schl?ssel der automatischen Aktualisierung unbrauchbar sei! Dies bedeutet, dass 
ein Angreifer den privaten Schl?ssel f?r das automatische 
Aktualisierungs-System kennen k?nnte und deshalb Ihren Knoten zur Ausf?hrung 
von Code seiner Wahl veranlassen k?nnte (wenn Sie aktualisieren)! Das 
automatische Aktualisierungs-System wurde ausgeschaltet. Es ist auch m?glich, 
dass Ihre Partner diesbez?glich bewusst l?gen.
 PeersSayKeyBlownAlert.short=Einige Ihrer Partner melden, dass der Schl?ssel 
f?r die automatischen Aktualisierungen unbrauchbar gemacht wurde!
 PeersSayKeyBlownAlert.titleWithCount=Laut ${count} Partner(n) ist der 
Schl?ssel der automatischen Aktualisierung unbrauchbar!
+PluginConfig.configFile=Plugin-Konfigurations-Datei
+PluginConfig.configFileLong=Pfad/Dateiname der Datei in welcher die 
Einstellungen der Plugins (Erweiterungen) gespeichert werden.
+PluginConfig.installDir=Plugin-Installations-Verzeichnis
+PluginConfig.installDirLong=Verzeichnis in dem die Plugins (Erweiterungen) 
installiert werden.
 PluginManager.cannotSetOnceLoaded=Kann die Plugin(=Erweiterungs)-Liste nicht 
modifizieren sobald sie geladen wurde
 PluginManager.loadedOnStartup=Plugins die beim Start geladen werden
 PluginManager.loadedOnStartupLong=Klassenpfad, Name und Verzeichnis f?r 
Plugins (Erweiterungen) die beim Start des Knotens geladen werden sollen
@@ -861,13 +868,17 @@
 PproxyToadlet.changeReloadOnStartup=?ndern
 PproxyToadlet.classNameTitle=Klassen-Name
 PproxyToadlet.downloadNotAllowedFromRemoteServer=Das downloaden von Plugins 
ist nur von unserem Server erlaubt.
+PproxyToadlet.fileonly=nur lokale Dateien
 PproxyToadlet.internalIDTitle=Interne ID
+PproxyToadlet.loadFreenetPlugin=Ein inoffizielles Plugin aus dem Freenet 
hinzuf?gen
+PproxyToadlet.loadFreenetPluginText=Hier k?nnen Sie die Freenet-URI eines 
Plugins das Sie laden m?chten eingeben. Diese Plugins werden von uns nicht im 
Entferntesten unterst?tzt oder darauf ?berpr?ft, ob sie private Informationen 
herausgeben. Wenn Sie also hier ein inoffizielles Plugin laden, sind Sie auf 
sich allein gestellt.
+PproxyToadlet.loadFreenetURLLabel=Schl?ssel des Plugins
 PproxyToadlet.loadOfficialPlugin=Ein offizielles Plugin hinzuf?gen
 PproxyToadlet.loadOfficialPluginLabel=Offizielles Plugin laden
 PproxyToadlet.loadOfficialPluginText=Diese Plugins liegen auf den Servern des 
Freenet-Projekts. Wir glauben, dass diese Plugins keine pers?nlichen 
Informationen ungefragt herausgeben, auch wenn wir es nicht garantieren.
 PproxyToadlet.loadOfficialPluginWarning=WARNUNG: Das Laden eines offiziellen 
Plugins beinhaltet das Herunterladen des Plugins aus dem Internet (nicht aus 
dem Freenet). Laden Sie hier keine Plugins herunter wenn dies ein Problem 
darstellt.
 PproxyToadlet.loadOtherPlugin=Ein inoffizielles Plugin hinzuf?gen
-PproxyToadlet.loadOtherPluginText=Hier k?nnen Sie die URL eines Plugins 
eingeben, das geladen werden soll. Andere Plugins als die oben aufgelisteten, 
werden von uns noch nicht einmal im Entferntesten unterst?tzt oder darauf 
gepr?ft, ob sie pers?nliche Informationen herausgeben. Wenn Sie also hier ein 
inoffizielles Plugin laden, sind Sie auf sich allein gestellt.
+PproxyToadlet.loadOtherPluginText=Hier k?nnen Sie die URL eines Plugins 
eingeben, das geladen werden soll. Andere Plugins als die oben aufgelisteten, 
werden von uns noch nicht einmal im Entferntesten unterst?tzt oder darauf 
?berpr?ft, ob sie pers?nliche Informationen herausgeben. Wenn Sie also hier ein 
inoffizielles Plugin laden, sind Sie auf sich allein gestellt.
 PproxyToadlet.loadOtherURLLabel=Plugin-URL
 PproxyToadlet.loadPluginLabel=Plugin laden:
 PproxyToadlet.noPlugins=Keine Plugins geladen

Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties
===================================================================
--- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -87,6 +87,10 @@
 ConfigToadlet.fproxy=fproxy
 ConfigToadlet.fullTitle=Freenet Node Configuration of ${name}
 ConfigToadlet.logger=logger
+ConfigToadlet.needRestartTitle=Node restart required
+ConfigToadlet.needRestart=Some config need restart to activate, please restart 
the node immediately.
+ConfigToadlet.needRestartShort=Some config need restart to activate, please 
restart the node immediately.
+ConfigToadlet.restartNode=Restart Now
 PageMaker.modeSimple=Simple interface
 PageMaker.modeSimpleTooltip=A simple interface all users can use
 PageMaker.modeAdvanced=Advanced interface
@@ -255,12 +259,10 @@
 FirstTimeWizardToadlet.chooseNodeName=Node name required!
 FirstTimeWizardToadlet.chooseNodeNameLong=Please enter a node name in the 
field below (we recommend a nickname possibly with an email address). This is 
so that your friends (trusted peers, which you have manually added) can easily 
tell your node from their other nodes. This is not visible to strangers 
(untrusted automatically added peers). Note that any friend or stranger may 
trivially identify you from your IP address, since you are connected to them, 
but they cannot easily tell what you are requesting.
 FirstTimeWizardToadlet.connectToStrangers=Connect to strangers?
-FirstTimeWizardToadlet.connectToStrangersLong=Ideally, all Freenet users would 
connect only to people they know. This is far more secure, making it very 
difficult for others to tell that you are using Freenet. However, if you don't 
know at least 5 people already running Freenet, you can choose to connect to 
strangers. Note that you can always turn this off later.
-FirstTimeWizardToadlet.enableOpennet=Do you know anyone already using Freenet?
-FirstTimeWizardToadlet.opennetYes=No, I want the node to automatically find 
strangers to connect to. 
-FirstTimeWizardToadlet.opennetNo=Yes, I have at least 5 friends already using 
Freenet and I will add their details on the Friends page.
-FirstTimeWizardToadlet.warningTitle=Warning!
-FirstTimeWizardToadlet.opennetWarning=If Freenet is illegal where you live, or 
if you are using it to access materials that may get you into trouble, telling 
the node to automatically connect to strangers may be dangerous as it makes 
life much easier for an attacker. Freenet is still experimental, and we offer 
no guarantees about security.
+FirstTimeWizardToadlet.connectToStrangersLong=To run Freenet, you must connect 
to at least five other nodes.  These should ideally be run by people whom you 
know and trust.  If you don't know enough friends running Freenet, you can 
choose to connect to strangers' nodes as well.  However, connecting to 
strangers allows others to find out that you are using Freenet and adds some 
additional security risks.  If you want to keep your use of Freenet secret, 
this may get you into trouble.
+FirstTimeWizardToadlet.enableOpennet=It is possible to turn off stranger 
connections later on, once you have added enough friends, although you will 
already have revealed some information to strangers in the meantime.  Freenet 
is still experimental, and we offer no guarantees about security.
+FirstTimeWizardToadlet.opennetYes=I want the node to automatically find 
strangers to connect to. 
+FirstTimeWizardToadlet.opennetNo=I have at least 5 friends already using 
Freenet and I will add their details on the Friends page.
 FirstTimeWizardToadlet.welcomeInfoboxTitle=Welcome to Freenet first time 
wizard!
 FirstTimeWizardToadlet.welcomeInfoboxContent1=Welcome to Freenet first time 
wizard. This tool will enable you to configure your node quickly and easily to 
get you started.
 FirstTimeWizardToadlet.bandwidthLimit=Bandwidth limits
@@ -720,6 +722,10 @@
 NodeClientCore.downloadAllowedDirsLong=Semicolon separated list of directories 
to which downloads are allowed. "downloads" means downloadsDir, empty means no 
downloads to disk allowed, "all" means downloads allowed from anywhere. 
WARNING! If this is set to "all" any user can download any file to anywhere on 
your computer!
 NodeClientCore.downloadDir=Default download directory
 NodeClientCore.downloadDirLong=The directory to save downloaded files into by 
default
+NodeClientCore.encryptPersistentTempBuckets=Encrypt the persistent temporary 
buckets? LEAVE THIS ALONE!
+NodeClientCore.encryptPersistentTempBucketsLong=Encrypt the persistent 
temporary buckets? In some cases (if you use hard-drive and swap encryption) it 
might not make sense to encrypt persistent temporary buckets. LEAVE THIS ALONE 
IF YOU DON'T KNOW WHAT YOU ARE DOING!
+NodeClientCore.encryptTempBuckets=Encrypt the temporary buckets? LEAVE THIS 
ALONE!
+NodeClientCore.encryptTempBucketsLong=Encrypt the temporary buckets? In some 
cases (if you use hard-drive and swap encryption) it might not make sense to 
encrypt temporary buckets. LEAVE THIS ALONE IF YOU DON'T KNOW WHAT YOU ARE 
DOING!
 NodeClientCore.fileForClientStats=File to store client statistics in
 NodeClientCore.fileForClientStatsLong=File to store client throttling 
statistics in (used to decide how often to send requests)
 NodeClientCore.lazyResume=Complete loading of persistent requests after 
startup? (Uses more memory)
@@ -730,6 +736,10 @@
 NodeClientCore.movingTempDirOnTheFlyNotSupported=Moving temp directory on the 
fly not supported at present
 NodeClientCore.persistentTempDir=Persistent temp files directory
 NodeClientCore.persistentTempDirLong=Name of directory to put persistent temp 
files in
+NodeClientCore.maxRAMBucketSize=Maximum size of a RAMBucket
+NodeClientCore.maxRAMBucketSizeLong=Maximum size of a RAMBucket (bigger 
buckets will be kept as files on the disk)
+NodeClientCore.ramBucketPoolSize=Amount of RAM to dedicate to temporary buckets
+NodeClientCore.ramBucketPoolSizeLong=Amount of RAM to dedicate to temporary 
buckets. The tradeoff is more memory usage against more IOs.
 NodeClientCore.startingUpTitle=Freenet is starting up
 NodeClientCore.startingUp=Please allow Freenet a few moments to complete the 
startup process, in the meantime some things may not work and the node may be 
slower than usual.
 NodeClientCore.startingUpShort=Freenet is starting up, some things may not 
work and the node may be slow.
@@ -1050,6 +1060,8 @@
 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.
+SimpleToadletServer.passthroughMaxSize=Maximum size for transparent 
pass-through in fproxy
+SimpleToadletServer.passthroughMaxSizeLong=Maximum size of a file for 
transparent pass-through in fproxy
 SimpleToadletServer.port=FProxy port
 SimpleToadletServer.portLong=The TCP port FProxy should listen on
 SimpleToadletServer.ssl=Enable SSL?

Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.fr.properties
===================================================================
--- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.fr.properties   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.fr.properties   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -285,6 +285,7 @@
 FProxyToadlet.notEnoughMetaStrings=Pas assez de m?ta-donn?es
 FProxyToadlet.notFoundTitle=Introuvable
 FProxyToadlet.openAsText=${link}Cliquez ici${/link} pour ouvrir le fichier en 
texte brut (ceci ne devrait pr?senter aucun danger mais risque d'?tre 
illisible).
+FProxyToadlet.openAsThawIndex=${link}Cliquer ici${/link} pour ouvrir ce 
fichier avec le navigateur d'index Thaw (lisez l'avertissement ci-dessus !).
 FProxyToadlet.openForce=${link}Cliquez ici${/link} pour ouvrir le fichier en 
tant que  ${mime} (lisez l'avertissement ci-dessus !).
 FProxyToadlet.openForceDisk=${link}Cliquez ici${/link} pour force le 
navigateur ? enregistrer le fichier sur le disque.
 FProxyToadlet.openPossRSSAsForceDisk=${link}Cliquez ici${/link} pour essayer 
de forcer votre navigateur ? enregistrer ce fichier sur le disque (${bold}ceci 
peut ?tre dangereux${/bold} si vous utilisez Firefox 2.0.0, les versions 
suivantes n'ont pas de probl?me).
@@ -719,6 +720,8 @@
 Node.tooSmallMTU=MTU trop faible
 Node.tooSmallMTULong=Le MTU de votre connexion est de ${mtu} octets. Freenet a 
besoin d'un MTU de ${minMTU} au moins pour fonctionner correctement : les 
connexions seront lentes et peu fiables. Corrigez ce probl?me si possible.
 Node.tooSmallMTUShort=Probl?mes de connexion : Le MTU de votre connexion est 
trop faible pour Freenet. Attendez-vous ? des probl?mes.
+Node.withAnnouncement=S'annoncer aux seednodes ?
+Node.withAnnouncementLong=Laisser le noeud s'annoncer aux seednodes ? C'est 
indispensable mais c'est un risque?
 NodeClientCore.couldNotFindOrCreateDir=Impossible de trouver ou de cr?er le 
dossier
 NodeClientCore.downloadAllowedDirs=Les dossiers de t?l?chargement autoris?s 
sont
 NodeClientCore.downloadAllowedDirsLong=Liste de dossiers (s?par?s par des ';') 
o? le t?l?chargement est autoris?. "downloads" correspond au dossier de 
t?l?chargement, laissez-la vide pour n'autoriser aucun t?l?chargement sur le 
disque dur, "all" autorise les t?l?chargements partout !
@@ -836,6 +839,10 @@
 PeersSayKeyBlownAlert.intro=Au moins un des noeuds auxquels vous ?tes connect? 
affirme que la cl? de mise ? jour est compromise ! Cela signifie qu'il est 
possible qu'un attaquant connaisse la cl? du syst?me de mise ? jour automatique 
et l'utilise pour essayer de vous pirater (si vous acceptez la mise ? jour) ! 
Le syst?me de mise ? jour automatique a ?t? d?sactiv?. Il est aussi possible 
que ces noeuds mentent d?lib?r?ment.
 PeersSayKeyBlownAlert.short=Certains noeuds disent que la cl? de mise ? jour 
automatique a ?t? compromise !
 PeersSayKeyBlownAlert.titleWithCount=${count} noeud(s) affirme(nt) que la cl? 
de mise ? jour automatique est compromise !
+PluginConfig.configFile=Fichier de configuration des plugins
+PluginConfig.configFileLong=Chemin du fichier de configuration des plugins
+PluginConfig.installDir=Dossier d'installation des plugins
+PluginConfig.installDirLong=Dossier d'installation des plugins
 PluginManager.cannotSetOnceLoaded=Impossible de d?finir la liste des plugins 
une fois d?marr?
 PluginManager.loadedOnStartup=Plugins ? charger au d?marrage
 PluginManager.loadedOnStartupLong=Classpath, nom et emplacement des plugins ? 
charger au d?marrage du node
@@ -869,11 +876,15 @@
 PproxyToadlet.changeReloadOnStartup=Changer
 PproxyToadlet.classNameTitle=Nom de Class
 PproxyToadlet.downloadNotAllowedFromRemoteServer=Le t?l?chargement de plugins 
n'est autoris? que depuis notre serveur.
+PproxyToadlet.fileonly=Fichiers locaux uniquement
 PproxyToadlet.internalIDTitle=ID interne
+PproxyToadlet.loadFreenetPlugin=Chargez un plugin non officiel depuis Freenet
+PproxyToadlet.loadFreenetPluginText=Vous pouvez entrer la cl? Freenet d'un 
plugin que vous voulez charger. Ces plugins ne sont ni support?s ni m?me test?s 
par le projet. Si vous en chargez un, vous ?tes livr? ? vous m?me.
+PproxyToadlet.loadFreenetURLLabel=Cl? du plugin
 PproxyToadlet.loadOfficialPlugin=Ajouter un plugin officiel
 PproxyToadlet.loadOfficialPluginLabel=Charger un plugin officiel
 PproxyToadlet.loadOfficialPluginText=Ces plugins sont h?berg?s sur les 
serveurs du projet Freenet. Nous pensons que ces plugins ne contiennent pas de 
failles de s?curit?, sans toutefois le garantir.
-PproxyToadlet.loadOfficialPluginWarning=ATTENTION : Charger un plugin officiel 
implique de le t?l?charger sur internet (pas sur freenet). Un attaquant 
pourrait le d?tecter et peut-?tre interf?rer. Ne chargez pas de plugins si vous 
pensez qu'il y a un risque.
+PproxyToadlet.loadOfficialPluginWarning=ATTENTION : Charger un plugin officiel 
implique de le t?l?charger sur internet (pas sur freenet). Ne chargez pas de 
plugins si vous pensez qu'il y a un risque.
 PproxyToadlet.loadOtherPlugin=Charger un plugin non-officiel
 PproxyToadlet.loadOtherPluginText=Vous pouvez entrer l'URL d'un plugin que 
vous voulez charger. Les plugins qui ne sont pas list?s ci-dessus ne sont pas 
support?s et leur s?curit? n'est pas v?rifi?e. Donc, si vous chargez un plugin 
ici, vous ?tes livr? ? vous m?me.
 PproxyToadlet.loadOtherURLLabel=URL du plugin
@@ -1065,7 +1076,7 @@
 SimpleToadletServer.sslLong=Activer SSL pour FProxy
 StartupToadlet.entropyErrorContent=Il n'y a pas assez d'entropy sur votre 
syst?me... Freenet ne d?marrera pas avant d'en avoir suffisament.
 StartupToadlet.entropyErrorTitle=Pas assez d'entropie disponible !
-StartupToadlet.isStartingUp=D?arrage de Freenet en cours, veuillez patienter.
+StartupToadlet.isStartingUp=D?marrage de Freenet en cours, veuillez patienter.
 StartupToadlet.title=D?marrage de Freenet
 StaticToadlet.pathInvalidChars=Cette URI contient des caract?res interdits.
 StaticToadlet.pathNotFound=Le chemin sp?cifi? n'existe pas.

Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties
===================================================================
--- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -878,7 +878,7 @@
 PproxyToadlet.changeReloadOnStartup=??
 PproxyToadlet.classNameTitle=????
 PproxyToadlet.downloadNotAllowedFromRemoteServer=??????????????.
-PproxyToadlet.fileonly=??????
+PproxyToadlet.fileonly=???????
 PproxyToadlet.internalIDTitle=?????
 PproxyToadlet.loadFreenetPlugin=? Freenet ????????
 PproxyToadlet.loadFreenetPluginText=????????????????? Freenet URI. 
???????????, ??????????????, ??????????, ????????????.
@@ -886,7 +886,7 @@
 PproxyToadlet.loadOfficialPlugin=??????
 PproxyToadlet.loadOfficialPluginLabel=??????
 PproxyToadlet.loadOfficialPluginText=?????? Freenet ???????. ????????????????, 
????????.
-PproxyToadlet.loadOfficialPluginWarning=??: ????????????????, ??? Freenet ??. 
?????????????, ?????. ?????????????, ??????????.
+PproxyToadlet.loadOfficialPluginWarning=??: ????????????????, ??? Freenet ??. 
?????????????, ??????????.
 PproxyToadlet.loadOtherPlugin=???????
 PproxyToadlet.loadOtherPluginText=?????????????? URL. ???????????????????, 
???????????????????. ????????????????????, ????????.
 PproxyToadlet.loadOtherURLLabel=??? URL

Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties
===================================================================
--- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -877,7 +877,7 @@
 PproxyToadlet.changeReloadOnStartup=??
 PproxyToadlet.classNameTitle=????
 PproxyToadlet.downloadNotAllowedFromRemoteServer=????????????????.
-PproxyToadlet.fileonly=??????
+PproxyToadlet.fileonly=???????
 PproxyToadlet.internalIDTitle=?????
 PproxyToadlet.loadFreenetPlugin=? Freenet ??????????
 PproxyToadlet.loadFreenetPluginText=????????????????? Freenet URI. 
???????????, ??????????????, ??????????, ????????????.
@@ -885,7 +885,7 @@
 PproxyToadlet.loadOfficialPlugin=??????
 PproxyToadlet.loadOfficialPluginLabel=??????
 PproxyToadlet.loadOfficialPluginText=???????? Freenet ???????. 
????????????????, ????????.
-PproxyToadlet.loadOfficialPluginWarning=??: ?????????????????, ??? Freenet ??. 
?????????????, ?????. ?????????????, ??????????.
+PproxyToadlet.loadOfficialPluginWarning=??: ?????????????????, ??? Freenet ??. 
?????????????, ??????????.
 PproxyToadlet.loadOtherPlugin=???????
 PproxyToadlet.loadOtherPluginText=?????????????? URL. ???????????????????, 
???????????????????. ????????????????????, ????????.
 PproxyToadlet.loadOtherURLLabel=??? URL

Modified: branches/db4o/freenet/src/freenet/node/ConfigurablePersister.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/ConfigurablePersister.java   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/ConfigurablePersister.java   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -22,7 +22,6 @@
                        public void set(String val) throws 
InvalidConfigValueException {
                                setThrottles(val);
                        }
-                       
                });

                String throttleFile = nodeConfig.getString(optionName);

Modified: branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -43,7 +43,6 @@
 import freenet.support.HexUtil;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
-import freenet.support.StringArray;
 import freenet.support.TimeUtil;
 import freenet.support.WouldBlockException;
 import freenet.support.io.NativeThread;
@@ -95,7 +94,7 @@
        /* How often shall we generate a new exponential and add it to the 
FIFO? */
        public final static int DH_GENERATION_INTERVAL = 30000; // 30sec
        /* How big is the FIFO? */
-       public final static int DH_CONTEXT_BUFFER_SIZE = 10;
+       public final static int DH_CONTEXT_BUFFER_SIZE = 20;
        /*
        * The FIFO itself
        * Get a lock on dhContextFIFO before touching it!
@@ -1634,10 +1633,9 @@
         */
        private void sendAuthPacket(byte[] output, BlockCipher cipher, PeerNode 
pn, Peer replyTo, boolean anonAuth) {
                int length = output.length;
-               // FIXME shorten seednode phase 3/4 so it's within the limit
-//             if(length > sock.getMaxPacketSize()) {
-//                     throw new IllegalStateException("Cannot send auth 
packet: too long: "+length);
-//             }
+               if(length > sock.getMaxPacketSize()) {
+                       throw new IllegalStateException("Cannot send auth 
packet: too long: "+length);
+               }
                PCFBMode pcfb = PCFBMode.create(cipher);
                byte[] iv = new byte[pcfb.lengthIV()];
                node.random.nextBytes(iv);
@@ -2077,7 +2075,7 @@
                                alreadyReported[x] = mi.alreadyReportedBytes;
                                x++;
                                if(mi.cb != null) callbacksCount += 
mi.cb.length;
-                               if(logMINOR) Logger.minor(this, "Sending: 
"+mi+" length "+data.length+" cb "+ StringArray.toString(mi.cb)+" reported 
"+mi.alreadyReportedBytes);
+                               if(logMINOR) Logger.minor(this, "Sending: 
"+mi+" length "+data.length+" cb "+ Arrays.toString(mi.cb)+" reported 
"+mi.alreadyReportedBytes);
                                length += (data.length + 2);
                        }
                }
@@ -2294,7 +2292,7 @@
                if(logMINOR) {
                        String log = 
"processOutgoingPreformatted("+Fields.hashCode(buf)+", "+offset+ ',' +length+ 
',' +tracker+ ',' +packetNumber+ ',';
                        if(callbacks == null) log += "null";
-                       else log += 
""+callbacks.length+StringArray.toString(callbacks); // FIXME too verbose?
+                       else log += 
""+callbacks.length+Arrays.toString(callbacks); // FIXME too verbose?
                        Logger.minor(this, log);
                }
                if((tracker == null) || (!tracker.pn.isConnected())) {
@@ -2833,10 +2831,8 @@
                        // reset the authenticator cache
                        authenticatorCache.clear();
                }
-               if(logMINOR)
-                       Logger.minor(this, "Reset the JFK transitent key 
because "+(isCacheTooBig ? ("the cache's capacity is exeeded 
("+authenticatorCache.size()+')') : "it's time to rekey") + this);
                node.getTicker().queueTimedJob(transientKeyRekeyer, 
"JFKmaybeResetTransitentKey "+now, TRANSIENT_KEY_REKEYING_MIN_INTERVAL, false);
-               Logger.normal(this, "JFK's TransientKey has been changed and 
the message cache flushed.");
+               Logger.normal(this, "JFK's TransientKey has been changed and 
the message cache flushed because "+(isCacheTooBig ? ("the cache is oversized 
("+authenticatorCache.size()+')') : "it's time to rekey")+ " on " + this);
                return true;
        }


Modified: branches/db4o/freenet/src/freenet/node/FailureTable.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/FailureTable.java    2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/FailureTable.java    2008-09-24 
20:42:20 UTC (rev 22823)
@@ -98,12 +98,9 @@
                FailureTableEntry entry;
                synchronized(this) {
                        entry = (FailureTableEntry) entriesByKey.get(key);
-                       if(entry == null) {
+                       if(entry == null)
                                entry = new FailureTableEntry(key);
-                               entriesByKey.push(key, entry);
-                       } else {
-                               entriesByKey.push(key, entry);
-                       }
+                       entriesByKey.push(key, entry);
                        trimEntries(now);
                }
                entry.failedTo(routedTo, timeout, now, htl);
@@ -115,12 +112,10 @@
                FailureTableEntry entry;
                synchronized(this) {
                        entry = (FailureTableEntry) entriesByKey.get(key);
-                       if(entry == null) {
+                       if(entry == null)
                                entry = new FailureTableEntry(key);
-                               entriesByKey.push(key, entry);
-                       } else {
-                               entriesByKey.push(key, entry);
-                       }
+                       entriesByKey.push(key, entry);
+
                        trimEntries(now);
                }
                if(routedTo != null)

Modified: branches/db4o/freenet/src/freenet/node/FailureTableEntry.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/FailureTableEntry.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/FailureTableEntry.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -8,7 +8,7 @@

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

 class FailureTableEntry implements TimedOutNodesList {

@@ -75,7 +75,7 @@
         */
        public void onFailure(short htl2, PeerNode[] requestors, PeerNode[] 
requestedFrom, int timeout, long now) {
                if(logMINOR)
-                       Logger.minor(this, 
"onFailure("+htl2+",requestors="+StringArray.toString(requestors)+",requestedFrom="+StringArray.toString(requestedFrom)+",timeout="+timeout);
+                       Logger.minor(this, 
"onFailure("+htl2+",requestors="+Arrays.toString(requestors)+",requestedFrom="+Arrays.toString(requestedFrom)+",timeout="+timeout);
                synchronized(this) {
                        if(requestors != null) {
                                for(int i=0;i<requestors.length;i++)

Modified: branches/db4o/freenet/src/freenet/node/GlobalProbe.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/GlobalProbe.java     2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/GlobalProbe.java     2008-09-24 
20:42:20 UTC (rev 22823)
@@ -4,20 +4,20 @@
 package freenet.node;

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

 public class GlobalProbe implements Runnable {

        double lastLocation = 0.0;
        long lastTime;
        int lastHops;
-       boolean doneSomething = false;
+       private boolean doneSomething = false;
        final ProbeCallback cb;
        final Node node;
        int ctr;
        final int probeType;

-       GlobalProbe(Node n, int probeType) {
+       public GlobalProbe(Node n, int probeType) {
                this.node = n;
                this.probeType = probeType;
        cb = new ProbeCallback() {
@@ -33,7 +33,7 @@
                        }

                        public void onTrace(long uid, double target, double 
nearest, double best, short htl, short counter, double location, long nodeUID, 
double[] peerLocs, long[] peerUIDs, double[] locsNotVisited, short forkCount, 
short linearCount, String reason, long prevUID) {
-                               String msg = "Probe trace: UID="+uid+" 
target="+target+" nearest="+nearest+" best="+best+" htl="+htl+" 
counter="+counter+" location="+location+" node UID="+nodeUID+" prev 
UID="+prevUID+" peers="+NodeDispatcher.peersUIDsToString(peerUIDs, peerLocs)+" 
locs not visited: "+StringArray.toString(locsNotVisited)+" fork count: 
"+forkCount+" linear count: "+linearCount+" from "+reason;
+                               String msg = "Probe trace: UID="+uid+" 
target="+target+" nearest="+nearest+" best="+best+" htl="+htl+" 
counter="+counter+" location="+location+" node UID="+nodeUID+" prev 
UID="+prevUID+" peers="+NodeDispatcher.peersUIDsToString(peerUIDs, peerLocs)+" 
locs not visited: "+Arrays.toString(locsNotVisited)+" fork count: "+forkCount+" 
linear count: "+linearCount+" from "+reason;
                                Logger.normal(this, msg);
                        }

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

        private void error(String string) {
                Logger.error(this, string);
-               System.out.println("GlobalProbe error: "+string);
+               System.err.println("GlobalProbe error: "+string);
        }
-       
-
 }

Modified: branches/db4o/freenet/src/freenet/node/IPDetectorPluginManager.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/IPDetectorPluginManager.java 
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/IPDetectorPluginManager.java 
2008-09-24 20:42:20 UTC (rev 22823)
@@ -277,7 +277,7 @@
         */
        public int[] getUDPPortsNotForwarded() {
                OpennetManager om = node.getOpennet();
-               int darknetStatus = 
node.darknetCrypto.getDetectedConnectivityStatus();
+               int darknetStatus = (node.peers.anyDarknetPeers() ? 
node.darknetCrypto.getDetectedConnectivityStatus() : 
AddressTracker.MAYBE_PORT_FORWARDED);
                int opennetStatus = om == null ? AddressTracker.DONT_KNOW : 
om.crypto.getDetectedConnectivityStatus();
                if(om == null || opennetStatus > AddressTracker.DONT_KNOW) {
                        if(darknetStatus > AddressTracker.DONT_KNOW) {
@@ -289,7 +289,7 @@
                        if(darknetStatus > AddressTracker.DONT_KNOW) {
                                return new int[] { (opennetStatus < 
AddressTracker.DONT_KNOW ? -1 : 1 ) * om.crypto.portNumber };
                        } else {
-                               return new int[] { (darknetStatus < 
AddressTracker.DONT_KNOW ? -1 : 1 ) * node.getDarknetPortNumber(), 
+                               return new int[] { ((darknetStatus < 
AddressTracker.DONT_KNOW) ? -1 : 1 ) * node.getDarknetPortNumber(), 
                                                (opennetStatus < 
AddressTracker.DONT_KNOW ? -1 : 1 ) * om.crypto.portNumber };
                        }
                }

Modified: branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java    
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java    
2008-09-24 20:42:20 UTC (rev 22823)
@@ -8,6 +8,7 @@

 import freenet.config.EnumerableOptionCallback;
 import freenet.config.InvalidConfigValueException;
+import freenet.config.NodeNeedRestartException;
 import freenet.config.OptionFormatException;
 import freenet.config.SubConfig;
 import freenet.support.Executor;
@@ -23,7 +24,7 @@
 import freenet.support.api.StringCallback;

 public class LoggingConfigHandler {
-       private static class PriorityCallback implements StringCallback, 
EnumerableOptionCallback {
+       private static class PriorityCallback extends StringCallback implements 
EnumerableOptionCallback {
                private final String[] possibleValues = new String[]{ "ERROR", 
"NORMAL", "MINOR", "DEBUG" };

                public String get() {
@@ -45,7 +46,7 @@

                public void setPossibleValues(String[] val) {
                        throw new NullPointerException("Should not happen!");
-               }
+                }
        }

        protected static final String LOG_PREFIX = "freenet";
@@ -64,10 +65,10 @@

        loggingConfig.register("enabled", true, 1, true, false, 
"LogConfigHandler.enabled", "LogConfigHandler.enabledLong",
                        new BooleanCallback() {
-                                       public boolean get() {
+                                       public Boolean get() {
                                                return fileLoggerHook != null;
                                        }
-                                       public void set(boolean val) throws 
InvalidConfigValueException {
+                                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                                if(val == (fileLoggerHook != 
null)) return;
                                                if(!val) {
                                                        disableLogger();
@@ -110,11 +111,12 @@

        config.register("maxZippedLogsSize", "128M", 3, true, true, 
"LogConfigHandler.maxZippedLogsSize", "LogConfigHandler.maxZippedLogsSizeLong",
                        new LongCallback() {
-                                       public long get() {
+                                       public Long get() {
                                                return maxZippedLogsSize;
                                        }
-                                       public void set(long val) throws 
InvalidConfigValueException {
-                                               if(val < 0) val = 0;
+                                       public void set(Long val) throws 
InvalidConfigValueException {
+                                               if (val < 0)
+                                               val = 0L;
                                                maxZippedLogsSize = val;
                                                if(fileLoggerHook != null) {
                                                        
fileLoggerHook.setMaxOldLogsSize(val);
@@ -179,11 +181,12 @@
        // max cached bytes in RAM
        config.register("maxCachedBytes", "10M", 6, true, false, 
"LogConfigHandler.maxCachedBytes", "LogConfigHandler.maxCachedBytesLong", 
                        new LongCallback() {
-                                       public long get() {
+                                       public Long get() {
                                                return maxCachedLogBytes;
                                        }
-                                       public void set(long val) throws 
InvalidConfigValueException {
-                                               if(val < 0) val = 0;
+                                       public void set(Long val) throws 
InvalidConfigValueException {
+                                               if (val < 0)
+                                               val = 0L;
                                                if(val == maxCachedLogBytes) 
return;
                                                maxCachedLogBytes = val;
                                                if(fileLoggerHook != null)
@@ -196,10 +199,10 @@
        // max cached lines in RAM
        config.register("maxCachedLines", "100k", 7, true, false, 
"LogConfigHandler.maxCachedLines", "LogConfigHandler.maxCachedLinesLong",
                        new IntCallback() {
-                                       public int get() {
+                                       public Integer get() {
                                                return maxCachedLogLines;
                                        }
-                                       public void set(int val) throws 
InvalidConfigValueException {
+                                       public void set(Integer val) throws 
InvalidConfigValueException {
                                                if(val < 0) val = 0;
                                                if(val == maxCachedLogLines) 
return;
                                                maxCachedLogLines = val;
@@ -237,6 +240,10 @@
                        } catch (InvalidConfigValueException e2) {
                                System.err.println("Invalid config value for 
logger.priority in config file: "+config.getString("priority"));
                                // Leave it at the default.
+                       } catch (NodeNeedRestartException e) {
+                               // impossible
+                               System.err.println("impossible 
NodeNeedRestartException for logger.priority in config file: "
+                                       + config.getString("priority"));
                        }
                        FileLoggerHook hook;
                        try {
@@ -344,7 +351,8 @@
                return maxZippedLogsSize;
        }

-       public void setMaxZippedLogFiles(String maxSizeAsString) throws 
InvalidConfigValueException {
+       public void setMaxZippedLogFiles(String maxSizeAsString) throws 
InvalidConfigValueException,
+               NodeNeedRestartException {
                config.set("maxZippedLogsSize", maxSizeAsString);
        }


Modified: branches/db4o/freenet/src/freenet/node/Node.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/Node.java    2008-09-24 19:52:19 UTC 
(rev 22822)
+++ branches/db4o/freenet/src/freenet/node/Node.java    2008-09-24 20:42:20 UTC 
(rev 22823)
@@ -3,6 +3,7 @@

 import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileFilter;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -45,6 +46,7 @@
 import freenet.config.FreenetFilePersistentConfig;
 import freenet.config.InvalidConfigValueException;
 import freenet.config.LongOption;
+import freenet.config.NodeNeedRestartException;
 import freenet.config.PersistentConfig;
 import freenet.config.SubConfig;
 import freenet.crypt.DSAPublicKey;
@@ -127,7 +129,6 @@
 import freenet.support.io.FileUtil;
 import freenet.support.io.NativeThread;
 import freenet.support.transport.ip.HostnameSyntaxException;
-import java.io.FileFilter;

 /**
  * @author amphibian
@@ -141,7 +142,7 @@
        private static TimeSkewDetectedUserAlert timeSkewDetectedUserAlert;
        private final static ClockProblemDetectedUserAlert 
clockProblemDetectedUserAlert = new ClockProblemDetectedUserAlert();

-       public class NodeNameCallback implements StringCallback {
+       public class NodeNameCallback extends StringCallback  {
                GetPubkey node;

                NodeNameCallback(GetPubkey n) {
@@ -179,30 +180,40 @@
                }
        }

-       private class StoreTypeCallback implements StringCallback, 
EnumerableOptionCallback {
+       private class StoreTypeCallback extends StringCallback implements 
EnumerableOptionCallback {
+               private String cachedStoreType;

                public String get() {
-                       return storeType;
+                       if (cachedStoreType == null)
+                               cachedStoreType = storeType;
+                       return cachedStoreType;
                }

-               public void set(String val) throws InvalidConfigValueException {
-                       throw new InvalidConfigValueException("Store type 
cannot be changed on the fly");
+               public void set(String val) throws InvalidConfigValueException, 
NodeNeedRestartException {
+                       boolean found = false;
+                       for (String p : getPossibleValues()) {
+                               if (p.equals(val)) {
+                                       found = true;
+                                       break;
+                               }
+                       }
+                       if (!found)
+                               throw new InvalidConfigValueException("Invalid 
store type");
+                       
+                       cachedStoreType = val;
+                       throw new NodeNeedRestartException("Store type cannot 
be changed on the fly");
                }

                public String[] getPossibleValues() {
-                       return new String[] {
-                                       "bdb-index",
-                                       "ram"
-                       };
+                       return new String[] { "bdb-index", "ram" };
                }

                public void setPossibleValues(String[] val) {
                        throw new UnsupportedOperationException();
                }
-               
        }

-       private static class L10nCallback implements StringCallback, 
EnumerableOptionCallback {
+       private static class L10nCallback extends StringCallback implements 
EnumerableOptionCallback {

                public String get() {
                        return 
L10n.mapLanguageNameToLongName(L10n.getSelectedLanguage());
@@ -483,7 +494,6 @@

        // Things that's needed to keep track of
        public final PluginManager pluginManager;
-       public freenet.oldplugins.plugin.PluginManager pluginManager2;

        // Helpers
        public final InetAddress localhostAddress;
@@ -777,6 +787,9 @@
                                                // Don't translate the below as 
very few users will use it.
                                                throw new 
InvalidConfigValueException("Moving node directory on the fly not supported at 
present");
                                        }
+                                       public boolean isReadOnly() {
+                                       return true;
+                               }
                });

                nodeDir = new File(nodeConfig.getString("nodeDir"));
@@ -910,11 +923,11 @@
                nodeConfig.register("disableProbabilisticHTLs", false, 
sortOrder++, true, false, "Node.disablePHTLS", "Node.disablePHTLSLong", 
                                new BooleanCallback() {

-                                       public boolean get() {
+                                       public Boolean get() {
                                                return disableProbabilisticHTLs;
                                        }

-                                       public void set(boolean val) throws 
InvalidConfigValueException {
+                                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                                disableProbabilisticHTLs = val;
                                        }

@@ -924,11 +937,11 @@

                nodeConfig.register("maxHTL", DEFAULT_MAX_HTL, sortOrder++, 
true, false, "Node.maxHTL", "Node.maxHTLLong", new ShortCallback() {

-                                       public short get() {
+                                       public Short get() {
                                                return maxHTL;
                                        }

-                                       public void set(short val) throws 
InvalidConfigValueException {
+                                       public void set(Short val) throws 
InvalidConfigValueException {
                                                if(maxHTL < 0) throw new 
InvalidConfigValueException("Impossible max HTL");
                                                maxHTL = val;
                                        }
@@ -952,63 +965,75 @@

                nodeConfig.register("enableARKs", true, sortOrder++, true, 
false, "Node.enableARKs", "Node.enableARKsLong", new BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return enableARKs;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                throw new InvalidConfigValueException("Cannot 
change on the fly");
                        }
-                       
+
+                       public boolean isReadOnly() {
+                                       return true;
+                               }                       
                });
                enableARKs = nodeConfig.getBoolean("enableARKs");

                nodeConfig.register("enablePerNodeFailureTables", true, 
sortOrder++, true, false, "Node.enablePerNodeFailureTables", 
"Node.enablePerNodeFailureTablesLong", new BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return enablePerNodeFailureTables;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                throw new InvalidConfigValueException("Cannot 
change on the fly");
                        }
-                       
+
+                       public boolean isReadOnly() {
+                                       return true;
+                             }                 
                });
                enablePerNodeFailureTables = 
nodeConfig.getBoolean("enablePerNodeFailureTables");

                nodeConfig.register("enableULPRDataPropagation", true, 
sortOrder++, true, false, "Node.enableULPRDataPropagation", 
"Node.enableULPRDataPropagationLong", new BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return enableULPRDataPropagation;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                throw new InvalidConfigValueException("Cannot 
change on the fly");
                        }
-                       
+
+                       public boolean isReadOnly() {
+                                       return true;
+                               }                       
                });
                enableULPRDataPropagation = 
nodeConfig.getBoolean("enableULPRDataPropagation");

                nodeConfig.register("enableSwapping", true, sortOrder++, true, 
false, "Node.enableSwapping", "Node.enableSwappingLong", new BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return enableSwapping;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                throw new InvalidConfigValueException("Cannot 
change on the fly");
                        }
-                       
+
+                       public boolean isReadOnly() {
+                                       return true;
+                               }                       
                });
                enableSwapping = nodeConfig.getBoolean("enableSwapping");

                nodeConfig.register("publishOurPeersLocation", false, 
sortOrder++, true, false, "Node.publishOurPeersLocation", 
"Node.publishOurPeersLocationLong", new BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return publishOurPeersLocation;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                publishOurPeersLocation = val;
                        }
                });
@@ -1016,22 +1041,22 @@

                nodeConfig.register("routeAccordingToOurPeersLocation", false, 
sortOrder++, true, false, "Node.routeAccordingToOurPeersLocation", 
"Node.routeAccordingToOurPeersLocationLong", new BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return routeAccordingToOurPeersLocation;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                routeAccordingToOurPeersLocation = val;
                        }
                });
                routeAccordingToOurPeersLocation = 
nodeConfig.getBoolean("routeAccordingToOurPeersLocation");

                nodeConfig.register("enableSwapQueueing", true, sortOrder++, 
true, false, "Node.enableSwapQueueing", "Node.enableSwapQueueingLong", new 
BooleanCallback() {
-                       public boolean get() {
+                       public Boolean get() {
                                return enableSwapQueueing;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                enableSwapQueueing = val;
                        }

@@ -1039,11 +1064,11 @@
                enableSwapQueueing = 
nodeConfig.getBoolean("enableSwapQueueing");

                nodeConfig.register("enablePacketCoalescing", true, 
sortOrder++, true, false, "Node.enablePacketCoalescing", 
"Node.enablePacketCoalescingLong", new BooleanCallback() {
-                       public boolean get() {
+                       public Boolean get() {
                                return enablePacketCoalescing;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                enablePacketCoalescing = val;
                        }

@@ -1088,11 +1113,11 @@
                // Bandwidth limit

                nodeConfig.register("outputBandwidthLimit", "15K", sortOrder++, 
false, true, "Node.outBWLimit", "Node.outBWLimitLong", new IntCallback() {
-                                       public int get() {
+                                       public Integer get() {
                                                //return 
BlockTransmitter.getHardBandwidthLimit();
                                                return outputBandwidthLimit;
                                        }
-                                       public void set(int obwLimit) throws 
InvalidConfigValueException {
+                                       public void set(Integer obwLimit) 
throws InvalidConfigValueException {
                                                if(obwLimit <= 0) throw new 
InvalidConfigValueException(l10n("bwlimitMustBePositive"));
                                                synchronized(Node.this) {
                                                        outputBandwidthLimit = 
obwLimit;
@@ -1113,11 +1138,11 @@
                outputThrottle = new DoubleTokenBucket(obwLimit/2, 
(1000L*1000L*1000L) / obwLimit, obwLimit/2, 0.8);

                nodeConfig.register("inputBandwidthLimit", "-1", sortOrder++, 
false, true, "Node.inBWLimit", "Node.inBWLimitLong",      new IntCallback() {
-                                       public int get() {
+                                       public Integer get() {
                                                if(inputLimitDefault) return -1;
                                                return inputBandwidthLimit;
                                        }
-                                       public void set(int ibwLimit) throws 
InvalidConfigValueException {
+                                       public void set(Integer ibwLimit) 
throws InvalidConfigValueException {
                                                synchronized(Node.this) {
                                                        if(ibwLimit == -1) {
                                                                
inputLimitDefault = true;
@@ -1142,11 +1167,11 @@

                nodeConfig.register("throttleLocalTraffic", false, sortOrder++, 
true, false, "Node.throttleLocalTraffic", "Node.throttleLocalTrafficLong", new 
BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return throttleLocalData;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                throttleLocalData = val;
                        }

@@ -1177,7 +1202,9 @@
                                try {
                                        
logConfigHandler.setMaxZippedLogFiles(TESTNET_MIN_MAX_ZIPPED_LOGFILES_STRING);
                                } catch (InvalidConfigValueException e) {
-                                       throw new Error("Impossible: "+e);
+                                       throw new Error("Impossible: " + e, e);
+                               } catch (NodeNeedRestartException e) {
+                                       throw new Error("Impossible: " + e, e);
                                }
                        }
                } else {
@@ -1245,10 +1272,10 @@

                final SubConfig opennetConfig = new SubConfig("node.opennet", 
config);
                opennetConfig.register("connectToSeednodes", true, 0, true, 
false, "Node.withAnnouncement", "Node.withAnnouncementLong", new 
BooleanCallback() {
-                       public boolean get() {
+                       public Boolean get() {
                                return isAllowedToConnectToSeednodes;
                        }
-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                if(val == get()) return;
                                synchronized(Node.this) {
                                        if(opennet != null)
@@ -1257,17 +1284,21 @@
                                                isAllowedToConnectToSeednodes = 
val;
                                }
                        }
+
+                       public boolean isReadOnly() {
+                                       return opennet != null;
+                               }
                });
                isAllowedToConnectToSeednodes = 
opennetConfig.getBoolean("connectToSeednodes");

                // Can be enabled on the fly
                opennetConfig.register("enabled", false, 0, false, true, 
"Node.opennetEnabled", "Node.opennetEnabledLong", new BooleanCallback() {
-                       public boolean get() {
+                       public Boolean get() {
                                synchronized(Node.this) {
                                        return opennet != null;
                                }
                        }
-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                OpennetManager o;
                                synchronized(Node.this) {
                                        if(val == (opennet != null)) return;
@@ -1292,10 +1323,10 @@

                opennetConfig.register("maxOpennetPeers", "20", 1, true, false, 
"Node.maxOpennetPeers",
                                "Node.maxOpennetPeersLong", new IntCallback() {
-                                       public int get() {
+                                       public Integer get() {
                                                return maxOpennetPeers;
                                        }
-                                       public void set(int 
inputMaxOpennetPeers) throws InvalidConfigValueException {
+                                       public void set(Integer 
inputMaxOpennetPeers) throws InvalidConfigValueException {
                                                if(inputMaxOpennetPeers < 0) 
throw new InvalidConfigValueException(l10n("mustBePositive"));
                                                if(inputMaxOpennetPeers > 20) 
throw new 
InvalidConfigValueException(l10n("maxOpennetPeersMustBeTwentyOrLess"));
                                                maxOpennetPeers = 
inputMaxOpennetPeers;
@@ -1320,11 +1351,11 @@

                opennetConfig.register("acceptSeedConnections", true, 2, true, 
true, "Node.acceptSeedConnectionsShort", "Node.acceptSeedConnections", new 
BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return acceptSeedConnections;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                acceptSeedConnections = val;
                        }

@@ -1337,13 +1368,13 @@
                nodeConfig.register("passOpennetPeersThroughDarknet", true, 
sortOrder++, true, false, "Node.passOpennetPeersThroughDarknet", 
"Node.passOpennetPeersThroughDarknetLong",
                                new BooleanCallback() {

-                                       public boolean get() {
+                                       public Boolean get() {
                                                synchronized(Node.this) {
                                                        return 
passOpennetRefsThroughDarknet;
                                                }
                                        }

-                                       public void set(boolean val) throws 
InvalidConfigValueException {
+                                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                                synchronized(Node.this) {
                                                        
passOpennetRefsThroughDarknet = val;
                                                }
@@ -1364,6 +1395,9 @@
                                                // FIXME
                                                throw new 
InvalidConfigValueException("Moving extra peer data directory on the fly not 
supported at present");
                                        }
+                                       public boolean isReadOnly() {
+                                       return true;
+                               }
                });
                extraPeerDataDir = new 
File(nodeConfig.getString("extraPeerDataDir"));
                if(!((extraPeerDataDir.exists() && 
extraPeerDataDir.isDirectory()) || (extraPeerDataDir.mkdir()))) {
@@ -1381,13 +1415,13 @@
                nodeConfig.register("storeForceBigShrinks", false, sortOrder++, 
true, false, "Node.forceBigShrink", "Node.forceBigShrinkLong",
                                new BooleanCallback() {

-                                       public boolean get() {
+                                       public Boolean get() {
                                                synchronized(Node.this) {
                                                        return 
storeForceBigShrinks;
                                                }
                                        }

-                                       public void set(boolean val) throws 
InvalidConfigValueException {
+                                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                                synchronized(Node.this) {
                                                        storeForceBigShrinks = 
val;
                                                }
@@ -1402,11 +1436,11 @@
                nodeConfig.register("storeSize", "1G", sortOrder++, false, 
true, "Node.storeSize", "Node.storeSizeLong", 
                                new LongCallback() {

-                                       public long get() {
+                                       public Long get() {
                                                return maxTotalDatastoreSize;
                                        }

-                                       public void set(long storeSize) throws 
InvalidConfigValueException {
+                                       public void set(Long storeSize) throws 
InvalidConfigValueException {
                                                if((storeSize < 0) || 
(storeSize < (32 * 1024 * 1024)))
                                                        throw new 
InvalidConfigValueException(l10n("invalidStoreSize"));
                                                long newMaxStoreKeys = 
storeSize / sizePerKey;
@@ -1459,6 +1493,9 @@
                                                // FIXME
                                                throw new 
InvalidConfigValueException("Moving datastore on the fly not supported at 
present");
                                        }
+                                       public boolean isReadOnly() {
+                                       return true;
+                               }
                });

                final String suffix = "-" + getDarknetPortNumber();
@@ -1610,11 +1647,11 @@
                nodeConfig.register("databaseMaxMemory", "20M", sortOrder++, 
true, false, "Node.databaseMemory", "Node.databaseMemoryLong", 
                                new LongCallback() {

-                       public long get() {
+                       public Long get() {
                                return databaseMaxMemory;
                        }

-                       public void set(long val) throws 
InvalidConfigValueException {
+                       public void set(Long val) throws 
InvalidConfigValueException {
                                if(val < 0)
                                        throw new 
InvalidConfigValueException(l10n("mustBePositive"));
                                else {
@@ -1737,14 +1774,13 @@

                nodeConfig.register("disableHangCheckers", false, sortOrder++, 
true, false, "Node.disableHangCheckers", "Node.disableHangCheckersLong", new 
BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return disableHangCheckers;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                disableHangCheckers = val;
                        }
-                       
                });

                disableHangCheckers = 
nodeConfig.getBoolean("disableHangCheckers");
@@ -1756,8 +1792,7 @@
                Logger.normal(this, "Initializing Plugin Manager");
                System.out.println("Initializing Plugin Manager");
                pluginManager = new PluginManager(this);
-               pluginManager2 = new 
freenet.oldplugins.plugin.PluginManager(this);
-               
+
                FetchContext ctx = clientCore.makeClient((short)0, 
true).getFetchContext();

                ctx.allowSplitfiles = false;
@@ -2183,16 +2218,14 @@
        }

        void addTransferringRequestHandler(long id) {
-               Long l = new Long(id);
                synchronized(transferringRequestHandlers) {
-                       transferringRequestHandlers.add(l);
+                       transferringRequestHandlers.add(id);
                }
        }

        void removeTransferringRequestHandler(long id) {
-               Long l = new Long(id);
                synchronized(transferringRequestHandlers) {
-                       transferringRequestHandlers.remove(l);
+                       transferringRequestHandlers.remove(id);
                }
        }

@@ -2527,9 +2560,8 @@
        }

        public boolean lockUID(long uid, boolean ssk, boolean insert, boolean 
offerReply, boolean local) {
-               Long l = new Long(uid);
                synchronized(runningUIDs) {
-                       if(!runningUIDs.add(l)) {
+                       if(!runningUIDs.add(uid)) {
                                // Already present.
                                return false;
                        }
@@ -2538,23 +2570,22 @@
                HashSet set = getUIDTracker(ssk, insert, offerReply, local);
                synchronized(set) {
                        if(logMINOR) Logger.minor(this, "Locking "+uid+" 
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+" local="+local+" 
size="+set.size());
-                       set.add(l);
+                       set.add(uid);
                        if(logMINOR) Logger.minor(this, "Locked "+uid+" 
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+" local="+local+" 
size="+set.size());
                }
                return true;
        }

        public void unlockUID(long uid, boolean ssk, boolean insert, boolean 
canFail, boolean offerReply, boolean local) {
-               Long l = new Long(uid);
                completed(uid);
                HashSet set = getUIDTracker(ssk, insert, offerReply, local);
                synchronized(set) {
                        if(logMINOR) Logger.minor(this, "Unlocking "+uid+" 
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+", local="+local+" 
size="+set.size());
-                       set.remove(l);
+                       set.remove(uid);
                        if(logMINOR) Logger.minor(this, "Unlocked "+uid+" 
ssk="+ssk+" insert="+insert+" offerReply="+offerReply+", local="+local+" 
size="+set.size());
                }
                synchronized(runningUIDs) {
-                       if(!runningUIDs.remove(l) && !canFail)
+                       if(!runningUIDs.remove(uid) && !canFail)
                                throw new IllegalStateException("Could not 
unlock "+uid+ '!');
                }
        }
@@ -2737,7 +2768,7 @@
         */
        public boolean recentlyCompleted(long id) {
                synchronized (recentlyCompletedIDs) {
-                       return recentlyCompletedIDs.contains(new Long(id));
+                       return recentlyCompletedIDs.contains(id);
                }
        }

@@ -2746,7 +2777,7 @@
         */
        void completed(long id) {
                synchronized (recentlyCompletedIDs) {
-                       recentlyCompletedIDs.push(new Long(id));
+                       recentlyCompletedIDs.push(id);
                        while(recentlyCompletedIDs.size() > 
MAX_RECENTLY_COMPLETED_IDS)
                                recentlyCompletedIDs.pop();
                }
@@ -3235,7 +3266,7 @@
                }
        }

-       public void setName(String key) throws InvalidConfigValueException {
+       public void setName(String key) throws InvalidConfigValueException, 
NodeNeedRestartException {
                 config.get("node").getOption("name").setValue(key);
        }


Modified: branches/db4o/freenet/src/freenet/node/NodeClientCore.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeClientCore.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/NodeClientCore.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -67,14 +67,12 @@
 import freenet.support.api.BooleanCallback;
 import freenet.support.api.Bucket;
 import freenet.support.api.IntCallback;
-import freenet.support.api.BucketFactory;
+import freenet.support.api.LongCallback;
 import freenet.support.api.StringArrCallback;
 import freenet.support.api.StringCallback;
 import freenet.support.io.FileUtil;
 import freenet.support.io.FilenameGenerator;
 import freenet.support.io.NativeThread;
-import freenet.support.io.PaddedEphemerallyEncryptedBucketFactory;
-import freenet.support.io.PersistentEncryptedTempBucketFactory;
 import freenet.support.io.PersistentTempBucketFactory;
 import freenet.support.io.TempBucketFactory;

@@ -98,14 +96,13 @@
        private boolean uploadAllowedEverywhere;
        public final FilenameGenerator tempFilenameGenerator;
        public final FilenameGenerator persistentFilenameGenerator;
-       public final BucketFactory tempBucketFactory;
+       public final TempBucketFactory tempBucketFactory;
+       public final PersistentTempBucketFactory persistentTempBucketFactory;
        public final Node node;
        final NodeStats nodeStats;
        public final RandomSource random;
        final File tempDir;     // Persistent temporary buckets
        public final FECQueue fecQueue;
-       public final PersistentTempBucketFactory persistentTempBucketFactory;
-       public final PersistentEncryptedTempBucketFactory 
persistentEncryptedTempBucketFactory;
        public final UserAlertManager alerts;
        final TextModeClientInterfaceServer tmci;
        TextModeClientInterface directTMCI;
@@ -180,6 +177,9 @@
                                        // FIXME
                                        throw new 
InvalidConfigValueException(l10n("movingTempDirOnTheFlyNotSupported"));
                                }
+                               public boolean isReadOnly() {
+                                       return true;
+                               }
                        });

                tempDir = new File(nodeConfig.getString("tempDir"));
@@ -195,10 +195,21 @@
                        throw new 
NodeInitException(NodeInitException.EXIT_BAD_TEMP_DIR, msg);
                }

-               archiveManager = new ArchiveManager(MAX_ARCHIVE_HANDLERS, 
MAX_CACHED_ARCHIVE_DATA, MAX_ARCHIVE_SIZE, MAX_ARCHIVED_FILE_SIZE, 
MAX_CACHED_ELEMENTS, random, node.fastWeakRandom, tempFilenameGenerator);
                uskManager = new USKManager(this);

                // Persistent temp files
+               nodeConfig.register("encryptPersistentTempBuckets", true, 
sortOrder++, true, false, "NodeClientCore.encryptPersistentTempBuckets", 
"NodeClientCore.encryptPersistentTempBucketsLong", new BooleanCallback() {
+
+                       public Boolean get() {
+                               return (persistentTempBucketFactory == null ? 
true : persistentTempBucketFactory.isEncrypting());
+                       }
+
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
+                               if((val == get()) || 
(persistentTempBucketFactory == null)) return;
+                               persistentTempBucketFactory.setEncryption(val);
+                       }
+               });
+               
                nodeConfig.register("persistentTempDir", new File(nodeDir, 
"persistent-temp-" + portNumber).toString(), sortOrder++, true, false, 
"NodeClientCore.persistentTempDir", "NodeClientCore.persistentTempDirLong",
                        new StringCallback() {

@@ -212,32 +223,68 @@
                                        // FIXME
                                        throw new 
InvalidConfigValueException("Moving persistent temp directory on the fly not 
supported at present");
                                }
+                               public boolean isReadOnly() {
+                                       return true;
+                               }
                        });
                try {
                        File dir = new 
File(nodeConfig.getString("persistentTempDir"));
                        String prefix = "freenet-temp-";
-                       persistentTempBucketFactory = 
PersistentTempBucketFactory.load(dir, prefix, random, node.fastWeakRandom, 
container, node.nodeDBHandle);
+                       persistentTempBucketFactory = 
PersistentTempBucketFactory.load(dir, prefix, random, node.fastWeakRandom, 
container, node.nodeDBHandle, 
nodeConfig.getBoolean("encryptPersistentTempBuckets"));
                        persistentTempBucketFactory.init(dir, prefix, random, 
node.fastWeakRandom);
-                       persistentEncryptedTempBucketFactory = 
PersistentEncryptedTempBucketFactory.load(persistentTempBucketFactory, 
container);
                        persistentFilenameGenerator = 
persistentTempBucketFactory.fg;
                } catch(IOException e2) {
                        String msg = "Could not find or create persistent 
temporary directory";
                        throw new 
NodeInitException(NodeInitException.EXIT_BAD_TEMP_DIR, msg);
                }

-               tempBucketFactory = new 
PaddedEphemerallyEncryptedBucketFactory(new 
TempBucketFactory(tempFilenameGenerator), random, node.fastWeakRandom, 1024);
-               
-               healingQueue = new SimpleHealingQueue(
-                               new InsertContext(tempBucketFactory, 
tempBucketFactory, persistentTempBucketFactory,
-                                               0, 2, 1, 0, 0, new 
SimpleEventProducer(),
-                                               
!Node.DONT_CACHE_LOCAL_REQUESTS), RequestStarter.PREFETCH_PRIORITY_CLASS, 512 
/* FIXME make configurable */);
-               
                clientContext = new ClientContext(this);
                storeChecker.setContext(clientContext);
                requestStarters = new RequestStarterGroup(node, this, 
portNumber, random, config, throttleFS, clientContext);
                clientContext.init(requestStarters);
                InsertCompressor.load(container, clientContext);

+               nodeConfig.register("maxRAMBucketSize", "32KiB", sortOrder++, 
true, false, "NodeClientCore.maxRAMBucketSize", 
"NodeClientCore.maxRAMBucketSizeLong", new LongCallback() {
+                       
+                       public Long get() {
+                               return (tempBucketFactory == null ? 0 : 
tempBucketFactory.getMaxRAMBucketSize());
+                       }
+
+                       public void set(Long val) throws 
InvalidConfigValueException {
+                               if((val == get()) || (tempBucketFactory == 
null)) return;
+                               tempBucketFactory.setMaxRAMBucketSize(val);
+                       }
+               });
+               nodeConfig.register("RAMBucketPoolSize", "10MiB", sortOrder++, 
true, false, "NodeClientCore.ramBucketPoolSize", 
"NodeClientCore.ramBucketPoolSizeLong", new LongCallback() {
+
+                       public Long get() {
+                               return (tempBucketFactory == null ? 0 : 
tempBucketFactory.getMaxRamUsed());
+                       }
+
+                       public void set(Long val) throws 
InvalidConfigValueException {
+                               if((val == get()) || (tempBucketFactory == 
null)) return;
+                               tempBucketFactory.setMaxRamUsed(val);
+                       }
+               });
+                       
+               nodeConfig.register("encryptTempBuckets", true, sortOrder++, 
true, false, "NodeClientCore.encryptTempBuckets", 
"NodeClientCore.encryptTempBucketsLong", new BooleanCallback() {
+
+                       public Boolean get() {
+                               return (tempBucketFactory == null ? true : 
tempBucketFactory.isEncrypting());
+                       }
+
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
+                               if((val == get()) || (tempBucketFactory == 
null)) return;
+                               tempBucketFactory.setEncryption(val);
+                       }
+               });
+               tempBucketFactory = new 
TempBucketFactory(tempFilenameGenerator, 
nodeConfig.getLong("maxRAMBucketSize"), 
nodeConfig.getLong("RAMBucketPoolSize"), random, node.fastWeakRandom, 
nodeConfig.getBoolean("encryptTempBuckets"));
+
+               healingQueue = new SimpleHealingQueue(
+                               new InsertContext(tempBucketFactory, 
tempBucketFactory, persistentTempBucketFactory,
+                                               0, 2, 1, 0, 0, new 
SimpleEventProducer(),
+                                               
!Node.DONT_CACHE_LOCAL_REQUESTS), RequestStarter.PREFETCH_PRIORITY_CLASS, 512 
/* FIXME make configurable */);
+               
                // Downloads directory

                nodeConfig.register("downloadsDir", "downloads", sortOrder++, 
true, true, "NodeClientCore.downloadDir", "NodeClientCore.downloadDirLong", new 
StringCallback() {
@@ -308,6 +355,7 @@
                        });
                
setUploadAllowedDirs(nodeConfig.getStringArr("uploadAllowedDirs"));

+               archiveManager = new ArchiveManager(MAX_ARCHIVE_HANDLERS, 
MAX_CACHED_ARCHIVE_DATA, MAX_ARCHIVE_SIZE, MAX_ARCHIVED_FILE_SIZE, 
MAX_CACHED_ELEMENTS, tempBucketFactory);
                Logger.normal(this, "Initializing USK Manager");
                System.out.println("Initializing USK Manager");
                uskManager.init(container, clientContext);
@@ -315,11 +363,11 @@
                nodeConfig.register("lazyResume", false, sortOrder++, true, 
false, "NodeClientCore.lazyResume",
                        "NodeClientCore.lazyResumeLong", new BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return lazyResume;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                synchronized(NodeClientCore.this) {
                                        lazyResume = val;
                                }
@@ -331,11 +379,11 @@
                nodeConfig.register("maxBackgroundUSKFetchers", "64", 
sortOrder++, true, false, "NodeClientCore.maxUSKFetchers",
                        "NodeClientCore.maxUSKFetchersLong", new IntCallback() {

-                       public int get() {
+                       public Integer get() {
                                return maxBackgroundUSKFetchers;
                        }

-                       public void set(int uskFetch) throws 
InvalidConfigValueException {
+                       public void set(Integer uskFetch) throws 
InvalidConfigValueException {
                                if(uskFetch <= 0)
                                        throw new 
InvalidConfigValueException(l10n("maxUSKFetchersMustBeGreaterThanZero"));
                                maxBackgroundUSKFetchers = uskFetch;

Modified: branches/db4o/freenet/src/freenet/node/NodeCrypto.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeCrypto.java      2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/NodeCrypto.java      2008-09-24 
20:42:20 UTC (rev 22823)
@@ -36,7 +36,6 @@
 import freenet.keys.InsertableClientSSK;
 import freenet.support.Base64;
 import freenet.support.Fields;
-import freenet.support.HexUtil;
 import freenet.support.IllegalBase64Exception;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
@@ -357,9 +356,8 @@
                        BigInteger m = new BigInteger(1, SHA256.digest(ref));
                        if(logMINOR) Logger.minor(this, "m = "+m.toString(16));
                        DSASignature _signature = DSA.sign(cryptoGroup, 
privKey, m, random);
-                       // FIXME remove this ... eventually
-                       if(!DSA.verify(pubKey, _signature, m, false))
-                               Logger.error(this, "Signature failed!");
+                       if(logMINOR && !DSA.verify(pubKey, _signature, m, 
false))
+                               throw new 
NodeInitException(NodeInitException.EXIT_EXCEPTION_TO_DEBUG, mySignedReference);
                        return _signature;
                } catch(UnsupportedEncodingException e){
                        //duh ?
@@ -370,13 +368,9 @@
                }
        }

-       public static boolean DISABLE_GROUP_STRIP = false;
-       
        private byte[] myCompressedRef(boolean setup, boolean heavySetup, 
boolean forARK) {
                SimpleFieldSet fs = exportPublicFieldSet(setup, heavySetup, 
forARK);
-               // TODO: we should change that to ((setup || heavySetup) && 
!forARK) when all the nodes have the new code
-               boolean shouldStripGroup = heavySetup && 
Global.DSAgroupBigA.equals(cryptoGroup);
-               if(DISABLE_GROUP_STRIP) shouldStripGroup = false;
+               boolean shouldStripGroup = ((setup || heavySetup) && !forARK) 
&& Global.DSAgroupBigA.equals(cryptoGroup);
                if(shouldStripGroup)
                        fs.removeSubset("dsaGroup");


Modified: branches/db4o/freenet/src/freenet/node/NodeCryptoConfig.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeCryptoConfig.java        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/NodeCryptoConfig.java        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -50,14 +50,14 @@
        NodeCryptoConfig(SubConfig config, int sortOrder, boolean onePerIP) 
throws NodeInitException {

                config.register("listenPort", -1 /* means random */, 
sortOrder++, true, true, "Node.port", "Node.portLong",     new IntCallback() {
-                       public int get() {
+                       public Integer get() {
                                synchronized(NodeCryptoConfig.class) {
                                        if(crypto != null)
                                                portNumber = crypto.portNumber;
                                        return portNumber;
                                }
                        }
-                       public void set(int val) throws 
InvalidConfigValueException {
+                       public void set(Integer val) throws 
InvalidConfigValueException {

                                if(portNumber < -1 || portNumber == 0 || 
portNumber > 65535) {
                                        throw new 
InvalidConfigValueException("Invalid port number");
@@ -73,6 +73,9 @@
                                        portNumber = val;
                                }
                        }
+                       public boolean isReadOnly() {
+                                       return true;
+                               }               
                });

                try{
@@ -97,13 +100,13 @@
                config.register("testingDropPacketsEvery", 0, sortOrder++, 
true, false, "Node.dropPacketEvery", "Node.dropPacketEveryLong",
                                new IntCallback() {

-                                       public int get() {
+                                       public Integer get() {
                                                
synchronized(NodeCryptoConfig.this) {
                                                        return dropProbability;
                                                }
                                        }

-                                       public void set(int val) throws 
InvalidConfigValueException {
+                                       public void set(Integer val) throws 
InvalidConfigValueException {
                                                if(val < 0) throw new 
InvalidConfigValueException("testingDropPacketsEvery must not be negative");
                                                
synchronized(NodeCryptoConfig.this) {
                                                        if(val == 
dropProbability) return;
@@ -111,7 +114,7 @@
                                                        if(crypto == null) 
return;
                                                }
                                                
crypto.onSetDropProbability(val);
-                                       }
+                                       }               

                });
                dropProbability = config.getInt("testingDropPacketsEvery"); 
@@ -119,13 +122,13 @@
                config.register("oneConnectionPerIP", onePerIP, sortOrder++, 
true, false, "Node.oneConnectionPerIP", "Node.oneConnectionPerIPLong",
                                new BooleanCallback() {

-                                       public boolean get() {
+                                       public Boolean get() {
                                                
synchronized(NodeCryptoConfig.this) {
                                                        return 
oneConnectionPerAddress;
                                                }
                                        }

-                                       public void set(boolean val) throws 
InvalidConfigValueException {
+                                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                                
synchronized(NodeCryptoConfig.this) {
                                                        oneConnectionPerAddress 
= val;
                                                }
@@ -137,29 +140,29 @@
                config.register("alwaysAllowLocalAddresses", false, 
sortOrder++, true, false, "Node.alwaysAllowLocalAddresses", 
"Node.alwaysAllowLocalAddressesLong",
                                new BooleanCallback() {

-                                       public boolean get() {
+                                       public Boolean get() {
                                                
synchronized(NodeCryptoConfig.this) {
                                                        return 
alwaysAllowLocalAddresses;
                                                }
                                        }

-                                       public void set(boolean val) throws 
InvalidConfigValueException {
+                                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                                
synchronized(NodeCryptoConfig.this) {
                                                        
alwaysAllowLocalAddresses = val;
                                                }
-                                       }
+                                       }                       
                });
                alwaysAllowLocalAddresses = 
config.getBoolean("alwaysAllowLocalAddresses");

                config.register("assumeNATed", true, sortOrder++, true, true, 
"Node.assumeNATed", "Node.assumeNATedLong", new BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return assumeNATed;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                assumeNATed = val;
-                       }
+                       }               
                });
                assumeNATed = config.getBoolean("assumeNATed");
        }
@@ -188,7 +191,7 @@
                return portNumber;
        }

-       class NodeBindtoCallback implements StringCallback {
+       class NodeBindtoCallback extends StringCallback  {

                public String get() {
                        return bindTo.toString();
@@ -199,6 +202,9 @@
                        // FIXME why not? Can't we use 
freenet.io.NetworkInterface like everywhere else, just adapt it for UDP?
                        throw new InvalidConfigValueException("Cannot be 
updated on the fly");
                }
+               public boolean isReadOnly() {
+                       return true;
+               }
        }

        public synchronized FreenetInetAddress getBindTo() {

Modified: branches/db4o/freenet/src/freenet/node/NodeDispatcher.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeDispatcher.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/NodeDispatcher.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -143,13 +143,6 @@
                        }
                        // We claim it in any case
                        return true;
-               } else if(source.isRealConnection() && spec == 
DMT.FNPLocChangeNotification) {
-                       double newLoc = m.getDouble(DMT.LOCATION);
-                       source.updateLocation(newLoc);
-                       // TODO: remove dead code when 
FNPLocChangeNotificationNew is mandatory
-                       if(source.getVersionNumber() > 1153)
-                               Logger.error(this, "We received a 
FNPLocChangeNotification from a recent build: that should *not* happen! 
("+source.toString()+')');
-                       return true;
                } else if(source.isRealConnection() && spec == 
DMT.FNPLocChangeNotificationNew) {
                        double newLoc = m.getDouble(DMT.LOCATION);
                        ShortBuffer buffer = ((ShortBuffer) 
m.getObject(DMT.PEER_LOCATIONS));

Modified: branches/db4o/freenet/src/freenet/node/NodeIPDetector.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeIPDetector.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/NodeIPDetector.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -18,6 +18,7 @@
 import freenet.node.useralerts.SimpleUserAlert;
 import freenet.node.useralerts.UserAlert;
 import freenet.pluginmanager.DetectedIP;
+import freenet.pluginmanager.FredPluginBandwidthIndicator;
 import freenet.pluginmanager.FredPluginIPDetector;
 import freenet.pluginmanager.FredPluginPortForward;
 import freenet.support.HTMLNode;
@@ -372,7 +373,6 @@
                                }
                                redetectAddress();
                        }
-                       
                });

                hasValidAddressOverride = true;
@@ -419,7 +419,6 @@
                                }
                                redetectAddress();
                        }
-                       
                });

                String ipHintString = nodeConfig.getString("tempIPAddressHint");
@@ -438,16 +437,15 @@

                nodeConfig.register("includeLocalAddressesInNoderefs", false, 
sortOrder++, true, false, "NodeIPDectector.inclLocalAddress", 
"NodeIPDectector.inclLocalAddressLong", new BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                return includeLocalAddressesInNoderefs;
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                includeLocalAddressesInNoderefs = val;
                                lastIPAddress = null;
                                ipDetector.clearCached();
                        }
-                       
                });

                includeLocalAddressesInNoderefs = 
nodeConfig.getBoolean("includeLocalAddressesInNoderefs");
@@ -526,6 +524,18 @@
                ipDetectorManager.unregisterPortForwardPlugin(forward);
        }

+       //TODO: ugly: deal with multiple instances properly
+       public synchronized void 
registerBandwidthIndicatorPlugin(FredPluginBandwidthIndicator indicator) {
+               bandwidthIndicator = indicator;
+       }
+       public synchronized void 
unregisterBandwidthIndicatorPlugin(FredPluginBandwidthIndicator indicator) {
+               bandwidthIndicator = null;
+       }
+       public synchronized FredPluginBandwidthIndicator 
getBandwidthIndicator() {
+               return bandwidthIndicator;
+       }
+       private FredPluginBandwidthIndicator bandwidthIndicator;
+       
        boolean hasValidAddressOverride() {
                synchronized(this) {
                        return hasValidAddressOverride;

Modified: branches/db4o/freenet/src/freenet/node/NodeInitException.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeInitException.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/NodeInitException.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -37,6 +37,8 @@
        public static final int EXIT_NODE_UPPER_LIMIT = 1024;
        public static final int EXIT_BROKE_WRAPPER_CONF = 28;
        public static final int EXIT_OUT_OF_MEMORY_PROTECTING_DATABASE = 29;
+       public static final int EXIT_EXCEPTION_TO_DEBUG = 1023;
+       
        private static final long serialVersionUID = -1;

        NodeInitException(int exitCode, String msg) {

Modified: branches/db4o/freenet/src/freenet/node/NodeStarter.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeStarter.java     2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/NodeStarter.java     2008-09-24 
20:42:20 UTC (rev 22823)
@@ -393,6 +393,8 @@
                configFS.put("node.opennet.oneConnectionPerIP", false);
                configFS.put("node.opennet.assumeNATed", true);
                configFS.put("node.opennet.connectToSeednodes", 
connectToSeednodes);
+               configFS.put("node.encryptTempBuckets", false);
+               configFS.put("node.encryptPersistentTempBuckets", false);

                PersistentConfig config = new PersistentConfig(configFS);


Modified: branches/db4o/freenet/src/freenet/node/NodeStats.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeStats.java       2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/NodeStats.java       2008-09-24 
20:42:20 UTC (rev 22823)
@@ -212,10 +212,10 @@

                statsConfig.register("threadLimit", 500, sortOrder++, true, 
true, "NodeStat.threadLimit", "NodeStat.threadLimitLong",
                                new IntCallback() {
-                                       public int get() {
+                                       public Integer get() {
                                                return threadLimit;
                                        }
-                                       public void set(int val) throws 
InvalidConfigValueException {
+                                       public void set(Integer val) throws 
InvalidConfigValueException {
                                                if(val == get()) return;
                                                if(val < 100)
                                                        throw new 
InvalidConfigValueException(l10n("valueTooLow"));
@@ -227,10 +227,10 @@
                // Yes it could be in seconds insteed of multiples of 0.12, but 
we don't want people to play with it :)
                statsConfig.register("aggressiveGC", aggressiveGCModificator, 
sortOrder++, true, false, "NodeStat.aggressiveGC", "NodeStat.aggressiveGCLong",
                                new IntCallback() {
-                                       public int get() {
+                                       public Integer get() {
                                                return aggressiveGCModificator;
                                        }
-                                       public void set(int val) throws 
InvalidConfigValueException {
+                                       public void set(Integer val) throws 
InvalidConfigValueException {
                                                if(val == get()) return;
                                                Logger.normal(this, "Changing 
aggressiveGCModificator to "+val);
                                                aggressiveGCModificator = val;
@@ -241,11 +241,11 @@
                myMemoryChecker = new MemoryChecker(node.ps, 
aggressiveGCModificator);
                statsConfig.register("memoryChecker", true, sortOrder++, true, 
false, "NodeStat.memCheck", "NodeStat.memCheckLong", 
                                new BooleanCallback(){
-                                       public boolean get() {
+                                       public Boolean get() {
                                                return 
myMemoryChecker.isRunning();
                                        }

-                                       public void set(boolean val) throws 
InvalidConfigValueException {
+                                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                                if(val == get()) return;

                                                if(val)
@@ -259,18 +259,17 @@

                statsConfig.register("ignoreLocalVsRemoteBandwidthLiability", 
false, sortOrder++, true, false, 
"NodeStat.ignoreLocalVsRemoteBandwidthLiability", 
"NodeStat.ignoreLocalVsRemoteBandwidthLiabilityLong", new BooleanCallback() {

-                       public boolean get() {
+                       public Boolean get() {
                                synchronized(NodeStats.this) {
                                        return 
ignoreLocalVsRemoteBandwidthLiability;
                                }
                        }

-                       public void set(boolean val) throws 
InvalidConfigValueException {
+                       public void set(Boolean val) throws 
InvalidConfigValueException {
                                synchronized(NodeStats.this) {
                                        ignoreLocalVsRemoteBandwidthLiability = 
val;
                                }
                        }
-                       
                });

                persister = new ConfigurablePersister(this, statsConfig, 
"nodeThrottleFile", "node-throttle.dat", sortOrder++, true, false, 

Modified: branches/db4o/freenet/src/freenet/node/PeerManager.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/PeerManager.java     2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/PeerManager.java     2008-09-24 
20:42:20 UTC (rev 22823)
@@ -38,6 +38,8 @@
 import freenet.support.SimpleFieldSet;
 import freenet.support.io.FileUtil;
 import freenet.support.io.Closer;
+import java.util.SortedSet;
+import java.util.TreeSet;

 /**
  * @author amphibian
@@ -79,9 +81,14 @@
        private long nextRoutableConnectionStatsUpdateTime = -1;
        /** routableConnectionStats update interval (milliseconds) */
        private static final long routableConnectionStatsUpdateInterval = 7 * 
1000;  // 7 seconds
-       /** number of samples we have to do stats on peer-selection */
-       private long numberOfSelectionSamples = 0;

+       /**
+        * Track the number of times a PeerNode has been selected by the 
routing algorithm
+        * @see PeerNode.numberOfSelections
+        */
+       private SortedSet<Long> numberOfSelectionSamples = new TreeSet<Long>();
+       private final Object numberOfSelectionSamplesSync = new Object();
+       
        public static final int PEER_NODE_STATUS_CONNECTED = 1;
        public static final int PEER_NODE_STATUS_ROUTING_BACKED_OFF = 2;
        public static final int PEER_NODE_STATUS_TOO_NEW = 3;
@@ -991,10 +998,8 @@
                                //Add the location which we did not pick, if it 
exists.
                                if(closestNotBackedOff != null && 
closestBackedOff != null)
                                        addUnpickedLocsTo.add(new 
Double(closestBackedOff.getLocation()));
-
-                       //TODO: synchronize! ; store the stats here instead of 
into PeerNode?
-                       best.incrementNumberOfSelections();
-                       numberOfSelectionSamples++;
+                                       
+                       incrementSelectionSamples(now, best);
                }

                return best;
@@ -1219,6 +1224,17 @@
                }
                return false;
        }
+       
+       public boolean anyDarknetPeers() {
+               PeerNode[] conns;
+               synchronized(this) {
+                       conns = connectedPeers;
+               }
+               for(PeerNode p : conns)
+                       if(p.isDarknet())
+                               return true;
+               return false;
+       }

        /**
         * Ask each PeerNode to read in it's extra peer data
@@ -1824,7 +1840,19 @@
                return null;
        }

-       public long getNumberOfSelectionSamples() {
-               return numberOfSelectionSamples;
+       public SortedSet<Long> getNumberOfSelectionSamples() {
+               synchronized (numberOfSelectionSamplesSync) {
+                       return new TreeSet<Long>(numberOfSelectionSamples);
+               }
        }
+               
+       private void incrementSelectionSamples(long now, PeerNode pn) {
+               // TODO: reimplement with a bit field to spare memory
+               synchronized (numberOfSelectionSamplesSync) {
+                       if(numberOfSelectionSamples.size() > 
PeerNode.SELECTION_MAX_SAMPLES * OpennetManager.MAX_PEERS_FOR_SCALING)
+                               numberOfSelectionSamples = 
numberOfSelectionSamples.tailSet(now - PeerNode.SELECTION_SAMPLING_PERIOD);
+                       numberOfSelectionSamples.add(now);
+                       pn.incrementNumberOfSelections(now);
+               }
+       }
 }

Modified: branches/db4o/freenet/src/freenet/node/PeerNode.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/PeerNode.java        2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/PeerNode.java        2008-09-24 
20:42:20 UTC (rev 22823)
@@ -74,7 +74,8 @@
 import freenet.support.math.TimeDecayingRunningAverage;
 import freenet.support.transport.ip.HostnameSyntaxException;
 import freenet.support.transport.ip.IPUtil;
-import java.util.Collection;
+import java.util.SortedSet;
+import java.util.TreeSet;

 /**
  * @author amphibian
@@ -151,9 +152,21 @@
        private long timeLastRoutable;
        /** Time added or restarted (reset on startup unlike peerAddedTime) */
        private long timeAddedOrRestarted;
-       /** Number of time that peer has been selected by the routing algorithm 
*/
-       private long numberOfSelections = 0;

+       /**
+        * Track the number of times this PeerNode has been selected by
+        * the routing algorithm over a given period of time
+        */
+       private SortedSet<Long> numberOfSelections = new TreeSet<Long>();
+       private final Object numberOfSelectionsSync = new Object();
+       // 5mins; yes it's alchemy!
+       public static final int SELECTION_SAMPLING_PERIOD = 5 * 60 * 1000;
+       // 30%; yes it's alchemy too! and probably *way* too high to serve any 
purpose
+       public static final int SELECTION_PERCENTAGE_WARNING = 30;
+       // Should be good enough provided we don't get selected more than 10 
times per/sec
+       // Lower the following value if you want to spare memory... or better 
switch from a TreeSet to a bit field.
+       public static final int SELECTION_MAX_SAMPLES = 10 * 
SELECTION_SAMPLING_PERIOD / 1000; 
+       
        /** Are we connected? If not, we need to start trying to
        * handshake.
        */
@@ -975,7 +988,6 @@
        * PeerManager in e.g. verified.
        */
        public boolean isRoutable() {
-               //FIXME: isConnected() is redundant if 'isRoutable', right? ... 
currentLocation>1.0 is impossible.
                return isConnected() && isRoutingCompatible() &&
                        !(currentLocation < 0.0 || currentLocation > 1.0);
        }
@@ -1607,24 +1619,6 @@
                        }
                }
        }
-
-       /**
-       * Update the Location to a new value.
-       * @deprecated
-       */
-       public void updateLocation(double newLoc) {
-               logMINOR = Logger.shouldLog(Logger.MINOR, PeerNode.class);
-               if(newLoc < 0.0 || newLoc > 1.0) {
-                       Logger.error(this, "Invalid location update for " + 
this+ " ("+newLoc+')', new Exception("error"));
-                       // Ignore it
-                       return;
-               }
-               synchronized(this) {
-                       currentLocation = newLoc;
-                       locSetTime = System.currentTimeMillis();
-               }
-               node.peers.writePeers();
-       }

        public void updateLocation(double newLoc, double[] newLocs) {
                logMINOR = Logger.shouldLog(Logger.MINOR, PeerNode.class);
@@ -2109,14 +2103,12 @@
        * Send any high level messages that need to be sent on connect.
        */
        protected void sendInitialMessages() {
-               Message locMsg = ((getVersionNumber() > 1153) ?
-                       
DMT.createFNPLocChangeNotificationNew(node.lm.getLocation(), 
node.peers.getPeerLocationDoubles(true)) :
-                       
DMT.createFNPLocChangeNotification(node.lm.getLocation()));
+               Message locMsg = 
DMT.createFNPLocChangeNotificationNew(node.lm.getLocation(), 
node.peers.getPeerLocationDoubles(true));
                Message ipMsg = DMT.createFNPDetectedIPAddress(detectedPeer);
                Message timeMsg = DMT.createFNPTime(System.currentTimeMillis());
                Message packetsMsg = createSentPacketsMessage();
-               Message dRouting = 
DMT.createRoutingStatus(!disableRoutingHasBeenSetLocally);
-               Message uptime = 
DMT.createFNPUptime((byte)(int)(100*node.uptime.getUptime()));
+               Message dRoutingMsg = 
DMT.createRoutingStatus(!disableRoutingHasBeenSetLocally);
+               Message uptimeMsg = 
DMT.createFNPUptime((byte)(int)(100*node.uptime.getUptime()));

                try {
                        if(isRealConnection())
@@ -2124,8 +2116,8 @@
                        sendAsync(ipMsg, null, 0, 
node.nodeStats.initialMessagesCtr);
                        sendAsync(timeMsg, null, 0, 
node.nodeStats.initialMessagesCtr);
                        sendAsync(packetsMsg, null, 0, 
node.nodeStats.initialMessagesCtr);
-                       sendAsync(dRouting, null, 0, 
node.nodeStats.initialMessagesCtr);
-                       sendAsync(uptime, null, 0, 
node.nodeStats.initialMessagesCtr);
+                       sendAsync(dRoutingMsg, null, 0, 
node.nodeStats.initialMessagesCtr);
+                       sendAsync(uptimeMsg, null, 0, 
node.nodeStats.initialMessagesCtr);
                } catch(NotConnectedException e) {
                        Logger.error(this, "Completed handshake with " + 
getPeer() + " but disconnected (" + isConnected + ':' + currentTracker + "!!!: 
" + e, e);
                }
@@ -2972,9 +2964,9 @@
                synchronized(this) {
                        count = (Long) 
localNodeSentMessageTypes.get(messageSpecName);
                        if(count == null)
-                               count = new Long(1);
+                               count = 1L;
                        else
-                               count = new Long(count.longValue() + 1);
+                               count = count.longValue() + 1;
                        localNodeSentMessageTypes.put(messageSpecName, count);
                }
        }
@@ -2988,9 +2980,9 @@
                synchronized(localNodeReceivedMessageTypes) {
                        count = (Long) 
localNodeReceivedMessageTypes.get(messageSpecName);
                        if(count == null)
-                               count = new Long(1);
+                               count = 1L;
                        else
-                               count = new Long(count.longValue() + 1);
+                               count = count.longValue() + 1;
                        localNodeReceivedMessageTypes.put(messageSpecName, 
count);
                }
        }
@@ -3990,12 +3982,20 @@
                return (short)(((int)uptime) & 0xFF);
        }

-       public long getNumberOfSelections() {
-               return numberOfSelections;
+       public SortedSet<Long> getNumberOfSelections() {
+               // FIXME: returning a copy is not an option: find a smarter way 
of dealing with the synchronization
+               synchronized(numberOfSelectionsSync) {
+                       return numberOfSelections;
+               }
        }

-       public void incrementNumberOfSelections() {
-               numberOfSelections++;
+       public void incrementNumberOfSelections(long time) {
+               // TODO: reimplement with a bit field to spare memory
+               synchronized(numberOfSelectionsSync) {
+                       if(numberOfSelections.size() > SELECTION_MAX_SAMPLES)
+                               numberOfSelections = 
numberOfSelections.tailSet(time - SELECTION_SAMPLING_PERIOD);
+                       numberOfSelections.add(time);
+               }
        }

        private long offeredMainJarVersion;

Modified: branches/db4o/freenet/src/freenet/node/PeerNodeStatus.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/PeerNodeStatus.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/PeerNodeStatus.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -8,6 +8,7 @@
 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
@@ -94,7 +95,7 @@

        private final int reportedUptimePercentage;

-       private final long numberOfSelections;
+       private final SortedSet<Long> numberOfSelections;

        PeerNodeStatus(PeerNode peerNode, boolean noHeavy) {
                if(Logger.shouldLog(Logger.MINOR, this)) {
@@ -397,7 +398,7 @@
                return reportedUptimePercentage;
        }

-       public long getNumberOfSelections() {
+       public SortedSet<Long> getNumberOfSelections() {
                return numberOfSelections;
        }
 }

Modified: branches/db4o/freenet/src/freenet/node/SeedClientPeerNode.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/SeedClientPeerNode.java      
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/SeedClientPeerNode.java      
2008-09-24 20:42:20 UTC (rev 22823)
@@ -100,6 +100,10 @@
                                                System.currentTimeMillis() - 
lastReceivedPacketTime() > 60*1000)
                                return true;
                        }
+               } else {
+                       // Disconnect after an hour in any event.
+                       if(System.currentTimeMillis() - 
timeLastConnectionCompleted() > 60*60*1000)
+                               return true;
                }
                return false;
        }

Modified: branches/db4o/freenet/src/freenet/node/TestnetHandler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/TestnetHandler.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/TestnetHandler.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -208,7 +208,7 @@

        }

-       private static class TestnetEnabledCallback implements BooleanCallback {
+       private static class TestnetEnabledCallback extends BooleanCallback  {

                final Node node;

@@ -216,30 +216,33 @@
                        this.node = node;
                }

-               public boolean get() {
+               public Boolean get() {
                        return node.testnetEnabled;
                }

-               public void set(boolean val) throws InvalidConfigValueException 
{
+               public void set(Boolean val) throws InvalidConfigValueException 
{
                        if(node.testnetEnabled == val) return;
                        throw new 
InvalidConfigValueException(L10n.getString("TestnetHandler.cannotEnableDisableOnTheFly"));
                }
-               
+
+               public boolean isReadOnly() {
+                       return true;
+               }
        }


-       static class TestnetPortNumberCallback implements IntCallback {
+       static class TestnetPortNumberCallback extends IntCallback  {
                Node node;

                TestnetPortNumberCallback(Node n){
                        this.node = n;
                }

-               public int get() {
+               public Integer get() {
                        return node.testnetHandler.getPort();
                }

-               public void set(int val) throws InvalidConfigValueException {
+               public void set(Integer val) throws InvalidConfigValueException 
{
                        if(val == get()) return;
                        node.testnetHandler.rebind(val);
                }

Modified: branches/db4o/freenet/src/freenet/node/TextModeClientInterface.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/TextModeClientInterface.java 
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/TextModeClientInterface.java 
2008-09-24 20:42:20 UTC (rev 22823)
@@ -45,12 +45,12 @@
 import freenet.support.OOMHandler;
 import freenet.support.SimpleFieldSet;
 import freenet.support.SizeUtil;
-import freenet.support.StringArray;
 import freenet.support.api.Bucket;
 import freenet.support.io.ArrayBucket;
 import freenet.support.io.ArrayBucketFactory;
 import freenet.support.io.BucketTools;
 import freenet.support.io.FileBucket;
+import java.util.Arrays;

 /**
  * @author amphibian
@@ -860,7 +860,7 @@
                                }

                                public void onTrace(long uid, double target, 
double nearest, double best, short htl, short counter, double location, long 
nodeUID, double[] peerLocs, long[] peerUIDs, double[] locsNotVisited, short 
forkCount, short linearCounter, String reason, long prevUID) {
-                                       String msg = "Probe trace: UID="+uid+" 
target="+target+" nearest="+nearest+" best="+best+" htl="+htl+" 
counter="+counter+" linear="+linearCounter+" location="+location+"node 
UID="+nodeUID+" prev UID="+prevUID+" peer 
locs="+StringArray.toString(peerLocs)+" peer 
UIDs="+StringArray.toString(peerUIDs)+" locs not visited = 
"+StringArray.toString(locsNotVisited)+" forks: "+forkCount+" 
reason="+reason+'\n';
+                                       String msg = "Probe trace: UID="+uid+" 
target="+target+" nearest="+nearest+" best="+best+" htl="+htl+" 
counter="+counter+" linear="+linearCounter+" location="+location+"node 
UID="+nodeUID+" prev UID="+prevUID+" peer locs="+Arrays.toString(peerLocs)+" 
peer UIDs="+Arrays.toString(peerUIDs)+" locs not visited = 
"+Arrays.toString(locsNotVisited)+" forks: "+forkCount+" reason="+reason+'\n';
                                        try {
                                                out.write(msg.getBytes());
                                                out.flush();

Modified: 
branches/db4o/freenet/src/freenet/node/TextModeClientInterfaceServer.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/TextModeClientInterfaceServer.java   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/TextModeClientInterfaceServer.java   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -103,7 +103,7 @@
        }


-    static class TMCIEnabledCallback implements BooleanCallback {
+    static class TMCIEnabledCallback extends BooleanCallback  {

        final NodeClientCore core;

@@ -111,24 +111,27 @@
                this.core = core;
        }

-       public boolean get() {
+       public Boolean get() {
                return core.getTextModeClientInterface() != null;
        }

-       public void set(boolean val) throws InvalidConfigValueException {
+       public void set(Boolean val) throws InvalidConfigValueException {
                if(val == get()) return;
                // FIXME implement - see bug #122
                throw new InvalidConfigValueException("Cannot be updated on the 
fly");
        }
+               public boolean isReadOnly() {
+                       return true;
+               }
     }

-    static class TMCISSLCallback implements BooleanCallback {
+    static class TMCISSLCallback extends BooleanCallback  {

-       public boolean get() {
+       public Boolean get() {
                return ssl;
        }

-       public void set(boolean val) throws InvalidConfigValueException {
+       public void set(Boolean val) throws InvalidConfigValueException {
                if(val == get()) return;
                        if(!SSL.available()) {
                                throw new InvalidConfigValueException("Enable 
SSL support before use ssl with TMCI");
@@ -136,9 +139,12 @@
                ssl = val;
                throw new InvalidConfigValueException("Cannot change SSL on the 
fly, please restart freenet");
        }
+               public boolean isReadOnly() {
+                       return true;
+               }
     }

-    static class TMCIDirectEnabledCallback implements BooleanCallback {
+    static class TMCIDirectEnabledCallback extends BooleanCallback  {

        final NodeClientCore core;

@@ -146,18 +152,21 @@
                this.core = core;
        }

-       public boolean get() {
+       public Boolean get() {
                return core.getDirectTMCI() != null;
        }

-       public void set(boolean val) throws InvalidConfigValueException {
+       public void set(Boolean val) throws InvalidConfigValueException {
                if(val == get()) return;
                // FIXME implement - see bug #122
                throw new InvalidConfigValueException("Cannot be updated on the 
fly");
        }
+               public boolean isReadOnly() {
+                       return true;
+               }
     }

-    static class TMCIBindtoCallback implements StringCallback {
+    static class TMCIBindtoCallback extends StringCallback  {

        final NodeClientCore core;

@@ -183,7 +192,7 @@
        }
     }

-    static class TMCIAllowedHostsCallback implements StringCallback {
+    static class TMCIAllowedHostsCallback extends StringCallback  {

        private final NodeClientCore core;

@@ -208,10 +217,9 @@
                                        throw new 
InvalidConfigValueException("Setting allowedHosts for TMCI (console) server 
when TMCI is disabled");
                        }
                }
-       
     }

-    static class TCMIPortNumberCallback implements IntCallback{
+    static class TCMIPortNumberCallback extends IntCallback {

        final NodeClientCore core;

@@ -219,7 +227,7 @@
                this.core = core;
        }

-       public int get() {
+       public Integer get() {
                if(core.getTextModeClientInterface()!=null)
                        return core.getTextModeClientInterface().port;
                else
@@ -227,7 +235,7 @@
        }

        // TODO: implement it
-       public void set(int val) throws InvalidConfigValueException {
+       public void set(Integer val) throws InvalidConfigValueException {
                if(val == get()) return;
                core.getTextModeClientInterface().setPort(val);
        }

Modified: branches/db4o/freenet/src/freenet/node/UptimeEstimator.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/UptimeEstimator.java 2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/UptimeEstimator.java 2008-09-24 
20:42:20 UTC (rev 22823)
@@ -48,8 +48,6 @@
        /** We write to disk every 5 minutes. The offset is derived from the 
node's identity. */
        private long timeOffset;

-       private final DecimalFormat fix1p2 = new DecimalFormat("0.00");
-
        public UptimeEstimator(File nodeDir, Ticker ticker, byte[] bs) {
                this.ticker = ticker;
                logFile = new File(nodeDir, "uptime.dat");
@@ -67,7 +65,7 @@
                readData(prevFile, base);
                readData(logFile, base);
                schedule(System.currentTimeMillis());
-               System.out.println("Created uptime estimator, time offset is 
"+timeOffset+" uptime at startup is "+fix1p2.format(getUptime())+'%');
+               System.out.println("Created uptime estimator, time offset is 
"+timeOffset+" uptime at startup is "+new 
DecimalFormat("0.00").format(getUptime())+'%');
        }

        private void readData(File file, int base) {

Modified: branches/db4o/freenet/src/freenet/node/fcp/ClientGet.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/fcp/ClientGet.java   2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/fcp/ClientGet.java   2008-09-24 
20:42:20 UTC (rev 22823)
@@ -112,9 +112,9 @@
                        targetFile = null;
                        tempFile = null;
                                if(persistenceType == PERSIST_FOREVER)
-                                       ret = 
server.core.persistentTempBucketFactory.makeEncryptedBucket();
+                                       ret = 
server.core.persistentTempBucketFactory.makeBucket(maxOutputLength);
                                else
-                                       ret = 
server.core.tempBucketFactory.makeBucket(-1);
+                                       ret = 
server.core.tempBucketFactory.makeBucket(maxOutputLength);
                }
                returnBucket = ret;
                        getter = new ClientGetter(this, 
server.core.requestStarters.chkFetchScheduler, 
server.core.requestStarters.sskFetchScheduler, uri, fctx, priorityClass,
@@ -164,9 +164,9 @@
                        tempFile = null;
                        try {
                                if(persistenceType == PERSIST_FOREVER)
-                                       ret = 
server.core.persistentTempBucketFactory.makeEncryptedBucket();
+                                       ret = 
server.core.persistentTempBucketFactory.makeBucket(fctx.maxOutputLength);
                                else
-                                       ret = 
server.core.tempBucketFactory.makeBucket(-1);
+                                       ret = 
server.core.tempBucketFactory.makeBucket(fctx.maxOutputLength);
                        } catch (IOException e) {
                                Logger.error(this, "Cannot create bucket for 
temp storage: "+e, e);
                                getter = null;
@@ -246,9 +246,9 @@
                                try {
                                        // Create a new temp bucket
                                        if(persistenceType == PERSIST_FOREVER)
-                                               ret = 
server.core.persistentTempBucketFactory.makeEncryptedBucket();
+                                               ret = 
server.core.persistentTempBucketFactory.makeBucket(fctx.maxOutputLength);
                                        else
-                                               ret = 
server.core.tempBucketFactory.makeBucket(-1);
+                                               ret = 
server.core.tempBucketFactory.makeBucket(fctx.maxOutputLength);
                                } catch (IOException e1) {
                                        Logger.error(this, "Cannot create 
bucket for temp storage: "+e, e);
                                        getter = null;

Modified: branches/db4o/freenet/src/freenet/node/fcp/ClientPutMessage.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/fcp/ClientPutMessage.java    
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/fcp/ClientPutMessage.java    
2008-09-24 20:42:20 UTC (rev 22823)
@@ -262,7 +262,7 @@

        Bucket createBucket(BucketFactory bf, long length, FCPServer server) 
throws IOException {
                if(persistenceType == ClientRequest.PERSIST_FOREVER) {
-                       return 
server.core.persistentTempBucketFactory.makeEncryptedBucket();
+                       return 
server.core.persistentTempBucketFactory.makeBucket(length);
                } else {
                        return super.createBucket(bf, length, server);
                }

Modified: branches/db4o/freenet/src/freenet/node/fcp/ClientRequest.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/fcp/ClientRequest.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/fcp/ClientRequest.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -115,7 +115,7 @@
                finished = Fields.stringToBool(fs.get("Finished"), false);
                global = Fields.stringToBool(fs.get("Global"), false);
                final String stime = fs.get("StartupTime");
-               this.startupTime = stime == null ? System.currentTimeMillis() : 
Fields.parseSILong(stime);
+               this.startupTime = stime == null ? System.currentTimeMillis() : 
Fields.parseLong(stime);
                completionTime = fs.getLong("CompletionTime", 0);
                if (finished)
                        started=true;

Modified: branches/db4o/freenet/src/freenet/node/fcp/ConfigData.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/fcp/ConfigData.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/fcp/ConfigData.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -40,49 +40,49 @@
        public SimpleFieldSet getFieldSet() {
                SimpleFieldSet fs = new SimpleFieldSet(true);
                if(withCurrent) {
-                       SimpleFieldSet current = 
node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_CURRENT_SETTINGS, true);
+                       SimpleFieldSet current = 
node.config.exportFieldSet(Config.RequestType.CURRENT_SETTINGS, true);
                        if(!current.isEmpty()) {
                                fs.put("current", current);
                        }
                }
                if(withDefaults) {
-                       SimpleFieldSet defaultSettings = 
node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_DEFAULT_SETTINGS, false);
+                       SimpleFieldSet defaultSettings = 
node.config.exportFieldSet(Config.RequestType.DEFAULT_SETTINGS, false);
                        if(!defaultSettings.isEmpty()) {
                                fs.put("default", defaultSettings);
                        }
                }
                if(withSortOrder) {
-                       SimpleFieldSet sortOrder = 
node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_SORT_ORDER, false);
+                       SimpleFieldSet sortOrder = 
node.config.exportFieldSet(Config.RequestType.SORT_ORDER, false);
                        if(!sortOrder.isEmpty()) {
                                fs.put("sortOrder", sortOrder);
                        }
                }
                if(withExpertFlag) {
-                       SimpleFieldSet expertFlag = 
node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_EXPERT_FLAG, false);
+                       SimpleFieldSet expertFlag = 
node.config.exportFieldSet(Config.RequestType.EXPERT_FLAG, false);
                        if(!expertFlag.isEmpty()) {
                                fs.put("expertFlag", expertFlag);
                        }
                }
                if(withForceWriteFlag) {
-                       SimpleFieldSet forceWriteFlag = 
node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_FORCE_WRITE_FLAG, false);
+                       SimpleFieldSet forceWriteFlag = 
node.config.exportFieldSet(Config.RequestType.FORCE_WRITE_FLAG, false);
                        if(!forceWriteFlag.isEmpty()) {
                                fs.put("forceWriteFlag", forceWriteFlag);
                        }
                }
                if(withShortDescription) {
-                       SimpleFieldSet shortDescription = 
node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_SHORT_DESCRIPTION, false);
+                       SimpleFieldSet shortDescription = 
node.config.exportFieldSet(Config.RequestType.SHORT_DESCRIPTION, false);
                        if(!shortDescription.isEmpty()) {
                                fs.put("shortDescription", shortDescription);
                        }
                }
                if(withLongDescription) {
-                       SimpleFieldSet longDescription = 
node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_LONG_DESCRIPTION, false);
+                       SimpleFieldSet longDescription = 
node.config.exportFieldSet(Config.RequestType.LONG_DESCRIPTION, false);
                        if(!longDescription.isEmpty()) {
                                fs.put("longDescription", longDescription);
                        }
                }
                if(withDataTypes) {
-                       SimpleFieldSet type = 
node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_DATA_TYPE, false);
+                       SimpleFieldSet type = 
node.config.exportFieldSet(Config.RequestType.DATA_TYPE, false);
                        if(!type.isEmpty()) {
                                fs.put("dataType", type);
                        }

Modified: branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionHandler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionHandler.java        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionHandler.java        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -1,6 +1,7 @@
 package freenet.node.fcp;

 import java.io.BufferedOutputStream;
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -22,7 +23,7 @@
 import freenet.support.io.FileUtil;
 import freenet.support.io.NativeThread;

-public class FCPConnectionHandler {
+public class FCPConnectionHandler implements Closeable {
        private static final class DirectoryAccess {
                final boolean canWrite;
                final boolean canRead;

Modified: branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java   2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java   2008-09-24 
20:42:20 UTC (rev 22823)
@@ -11,6 +11,7 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.Socket;
+import java.util.LinkedList;
 import java.util.Vector;
 import java.util.WeakHashMap;
 import java.util.zip.GZIPInputStream;
@@ -51,6 +52,7 @@
 import freenet.support.io.BucketTools;
 import freenet.support.io.Closer;
 import freenet.support.io.NativeThread;
+import freenet.support.io.FileUtil;

 /**
  * FCP server process.
@@ -188,7 +190,7 @@
                ch.start();
        }

-       static class FCPPortNumberCallback implements IntCallback {
+       static class FCPPortNumberCallback extends IntCallback  {

                private final NodeClientCore node;

@@ -196,18 +198,22 @@
                        this.node = node;
                }

-               public int get() {
+               public Integer get() {
                        return node.getFCPServer().port;
                }

-               public void set(int val) throws InvalidConfigValueException {
+               public void set(Integer val) throws InvalidConfigValueException 
{
                        if(val != get()) {
                                throw new InvalidConfigValueException("Cannot 
change FCP port number on the fly");
                        }
                }
+
+               public boolean isReadOnly() {
+                       return true;
+               }
        }

-       static class FCPEnabledCallback implements BooleanCallback{
+       static class FCPEnabledCallback extends BooleanCallback {

                final NodeClientCore node;

@@ -215,24 +221,28 @@
                        this.node = node;
                }

-               public boolean get() {
+               public Boolean get() {
                        return node.getFCPServer().enabled;
                }
 //TODO: Allow it
-               public void set(boolean val) throws InvalidConfigValueException 
{
+               public void set(Boolean val) throws InvalidConfigValueException 
{
                        if(val != get()) {
                                throw new 
InvalidConfigValueException(l10n("cannotStartOrStopOnTheFly"));
                        }
                }
+
+               public boolean isReadOnly() {
+                       return true;
+               }
        }

-       static class FCPSSLCallback implements BooleanCallback{
+       static class FCPSSLCallback extends BooleanCallback {

-               public boolean get() {
+               public Boolean get() {
                        return ssl;
                }

-               public void set(boolean val) throws InvalidConfigValueException 
{
+               public void set(Boolean val) throws InvalidConfigValueException 
{
                if(val == get()) return;
                        if(!SSL.available()) {
                                throw new InvalidConfigValueException("Enable 
SSL support before use ssl with FCP");
@@ -240,12 +250,16 @@
                        ssl = val;
                        throw new InvalidConfigValueException("Cannot change 
SSL on the fly, please restart freenet");
                }
+
+               public boolean isReadOnly() {
+                       return true;
+               }
        }

        // FIXME: Consider moving everything except enabled into constructor
        // Actually we could move enabled in too with an exception???

-       static class FCPBindtoCallback implements StringCallback{
+       static class FCPBindtoCallback extends StringCallback {

                final NodeClientCore node;

@@ -272,7 +286,7 @@
                }
        }

-       static class FCPAllowedHostsCallback implements StringCallback {
+       static class FCPAllowedHostsCallback extends StringCallback  {

                private final NodeClientCore node;

@@ -291,28 +305,26 @@
                        if (!val.equals(get())) {
                                
node.getFCPServer().networkInterface.setAllowedHosts(val);
                        }
-               }
-               
+               }               
        }

-       static class PersistentDownloadsEnabledCallback implements 
BooleanCallback {
+       static class PersistentDownloadsEnabledCallback extends BooleanCallback 
{

                boolean enabled;

-               public boolean get() {
+               public Boolean get() {
                        return enabled;
                }

-               public void set(boolean set) throws InvalidConfigValueException 
{
+               public void set(Boolean set) throws InvalidConfigValueException 
{
                        // This option will be removed completely soon, so 
there is little
                        // point in translating it. FIXME remove.
-                       if(set != enabled) throw new 
InvalidConfigValueException("Cannot disable/enable persistent download loading 
support on the fly");
+                       if(set.booleanValue() != enabled) throw new 
InvalidConfigValueException("Cannot disable/enable persistent download loading 
support on the fly");
                }

        }

-       static class FCPAllowedHostsFullAccessCallback implements 
StringCallback {
-
+       static class FCPAllowedHostsFullAccessCallback extends StringCallback  {
                private final NodeClientCore node;

                public FCPAllowedHostsFullAccessCallback(NodeClientCore node) {
@@ -330,8 +342,7 @@
                }

        }
-       
-       static class PersistentDownloadsFileCallback implements StringCallback {
+       static class PersistentDownloadsFileCallback extends StringCallback  {

                FCPServer server;

@@ -346,27 +357,27 @@
                }
        }

-       static class AssumeDDADownloadIsAllowedCallback implements 
BooleanCallback{
+       static class AssumeDDADownloadIsAllowedCallback extends BooleanCallback 
{
                FCPServer server;

-               public boolean get() {
+               public Boolean get() {
                        return server.assumeDownloadDDAIsAllowed;
                }

-               public void set(boolean val) throws InvalidConfigValueException 
{
+               public void set(Boolean val) throws InvalidConfigValueException 
{
                        if(val == get()) return;
                        server.assumeDownloadDDAIsAllowed = val;
                }
        }

-       static class AssumeDDAUploadIsAllowedCallback implements 
BooleanCallback{
+       static class AssumeDDAUploadIsAllowedCallback extends BooleanCallback {
                FCPServer server;

-               public boolean get() {
+               public Boolean get() {
                        return server.assumeUploadDDAIsAllowed;
                }

-               public void set(boolean val) throws InvalidConfigValueException 
{
+               public void set(Boolean val) throws InvalidConfigValueException 
{
                        if(val == get()) return;
                        server.assumeUploadDDAIsAllowed = val;
                }

Modified: branches/db4o/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -28,7 +28,7 @@
                SimpleFieldSet fs = new SimpleFieldSet(true);
                fs.putSingle("Identifier", identifier);
                if(global) fs.putSingle("Global", "true");
-               // FIXME debug and remove!
+               // This is useful for simple clients.
                if(uri != null)
                        fs.putSingle("URI", uri.toString());
                fs.put("StartupTime", startupTime);

Copied: branches/db4o/freenet/src/freenet/node/simulator/BootstrapPullTest.java 
(from rev 21939, 
trunk/freenet/src/freenet/node/simulator/BootstrapPullTest.java)
===================================================================
--- branches/db4o/freenet/src/freenet/node/simulator/BootstrapPullTest.java     
                        (rev 0)
+++ branches/db4o/freenet/src/freenet/node/simulator/BootstrapPullTest.java     
2008-09-24 20:42:20 UTC (rev 22823)
@@ -0,0 +1,196 @@
+package freenet.node.simulator;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.InetAddress;
+import java.net.Socket;
+
+import org.spaceroots.mantissa.random.MersenneTwister;
+
+import freenet.client.FetchException;
+import freenet.client.HighLevelSimpleClient;
+import freenet.crypt.RandomSource;
+import freenet.keys.FreenetURI;
+import freenet.node.Node;
+import freenet.node.NodeInitException;
+import freenet.node.NodeStarter;
+import freenet.support.Logger;
+import freenet.support.PooledExecutor;
+import freenet.support.SimpleFieldSet;
+import freenet.support.TimeUtil;
+import freenet.support.LoggerHook.InvalidThresholdException;
+import freenet.support.io.FileUtil;
+import freenet.support.io.LineReadingInputStream;
+
+/**
+ * Insert a random block of data to an established node via FCP, then
+ * bootstrap a newbie node and pull it from that.
+ * @author Matthew Toseland <toad at amphibian.dyndns.org> (0xE43DA450)
+ */
+public class BootstrapPullTest {
+
+       public static int TARGET_PEERS = 10;
+       public static int TEST_SIZE = 1024*1024;
+       
+       public static int EXIT_NO_SEEDNODES = 257;
+       public static int EXIT_FAILED_TARGET = 258;
+       public static int EXIT_INSERT_FAILED = 259;
+       public static int EXIT_FETCH_FAILED = 260;
+       public static int EXIT_INSERTER_PROBLEM = 261;
+       
+       public static int DARKNET_PORT = 5004;
+       public static int OPENNET_PORT = 5005;
+       
+       /**
+        * @param args
+        * @throws InvalidThresholdException 
+        * @throws IOException 
+        * @throws NodeInitException 
+        * @throws InterruptedException 
+        */
+       public static void main(String[] args) throws 
InvalidThresholdException, IOException, NodeInitException, InterruptedException 
{
+        File dir = new File("bootstrap-pull-test");
+        FileUtil.removeAll(dir);
+        RandomSource random = NodeStarter.globalTestInit(dir.getPath(), false, 
Logger.ERROR, "");
+        byte[] seed = new byte[64];
+        random.nextBytes(seed);
+        MersenneTwister fastRandom = new MersenneTwister(seed);
+        File seednodes = new File("seednodes.fref");
+        if(!seednodes.exists() || seednodes.length() == 0 || 
!seednodes.canRead()) {
+               System.err.println("Unable to read seednodes.fref, it doesn't 
exist, or is empty");
+               System.exit(EXIT_NO_SEEDNODES);
+        }
+        File secondInnerDir = new File(dir, Integer.toString(DARKNET_PORT));
+        secondInnerDir.mkdir();
+        FileInputStream fis = new FileInputStream(seednodes);
+        FileUtil.writeTo(fis, new File(secondInnerDir, "seednodes.fref"));
+        fis.close();
+        
+        // Create the test data
+        System.out.println("Creating test data.");
+        File dataFile = File.createTempFile("testdata", ".tmp", dir);
+        OutputStream os = new FileOutputStream(dataFile);
+        byte[] buf = new byte[4096];
+        for(long written = 0; written < TEST_SIZE;) {
+               fastRandom.nextBytes(buf);
+               int toWrite = (int) Math.min(TEST_SIZE - written, buf.length);
+               os.write(buf, 0, toWrite);
+               written += toWrite;
+        }
+        os.close();
+        
+        // Insert it to the established node.
+        System.out.println("Inserting test data to an established node.");
+        FreenetURI uri = insertData(dataFile);
+        
+        // Bootstrap a second node.
+        secondInnerDir.mkdir();
+        fis = new FileInputStream(seednodes);
+        FileUtil.writeTo(fis, new File(secondInnerDir, "seednodes.fref"));
+        fis.close();
+        PooledExecutor executor = new PooledExecutor();
+        Node secondNode = NodeStarter.createTestNode(DARKNET_PORT, 
OPENNET_PORT, dir.getPath(), true, false, false, Node.DEFAULT_MAX_HTL, 0, 
random, executor, 1000, 5*1024*1024, true, true, true, true, true, true, true, 
12*1024, false, true);        
+        secondNode.start(true);
+        waitForTenNodes(secondNode);
+        
+        // Fetch the data
+        long startFetchTime = System.currentTimeMillis();
+        HighLevelSimpleClient client = 
secondNode.clientCore.makeClient((short)0);
+        try {
+                       client.fetch(uri);
+               } catch (FetchException e) {
+                       System.err.println("FETCH FAILED: "+e);
+                       e.printStackTrace();
+                       System.exit(EXIT_FETCH_FAILED);
+                       return;
+               }
+               long endFetchTime = System.currentTimeMillis();
+               System.out.println("RESULT: Fetch took 
"+(endFetchTime-startFetchTime)+"ms 
("+TimeUtil.formatTime(endFetchTime-startFetchTime)+") of "+uri+" .");
+               secondNode.park();
+               System.exit(0);
+
+       }
+
+       private static FreenetURI insertData(File dataFile) throws IOException {
+        long startInsertTime = System.currentTimeMillis();
+        InetAddress localhost = InetAddress.getByName("127.0.0.1");
+        Socket sock = new Socket(localhost, 9481);
+        OutputStream sockOS = sock.getOutputStream();
+        InputStream sockIS = sock.getInputStream();
+        System.out.println("Connected to node.");
+        LineReadingInputStream lis = new LineReadingInputStream(sockIS);
+        OutputStreamWriter osw = new OutputStreamWriter(sockOS, "UTF-8");
+        
osw.write("ClientHello\nExpectedVersion=0.7\nName=BootstrapPullTest-"+System.currentTimeMillis()+"\nEnd\n");
+        osw.flush();
+               String name = lis.readLine(65536, 128, true);
+               SimpleFieldSet fs = new SimpleFieldSet(lis, 65536, 128, true, 
true, false, true);
+               if(!name.equals("NodeHello")) {
+                       System.err.println("No NodeHello from insertor node!");
+                       System.exit(EXIT_INSERTER_PROBLEM);
+               }
+               System.out.println("Connected to "+sock);
+               
osw.write("ClientPut\nIdentifier=test-insert\nURI=CHK@\nVerbosity=1023\nUploadFrom=direct\nMaxRetries=-1\nDataLength="+TEST_SIZE+"\nData\n");
+               osw.flush();
+               InputStream is = new FileInputStream(dataFile);
+               FileUtil.copy(is, sockOS, TEST_SIZE);
+               System.out.println("Sent data");
+               while(true) {
+               name = lis.readLine(65536, 128, true);
+               fs = new SimpleFieldSet(lis, 65536, 128, true, true, false, 
true);
+                       System.out.println("Got FCP message: \n"+name);
+                       System.out.print(fs.toOrderedString());
+                       if(name.equals("ProtocolError")) {
+                               System.err.println("Protocol error when 
inserting data.");
+                               System.exit(EXIT_INSERTER_PROBLEM);
+                       }
+                       if(name.equals("PutFailed")) {
+                               System.err.println("Insert failed");
+                               System.exit(EXIT_INSERT_FAILED);
+                       }
+                       if(name.equals("PutSuccessful")) {
+                       long endInsertTime = System.currentTimeMillis();
+                               FreenetURI uri = new FreenetURI(fs.get("URI"));
+                       System.out.println("RESULT: Insert took 
"+(endInsertTime-startInsertTime)+"ms 
("+TimeUtil.formatTime(endInsertTime-startInsertTime)+") to "+uri+" .");
+                               sockOS.close();
+                               sockIS.close();
+                               sock.close();
+                               return uri;
+                       }
+               }
+       }
+       
+       private static void waitForTenNodes(Node node) throws 
InterruptedException {
+       long startTime = System.currentTimeMillis();
+        // Wait until we have 10 connected nodes...
+        int seconds = 0;
+        boolean success = false;
+        while(seconds < 600) {
+               Thread.sleep(1000);
+               int seeds = node.peers.countSeednodes();
+               int seedConns = 
node.peers.getConnectedSeedServerPeersVector(null).size();
+               int opennetPeers = node.peers.countValidPeers();
+               int opennetConns = node.peers.countConnectedOpennetPeers();
+               System.err.println(""+seconds+" : seeds: "+seeds+", connected: 
"+seedConns
+                               +" opennet: peers: "+opennetPeers+", connected: 
"+opennetConns);
+               seconds++;
+               if(opennetConns >= TARGET_PEERS) {
+                       long timeTaken = System.currentTimeMillis()-startTime;
+                       System.out.println("RESULT: Completed bootstrap 
("+TARGET_PEERS+" peers) in "+timeTaken+"ms 
("+TimeUtil.formatTime(timeTaken)+")");
+                       success = true;
+                       break;
+               }
+        }
+        if(!success) {
+               System.err.println("Failed to reach target peers count 
"+TARGET_PEERS+" in 10 minutes.");
+               node.park();
+               System.exit(EXIT_FAILED_TARGET);
+        }
+       }
+
+
+}

Copied: 
branches/db4o/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java 
(from rev 21939, 
trunk/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java)
===================================================================
--- branches/db4o/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java 
                        (rev 0)
+++ branches/db4o/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java 
2008-09-24 20:42:20 UTC (rev 22823)
@@ -0,0 +1,143 @@
+package freenet.node.simulator;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import freenet.client.ClientMetadata;
+import freenet.client.FetchException;
+import freenet.client.HighLevelSimpleClient;
+import freenet.client.InsertBlock;
+import freenet.client.InsertException;
+import freenet.crypt.RandomSource;
+import freenet.keys.FreenetURI;
+import freenet.node.Node;
+import freenet.node.NodeInitException;
+import freenet.node.NodeStarter;
+import freenet.support.Executor;
+import freenet.support.Logger;
+import freenet.support.PooledExecutor;
+import freenet.support.TimeUtil;
+import freenet.support.LoggerHook.InvalidThresholdException;
+import freenet.support.api.Bucket;
+import freenet.support.io.FileUtil;
+
+public class BootstrapPushPullTest {
+
+       public static int TARGET_PEERS = 10;
+       public static int TEST_SIZE = 1024*1024;
+       
+       public static int EXIT_NO_SEEDNODES = 257;
+       public static int EXIT_FAILED_TARGET = 258;
+       public static int EXIT_INSERT_FAILED = 259;
+       public static int EXIT_FETCH_FAILED = 260;
+       
+       public static void main(String[] args) throws 
InvalidThresholdException, IOException, NodeInitException, InterruptedException 
{
+        File dir = new File("bootstrap-push-pull-test");
+        FileUtil.removeAll(dir);
+        RandomSource random = NodeStarter.globalTestInit(dir.getPath(), false, 
Logger.ERROR, "");
+        File seednodes = new File("seednodes.fref");
+        if(!seednodes.exists() || seednodes.length() == 0 || 
!seednodes.canRead()) {
+               System.err.println("Unable to read seednodes.fref, it doesn't 
exist, or is empty");
+               System.exit(EXIT_NO_SEEDNODES);
+        }
+        File innerDir = new File(dir, "5000");
+        innerDir.mkdir();
+        FileInputStream fis = new FileInputStream(seednodes);
+        FileUtil.writeTo(fis, new File(innerDir, "seednodes.fref"));
+        fis.close();
+        // Create one node
+        Executor executor = new PooledExecutor();
+        Node node = NodeStarter.createTestNode(5000, 5001, dir.getPath(), 
true, false, false, Node.DEFAULT_MAX_HTL, 0, random, executor, 1000, 
5*1024*1024, true, true, true, true, true, true, true, 12*1024, false, true);
+        //NodeCrypto.DISABLE_GROUP_STRIP = true;
+       //Logger.setupStdoutLogging(Logger.MINOR, 
"freenet:NORMAL,freenet.node.NodeDispatcher:MINOR,freenet.node.FNPPacketMangler:MINOR");
+       Logger.getChain().setThreshold(Logger.ERROR); // kill logging
+       // Start it
+        node.start(true);
+        waitForTenNodes(node);
+        System.out.println("Creating test data: "+TEST_SIZE+" bytes.");
+        Bucket data = node.clientCore.tempBucketFactory.makeBucket(TEST_SIZE);
+        OutputStream os = data.getOutputStream();
+        byte[] buf = new byte[4096];
+        for(long written = 0; written < TEST_SIZE;) {
+               node.fastWeakRandom.nextBytes(buf);
+               int toWrite = (int) Math.min(TEST_SIZE - written, buf.length);
+               os.write(buf, 0, toWrite);
+               written += toWrite;
+        }
+        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);
+        long startInsertTime = System.currentTimeMillis();
+        FreenetURI uri;
+        try {
+                       uri = client.insert(block, false, null);
+               } catch (InsertException e) {
+                       System.err.println("INSERT FAILED: "+e);
+                       e.printStackTrace();
+                       System.exit(EXIT_INSERT_FAILED);
+                       return;
+               }
+        long endInsertTime = System.currentTimeMillis();
+        System.out.println("RESULT: Insert took 
"+(endInsertTime-startInsertTime)+"ms 
("+TimeUtil.formatTime(endInsertTime-startInsertTime)+") to "+uri+" .");
+        node.park();
+               
+        // Bootstrap a second node.
+        File secondInnerDir = new File(dir, "5002");
+        secondInnerDir.mkdir();
+        fis = new FileInputStream(seednodes);
+        FileUtil.writeTo(fis, new File(secondInnerDir, "seednodes.fref"));
+        fis.close();
+        executor = new PooledExecutor();
+        Node secondNode = NodeStarter.createTestNode(5002, 5003, 
dir.getPath(), true, false, false, Node.DEFAULT_MAX_HTL, 0, random, executor, 
1000, 5*1024*1024, true, true, true, true, true, true, true, 12*1024, false, 
true);        
+        secondNode.start(true);
+        waitForTenNodes(secondNode);
+        
+        // Fetch the data
+        long startFetchTime = System.currentTimeMillis();
+        client = secondNode.clientCore.makeClient((short)0);
+        try {
+                       client.fetch(uri);
+               } catch (FetchException e) {
+                       System.err.println("FETCH FAILED: "+e);
+                       e.printStackTrace();
+                       System.exit(EXIT_FETCH_FAILED);
+                       return;
+               }
+               long endFetchTime = System.currentTimeMillis();
+               System.out.println("RESULT: Fetch took 
"+(endFetchTime-startFetchTime)+"ms 
("+TimeUtil.formatTime(endFetchTime-startFetchTime)+") of "+uri+" .");
+               secondNode.park();
+               System.exit(0);
+       }
+
+       private static void waitForTenNodes(Node node) throws 
InterruptedException {
+       long startTime = System.currentTimeMillis();
+        // Wait until we have 10 connected nodes...
+        int seconds = 0;
+        boolean success = false;
+        while(seconds < 600) {
+               Thread.sleep(1000);
+               int seeds = node.peers.countSeednodes();
+               int seedConns = 
node.peers.getConnectedSeedServerPeersVector(null).size();
+               int opennetPeers = node.peers.countValidPeers();
+               int opennetConns = node.peers.countConnectedOpennetPeers();
+               System.err.println(""+seconds+" : seeds: "+seeds+", connected: 
"+seedConns
+                               +" opennet: peers: "+opennetPeers+", connected: 
"+opennetConns);
+               seconds++;
+               if(opennetConns >= TARGET_PEERS) {
+                       long timeTaken = System.currentTimeMillis()-startTime;
+                       System.out.println("RESULT: Completed bootstrap 
("+TARGET_PEERS+" peers) in "+timeTaken+"ms 
("+TimeUtil.formatTime(timeTaken)+")");
+                       success = true;
+                       break;
+               }
+        }
+        if(!success) {
+               System.err.println("Failed to reach target peers count 
"+TARGET_PEERS+" in 10 minutes.");
+               node.park();
+               System.exit(EXIT_FAILED_TARGET);
+        }
+       }
+
+}

Copied: branches/db4o/freenet/src/freenet/node/simulator/BootstrapSeedTest.java 
(from rev 21939, 
trunk/freenet/src/freenet/node/simulator/BootstrapSeedTest.java)
===================================================================
--- branches/db4o/freenet/src/freenet/node/simulator/BootstrapSeedTest.java     
                        (rev 0)
+++ branches/db4o/freenet/src/freenet/node/simulator/BootstrapSeedTest.java     
2008-09-24 20:42:20 UTC (rev 22823)
@@ -0,0 +1,77 @@
+package freenet.node.simulator;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import freenet.crypt.RandomSource;
+import freenet.node.Node;
+import freenet.node.NodeInitException;
+import freenet.node.NodeStarter;
+import freenet.support.Executor;
+import freenet.support.Logger;
+import freenet.support.PooledExecutor;
+import freenet.support.TimeUtil;
+import freenet.support.LoggerHook.InvalidThresholdException;
+import freenet.support.io.FileUtil;
+
+public class BootstrapSeedTest {
+
+       public static int TARGET_PEERS = 10;
+       public static int EXIT_NO_SEEDNODES = 257;
+       public static int EXIT_FAILED_TARGET = 258;
+       
+       /**
+        * @param args
+        * @throws InvalidThresholdException 
+        * @throws NodeInitException 
+        * @throws InterruptedException 
+        * @throws IOException 
+        */
+       public static void main(String[] args) throws 
InvalidThresholdException, NodeInitException, InterruptedException, IOException 
{
+        File dir = new File("bootstrap-test");
+        FileUtil.removeAll(dir);
+        RandomSource random = NodeStarter.globalTestInit(dir.getPath(), false, 
Logger.ERROR, "");
+        File seednodes = new File("seednodes.fref");
+        if(!seednodes.exists() || seednodes.length() == 0 || 
!seednodes.canRead()) {
+               System.err.println("Unable to read seednodes.fref, it doesn't 
exist, or is empty");
+               System.exit(EXIT_NO_SEEDNODES);
+        }
+        File innerDir = new File(dir, "5000");
+        innerDir.mkdir();
+        FileInputStream fis = new FileInputStream(seednodes);
+        FileUtil.writeTo(fis, new File(innerDir, "seednodes.fref"));
+        fis.close();
+        // Create one node
+        Executor executor = new PooledExecutor();
+        Node node = NodeStarter.createTestNode(5000, 5001, "bootstrap-test", 
true, false, false, Node.DEFAULT_MAX_HTL, 0, random, executor, 1000, 
5*1024*1024, true, true, true, true, true, true, true, 12*1024, false, true);
+        //NodeCrypto.DISABLE_GROUP_STRIP = true;
+       //Logger.setupStdoutLogging(Logger.MINOR, 
"freenet:NORMAL,freenet.node.NodeDispatcher:MINOR,freenet.node.FNPPacketMangler:MINOR");
+       Logger.getChain().setThreshold(Logger.ERROR); // kill logging
+       long startTime = System.currentTimeMillis();
+       // Start it
+        node.start(true);
+        // Wait until we have 10 connected nodes...
+        int seconds = 0;
+        while(seconds < 600) {
+               Thread.sleep(1000);
+               int seeds = node.peers.countSeednodes();
+               int seedConns = 
node.peers.getConnectedSeedServerPeersVector(null).size();
+               int opennetPeers = node.peers.countValidPeers();
+               int opennetConns = node.peers.countConnectedOpennetPeers();
+               System.err.println(""+seconds+" : seeds: "+seeds+", connected: 
"+seedConns
+                               +" opennet: peers: "+opennetPeers+", connected: 
"+opennetConns);
+               seconds++;
+               if(opennetConns >= TARGET_PEERS) {
+                       long timeTaken = System.currentTimeMillis()-startTime;
+                       System.out.println("Completed bootstrap 
("+TARGET_PEERS+" peers) in "+timeTaken+"ms 
("+TimeUtil.formatTime(timeTaken)+")");
+                       node.park();
+                       System.exit(0);
+               }
+        }
+        System.err.println("Failed to reach target peers count 
"+TARGET_PEERS+" in 5 minutes.");
+               node.park();
+        System.exit(EXIT_FAILED_TARGET);
+       }
+
+}

Modified: 
branches/db4o/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java   
    2008-09-24 19:52:19 UTC (rev 22822)
+++ 
branches/db4o/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java   
    2008-09-24 20:42:20 UTC (rev 22823)
@@ -157,9 +157,9 @@
                        totalRunningRequests += 
nodes[i].clientCore.countTransientQueuedRequests();
                }
                System.err.println("Running requests: "+totalRunningRequests);
-               if(totalRunningRequests == 0) return;
+               if(totalRunningRequests == 0) break;
                Thread.sleep(1000);
         }
-        
+        System.exit(0);
     }
 }

Modified: 
branches/db4o/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java 
    2008-09-24 19:52:19 UTC (rev 22822)
+++ 
branches/db4o/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java 
    2008-09-24 20:42:20 UTC (rev 22823)
@@ -24,7 +24,6 @@
 import freenet.support.Executor;
 import freenet.support.Logger;
 import freenet.support.PooledExecutor;
-import freenet.support.StringArray;
 import freenet.support.LoggerHook.InvalidThresholdException;
 import freenet.support.io.ArrayBucket;
 import freenet.support.io.FileUtil;
@@ -209,7 +208,7 @@
                 if(totalRunningUIDsAlt != 0)
                        System.err.println("Still running UIDs (alt): 
"+totalRunningUIDsAlt);
                 if(!runningUIDsList.isEmpty()) {
-                       System.err.println("List of running UIDs: 
"+StringArray.toString(runningUIDsList.toArray()));
+                       System.err.println("List of running UIDs: 
"+Arrays.toString(runningUIDsList.toArray()));
                 }
             } catch (Throwable t) {
                 Logger.error(RealNodeRequestInsertTest.class, "Caught "+t, t);

Modified: branches/db4o/freenet/src/freenet/node/simulator/SeednodePingTest.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/simulator/SeednodePingTest.java      
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/simulator/SeednodePingTest.java      
2008-09-24 20:42:20 UTC (rev 22823)
@@ -10,7 +10,6 @@
 import freenet.node.Announcer;
 import freenet.node.FSParseException;
 import freenet.node.Node;
-import freenet.node.NodeCrypto;
 import freenet.node.NodeInitException;
 import freenet.node.NodeStarter;
 import freenet.node.OpennetDisabledException;
@@ -39,7 +38,6 @@
         // Create one node
         Executor executor = new PooledExecutor();
        Node 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);
-       NodeCrypto.DISABLE_GROUP_STRIP = true;
        // Connect & ping
        Vector<SeedServerTestPeerNode> seedNodes = new 
Vector<SeedServerTestPeerNode>();
        Vector<SimpleFieldSet> seedNodesAsSFS = Announcer.readSeednodes(new 
File("/tmp/"));

Modified: branches/db4o/freenet/src/freenet/node/updater/NodeUpdateManager.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/updater/NodeUpdateManager.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/node/updater/NodeUpdateManager.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -804,29 +804,29 @@

        // Config callbacks

-       class UpdaterEnabledCallback implements BooleanCallback {
+       class UpdaterEnabledCallback extends BooleanCallback  {

-               public boolean get() {
+               public Boolean get() {
                        return isEnabled();
                }

-               public void set(boolean val) throws InvalidConfigValueException 
{
+               public void set(Boolean val) throws InvalidConfigValueException 
{
                        enable(val);
                }
        }

-       class AutoUpdateAllowedCallback implements BooleanCallback {
+       class AutoUpdateAllowedCallback extends BooleanCallback  {

-               public boolean get() {
+               public Boolean get() {
                        return isAutoUpdateAllowed();
                }

-               public void set(boolean val) throws InvalidConfigValueException 
{
+               public void set(Boolean val) throws InvalidConfigValueException 
{
                        setAutoUpdateAllowed(val);
                }
        }

-       class UpdateURICallback implements StringCallback {
+       class UpdateURICallback extends StringCallback  {

                boolean isExt;

@@ -847,10 +847,9 @@
                        }
                        setURI(isExt, uri);
                }
-
        }

-       public class UpdateRevocationURICallback implements StringCallback {
+       public class UpdateRevocationURICallback extends StringCallback  {

                public String get() {
                        return getRevocationURI().toString(false, false);
@@ -865,7 +864,6 @@
                        }
                        setRevocationURI(uri);
                }
-               
        }

        /** Called when a peer indicates in its UOMAnnounce that it has fetched 
the revocation key

Modified: 
branches/db4o/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java
  2008-09-24 19:52:19 UTC (rev 22822)
+++ 
branches/db4o/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java
  2008-09-24 20:42:20 UTC (rev 22823)
@@ -17,6 +17,7 @@
                this.node = n;
        }

+       @Override
        public String getTitle() {
                return l10n("noNodeNickTitle");
        }
@@ -25,14 +26,17 @@
                return L10n.getString("MeaningfulNodeNameUserAlert."+key);
        }

+       @Override
        public String getText() {
                return l10n("noNodeNick");
        }

+       @Override
        public String getShortText() {
                return l10n("noNodeNickShort");
        }

+       @Override
        public HTMLNode getHTMLText() {
                SubConfig sc = node.config.get("node");
                Option o = sc.getOption("name");
@@ -55,4 +59,8 @@
                return alertNode;
        }

+       @Override
+       public boolean isValid() {
+               return node.peers.anyDarknetPeers();
+       }
 }

Copied: 
branches/db4o/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java
 (from rev 21939, 
trunk/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java)
===================================================================
--- 
branches/db4o/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java
                           (rev 0)
+++ 
branches/db4o/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java
   2008-09-24 20:42:20 UTC (rev 22823)
@@ -0,0 +1,17 @@
+/* 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;
+
+public interface FredPluginBandwidthIndicator {
+
+       /**
+        * @return the reported upstream bit rate in bits per second. -1 if 
it's not available. Blocking.
+        */
+       public int getUpstramMaxBitRate();
+
+       /**
+        * @return the reported downstream bit rate in bits per second. -1 if 
it's not available. Blocking.
+        */
+       public int getDownstreamMaxBitRate();
+}

Modified: 
branches/db4o/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java   
    2008-09-24 19:52:19 UTC (rev 22822)
+++ 
branches/db4o/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java   
    2008-09-24 20:42:20 UTC (rev 22823)
@@ -3,12 +3,15 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.pluginmanager;

+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.MalformedURLException;
 import java.net.URL;
+import java.net.URLConnection;
 import java.security.KeyStore;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
@@ -35,7 +38,29 @@

        @Override
        String getSHA1sum() throws PluginNotFoundException {
-               return null;
+               try {
+                       URL sha1url = new URL(getSource().toString()+".sha1");
+                       URLConnection urlConnection = sha1url.openConnection();
+                       urlConnection.setUseCaches(false);
+                       urlConnection.setAllowUserInteraction(false);
+                       
+                       InputStream is = 
openConnectionCheckRedirects(urlConnection);
+                       ByteArrayOutputStream bos = new ByteArrayOutputStream();
+               
+                       byte[] buffer = new byte[1024];
+                       int read;
+               
+                       while ((read = is.read(buffer)) != -1) {
+                               bos.write(buffer, 0, read);
+                       }
+                       
+                       return new String(bos.toByteArray()).split(" ")[0];
+       
+               } catch (MalformedURLException e) {
+                       throw new PluginNotFoundException("impossible: "+e,e);
+               } catch (IOException e) {
+                       throw new PluginNotFoundException("Error while fetching 
sha1 for plugin: "+e,e);
+               }
        }

        @Override

Modified: branches/db4o/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
===================================================================
--- branches/db4o/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java      
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java      
2008-09-24 20:42:20 UTC (rev 22823)
@@ -5,37 +5,37 @@

 import freenet.l10n.L10n;
 import freenet.support.Logger;
-import freenet.support.StringArray;

 public class PluginInfoWrapper {
        // Parameters to make the object OTP
        private boolean fedPluginThread = false;
        // Public since only PluginHandler will know about it
-       private String className;
+       private final String className;
        private Thread thread;
-       private long start;
-       private String threadName;
+       private final long start;
+       private final String threadName;
        final FredPlugin plug;
-       private boolean isPproxyPlugin;
-       private boolean isThreadlessPlugin;
-       private boolean isIPDetectorPlugin;
-       private boolean isPortForwardPlugin;
-       private boolean isMultiplePlugin;
-       private boolean isFCPPlugin;
-       private boolean isVersionedPlugin;
-       private String filename;
-       private HashSet toadletLinks=new HashSet();
-       private boolean stopping = false;
-       private boolean unregistered = false;
+       private final boolean isPproxyPlugin;
+       private final boolean isThreadlessPlugin;
+       private final boolean isIPDetectorPlugin;
+       private final boolean isBandwidthIndicator;
+       private final boolean isPortForwardPlugin;
+       private final boolean isMultiplePlugin;
+       private final boolean isFCPPlugin;
+       private final boolean isVersionedPlugin;
+       private final String filename;
+       private HashSet<String> toadletLinks = new HashSet<String>();
+       private volatile boolean stopping = false;
+       private volatile boolean unregistered = false;

        public PluginInfoWrapper(FredPlugin plug, String filename) {
                this.plug = plug;
-               if (fedPluginThread) return;
                className = plug.getClass().toString();
                this.filename = filename;
                threadName = 'p' + className.replaceAll("^class ", "") + '_' + 
hashCode();
                start = System.currentTimeMillis();
                fedPluginThread = true;
+               isBandwidthIndicator = (plug instanceof 
FredPluginBandwidthIndicator);
                isPproxyPlugin = (plug instanceof FredPluginHTTP);
                isThreadlessPlugin = (plug instanceof FredPluginThreadless);
                isIPDetectorPlugin = (plug instanceof FredPluginIPDetector);
@@ -52,6 +52,7 @@
                thread.setName(threadName);
        }

+       @Override
        public String toString() {
                return "ID: \"" +threadName + "\", Name: "+ className +", 
Started: " + (new Date(start)).toString();
        }
@@ -77,7 +78,7 @@
        }

        public synchronized String[] getPluginToadletSymlinks(){
-               return StringArray.toArray(toadletLinks.toArray());
+               return toadletLinks.toArray(new String[0]);
        }

        public synchronized boolean addPluginToadletSymlink(String linkfrom){
@@ -143,6 +144,8 @@
                        
manager.node.ipDetector.unregisterIPDetectorPlugin((FredPluginIPDetector)plug);
                if(isPortForwardPlugin)
                        
manager.node.ipDetector.unregisterPortForwardPlugin((FredPluginPortForward)plug);
+               if(isBandwidthIndicator)
+                       
manager.node.ipDetector.unregisterBandwidthIndicatorPlugin((FredPluginBandwidthIndicator)plug);
        }

        public boolean isPproxyPlugin() {
@@ -152,6 +155,10 @@
        public String getFilename() {
                return filename;
        }
+       
+       public boolean isBandwidthIndicator() {
+               return isBandwidthIndicator;
+       }

        public boolean isThreadlessPlugin() {
                return isThreadlessPlugin;

Modified: branches/db4o/freenet/src/freenet/pluginmanager/PluginManager.java
===================================================================
--- branches/db4o/freenet/src/freenet/pluginmanager/PluginManager.java  
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/pluginmanager/PluginManager.java  
2008-09-24 20:42:20 UTC (rev 22823)
@@ -6,20 +6,15 @@
 import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
 import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import java.util.Vector;
@@ -45,7 +40,6 @@
 import freenet.support.Logger;
 import freenet.support.api.HTTPRequest;
 import freenet.support.api.StringArrCallback;
-import freenet.support.api.StringCallback;
 import freenet.support.io.Closer;
 import freenet.support.io.FileUtil;

@@ -60,16 +54,11 @@
         * TODO: Synchronize
         *
         */
-
-       private String configFile;
-       private String installDir;
-       
        private final HashMap toadletList;

        /* All currently starting plugins. */
-       private final Set/* <PluginProgress> */startingPlugins = new HashSet/* 
<PluginProgress> */();
-
-       private final Vector/* <PluginInfoWrapper> */pluginWrappers;
+       private final Set<PluginProgress> startingPlugins = new 
HashSet<PluginProgress>();
+       private final Vector<PluginInfoWrapper> pluginWrappers;
        final Node node;
        private final NodeClientCore core;
        SubConfig pmconfig;
@@ -78,23 +67,25 @@
        private final HighLevelSimpleClient client;

        public PluginManager(Node node) {
-               
+
                logMINOR = Logger.shouldLog(Logger.MINOR, this);
                logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
                // config 
-               
+
                toadletList = new HashMap();
                pluginWrappers = new Vector();
                this.node = node;
                this.core = node.clientCore;
-               
-               if(logMINOR) Logger.minor(this, "Starting Plugin Manager");
-               
-               if(logDEBUG) Logger.debug(this, "Initialize Plugin Manager 
config");
-               
+
+               if(logMINOR)
+                       Logger.minor(this, "Starting Plugin Manager");
+
+               if(logDEBUG)
+                       Logger.debug(this, "Initialize Plugin Manager config");
+
                client = 
core.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS, true);
-               

+
                pmconfig = new SubConfig("pluginmanager", node.config);
 //             pmconfig.register("configfile", "fplugins.ini", 9, true, true, 
"PluginConfig.configFile", "PluginConfig.configFileLong",
 //                             new StringCallback() {
@@ -124,44 +115,43 @@
 //             installDir = pmconfig.getString("installdir");

                // Start plugins in the config
-               pmconfig.register("loadplugin", null, 9, true, false, 
"PluginManager.loadedOnStartup", "PluginManager.loadedOnStartupLong",
-                               new StringArrCallback() {
-                       public String[] get() {
-                               return getConfigLoadString();
-                       }
+               pmconfig.register("loadplugin", null, 0, true, false, 
"PluginManager.loadedOnStartup", "PluginManager.loadedOnStartupLong",
+                       new StringArrCallback() {

-                       public void set(String[] val) throws 
InvalidConfigValueException {
-                               //if(storeDir.equals(new File(val))) return;
-                               // FIXME
-                               throw new 
InvalidConfigValueException(L10n.getString("PluginManager.cannotSetOnceLoaded"));
-                       }
-               });
+                               public String[] get() {
+                                       return getConfigLoadString();
+                               }

+                               public void set(String[] val) throws 
InvalidConfigValueException {
+                                       //if(storeDir.equals(new File(val))) 
return;
+                                       // FIXME
+                                       throw new 
InvalidConfigValueException(L10n.getString("PluginManager.cannotSetOnceLoaded"));
+                               }
+
+                       @Override
+                               public boolean isReadOnly() {
+                                       return true;
+                               }
+                       });
+
                String fns[] = pmconfig.getStringArr("loadplugin");
-               if (fns != null) {
-                       for (String name : fns)
+               if(fns != null)
+                       for(String name : fns)
                                startPluginAuto(name, false);
-               }

                pmconfig.finishedInitialization();
        }

        private String[] getConfigLoadString() {
-               try{
-                       Iterator it = getPlugins().iterator();
-
-                       Vector v = new Vector();
-
-                       while (it.hasNext()) {
-                               PluginInfoWrapper pluginInfoWrapper = 
(PluginInfoWrapper) it.next();
-                               v.add(pluginInfoWrapper.getFilename());
+               Vector<String> v = new Vector<String>();
+               
+               synchronized(pluginWrappers) {
+                       for(PluginInfoWrapper pi : pluginWrappers) {
+                               v.add(pi.getFilename());
                        }
-
-                       return (String[]) v.toArray(new String[v.size()]);
-               }catch (NullPointerException e){
-                       Logger.error(this, "error while loading plugins: 
disabling them:"+e);
-                       return new String[0];
                }
+               
+               return v.toArray(new String[v.size()]);
        }

        /**
@@ -169,32 +159,30 @@
         * 
         * @return All currently starting plugins
         */
-       public Set/* <PluginProgess> */getStartingPlugins() {
-               synchronized (startingPlugins) {
+       public Set/* <PluginProgess> */ getStartingPlugins() {
+               synchronized(startingPlugins) {
                        return new HashSet/* <PluginProgress> 
*/(startingPlugins);
                }
        }
-       
-       
        // try to guess around...
        public void startPluginAuto(final String pluginname, boolean store) {
-               
-               if (isOfficialPlugin(pluginname)) {
+
+               if(isOfficialPlugin(pluginname)) {
                        startPluginOfficial(pluginname, store);
                        return;
                }
-               
+
                try {
                        FreenetURI uri = new FreenetURI(pluginname);
                        startPluginFreenet(pluginname, store);
                        return;
-               } catch (MalformedURLException e) {
+               } catch(MalformedURLException e) {
                        // not a freenet key
                }
-               
+
                File[] roots = File.listRoots();
-               for (File f: roots) {
-                       if (pluginname.startsWith(f.getName())) {
+               for(File f : roots) {
+                       if(pluginname.startsWith(f.getName())) {
                                startPluginFile(pluginname, store);
                                return;
                        }
@@ -202,28 +190,28 @@

                startPluginURL(pluginname, store);
        }
-       
+
        public void startPluginOfficial(final String pluginname, boolean store) 
{
                realStartPlugin(new PluginDownLoaderOfficial(), pluginname, 
store);
        }
-       
+
        public void startPluginFile(final String filename, boolean store) {
                realStartPlugin(new PluginDownLoaderFile(), filename, store);
        }
-       
+
        public void startPluginURL(final String filename, boolean store) {
                realStartPlugin(new PluginDownLoaderURL(), filename, store);
        }
-       
+
        public void startPluginFreenet(final String filename, boolean store) {
                realStartPlugin(new PluginDownLoaderFreenet(client), filename, 
true);
        }
-       
+
        private void realStartPlugin(final PluginDownLoader pdl, final String 
filename, final boolean store) {
-               if (filename.trim().length() == 0)
+               if(filename.trim().length() == 0)
                        return;
                final PluginProgress pluginProgress = new 
PluginProgress(filename);
-               synchronized (startingPlugins) {
+               synchronized(startingPlugins) {
                        startingPlugins.add(pluginProgress);
                }
                node.executor.execute(new Runnable() {
@@ -235,32 +223,29 @@
                                        plug = loadPlugin(pdl, filename);
                                        
pluginProgress.setProgress(PluginProgress.STARTING);
                                        PluginInfoWrapper pi = 
PluginHandler.startPlugin(PluginManager.this, filename, plug, new 
PluginRespirator(node, PluginManager.this));
-                                       synchronized (pluginWrappers) {
+                                       synchronized(pluginWrappers) {
                                                pluginWrappers.add(pi);
                                        }
                                        Logger.normal(this, "Plugin loaded: " + 
filename);
-                               } catch (PluginNotFoundException e) {
+                               } catch(PluginNotFoundException e) {
                                        Logger.normal(this, "Loading plugin 
failed (" + filename + ')', e);
                                        String message = e.getMessage();
-                                       core.alerts.register(new 
SimpleUserAlert(true, l10n("pluginLoadingFailedTitle"), 
l10n("pluginLoadingFailedWithMessage", new String[] { "name", "message" }, new 
String[] { filename, message }), l10n("pluginLoadingFailedShort", "name", 
filename), UserAlert.ERROR, PluginManager.class));
-                               } catch (UnsupportedClassVersionError e) {
+                                       core.alerts.register(new 
SimpleUserAlert(true, l10n("pluginLoadingFailedTitle"), 
l10n("pluginLoadingFailedWithMessage", new String[]{"name", "message"}, new 
String[]{filename, message}), l10n("pluginLoadingFailedShort", "name", 
filename), UserAlert.ERROR, PluginManager.class));
+                               } catch(UnsupportedClassVersionError e) {
                                        Logger.error(this, "Could not load 
plugin " + filename + " : " + e, e);
                                        System.err.println("Could not load 
plugin " + filename + " : " + e);
                                        e.printStackTrace();
-                                       String jvmVersion = 
System.getProperty("java.version");
-                                       if (jvmVersion.startsWith("1.4.") || 
jvmVersion.equals("1.4")) {
-                                               System.err.println("Plugin " + 
filename + " appears to require a later JVM");
-                                               Logger.error(this, "Plugin " + 
filename + " appears to require a later JVM");
-                                               core.alerts.register(new 
SimpleUserAlert(true, l10n("pluginReqNewerJVMTitle", "name", filename), 
l10n("pluginReqNewerJVM", "name", filename), l10n("pluginLoadingFailedShort", 
"name", filename), UserAlert.ERROR, PluginManager.class));
-                                       }
+                                       System.err.println("Plugin " + filename 
+ " appears to require a later JVM");
+                                       Logger.error(this, "Plugin " + filename 
+ " appears to require a later JVM");
+                                       core.alerts.register(new 
SimpleUserAlert(true, l10n("pluginReqNewerJVMTitle", "name", filename), 
l10n("pluginReqNewerJVM", "name", filename), l10n("pluginLoadingFailedShort", 
"name", filename), UserAlert.ERROR, PluginManager.class));
                                } finally {
-                                       synchronized (startingPlugins) {
+                                       synchronized(startingPlugins) {
                                                
startingPlugins.remove(pluginProgress);
                                        }
                                }
                                /* try not to destroy the config. */
-                               synchronized (this) {
-                                       if (store)
+                               synchronized(this) {
+                                       if(store)
                                                core.storeConfig();
                                }
                        }
@@ -270,15 +255,15 @@
        void register(FredPlugin plug, PluginInfoWrapper pi) {
                // handles FProxy? If so, register

-               if (pi.isPproxyPlugin())
+               if(pi.isPproxyPlugin())
                        registerToadlet(plug);

-               if(pi.isIPDetectorPlugin()) {
+               if(pi.isIPDetectorPlugin())
                        
node.ipDetector.registerIPDetectorPlugin((FredPluginIPDetector) plug);
-               }
-               if(pi.isPortForwardPlugin()) {
+               if(pi.isPortForwardPlugin())
                        
node.ipDetector.registerPortForwardPlugin((FredPluginPortForward) plug);
-               }
+               if(pi.isBandwidthIndicator())
+                       
node.ipDetector.registerBandwidthIndicatorPlugin((FredPluginBandwidthIndicator) 
plug);
        }

        /**
@@ -294,7 +279,7 @@
        }

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

        /**
@@ -313,20 +298,21 @@
                return L10n.getString("PluginManager." + key, patterns, values);
        }

-       private void registerToadlet(FredPlugin pl){
+       private void registerToadlet(FredPlugin pl) {
                //toadletList.put(e.getStackTrace()[1].getClass().toString(), 
pl);
-               synchronized (toadletList) {
+               synchronized(toadletList) {
                        toadletList.put(pl.getClass().getName(), pl);
                }
-               Logger.normal(this, "Added HTTP handler for 
/plugins/"+pl.getClass().getName()+ '/');
+               Logger.normal(this, "Added HTTP handler for /plugins/" + 
pl.getClass().getName() + '/');
        }

        /**
         * Remove a plugin from the plugin list.
         */
        public void removePlugin(PluginInfoWrapper pi) {
-               synchronized (pluginWrappers) {
-                       if(!pluginWrappers.remove(pi)) return;
+               synchronized(pluginWrappers) {
+                       if(!pluginWrappers.remove(pi))
+                               return;
                }
                core.storeConfig();
        }
@@ -340,79 +326,77 @@
        public void removeCachedCopy(String pluginSpecification) {
                int lastSlash = pluginSpecification.lastIndexOf('/');
                File pluginFile;
-               if (lastSlash == -1) {
+               if(lastSlash == -1)
                        /* Windows, maybe? */
                        lastSlash = pluginSpecification.lastIndexOf('\\');
-               }
                File pluginDirectory = new File(node.getNodeDir(), "plugins");
-               if (lastSlash == -1) {
+               if(lastSlash == -1)
                        /* it's an official plugin! */
                        pluginFile = new File(pluginDirectory, 
pluginSpecification + ".jar");
-               } else {
+               else
                        pluginFile = new File(pluginDirectory, 
pluginSpecification.substring(lastSlash + 1));
-               }
-               if(logDEBUG) Logger.minor(this, "Delete plugin - plugname: " + 
pluginSpecification + "filename: " + pluginFile.getAbsolutePath() , new 
Exception("debug"));
-               if (pluginFile.exists()) {
+               if(logDEBUG)
+                       Logger.minor(this, "Delete plugin - plugname: " + 
pluginSpecification + "filename: " + pluginFile.getAbsolutePath(), new 
Exception("debug"));
+               if(pluginFile.exists())
                        pluginFile.delete();
-               }
        }

        public void unregisterPluginToadlet(PluginInfoWrapper pi) {
-               synchronized (toadletList) {
+               synchronized(toadletList) {
                        try {
                                toadletList.remove(pi.getPluginClassName());
-                               Logger.normal(this, "Removed HTTP handler for 
/plugins/"+
-                                               pi.getPluginClassName()+ '/', 
new Exception("debug"));
-                       } catch (Throwable ex) {
+                               Logger.normal(this, "Removed HTTP handler for 
/plugins/" +
+                                       pi.getPluginClassName() + '/', new 
Exception("debug"));
+                       } catch(Throwable ex) {
                                Logger.error(this, "removing Plugin", ex);
                        }
                }
        }

        public void addToadletSymlinks(PluginInfoWrapper pi) {
-               synchronized (toadletList) {
+               synchronized(toadletList) {
                        try {
                                String targets[] = 
pi.getPluginToadletSymlinks();
-                               if (targets == null)
+                               if(targets == null)
                                        return;

-                               for (int i = 0 ; i < targets.length ; i++) {
+                               for(int i = 0; i < targets.length; i++) {
                                        toadletList.remove(targets[i]);
                                        Logger.normal(this, "Removed HTTP 
symlink: " + targets[i] +
-                                                       " => 
/plugins/"+pi.getPluginClassName()+ '/');
+                                               " => /plugins/" + 
pi.getPluginClassName() + '/');
                                }
-                       } catch (Throwable ex) {
+                       } catch(Throwable ex) {
                                Logger.error(this, "removing Toadlet-link", ex);
                        }
                }
        }

        public void removeToadletSymlinks(PluginInfoWrapper pi) {
-               synchronized (toadletList) {
+               synchronized(toadletList) {
                        String rm = null;
                        try {
                                String targets[] = 
pi.getPluginToadletSymlinks();
-                               if (targets == null)
+                               if(targets == null)
                                        return;

-                               for (int i = 0 ; i < targets.length ; i++) {
+                               for(int i = 0; i < targets.length; i++) {
                                        rm = targets[i];
                                        toadletList.remove(targets[i]);
                                        
pi.removePluginToadletSymlink(targets[i]);
                                        Logger.normal(this, "Removed HTTP 
symlink: " + targets[i] +
-                                                       " => 
/plugins/"+pi.getPluginClassName()+ '/');
+                                               " => /plugins/" + 
pi.getPluginClassName() + '/');
                                }
-                       } catch (Throwable ex) {
+                       } catch(Throwable ex) {
                                Logger.error(this, "removing Toadlet-link: " + 
rm, ex);
                        }
                }
        }

        public String dumpPlugins() {
-               StringBuffer out= new StringBuffer();
-               synchronized (pluginWrappers) {
-                       for(int i=0;i<pluginWrappers.size();i++) {
-                               PluginInfoWrapper pi = (PluginInfoWrapper) 
pluginWrappers.get(i);
+               StringBuffer out = new StringBuffer();
+               synchronized(pluginWrappers) {
+                       for(int i = 0; i < pluginWrappers.size(); i++) {
+                               PluginInfoWrapper pi = pluginWrappers.get(i);
                                out.append(pi.toString());
                                out.append('\n');
                        }
@@ -422,57 +406,57 @@

        public Set getPlugins() {
                HashSet out = new HashSet();
-               synchronized (pluginWrappers) {
-                       for(int i=0;i<pluginWrappers.size();i++) {
-                               PluginInfoWrapper pi = (PluginInfoWrapper) 
pluginWrappers.get(i);
+               synchronized(pluginWrappers) {
+                       for(int i = 0; i < pluginWrappers.size(); i++) {
+                               PluginInfoWrapper pi = pluginWrappers.get(i);
                                out.add(pi);
                        }
                }
                return out;
        }
-       
+
        /**
         * look for PluginInfo for a FCPPlugin with given classname
         * @param plugname
         * @return the PluginInfo or null if not found
         */
        public PluginInfoWrapper getFCPPluginInfo(String plugname) {
-               synchronized (pluginWrappers) {
-                       for(int i=0;i<pluginWrappers.size();i++) {
-                               PluginInfoWrapper pi = (PluginInfoWrapper) 
pluginWrappers.get(i);
-                               if (pi.getPluginClassName().equals(plugname))
+               synchronized(pluginWrappers) {
+                       for(int i = 0; i < pluginWrappers.size(); i++) {
+                               PluginInfoWrapper pi = pluginWrappers.get(i);
+                               if(pi.getPluginClassName().equals(plugname))
                                        return pi;
                        }
                }
                return null;
        }
-       
+
        /**
         * look for a FCPPlugin with given classname
         * @param plugname
         * @return the plugin or null if not found
         */
        public FredPluginFCP getFCPPlugin(String plugname) {
-               synchronized (pluginWrappers) {
-                       for(int i=0;i<pluginWrappers.size();i++) {
-                               PluginInfoWrapper pi = (PluginInfoWrapper) 
pluginWrappers.get(i);
-                               if (pi.isFCPPlugin() && 
pi.getPluginClassName().equals(plugname))
+               synchronized(pluginWrappers) {
+                       for(int i = 0; i < pluginWrappers.size(); i++) {
+                               PluginInfoWrapper pi = pluginWrappers.get(i);
+                               if(pi.isFCPPlugin() && 
pi.getPluginClassName().equals(plugname))
                                        return (FredPluginFCP) pi.plug;
                        }
                }
                return null;
        }
-       
+
        /**
         * look for a Plugin with given classname
         * @param plugname
         * @return the true if not found
         */
        public boolean isPluginLoaded(String plugname) {
-               synchronized (pluginWrappers) {
-                       for(int i=0;i<pluginWrappers.size();i++) {
-                               PluginInfoWrapper pi = (PluginInfoWrapper) 
pluginWrappers.get(i);
-                               if (pi.getPluginClassName().equals(plugname))
+               synchronized(pluginWrappers) {
+                       for(int i = 0; i < pluginWrappers.size(); i++) {
+                               PluginInfoWrapper pi = pluginWrappers.get(i);
+                               if(pi.getPluginClassName().equals(plugname))
                                        return true;
                        }
                }
@@ -481,30 +465,30 @@

        public String handleHTTPGet(String plugin, HTTPRequest request) throws 
PluginHTTPException {
                FredPlugin handler = null;
-               synchronized (toadletList) {
-                       handler = (FredPlugin)toadletList.get(plugin);
+               synchronized(toadletList) {
+                       handler = (FredPlugin) toadletList.get(plugin);
                }
                /*if (handler == null)
-                 return null;
+               return null;
                 */

-               if (handler instanceof FredPluginHTTP)
-                       return ((FredPluginHTTP)handler).handleHTTPGet(request);
+               if(handler instanceof FredPluginHTTP)
+                       return ((FredPluginHTTP) 
handler).handleHTTPGet(request);

                throw new NotFoundPluginHTTPException("Plugin not found!", 
"/plugins");
        }

        public String handleHTTPPost(String plugin, HTTPRequest request) throws 
PluginHTTPException {
                FredPlugin handler = null;
-               synchronized (toadletList) {
-                       handler = (FredPlugin)toadletList.get(plugin);
+               synchronized(toadletList) {
+                       handler = (FredPlugin) toadletList.get(plugin);
                }
                /*if (handler == null)
-                 return null;
+               return null;
                 */

-               if (handler instanceof FredPluginHTTP)
-                       return 
((FredPluginHTTP)handler).handleHTTPPost(request);
+               if(handler instanceof FredPluginHTTP)
+                       return ((FredPluginHTTP) 
handler).handleHTTPPost(request);

                throw new NotFoundPluginHTTPException("Plugin not found!", 
"/plugins");
        }
@@ -512,36 +496,33 @@
        public void killPlugin(String name, int maxWaitTime) {
                PluginInfoWrapper pi = null;
                boolean found = false;
-               synchronized (pluginWrappers) {
-                       for(int i=0;i<pluginWrappers.size() && !found;i++) {
-                               pi = (PluginInfoWrapper) pluginWrappers.get(i);
-                               if (pi.getThreadName().equals(name)) {
+               synchronized(pluginWrappers) {
+                       for(int i = 0; i < pluginWrappers.size() && !found; 
i++) {
+                               pi = pluginWrappers.get(i);
+                               if(pi.getThreadName().equals(name)) {
                                        found = true;
                                        break;
                                }
                        }
                }
-               if (found) {
+               if(found)
                        pi.stopPlugin(this, maxWaitTime);
-               }
        }

        public void killPlugin(FredPlugin plugin, int maxWaitTime) {
                PluginInfoWrapper pi = null;
                boolean found = false;
-               synchronized (pluginWrappers) {
-                       for(int i=0;i<pluginWrappers.size() && !found;i++) {
-                               pi = (PluginInfoWrapper) pluginWrappers.get(i);
-                               if (pi.plug == plugin) {
+               synchronized(pluginWrappers) {
+                       for(int i = 0; i < pluginWrappers.size() && !found; 
i++) {
+                               pi = pluginWrappers.get(i);
+                               if(pi.plug == plugin)
                                        found = true;
-                               }
                        }
                }
-               if (found) {
+               if(found)
                        pi.stopPlugin(this, maxWaitTime);
-               }
        }
-       
+
        /**
         * Returns a list of the names of all available official plugins. Right 
now
         * this list is hardcoded but in future we could retrieve this list 
from emu
@@ -550,7 +531,7 @@
         * @return A list of all available plugin names
         */
        public List<String> findAvailablePlugins() {
-               List<String> availablePlugins = new ArrayList<String> ();
+               List<String> availablePlugins = new ArrayList<String>();
                availablePlugins.add("Echo");
                availablePlugins.add("Freemail");
                availablePlugins.add("HelloWorld");
@@ -566,12 +547,14 @@
                availablePlugins.add("XMLSpider");
                return availablePlugins;
        }
-       
+
        public boolean isOfficialPlugin(String name) {
-               if ((name == null) || (name.trim().length() == 0)) return false;
+               if((name == null) || (name.trim().length() == 0))
+                       return false;
                List<String> availablePlugins = findAvailablePlugins();
-               for(String n:availablePlugins) {
-                       if (n.equals(name)) return true;                        
+               for(String n : availablePlugins) {
+                       if(n.equals(name))
+                               return true;
                }
                return false;
        }
@@ -592,12 +575,12 @@
         *             If anything goes wrong.
         */
        private FredPlugin loadPlugin(PluginDownLoader pdl, String name) throws 
PluginNotFoundException {
-               
+
                pdl.setSource(name);
-               
+
                /* check for plugin directory. */
                File pluginDirectory = new File(node.getNodeDir(), "plugins");
-               if ((pluginDirectory.exists() && 
!pluginDirectory.isDirectory()) || (!pluginDirectory.exists() && 
!pluginDirectory.mkdirs())) {
+               if((pluginDirectory.exists() && !pluginDirectory.isDirectory()) 
|| (!pluginDirectory.exists() && !pluginDirectory.mkdirs())) {
                        Logger.error(this, "could not create plugin directory");
                        throw new PluginNotFoundException("could not create 
plugin directory");
                }
@@ -607,12 +590,11 @@
                File pluginFile = new File(pluginDirectory, filename);

                /* check if file needs to be downloaded. */
-               if (logMINOR) {
+               if(logMINOR)
                        Logger.minor(this, "plugin file " + 
pluginFile.getAbsolutePath() + " exists: " + pluginFile.exists());
-               }
                int RETRIES = 5;
-               for(int i=0;i<RETRIES;i++) {
-                       if (!pluginFile.exists() || pluginFile.length() == 0) {
+               for(int i = 0; i < RETRIES; i++) {
+                       if(!pluginFile.exists() || pluginFile.length() == 0)
                                try {
                                        File tempPluginFile = null;
                                        OutputStream pluginOutputStream = null;
@@ -620,13 +602,13 @@
                                        try {
                                                tempPluginFile = 
File.createTempFile("plugin-", ".jar", pluginDirectory);
                                                tempPluginFile.deleteOnExit();
-                                               
-                                               
+
+
                                                pluginOutputStream = new 
FileOutputStream(tempPluginFile);
                                                pluginInputStream = 
pdl.getInputStream();
                                                byte[] buffer = new byte[1024];
                                                int read;
-                                               while ((read = 
pluginInputStream.read(buffer)) != -1) {
+                                               while((read = 
pluginInputStream.read(buffer)) != -1) {
                                                        
pluginOutputStream.write(buffer, 0, read);
                                                }
                                                pluginOutputStream.close();
@@ -636,33 +618,32 @@
                                                        Logger.error(this, 
"could not rename temp file to plugin file");
                                                        throw new 
PluginNotFoundException("could not rename temp file to plugin file");
                                                }
-                                               
+
                                                String digest = 
pdl.getSHA1sum();
-                                               if (digest != null) {
+                                               if(digest != null) {
                                                        String testsum = 
getFileSHA1(pluginFile);
-                                                       if 
(!(digest.equalsIgnoreCase(testsum))) {
-                                                               
Logger.error(this, "Checksum verification failed, should be " +digest+ " but 
was " + testsum);
-                                                               throw new 
PluginNotFoundException("Checksum verification failed, should be " +digest+ " 
but was " + testsum);
+                                                       
if(!(digest.equalsIgnoreCase(testsum))) {
+                                                               
Logger.error(this, "Checksum verification failed, should be " + digest + " but 
was " + testsum);
+                                                               throw new 
PluginNotFoundException("Checksum verification failed, should be " + digest + " 
but was " + testsum);
                                                        }
                                                }
-                                               
-                                       } catch (IOException ioe1) {
+
+                                       } catch(IOException ioe1) {
                                                Logger.error(this, "could not 
load plugin", ioe1);
-                                               if (tempPluginFile != null) {
+                                               if(tempPluginFile != null)
                                                        tempPluginFile.delete();
-                                               }
                                                throw new 
PluginNotFoundException("could not load plugin: " + ioe1.getMessage(), ioe1);
                                        } finally {
                                                
Closer.close(pluginOutputStream);
                                                Closer.close(pluginInputStream);
                                        }
-                               } catch (PluginNotFoundException e) {
-                                       if(i < RETRIES-1) {
-                                               Logger.normal(this, "Failed to 
load plugin: "+e, e);
+                               } catch(PluginNotFoundException e) {
+                                       if(i < RETRIES - 1) {
+                                               Logger.normal(this, "Failed to 
load plugin: " + e, e);
                                                continue;
-                                       } else throw e;
+                                       } else
+                                               throw e;
                                }
-                       }
                }

                /* now get the manifest file. */
@@ -671,32 +652,32 @@
                try {
                        pluginJarFile = new JarFile(pluginFile);
                        Manifest manifest = pluginJarFile.getManifest();
-                       if (manifest == null) {
+                       if(manifest == null) {
                                Logger.error(this, "could not load manifest 
from plugin file");
                                pluginFile.delete();
                                throw new PluginNotFoundException("could not 
load manifest from plugin file");
                        }
                        Attributes mainAttributes = 
manifest.getMainAttributes();
-                       if (mainAttributes == null) {
+                       if(mainAttributes == null) {
                                Logger.error(this, "manifest does not contain 
attributes");
                                pluginFile.delete();
                                throw new PluginNotFoundException("manifest 
does not contain attributes");
                        }
                        pluginMainClassName = 
mainAttributes.getValue("Plugin-Main-Class");
-                       if (pluginMainClassName == null) {
+                       if(pluginMainClassName == null) {
                                Logger.error(this, "manifest does not contain a 
Plugin-Main-Class attribute");
                                pluginFile.delete();
                                throw new PluginNotFoundException("manifest 
does not contain a Plugin-Main-Class attribute");
                        }
-               } catch (JarException je1) {
+               } catch(JarException je1) {
                        Logger.error(this, "could not process jar file", je1);
                        pluginFile.delete();
                        throw new PluginNotFoundException("could not process 
jar file", je1);
-               } catch (ZipException ze1) {
+               } catch(ZipException ze1) {
                        Logger.error(this, "could not process jar file", ze1);
                        pluginFile.delete();
                        throw new PluginNotFoundException("could not process 
jar file", ze1);
-               } catch (IOException ioe1) {
+               } catch(IOException ioe1) {
                        Logger.error(this, "error processing jar file", ioe1);
                        pluginFile.delete();
                        throw new PluginNotFoundException("error procesesing 
jar file", ioe1);
@@ -708,36 +689,36 @@
                        JarClassLoader jarClassLoader = new 
JarClassLoader(pluginFile);
                        Class pluginMainClass = 
jarClassLoader.loadClass(pluginMainClassName);
                        Object object = pluginMainClass.newInstance();
-                       if (!(object instanceof FredPlugin)) {
+                       if(!(object instanceof FredPlugin)) {
                                Logger.error(this, "plugin main class is not a 
plugin");
                                pluginFile.delete();
                                throw new PluginNotFoundException("plugin main 
class is not a plugin");
                        }
                        return (FredPlugin) object;
-               } catch (IOException ioe1) {
+               } catch(IOException ioe1) {
                        Logger.error(this, "could not load plugin", ioe1);
                        pluginFile.delete();
                        throw new PluginNotFoundException("could not load 
plugin", ioe1);
-               } catch (ClassNotFoundException cnfe1) {
+               } catch(ClassNotFoundException cnfe1) {
                        Logger.error(this, "could not find plugin class", 
cnfe1);
                        pluginFile.delete();
                        throw new PluginNotFoundException("could not find 
plugin class", cnfe1);
-               } catch (InstantiationException ie1) {
+               } catch(InstantiationException ie1) {
                        Logger.error(this, "could not instantiate plugin", ie1);
                        pluginFile.delete();
                        throw new PluginNotFoundException("could not 
instantiate plugin", ie1);
-               } catch (IllegalAccessException iae1) {
+               } catch(IllegalAccessException iae1) {
                        Logger.error(this, "could not access plugin main 
class", iae1);
                        pluginFile.delete();
                        throw new PluginNotFoundException("could not access 
plugin main class", iae1);
-               } catch (NoClassDefFoundError ncdfe1) {
+               } catch(NoClassDefFoundError ncdfe1) {
                        Logger.error(this, "could not find class def, may a 
missing lib?", ncdfe1);
                        pluginFile.delete();
                        throw new PluginNotFoundException("could not find class 
def, may a missing lib?", ncdfe1);
-               } catch (Throwable t) {
+               } catch(Throwable t) {
                        Logger.error(this, "unexcpected error while plugin 
loading", t);
                        pluginFile.delete();
-                       throw new PluginNotFoundException("unexcpected error 
while plugin loading "+t, t);
+                       throw new PluginNotFoundException("unexcpected error 
while plugin loading " + t, t);
                }
        }

@@ -746,7 +727,7 @@
                MessageDigest hash = null;
                FileInputStream fis = null;
                BufferedInputStream bis = null;
-               
+
                try {
                        hash = MessageDigest.getInstance("SHA-1");
                        // We compute the hash
@@ -757,9 +738,9 @@
                        byte[] buffer = new byte[BUFFERSIZE];
                        while((len = bis.read(buffer)) > -1) {
                                hash.update(buffer, 0, len);
-                       }       
-               } catch (Exception e) {
-                       throw new PluginNotFoundException("Error while 
computing sha1 hash of the downloaded plugin: "+e, e);
+                       }
+               } catch(Exception e) {
+                       throw new PluginNotFoundException("Error while 
computing sha1 hash of the downloaded plugin: " + e, e);
                } finally {
                        Closer.close(bis);
                        Closer.close(fis);
@@ -781,16 +762,12 @@

                /** State for downloading. */
                public static final PluginProgress DOWNLOADING = new 
PluginProgress();
-
                /** State for starting. */
                public static final PluginProgress STARTING = new 
PluginProgress();
-
                /** The starting time. */
                private long startingTime = System.currentTimeMillis();
-
                /** The current state. */
                private PluginProgress pluginProgress;
-
                /** The name by which the plugin is loaded. */
                private String name;

@@ -859,16 +836,13 @@
                 * 
                 * @return The name of a constant, or the plugin progress
                 */
-               /* @Override */
+               @Override
                public String toString() {
-                       if (this == DOWNLOADING) {
+                       if(this == DOWNLOADING)
                                return "downloading";
-                       } else if (this == STARTING) {
+                       else if(this == STARTING)
                                return "starting";
-                       }
                        return "PluginProgress[name=" + name + ",startingTime=" 
+ startingTime + ",progress=" + pluginProgress + "]";
                }
-
        }
-
 }

Modified: branches/db4o/freenet/src/freenet/store/RAMFreenetStore.java
===================================================================
--- branches/db4o/freenet/src/freenet/store/RAMFreenetStore.java        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/store/RAMFreenetStore.java        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -17,7 +17,7 @@
                byte[] fullKey;
        }

-       private final LRUHashtable blocksByRoutingKey;
+       private final LRUHashtable<ByteArrayWrapper, Block> blocksByRoutingKey;

        private final StoreCallback callback;

@@ -29,7 +29,7 @@

        public RAMFreenetStore(StoreCallback callback, int maxKeys) {
                this.callback = callback;
-               this.blocksByRoutingKey = new LRUHashtable();
+               this.blocksByRoutingKey = new LRUHashtable<ByteArrayWrapper, 
Block>();
                this.maxKeys = maxKeys;
                callback.setStore(this);
        }
@@ -37,7 +37,7 @@
        public synchronized StorableBlock fetch(byte[] routingKey, byte[] 
fullKey,
                        boolean dontPromote) throws IOException {
                ByteArrayWrapper key = new ByteArrayWrapper(routingKey);
-               Block block = (Block) blocksByRoutingKey.get(key);
+               Block block = blocksByRoutingKey.get(key);
                if(block == null) {
                        misses++;
                        return null;
@@ -77,7 +77,7 @@
                        KeyCollisionException {
                writes++;
                ByteArrayWrapper key = new ByteArrayWrapper(routingkey);
-               Block oldBlock = (Block) blocksByRoutingKey.get(key);
+               Block oldBlock = blocksByRoutingKey.get(key);
                boolean storeFullKeys = callback.storeFullKeys();
                if(oldBlock != null) {
                        if(callback.collisionPossible()) {

Modified: branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java     
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java     
2008-09-24 20:42:20 UTC (rev 22823)
@@ -6,36 +6,36 @@
  * Framework for managing a doubly linked list.
  * @author tavin
  */
-public interface DoublyLinkedList {
-    public abstract Object clone();
+public interface DoublyLinkedList<T> {
+    public abstract DoublyLinkedList<T> clone();

     /**
      * List element
      */
-    public interface Item {
+    public interface Item<T> {
                /**
                 * Get next {@link Item}. May or may not return
                 * <code>null</code> if this is the last <code>Item</code>.
                 * 
                 * @see DoublyLinkedList#hasNext()
                 */
-        Item getNext();
+        DoublyLinkedList.Item<T> getNext();
         /** Set next {@link Item} */
-        Item setNext(Item i);
+        DoublyLinkedList.Item<T> setNext(DoublyLinkedList.Item<T> i);
         /**
         * Get previous {@link Item}. May or may not return <code>null</code>
         * if this is the first <code>Item</code>.
         * 
         * @see DoublyLinkedList#hasNext()
         */
-        Item getPrev();
+        Item<T> getPrev();
         /** Get previous {@link Item} */
-        Item setPrev(Item i);
+        Item<T> setPrev(DoublyLinkedList.Item<T> i);

         /** Return the contained list. <strong>For sanity checking 
only.</strong> */
-        DoublyLinkedList getParent();
+        DoublyLinkedList<T> getParent();
         /** Set the contained list. <strong>For sanity checking 
only.</strong>*/
-        DoublyLinkedList setParent(DoublyLinkedList l);
+        DoublyLinkedList<T> setParent(DoublyLinkedList<T> l);
     }

     /** Clear this list */
@@ -61,11 +61,11 @@
     /**
      * Puts the item before the first item.
      */
-    void unshift(Item i);
+    void unshift(DoublyLinkedList.Item<T> i);
     /**
      * Put all items in the specified list before the first item.
      */
-    void unshift(DoublyLinkedList l);
+    void unshift(DoublyLinkedList<T> l);
     /**
      * Removes and returns the first item.
      */
@@ -73,16 +73,16 @@
     /**
      * Remove <tt>n</tt> elements from head and return them as a 
<code>DoublyLinkedList</code>.
      */
-    DoublyLinkedList shift(int n);
+    DoublyLinkedList<T> shift(int n);

     /**
      * Puts the item after the last item.
      */
-    void push(Item i);
+    void push(DoublyLinkedList.Item<T> i);
     /**
      * Puts all items in the specified list after the last item.
      */
-    void push(DoublyLinkedList l);
+    void push(DoublyLinkedList<T> l);
     /**
      * Removes and returns the last item.
      */
@@ -93,34 +93,34 @@
     DoublyLinkedList pop(int n);

     /** @return <code>true</code> if <code>i</code> has next item. (ie. not 
the last item); <code>false</code> otherwise */ 
-    boolean hasNext(Item i);
+    boolean hasNext(DoublyLinkedList.Item<T> i);
     /** @return <code>true</code> if <code>i</code> has previous item. (ie. 
not the first item); <code>false</code> otherwise */
-    boolean hasPrev(Item i);
+    boolean hasPrev(DoublyLinkedList.Item<T> i);

     /** @return next item of <code>i</code>. If this is the last element, 
return <code>null</code> */
-    Item next(Item i);
+    Item next(DoublyLinkedList.Item<T> i);
     /** @return previous item of <code>i</code>. If this is the first element, 
return <code>null</code> */
-    Item prev(Item i);
+    Item prev(DoublyLinkedList.Item<T> i);
     /** Remove and return a element 
      * @return  this item, or <code>null</code> if the item was not in the list
      */
-    Item remove(Item i);
+    Item remove(DoublyLinkedList.Item<T> i);
     /**
      * Inserts item <code>j</code> before item <code>i</code>.
      */
-    void insertPrev(Item i, Item j);
+    void insertPrev(DoublyLinkedList.Item<T> i, DoublyLinkedList.Item<T> j);
     /**
      * Inserts the entire {@link DoublyLinkedList} <code>l</code> before item 
<code>i</code>.
      */
-    void insertPrev(Item i, DoublyLinkedList l);  
+    void insertPrev(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l);  
     /**
      * Inserts item <code>j</code> after item <code>i</code.
      */
-    void insertNext(Item i, Item j);    
+    void insertNext(DoublyLinkedList.Item<T> i, DoublyLinkedList.Item<T> j);   
 
     /**
      * Inserts the entire {@link DoublyLinkedList} <code>l</code> after item 
<code>i</code>.
      */
-    void insertNext(Item i, DoublyLinkedList l);
+    void insertNext(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l);
 }



Modified: branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java 
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java 
2008-09-24 20:42:20 UTC (rev 22823)
@@ -10,27 +10,28 @@
  * TODO: there are still some unimplemented methods
  *       -- it remains to be seen if they are needed at all
  */
-public class DoublyLinkedListImpl implements DoublyLinkedList {
+public class DoublyLinkedListImpl<T> implements DoublyLinkedList<T>{

     protected int size;
-    protected Item _headptr, _tailptr;
+    protected DoublyLinkedListImpl.Item<T> _headptr, _tailptr;

-    public final Object clone() {
-        return new DoublyLinkedListImpl(this);
+       @Override
+    public final DoublyLinkedListImpl<T> clone() {
+        return new DoublyLinkedListImpl<T>(this);
     }

     /**
      * A new list with no items.
      */
     public DoublyLinkedListImpl() {
-        _headptr = new Item();
-        _tailptr = new Item();
+        _headptr = new Item<T>();
+        _tailptr = new Item<T>();
         _headptr.setParent(this);
         _tailptr.setParent(this);
         clear();
     }

-    protected DoublyLinkedListImpl(Item _h, Item _t, int size) {
+    protected DoublyLinkedListImpl(DoublyLinkedListImpl.Item<T> _h, 
DoublyLinkedListImpl.Item<T> _t, int size) {
         _headptr  = _h;
         _tailptr  = _t;
         _headptr.setParent(this);
@@ -44,11 +45,11 @@
      */
     protected DoublyLinkedListImpl(DoublyLinkedListImpl impl) {
         this();
-        Enumeration e = impl.forwardElements();
+        Enumeration<DoublyLinkedListImpl.Item<T>> e = impl.forwardElements();
         boolean checked = false;
         for(;e.hasMoreElements();) {
-            Item oi = (Item)e.nextElement();
-            Item i = (Item) oi.clone();
+            DoublyLinkedListImpl.Item<T> oi = e.nextElement();
+            DoublyLinkedList.Item<T> i = oi.clone();
             if(!checked) {
                 checked = true;
                 if(!i.getClass().getName().equals(oi.getClass().getName())) {
@@ -69,8 +70,8 @@
        // Help to detect removal after clear().
        // The check in remove() is enough, strictly,
        // as long as people don't add elements afterwards.
-       DoublyLinkedList.Item pos = _headptr.next;
-       DoublyLinkedList.Item opos = _headptr;
+       DoublyLinkedList.Item<T> pos = _headptr.next;
+       DoublyLinkedList.Item<T> opos = _headptr;
        while(true) {
                if(pos == _tailptr) break;
                if(pos == null) break;
@@ -103,21 +104,21 @@
      * {@inheritDoc}
      * @see #forwardElements()
      */
-    public final Enumeration elements() {
+    public final Enumeration<DoublyLinkedList.Item<T>> elements() {
         return forwardElements();
     }

     /**
      * {@inheritDoc}
      */
-    public final DoublyLinkedList.Item head() {
+    public final DoublyLinkedList.Item<T> head() {
         return size == 0 ? null : _headptr.next;
     }

     /**
      * {@inheritDoc}
      */
-    public final DoublyLinkedList.Item tail() {
+    public final DoublyLinkedList.Item<T> tail() {
         return size == 0 ? null : _tailptr.prev;
     }

@@ -126,7 +127,7 @@
     /**
      * {@inheritDoc}
      */
-    public final void unshift(DoublyLinkedList.Item i) {
+    public final void unshift(DoublyLinkedList.Item<T> i) {
         insertNext(_headptr, i);
     }

@@ -134,30 +135,30 @@
      * {@inheritDoc}
      *  FIXME: unimplemented
      */
-    public void unshift(DoublyLinkedList l) {
+    public void unshift(DoublyLinkedList<T> l) {
         throw new RuntimeException("function currently unimplemented because i 
am a lazy sod");
     }
     /**
      * {@inheritDoc}
      */
-    public final DoublyLinkedList.Item shift() {
+    public final DoublyLinkedList.Item<T> shift() {
         return size == 0 ? null : remove(_headptr.next);
     }
     /**
      * {@inheritDoc}
      */
-    public DoublyLinkedList shift(int n) {
+    public DoublyLinkedList<T> shift(int n) {

         if (n > size) n = size;
-        if (n < 1) return new DoublyLinkedListImpl();
+        if (n < 1) return new DoublyLinkedListImpl<T>();

-        DoublyLinkedList.Item i = _headptr;
+        DoublyLinkedList.Item<T> i = _headptr;
         for (int m=0; m<n; ++m)
             i = i.getNext();

-        DoublyLinkedList.Item j = i.getNext();
-        Item newheadptr = new Item();
-        Item newtailptr = new Item();
+        DoublyLinkedList.Item<T> j = i.getNext();
+        Item<T> newheadptr = new Item<T>();
+        Item<T> newtailptr = new Item<T>();

         j.setPrev(newheadptr);
         newheadptr.setNext(j);
@@ -165,7 +166,7 @@
         i.setNext(newtailptr);
         newtailptr.setPrev(i);

-        DoublyLinkedList newlist = new DoublyLinkedListImpl(_headptr, 
newtailptr, n);
+        DoublyLinkedList<T> newlist = new DoublyLinkedListImpl<T>(_headptr, 
newtailptr, n);
         _headptr = newheadptr;
         _headptr.setParent(this);
         size -= n;
@@ -178,37 +179,37 @@
     /**
      * {@inheritDoc}
      */
-    public final void push(DoublyLinkedList.Item i) {
+    public final void push(DoublyLinkedList.Item<T> i) {
         insertPrev(_tailptr, i);
     }
     /**
      * {@inheritDoc}
      * FIXME: unimplemented
      */
-    public void push(DoublyLinkedList l) {
+    public void push(DoublyLinkedList<T> l) {
         throw new RuntimeException("function currently unimplemented because i 
am a lazy sod");
     }
     /**
      * {@inheritDoc}
      */
-    public final DoublyLinkedList.Item pop() {
+    public final DoublyLinkedList.Item<T> pop() {
         return size == 0 ? null : remove(_tailptr.prev);
     }
     /**
      * {@inheritDoc}
      */
-    public DoublyLinkedList pop(int n) {
+    public DoublyLinkedList<T> pop(int n) {

         if (n > size) n = size;
-        if (n < 1) return new DoublyLinkedListImpl();
+        if (n < 1) return new DoublyLinkedListImpl<T>();

-        DoublyLinkedList.Item i = _tailptr;
+        DoublyLinkedList.Item<T> i = _tailptr;
         for (int m=0; m<n; ++m)
             i = i.getPrev();

-        DoublyLinkedList.Item j = i.getPrev();
-        Item newtailptr = new Item();
-        Item newheadptr = new Item();
+        DoublyLinkedList.Item<T> j = i.getPrev();
+        DoublyLinkedListImpl.Item<T> newtailptr = new Item<T>();
+        DoublyLinkedListImpl.Item<T> newheadptr = new Item<T>();

         j.setNext(newtailptr);
         newtailptr.setPrev(j);
@@ -217,7 +218,7 @@
         i.setPrev(newheadptr);
         newheadptr.setNext(i);

-        DoublyLinkedList newlist = new DoublyLinkedListImpl(newheadptr, 
_tailptr, n);
+        DoublyLinkedList<T> newlist = new DoublyLinkedListImpl<T>(newheadptr, 
_tailptr, n);
         _tailptr = newtailptr;
         size -= n;

@@ -229,29 +230,29 @@
     /**
      * {@inheritDoc}
      */
-    public final boolean hasNext(DoublyLinkedList.Item i) {
-        DoublyLinkedList.Item next = i.getNext();
+    public final boolean hasNext(DoublyLinkedList.Item<T> i) {
+        DoublyLinkedList.Item<T> next = i.getNext();
         return (next != null) && (next != _tailptr);
     }
     /**
      * {@inheritDoc}
      */
-    public final boolean hasPrev(DoublyLinkedList.Item i) {
-        DoublyLinkedList.Item prev = i.getPrev();
+    public final boolean hasPrev(DoublyLinkedList.Item<T> i) {
+        DoublyLinkedList.Item<T> prev = i.getPrev();
         return (prev != null) && (prev != _headptr);
     }
     /**
      * {@inheritDoc}
      */
-    public final DoublyLinkedList.Item next(DoublyLinkedList.Item i) {
-        DoublyLinkedList.Item next = i.getNext();
+    public final DoublyLinkedList.Item<T> next(DoublyLinkedList.Item<T> i) {
+        DoublyLinkedList.Item<T> next = i.getNext();
         return next == _tailptr ? null : next;
     }
     /**
      * {@inheritDoc}
      */
-    public final DoublyLinkedList.Item prev(DoublyLinkedList.Item i) {
-        DoublyLinkedList.Item prev = i.getPrev();
+    public final DoublyLinkedList.Item<T> prev(DoublyLinkedList.Item<T> i) {
+        DoublyLinkedList.Item<T> prev = i.getPrev();
         return prev == _headptr ? null : prev;
     }

@@ -261,7 +262,7 @@
     /**
      * {@inheritDoc}
      */
-    public DoublyLinkedList.Item remove(DoublyLinkedList.Item i) {
+    public DoublyLinkedList.Item<T> remove(DoublyLinkedList.Item<T> i) {
        if (i.getParent() == null) return null; // not in list
        if(isEmpty()) {
                Logger.error(this, "Illegal ERROR: Removing from an empty 
list!!");
@@ -269,7 +270,7 @@
        }
        if (i.getParent() != this)
                throw new PromiscuousItemException(i, i.getParent());
-        DoublyLinkedList.Item next = i.getNext(), prev = i.getPrev();
+        DoublyLinkedList.Item<T> next = i.getNext(), prev = i.getPrev();
         if ((next == null) && (prev == null)) return null;  // not in the list
         if ((next == null) || (prev == null))
                throw new NullPointerException("next="+next+", prev="+prev); // 
partially in the list?!
@@ -290,7 +291,7 @@
     /**
      * {@inheritDoc}
      */
-    public void insertPrev(DoublyLinkedList.Item i, DoublyLinkedList.Item j) {
+    public void insertPrev(DoublyLinkedList.Item<T> i, 
DoublyLinkedList.Item<T> j) {
        if (i.getParent() == null)
                throw new PromiscuousItemException(i, i.getParent()); // 
different trace to make easier debugging
        if (i.getParent() != this)
@@ -299,7 +300,7 @@
                throw new PromiscuousItemException(j, j.getParent());
         if ((j.getNext() != null) || (j.getPrev() != null))
             throw new PromiscuousItemException(j);
-        DoublyLinkedList.Item prev = i.getPrev();
+        DoublyLinkedList.Item<T> prev = i.getPrev();
         if (prev == null)
             throw new VirginItemException(i);
         prev.setNext(j);
@@ -314,14 +315,14 @@
      * {@inheritDoc}
      * FIXME: unimplemented
      */
-    public void insertPrev(DoublyLinkedList.Item i, DoublyLinkedList l) {
+    public void insertPrev(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l) {
         throw new RuntimeException("function currently unimplemented because i 
am a lazy sod");
     }

     /**
      * {@inheritDoc}
      */
-    public void insertNext(DoublyLinkedList.Item i, DoublyLinkedList.Item j) {
+    public void insertNext(DoublyLinkedList.Item<T> i, 
DoublyLinkedList.Item<T> j) {
        if (i.getParent() != this)
                throw new PromiscuousItemException(i, i.getParent());
        if (j.getParent() != null)
@@ -343,7 +344,7 @@
      * {@inheritDoc}
      * FIXME: unimplemented
      */
-    public void insertNext(DoublyLinkedList.Item i, DoublyLinkedList l) {
+    public void insertNext(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l) {
         throw new RuntimeException("function currently unimplemented because i 
am a lazy sod");
     }

@@ -353,54 +354,54 @@
     /**
      * @return  an Enumeration of list elements from head to tail
      */
-    private Enumeration forwardElements() {
+    private Enumeration<DoublyLinkedList.Item<T>> forwardElements() {
         return new ForwardWalker();
     }

     /**
      * @return  an Enumeration of list elements from tail to head
      */
-    protected Enumeration reverseElements() {
+    protected Enumeration<DoublyLinkedList.Item<T>> reverseElements() {
         return new ReverseWalker();
     }

-    private class ForwardWalker implements Enumeration {
-        protected DoublyLinkedList.Item next;
+    private class ForwardWalker<T extends DoublyLinkedListImpl.Item<T>> 
implements Enumeration<DoublyLinkedList.Item<T>> {
+        protected DoublyLinkedList.Item<T> next;
         protected ForwardWalker() {
             next = _headptr.getNext();
         }
-        protected ForwardWalker(DoublyLinkedList.Item startAt,
+        protected ForwardWalker(DoublyLinkedList.Item<T> startAt,
                                 boolean inclusive) {
             next = (inclusive ? startAt : startAt.getNext());
         }
         public final boolean hasMoreElements() {
             return next != _tailptr;
         }
-        public Object nextElement() {
+        public DoublyLinkedList.Item<T> nextElement() {
             if (next == _tailptr)
                 throw new NoSuchElementException();
-            DoublyLinkedList.Item result = next;
+            DoublyLinkedList.Item<T> result = next;
             next = next.getNext();
             return result;
         }
     }

-    private class ReverseWalker implements Enumeration {
-        protected DoublyLinkedList.Item next;
+    private class ReverseWalker<T extends DoublyLinkedList.Item<T>> implements 
Enumeration<DoublyLinkedList.Item<T>> {
+        protected DoublyLinkedList.Item<T> next;
         protected ReverseWalker() {
             next = _tailptr.getPrev();
         }
-        protected ReverseWalker(DoublyLinkedList.Item startAt,
+        protected ReverseWalker(DoublyLinkedList.Item<T> startAt,
                                 boolean inclusive) {
             next = (inclusive ? startAt : startAt.getPrev());
         }
         public final boolean hasMoreElements() {
             return next != _headptr;
         }
-        public Object nextElement() {
+        public DoublyLinkedList.Item<T> nextElement() {
             if (next == _headptr)
                 throw new NoSuchElementException();
-            DoublyLinkedList.Item result = next;
+            DoublyLinkedList.Item<T> result = next;
            if(next == null) throw new IllegalStateException("next==null");
             next = next.getPrev();
             return result;
@@ -410,35 +411,36 @@

     //=== list element ====================================================

-    public static class Item implements DoublyLinkedList.Item {
-        private DoublyLinkedList.Item prev;
-        private DoublyLinkedList.Item next;
+    public static class Item<T> implements DoublyLinkedList.Item<T> {
+        private DoublyLinkedList.Item<T> prev;
+        private DoublyLinkedList.Item<T> next;
         private DoublyLinkedList list;
-        public Object clone() {
+               @Override
+        public DoublyLinkedList.Item<T> clone() {
             if(getClass() != Item.class)
                 throw new RuntimeException("Must implement clone() for 
"+getClass());
-            return new Item();
+            return new Item<T>();
         }
         public final DoublyLinkedList.Item getNext() {
             return next;
         }
-        public final DoublyLinkedList.Item setNext(DoublyLinkedList.Item i) {
-            DoublyLinkedList.Item old = next;
+        public final DoublyLinkedList.Item setNext(DoublyLinkedList.Item<T> i) 
{
+            DoublyLinkedList.Item<T> old = next;
             next = i;
             return old;
         }
         public final DoublyLinkedList.Item getPrev() {
             return prev;
         }
-        public final DoublyLinkedList.Item setPrev(DoublyLinkedList.Item i) {
-            DoublyLinkedList.Item old = prev;
+        public final DoublyLinkedList.Item setPrev(DoublyLinkedList.Item<T> i) 
{
+            DoublyLinkedList.Item<T> old = prev;
             prev = i;
             return old;
         }
                public DoublyLinkedList getParent() {
                        return list;
                }
-               public DoublyLinkedList setParent(DoublyLinkedList l) {
+               public DoublyLinkedList setParent(DoublyLinkedList<T> l) {
                        DoublyLinkedList old = list;
                        list = l;
                        return old;

Modified: branches/db4o/freenet/src/freenet/support/Fields.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/Fields.java       2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/Fields.java       2008-09-24 
20:42:20 UTC (rev 22823)
@@ -60,6 +60,15 @@
                        'y',
                        'z' };

+       private static final long[] MULTIPLES = {
+               1000,                                           1l << 10,
+               1000 * 1000,                                    1l << 20,
+               1000l * 1000l * 1000l,                          1l << 30,
+               1000l * 1000l * 1000l * 1000l,                  1l << 40,
+               1000l * 1000l * 1000l * 1000l * 1000,           1l << 50,
+               1000l * 1000l * 1000l * 1000l * 1000l * 1000l,  1l << 60
+       };
+       
        /**
         * Converts a hex string into a long. Long.parseLong(hex, 16) assumes 
the
         * input is nonnegative unless there is a preceding minus sign. This 
method
@@ -597,23 +606,20 @@
        }

     /**
-     * Parse a human-readable string possibly including SI units into a short.
+     * Parse a human-readable string possibly including SI and ICE units into 
a short.
         * @throws NumberFormatException
         *             if the string is not parseable
         */
-       public static short parseSIShort(String s) throws NumberFormatException 
{
+       public static short parseShort(String s) throws NumberFormatException {
+               s = s.replaceFirst("(i)*B$", "");
                short res = 1;
                int x = s.length() - 1;
                int idx;
                try {
-                       long[] l =
-                               {
-                                       1000,
-                                       1 << 10 };
                        while ((x >= 0)
                                && ((idx = "kK".indexOf(s.charAt(x))) != -1)) {
                                x--;
-                               res *= l[idx];
+                               res *= MULTIPLES[idx];
                        }
                        res *= Double.parseDouble(s.substring(0, x + 1));
                } catch (ArithmeticException e) {
@@ -624,27 +630,20 @@
        }

        /**
-        * Parse a human-readable string possibly including SI units into an 
integer.
+        * Parse a human-readable string possibly including SI and ICE units 
into an integer.
         * @throws NumberFormatException
         *             if the string is not parseable
         */
-       public static int parseSIInt(String s) throws NumberFormatException {
+       public static int parseInt(String s) throws NumberFormatException {
+               s = s.replaceFirst("(i)*B$", "");
                int res = 1;
                int x = s.length() - 1;
                int idx;
                try {
-                       long[] l =
-                               {
-                                       1000,
-                                       1 << 10,
-                                       1000 * 1000,
-                                       1 << 20,
-                                       1000 * 1000 * 1000,
-                                       1 << 30 };
                        while ((x >= 0)
                                && ((idx = "kKmMgG".indexOf(s.charAt(x))) != 
-1)) {
                                x--;
-                               res *= l[idx];
+                               res *= MULTIPLES[idx];
                        }
                        res *= Double.parseDouble(s.substring(0, x + 1));
                } catch (ArithmeticException e) {
@@ -655,33 +654,20 @@
        }

        /**
-        * Parse a human-readable string possibly including SI units into a 
long.
+        * Parse a human-readable string possibly including SI and ICE units 
into a long.
         * @throws NumberFormatException
         *             if the string is not parseable
         */
-       public static long parseSILong(String s) throws NumberFormatException {
+       public static long parseLong(String s) throws NumberFormatException {
+               s = s.replaceFirst("(i)*B$", "");
                long res = 1;
                int x = s.length() - 1;
                int idx;
                try {
-                       long[] l =
-                               {
-                                       1000,
-                                       1 << 10,
-                                       1000 * 1000,
-                                       1 << 20,
-                                       1000l * 1000l * 1000l,
-                                       1l << 30,
-                                       1000l * 1000l * 1000l * 1000l,
-                                       1l << 40,
-                                       1000l * 1000l * 1000l * 1000l * 1000,
-                                       1l << 50,
-                                       1000l * 1000l * 1000l * 1000l * 1000l * 
1000l,
-                                       1l << 60 };
                        while ((x >= 0)
                                && ((idx = "kKmMgGtTpPeE".indexOf(s.charAt(x))) 
!= -1)) {
                                x--;
-                               res *= l[idx];
+                               res *= MULTIPLES[idx];
                        }
                        String multiplier = s.substring(0, x + 1).trim();
                        if(multiplier.indexOf('.') > -1 || 
multiplier.indexOf('E') > -1) {
@@ -698,6 +684,60 @@
                return res;
        }

+       public static String longToString(long val) {
+               String[] u = { "k", "K", "m", "M", "g", "G", "t", "T", "p", 
"P", "e", "E" };
+               String ret = Long.toString(val);
+
+               if (val <= 0)
+                       return ret;
+
+               for (int i = MULTIPLES.length - 1; i >= 0; i--) {
+                       if (val > MULTIPLES[i] && val % MULTIPLES[i] == 0) {
+                               ret = (val / MULTIPLES[i]) + u[i];
+                               if (!u[i].toLowerCase().equals(u[i]))
+                                       ret += "iB";
+                               break;
+                       }
+               }
+               return ret;
+       }
+
+       public static String intToString(int val) {
+               String[] u = { "k", "K", "m", "M", "g", "G", "t", "T", "p", 
"P", "e", "E" };
+               String ret = Integer.toString(val);
+
+               if (val <= 0)
+                       return ret;
+
+               for (int i = MULTIPLES.length - 1; i >= 0; i--) {
+                       if (val > MULTIPLES[i] && val % MULTIPLES[i] == 0) {
+                               ret = (val / MULTIPLES[i]) + u[i];
+                               if (!u[i].toLowerCase().equals(u[i]))
+                                       ret += "iB";
+                               break;
+                       }
+               }
+               return ret;
+       }
+
+       public static String shortToString(short val) {
+               String[] u = { "k", "K", "m", "M", "g", "G", "t", "T", "p", 
"P", "e", "E" };
+               String ret = Short.toString(val);
+
+               if (val <= 0)
+                       return ret;
+               
+               for (int i = MULTIPLES.length - 1; i >= 0; i--) {
+                       if (val > MULTIPLES[i] && val % MULTIPLES[i] == 0) {
+                               ret = (val / MULTIPLES[i]) + u[i];
+                               if (!u[i].toLowerCase().equals(u[i]))
+                                       ret += "iB";
+                               break;
+                       }
+               }
+               return ret;
+       }
+
        public static double[] bytesToDoubles(byte[] data, int offset, int 
length) {
                long[] longs = bytesToLongs(data, offset, length);
                double[] doubles = new double[longs.length];

Modified: branches/db4o/freenet/src/freenet/support/FileLoggerHook.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/FileLoggerHook.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/FileLoggerHook.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -1,6 +1,7 @@
 package freenet.support;

 import java.io.BufferedOutputStream;
+import java.io.Closeable;
 import java.io.DataInputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -32,7 +33,7 @@
  * 
  * @author oskar
  */
-public class FileLoggerHook extends LoggerHook {
+public class FileLoggerHook extends LoggerHook implements Closeable {

        /** Verbosity types */
        public static final int DATE = 1,

Modified: branches/db4o/freenet/src/freenet/support/HTMLEncoder.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/HTMLEncoder.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/HTMLEncoder.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -18,16 +18,16 @@

        public static String encode(String s) {
                int n = s.length();
-               StringBuffer sb = new StringBuffer(n);
+               StringBuilder sb = new StringBuilder(n);
                encodeToBuffer(n, s, sb);
                return sb.toString();
        }

-       public static void encodeToBuffer(String s, StringBuffer sb) {
+       public static void encodeToBuffer(String s, StringBuilder sb) {
                encodeToBuffer(s.length(), s, sb);
        }

-       private static void encodeToBuffer(int n, String s, StringBuffer sb) {
+       private static void encodeToBuffer(int n, String s, StringBuilder sb) {
                for (int i = 0; i < n; i++) {
                        char c = s.charAt(i);
                        if(Character.isLetterOrDigit(c)){ //only special 
characters need checking
@@ -48,7 +48,7 @@
                private String[] strings;
                private int modulo = 0;

-               public CharTable(HashMap map){
+               public CharTable(HashMap<Character, String> map){
                        int[] keys = new int[map.size()]; 
                        int keyIndex = 0;

@@ -84,7 +84,7 @@
                                character = ((Character)it.next());
                                keyIndex = character.charValue()%modulo;
                                chars[keyIndex] = character.charValue();
-                               strings[keyIndex] = (String) map.get(character);
+                               strings[keyIndex] = map.get(character);
                        }
                        if (chars[0] == 0 && strings[0] != null) chars[0] = 1;
                }

Modified: branches/db4o/freenet/src/freenet/support/HTMLNode.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/HTMLNode.java     2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/HTMLNode.java     2008-09-24 
20:42:20 UTC (rev 22823)
@@ -19,9 +19,9 @@

        private final String content;

-       private final Map attributes = new HashMap();
+       private final Map<String, String> attributes = new HashMap<String, 
String>();

-       protected final List children = new ArrayList();
+       protected final List<HTMLNode> children = new ArrayList<HTMLNode>();

        public HTMLNode(String name) {
                this(name, null);
@@ -61,7 +61,7 @@
                        }
                }
                this.name = name.toLowerCase(Locale.ENGLISH);
-               if (content != null && !name.equals("#") && !name.equals("%")) {
+               if (content != null && !("#").equals(name)&& 
!("%").equals(name)) {
                        addChild(new HTMLNode("#", content));
                        this.content = null;
                } else
@@ -83,12 +83,12 @@
                attributes.put(attributeName, attributeValue);
        }

-       public Map getAttributes() {
+       public Map<String, String> getAttributes() {
                return Collections.unmodifiableMap(attributes);
        }

        public String getAttribute(String attributeName) {
-               return (String) attributes.get(attributeName);
+               return attributes.get(attributeName);
        }

        public HTMLNode addChild(HTMLNode childNode) {
@@ -142,11 +142,11 @@
         *         "real" tag could be found
         */
        public String getFirstTag() {
-               if (!name.equals("#")) {
+               if (!"#".equals(name)) {
                        return name;
                }
                for (int childIndex = 0, childCount = children.size(); 
childIndex < childCount; childIndex++) {
-                       HTMLNode childNode = (HTMLNode) 
children.get(childIndex);
+                       HTMLNode childNode = children.get(childIndex);
                        String tag = childNode.getFirstTag();
                        if (tag != null) {
                                return tag;
@@ -156,28 +156,29 @@
        }

        public String generate() {
-               StringBuffer tagBuffer = new StringBuffer();
+               StringBuilder tagBuffer = new StringBuilder();
                return generate(tagBuffer).toString();
        }

-       public StringBuffer generate(StringBuffer tagBuffer) {
-               if (name.equals("#") && (content != null)) {
-                       HTMLEncoder.encodeToBuffer(content, tagBuffer);
+       public StringBuilder generate(StringBuilder tagBuffer) {
+               if("#".equals(name)) {
+                       if(content != null) {
+                               HTMLEncoder.encodeToBuffer(content, tagBuffer);
+                               return tagBuffer;
+                       }
+                       
+                       for(int childIndex = 0, childCount = children.size(); 
childIndex < childCount; childIndex++) {
+                               HTMLNode childNode = children.get(childIndex);
+                               childNode.generate(tagBuffer);
+                       }
                        return tagBuffer;
                }
                // Perhaps this should be something else, but since I don't 
know if '#' was not just arbitrary chosen, I'll just pick '%'
                // This allows non-encoded text to be appended to the tag buffer
-               if (name.equals("%")) {
+               if ("%".equals(name)) {
                        tagBuffer.append(content);
                        return tagBuffer;
                }
-               if (name.equals("#")) {
-                       for (int childIndex = 0, childCount = children.size(); 
childIndex < childCount; childIndex++) {
-                               HTMLNode childNode = (HTMLNode) 
children.get(childIndex);
-                               childNode.generate(tagBuffer);
-                       }
-                       return tagBuffer;
-               }
                tagBuffer.append('<').append(name);
                Set attributeSet = attributes.entrySet();
                for (Iterator attributeIterator = attributeSet.iterator(); 
attributeIterator.hasNext();) {
@@ -188,25 +189,25 @@
                        HTMLEncoder.encodeToBuffer(attributeName, tagBuffer);
                        tagBuffer.append("=\"");
                        HTMLEncoder.encodeToBuffer(attributeValue, tagBuffer);
-                       tagBuffer.append('"');;
+                       tagBuffer.append('"');
                }
                if (children.size() == 0) {
-                       if (name.equals("textarea") || name.equals("div") || 
name.equals("a")) {
-                tagBuffer.append("></").append(name).append('>');
+                       if ("textarea".equals(name) || ("div").equals(name) || 
("a").equals(name)) {
+                               
tagBuffer.append("></").append(name).append('>');
                        } else {
                                tagBuffer.append(" />");
                        }
                } else {
                        tagBuffer.append('>');
-                       if(name.equals("div") || name.equals("form") || 
name.equals("input") || name.equals("script") || name.equals("table") || 
name.equals("tr") || name.equals("td")) {
+                       if(("div").equals(name) || ("form").equals(name) || 
("input").equals(name) || ("script").equals(name) || ("table").equals(name) || 
("tr").equals(name) || ("td").equals(name)) {
                                tagBuffer.append('\n');
                        }
                        for (int childIndex = 0, childCount = children.size(); 
childIndex < childCount; childIndex++) {
-                               HTMLNode childNode = (HTMLNode) 
children.get(childIndex);
+                               HTMLNode childNode = children.get(childIndex);
                                childNode.generate(tagBuffer);
                        }
                        tagBuffer.append("</").append(name).append('>');
-                       if(name.equals("div") || name.equals("form") || 
name.equals("input") || name.equals("li") || name.equals("option") || 
name.equals("script") || name.equals("table") || name.equals("tr") || 
name.equals("td")) {
+                       if(("div").equals(name)|| ("form").equals(name)|| 
("input").equals(name)|| ("li").equals(name)|| ("option").equals(name)|| 
("script").equals(name)|| ("table").equals(name)|| ("tr").equals(name)|| 
("td").equals(name)) {
                                tagBuffer.append('\n');
                        }
                }
@@ -236,12 +237,13 @@
                /**
                 * @see 
freenet.support.HTMLNode#generate(java.lang.StringBuffer)
                 */
-               public StringBuffer generate(StringBuffer tagBuffer) {
+               @Override
+               public StringBuilder generate(StringBuilder tagBuffer) {
                        tagBuffer.append("<!DOCTYPE ").append(name).append(" 
PUBLIC \"").append(systemUri).append("\">\n");
                        //TODO A meaningful exception should be raised 
                        // when trying to call the method for a HTMLDoctype 
                        // with number of child != 1 
-                       return ((HTMLNode) children.get(0)).generate(tagBuffer);
+                       return children.get(0).generate(tagBuffer);
                }

        }

Modified: branches/db4o/freenet/src/freenet/support/LRUHashtable.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/LRUHashtable.java 2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/LRUHashtable.java 2008-09-24 
20:42:20 UTC (rev 22823)
@@ -3,7 +3,7 @@
 import java.util.Enumeration;
 import java.util.Hashtable;

-public class LRUHashtable {
+public class LRUHashtable<K, V> {

     /*
      * I've just converted this to using the DLList and Hashtable
@@ -12,8 +12,8 @@
      * push is by far the most done operation, this should be an
      * overall improvement.
      */
-    private final DoublyLinkedListImpl list = new DoublyLinkedListImpl();
-    private final Hashtable hash = new Hashtable();
+    private final DoublyLinkedListImpl<V> list = new DoublyLinkedListImpl<V>();
+    private final Hashtable<K, QItem<K, V>> hash = new Hashtable<K, QItem<K, 
V>>();

     /**
      *       push()ing an object that is already in
@@ -21,10 +21,10 @@
      *       recently used position, but doesn't add
      *       a duplicate entry in the queue.
      */
-    public final synchronized void push(Object key, Object value) {
-        QItem insert = (QItem)hash.get(key);
+    public final synchronized void push(K key, V value) {
+        QItem<K,V> insert = hash.get(key);
         if (insert == null) {
-            insert = new QItem(key, value);
+            insert = new QItem<K, V>(key, value);
             hash.put(key,insert);
         } else {
                insert.value = value;
@@ -41,7 +41,7 @@
      */
     public final synchronized Object popKey() {
         if ( list.size() > 0 ) {
-            return ((QItem)hash.remove(((QItem)list.pop()).obj)).obj;
+            return (   hash.remove(((QItem) list.pop()).obj)).obj;
         } else {
             return null;
         }
@@ -52,7 +52,7 @@
      */
     public final synchronized Object popValue() {
         if ( list.size() > 0 ) {
-            return ((QItem)hash.remove(((QItem)list.pop()).obj)).value;
+            return (   hash.remove(((QItem) list.pop()).obj)).value;
         } else {
             return null;
         }
@@ -85,8 +85,8 @@
         return list.size();
     }

-    public final synchronized boolean removeKey(Object key) {
-       QItem i = (QItem)(hash.remove(key));
+    public final synchronized boolean removeKey(K key) {
+       QItem<K,V> i = (hash.remove(key));
        if(i != null) {
            list.remove(i);
            return true;
@@ -100,7 +100,7 @@
      * @param obj Object to match
      * @return true if this queue contains obj.
      */
-    public final synchronized boolean containsKey(Object key) {
+    public final synchronized boolean containsKey(K key) {
         return hash.containsKey(key);
     }

@@ -108,8 +108,8 @@
      * Note that this does not automatically promote the key. You have
      * to do that by hand with push(key, value).
      */
-    public final synchronized Object get(Object key) {
-       QItem q = (QItem) hash.get(key);
+    public final synchronized V get(K key) {
+       QItem<K,V> q = hash.get(key);
        if(q == null) return null;
        return q.value;
     }
@@ -146,15 +146,16 @@
         }
     }

-    private static class QItem extends DoublyLinkedListImpl.Item {
-        public Object obj;
-        public Object value;
+    public static class QItem<K, V> extends DoublyLinkedListImpl.Item<V> {
+        public K obj;
+        public V value;

-        public QItem(Object key, Object val) {
+        public QItem(K key, V val) {
             this.obj = key;
             this.value = val;
         }

+               @Override
         public String toString() {
                return super.toString()+": "+obj+ ' ' +value;
         }
@@ -170,8 +171,8 @@
         * @param entries
         * @return
         */
-       public synchronized void valuesToArray(Object[] entries) {
-               Enumeration values = values();
+       public synchronized void valuesToArray(V[] entries) {
+               Enumeration<V> values = values();
                int i=0;
                while(values.hasMoreElements())
                        entries[i++] = values.nextElement();

Modified: branches/db4o/freenet/src/freenet/support/OOMHandler.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/OOMHandler.java   2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/OOMHandler.java   2008-09-24 
20:42:20 UTC (rev 22823)
@@ -8,8 +8,6 @@

 import org.tanukisoftware.wrapper.WrapperManager;

-import freenet.support.Logger;
-
 /**
  * Do this processing as a standard response to an OutOfMemoryError
  */
@@ -25,7 +23,7 @@
        /**
         * List of {@link OOMHook}s
         */
-       private static Set oomHooks = new WeakHashSet();
+       private static Set<OOMHook> oomHooks = new WeakHashSet<OOMHook>();

        public static void addOOMHook(OOMHook hook) {
                synchronized (oomHooks) {
@@ -41,9 +39,9 @@
                System.runFinalization();

                // iterate all oom hooks
-               Iterator it = oomHooks.iterator();
+               Iterator<OOMHook> it = oomHooks.iterator();
                while (it.hasNext()) {
-                       OOMHook hook = ((OOMHook) it.next());
+                       OOMHook hook = it.next();
                        if (hook != null) {
                                try {
                                        hook.handleLowMemory();
@@ -77,9 +75,9 @@
                        System.runFinalization();

                        // iterate all oom hooks
-                       Iterator it = oomHooks.iterator();
+                       Iterator<OOMHook> it = oomHooks.iterator();
                        while (it.hasNext()) {
-                               OOMHook hook = ((OOMHook) it.next());
+                               OOMHook hook = it.next();
                                if (hook != null) {
                                        try {
                                                hook.handleOutOfMemory();

Modified: branches/db4o/freenet/src/freenet/support/PooledExecutor.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/PooledExecutor.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/PooledExecutor.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -16,9 +16,9 @@
 public class PooledExecutor implements Executor {

        /** All threads running or waiting */
-       private final ArrayList[] runningThreads /* <MyThread> */ = new 
ArrayList[NativeThread.JAVA_PRIORITY_RANGE + 1];
+       private final ArrayList<MyThread>[] runningThreads = new 
ArrayList[NativeThread.JAVA_PRIORITY_RANGE + 1];
        /** Threads waiting for a job */
-       private final ArrayList[] waitingThreads /* <MyThread> */ = new 
ArrayList[runningThreads.length];
+       private final ArrayList<MyThread>[] waitingThreads = new 
ArrayList[runningThreads.length];
        long[] threadCounter = new long[runningThreads.length];
        private long jobCount;
        private long jobMisses;
@@ -64,7 +64,7 @@
                        synchronized(this) {
                                jobCount++;
                                if(!waitingThreads[prio - 1].isEmpty()) {
-                                       t = (MyThread) waitingThreads[prio - 
1].remove(waitingThreads[prio - 1].size() - 1);
+                                       t = waitingThreads[prio - 
1].remove(waitingThreads[prio - 1].size() - 1);
                                        if(logMINOR)
                                                Logger.minor(this, "Reusing 
thread " + t);
                                } else {
@@ -140,6 +140,7 @@
                        threadNo = threadCounter;
                }

+               @Override
                public void run() {
                        super.run();
                        long ranJobs = 0;

Modified: branches/db4o/freenet/src/freenet/support/SimpleFieldSet.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/SimpleFieldSet.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/SimpleFieldSet.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -33,8 +33,8 @@
  */
 public class SimpleFieldSet {

-    private final Map values;
-    private Map subsets;
+    private final Map<String, String> values;
+    private Map<String, SimpleFieldSet> subsets;
     private String endMarker;
     private final boolean shortLived;
     static public final char MULTI_LEVEL_CHAR = '.';
@@ -49,7 +49,7 @@
      * small.
      */
     public SimpleFieldSet(boolean shortLived) {
-        values = new HashMap();
+        values = new HashMap<String, String>();
                subsets = null;
                this.shortLived = shortLived;
     }
@@ -71,9 +71,9 @@
     }

     public SimpleFieldSet(SimpleFieldSet sfs){
-       values = new HashMap(sfs.values);
+       values = new HashMap<String, String>(sfs.values);
        if(sfs.subsets != null)
-               subsets = new HashMap(sfs.subsets);
+               subsets = new HashMap<String, SimpleFieldSet>(sfs.subsets);
        this.shortLived = false; // it's been copied!
        endMarker = sfs.endMarker;
     }
@@ -173,14 +173,14 @@
     public synchronized String get(String key) {
                int idx = key.indexOf(MULTI_LEVEL_CHAR);
                if(idx == -1)
-                       return (String) values.get(key);
+                       return values.get(key);
                else if(idx == 0)
                        return (subset("") == null) ? null : 
subset("").get(key.substring(1));
                else {
                        if(subsets == null) return null;
                        String before = key.substring(0, idx);
                        String after = key.substring(idx+1);
-                       SimpleFieldSet fs = (SimpleFieldSet) 
(subsets.get(before));
+                       SimpleFieldSet fs = subsets.get(before);
                        if(fs == null) return null;
                        return fs.get(after);
                }
@@ -193,7 +193,7 @@
     }

     private static final String[] split(String string) {
-       if(string == null) return new String[0];
+       if(string == null) return EMPTY_STRING_ARRAY;
        return string.split(String.valueOf(MULTI_VALUE_CHAR)); // slower???
 //     int index = string.indexOf(';');
 //     if(index == -1) return null;
@@ -212,7 +212,7 @@
        }

     private static final String unsplit(String[] strings) {
-       StringBuffer sb = new StringBuffer();
+       StringBuilder sb = new StringBuilder();
        for(int i=0;i<strings.length;i++) {
                if(i != 0) sb.append(MULTI_VALUE_CHAR);
                sb.append(strings[i]);
@@ -227,7 +227,7 @@
        Iterator i = fs.values.keySet().iterator();
        while(i.hasNext()) {
                String key = (String) i.next();
-               String hisVal = (String) fs.values.get(key);
+               String hisVal = fs.values.get(key);
                values.put(key, hisVal); // overwrite old
        }
        if(fs.subsets == null) return;
@@ -235,8 +235,8 @@
        i = fs.subsets.keySet().iterator();
        while(i.hasNext()) {
                String key = (String) i.next();
-               SimpleFieldSet hisFS = (SimpleFieldSet) fs.subsets.get(key);
-               SimpleFieldSet myFS = (SimpleFieldSet) subsets.get(key);
+               SimpleFieldSet hisFS = fs.subsets.get(key);
+               SimpleFieldSet myFS = subsets.get(key);
                if(myFS != null) {
                        myFS.putAllOverwrite(hisFS);
                } else {
@@ -294,14 +294,14 @@
                if(value == null) return true; // valid no-op
                if(value.indexOf('\n') != -1) throw new 
IllegalArgumentException("A simplefieldSet can't accept newlines !");
                if((idx = key.indexOf(MULTI_LEVEL_CHAR)) == -1) {
-                       String x = (String) values.get(key);
+                       String x = values.get(key);

                        if(!shortLived) key = key.intern();
                        if(x == null || overwrite) {
                                values.put(key, value);
                        } else {
                                if(!allowMultiple) return false;
-                               values.put(key, ((String)values.get(key))+ 
MULTI_VALUE_CHAR +value);
+                               values.put(key, (values.get(key))+ 
MULTI_VALUE_CHAR +value);
                        }
                } else {
                        String before = key.substring(0, idx);
@@ -309,7 +309,7 @@
                        SimpleFieldSet fs = null;
                        if(subsets == null)
                                subsets = new HashMap();
-                       fs = (SimpleFieldSet) (subsets.get(before));
+                       fs = subsets.get(before);
                        if(fs == null) {
                                fs = new SimpleFieldSet(shortLived);
                                if(!shortLived) before = before.intern();
@@ -399,7 +399,7 @@
        }

     private synchronized void writeToOrdered(Writer w, String prefix, boolean 
noEndMarker) throws IOException {
-       String[] keys = (String[]) values.keySet().toArray(new 
String[values.size()]);
+       String[] keys = values.keySet().toArray(new String[values.size()]);
        int i=0;

        // Sort
@@ -410,7 +410,7 @@
                
w.write(prefix+keys[i]+KEYVALUE_SEPARATOR_CHAR+get(keys[i])+'\n');

        if(subsets != null) {
-               String[] orderedPrefixes = (String[]) 
subsets.keySet().toArray(new String[subsets.size()]);
+               String[] orderedPrefixes = subsets.keySet().toArray(new 
String[subsets.size()]);
                // Sort
                Arrays.sort(orderedPrefixes);

@@ -429,6 +429,7 @@
        }
     }

+       @Override
     public String toString() {
         StringWriter sw = new StringWriter();
         try {
@@ -461,10 +462,10 @@
                if(subsets == null) return null;
                int idx = key.indexOf(MULTI_LEVEL_CHAR);
                if(idx == -1)
-                       return (SimpleFieldSet) subsets.get(key);
+                       return subsets.get(key);
                String before = key.substring(0, idx);
                String after = key.substring(idx+1);
-               SimpleFieldSet fs = (SimpleFieldSet) subsets.get(before);
+               SimpleFieldSet fs = subsets.get(before);
                if(fs == null) return null;
                return fs.subset(after);
        }
@@ -519,7 +520,7 @@
                                if(subsetIterator == null || 
!subsetIterator.hasNext()) break;
                                String name = (String) subsetIterator.next();
                                if(name == null) continue;
-                               SimpleFieldSet fs = (SimpleFieldSet) 
subsets.get(name);
+                               SimpleFieldSet fs = subsets.get(name);
                                if(fs == null) continue;
                                String newPrefix = prefix + name + 
MULTI_LEVEL_CHAR;
                                subIterator = fs.keyIterator(newPrefix);
@@ -538,7 +539,7 @@
                                        if(subIterator != null) subIterator = 
null;
                                        if(subsetIterator != null && 
subsetIterator.hasNext()) {
                                                String key = (String) 
subsetIterator.next();
-                                               SimpleFieldSet fs = 
(SimpleFieldSet) subsets.get(key);
+                                               SimpleFieldSet fs = 
subsets.get(key);
                                                String newPrefix = prefix + key 
+ MULTI_LEVEL_CHAR;
                                                subIterator = 
fs.keyIterator(newPrefix);
                                        } else
@@ -571,7 +572,7 @@
                                        subIterator = null;
                                        if(subsetIterator != null && 
subsetIterator.hasNext()) {
                                                String key = (String) 
subsetIterator.next();
-                                               SimpleFieldSet fs = 
(SimpleFieldSet) subsets.get(key);
+                                               SimpleFieldSet fs = 
subsets.get(key);
                                                String newPrefix = prefix + key 
+ MULTI_LEVEL_CHAR;
                                                subIterator = 
fs.keyIterator(newPrefix);
                                        } else {
@@ -615,7 +616,7 @@
                        if(subsets == null) return;
                        String before = key.substring(0, idx);
                        String after = key.substring(idx+1);
-                       SimpleFieldSet fs = (SimpleFieldSet) 
(subsets.get(before));
+                       SimpleFieldSet fs = subsets.get(before);
                        if(fs == null) {
                                return;
                        }
@@ -646,7 +647,7 @@
                } else {
                        String before = key.substring(0, idx);
                        String after = key.substring(idx+1);
-                       SimpleFieldSet fs = (SimpleFieldSet) 
(subsets.get(before));
+                       SimpleFieldSet fs = subsets.get(before);
                        if(fs == null) {
                                return;
                        }
@@ -669,7 +670,7 @@
        }

        public String[] namesOfDirectSubsets() {
-               return (subsets == null) ? EMPTY_STRING_ARRAY : (String[]) 
subsets.keySet().toArray(new String[subsets.size()]);
+               return (subsets == null) ? EMPTY_STRING_ARRAY : 
subsets.keySet().toArray(new String[subsets.size()]);
        }

        public static SimpleFieldSet readFrom(InputStream is, boolean 
allowMultiple, boolean shortLived) throws IOException {

Modified: branches/db4o/freenet/src/freenet/support/SizeUtil.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/SizeUtil.java     2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/SizeUtil.java     2008-09-24 
20:42:20 UTC (rev 22823)
@@ -10,7 +10,17 @@
                return formatSize(sz, false);
        }

+       public static String formatSizeWithoutSpace(long sz) {
+               String[] result = _formatSize(sz);
+               return result[0].concat(result[1]);
+       }
+       
        public static String formatSize(long sz, boolean useNonBreakingSpace) {
+               String[] result = _formatSize(sz);
+               return result[0].concat((useNonBreakingSpace ? "\u00a0" : " 
")).concat(result[1]);
+       }
+       
+       public static String[] _formatSize(long sz) {
                long s = 1;
                int i;
                for(i=0;i<SizeUtil.suffixes.length;i++) {
@@ -24,39 +34,19 @@
                s /= 1024; // we use the previous unit
                if (s == 1)  // Bytes? Then we don't need real numbers with a 
comma
                {
-                       return sz + " " + SizeUtil.suffixes[0];
+                       return new String[] { String.valueOf(sz), 
SizeUtil.suffixes[0] };
                }
                else
                {
                        double mantissa = (double)sz / (double)s;
-                       String o = Double.toString(mantissa);
+                       String o = String.valueOf(mantissa);
                        if(o.indexOf('.') == 3)
                                o = o.substring(0, 3);
                        else if((o.indexOf('.') > -1) && (o.indexOf('E') == -1) 
&& (o.length() > 4))
                                o = o.substring(0, 4);
                        if(i < SizeUtil.suffixes.length) // handle the case 
where the mantissa is Infinity
-                               if(useNonBreakingSpace) {
-                                       o += '\u00a0' + SizeUtil.suffixes[i];
-                               } else {
-                                       o += ' ' + SizeUtil.suffixes[i];
-                               }
-                       return o;
+                               return new String[] { o , SizeUtil.suffixes[i] 
};
+                       return new String[] { o , "" };
                }
        }
-
-       public static String stripBytesEtc(String size) {
-               if(size.length() > 0 && size.charAt(size.length()-1) == 'B')
-                       size = size.substring(0, size.length()-1);
-               if(size.length() > 0 && size.charAt(size.length()-1) == 'i')
-                       size = size.substring(0, size.length()-1);
-               if(size.indexOf(' ') != -1) {
-                       StringBuffer sb = new StringBuffer(size.length()-1);
-                       for(int i=0;i<size.length();i++) {
-                               char c = size.charAt(i);
-                               if(c != ' ') sb.append(c);
-                       }
-                       size = sb.toString();
-               }
-               return size;
-       }
 }

Modified: branches/db4o/freenet/src/freenet/support/SortedLongSet.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/SortedLongSet.java        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/SortedLongSet.java        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -1,6 +1,5 @@
 package freenet.support;

-import java.util.Arrays;

 /**
  * Sorted array of long's.

Deleted: branches/db4o/freenet/src/freenet/support/StringArray.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/StringArray.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/StringArray.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -1,101 +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;
-
-/**
- * This class implements various toString methods available in java 1.5 but 
not 1.4
- * 
- * @author Florent Daigni&egrave;re &lt;nextgens at freenetproject.org&gt;
- */
-public class StringArray {
-       
-       /**
-        * This method implements the equivalent of Arrays.valueOf() (java 1.5)
-        * @param array
-        * @return string
-        */
-       public static String toString(Object[] array){
-               if((array != null) && (array.length > 0)){
-                       StringBuffer sb = new StringBuffer();
-                       for(int i=0; i<array.length; i++)
-                               sb.append(array[i].toString()+'|');
-                       return '[' + sb.substring(0, sb.length() - 1) + ']';
-               }else
-                       return "";
-       }
-       
-       /**
-        * This method implements the equivalent of Arrays.valueOf() (java 1.5)
-        * @param array
-        * @return string
-        */
-       public static String toString(String[] array){
-               if((array != null) && (array.length > 0)){
-                       StringBuffer sb = new StringBuffer();
-                       for(int i=0; i<array.length; i++)
-                               sb.append(array[i]+'|');
-                       return '[' + sb.substring(0, sb.length() - 1) + ']';
-               }else
-                       return "";
-       }
-       
-       /**
-        * This methods returns a String[] from Object[]
-        * @param array
-        * @return string[]
-        */
-       public static String[] toArray(Object[] array){
-               if((array != null) && (array.length > 0)){
-                       String[] result = new String[array.length];
-                       for(int i=0; i<array.length; i++)
-                               result[i] = (array[i]).toString();
-                       return result;
-               }else
-                       return null;
-       }
-
-       public static String[] toArray(double[] array) {
-               if((array != null) && (array.length > 0)){
-                       String[] result = new String[array.length];
-                       for(int i=0; i<array.length; i++)
-                               result[i] = Double.toString(array[i]);
-                       return result;
-               }else
-                       return null;
-       }
-       
-       public static String toString(double[] array) {
-               return toString(toArray(array));
-       }
-       
-       public static String[] toArray(long[] array) {
-               if((array != null) && (array.length > 0)){
-                       String[] result = new String[array.length];
-                       for(int i=0; i<array.length; i++)
-                               result[i] = Long.toString(array[i]);
-                       return result;
-               }else
-                       return null;
-       }
-       
-       public static String toString(long[] array) {
-               return toString(toArray(array));
-       }
-
-       public static String[] toArray(int[] array) {
-               if((array != null) && (array.length > 0)){
-                       String[] result = new String[array.length];
-                       for(int i=0; i<array.length; i++)
-                               result[i] = Long.toString(array[i]);
-                       return result;
-               }else
-                       return null;
-       }
-       
-       public static String toString(int[] array) {
-               return toString(toArray(array));
-       }
-       
-}

Modified: branches/db4o/freenet/src/freenet/support/TimeSortedHashtable.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/TimeSortedHashtable.java  
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/TimeSortedHashtable.java  
2008-09-24 20:42:20 UTC (rev 22823)
@@ -9,8 +9,18 @@
 /**
  * Variant on LRUHashtable which provides an efficient how-many-since-time-T 
operation.
  */
-public class TimeSortedHashtable {
-
+public class TimeSortedHashtable implements Cloneable {
+       
+       public TimeSortedHashtable() {
+               this.elements = new TreeSet(new MyComparator());
+               this.valueToElement = new HashMap();
+       }
+       
+       private TimeSortedHashtable(TimeSortedHashtable c) {
+               this.elements = new TreeSet(c.elements);
+               this.valueToElement = new HashMap(c.valueToElement);
+       }
+       
        private static class Element {

                Element(long t, Comparable v) {
@@ -54,9 +64,13 @@

        }

-    private final TreeSet elements = new TreeSet(new MyComparator());
-    private final HashMap valueToElement = new HashMap();
+    private final TreeSet elements;
+    private final HashMap valueToElement;

+    public TimeSortedHashtable clone() {
+           return new TimeSortedHashtable(this);
+    }
+    
     public final void push(Comparable value) {
        push(value, System.currentTimeMillis());
     }

Modified: branches/db4o/freenet/src/freenet/support/WeakHashSet.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/WeakHashSet.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/WeakHashSet.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -5,50 +5,60 @@
 import java.util.Iterator;
 import java.util.WeakHashMap;

-public class WeakHashSet extends AbstractSet {
-       private final WeakHashMap map;
+public class WeakHashSet<E> extends AbstractSet<E> {
+       private final WeakHashMap<E, Object> map;

        public WeakHashSet() {
-               map = new WeakHashMap();
+               map = new WeakHashMap<E, Object>();
        }

-       public boolean add(Object key) {
+       @Override
+    public boolean add(E key) {
                return map.put(key, null) == null;
        }

-       public void clear() {
+       @Override
+    public void clear() {
                map.clear();
        }

-       public boolean contains(Object key) {
+       @Override
+    public boolean contains(Object key) {
                return map.containsKey(key);
        }

-       public boolean containsAll(Collection arg0) {
+       @Override
+    public boolean containsAll(Collection<?> arg0) {
                return map.keySet().containsAll(arg0);
        }

-       public boolean isEmpty() {
+       @Override
+    public boolean isEmpty() {
                return map.isEmpty();
        }

-       public Iterator iterator() {
+       @Override
+    public Iterator<E> iterator() {
                return map.keySet().iterator();
        }

-       public boolean remove(Object key) {
+       @Override
+    public boolean remove(Object key) {
                return map.remove(key) != null;
        }

-       public int size() {
+       @Override
+    public int size() {
                return map.size();
        }

-       public Object[] toArray() {
+       @Override
+    public Object[] toArray() {
                return map.keySet().toArray();
        }

-       public Object[] toArray(Object[] arg0) {
+       @Override
+    public <T> T[] toArray(T[] arg0) {
                return map.keySet().toArray(arg0);
        }
 }

Modified: branches/db4o/freenet/src/freenet/support/api/BooleanCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/api/BooleanCallback.java  
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/api/BooleanCallback.java  
2008-09-24 20:42:20 UTC (rev 22823)
@@ -4,25 +4,10 @@
 package freenet.support.api;

 import freenet.config.ConfigCallback;
-import freenet.config.InvalidConfigValueException;

 /**
  * A callback to be called when a config value of integer type changes.
  * Also reports the current value.
  */
-public interface BooleanCallback extends ConfigCallback {
-       
-       /**
-        * Get the current, used value of the config variable.
-        */
-       boolean get();
-       
-       /**
-        * Set the config variable to a new value.
-        * @param val The new value.
-        * @throws InvalidConfigOptionException If the new value is invalid for 
-        * this particular option.
-        */
-       void set(boolean val) throws InvalidConfigValueException;
-
+public abstract class BooleanCallback extends ConfigCallback<Boolean> {
 }

Modified: branches/db4o/freenet/src/freenet/support/api/IntCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/api/IntCallback.java      
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/api/IntCallback.java      
2008-09-24 20:42:20 UTC (rev 22823)
@@ -4,25 +4,10 @@
 package freenet.support.api;

 import freenet.config.ConfigCallback;
-import freenet.config.InvalidConfigValueException;

 /**
  * A callback to be called when a config value of integer type changes.
  * Also reports the current value.
  */
-public interface IntCallback extends ConfigCallback {
-
-       /**
-        * Get the current, used value of the config variable.
-        */
-       int get();
-       
-       /**
-        * Set the config variable to a new value.
-        * @param val The new value.
-        * @throws InvalidConfigOptionException If the new value is invalid for 
-        * this particular option.
-        */
-       void set(int val) throws InvalidConfigValueException;
-       
+public abstract class IntCallback extends ConfigCallback<Integer> {
 }

Modified: branches/db4o/freenet/src/freenet/support/api/LongCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/api/LongCallback.java     
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/api/LongCallback.java     
2008-09-24 20:42:20 UTC (rev 22823)
@@ -4,25 +4,10 @@
 package freenet.support.api;

 import freenet.config.ConfigCallback;
-import freenet.config.InvalidConfigValueException;

 /**
  * A callback to be called when a config value of long type changes.
  * Also reports the current value.
  */
-public interface LongCallback extends ConfigCallback {
-
-       /**
-        * Get the current, used value of the config variable.
-        */
-       long get();
-       
-       /**
-        * Set the config variable to a new value.
-        * @param val The new value.
-        * @throws InvalidConfigOptionException If the new value is invalid for 
-        * this particular option.
-        */
-       void set(long val) throws InvalidConfigValueException;
-       
+public abstract class LongCallback extends ConfigCallback<Long> {
 }

Modified: branches/db4o/freenet/src/freenet/support/api/ShortCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/api/ShortCallback.java    
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/api/ShortCallback.java    
2008-09-24 20:42:20 UTC (rev 22823)
@@ -1,25 +1,10 @@
 package freenet.support.api;

 import freenet.config.ConfigCallback;
-import freenet.config.InvalidConfigValueException;

 /**
  * A callback to be called when a config value of short type changes.
  * Also reports the current value.
  */
-public interface ShortCallback extends ConfigCallback {
-
-       /**
-        * Get the current, used value of the config variable.
-        */
-       short get();
-       
-       /**
-        * Set the config variable to a new value.
-        * @param val The new value.
-        * @throws InvalidConfigOptionException If the new value is invalid for 
-        * this particular option.
-        */
-       void set(short val) throws InvalidConfigValueException;
-       
+public abstract class ShortCallback extends ConfigCallback<Short> {
 }

Modified: branches/db4o/freenet/src/freenet/support/api/StringArrCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/api/StringArrCallback.java        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/api/StringArrCallback.java        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -4,22 +4,7 @@
 package freenet.support.api;

 import freenet.config.ConfigCallback;
-import freenet.config.InvalidConfigValueException;

 /** Callback (getter/setter) for a string config variable */
-public interface StringArrCallback extends ConfigCallback {
-       
-       /**
-        * Get the current, used value of the config variable.
-        */
-       String[] get();
-
-       /**
-        * Set the config variable to a new value.
-        * @param val The new value.
-        * @throws InvalidConfigOptionException If the new value is invalid for 
-        * this particular option.
-        */
-       void set(String[] val) throws InvalidConfigValueException;
-       
+public abstract class StringArrCallback extends ConfigCallback<String[]> {
 }

Modified: branches/db4o/freenet/src/freenet/support/api/StringCallback.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/api/StringCallback.java   
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/api/StringCallback.java   
2008-09-24 20:42:20 UTC (rev 22823)
@@ -4,22 +4,8 @@
 package freenet.support.api;

 import freenet.config.ConfigCallback;
-import freenet.config.InvalidConfigValueException;

 /** Callback (getter/setter) for a string config variable */
-public interface StringCallback extends ConfigCallback {
-       
-       /**
-        * Get the current, used value of the config variable.
-        */
-       String get();
+public abstract class StringCallback extends ConfigCallback<String> {

-       /**
-        * Set the config variable to a new value.
-        * @param val The new value.
-        * @throws InvalidConfigOptionException If the new value is invalid for 
-        * this particular option.
-        */
-       void set(String val) throws InvalidConfigValueException;
-       
 }

Modified: branches/db4o/freenet/src/freenet/support/compress/GzipCompressor.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/compress/GzipCompressor.java      
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/compress/GzipCompressor.java      
2008-09-24 20:42:20 UTC (rev 22823)
@@ -17,7 +17,7 @@
 public class GzipCompressor extends Compressor {

        public Bucket compress(Bucket data, BucketFactory bf, long maxLength) 
throws IOException, CompressionOutputSizeException {
-               Bucket output = bf.makeBucket(-1);
+               Bucket output = bf.makeBucket(maxLength);
                InputStream is = null;
                OutputStream os = null;
                GZIPOutputStream gos = null;
@@ -54,7 +54,7 @@
                if(preferred != null)
                        output = preferred;
                else
-                       output = bf.makeBucket(-1);
+                       output = bf.makeBucket(maxLength);
                InputStream is = null;
                OutputStream os = null;
                try {

Modified: branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -15,15 +15,13 @@
 /**
  * A bucket that stores data in the memory.
  * 
- * FIXME: No synchronization, should there be?
- * 
  * @author oskar
  */
 public class ArrayBucket implements Bucket {

-       private final ArrayList data;
-       private String name;
-       private boolean readOnly;
+       private final ArrayList<byte[]> data;
+       private final String name;
+       private volatile boolean readOnly;

        public ArrayBucket() {
                this("ArrayBucket");
@@ -35,20 +33,21 @@
        }

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

-       public OutputStream getOutputStream() throws IOException {
+       public synchronized OutputStream getOutputStream() throws IOException {
                if(readOnly) throw new IOException("Read only");
                return new ArrayBucketOutputStream();
        }

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

-       public String toString() {
+       @Override
+       public synchronized String toString() {
                StringBuffer s = new StringBuffer(250);
                for (Iterator i = data.iterator(); i.hasNext();) {
                        byte[] b = (byte[]) i.next();
@@ -57,7 +56,7 @@
                return s.toString();
        }

-       public void read(InputStream in) throws IOException {
+       public synchronized void read(InputStream in) throws IOException {
                OutputStream out = new ArrayBucketOutputStream();
                int i;
                byte[] b = new byte[8 * 1024];
@@ -67,13 +66,13 @@
                out.close();
        }

-       public long size() {
-               long size = 0;
-               for (Iterator i = data.iterator(); i.hasNext();) {
-                       byte[] b = (byte[]) i.next();
-                       size += b.length;
-               }
-               return size;
+       public synchronized long size() {
+               long currentSize = 0;
+               
+               for(byte[] buf : data)
+                       currentSize += buf.length;
+               
+               return currentSize;
        }

        public String getName() {
@@ -81,15 +80,30 @@
        }

        private class ArrayBucketOutputStream extends ByteArrayOutputStream {
+               boolean hasBeenClosed = false;

                public ArrayBucketOutputStream() {
                        super();
                }
+               
+               @Override
+               public synchronized void write(byte b[], int off, int len) {
+                       if(readOnly) throw new IllegalStateException("Read 
only");
+                       super.write(b, off, len);
+               }
+               
+               @Override
+               public synchronized void write(int b) {
+                       if(readOnly) throw new IllegalStateException("Read 
only");
+                       super.write(b);
+               }

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

@@ -102,11 +116,11 @@
                        i = data.iterator();
                }

-               public int read() {
+               public synchronized int read() {
                        return priv_read();
                }

-               private int priv_read() {
+               private synchronized int priv_read() {
                        if (in == null) {
                                if (i.hasNext()) {
                                        in = new ByteArrayInputStream((byte[]) 
i.next());
@@ -123,15 +137,17 @@
                        }
                }

-               public int read(byte[] b) {
+               @Override
+               public synchronized int read(byte[] b) {
                        return priv_read(b, 0, b.length);
                }

-               public int read(byte[] b, int off, int len) {
+               @Override
+               public synchronized int read(byte[] b, int off, int len) {
                        return priv_read(b, off, len);
                }

-               private int priv_read(byte[] b, int off, int len) {
+               private synchronized int priv_read(byte[] b, int off, int len) {
                        if (in == null) {
                                if (i.hasNext()) {
                                        in = new ByteArrayInputStream((byte[]) 
i.next());
@@ -148,7 +164,8 @@
                        }
                }

-               public int available() {
+               @Override
+               public synchronized int available() {
                        if (in == null) {
                                if (i.hasNext()) {
                                        in = new ByteArrayInputStream((byte[]) 
i.next());
@@ -169,12 +186,12 @@
                readOnly = true;
        }

-       public void free() {
+       public synchronized void free() {
                data.clear();
                // Not much else we can do.
        }

-       public byte[] toByteArray() {
+       public synchronized byte[] toByteArray() {
                long sz = size();
                int size = (int)sz;
                byte[] buf = new byte[size];

Modified: branches/db4o/freenet/src/freenet/support/io/BaseFileBucket.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/BaseFileBucket.java    
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/io/BaseFileBucket.java    
2008-09-24 20:42:20 UTC (rev 22823)
@@ -14,8 +14,8 @@
 import freenet.support.Fields;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
-import freenet.support.StringArray;
 import freenet.support.api.Bucket;
+import java.util.Arrays;

 public abstract class BaseFileBucket implements Bucket, 
SerializableToFieldSetBucket {

@@ -394,7 +394,7 @@
                }

                if(toClose != null) {
-                       Logger.error(this, "Streams open free()ing "+this+" : 
"+StringArray.toString(toClose), new Exception("debug"));
+                       Logger.error(this, "Streams open free()ing "+this+" : 
"+Arrays.toString(toClose), new Exception("debug"));
                        for(int i=0;i<toClose.length;i++) {
                                try {
                                        if(toClose[i] instanceof 
FileBucketOutputStream) {
@@ -421,6 +421,7 @@
                }
        }

+       @Override
        public synchronized String toString() {
                StringBuffer sb = new StringBuffer();
                sb.append(super.toString());

Modified: branches/db4o/freenet/src/freenet/support/io/BucketTools.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/BucketTools.java       
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/io/BucketTools.java       
2008-09-24 20:42:20 UTC (rev 22823)
@@ -288,6 +288,7 @@
                                if(bytes <= 0) {
                                        if(truncateLength == Long.MAX_VALUE)
                                                break;
+                                       new IOException().printStackTrace();
                                        throw new IOException("Could not move 
required quantity of data in copyTo: "+bytes+" (moved "+moved+" of 
"+truncateLength+"): unable to read from "+is);
                                }
                                os.write(buf, 0, bytes);
@@ -419,10 +420,12 @@
                                os.write(buf, 0, thisCycle);
                                x += thisCycle;
                        }
+                       os.close();
+                       os = null;
                        if(b.size() != blockLength)
-                               throw new IllegalStateException();
+                               throw new IllegalStateException("The bucket's 
size is "+b.size()+" whereas it should be "+blockLength+'!');
                        return b;
-               } finally { os.close(); }
+               } finally { Closer.close(os); }
        }

 }

Modified: branches/db4o/freenet/src/freenet/support/io/Closer.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/Closer.java    2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/io/Closer.java    2008-09-24 
20:42:20 UTC (rev 22823)
@@ -18,12 +18,8 @@

 package freenet.support.io;

+import java.io.Closeable;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.jar.JarFile;
 import java.util.zip.ZipFile;

 /**
@@ -36,77 +32,16 @@
  * @version $Id$
  */
 public class Closer {
-
        /**
-        * Closes the given output stream.
+        * Closes the given stream.
         * 
         * @param outputStream
         *            The output stream to close
         */
-       public static void close(OutputStream outputStream) {
-               if (outputStream != null) {
+       public static void close(Closeable closable) {
+               if (closable != null) {
                        try {
-                               outputStream.close();
-                       } catch (IOException ioe1) {
-                       }
-               }
-       }
-
-       /**
-        * Closes the given input stream.
-        * 
-        * @param inputStream
-        *            The input stream to close
-        */
-       public static void close(InputStream inputStream) {
-               if (inputStream != null) {
-                       try {
-                               inputStream.close();
-                       } catch (IOException ioe1) {
-                       }
-               }
-       }
-
-       /**
-        * Closes the given writer.
-        * 
-        * @param writer
-        *            The writer to close
-        */
-       public static void close(Writer writer) {
-               if (writer != null) {
-                       try {
-                               writer.close();
-                       } catch (IOException ioe1) {
-                       }
-               }
-       }
-
-       /**
-        * Closes the given reader.
-        * 
-        * @param reader
-        *            The reader to close
-        */
-       public static void close(Reader reader) {
-               if (reader != null) {
-                       try {
-                               reader.close();
-                       } catch (IOException ioe1) {
-                       }
-               }
-       }
-
-       /**
-        * Closes the given jar file.
-        * 
-        * @param jarFile
-        *            The jar file to close
-        */
-       public static void close(JarFile jarFile) {
-               if (jarFile != null) {
-                       try {
-                               jarFile.close();
+                               closable.close();
                        } catch (IOException e) {
                        }
                }

Modified: branches/db4o/freenet/src/freenet/support/io/DelayedFreeBucket.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/DelayedFreeBucket.java 
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/io/DelayedFreeBucket.java 
2008-09-24 20:42:20 UTC (rev 22823)
@@ -22,7 +22,7 @@
        Bucket bucket;
        boolean freed;

-       public DelayedFreeBucket(PersistentTempBucketFactory factory, 
PaddedEphemerallyEncryptedBucket bucket) {
+       public DelayedFreeBucket(PersistentTempBucketFactory factory, Bucket 
bucket) {
                this.factory = factory;
                this.bucket = bucket;
                if(bucket == null) throw new NullPointerException();

Modified: 
branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java    
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java    
2008-09-24 20:42:20 UTC (rev 22823)
@@ -16,8 +16,6 @@
                super(in);
        }

-       private byte[] buf;
-
        /**
         * Read a \n or \r\n terminated line of UTF-8 or ISO-8859-1.
         * @param maxLength The maximum length of a line. If a line is longer 
than this, we throw IOException rather
@@ -26,31 +24,73 @@
         * @param utf If true, read as UTF-8, if false, read as ISO-8859-1.
         */
        public String readLine(int maxLength, int bufferSize, boolean utf) 
throws IOException {
+               if(maxLength <= bufferSize)
+                       bufferSize = maxLength + 1; // Buffer too big, shrink 
it (add 1 for the optional \r)
+
+               if(!markSupported())
+                       return readLineWithoutMarking(maxLength, bufferSize, 
utf);
+               
+               byte[] buf = new byte[Math.max(Math.min(128, maxLength), 
Math.min(1024, bufferSize))];
+               int ctr = 0;
+               mark((maxLength+1)*2); // Might be more than maxLengh if we use 
utf8
+               while(true) {
+                       int x = read(buf, ctr, buf.length - ctr);
+                       if(x == -1) {
+                               if(ctr == 0)
+                                       return null;
+                               return new String(buf, 0, ctr, utf ? "UTF-8" : 
"ISO-8859-1");
+                       }
+                       // REDFLAG this is definitely safe with the above 
charsets, it may not be safe with some wierd ones. 
+                       for(; ctr < buf.length; ctr++) {
+                               if(ctr >= maxLength)
+                                       throw new TooLongException();
+                               if(buf[ctr] == '\n') {
+                                       String toReturn = "";
+                                       if(ctr != 0) {
+                                               boolean removeCR = (buf[ctr - 
1] == '\r');
+                                               toReturn = new String(buf, 0, 
(removeCR ? ctr - 1 : ctr), utf ? "UTF-8" : "ISO-8859-1");
+                                       }
+                                       reset();
+                                       skip(ctr + 1);
+                                       return toReturn;
+                               }
+                       }
+                       if(x > 0) {
+                               byte[] newBuf = new byte[Math.min(buf.length * 
2, maxLength)];
+                               System.arraycopy(buf, 0, newBuf, 0, buf.length);
+                               buf = newBuf;
+                       }
+               }
+       }
+
+       public String readLineWithoutMarking(int maxLength, int bufferSize, 
boolean utf) throws IOException {
                if(maxLength < bufferSize)
                        bufferSize = maxLength + 1; // Buffer too big, shrink 
it (add 1 for the optional \r)
-               if(buf == null)
-                       buf = new byte[Math.max(Math.min(128,maxLength), 
Math.min(1024, bufferSize))];
+               byte[] buf = new byte[Math.max(Math.min(128, maxLength), 
Math.min(1024, bufferSize))];
                int ctr = 0;
                while(true) {
                        int x = read();
                        if(x == -1) {
-                               if(ctr == 0) return null;
+                               if(ctr == 0)
+                                       return null;
                                return new String(buf, 0, ctr, utf ? "UTF-8" : 
"ISO-8859-1");
                        }
                        // REDFLAG this is definitely safe with the above 
charsets, it may not be safe with some wierd ones. 
                        if(x == '\n') {
-                               if(ctr == 0) return "";
-                               if(buf[ctr-1] == '\r') ctr--;
+                               if(ctr == 0)
+                                       return "";
+                               if(buf[ctr - 1] == '\r')
+                                       ctr--;
                                return new String(buf, 0, ctr, utf ? "UTF-8" : 
"ISO-8859-1");
                        }
-                       if(ctr >= maxLength) throw new TooLongException();
+                       if(ctr >= maxLength)
+                               throw new TooLongException();
                        if(ctr >= buf.length) {
                                byte[] newBuf = new byte[Math.min(buf.length * 
2, maxLength)];
                                System.arraycopy(buf, 0, newBuf, 0, buf.length);
                                buf = newBuf;
                        }
-                       buf[ctr++] = (byte)x;
+                       buf[ctr++] = (byte) x;
                }
        }
-       
 }

Modified: branches/db4o/freenet/src/freenet/support/io/NativeThread.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/NativeThread.java      
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/io/NativeThread.java      
2008-09-24 20:42:20 UTC (rev 22823)
@@ -4,7 +4,6 @@

 package freenet.support.io;

-import java.io.File;
 import freenet.node.NodeStarter;
 import freenet.support.LibraryLoader;
 import freenet.support.Logger;
@@ -93,6 +92,7 @@
         */
        private static native int getLinuxPriority();   

+       @Override
        public void run() {
                if(!setNativePriority(currentPriority))
                        
System.err.println("setNativePriority("+currentPriority+") has failed!");

Deleted: 
branches/db4o/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java
   2008-09-24 19:52:19 UTC (rev 22822)
+++ 
branches/db4o/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java
   2008-09-24 20:42:20 UTC (rev 22823)
@@ -1,31 +0,0 @@
-package freenet.support.io;
-
-import freenet.crypt.RandomSource;
-import java.io.IOException;
-
-import freenet.support.api.Bucket;
-import freenet.support.api.BucketFactory;
-import java.util.Random;
-
-/**
- * Factory wrapper for PaddedEphemerallyEncryptedBucket's, which are themselves
- * wrappers.
- */
-public class PaddedEphemerallyEncryptedBucketFactory implements BucketFactory {
-
-       final BucketFactory baseFactory;
-       final RandomSource strongPRNG;
-       final Random weakPRNG;
-       final int minSize;
-       
-       public PaddedEphemerallyEncryptedBucketFactory(BucketFactory factory, 
RandomSource strongPRNG, Random weakPRNG, int minSize) {
-               baseFactory = factory;
-               this.minSize = minSize;
-               this.strongPRNG = strongPRNG;
-               this.weakPRNG = weakPRNG;
-       }
-
-       public Bucket makeBucket(long size) throws IOException {
-               return new 
PaddedEphemerallyEncryptedBucket(baseFactory.makeBucket(size), minSize, 
strongPRNG, weakPRNG);
-       }
-}

Deleted: 
branches/db4o/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java
      2008-09-24 19:52:19 UTC (rev 22822)
+++ 
branches/db4o/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java
      2008-09-24 20:42:20 UTC (rev 22823)
@@ -1,52 +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.io;
-
-import java.io.IOException;
-
-import com.db4o.ObjectContainer;
-import com.db4o.ObjectSet;
-import com.db4o.query.Predicate;
-import com.db4o.query.Query;
-
-import freenet.support.api.Bucket;
-import freenet.support.api.BucketFactory;
-
-
-public class PersistentEncryptedTempBucketFactory implements BucketFactory {
-
-       PersistentTempBucketFactory bf;
-       
-       public PersistentEncryptedTempBucketFactory(PersistentTempBucketFactory 
bf) {
-               this.bf = bf;
-       }
-
-       public Bucket makeBucket(long size) throws IOException {
-               return bf.makeEncryptedBucket();
-       }
-
-       public static PersistentEncryptedTempBucketFactory load(final 
PersistentTempBucketFactory persistentTempBucketFactory, ObjectContainer 
container) {
-               // This causes an OOM in init. WTF?
-//             ObjectSet results = container.query(new Predicate() {
-//                     public boolean 
match(PersistentEncryptedTempBucketFactory bf) {
-//                             return bf.bf == persistentTempBucketFactory;
-//                     }
-//             });
-               // REDFLAG: 
-               // Constraining on bf causes an OOM for Cooo on db4o 
6.4.48.10991. Commenting out bf below fixes it.
-               // Neither of the below log messages was logged ... which 
suggests something very strange is happening in db4o.
-               // FIXME EVIL DB4O BUG - if can replicate, file a bug... but it 
didn't happen to me, on the same version, also on linux, so it may not be 
replicable.
-               Query query = container.query();
-               query.constrain(PersistentEncryptedTempBucketFactory.class);
-               //query.descend("bf").constrain(persistentTempBucketFactory);
-               ObjectSet results = query.execute();
-               while(results.hasNext()) {
-                       PersistentEncryptedTempBucketFactory factory = 
(PersistentEncryptedTempBucketFactory) results.next();
-                       if(factory.bf == persistentTempBucketFactory) return 
factory;
-                       System.err.println("Not matched factory");
-               }
-               System.err.println("Creating new factory");
-               return new 
PersistentEncryptedTempBucketFactory(persistentTempBucketFactory);
-       }
-}

Modified: 
branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java   
    2008-09-24 19:52:19 UTC (rev 22822)
+++ 
branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java   
    2008-09-24 20:42:20 UTC (rev 22823)
@@ -44,12 +44,15 @@
        private LinkedList bucketsToFree;

        private final long nodeDBHandle;
+       
+       private volatile boolean encrypt;

-       public PersistentTempBucketFactory(File dir, final String prefix, 
RandomSource strongPRNG, Random weakPRNG, long nodeDBHandle) throws IOException 
{
+       public PersistentTempBucketFactory(File dir, final String prefix, 
RandomSource strongPRNG, Random weakPRNG, boolean encrypt, long nodeDBHandle) 
throws IOException {
                boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
                this.strongPRNG = strongPRNG;
                this.nodeDBHandle = nodeDBHandle;
                this.weakPRNG = weakPRNG;
+               this.encrypt = encrypt;
                this.fg = new FilenameGenerator(weakPRNG, false, dir, prefix);
                if(!dir.exists()) {
                        dir.mkdir();
@@ -116,19 +119,11 @@
                originalFiles = null;
        }

-       private Bucket makeRawBucket(long size) throws IOException {
-               return new PersistentTempFileBucket(fg.makeRandomFilename(), 
fg);
-       }
-
        public Bucket makeBucket(long size) throws IOException {
-               Bucket b = makeRawBucket(size);
-               return new DelayedFreeBucket(this, new 
PaddedEphemerallyEncryptedBucket(b, 1024, strongPRNG, weakPRNG));
+               PersistentTempFileBucket rawBucket = new 
PersistentTempFileBucket(fg.makeRandomFilename(), fg);
+               Bucket maybeEncryptedBucket = (encrypt ? new 
PaddedEphemerallyEncryptedBucket(rawBucket, 1024, strongPRNG, weakPRNG) : 
rawBucket);
+               return new DelayedFreeBucket(this, maybeEncryptedBucket);
        }
-       
-       public Bucket makeEncryptedBucket() throws IOException {
-               Bucket b = makeRawBucket(-1);
-               return new DelayedFreeBucket(this, new 
PaddedEphemerallyEncryptedBucket(b, 1024, strongPRNG, weakPRNG));
-       }

        /**
         * Free an allocated bucket, but only after the change has been written 
to disk.
@@ -162,8 +157,12 @@
        public long getID(File file) {
                return fg.getID(file);
        }
+       
+       public boolean isEncrypting() {
+               return encrypt;
+       }

-       public static PersistentTempBucketFactory load(File dir, String prefix, 
RandomSource random, Random fastWeakRandom, ObjectContainer container, final 
long nodeDBHandle) throws IOException {
+       public static PersistentTempBucketFactory load(File dir, String prefix, 
RandomSource random, Random fastWeakRandom, ObjectContainer container, final 
long nodeDBHandle, boolean encrypt) throws IOException {
                ObjectSet<PersistentTempBucketFactory> results = 
container.query(new Predicate<PersistentTempBucketFactory>() {
                        public boolean match(PersistentTempBucketFactory 
factory) {
                                if(factory.nodeDBHandle == nodeDBHandle) return 
true;
@@ -174,9 +173,13 @@
                        PersistentTempBucketFactory factory = results.next();
                        container.activate(factory, 5);
                        factory.init(dir, prefix, random, fastWeakRandom);
+                       factory.setEncryption(encrypt);
                        return factory;
                } else
-                       return new PersistentTempBucketFactory(dir, prefix, 
random, fastWeakRandom, nodeDBHandle);
+                       return new PersistentTempBucketFactory(dir, prefix, 
random, fastWeakRandom, encrypt, nodeDBHandle);
        }

+       public void setEncryption(boolean encrypt) {
+               this.encrypt = encrypt;
+       }
 }

Modified: branches/db4o/freenet/src/freenet/support/io/RandomAccessThing.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/RandomAccessThing.java 
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/io/RandomAccessThing.java 
2008-09-24 20:42:20 UTC (rev 22823)
@@ -3,13 +3,14 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.support.io;

+import java.io.Closeable;
 import java.io.IOException;

 /**
  * Trivial random access file base interface.
  * @author toad
  */
-public interface RandomAccessThing {
+public interface RandomAccessThing extends Closeable {

        public long size() throws IOException;


Modified: branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java 
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java 
2008-09-24 20:42:20 UTC (rev 22823)
@@ -1,5 +1,6 @@
 package freenet.support.io;

+import freenet.crypt.RandomSource;
 import java.io.IOException;

 import freenet.support.api.Bucket;
@@ -10,6 +11,7 @@
  * distributed under the GNU Public Licence (GPL) version 2. See
  * http://www.gnu.org/ for further details of the GPL.
  */
+import java.util.Random;

 /**
  * Temporary Bucket Factory
@@ -18,15 +20,43 @@
  */
 public class TempBucketFactory implements BucketFactory {

+       private class RAMBucket extends ArrayBucket {
+               private final long size;
+               
+               public RAMBucket(long size) {
+                       super("RAMBucket");
+                       this.size = size;
+               }
+               
+               @Override
+               public void free() {
+                       super.free();
+                       _hasFreed(size);
+               }
+       }
+       
        private final FilenameGenerator filenameGenerator;
+       private long bytesInUse = 0;

        public final static long defaultIncrement = 4096;

        public final static float DEFAULT_FACTOR = 1.25F;
+       
+       public long maxRAMBucketSize;
+       public long maxRamUsed;

+       final RandomSource strongPRNG;
+       final Random weakPRNG;
+       private volatile boolean reallyEncrypt;
+
        // Storage accounting disabled by default.
-       public TempBucketFactory(FilenameGenerator filenameGenerator) {
+       public TempBucketFactory(FilenameGenerator filenameGenerator, long 
maxBucketSizeKeptInRam, long maxRamUsed, RandomSource strongPRNG, Random 
weakPRNG, boolean reallyEncrypt) {
                this.filenameGenerator = filenameGenerator;
+               this.maxRamUsed = maxRamUsed;
+               this.maxRAMBucketSize = maxBucketSizeKeptInRam;
+               this.strongPRNG = strongPRNG;
+               this.weakPRNG = weakPRNG;
+               this.reallyEncrypt = reallyEncrypt;
        }

        public Bucket makeBucket(long size) throws IOException {
@@ -36,6 +66,38 @@
        public Bucket makeBucket(long size, float factor) throws IOException {
                return makeBucket(size, factor, defaultIncrement);
        }
+       
+       protected synchronized void _hasFreed(long size) {
+               bytesInUse -= size;
+       }
+       
+       public synchronized long getRamUsed() {
+               return bytesInUse;
+       }
+       
+       public synchronized void setMaxRamUsed(long size) {
+               maxRamUsed = size;
+       }
+       
+       public synchronized long getMaxRamUsed() {
+               return maxRamUsed;
+       }
+       
+       public synchronized void setMaxRAMBucketSize(long size) {
+               maxRAMBucketSize = size;
+       }
+       
+       public synchronized long getMaxRAMBucketSize() {
+               return maxRAMBucketSize;
+       }
+       
+       public void setEncryption(boolean value) {
+               reallyEncrypt = value;
+       }
+       
+       public boolean isEncrypting() {
+               return reallyEncrypt;
+       }

        /**
         * Create a temp bucket
@@ -49,11 +111,19 @@
         *                If it is not possible to create a temp bucket due to 
an
         *                I/O error
         */
-       public TempFileBucket makeBucket(long size, float factor, long 
increment)
-               throws IOException {
-               long id = filenameGenerator.makeRandomFilename();
-
-               return new TempFileBucket(id, filenameGenerator);
+       public Bucket makeBucket(long size, float factor, long increment) 
throws IOException {
+               Bucket realBucket = null;
+               boolean isARAMBucket = false;
+               
+               synchronized(this) {
+                       if((size > 0) && (size <= maxRAMBucketSize) && 
(bytesInUse <= maxRamUsed)) {
+                               bytesInUse += size;
+                               isARAMBucket = true;
+                       }
+               }
+               
+               realBucket = (isARAMBucket ? new RAMBucket(size) : new 
TempFileBucket(filenameGenerator.makeRandomFilename(), filenameGenerator));
+               
+               return (!reallyEncrypt ? realBucket : new 
PaddedEphemerallyEncryptedBucket(realBucket, 1024, strongPRNG, weakPRNG));
        }
-
 }

Copied: branches/db4o/freenet/test/freenet/crypt/YarrowTest.java (from rev 
21939, trunk/freenet/test/freenet/crypt/YarrowTest.java)
===================================================================
--- branches/db4o/freenet/test/freenet/crypt/YarrowTest.java                    
        (rev 0)
+++ branches/db4o/freenet/test/freenet/crypt/YarrowTest.java    2008-09-24 
20:42:20 UTC (rev 22823)
@@ -0,0 +1,23 @@
+/* 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 org.spaceroots.mantissa.random.ScalarSampleStatistics;
+import junit.framework.*;
+
+public class YarrowTest extends TestCase {
+
+       
+// REDFLAG: for some reason that test fails on emu... investigate why and 
review our implementation of Yarrow!
+       public void testDouble() {
+//             Yarrow mt = new Yarrow(false);
+               ScalarSampleStatistics sample = new ScalarSampleStatistics();
+//             for(int i = 0; i < 1000; ++i) {
+//                     sample.add(mt.nextDouble());
+//             }
+//
+//             assertEquals(0.5, sample.getMean(), 0.02);
+//             assertEquals(1.0 / (2.0 * Math.sqrt(3.0)), 
sample.getStandardDeviation(), 0.002);
+       }
+}

Modified: branches/db4o/freenet/test/freenet/support/BufferTest.java
===================================================================
--- branches/db4o/freenet/test/freenet/support/BufferTest.java  2008-09-24 
19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/test/freenet/support/BufferTest.java  2008-09-24 
20:42:20 UTC (rev 22823)
@@ -141,7 +141,7 @@
                Buffer b2 = new Buffer("Buffer2".getBytes());
                Buffer b3 = new Buffer("Buffer1".getBytes());

-               Map hashMap = new HashMap();
+               Map<Buffer, Buffer> hashMap = new HashMap<Buffer, Buffer>();

                hashMap.put(b1, b1); 
                hashMap.put(b2, b2);

Modified: branches/db4o/freenet/test/freenet/support/ByteArrayWrapperTest.java
===================================================================
--- branches/db4o/freenet/test/freenet/support/ByteArrayWrapperTest.java        
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/test/freenet/support/ByteArrayWrapperTest.java        
2008-09-24 20:42:20 UTC (rev 22823)
@@ -32,7 +32,7 @@
                assertFalse(wrapper2.equals(wrapper3));
                assertFalse(wrapper1.equals(new String()));

-               Map map = new HashMap();
+               Map<ByteArrayWrapper, ByteArrayWrapper> map = new 
HashMap<ByteArrayWrapper, ByteArrayWrapper>();

                map.put(wrapper1, wrapper1);
                map.put(wrapper2, wrapper2); // should clobber 1 by hashcode

Modified: branches/db4o/freenet/test/freenet/support/MultiValueTableTest.java
===================================================================
--- branches/db4o/freenet/test/freenet/support/MultiValueTableTest.java 
2008-09-24 19:52:19 UTC (rev 22822)
+++ branches/db4o/freenet/test/freenet/support/MultiValueTableTest.java 
2008-09-24 20:42:20 UTC (rev 22823)
@@ -63,8 +63,8 @@
         * @param valuesNumber number of objects to create
         * @return the sample List
         */
-       private List fillSampleValuesList(int valuesNumber) {
-               List sampleValues = new LinkedList();
+       private List<Object> fillSampleValuesList(int valuesNumber) {
+               List<Object> sampleValues = new LinkedList<Object>();
                for(int i=0; i<valuesNumber;i++)
                        sampleValues.add(new Object());
                return sampleValues;

Copied: branches/db4o/freenet/test/freenet/support/io (from rev 21939, 
trunk/freenet/test/freenet/support/io)

Deleted: 
branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java
===================================================================
--- trunk/freenet/test/freenet/support/io/LineReadingInputStreamTest.java       
2008-08-16 19:34:12 UTC (rev 21939)
+++ 
branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java   
    2008-09-24 20:42:20 UTC (rev 22823)
@@ -1,106 +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.io;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import junit.framework.TestCase;
-
-public class LineReadingInputStreamTest extends TestCase {
-       public static final String BLOCK = 
"\ntesting1\ntesting2\r\ntesting3\n\n";
-       public static final String[] LINES = new String[] {
-               "",
-               "testing1",
-               "testing2",
-               "testing3",
-               ""
-       };
-       
-       public static final String STRESSED_LINE = "\n\u0114\n";
-       
-       public static final int MAX_LENGTH = 128;
-       public static final int BUFFER_SIZE = 128;
-       
-       public void testReadLineWithoutMarking() throws Exception {
-               // try utf8
-               InputStream is = new 
ByteArrayInputStream(STRESSED_LINE.getBytes("utf-8"));
-               LineReadingInputStream instance = new 
LineReadingInputStream(is);
-               assertEquals("", instance.readLineWithoutMarking(MAX_LENGTH, 
BUFFER_SIZE, true));
-               assertEquals("\u0114", 
instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, true));
-               assertNull(instance.readLineWithoutMarking(MAX_LENGTH, 
BUFFER_SIZE, true));
-               
-               // try ISO-8859-1
-               is = new ByteArrayInputStream(BLOCK.getBytes("ISO-8859-1"));
-               instance = new LineReadingInputStream(is);
-               for(String expectedLine : LINES) {
-                       assertEquals(expectedLine, 
instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, false));
-               }
-               assertNull(instance.readLineWithoutMarking(MAX_LENGTH, 
BUFFER_SIZE, false));
-               
-               // is it returning null?
-               is = new NullInputStream();
-               instance = new LineReadingInputStream(is);
-               assertNull(instance.readLineWithoutMarking(0, BUFFER_SIZE, 
false));
-               
-               // is it throwing?
-               is = new ByteArrayInputStream("aaa\na\n".getBytes());
-               instance = new LineReadingInputStream(is);
-               try {
-                       instance.readLineWithoutMarking(2, BUFFER_SIZE, true);
-                       fail();
-               } catch (TooLongException e) {}
-       }
-       
-       public void testReadLine() throws Exception {
-               // try utf8
-               InputStream is = new 
ByteArrayInputStream(STRESSED_LINE.getBytes("utf-8"));
-               LineReadingInputStream instance = new 
LineReadingInputStream(is);
-               assertEquals("", instance.readLine(MAX_LENGTH, BUFFER_SIZE, 
true));
-               assertEquals("\u0114", instance.readLine(MAX_LENGTH, 
BUFFER_SIZE, true));
-               assertNull(instance.readLine(MAX_LENGTH, BUFFER_SIZE, true));
-               
-               // try ISO-8859-1
-               is = new ByteArrayInputStream(BLOCK.getBytes("ISO-8859-1"));
-               instance = new LineReadingInputStream(is);
-               for(String expectedLine : LINES) {
-                       assertEquals(expectedLine, 
instance.readLine(MAX_LENGTH, BUFFER_SIZE, false));
-               }
-               assertNull(instance.readLine(MAX_LENGTH, BUFFER_SIZE, false));
-               
-               // is it returning null?
-               is = new NullInputStream();
-               instance = new LineReadingInputStream(is);
-               assertNull(instance.readLine(0, BUFFER_SIZE, false));
-               
-               // is it throwing?
-               is = new ByteArrayInputStream("aaa\na\n".getBytes());
-               instance = new LineReadingInputStream(is);
-               try {
-                       instance.readLine(2, BUFFER_SIZE, true);
-                       fail();
-               } catch (TooLongException e) {}
-       }
-
-       public void testBothImplementation() throws Exception {
-               // CWD is either the node's or the build tree
-               File f = new File("freenet.ini");
-               if(!f.exists())
-                       f = new File("build.xml");
-               BufferedInputStream bis1 =  new BufferedInputStream(new 
FileInputStream(f));
-               BufferedInputStream bis2 =  new BufferedInputStream(new 
FileInputStream(f));
-               LineReadingInputStream lris1 = new LineReadingInputStream(bis1);
-               LineReadingInputStream lris2 = new LineReadingInputStream(bis2);
-               
-               while(bis1.available() > 0 || bis2.available() > 0) {
-                       String stringWithoutMark 
=lris2.readLineWithoutMarking(MAX_LENGTH*10, BUFFER_SIZE, true);
-                       String stringWithMark = lris1.readLine(MAX_LENGTH*10, 
BUFFER_SIZE, true);
-                       assertEquals(stringWithMark, stringWithoutMark);
-               }
-               assertNull(lris1.readLine(MAX_LENGTH, BUFFER_SIZE, true));
-               assertNull(lris2.readLineWithoutMarking(MAX_LENGTH, 
BUFFER_SIZE, true));
-       }
-}

Copied: 
branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java 
(from rev 21939, 
trunk/freenet/test/freenet/support/io/LineReadingInputStreamTest.java)
===================================================================
--- 
branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java   
                            (rev 0)
+++ 
branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java   
    2008-09-24 20:42:20 UTC (rev 22823)
@@ -0,0 +1,106 @@
+/* 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.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import junit.framework.TestCase;
+
+public class LineReadingInputStreamTest extends TestCase {
+       public static final String BLOCK = 
"\ntesting1\ntesting2\r\ntesting3\n\n";
+       public static final String[] LINES = new String[] {
+               "",
+               "testing1",
+               "testing2",
+               "testing3",
+               ""
+       };
+       
+       public static final String STRESSED_LINE = "\n\u0114\n";
+       
+       public static final int MAX_LENGTH = 128;
+       public static final int BUFFER_SIZE = 128;
+       
+       public void testReadLineWithoutMarking() throws Exception {
+               // try utf8
+               InputStream is = new 
ByteArrayInputStream(STRESSED_LINE.getBytes("utf-8"));
+               LineReadingInputStream instance = new 
LineReadingInputStream(is);
+               assertEquals("", instance.readLineWithoutMarking(MAX_LENGTH, 
BUFFER_SIZE, true));
+               assertEquals("\u0114", 
instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, true));
+               assertNull(instance.readLineWithoutMarking(MAX_LENGTH, 
BUFFER_SIZE, true));
+               
+               // try ISO-8859-1
+               is = new ByteArrayInputStream(BLOCK.getBytes("ISO-8859-1"));
+               instance = new LineReadingInputStream(is);
+               for(String expectedLine : LINES) {
+                       assertEquals(expectedLine, 
instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, false));
+               }
+               assertNull(instance.readLineWithoutMarking(MAX_LENGTH, 
BUFFER_SIZE, false));
+               
+               // is it returning null?
+               is = new NullInputStream();
+               instance = new LineReadingInputStream(is);
+               assertNull(instance.readLineWithoutMarking(0, BUFFER_SIZE, 
false));
+               
+               // is it throwing?
+               is = new ByteArrayInputStream("aaa\na\n".getBytes());
+               instance = new LineReadingInputStream(is);
+               try {
+                       instance.readLineWithoutMarking(2, BUFFER_SIZE, true);
+                       fail();
+               } catch (TooLongException e) {}
+       }
+       
+       public void testReadLine() throws Exception {
+               // try utf8
+               InputStream is = new 
ByteArrayInputStream(STRESSED_LINE.getBytes("utf-8"));
+               LineReadingInputStream instance = new 
LineReadingInputStream(is);
+               assertEquals("", instance.readLine(MAX_LENGTH, BUFFER_SIZE, 
true));
+               assertEquals("\u0114", instance.readLine(MAX_LENGTH, 
BUFFER_SIZE, true));
+               assertNull(instance.readLine(MAX_LENGTH, BUFFER_SIZE, true));
+               
+               // try ISO-8859-1
+               is = new ByteArrayInputStream(BLOCK.getBytes("ISO-8859-1"));
+               instance = new LineReadingInputStream(is);
+               for(String expectedLine : LINES) {
+                       assertEquals(expectedLine, 
instance.readLine(MAX_LENGTH, BUFFER_SIZE, false));
+               }
+               assertNull(instance.readLine(MAX_LENGTH, BUFFER_SIZE, false));
+               
+               // is it returning null?
+               is = new NullInputStream();
+               instance = new LineReadingInputStream(is);
+               assertNull(instance.readLine(0, BUFFER_SIZE, false));
+               
+               // is it throwing?
+               is = new ByteArrayInputStream("aaa\na\n".getBytes());
+               instance = new LineReadingInputStream(is);
+               try {
+                       instance.readLine(2, BUFFER_SIZE, true);
+                       fail();
+               } catch (TooLongException e) {}
+       }
+
+       public void testBothImplementation() throws Exception {
+               // CWD is either the node's or the build tree
+               File f = new File("freenet.ini");
+               if(!f.exists())
+                       f = new File("build.xml");
+               BufferedInputStream bis1 =  new BufferedInputStream(new 
FileInputStream(f));
+               BufferedInputStream bis2 =  new BufferedInputStream(new 
FileInputStream(f));
+               LineReadingInputStream lris1 = new LineReadingInputStream(bis1);
+               LineReadingInputStream lris2 = new LineReadingInputStream(bis2);
+               
+               while(bis1.available() > 0 || bis2.available() > 0) {
+                       String stringWithoutMark 
=lris2.readLineWithoutMarking(MAX_LENGTH*10, BUFFER_SIZE, true);
+                       String stringWithMark = lris1.readLine(MAX_LENGTH*10, 
BUFFER_SIZE, true);
+                       assertEquals(stringWithMark, stringWithoutMark);
+               }
+               assertNull(lris1.readLine(MAX_LENGTH, BUFFER_SIZE, true));
+               assertNull(lris2.readLineWithoutMarking(MAX_LENGTH, 
BUFFER_SIZE, true));
+       }
+}


Reply via email to