Author: toad
Date: 2006-07-25 16:18:57 +0000 (Tue, 25 Jul 2006)
New Revision: 9752

Added:
   trunk/freenet/src/freenet/support/io/ArrayBucket.java
   trunk/freenet/src/freenet/support/io/ArrayBucketFactory.java
   trunk/freenet/src/freenet/support/io/Bucket.java
   trunk/freenet/src/freenet/support/io/BucketFactory.java
   trunk/freenet/src/freenet/support/io/BucketTools.java
   trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java
   
trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java
   trunk/freenet/src/freenet/support/io/RandomAccessFileBucket.java
   trunk/freenet/src/freenet/support/io/ReadOnlyFileSliceBucket.java
Removed:
   trunk/freenet/src/freenet/support/ArrayBucket.java
   trunk/freenet/src/freenet/support/ArrayBucketFactory.java
   trunk/freenet/src/freenet/support/Bucket.java
   trunk/freenet/src/freenet/support/BucketFactory.java
   trunk/freenet/src/freenet/support/BucketTools.java
   trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
   
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java
   trunk/freenet/src/freenet/support/RandomAccessFileBucket.java
   trunk/freenet/src/freenet/support/ReadOnlyFileSliceBucket.java
Modified:
   trunk/freenet/src/freenet/client/ArchiveHandler.java
   trunk/freenet/src/freenet/client/ArchiveManager.java
   trunk/freenet/src/freenet/client/ArchiveStoreContext.java
   trunk/freenet/src/freenet/client/ArchiveStoreItem.java
   trunk/freenet/src/freenet/client/ErrorArchiveStoreItem.java
   trunk/freenet/src/freenet/client/FECCodec.java
   trunk/freenet/src/freenet/client/FetchResult.java
   trunk/freenet/src/freenet/client/FetcherContext.java
   trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
   trunk/freenet/src/freenet/client/InsertBlock.java
   trunk/freenet/src/freenet/client/InserterContext.java
   trunk/freenet/src/freenet/client/Metadata.java
   trunk/freenet/src/freenet/client/RealArchiveStoreItem.java
   trunk/freenet/src/freenet/client/SplitfileBlock.java
   trunk/freenet/src/freenet/client/StandardOnionFECCodec.java
   trunk/freenet/src/freenet/client/TempStoreElement.java
   trunk/freenet/src/freenet/client/async/ClientGetter.java
   trunk/freenet/src/freenet/client/async/ClientPutter.java
   trunk/freenet/src/freenet/client/async/ManifestElement.java
   trunk/freenet/src/freenet/client/async/MinimalSplitfileBlock.java
   trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
   trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
   trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
   trunk/freenet/src/freenet/client/async/SingleFileInserter.java
   trunk/freenet/src/freenet/client/async/SplitFileFetcher.java
   trunk/freenet/src/freenet/client/async/SplitFileFetcherSegment.java
   trunk/freenet/src/freenet/client/async/SplitFileInserter.java
   trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java
   trunk/freenet/src/freenet/client/async/USKFetcher.java
   trunk/freenet/src/freenet/client/async/USKInserter.java
   trunk/freenet/src/freenet/clients/http/ConfigToadlet.java
   trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
   trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
   trunk/freenet/src/freenet/clients/http/HTTPRequest.java
   trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java
   trunk/freenet/src/freenet/clients/http/NinjaSpider.java
   trunk/freenet/src/freenet/clients/http/PluginToadlet.java
   trunk/freenet/src/freenet/clients/http/PproxyToadlet.java
   trunk/freenet/src/freenet/clients/http/QueueToadlet.java
   trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
   trunk/freenet/src/freenet/clients/http/Spider.java
   trunk/freenet/src/freenet/clients/http/StaticToadlet.java
   trunk/freenet/src/freenet/clients/http/Toadlet.java
   trunk/freenet/src/freenet/clients/http/ToadletContext.java
   trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java
   trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java
   trunk/freenet/src/freenet/clients/http/filter/CSSReadFilter.java
   trunk/freenet/src/freenet/clients/http/filter/CharsetExtractor.java
   trunk/freenet/src/freenet/clients/http/filter/ContentDataFilter.java
   trunk/freenet/src/freenet/clients/http/filter/ContentFilter.java
   trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
   trunk/freenet/src/freenet/keys/ClientCHKBlock.java
   trunk/freenet/src/freenet/keys/ClientKeyBlock.java
   trunk/freenet/src/freenet/keys/ClientSSKBlock.java
   trunk/freenet/src/freenet/keys/InsertableClientSSK.java
   trunk/freenet/src/freenet/keys/Key.java
   trunk/freenet/src/freenet/node/ARKFetcher.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/TextModeClientInterface.java
   trunk/freenet/src/freenet/node/fcp/AllDataMessage.java
   trunk/freenet/src/freenet/node/fcp/BaseDataCarryingMessage.java
   trunk/freenet/src/freenet/node/fcp/ClientGet.java
   trunk/freenet/src/freenet/node/fcp/ClientPut.java
   trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
   trunk/freenet/src/freenet/node/fcp/ClientPutDir.java
   trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
   trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java
   trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java
   trunk/freenet/src/freenet/node/fcp/DirPutFile.java
   trunk/freenet/src/freenet/node/fcp/DirectDirPutFile.java
   trunk/freenet/src/freenet/node/fcp/DiskDirPutFile.java
   trunk/freenet/src/freenet/node/fcp/FCPConnectionHandler.java
   trunk/freenet/src/freenet/node/fcp/FCPMessage.java
   trunk/freenet/src/freenet/node/fcp/FCPServer.java
   trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java
   trunk/freenet/src/freenet/node/fcp/RedirectDirPutFile.java
   trunk/freenet/src/freenet/node/updater/NodeUpdater.java
   trunk/freenet/src/freenet/support/SimpleReadOnlyArrayBucket.java
   trunk/freenet/src/freenet/support/compress/Compressor.java
   trunk/freenet/src/freenet/support/compress/GzipCompressor.java
   trunk/freenet/src/freenet/support/io/FileBucket.java
   trunk/freenet/src/freenet/support/io/FileBucketFactory.java
   trunk/freenet/src/freenet/support/io/NullBucket.java
   
trunk/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java
   trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
   trunk/freenet/src/freenet/support/io/SerializableToFieldSetBucket.java
   trunk/freenet/src/freenet/support/io/SerializableToFieldSetBucketUtil.java
   trunk/freenet/src/freenet/support/io/TempBucketFactory.java
Log:
Move some Bucket's to freenet/support/io.

Modified: trunk/freenet/src/freenet/client/ArchiveHandler.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveHandler.java        2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/ArchiveHandler.java        2006-07-25 
16:18:57 UTC (rev 9752)
@@ -1,6 +1,6 @@
 package freenet.client;

-import freenet.support.Bucket;
+import freenet.support.io.Bucket;

 /**
  * The public face (to Fetcher, for example) of ArchiveStoreContext.

Modified: trunk/freenet/src/freenet/client/ArchiveManager.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveManager.java        2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/ArchiveManager.java        2006-07-25 
16:18:57 UTC (rev 9752)
@@ -12,13 +12,13 @@

 import freenet.crypt.RandomSource;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.LRUHashtable;
 import freenet.support.Logger;
-import freenet.support.PaddedEphemerallyEncryptedBucket;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;
 import freenet.support.io.FileBucket;
 import freenet.support.io.FilenameGenerator;
+import freenet.support.io.PaddedEphemerallyEncryptedBucket;

 /**
  * Cache of recently decoded archives:

Modified: trunk/freenet/src/freenet/client/ArchiveStoreContext.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveStoreContext.java   2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/ArchiveStoreContext.java   2006-07-25 
16:18:57 UTC (rev 9752)
@@ -1,9 +1,9 @@
 package freenet.client;

 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
 import freenet.support.DoublyLinkedListImpl;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;

 /**
  * Tracks all files currently in the cache from a given key.

Modified: trunk/freenet/src/freenet/client/ArchiveStoreItem.java
===================================================================
--- trunk/freenet/src/freenet/client/ArchiveStoreItem.java      2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/ArchiveStoreItem.java      2006-07-25 
16:18:57 UTC (rev 9752)
@@ -1,7 +1,7 @@
 package freenet.client;

-import freenet.support.Bucket;
 import freenet.support.DoublyLinkedListImpl;
+import freenet.support.io.Bucket;

 /**
  * Base class for items stored in the archive cache.

Modified: trunk/freenet/src/freenet/client/ErrorArchiveStoreItem.java
===================================================================
--- trunk/freenet/src/freenet/client/ErrorArchiveStoreItem.java 2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/ErrorArchiveStoreItem.java 2006-07-25 
16:18:57 UTC (rev 9752)
@@ -1,7 +1,7 @@
 package freenet.client;

 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
+import freenet.support.io.Bucket;

 class ErrorArchiveStoreItem extends ArchiveStoreItem {


Modified: trunk/freenet/src/freenet/client/FECCodec.java
===================================================================
--- trunk/freenet/src/freenet/client/FECCodec.java      2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/client/FECCodec.java      2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -2,8 +2,8 @@

 import java.io.IOException;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;

 /**
  * FEC (forward error correction) handler.

Modified: trunk/freenet/src/freenet/client/FetchResult.java
===================================================================
--- trunk/freenet/src/freenet/client/FetchResult.java   2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/client/FetchResult.java   2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -2,8 +2,8 @@

 import java.io.IOException;

-import freenet.support.Bucket;
-import freenet.support.BucketTools;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;

 /**
  * Class to contain the result of a key fetch.

Modified: trunk/freenet/src/freenet/client/FetcherContext.java
===================================================================
--- trunk/freenet/src/freenet/client/FetcherContext.java        2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/FetcherContext.java        2006-07-25 
16:18:57 UTC (rev 9752)
@@ -4,7 +4,7 @@
 import freenet.client.events.ClientEventProducer;
 import freenet.client.events.SimpleEventProducer;
 import freenet.crypt.RandomSource;
-import freenet.support.BucketFactory;
+import freenet.support.io.BucketFactory;

 /** Context for a Fetcher. Contains all the settings a Fetcher needs to know 
about. */
 public class FetcherContext implements Cloneable {

Modified: trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/HighLevelSimpleClientImpl.java     
2006-07-25 16:18:57 UTC (rev 9752)
@@ -13,10 +13,10 @@
 import freenet.crypt.RandomSource;
 import freenet.keys.FreenetURI;
 import freenet.node.Node;
-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
-import freenet.support.BucketTools;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
+import freenet.support.io.BucketTools;
 import freenet.support.io.NullPersistentFileTracker;
 import freenet.support.io.PersistentFileTracker;


Modified: trunk/freenet/src/freenet/client/InsertBlock.java
===================================================================
--- trunk/freenet/src/freenet/client/InsertBlock.java   2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/client/InsertBlock.java   2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -1,7 +1,7 @@
 package freenet.client;

 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
+import freenet.support.io.Bucket;

 /**
  * Class to contain everything needed for an insert.

Modified: trunk/freenet/src/freenet/client/InserterContext.java
===================================================================
--- trunk/freenet/src/freenet/client/InserterContext.java       2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/InserterContext.java       2006-07-25 
16:18:57 UTC (rev 9752)
@@ -4,7 +4,7 @@
 import freenet.client.events.ClientEventProducer;
 import freenet.client.events.SimpleEventProducer;
 import freenet.crypt.RandomSource;
-import freenet.support.BucketFactory;
+import freenet.support.io.BucketFactory;
 import freenet.support.io.NullPersistentFileTracker;
 import freenet.support.io.PersistentFileTracker;


Modified: trunk/freenet/src/freenet/client/Metadata.java
===================================================================
--- trunk/freenet/src/freenet/client/Metadata.java      2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/client/Metadata.java      2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -14,11 +14,11 @@
 import freenet.keys.BaseClientKey;
 import freenet.keys.ClientCHK;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
-import freenet.support.BucketTools;
 import freenet.support.Fields;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
+import freenet.support.io.BucketTools;


 /** Metadata parser/writer class. */

Modified: trunk/freenet/src/freenet/client/RealArchiveStoreItem.java
===================================================================
--- trunk/freenet/src/freenet/client/RealArchiveStoreItem.java  2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/RealArchiveStoreItem.java  2006-07-25 
16:18:57 UTC (rev 9752)
@@ -3,10 +3,10 @@
 import java.io.File;

 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
-import freenet.support.PaddedEphemerallyEncryptedBucket;
+import freenet.support.io.Bucket;
 import freenet.support.io.FileBucket;
 import freenet.support.io.FileUtil;
+import freenet.support.io.PaddedEphemerallyEncryptedBucket;

 class RealArchiveStoreItem extends ArchiveStoreItem {


Modified: trunk/freenet/src/freenet/client/SplitfileBlock.java
===================================================================
--- trunk/freenet/src/freenet/client/SplitfileBlock.java        2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/SplitfileBlock.java        2006-07-25 
16:18:57 UTC (rev 9752)
@@ -1,6 +1,6 @@
 package freenet.client;

-import freenet.support.Bucket;
+import freenet.support.io.Bucket;

 public interface SplitfileBlock {


Modified: trunk/freenet/src/freenet/client/StandardOnionFECCodec.java
===================================================================
--- trunk/freenet/src/freenet/client/StandardOnionFECCodec.java 2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/StandardOnionFECCodec.java 2006-07-25 
16:18:57 UTC (rev 9752)
@@ -10,11 +10,11 @@
 import com.onionnetworks.fec.FECCodeFactory;
 import com.onionnetworks.util.Buffer;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
-import freenet.support.BucketTools;
 import freenet.support.LRUHashtable;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
+import freenet.support.io.BucketTools;

 /**
  * FECCodec implementation using the onion code.

Modified: trunk/freenet/src/freenet/client/TempStoreElement.java
===================================================================
--- trunk/freenet/src/freenet/client/TempStoreElement.java      2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/TempStoreElement.java      2006-07-25 
16:18:57 UTC (rev 9752)
@@ -5,8 +5,8 @@

 import java.io.File;

-import freenet.support.PaddedEphemerallyEncryptedBucket;
 import freenet.support.io.FileBucket;
+import freenet.support.io.PaddedEphemerallyEncryptedBucket;

 class TempStoreElement {
        TempStoreElement(File myFile, FileBucket fb, 
PaddedEphemerallyEncryptedBucket encryptedBucket) {

Modified: trunk/freenet/src/freenet/client/async/ClientGetter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientGetter.java    2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/ClientGetter.java    2006-07-25 
16:18:57 UTC (rev 9752)
@@ -10,9 +10,9 @@
 import freenet.client.FetcherContext;
 import freenet.client.events.SplitfileProgressEvent;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;

 /**
  * A high level data request.

Modified: trunk/freenet/src/freenet/client/async/ClientPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientPutter.java    2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/ClientPutter.java    2006-07-25 
16:18:57 UTC (rev 9752)
@@ -8,9 +8,9 @@
 import freenet.client.events.SplitfileProgressEvent;
 import freenet.keys.BaseClientKey;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;

 public class ClientPutter extends BaseClientPutter implements 
PutCompletionCallback {


Modified: trunk/freenet/src/freenet/client/async/ManifestElement.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ManifestElement.java 2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/ManifestElement.java 2006-07-25 
16:18:57 UTC (rev 9752)
@@ -1,7 +1,7 @@
 package freenet.client.async;

 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
+import freenet.support.io.Bucket;

 /**
  * Represents an element in a manifest. Fed to SimpleManifestPutter.

Modified: trunk/freenet/src/freenet/client/async/MinimalSplitfileBlock.java
===================================================================
--- trunk/freenet/src/freenet/client/async/MinimalSplitfileBlock.java   
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/MinimalSplitfileBlock.java   
2006-07-25 16:18:57 UTC (rev 9752)
@@ -1,7 +1,7 @@
 package freenet.client.async;

 import freenet.client.SplitfileBlock;
-import freenet.support.Bucket;
+import freenet.support.io.Bucket;

 public class MinimalSplitfileBlock implements SplitfileBlock {


Modified: trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java    
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/SimpleManifestPutter.java    
2006-07-25 16:18:57 UTC (rev 9752)
@@ -21,9 +21,9 @@
 import freenet.client.events.SplitfileProgressEvent;
 import freenet.keys.BaseClientKey;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;

 public class SimpleManifestPutter extends BaseClientPutter implements 
PutCompletionCallback {
        // Only implements PutCompletionCallback for the final metadata insert

Modified: trunk/freenet/src/freenet/client/async/SingleBlockInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleBlockInserter.java     
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/SingleBlockInserter.java     
2006-07-25 16:18:57 UTC (rev 9752)
@@ -16,9 +16,9 @@
 import freenet.keys.SSKEncodeException;
 import freenet.node.LowLevelPutException;
 import freenet.node.Node;
-import freenet.support.Bucket;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;

 /**
  * Insert *ONE KEY*.

Modified: trunk/freenet/src/freenet/client/async/SingleFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileFetcher.java       
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/SingleFileFetcher.java       
2006-07-25 16:18:57 UTC (rev 9752)
@@ -23,11 +23,11 @@
 import freenet.keys.KeyDecodeException;
 import freenet.keys.USK;
 import freenet.node.LowLevelGetException;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.Logger;
 import freenet.support.compress.CompressionOutputSizeException;
 import freenet.support.compress.Compressor;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;

 public class SingleFileFetcher extends BaseSingleFileFetcher implements 
ClientGetState {


Modified: trunk/freenet/src/freenet/client/async/SingleFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SingleFileInserter.java      
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/SingleFileInserter.java      
2006-07-25 16:18:57 UTC (rev 9752)
@@ -15,12 +15,12 @@
 import freenet.keys.ClientCHKBlock;
 import freenet.keys.FreenetURI;
 import freenet.keys.SSKBlock;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
 import freenet.support.compress.CompressionOutputSizeException;
 import freenet.support.compress.Compressor;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;

 /**
  * Attempt to insert a file. May include metadata.

Modified: trunk/freenet/src/freenet/client/async/SplitFileFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileFetcher.java        
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/SplitFileFetcher.java        
2006-07-25 16:18:57 UTC (rev 9752)
@@ -12,11 +12,11 @@
 import freenet.client.Metadata;
 import freenet.client.MetadataParseException;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
 import freenet.support.Fields;
 import freenet.support.Logger;
 import freenet.support.compress.CompressionOutputSizeException;
 import freenet.support.compress.Compressor;
+import freenet.support.io.Bucket;

 /**
  * Fetch a splitfile, decompress it if need be, and return it to the 
GetCompletionCallback.

Modified: trunk/freenet/src/freenet/client/async/SplitFileFetcherSegment.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileFetcherSegment.java 
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/SplitFileFetcherSegment.java 
2006-07-25 16:18:57 UTC (rev 9752)
@@ -14,9 +14,9 @@
 import freenet.client.MetadataParseException;
 import freenet.client.SplitfileBlock;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;

 /**
  * A single segment within a SplitFileFetcher.

Modified: trunk/freenet/src/freenet/client/async/SplitFileInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileInserter.java       
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/SplitFileInserter.java       
2006-07-25 16:18:57 UTC (rev 9752)
@@ -11,11 +11,11 @@
 import freenet.client.Metadata;
 import freenet.keys.CHKBlock;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
 import freenet.support.compress.Compressor;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;

 public class SplitFileInserter implements ClientPutState {


Modified: trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java
===================================================================
--- trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java        
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/SplitFileInserterSegment.java        
2006-07-25 16:18:57 UTC (rev 9752)
@@ -11,10 +11,10 @@
 import freenet.keys.BaseClientKey;
 import freenet.keys.CHKBlock;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
 import freenet.support.Fields;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;
 import freenet.support.io.CannotCreateFromFieldSetException;
 import freenet.support.io.SerializableToFieldSetBucket;
 import freenet.support.io.SerializableToFieldSetBucketUtil;

Modified: trunk/freenet/src/freenet/client/async/USKFetcher.java
===================================================================
--- trunk/freenet/src/freenet/client/async/USKFetcher.java      2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/USKFetcher.java      2006-07-25 
16:18:57 UTC (rev 9752)
@@ -12,8 +12,8 @@
 import freenet.keys.KeyDecodeException;
 import freenet.keys.USK;
 import freenet.node.RequestStarter;
-import freenet.support.Bucket;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;

 /**
  * 

Modified: trunk/freenet/src/freenet/client/async/USKInserter.java
===================================================================
--- trunk/freenet/src/freenet/client/async/USKInserter.java     2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/client/async/USKInserter.java     2006-07-25 
16:18:57 UTC (rev 9752)
@@ -11,10 +11,10 @@
 import freenet.keys.FreenetURI;
 import freenet.keys.InsertableUSK;
 import freenet.keys.USK;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;

 /**
  * Insert a USK. The algorithm is simply to do a thorough search for the 
latest edition, and insert at the

Modified: trunk/freenet/src/freenet/clients/http/ConfigToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ConfigToadlet.java   2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/ConfigToadlet.java   2006-07-25 
16:18:57 UTC (rev 9752)
@@ -9,11 +9,11 @@
 import freenet.config.Option;
 import freenet.config.SubConfig;
 import freenet.node.Node;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;


 // FIXME: add logging, comments

Modified: trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/DarknetConnectionsToadlet.java       
2006-07-25 16:18:57 UTC (rev 9752)
@@ -17,10 +17,10 @@
 import freenet.node.FSParseException;
 import freenet.node.Node;
 import freenet.node.PeerNode;
-import freenet.support.Bucket;
 import freenet.support.HTMLEncoder;
 import freenet.support.MultiValueTable;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;

 public class DarknetConnectionsToadlet extends Toadlet {


Modified: trunk/freenet/src/freenet/clients/http/FProxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/FProxyToadlet.java   2006-07-25 
16:18:57 UTC (rev 9752)
@@ -25,13 +25,13 @@
 import freenet.node.Node;
 import freenet.node.RequestStarter;
 import freenet.support.Base64;
-import freenet.support.Bucket;
 import freenet.support.HTMLEncoder;
 import freenet.support.HexUtil;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
 import freenet.support.SizeUtil;
 import freenet.support.URLEncoder;
+import freenet.support.io.Bucket;

 public class FProxyToadlet extends Toadlet {


Modified: trunk/freenet/src/freenet/clients/http/HTTPRequest.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/HTTPRequest.java     2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/HTTPRequest.java     2006-07-25 
16:18:57 UTC (rev 9752)
@@ -14,13 +14,13 @@
 import java.util.Map;
 import java.util.StringTokenizer;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
-import freenet.support.BucketTools;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
 import freenet.support.URLDecoder;
 import freenet.support.URLEncodedFormatException;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
+import freenet.support.io.BucketTools;
 import freenet.support.io.LineReadingInputStream;

 /**

Modified: trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java    2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/N2NTMToadlet.java    2006-07-25 
16:18:57 UTC (rev 9752)
@@ -10,10 +10,10 @@
 import freenet.io.comm.UdpSocketManager;
 import freenet.node.Node;
 import freenet.node.PeerNode;
-import freenet.support.Bucket;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
+import freenet.support.io.Bucket;

 public class N2NTMToadlet extends Toadlet {


Modified: trunk/freenet/src/freenet/clients/http/NinjaSpider.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/NinjaSpider.java     2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/NinjaSpider.java     2006-07-25 
16:18:57 UTC (rev 9752)
@@ -46,10 +46,10 @@
 import freenet.node.RequestStarter;
 import freenet.plugin.HttpPlugin;
 import freenet.plugin.PluginManager;
-import freenet.support.Bucket;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
+import freenet.support.io.Bucket;

 /**
  * NinjaSpider. Produces a ninj^W err ... an XML index.

Modified: trunk/freenet/src/freenet/clients/http/PluginToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/PluginToadlet.java   2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/PluginToadlet.java   2006-07-25 
16:18:57 UTC (rev 9752)
@@ -11,9 +11,9 @@
 import freenet.plugin.HttpPlugin;
 import freenet.plugin.Plugin;
 import freenet.plugin.PluginManager;
-import freenet.support.Bucket;
 import freenet.support.HTMLEncoder;
 import freenet.support.MultiValueTable;
+import freenet.support.io.Bucket;

 /**
  * Toadlet for the plugin manager.
@@ -98,7 +98,7 @@
        }

        /**
-        * @see freenet.clients.http.Toadlet#handlePost(java.net.URI, 
freenet.support.Bucket, freenet.clients.http.ToadletContext)
+        * @see freenet.clients.http.Toadlet#handlePost(java.net.URI, 
freenet.support.io.Bucket, freenet.clients.http.ToadletContext)
         */
        public void handlePost(URI uri, Bucket data, ToadletContext ctx) throws 
ToadletContextClosedException, IOException, RedirectException {
                HTTPRequest httpRequest = new HTTPRequest(uri, data, ctx);

Modified: trunk/freenet/src/freenet/clients/http/PproxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/PproxyToadlet.java   2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/PproxyToadlet.java   2006-07-25 
16:18:57 UTC (rev 9752)
@@ -13,11 +13,11 @@
 import freenet.pluginmanager.PluginHTTPException;
 import freenet.pluginmanager.PluginInfoWrapper;
 import freenet.pluginmanager.PluginManager;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;

 public class PproxyToadlet extends Toadlet {
        private final PluginManager pm;

Modified: trunk/freenet/src/freenet/clients/http/QueueToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/QueueToadlet.java    2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/QueueToadlet.java    2006-07-25 
16:18:57 UTC (rev 9752)
@@ -17,13 +17,13 @@
 import freenet.node.fcp.FCPServer;
 import freenet.node.fcp.MessageInvalidException;
 import freenet.node.Node;
-import freenet.support.Bucket;
 import freenet.support.HTMLDecoder;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
 import freenet.support.SizeUtil;
 import freenet.support.URLEncoder;
+import freenet.support.io.Bucket;

 public class QueueToadlet extends Toadlet {


Modified: trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java     
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/SimpleToadletServer.java     
2006-07-25 16:18:57 UTC (rev 9752)
@@ -26,10 +26,10 @@
 import freenet.crypt.DummyRandomSource;
 import freenet.io.NetworkInterface;
 import freenet.node.Node;
-import freenet.support.BucketFactory;
 import freenet.support.FileLoggerHook;
 import freenet.support.Logger;
 import freenet.support.FileLoggerHook.IntervalParseException;
+import freenet.support.io.BucketFactory;
 import freenet.support.io.FilenameGenerator;
 import freenet.support.io.TempBucketFactory;


Modified: trunk/freenet/src/freenet/clients/http/Spider.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/Spider.java  2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/clients/http/Spider.java  2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -35,10 +35,10 @@
 import freenet.node.RequestStarter;
 import freenet.plugin.HttpPlugin;
 import freenet.plugin.PluginManager;
-import freenet.support.Bucket;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
+import freenet.support.io.Bucket;

 /**
  * Spider. Produces an index.

Modified: trunk/freenet/src/freenet/clients/http/StaticToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/StaticToadlet.java   2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/StaticToadlet.java   2006-07-25 
16:18:57 UTC (rev 9752)
@@ -7,7 +7,7 @@

 import freenet.client.DefaultMIMETypes;
 import freenet.client.HighLevelSimpleClient;
-import freenet.support.Bucket;
+import freenet.support.io.Bucket;

 /**
  * Static Toadlet.

Modified: trunk/freenet/src/freenet/clients/http/Toadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/Toadlet.java 2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/clients/http/Toadlet.java 2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -10,11 +10,11 @@
 import freenet.client.InsertBlock;
 import freenet.client.InserterException;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;

 /**
  * Replacement for servlets. Just an easy to use HTTP interface, which is

Modified: trunk/freenet/src/freenet/clients/http/ToadletContext.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ToadletContext.java  2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/ToadletContext.java  2006-07-25 
16:18:57 UTC (rev 9752)
@@ -2,9 +2,9 @@

 import java.io.IOException;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
 import freenet.support.MultiValueTable;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;

 /**
  * Object represents context for a single request. Is used as a token,

Modified: trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java      
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java      
2006-07-25 16:18:57 UTC (rev 9752)
@@ -11,11 +11,11 @@
 import java.util.Enumeration;
 import java.util.TimeZone;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
-import freenet.support.BucketTools;
 import freenet.support.Logger;
 import freenet.support.MultiValueTable;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
+import freenet.support.io.BucketTools;
 import freenet.support.io.LineReadingInputStream;
 import freenet.support.io.TooLongException;


Modified: trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java  2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/WelcomeToadlet.java  2006-07-25 
16:18:57 UTC (rev 9752)
@@ -16,9 +16,9 @@
 import freenet.node.NodeStarter;
 import freenet.node.Version;
 import freenet.node.useralerts.UserAlert;
-import freenet.support.Bucket;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;

 public class WelcomeToadlet extends Toadlet {
        private final static int MODE_ADD = 1;

Modified: trunk/freenet/src/freenet/clients/http/filter/CSSReadFilter.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/CSSReadFilter.java    
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/filter/CSSReadFilter.java    
2006-07-25 16:18:57 UTC (rev 9752)
@@ -12,10 +12,10 @@
 import java.io.Writer;
 import java.util.HashMap;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
 import freenet.support.io.NullWriter;

 public class CSSReadFilter implements ContentDataFilter, CharsetExtractor {

Modified: trunk/freenet/src/freenet/clients/http/filter/CharsetExtractor.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/CharsetExtractor.java 
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/filter/CharsetExtractor.java 
2006-07-25 16:18:57 UTC (rev 9752)
@@ -2,7 +2,7 @@

 import java.io.IOException;

-import freenet.support.Bucket;
+import freenet.support.io.Bucket;

 /**
  * For a specific text/-based MIME type, extracts the charset if

Modified: trunk/freenet/src/freenet/clients/http/filter/ContentDataFilter.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/ContentDataFilter.java        
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/filter/ContentDataFilter.java        
2006-07-25 16:18:57 UTC (rev 9752)
@@ -3,8 +3,8 @@
 import java.io.IOException;
 import java.util.HashMap;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;

 /**
  * Data filter for a specific MIME type.

Modified: trunk/freenet/src/freenet/clients/http/filter/ContentFilter.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/ContentFilter.java    
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/filter/ContentFilter.java    
2006-07-25 16:18:57 UTC (rev 9752)
@@ -8,9 +8,9 @@
 import java.util.HashMap;
 import java.util.Hashtable;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;

 /**
  * Freenet content filter. This doesn't actually do any filtering,

Modified: trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java       
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java       
2006-07-25 16:18:57 UTC (rev 9752)
@@ -22,11 +22,11 @@
 import java.util.StringTokenizer;
 import java.util.Vector;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
 import freenet.support.HTMLDecoder;
 import freenet.support.HTMLEncoder;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
 import freenet.support.io.NullBucket;
 import freenet.support.io.NullWriter;


Modified: trunk/freenet/src/freenet/keys/ClientCHKBlock.java
===================================================================
--- trunk/freenet/src/freenet/keys/ClientCHKBlock.java  2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/keys/ClientCHKBlock.java  2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -13,11 +13,11 @@
 import freenet.crypt.ciphers.Rijndael;
 import freenet.keys.Key.Compressed;
 import freenet.node.Node;
-import freenet.support.ArrayBucket;
-import freenet.support.ArrayBucketFactory;
-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
-import freenet.support.BucketTools;
+import freenet.support.io.ArrayBucket;
+import freenet.support.io.ArrayBucketFactory;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
+import freenet.support.io.BucketTools;

 /**
  * @author amphibian

Modified: trunk/freenet/src/freenet/keys/ClientKeyBlock.java
===================================================================
--- trunk/freenet/src/freenet/keys/ClientKeyBlock.java  2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/keys/ClientKeyBlock.java  2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -2,8 +2,8 @@

 import java.io.IOException;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;

 public interface ClientKeyBlock {


Modified: trunk/freenet/src/freenet/keys/ClientSSKBlock.java
===================================================================
--- trunk/freenet/src/freenet/keys/ClientSSKBlock.java  2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/keys/ClientSSKBlock.java  2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -5,9 +5,9 @@
 import freenet.crypt.PCFBMode;
 import freenet.crypt.UnsupportedCipherException;
 import freenet.crypt.ciphers.Rijndael;
-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
-import freenet.support.BucketTools;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
+import freenet.support.io.BucketTools;

 public class ClientSSKBlock extends SSKBlock implements ClientKeyBlock {


Modified: trunk/freenet/src/freenet/keys/InsertableClientSSK.java
===================================================================
--- trunk/freenet/src/freenet/keys/InsertableClientSSK.java     2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/keys/InsertableClientSSK.java     2006-07-25 
16:18:57 UTC (rev 9752)
@@ -20,7 +20,7 @@
 import freenet.crypt.UnsupportedCipherException;
 import freenet.crypt.ciphers.Rijndael;
 import freenet.keys.Key.Compressed;
-import freenet.support.Bucket;
+import freenet.support.io.Bucket;

 public class InsertableClientSSK extends ClientSSK {


Modified: trunk/freenet/src/freenet/keys/Key.java
===================================================================
--- trunk/freenet/src/freenet/keys/Key.java     2006-07-25 16:14:02 UTC (rev 
9751)
+++ trunk/freenet/src/freenet/keys/Key.java     2006-07-25 16:18:57 UTC (rev 
9752)
@@ -7,16 +7,16 @@
 import java.security.NoSuchAlgorithmException;

 import freenet.io.WritableToDataOutputStream;
-import freenet.support.ArrayBucket;
-import freenet.support.ArrayBucketFactory;
-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
-import freenet.support.BucketTools;
 import freenet.support.Fields;
 import freenet.support.Logger;
 import freenet.support.SimpleReadOnlyArrayBucket;
 import freenet.support.compress.CompressionOutputSizeException;
 import freenet.support.compress.Compressor;
+import freenet.support.io.ArrayBucket;
+import freenet.support.io.ArrayBucketFactory;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
+import freenet.support.io.BucketTools;

 /**
  * @author amphibian

Modified: trunk/freenet/src/freenet/node/ARKFetcher.java
===================================================================
--- trunk/freenet/src/freenet/node/ARKFetcher.java      2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/node/ARKFetcher.java      2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -11,9 +11,9 @@
 import freenet.client.async.ClientGetter;
 import freenet.keys.FreenetURI;
 import freenet.keys.USK;
-import freenet.support.ArrayBucket;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.ArrayBucket;

 /**
  * Fetch an ARK. Permanent, tied to a PeerNode, stops itself after a 
successful fetch.

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-07-25 16:14:02 UTC (rev 
9751)
+++ trunk/freenet/src/freenet/node/Node.java    2006-07-25 16:18:57 UTC (rev 
9752)
@@ -107,8 +107,6 @@
 import freenet.store.FreenetStore;
 import freenet.store.KeyCollisionException;
 import freenet.support.Base64;
-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
 import freenet.support.DoubleTokenBucket;
 import freenet.support.Fields;
 import freenet.support.FileLoggerHook;
@@ -118,11 +116,13 @@
 import freenet.support.LRUHashtable;
 import freenet.support.LRUQueue;
 import freenet.support.Logger;
-import freenet.support.PaddedEphemerallyEncryptedBucketFactory;
 import freenet.support.SimpleFieldSet;
 import freenet.support.SimpleReadOnlyArrayBucket;
 import freenet.support.TokenBucket;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
 import freenet.support.io.FilenameGenerator;
+import freenet.support.io.PaddedEphemerallyEncryptedBucketFactory;
 import freenet.support.io.PersistentEncryptedTempBucketFactory;
 import freenet.support.io.PersistentTempBucketFactory;
 import freenet.support.io.TempBucketFactory;

Modified: trunk/freenet/src/freenet/node/TextModeClientInterface.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-07-25 
16:18:57 UTC (rev 9752)
@@ -32,12 +32,12 @@
 import freenet.io.comm.PeerParseException;
 import freenet.keys.FreenetURI;
 import freenet.keys.InsertableClientSSK;
-import freenet.support.ArrayBucket;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.HexUtil;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.ArrayBucket;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;
 import freenet.support.io.FileBucket;

 /**

Modified: trunk/freenet/src/freenet/node/fcp/AllDataMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/AllDataMessage.java      2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/AllDataMessage.java      2006-07-25 
16:18:57 UTC (rev 9752)
@@ -1,8 +1,8 @@
 package freenet.node.fcp;

 import freenet.node.Node;
-import freenet.support.Bucket;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;

 /**
  * All the data, all in one big chunk. Obviously we must already have

Modified: trunk/freenet/src/freenet/node/fcp/BaseDataCarryingMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/BaseDataCarryingMessage.java     
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/BaseDataCarryingMessage.java     
2006-07-25 16:18:57 UTC (rev 9752)
@@ -4,7 +4,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;

-import freenet.support.BucketFactory;
+import freenet.support.io.BucketFactory;

 public abstract class BaseDataCarryingMessage extends FCPMessage {


Modified: trunk/freenet/src/freenet/node/fcp/ClientGet.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientGet.java   2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/ClientGet.java   2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -17,15 +17,15 @@
 import freenet.client.events.ClientEventListener;
 import freenet.client.events.SplitfileProgressEvent;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
-import freenet.support.BucketTools;
 import freenet.support.Fields;
 import freenet.support.HexUtil;
 import freenet.support.Logger;
-import freenet.support.PaddedEphemerallyEncryptedBucket;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketTools;
 import freenet.support.io.FileBucket;
 import freenet.support.io.NullBucket;
+import freenet.support.io.PaddedEphemerallyEncryptedBucket;

 /**
  * A simple client fetch. This can of course fetch arbitrarily large

Modified: trunk/freenet/src/freenet/node/fcp/ClientPut.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPut.java   2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/ClientPut.java   2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -9,13 +9,13 @@
 import freenet.client.MetadataUnresolvedException;
 import freenet.client.async.ClientPutter;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
 import freenet.support.HexUtil;
 import freenet.support.Logger;
-import freenet.support.PaddedEphemerallyEncryptedBucket;
 import freenet.support.SimpleFieldSet;
 import freenet.support.SimpleReadOnlyArrayBucket;
+import freenet.support.io.Bucket;
 import freenet.support.io.FileBucket;
+import freenet.support.io.PaddedEphemerallyEncryptedBucket;

 public class ClientPut extends ClientPutBase {


Modified: trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java  
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java  
2006-07-25 16:18:57 UTC (rev 9752)
@@ -9,9 +9,9 @@

 import freenet.client.async.ManifestElement;
 import freenet.node.Node;
-import freenet.support.BucketFactory;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.BucketFactory;
 import freenet.support.io.PersistentTempBucketFactory;

 /**

Modified: trunk/freenet/src/freenet/node/fcp/ClientPutDir.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutDir.java        2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutDir.java        2006-07-25 
16:18:57 UTC (rev 9752)
@@ -13,12 +13,12 @@
 import freenet.client.async.SimpleManifestPutter;
 import freenet.client.events.ClientEventListener;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
 import freenet.support.HexUtil;
 import freenet.support.Logger;
-import freenet.support.PaddedEphemerallyEncryptedBucket;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;
 import freenet.support.io.FileBucket;
+import freenet.support.io.PaddedEphemerallyEncryptedBucket;

 public class ClientPutDir extends ClientPutBase implements 
ClientEventListener, ClientCallback {


Modified: trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java     
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutDiskDirMessage.java     
2006-07-25 16:18:57 UTC (rev 9752)
@@ -8,10 +8,10 @@

 import freenet.client.async.ManifestElement;
 import freenet.node.Node;
-import freenet.support.BucketFactory;
 import freenet.support.Fields;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.BucketFactory;
 import freenet.support.io.FileBucket;

 /**

Modified: trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java    2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutMessage.java    2006-07-25 
16:18:57 UTC (rev 9752)
@@ -7,10 +7,10 @@
 import freenet.keys.FreenetURI;
 import freenet.node.Node;
 import freenet.node.RequestStarter;
-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
 import freenet.support.Fields;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
 import freenet.support.io.FileBucket;

 /**

Modified: trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java 2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/DataCarryingMessage.java 2006-07-25 
16:18:57 UTC (rev 9752)
@@ -4,10 +4,10 @@
 import java.io.InputStream;
 import java.io.OutputStream;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
-import freenet.support.BucketTools;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
+import freenet.support.io.BucketTools;


 public abstract class DataCarryingMessage extends BaseDataCarryingMessage {

Modified: trunk/freenet/src/freenet/node/fcp/DirPutFile.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/DirPutFile.java  2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/DirPutFile.java  2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -3,10 +3,10 @@
 import freenet.client.ClientMetadata;
 import freenet.client.DefaultMIMETypes;
 import freenet.client.async.ManifestElement;
-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;

 /**
  * A request to upload a file to a manifest.

Modified: trunk/freenet/src/freenet/node/fcp/DirectDirPutFile.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/DirectDirPutFile.java    2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/DirectDirPutFile.java    2006-07-25 
16:18:57 UTC (rev 9752)
@@ -4,10 +4,10 @@
 import java.io.InputStream;
 import java.io.OutputStream;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
-import freenet.support.BucketTools;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;
+import freenet.support.io.BucketTools;

 /**
  * Specialized DirPutFile for direct uploads.

Modified: trunk/freenet/src/freenet/node/fcp/DiskDirPutFile.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/DiskDirPutFile.java      2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/DiskDirPutFile.java      2006-07-25 
16:18:57 UTC (rev 9752)
@@ -3,8 +3,8 @@
 import java.io.File;

 import freenet.client.DefaultMIMETypes;
-import freenet.support.Bucket;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;
 import freenet.support.io.FileBucket;

 public class DiskDirPutFile extends DirPutFile {

Modified: trunk/freenet/src/freenet/node/fcp/FCPConnectionHandler.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPConnectionHandler.java        
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/FCPConnectionHandler.java        
2006-07-25 16:18:57 UTC (rev 9752)
@@ -4,8 +4,8 @@
 import java.net.Socket;
 import java.util.HashMap;

-import freenet.support.BucketFactory;
 import freenet.support.Logger;
+import freenet.support.io.BucketFactory;

 public class FCPConnectionHandler {


Modified: trunk/freenet/src/freenet/node/fcp/FCPMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPMessage.java  2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/FCPMessage.java  2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -4,8 +4,8 @@
 import java.io.OutputStream;

 import freenet.node.Node;
-import freenet.support.BucketFactory;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.BucketFactory;
 import freenet.support.io.PersistentTempBucketFactory;

 public abstract class FCPMessage {

Modified: trunk/freenet/src/freenet/node/fcp/FCPServer.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPServer.java   2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/FCPServer.java   2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -35,8 +35,8 @@
 import freenet.node.Node;
 import freenet.node.RequestStarter;
 import freenet.support.Base64;
-import freenet.support.Bucket;
 import freenet.support.Logger;
+import freenet.support.io.Bucket;

 /**
  * FCP server process.

Modified: trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java    2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java    2006-07-25 
16:18:57 UTC (rev 9752)
@@ -6,10 +6,10 @@
 import freenet.client.async.SimpleManifestPutter;
 import freenet.keys.FreenetURI;
 import freenet.node.Node;
-import freenet.support.Bucket;
-import freenet.support.PaddedEphemerallyEncryptedBucket;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;
 import freenet.support.io.FileBucket;
+import freenet.support.io.PaddedEphemerallyEncryptedBucket;

 public class PersistentPutDir extends FCPMessage {


Modified: trunk/freenet/src/freenet/node/fcp/RedirectDirPutFile.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/RedirectDirPutFile.java  2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/fcp/RedirectDirPutFile.java  2006-07-25 
16:18:57 UTC (rev 9752)
@@ -5,9 +5,9 @@
 import freenet.client.ClientMetadata;
 import freenet.client.async.ManifestElement;
 import freenet.keys.FreenetURI;
-import freenet.support.Bucket;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.Bucket;

 public class RedirectDirPutFile extends DirPutFile {


Modified: trunk/freenet/src/freenet/node/updater/NodeUpdater.java
===================================================================
--- trunk/freenet/src/freenet/node/updater/NodeUpdater.java     2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/node/updater/NodeUpdater.java     2006-07-25 
16:18:57 UTC (rev 9752)
@@ -31,8 +31,8 @@
 import freenet.node.Version;
 import freenet.node.useralerts.RevocationKeyFoundUserAlert;
 import freenet.node.useralerts.UpdatedVersionAvailableUserAlert;
-import freenet.support.ArrayBucket;
 import freenet.support.Logger;
+import freenet.support.io.ArrayBucket;

 public class NodeUpdater implements ClientCallback, USKCallback {
        private FetcherContext ctx;

Deleted: trunk/freenet/src/freenet/support/ArrayBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/ArrayBucket.java  2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/support/ArrayBucket.java  2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -1,187 +0,0 @@
-package freenet.support;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * 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;
-
-       public ArrayBucket() {
-               this("ArrayBucket");
-       }
-
-       public ArrayBucket(byte[] initdata) {
-               this("ArrayBucket");
-               data.add(initdata);
-       }
-
-       public ArrayBucket(String name) {
-               data = new ArrayList();
-               this.name = name;
-       }
-
-       public OutputStream getOutputStream() throws IOException {
-               if(readOnly) throw new IOException("Read only");
-               return new ArrayBucketOutputStream();
-       }
-
-       public InputStream getInputStream() {
-               return new ArrayBucketInputStream();
-       }
-
-       public String toString() {
-               StringBuffer s = new StringBuffer(250);
-               for (Iterator i = data.iterator(); i.hasNext();) {
-                       byte[] b = (byte[]) i.next();
-                       s.append(new String(b));
-               }
-               return s.toString();
-       }
-
-       public void read(InputStream in) throws IOException {
-               OutputStream out = new ArrayBucketOutputStream();
-               int i;
-               byte[] b = new byte[8 * 1024];
-               while ((i = in.read(b)) != -1) {
-                       out.write(b, 0, i);
-               }
-               out.close();
-       }
-
-       public long size() {
-               long size = 0;
-               for (Iterator i = data.iterator(); i.hasNext();) {
-                       byte[] b = (byte[]) i.next();
-                       size += b.length;
-               }
-               return size;
-       }
-
-       public String getName() {
-               return name;
-       }
-
-       private class ArrayBucketOutputStream extends ByteArrayOutputStream {
-               
-               public ArrayBucketOutputStream() {
-                       super();
-               }
-
-               public void close() throws IOException {
-                       data.add(toByteArray());
-                       if(readOnly) throw new IOException("Read only");
-                       // FIXME maybe we should throw on write instead? :)
-               }
-       }
-
-       private class ArrayBucketInputStream extends InputStream {
-               
-               private Iterator i;
-               private ByteArrayInputStream in;
-
-               public ArrayBucketInputStream() {
-                       i = data.iterator();
-               }
-
-               public int read() {
-                       return priv_read();
-               }
-
-               private int priv_read() {
-                       if (in == null) {
-                               if (i.hasNext()) {
-                                       in = new ByteArrayInputStream((byte[]) 
i.next());
-                               } else {
-                                       return -1;
-                               }
-                       }
-                       int i = in.read();
-                       if (i == -1) {
-                               in = null;
-                               return priv_read();
-                       } else {
-                               return i;
-                       }
-               }
-
-               public int read(byte[] b) {
-                       return priv_read(b, 0, b.length);
-               }
-
-               public int read(byte[] b, int off, int len) {
-                       return priv_read(b, off, len);
-               }
-
-               private int priv_read(byte[] b, int off, int len) {
-                       if (in == null) {
-                               if (i.hasNext()) {
-                                       in = new ByteArrayInputStream((byte[]) 
i.next());
-                               } else {
-                                       return -1;
-                               }
-                       }
-                       int i = in.read(b, off, len);
-                       if (i == -1) {
-                               in = null;
-                               return priv_read(b, off, len);
-                       } else {
-                               return i;
-                       }
-               }
-
-               public int available() {
-                       if (in == null) {
-                               if (i.hasNext()) {
-                                       in = new ByteArrayInputStream((byte[]) 
i.next());
-                               } else {
-                                       return 0;
-                               }
-                       }
-                       return in.available();
-               }
-
-       }
-
-       public boolean isReadOnly() {
-               return readOnly;
-       }
-
-       public void setReadOnly() {
-               readOnly = true;
-       }
-
-       public void free() {
-               data.clear();
-               // Not much else we can do.
-       }
-
-       public byte[] toByteArray() {
-               long sz = size();
-               int size = (int)sz;
-               byte[] buf = new byte[size];
-               int index = 0;
-               for(Iterator i=data.iterator();i.hasNext();) {
-                       byte[] obuf = (byte[]) i.next();
-                       System.arraycopy(obuf, 0, buf, index, obuf.length);
-                       index += obuf.length;
-               }
-               if(index != buf.length)
-                       throw new IllegalStateException();
-               return buf;
-       }
-}

Deleted: trunk/freenet/src/freenet/support/ArrayBucketFactory.java
===================================================================
--- trunk/freenet/src/freenet/support/ArrayBucketFactory.java   2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/ArrayBucketFactory.java   2006-07-25 
16:18:57 UTC (rev 9752)
@@ -1,15 +0,0 @@
-package freenet.support;
-
-import java.io.IOException;
-
-public class ArrayBucketFactory implements BucketFactory {
-
-       public Bucket makeBucket(long size) throws IOException {
-               return new ArrayBucket();
-       }
-
-       public void freeBucket(Bucket b) throws IOException {
-               // Do nothing
-       }
-
-}

Deleted: trunk/freenet/src/freenet/support/Bucket.java
===================================================================
--- trunk/freenet/src/freenet/support/Bucket.java       2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/support/Bucket.java       2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -1,50 +0,0 @@
-package freenet.support;
-import java.io.*;
-/**
- * A bucket is any arbitrary object can temporarily store data.
- * 
- * @author oskar
- */
-public interface Bucket {
-
-    /**
-     * Returns an OutputStream that is used to put data in this Bucket, from 
the 
-     * beginning. It is not possible to append data to a Bucket! This 
simplifies the
-     * code significantly for some classes. If you need to append, just pass 
the 
-     * OutputStream around.
-     */
-    public OutputStream getOutputStream() throws IOException;
-
-    /**
-     * Returns an InputStream that reads data from this Bucket. If there is
-     * no data in this bucket, null is returned.
-     */
-    public InputStream getInputStream() throws IOException;
-
-    /**
-     * Returns a name for the bucket, may be used to identify them in
-     * certain in certain situations.
-     */
-    public String getName();
-
-    /**
-     * Returns the amount of data currently in this bucket.
-     */
-    public long size();
-
-    /**
-     * Is the bucket read-only?
-     */
-    public boolean isReadOnly();
-    
-    /**
-     * Make the bucket read-only. Irreversible.
-     */
-    public void setReadOnly();
-
-    /**
-     * Free the bucket, if supported.
-     */
-       public void free();
-
-}

Deleted: trunk/freenet/src/freenet/support/BucketFactory.java
===================================================================
--- trunk/freenet/src/freenet/support/BucketFactory.java        2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/BucketFactory.java        2006-07-25 
16:18:57 UTC (rev 9752)
@@ -1,10 +0,0 @@
-package freenet.support;
-
-import java.io.IOException;
-
-
-public interface BucketFactory {
-    public Bucket makeBucket(long size) throws IOException;
-    public void freeBucket(Bucket b) throws IOException;
-}
-

Deleted: trunk/freenet/src/freenet/support/BucketTools.java
===================================================================
--- trunk/freenet/src/freenet/support/BucketTools.java  2006-07-25 16:14:02 UTC 
(rev 9751)
+++ trunk/freenet/src/freenet/support/BucketTools.java  2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -1,476 +0,0 @@
-package freenet.support;
-
-import java.io.DataInputStream;
-import java.io.EOFException;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.List;
-
-import freenet.support.io.FileBucket;
-
-/**
- * Helper functions for working with Buckets.
- */
-public class BucketTools {
-
-       static final int BLOCK_SIZE = 4096;
-       
-       /**
-        * Copy from the input stream of <code>src</code> to the output stream 
of
-        * <code>dest</code>.
-        * 
-        * @param src
-        * @param dst
-        * @throws IOException
-        */
-       public final static void copy(Bucket src, Bucket dst) throws 
IOException {
-               OutputStream out = dst.getOutputStream();
-               InputStream in = src.getInputStream();
-               ReadableByteChannel readChannel = Channels.newChannel(in);
-               WritableByteChannel writeChannel = Channels.newChannel(out);
-
-               ByteBuffer buffer = ByteBuffer.allocateDirect(BLOCK_SIZE);
-               while (readChannel.read(buffer) != -1) {
-                       buffer.flip();
-                       writeChannel.write(buffer);
-                       buffer.clear();
-               }
-
-               writeChannel.close();
-               readChannel.close();
-               out.close();
-               in.close();
-       }
-
-       public final static void zeroPad(Bucket b, long size) throws 
IOException {
-               OutputStream out = b.getOutputStream();
-
-               // Initialized to zero by default.
-               byte[] buffer = new byte[16384];
-
-               long count = 0;
-               while (count < size) {
-                       long nRequired = buffer.length;
-                       if (nRequired > size - count) {
-                               nRequired = size - count;
-                       }
-                       out.write(buffer, 0, (int) nRequired);
-                       count += nRequired;
-               }
-
-               out.close();
-       }
-
-       public final static void paddedCopy(Bucket from, Bucket to, long nBytes,
-                       int blockSize) throws IOException {
-
-               if (nBytes > blockSize) {
-                       throw new IllegalArgumentException("nBytes > 
blockSize");
-               }
-
-               OutputStream out = null;
-               InputStream in = null;
-
-               try {
-
-                       out = to.getOutputStream();
-                       byte[] buffer = new byte[16384];
-                       in = from.getInputStream();
-
-                       long count = 0;
-                       while (count != nBytes) {
-                               long nRequired = nBytes - count;
-                               if (nRequired > buffer.length) {
-                                       nRequired = buffer.length;
-                               }
-                               long nRead = in.read(buffer, 0, (int) 
nRequired);
-                               if (nRead == -1) {
-                                       throw new IOException("Not enough data 
in source bucket.");
-                               }
-                               out.write(buffer, 0, (int) nRead);
-                               count += nRead;
-                       }
-
-                       if (count < blockSize) {
-                               // hmmm... better to just allocate a new buffer
-                               // instead of explicitly zeroing the old one?
-                               // Zero pad to blockSize
-                               long padLength = buffer.length;
-                               if (padLength > blockSize - nBytes) {
-                                       padLength = blockSize - nBytes;
-                               }
-                               for (int i = 0; i < padLength; i++) {
-                                       buffer[i] = 0;
-                               }
-
-                               while (count != blockSize) {
-                                       long nRequired = blockSize - count;
-                                       if (blockSize - count > buffer.length) {
-                                               nRequired = buffer.length;
-                                       }
-                                       out.write(buffer, 0, (int) nRequired);
-                                       count += nRequired;
-                               }
-                       }
-               } finally {
-                       if (in != null)
-                               in.close();
-                       if (out != null)
-                               out.close();
-               }
-       }
-
-       public static class BucketFactoryWrapper implements BucketFactory {
-               public BucketFactoryWrapper(BucketFactory bf) {
-                       BucketFactoryWrapper.this.bf = bf;
-               }
-               public Bucket makeBucket(long size) throws IOException {
-                       return bf.makeBucket(size);
-               }
-
-               public void freeBucket(Bucket b) throws IOException {
-                       if (b instanceof RandomAccessFileBucket) {
-                               ((RandomAccessFileBucket) b).release();
-                               return;
-                       }
-                       bf.freeBucket(b);
-               }
-               private BucketFactory bf = null;
-       }
-
-       public static Bucket[] makeBuckets(BucketFactory bf, int count, int 
size)
-               throws IOException {
-               Bucket[] ret = new Bucket[count];
-               for (int i = 0; i < count; i++) {
-                       ret[i] = bf.makeBucket(size);
-               }
-               return ret;
-       }
-
-       /**
-        * Free buckets. Get yer free buckets here! No charge! All you can carry
-        * free buckets!
-        * <p>
-        * If an exception happens the method will attempt to free the remaining
-        * buckets then retun the first exception. Buckets successfully freed 
are
-        * made <code>null</code> in the array.
-        * </p>
-        * 
-        * @param bf
-        * @param buckets
-        * @throws IOException
-        *             the first exception The <code>buckets</code> array will
-        */
-       public static void freeBuckets(BucketFactory bf, Bucket[] buckets)
-               throws IOException {
-               if (buckets == null) {
-                       return;
-               }
-
-               IOException firstIoe = null;
-
-               for (int i = 0; i < buckets.length; i++) {
-                       // Make sure we free any temp buckets on exception
-                       try {
-                               if (buckets[i] != null) {
-                                       bf.freeBucket(buckets[i]);
-                               }
-                               buckets[i] = null;
-                       } catch (IOException e) {
-                               if (firstIoe == null) {
-                                       firstIoe = e;
-                               }
-                       }
-               }
-
-               if (firstIoe != null) {
-                       throw firstIoe;
-               }
-       }
-
-       // Note: Not all buckets are allocated by the bf.
-       //       You must use the BucketFactoryWrapper class above
-       //       to free the returned buckets.
-       //
-       // Always returns blocks, blocks, even if it has to create
-       // zero padded ones.
-       public static Bucket[] splitFile(
-               File file,
-               int blockSize,
-               long offset,
-               int blocks,
-               boolean readOnly,
-               BucketFactoryWrapper bf)
-               throws IOException {
-
-               long len = file.length() - offset;
-               if (len > blocks * blockSize) {
-                       len = blocks * blockSize;
-               }
-
-               long padBlocks = 0;
-               if ((blocks * blockSize) - len >= blockSize) {
-                       padBlocks = ((blocks * blockSize) - len) / blockSize;
-               }
-
-               Bucket[] ret = new Bucket[blocks];
-               Bucket[] rab =
-                       RandomAccessFileBucket.segment(
-                               file,
-                               blockSize,
-                               offset,
-                               (int) (blocks - padBlocks),
-                               true);
-               System.arraycopy(rab, 0, ret, 0, rab.length);
-
-               boolean groovy = false;
-               try {
-                       if (len % blockSize != 0) {
-                               // Copy and zero pad final partial block
-                               Bucket partial = ret[rab.length - 1];
-                               ret[rab.length - 1] = bf.makeBucket(blockSize);
-                               paddedCopy(
-                                       partial,
-                                       ret[rab.length - 1],
-                                       len % blockSize,
-                                       blockSize);
-                       }
-
-                       // Trailing zero padded blocks
-                       for (int i = rab.length; i < ret.length; i++) {
-                               ret[i] = bf.makeBucket(blockSize);
-                               zeroPad(ret[i], blockSize);
-                       }
-                       groovy = true;
-               } finally {
-                       if (!groovy) {
-                               freeBuckets(bf, ret);
-                       }
-               }
-               return ret;
-       }
-
-       public final static int[] nullIndices(Bucket[] array) {
-               List list = new ArrayList();
-               for (int i = 0; i < array.length; i++) {
-                       if (array[i] == null) {
-                               list.add(new Integer(i));
-                       }
-               }
-
-               int[] ret = new int[list.size()];
-               for (int i = 0; i < list.size(); i++) {
-                       ret[i] = ((Integer) list.get(i)).intValue();
-               }
-               return ret;
-       }
-
-       public final static int[] nonNullIndices(Bucket[] array) {
-               List list = new ArrayList();
-               for (int i = 0; i < array.length; i++) {
-                       if (array[i] != null) {
-                               list.add(new Integer(i));
-                       }
-               }
-
-               int[] ret = new int[list.size()];
-               for (int i = 0; i < list.size(); i++) {
-                       ret[i] = ((Integer) list.get(i)).intValue();
-               }
-               return ret;
-       }
-
-       public final static Bucket[] nonNullBuckets(Bucket[] array) {
-               List list = new ArrayList(array.length);
-               for (int i = 0; i < array.length; i++) {
-                       if (array[i] != null) {
-                               list.add(array[i]);
-                       }
-               }
-
-               Bucket[] ret = new Bucket[list.size()];
-               return (Bucket[]) list.toArray(ret);
-       }
-
-       /**
-        * Read the entire bucket in as a byte array.
-        * Not a good idea unless it is very small!
-        * Don't call if concurrent writes may be happening.
-        * @throws IOException If there was an error reading from the bucket.
-        * @throws OutOfMemoryError If it was not possible to allocate enough 
-        * memory to contain the entire bucket.
-        */
-       public final static byte[] toByteArray(Bucket bucket) throws 
IOException {
-               long size = bucket.size();
-               if(size > Integer.MAX_VALUE) throw new OutOfMemoryError();
-               byte[] data = new byte[(int)size];
-               InputStream is = bucket.getInputStream();
-               try {
-                       DataInputStream dis = new DataInputStream(is);
-                       dis.readFully(data);
-               } finally {
-                       is.close();
-               }
-               return data;
-       }
-
-       public static int toByteArray(Bucket bucket, byte[] output) throws 
IOException {
-               long size = bucket.size();
-               if(size > output.length)
-                       throw new IllegalArgumentException("Data does not fit 
in provided buffer");
-               InputStream is = bucket.getInputStream();
-               int moved = 0;
-               while(true) {
-                       if(moved == size) return moved;
-                       int x = is.read(output, moved, (int)(size - moved));
-                       if(x == -1) return moved;
-                       moved += x;
-               }
-       }
-       
-       public static Bucket makeImmutableBucket(BucketFactory bucketFactory, 
byte[] data) throws IOException {
-               Bucket bucket = bucketFactory.makeBucket(data.length);
-               OutputStream os = bucket.getOutputStream();
-               os.write(data);
-               os.close();
-               bucket.setReadOnly();
-               return bucket;
-       }
-
-       public static byte[] hash(Bucket data) throws IOException {
-               InputStream is = null;
-               try {
-                       MessageDigest md = MessageDigest.getInstance("SHA-256");
-                       is = data.getInputStream();
-                       long bucketLength = data.size();
-                       long bytesRead = 0;
-                       byte[] buf = new byte[4096];
-                       while((bytesRead < bucketLength) || (bucketLength == 
-1)) {
-                               int readBytes = is.read(buf);
-                               if(readBytes < 0) break;
-                               bytesRead += readBytes;
-                               md.update(buf, 0, readBytes);
-                       }
-                       if((bytesRead < bucketLength) && (bucketLength > 0))
-                               throw new EOFException();
-                       if((bytesRead != bucketLength) && (bucketLength > 0))
-                               throw new IOException("Read "+bytesRead+" but 
bucket length "+bucketLength+"!");
-                       return md.digest();
-               } catch (NoSuchAlgorithmException e) {
-                       Logger.error(BucketTools.class, "No such digest: 
SHA-256 !!");
-                       throw new Error("No such digest: SHA-256 !!");
-               } finally {
-                       if(is != null) is.close();
-               }
-       }
-
-       /** Copy the given quantity of data from the given bucket to the given 
OutputStream. 
-        * @throws IOException If there was an error reading from the bucket or 
writing to the stream. */
-       public static void copyTo(Bucket decodedData, OutputStream os, long 
truncateLength) throws IOException {
-               if(truncateLength == 0) return;
-               if(truncateLength < 0) truncateLength = Long.MAX_VALUE;
-               InputStream is = decodedData.getInputStream();
-               try {
-                       byte[] buf = new byte[4096];
-                       long moved = 0;
-                       while(moved < truncateLength) {
-                               // DO NOT move the (int) inside the Math.min()! 
big numbers truncate to negative numbers.
-                               int bytes = (int) Math.min(buf.length, 
truncateLength - moved);
-                               if(bytes <= 0)
-                                       throw new 
IllegalStateException("bytes="+bytes+", truncateLength="+truncateLength+", 
moved="+moved);
-                               bytes = is.read(buf, 0, bytes);
-                               if(bytes <= 0) {
-                                       if(truncateLength == Long.MAX_VALUE)
-                                               break;
-                                       throw new IOException("Could not move 
required quantity of data: "+bytes+" (moved "+moved+" of "+truncateLength+")");
-                               }
-                               os.write(buf, 0, bytes);
-                               moved += bytes;
-                       }
-               } finally {
-                       is.close();
-               }
-       }
-
-       /** Copy data from an InputStream into a Bucket. */
-       public static void copyFrom(Bucket bucket, InputStream is, long 
truncateLength) throws IOException {
-               OutputStream os = bucket.getOutputStream();
-               byte[] buf = new byte[4096];
-               if(truncateLength < 0) truncateLength = Long.MAX_VALUE;
-               try {
-                       long moved = 0;
-                       while(moved < truncateLength) {
-                               // DO NOT move the (int) inside the Math.min()! 
big numbers truncate to negative numbers.
-                               int bytes = (int) Math.min(buf.length, 
truncateLength - moved);
-                               if(bytes <= 0)
-                                       throw new 
IllegalStateException("bytes="+bytes+", truncateLength="+truncateLength+", 
moved="+moved);
-                               bytes = is.read(buf, 0, bytes);
-                               if(bytes <= 0) {
-                                       if(truncateLength == Long.MAX_VALUE)
-                                               break;
-                                       throw new IOException("Could not move 
required quantity of data: "+bytes+" (moved "+moved+" of "+truncateLength+")");
-                               }
-                               os.write(buf, 0, bytes);
-                               moved += bytes;
-                       }
-               } finally {
-                       os.close();
-               }
-       }
-
-       /**
-        * Split the data into a series of read-only Bucket's.
-        * @param origData The original data Bucket.
-        * @param splitSize The number of bytes to put into each bucket.
-        * 
-        * FIXME This could be made many orders of magnitude more efficient on
-        * time and space if the underlying Bucket happens to be a passed-in
-        * plaintext file!
-        * 
-        * Note that this method will allocate a buffer of size splitSize.
-        * @throws IOException If there is an error creating buckets, reading 
from
-        * the provided bucket, or writing to created buckets.
-        */
-       public static Bucket[] split(Bucket origData, int splitSize, 
BucketFactory bf) throws IOException {
-               if(origData instanceof FileBucket) {
-                       return ((FileBucket)origData).split(splitSize);
-               }
-               long length = origData.size();
-               if(length > ((long)Integer.MAX_VALUE) * splitSize)
-                       throw new IllegalArgumentException("Way too big!: 
"+length+" for "+splitSize);
-               int bucketCount = (int) (length / splitSize);
-               if(length % splitSize > 0) bucketCount++;
-               Bucket[] buckets = new Bucket[bucketCount];
-               InputStream is = origData.getInputStream();
-               try {
-                       DataInputStream dis = new DataInputStream(is);
-                       long remainingLength = length;
-                       byte[] buf = new byte[splitSize];
-                       for(int i=0;i<bucketCount;i++) {
-                               int len = (int) Math.min(splitSize, 
remainingLength);
-                               Bucket bucket = bf.makeBucket(len);
-                               buckets[i] = bucket;
-                               dis.readFully(buf, 0, len);
-                               remainingLength -= len;
-                               OutputStream os = bucket.getOutputStream();
-                               try {
-                                       os.write(buf, 0, len);
-                               } finally {
-                                       os.close();
-                               }
-                       }
-               } finally {
-                       is.close();
-               }
-               return buckets;
-       }
-}

Deleted: trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java     
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java     
2006-07-25 16:18:57 UTC (rev 9752)
@@ -1,364 +0,0 @@
-package freenet.support;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.spaceroots.mantissa.random.MersenneTwister;
-
-import freenet.crypt.PCFBMode;
-import freenet.crypt.RandomSource;
-import freenet.crypt.UnsupportedCipherException;
-import freenet.crypt.ciphers.Rijndael;
-import freenet.support.io.CannotCreateFromFieldSetException;
-import freenet.support.io.PersistentFileTracker;
-import freenet.support.io.SerializableToFieldSetBucket;
-import freenet.support.io.SerializableToFieldSetBucketUtil;
-
-/**
- * A proxy Bucket which adds:
- * - Encryption with the supplied cipher, and a random, ephemeral key.
- * - Padding to the next PO2 size.
- */
-public class PaddedEphemerallyEncryptedBucket implements Bucket, 
SerializableToFieldSetBucket {
-
-       private final Bucket bucket;
-       private final int minPaddedSize;
-       private final RandomSource origRandom;
-       private final Rijndael aes;
-       /** The decryption key. May be null. */
-       private final byte[] key;
-       private long dataLength;
-       private boolean readOnly;
-       private int lastOutputStream;
-       
-       /**
-        * Create a padded encrypted proxy bucket.
-        * @param bucket The bucket which we are proxying to. Must be empty.
-        * @param pcfb The encryption mode with which to encipher/decipher the 
data.
-        * @param minSize The minimum padded size of the file (after it has 
been closed).
-        * @param origRandom Hard random number generator from which to obtain 
a seed for padding.
-        * @throws UnsupportedCipherException 
-        */
-       public PaddedEphemerallyEncryptedBucket(Bucket bucket, int minSize, 
RandomSource origRandom, boolean forgetKey) {
-               this.origRandom = origRandom;
-               this.bucket = bucket;
-               if(bucket.size() != 0) throw new 
IllegalArgumentException("Bucket must be empty");
-               try {
-                       aes = new Rijndael(256, 256);
-               } catch (UnsupportedCipherException e) {
-                       throw new Error(e);
-               }
-               byte[] tempKey = new byte[32];
-               origRandom.nextBytes(tempKey);
-               aes.initialize(tempKey);
-               if(forgetKey) {
-                       // Might as well blank it
-                       for(int i=0;i<tempKey.length;i++) tempKey[i] = 0;
-                       this.key = null;
-               } else {
-                       this.key = tempKey;
-               }
-               this.minPaddedSize = minSize;
-               readOnly = false;
-               lastOutputStream = 0;
-       }
-
-       /**
-        * Load an existing PaddedEphemerallyEncryptedBucket, with a key.
-        * The bucket can and should already exist.
-        * @param bucket
-        * @param minSize
-        * @param knownSize The size of the data. This cannot be deduced from 
the bucket
-        * alone and must be specified. If the bucket is smaller than this, we 
throw.
-        * @param key
-        * @param origRandom
-        * @throws IOException 
-        */
-       public PaddedEphemerallyEncryptedBucket(Bucket bucket, int minSize, 
long knownSize, byte[] key, RandomSource origRandom) throws IOException {
-               if(bucket.size() < knownSize)
-                       throw new IOException("Bucket is too small on disk - 
knownSize="+knownSize+" but bucket.size="+bucket.size()+" for "+bucket);
-               this.dataLength = knownSize;
-               this.origRandom = origRandom;
-               this.bucket = bucket;
-               try {
-                       aes = new Rijndael(256, 256);
-               } catch (UnsupportedCipherException e) {
-                       throw new Error(e);
-               }
-               aes.initialize(key);
-               this.key = key;
-               this.minPaddedSize = minSize;
-               readOnly = false;
-               lastOutputStream = 0;
-       }
-
-       public PaddedEphemerallyEncryptedBucket(SimpleFieldSet fs, RandomSource 
origRandom, PersistentFileTracker f) throws CannotCreateFromFieldSetException {
-               this.origRandom = origRandom;
-               String tmp = fs.get("DataLength");
-               if(tmp == null)
-                       throw new CannotCreateFromFieldSetException("No 
DataLength");
-               try {
-                       dataLength = Long.parseLong(tmp);
-               } catch (NumberFormatException e) {
-                       throw new CannotCreateFromFieldSetException("Corrupt 
dataLength: "+tmp, e);
-               }
-               SimpleFieldSet underlying = fs.subset("Underlying");
-               if(underlying == null)
-                       throw new CannotCreateFromFieldSetException("No 
underlying bucket");
-               bucket = SerializableToFieldSetBucketUtil.create(underlying, 
origRandom, f);
-               tmp = fs.get("DecryptKey");
-               if(tmp == null)
-                       throw new CannotCreateFromFieldSetException("No key");
-               key = HexUtil.hexToBytes(tmp);
-               try {
-                       aes = new Rijndael(256, 256);
-               } catch (UnsupportedCipherException e) {
-                       throw new Error(e);
-               }
-               aes.initialize(key);
-               tmp = fs.get("MinPaddedSize");
-               if(tmp == null)
-                       minPaddedSize = 1024; // FIXME throw! back 
compatibility hack
-               else {
-                       try {
-                               minPaddedSize = Integer.parseInt(tmp);
-                       } catch (NumberFormatException e) {
-                               throw new 
CannotCreateFromFieldSetException("Corrupt dataLength: "+tmp, e);
-                       }
-               }
-               if(dataLength > bucket.size())
-                       throw new CannotCreateFromFieldSetException("Underlying 
bucket is too small: should be "+dataLength+" actually "+bucket.size());
-       }
-
-       public OutputStream getOutputStream() throws IOException {
-               if(readOnly) throw new IOException("Read only");
-               OutputStream os = bucket.getOutputStream();
-               synchronized(this) {
-                       dataLength = 0;
-               }
-               return new PaddedEphemerallyEncryptedOutputStream(os, 
++lastOutputStream);
-       }
-
-       private class PaddedEphemerallyEncryptedOutputStream extends 
OutputStream {
-
-               final PCFBMode pcfb;
-               final OutputStream out;
-               final int streamNumber;
-               private boolean closed;
-               
-               public PaddedEphemerallyEncryptedOutputStream(OutputStream out, 
int streamNumber) {
-                       this.out = out;
-                       dataLength = 0;
-                       this.streamNumber = streamNumber;
-                       pcfb = new PCFBMode(aes);
-               }
-               
-               public void write(int b) throws IOException {
-                       if(closed) throw new IOException("Already closed!");
-                       if(streamNumber != lastOutputStream)
-                               throw new IllegalStateException("Writing to old 
stream in "+getName());
-                       if((b < 0) || (b > 255))
-                               throw new IllegalArgumentException();
-                       int toWrite = pcfb.encipher(b);
-                       synchronized(PaddedEphemerallyEncryptedBucket.this) {
-                               out.write(toWrite);
-                               dataLength++;
-                       }
-               }
-               
-               public void write(byte[] buf, int offset, int length) throws 
IOException {
-                       if(closed) throw new IOException("Already closed!");
-                       if(streamNumber != lastOutputStream)
-                               throw new IllegalStateException("Writing to old 
stream in "+getName());
-                       byte[] enc = new byte[length];
-                       System.arraycopy(buf, offset, enc, 0, length);
-                       pcfb.blockEncipher(enc, 0, enc.length);
-                       synchronized(PaddedEphemerallyEncryptedBucket.this) {
-                               out.write(enc, 0, enc.length);
-                               dataLength += enc.length;
-                       }
-               }
-               
-               // Override this or FOS will use write(int)
-               public void write(byte[] buf) throws IOException {
-                       if(closed) throw new IOException("Already closed!");
-                       if(streamNumber != lastOutputStream)
-                               throw new IllegalStateException("Writing to old 
stream in "+getName());
-                       write(buf, 0, buf.length);
-               }
-               
-               public void close() throws IOException {
-                       if(closed) return;
-                       try {
-                               if(streamNumber != lastOutputStream) {
-                                       Logger.normal(this, "Not padding out to 
length because have been superceded: "+getName());
-                                       return;
-                               }
-                               
synchronized(PaddedEphemerallyEncryptedBucket.this) {
-                                       MersenneTwister paddingSource = new 
MersenneTwister(origRandom.nextLong());
-                                       long finalLength = paddedLength();
-                                       long padding = finalLength - dataLength;
-                                       byte[] buf = new byte[4096];
-                                       long writtenPadding = 0;
-                                       while(writtenPadding < padding) {
-                                               int left = Math.min((int) 
(padding - writtenPadding), buf.length);
-                                               paddingSource.nextBytes(buf);
-                                               out.write(buf, 0, left);
-                                               writtenPadding += left;
-                                       }
-                               }
-                       } finally {
-                               closed = true;
-                               out.close();
-                       }
-               }
-       }
-
-       public InputStream getInputStream() throws IOException {
-               return new 
PaddedEphemerallyEncryptedInputStream(bucket.getInputStream());
-       }
-
-       private class PaddedEphemerallyEncryptedInputStream extends InputStream 
{
-
-               final InputStream in;
-               final PCFBMode pcfb;
-               long ptr;
-               
-               public PaddedEphemerallyEncryptedInputStream(InputStream in) {
-                       this.in = in;
-                       pcfb = new PCFBMode(aes);
-                       ptr = 0;
-               }
-               
-               public int read() throws IOException {
-                       if(ptr > dataLength) return -1;
-                       int x = in.read();
-                       if(x == -1) return x;
-                       ptr++;
-                       return pcfb.decipher(x);
-               }
-               
-               public final int available() {
-                       int x = (int)(dataLength - ptr);
-                       return (x < 0) ? 0 : x;
-               }
-               
-               public int read(byte[] buf, int offset, int length) throws 
IOException {
-                       // FIXME remove debugging
-                       if((length+offset > buf.length) || (offset < 0) || 
(length < 0))
-                               throw new 
ArrayIndexOutOfBoundsException("a="+offset+", b="+length+", length 
"+buf.length);
-                       int x = available();
-                       if(x <= 0) return -1;
-                       length = Math.min(length, x);
-                       int readBytes = in.read(buf, offset, length);
-                       if(readBytes <= 0) return readBytes;
-                       ptr += readBytes;
-                       pcfb.blockDecipher(buf, offset, readBytes);
-                       return readBytes;
-               }
-
-               public int read(byte[] buf) throws IOException {
-                       return read(buf, 0, buf.length);
-               }
-               
-               public long skip(long bytes) throws IOException {
-                       byte[] buf = new byte[(int)Math.min(4096, bytes)];
-                       long skipped = 0;
-                       while(skipped < bytes) {
-                               int x = read(buf, 0, 
(int)Math.min(bytes-skipped, buf.length));
-                               if(x <= 0) return skipped;
-                               skipped += x;
-                       }
-                       return skipped;
-               }
-               
-               public void close() throws IOException {
-                       in.close();
-               }
-       }
-
-       /**
-        * Return the length of the data in the proxied bucket, after padding.
-        */
-       public synchronized long paddedLength() {
-               long size = dataLength;
-               if(size < minPaddedSize) size = minPaddedSize;
-               if(size == minPaddedSize) return size;
-               long min = minPaddedSize;
-               long max = minPaddedSize << 1;
-               while(true) {
-                       if(max < 0)
-                               throw new Error("Impossible size: "+size+" - 
min="+min+", max="+max);
-                       if(size < min)
-                               throw new IllegalStateException("???");
-                       if((size >= min) && (size <= max)) {
-                               Logger.minor(this, "Padded: "+max+" was: 
"+dataLength+" for "+getName());
-                               return max;
-                       }
-                       min = max;
-                       max = max << 1;
-               }
-       }
-
-       public String getName() {
-               return "Encrypted:"+bucket.getName();
-       }
-
-       public String toString() {
-               return super.toString()+":"+bucket.toString();
-       }
-       
-       public synchronized long size() {
-               return dataLength;
-       }
-
-       public boolean isReadOnly() {
-               return readOnly;
-       }
-       
-       public void setReadOnly() {
-               readOnly = true;
-       }
-
-       /**
-        * @return The underlying Bucket.
-        */
-       public Bucket getUnderlying() {
-               return bucket;
-       }
-
-       public void free() {
-               bucket.free();
-       }
-
-       /**
-        * Get the decryption key. May have been blanked out.
-        */
-       public byte[] getKey() {
-               return key;
-       }
-
-       public SimpleFieldSet toFieldSet() {
-               SimpleFieldSet fs = new SimpleFieldSet(true);
-               fs.put("Type", "PaddedEphemerallyEncryptedBucket");
-               synchronized(this) {
-                       fs.put("DataLength", dataLength);
-               }
-               if(key != null) {
-                       fs.put("DecryptKey", HexUtil.bytesToHex(key));
-               } else {
-                       Logger.error(this, "Cannot serialize because no key");
-                       return null;
-               }
-               if(bucket instanceof SerializableToFieldSetBucket) {
-                       fs.put("Underlying", 
((SerializableToFieldSetBucket)bucket).toFieldSet());
-               } else {
-                       Logger.error(this, "Cannot serialize underlying bucket: 
"+bucket);
-                       return null;
-               }
-               fs.put("MinPaddedSize", minPaddedSize);
-               return fs;
-       }
-
-}

Deleted: 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java
===================================================================
--- 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java  
    2006-07-25 16:14:02 UTC (rev 9751)
+++ 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java  
    2006-07-25 16:18:57 UTC (rev 9752)
@@ -1,31 +0,0 @@
-package freenet.support;
-
-import java.io.IOException;
-
-import freenet.crypt.RandomSource;
-
-/**
- * Factory wrapper for PaddedEphemerallyEncryptedBucket's, which are themselves
- * wrappers.
- */
-public class PaddedEphemerallyEncryptedBucketFactory implements BucketFactory {
-
-       final BucketFactory baseFactory;
-       final RandomSource random;
-       final int minSize;
-       
-       public PaddedEphemerallyEncryptedBucketFactory(BucketFactory factory, 
RandomSource r, int minSize) {
-               baseFactory = factory;
-               this.minSize = minSize;
-               this.random = r;
-       }
-
-       public Bucket makeBucket(long size) throws IOException {
-               return new 
PaddedEphemerallyEncryptedBucket(baseFactory.makeBucket(size), minSize, random, 
true);
-       }
-
-       public void freeBucket(Bucket b) throws IOException {
-               
baseFactory.freeBucket(((PaddedEphemerallyEncryptedBucket)b).getUnderlying());
-       }
-
-}

Deleted: trunk/freenet/src/freenet/support/RandomAccessFileBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/RandomAccessFileBucket.java       
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/RandomAccessFileBucket.java       
2006-07-25 16:18:57 UTC (rev 9752)
@@ -1,467 +0,0 @@
-// REDFLAG: test and javadoc
-package freenet.support;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.util.Vector;
-
-import freenet.support.io.CannotCreateFromFieldSetException;
-import freenet.support.io.PersistentFileTracker;
-import freenet.support.io.SerializableToFieldSetBucket;
-
-/**
- * Bucket implementation that can efficiently access any arbitrary byte-range
- * of a file.
- *
- **/
-public class RandomAccessFileBucket implements Bucket, 
SerializableToFieldSetBucket {
-
-    private final File file;
-    private final long offset;
-    private long localOffset = 0;
-    private final long len;
-    private boolean readOnly = false;
-    private boolean released = false;
-    private Vector streams = new Vector();
-    
-    public RandomAccessFileBucket(File file, long offset, long len, boolean 
readOnly)
-        throws IOException {
-        if (!(file.exists() && file.canRead())) {
-            throw new IOException("Can't read file: " + 
file.getAbsolutePath());
-        } 
-        
-        if ((!file.canWrite()) && (!readOnly)) {
-            throw new IOException("Can't write to file: " + 
file.getAbsolutePath());
-        } 
-
-        this.file = file;
-        this.readOnly = readOnly;
-        this.offset = offset;
-        this.len = len;
-    }
-
-    public RandomAccessFileBucket(SimpleFieldSet fs, PersistentFileTracker f) 
throws CannotCreateFromFieldSetException {
-               String tmp = fs.get("Filename");
-               if(tmp == null) throw new CannotCreateFromFieldSetException("No 
filename");
-               this.file = new File(tmp);
-               tmp = fs.get("Length");
-               if(tmp == null) throw new CannotCreateFromFieldSetException("No 
length");
-               try {
-                       len = Long.parseLong(tmp);
-               } catch (NumberFormatException e) {
-                       throw new CannotCreateFromFieldSetException("Corrupt 
length "+tmp, e);
-               }
-               tmp = fs.get("Offset");
-               if(tmp == null) throw new CannotCreateFromFieldSetException("No 
offset");
-               try {
-                       offset = Long.parseLong(tmp);
-               } catch (NumberFormatException e) {
-                       throw new CannotCreateFromFieldSetException("Corrupt 
offset "+tmp, e);
-               }
-       }
-
-    public static class Range {
-        Range(long offset, long len) {
-            this.offset = offset;
-            this.len = len;
-        }
-
-        public long offset;
-        public long len;
-    }
-
-    public final synchronized Range getRange() {
-        return new Range(offset, len);
-    }
-    
-    // hmmm make protected???
-    public final synchronized boolean hasOpenStreams() {
-        return streams.size() > 0;
-    }
-
-    // Wrap non-const members so we can tell
-    // when code touches the Bucket after it
-    // has been released.
-    public synchronized InputStream getInputStream() throws IOException {
-        if (isReleased()) {
-            throw new IOException("Attempt to use a released 
RandomAccessFileBucket: " + getName() );
-        }
-
-        InputStream newIn = new RAInputStream(file.getAbsolutePath());
-        streams.addElement(newIn);
-        return newIn;
-    }
-
-    public synchronized OutputStream getOutputStream() throws IOException {
-        if (isReleased()) {
-            throw new IOException("Attempt to use a released 
RandomAccessBucket: " + getName() );
-        }
-
-        if (readOnly) {
-            throw new IOException("Tried to write a read-only Bucket.");
-        }
-
-        OutputStream newOut = new RAOutputStream(file.getAbsolutePath());
-        streams.addElement(newOut);
-        return newOut;
-    }
-
-    public String getName() {
-        return file.getAbsolutePath() + " [" + offset + ", " + 
-            (offset + len - 1) + "]";
-    }
-        
-    public synchronized void resetWrite() {
-        if (isReleased()) {
-            throw new RuntimeException("Attempt to use a released 
RandomAccessFileBucket: " + getName() );
-        }
-        // REDFLAG: implicit assumptions
-        // 0) Bucket is only written to at a time.
-        // 1) The output stream is closed before the
-        //    next is open. Ouch. This may cause problems...
-        localOffset = 0;
-    }
-
-    public long size() { return len; }
-
-    public synchronized boolean release() {
-        if (released) {
-            return true;
-        }
-
-        // Force all open streams closed. 
-        // Windows won't let us delete the file unless we
-        // do this.
-        for (int i =0; i < streams.size(); i++) {
-            try {
-                if (streams.elementAt(i) instanceof InputStream) {
-                    ((InputStream)streams.elementAt(i)).close();
-
-                    Logger.debug(this, "closed open InputStream !: " + 
-                               file.getAbsolutePath());
-                }
-                else if (streams.elementAt(i) instanceof OutputStream) {
-                    ((OutputStream)streams.elementAt(i)).close();
-                    Logger.debug(this, "closed open OutputStream !: " + 
-                               file.getAbsolutePath());
-                }
-            }
-            catch (IOException ioe) {
-            }
-        }
-        streams.removeAllElements();
-        streams.trimToSize();
-        // We don't delete anything because we don't own anything.
-        released = true;
-        return true;
-    }
-
-    public synchronized final boolean isReleased() { return released; }
-
-    public void finalize() throws Throwable {
-       synchronized(this) {
-               if(released) return;
-       }
-       release();
-    }
-
-    // REDFLAG: RETEST
-    // set blocks = -1 for until end.
-    // last block may have length < blockSize
-    public static Bucket[] segment(File file, int blockSize, 
-                                   long offset, int blocks,  boolean readOnly) 
-        throws IOException {
-        
-        if (!(file.exists() && file.canRead())) {
-            throw new IOException("Can't read file: " + 
file.getAbsolutePath());
-        } 
-        
-        if ((!file.canWrite()) && (!readOnly)) {
-            throw new IOException("Can't write to file: " + 
file.getAbsolutePath());
-        } 
-        
-        if ((offset < 0) || (offset >= file.length() - 1)) {
-            throw new IllegalArgumentException("offset: " + offset);
-        }
-
-        long length = file.length() - offset;
-        int nBlocks = (int) (length / blockSize);
-        if ((length % blockSize) != 0) {
-            nBlocks++;
-        }        
-        
-        if (blocks == -1) {
-            blocks = nBlocks;
-        }
-        else if ((blocks > nBlocks) || (blocks < 1)) {
-            throw new IllegalArgumentException("blocks: " + blocks);
-        } 
-
-        Bucket[] ret = new Bucket[blocks];
-        
-        for (int i = 0; i < blocks; i++) {
-            final long localOffset = i * blockSize + offset;
-            int blockLen = blockSize;
-            if (i == nBlocks - 1) {
-                blockLen = (int) (length - (nBlocks - 1) * blockSize);
-            }
-            ret[i] = new RandomAccessFileBucket(file, localOffset, blockLen, 
readOnly);
-        }
-        
-        return ret;
-    }
-
-    ////////////////////////////////////////////////////////////
-    // InputStream and OutputStream implementations
-    //
-    private final static boolean vociferous = false;
-
-    class RAInputStream extends InputStream  {
-        public RAInputStream(String prefix) throws IOException {
-            raf = new RandomAccessFile(file, "r");
-            raf.seek(offset);
-            println(" -- Created new InputStream [" + offset + 
-                    ", " + (offset + len -1) + "]" );
-        }
-        
-        ////////////////////////////////////////////////////////////
-        // FilterInput implementation
-
-        private final int bytesLeft() throws IOException {
-                       synchronized (RandomAccessFileBucket.this) {
-                               return (int)(offset + len - 
raf.getFilePointer());
-                       }
-        }
-
-        public int read() throws java.io.IOException {
-            synchronized (RandomAccessFileBucket.this) {
-                println(".read()");
-                checkValid();
-                if (bytesLeft() < 1) {
-                    return -1; // EOF
-                } 
-                return raf.read();
-            }
-        }
-        
-        public int read(byte[] bytes) throws java.io.IOException {
-            synchronized (RandomAccessFileBucket.this) {
-                println(".read(byte[])");
-                checkValid();
-                int nAvailable = bytesLeft();
-                if (nAvailable < 1) {
-                    return -1; // EOF
-                } 
-                if (nAvailable > bytes.length) {
-                    nAvailable = bytes.length;
-                }
-                return raf.read(bytes, 0, nAvailable);
-            }
-        }
-        
-        public int read(byte[] bytes, int a, int b) throws java.io.IOException 
{
-            synchronized (RandomAccessFileBucket.this) {
-                println(".read(byte[], int, int)");
-                checkValid();
-                int nAvailable = bytesLeft();
-                if (nAvailable < 1) {
-                    return -1; // EOF
-                } 
-                if (nAvailable > b) {
-                    nAvailable = b;
-                }
-                return raf.read(bytes, a, nAvailable);
-            }
-        }
-        
-        public long skip(long a) throws java.io.IOException {
-            synchronized (RandomAccessFileBucket.this) {
-                println(".skip(long)");
-                checkValid();
-                int nAvailable = bytesLeft();
-                if (nAvailable < 1) {
-                    return -1; // EOF
-                } 
-                if (nAvailable > a) {
-                    nAvailable = (int)a;
-                }
-
-                return raf.skipBytes(nAvailable);
-            }
-        }
-        
-        public int available() throws java.io.IOException {
-            synchronized (RandomAccessFileBucket.this) {
-                println(".available()");
-                checkValid();
-                return bytesLeft();
-            }
-        }
-        
-        public void close() throws java.io.IOException {
-            synchronized (RandomAccessFileBucket.this) {
-                println(".close()");
-                checkValid();       
-                raf.close();
-                if (streams.contains(RAInputStream.this)) {
-                    streams.removeElement(RAInputStream.this);
-                }
-                streams.trimToSize();
-            }
-        }
-        
-        // LATER: support if really needed.
-        public  void mark(int a) {
-            // NOP
-        }
-
-        public void reset() {
-            // NOP
-        }
-        
-        public boolean markSupported() {
-            return false;
-        }
-
-        private final void println(String text) {
-            if (vociferous) {
-                Logger.debug(this, text);
-            }
-        }
-        
-        private final void checkValid() throws IOException {
-                       synchronized(RandomAccessFileBucket.this) {
-                               if (released) {
-                                       throw new IOException("Attempt to use a 
released RandomAccessFileBucket: " + prefix);
-                               }
-                       }
-        }
-
-        ////////////////////////////////////////////////////////////
-        private RandomAccessFile raf = null;
-        private String prefix = "";
-    }
-
-    private class RAOutputStream extends OutputStream {
-        public RAOutputStream(String pref) throws IOException {
-            raf = new RandomAccessFile(file, "rw");
-            raf.seek(offset + localOffset);
-            println(" -- Created new OutputStream [" + offset + ", " 
-                    + (offset + len -1) + "]" );
-        }
-    
-        ////////////////////////////////////////////////////////////
-        // OutputStream implementation
-        public void write(int b) throws IOException {
-            synchronized (RandomAccessFileBucket.this) {
-                println(".write(b)");
-                checkValid();
-                int nAvailable = bytesLeft();
-                if (nAvailable < 1) {
-                    throw new IOException("Attempt to write past end of 
Bucket.");
-                }
-                raf.write(b);
-            }
-        }
-    
-        public void write(byte[] buf) throws IOException {
-            synchronized (RandomAccessFileBucket.this) {
-                println(".write(buf)");
-                checkValid();
-                int nAvailable = bytesLeft();
-                if (nAvailable < buf.length) {
-                    throw new IOException("Attempt to write past end of 
Bucket.");
-                }
-                raf.write(buf);
-            }
-        }
-    
-        public void write(byte[] buf, int off, int len) throws IOException {
-            synchronized (RandomAccessFileBucket.this) {
-                println(".write(buf,off,len)");
-                checkValid();
-                int nAvailable = bytesLeft();
-                if (nAvailable < len) {
-                    throw new IOException("Attempt to write past end of 
Bucket.");
-                }
-                raf.write(buf, off, len);
-            }
-        }
-    
-        public void flush() throws IOException {
-            synchronized (RandomAccessFileBucket.this) {
-                println(".flush()");
-                checkValid();
-                // NOP? Bytes written immediately?
-                // REDFLAG: double check.
-            }
-        }
-    
-        public void close() throws IOException {
-            synchronized (RandomAccessFileBucket.this) {
-                println(".close()");
-                checkValid();
-                if (streams.contains(RAOutputStream.this)) {
-                    streams.removeElement(RAOutputStream.this);
-                }
-                streams.trimToSize();
-                long added = raf.getFilePointer() - offset;
-                if (added > 0) {
-                    // To get proper append behavior.
-                    localOffset = added;
-                }
-                
-                raf.close();
-            }
-        }
-
-        ////////////////////////////////////////////////////////////
-        private void println(String text) {
-            if (vociferous) {
-                Logger.debug(this, text);
-            }
-        }
-
-        private final void checkValid() throws IOException {
-                       synchronized (RandomAccessFileBucket.this) {
-                               if (isReleased()) {
-                                       throw new IOException("Attempt to use a 
released RandomAccessFileBucket: " + prefix);
-                               }
-                       }
-        }
-        private final int bytesLeft() throws IOException {
-                       synchronized (RandomAccessFileBucket.this) {
-                               return (int)(offset + len - 
raf.getFilePointer());
-                       }
-        }
-
-        private RandomAccessFile raf = null;
-        private String prefix = "";
-
-    }
-    ////////////////////////////////////////////////////////////
-
-    public synchronized boolean isReadOnly() {
-       return readOnly;
-    }
-    
-    public synchronized void setReadOnly() {
-       readOnly = true;
-    }
-
-       public void free() {
-               release();
-       }
-
-       public synchronized SimpleFieldSet toFieldSet() {
-               SimpleFieldSet fs = new SimpleFieldSet(true);
-               fs.put("Type", "RandomAccessFileBucket");
-               fs.put("Filename", file.toString());
-               fs.put("Offset", offset);
-               fs.put("Length", len);
-               return fs;
-       }
-}

Deleted: trunk/freenet/src/freenet/support/ReadOnlyFileSliceBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/ReadOnlyFileSliceBucket.java      
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/ReadOnlyFileSliceBucket.java      
2006-07-25 16:18:57 UTC (rev 9752)
@@ -1,119 +0,0 @@
-package freenet.support;
-
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-
-/**
- * FIXME: implement a hash verifying version of this.
- */
-public class ReadOnlyFileSliceBucket implements Bucket {
-
-       private final File file;
-       private final long startAt;
-       private final long length;
-       
-       public ReadOnlyFileSliceBucket(File f, long startAt, long length) {
-               this.file = f;
-               this.startAt = startAt;
-               this.length = length;
-       }
-       
-       public OutputStream getOutputStream() throws IOException {
-               throw new IOException("Bucket is read-only");
-       }
-
-       public InputStream getInputStream() throws IOException {
-               return new MyInputStream();
-       }
-
-       public String getName() {
-               return "ROFS:"+file.getAbsolutePath()+":"+startAt+":"+length;
-       }
-
-       public long size() {
-               return length;
-       }
-
-       public boolean isReadOnly() {
-               return true;
-       }
-
-       public void setReadOnly() {
-               // Do nothing
-       }
-
-       class MyInputStream extends InputStream {
-
-               private RandomAccessFile f;
-               private long ptr; // relative to startAt
-               
-               MyInputStream() throws IOException {
-                       try {
-                               this.f = new RandomAccessFile(file,"r");
-                               f.seek(startAt);
-                               if(f.length() < (startAt+length))
-                                       throw new 
ReadOnlyFileSliceBucketException("File truncated? Length "+f.length()+" but 
start at "+startAt+" for "+length+" bytes");
-                               ptr = 0;
-                       } catch (FileNotFoundException e) {
-                               throw new ReadOnlyFileSliceBucketException(e);
-                       }
-               }
-               
-               public int read() throws IOException {
-                       if(ptr > length)
-                               throw new EOFException();
-                       int x = f.read();
-                       ptr++;
-                       return x;
-               }
-               
-               public int read(byte[] buf, int offset, int len) throws 
IOException {
-                       if(ptr > length)
-                               throw new EOFException();
-                       len = (int) Math.min(len, length - ptr);
-                       int x = f.read(buf, offset, len);
-                       ptr += x;
-                       return x;
-               }
-               
-               public int read(byte[] buf) throws IOException {
-                       return read(buf, 0, buf.length);
-               }
-
-               public void close() throws IOException {
-                       f.close();
-               }
-               
-               public void finalize() {
-                       try {
-                               close();
-                       } catch (IOException e) {
-                               // Ignore
-                       }
-               }
-       }
-
-       public class ReadOnlyFileSliceBucketException extends IOException {
-               private static final long serialVersionUID = -1;
-               
-               public ReadOnlyFileSliceBucketException(FileNotFoundException 
e) {
-                       super("File not found: "+e.getMessage());
-                       initCause(e);
-               }
-
-               public ReadOnlyFileSliceBucketException(String string) {
-                       super(string);
-               }
-               
-       }
-
-       public void free() {
-               // Do nothing
-       }
-       
-}

Modified: trunk/freenet/src/freenet/support/SimpleReadOnlyArrayBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/SimpleReadOnlyArrayBucket.java    
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/SimpleReadOnlyArrayBucket.java    
2006-07-25 16:18:57 UTC (rev 9752)
@@ -5,6 +5,8 @@
 import java.io.InputStream;
 import java.io.OutputStream;

+import freenet.support.io.Bucket;
+
 /**
  * Simple read-only array bucket. Just an adapter class to save some RAM.
  * Not the same as ArrayBucket, which can't take a (byte[], offset, len) in

Modified: trunk/freenet/src/freenet/support/compress/Compressor.java
===================================================================
--- trunk/freenet/src/freenet/support/compress/Compressor.java  2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/compress/Compressor.java  2006-07-25 
16:18:57 UTC (rev 9752)
@@ -3,8 +3,8 @@
 import java.io.IOException;

 import freenet.client.Metadata;
-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;

 /**
  * A data compressor. Contains methods to get all data compressors.

Modified: trunk/freenet/src/freenet/support/compress/GzipCompressor.java
===================================================================
--- trunk/freenet/src/freenet/support/compress/GzipCompressor.java      
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/compress/GzipCompressor.java      
2006-07-25 16:18:57 UTC (rev 9752)
@@ -8,8 +8,8 @@
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
+import freenet.support.io.Bucket;
+import freenet.support.io.BucketFactory;

 public class GzipCompressor extends Compressor {


Copied: trunk/freenet/src/freenet/support/io/ArrayBucket.java (from rev 9743, 
trunk/freenet/src/freenet/support/ArrayBucket.java)
===================================================================
--- trunk/freenet/src/freenet/support/ArrayBucket.java  2006-07-25 01:25:46 UTC 
(rev 9743)
+++ trunk/freenet/src/freenet/support/io/ArrayBucket.java       2006-07-25 
16:18:57 UTC (rev 9752)
@@ -0,0 +1,187 @@
+package freenet.support.io;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * 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;
+
+       public ArrayBucket() {
+               this("ArrayBucket");
+       }
+
+       public ArrayBucket(byte[] initdata) {
+               this("ArrayBucket");
+               data.add(initdata);
+       }
+
+       public ArrayBucket(String name) {
+               data = new ArrayList();
+               this.name = name;
+       }
+
+       public OutputStream getOutputStream() throws IOException {
+               if(readOnly) throw new IOException("Read only");
+               return new ArrayBucketOutputStream();
+       }
+
+       public InputStream getInputStream() {
+               return new ArrayBucketInputStream();
+       }
+
+       public String toString() {
+               StringBuffer s = new StringBuffer(250);
+               for (Iterator i = data.iterator(); i.hasNext();) {
+                       byte[] b = (byte[]) i.next();
+                       s.append(new String(b));
+               }
+               return s.toString();
+       }
+
+       public void read(InputStream in) throws IOException {
+               OutputStream out = new ArrayBucketOutputStream();
+               int i;
+               byte[] b = new byte[8 * 1024];
+               while ((i = in.read(b)) != -1) {
+                       out.write(b, 0, i);
+               }
+               out.close();
+       }
+
+       public long size() {
+               long size = 0;
+               for (Iterator i = data.iterator(); i.hasNext();) {
+                       byte[] b = (byte[]) i.next();
+                       size += b.length;
+               }
+               return size;
+       }
+
+       public String getName() {
+               return name;
+       }
+
+       private class ArrayBucketOutputStream extends ByteArrayOutputStream {
+               
+               public ArrayBucketOutputStream() {
+                       super();
+               }
+
+               public void close() throws IOException {
+                       data.add(toByteArray());
+                       if(readOnly) throw new IOException("Read only");
+                       // FIXME maybe we should throw on write instead? :)
+               }
+       }
+
+       private class ArrayBucketInputStream extends InputStream {
+               
+               private Iterator i;
+               private ByteArrayInputStream in;
+
+               public ArrayBucketInputStream() {
+                       i = data.iterator();
+               }
+
+               public int read() {
+                       return priv_read();
+               }
+
+               private int priv_read() {
+                       if (in == null) {
+                               if (i.hasNext()) {
+                                       in = new ByteArrayInputStream((byte[]) 
i.next());
+                               } else {
+                                       return -1;
+                               }
+                       }
+                       int i = in.read();
+                       if (i == -1) {
+                               in = null;
+                               return priv_read();
+                       } else {
+                               return i;
+                       }
+               }
+
+               public int read(byte[] b) {
+                       return priv_read(b, 0, b.length);
+               }
+
+               public int read(byte[] b, int off, int len) {
+                       return priv_read(b, off, len);
+               }
+
+               private int priv_read(byte[] b, int off, int len) {
+                       if (in == null) {
+                               if (i.hasNext()) {
+                                       in = new ByteArrayInputStream((byte[]) 
i.next());
+                               } else {
+                                       return -1;
+                               }
+                       }
+                       int i = in.read(b, off, len);
+                       if (i == -1) {
+                               in = null;
+                               return priv_read(b, off, len);
+                       } else {
+                               return i;
+                       }
+               }
+
+               public int available() {
+                       if (in == null) {
+                               if (i.hasNext()) {
+                                       in = new ByteArrayInputStream((byte[]) 
i.next());
+                               } else {
+                                       return 0;
+                               }
+                       }
+                       return in.available();
+               }
+
+       }
+
+       public boolean isReadOnly() {
+               return readOnly;
+       }
+
+       public void setReadOnly() {
+               readOnly = true;
+       }
+
+       public void free() {
+               data.clear();
+               // Not much else we can do.
+       }
+
+       public byte[] toByteArray() {
+               long sz = size();
+               int size = (int)sz;
+               byte[] buf = new byte[size];
+               int index = 0;
+               for(Iterator i=data.iterator();i.hasNext();) {
+                       byte[] obuf = (byte[]) i.next();
+                       System.arraycopy(obuf, 0, buf, index, obuf.length);
+                       index += obuf.length;
+               }
+               if(index != buf.length)
+                       throw new IllegalStateException();
+               return buf;
+       }
+}

Copied: trunk/freenet/src/freenet/support/io/ArrayBucketFactory.java (from rev 
9743, trunk/freenet/src/freenet/support/ArrayBucketFactory.java)
===================================================================
--- trunk/freenet/src/freenet/support/ArrayBucketFactory.java   2006-07-25 
01:25:46 UTC (rev 9743)
+++ trunk/freenet/src/freenet/support/io/ArrayBucketFactory.java        
2006-07-25 16:18:57 UTC (rev 9752)
@@ -0,0 +1,15 @@
+package freenet.support.io;
+
+import java.io.IOException;
+
+public class ArrayBucketFactory implements BucketFactory {
+
+       public Bucket makeBucket(long size) throws IOException {
+               return new ArrayBucket();
+       }
+
+       public void freeBucket(Bucket b) throws IOException {
+               // Do nothing
+       }
+
+}

Copied: trunk/freenet/src/freenet/support/io/Bucket.java (from rev 9743, 
trunk/freenet/src/freenet/support/Bucket.java)
===================================================================
--- trunk/freenet/src/freenet/support/Bucket.java       2006-07-25 01:25:46 UTC 
(rev 9743)
+++ trunk/freenet/src/freenet/support/io/Bucket.java    2006-07-25 16:18:57 UTC 
(rev 9752)
@@ -0,0 +1,50 @@
+package freenet.support.io;
+import java.io.*;
+/**
+ * A bucket is any arbitrary object can temporarily store data.
+ * 
+ * @author oskar
+ */
+public interface Bucket {
+
+    /**
+     * Returns an OutputStream that is used to put data in this Bucket, from 
the 
+     * beginning. It is not possible to append data to a Bucket! This 
simplifies the
+     * code significantly for some classes. If you need to append, just pass 
the 
+     * OutputStream around.
+     */
+    public OutputStream getOutputStream() throws IOException;
+
+    /**
+     * Returns an InputStream that reads data from this Bucket. If there is
+     * no data in this bucket, null is returned.
+     */
+    public InputStream getInputStream() throws IOException;
+
+    /**
+     * Returns a name for the bucket, may be used to identify them in
+     * certain in certain situations.
+     */
+    public String getName();
+
+    /**
+     * Returns the amount of data currently in this bucket.
+     */
+    public long size();
+
+    /**
+     * Is the bucket read-only?
+     */
+    public boolean isReadOnly();
+    
+    /**
+     * Make the bucket read-only. Irreversible.
+     */
+    public void setReadOnly();
+
+    /**
+     * Free the bucket, if supported.
+     */
+       public void free();
+
+}

Copied: trunk/freenet/src/freenet/support/io/BucketFactory.java (from rev 9743, 
trunk/freenet/src/freenet/support/BucketFactory.java)
===================================================================
--- trunk/freenet/src/freenet/support/BucketFactory.java        2006-07-25 
01:25:46 UTC (rev 9743)
+++ trunk/freenet/src/freenet/support/io/BucketFactory.java     2006-07-25 
16:18:57 UTC (rev 9752)
@@ -0,0 +1,10 @@
+package freenet.support.io;
+
+import java.io.IOException;
+
+
+public interface BucketFactory {
+    public Bucket makeBucket(long size) throws IOException;
+    public void freeBucket(Bucket b) throws IOException;
+}
+

Copied: trunk/freenet/src/freenet/support/io/BucketTools.java (from rev 9743, 
trunk/freenet/src/freenet/support/BucketTools.java)
===================================================================
--- trunk/freenet/src/freenet/support/BucketTools.java  2006-07-25 01:25:46 UTC 
(rev 9743)
+++ trunk/freenet/src/freenet/support/io/BucketTools.java       2006-07-25 
16:18:57 UTC (rev 9752)
@@ -0,0 +1,476 @@
+package freenet.support.io;
+
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+
+import freenet.support.Logger;
+
+/**
+ * Helper functions for working with Buckets.
+ */
+public class BucketTools {
+
+       static final int BLOCK_SIZE = 4096;
+       
+       /**
+        * Copy from the input stream of <code>src</code> to the output stream 
of
+        * <code>dest</code>.
+        * 
+        * @param src
+        * @param dst
+        * @throws IOException
+        */
+       public final static void copy(Bucket src, Bucket dst) throws 
IOException {
+               OutputStream out = dst.getOutputStream();
+               InputStream in = src.getInputStream();
+               ReadableByteChannel readChannel = Channels.newChannel(in);
+               WritableByteChannel writeChannel = Channels.newChannel(out);
+
+               ByteBuffer buffer = ByteBuffer.allocateDirect(BLOCK_SIZE);
+               while (readChannel.read(buffer) != -1) {
+                       buffer.flip();
+                       writeChannel.write(buffer);
+                       buffer.clear();
+               }
+
+               writeChannel.close();
+               readChannel.close();
+               out.close();
+               in.close();
+       }
+
+       public final static void zeroPad(Bucket b, long size) throws 
IOException {
+               OutputStream out = b.getOutputStream();
+
+               // Initialized to zero by default.
+               byte[] buffer = new byte[16384];
+
+               long count = 0;
+               while (count < size) {
+                       long nRequired = buffer.length;
+                       if (nRequired > size - count) {
+                               nRequired = size - count;
+                       }
+                       out.write(buffer, 0, (int) nRequired);
+                       count += nRequired;
+               }
+
+               out.close();
+       }
+
+       public final static void paddedCopy(Bucket from, Bucket to, long nBytes,
+                       int blockSize) throws IOException {
+
+               if (nBytes > blockSize) {
+                       throw new IllegalArgumentException("nBytes > 
blockSize");
+               }
+
+               OutputStream out = null;
+               InputStream in = null;
+
+               try {
+
+                       out = to.getOutputStream();
+                       byte[] buffer = new byte[16384];
+                       in = from.getInputStream();
+
+                       long count = 0;
+                       while (count != nBytes) {
+                               long nRequired = nBytes - count;
+                               if (nRequired > buffer.length) {
+                                       nRequired = buffer.length;
+                               }
+                               long nRead = in.read(buffer, 0, (int) 
nRequired);
+                               if (nRead == -1) {
+                                       throw new IOException("Not enough data 
in source bucket.");
+                               }
+                               out.write(buffer, 0, (int) nRead);
+                               count += nRead;
+                       }
+
+                       if (count < blockSize) {
+                               // hmmm... better to just allocate a new buffer
+                               // instead of explicitly zeroing the old one?
+                               // Zero pad to blockSize
+                               long padLength = buffer.length;
+                               if (padLength > blockSize - nBytes) {
+                                       padLength = blockSize - nBytes;
+                               }
+                               for (int i = 0; i < padLength; i++) {
+                                       buffer[i] = 0;
+                               }
+
+                               while (count != blockSize) {
+                                       long nRequired = blockSize - count;
+                                       if (blockSize - count > buffer.length) {
+                                               nRequired = buffer.length;
+                                       }
+                                       out.write(buffer, 0, (int) nRequired);
+                                       count += nRequired;
+                               }
+                       }
+               } finally {
+                       if (in != null)
+                               in.close();
+                       if (out != null)
+                               out.close();
+               }
+       }
+
+       public static class BucketFactoryWrapper implements BucketFactory {
+               public BucketFactoryWrapper(BucketFactory bf) {
+                       BucketFactoryWrapper.this.bf = bf;
+               }
+               public Bucket makeBucket(long size) throws IOException {
+                       return bf.makeBucket(size);
+               }
+
+               public void freeBucket(Bucket b) throws IOException {
+                       if (b instanceof RandomAccessFileBucket) {
+                               ((RandomAccessFileBucket) b).release();
+                               return;
+                       }
+                       bf.freeBucket(b);
+               }
+               private BucketFactory bf = null;
+       }
+
+       public static Bucket[] makeBuckets(BucketFactory bf, int count, int 
size)
+               throws IOException {
+               Bucket[] ret = new Bucket[count];
+               for (int i = 0; i < count; i++) {
+                       ret[i] = bf.makeBucket(size);
+               }
+               return ret;
+       }
+
+       /**
+        * Free buckets. Get yer free buckets here! No charge! All you can carry
+        * free buckets!
+        * <p>
+        * If an exception happens the method will attempt to free the remaining
+        * buckets then retun the first exception. Buckets successfully freed 
are
+        * made <code>null</code> in the array.
+        * </p>
+        * 
+        * @param bf
+        * @param buckets
+        * @throws IOException
+        *             the first exception The <code>buckets</code> array will
+        */
+       public static void freeBuckets(BucketFactory bf, Bucket[] buckets)
+               throws IOException {
+               if (buckets == null) {
+                       return;
+               }
+
+               IOException firstIoe = null;
+
+               for (int i = 0; i < buckets.length; i++) {
+                       // Make sure we free any temp buckets on exception
+                       try {
+                               if (buckets[i] != null) {
+                                       bf.freeBucket(buckets[i]);
+                               }
+                               buckets[i] = null;
+                       } catch (IOException e) {
+                               if (firstIoe == null) {
+                                       firstIoe = e;
+                               }
+                       }
+               }
+
+               if (firstIoe != null) {
+                       throw firstIoe;
+               }
+       }
+
+       // Note: Not all buckets are allocated by the bf.
+       //       You must use the BucketFactoryWrapper class above
+       //       to free the returned buckets.
+       //
+       // Always returns blocks, blocks, even if it has to create
+       // zero padded ones.
+       public static Bucket[] splitFile(
+               File file,
+               int blockSize,
+               long offset,
+               int blocks,
+               boolean readOnly,
+               BucketFactoryWrapper bf)
+               throws IOException {
+
+               long len = file.length() - offset;
+               if (len > blocks * blockSize) {
+                       len = blocks * blockSize;
+               }
+
+               long padBlocks = 0;
+               if ((blocks * blockSize) - len >= blockSize) {
+                       padBlocks = ((blocks * blockSize) - len) / blockSize;
+               }
+
+               Bucket[] ret = new Bucket[blocks];
+               Bucket[] rab =
+                       RandomAccessFileBucket.segment(
+                               file,
+                               blockSize,
+                               offset,
+                               (int) (blocks - padBlocks),
+                               true);
+               System.arraycopy(rab, 0, ret, 0, rab.length);
+
+               boolean groovy = false;
+               try {
+                       if (len % blockSize != 0) {
+                               // Copy and zero pad final partial block
+                               Bucket partial = ret[rab.length - 1];
+                               ret[rab.length - 1] = bf.makeBucket(blockSize);
+                               paddedCopy(
+                                       partial,
+                                       ret[rab.length - 1],
+                                       len % blockSize,
+                                       blockSize);
+                       }
+
+                       // Trailing zero padded blocks
+                       for (int i = rab.length; i < ret.length; i++) {
+                               ret[i] = bf.makeBucket(blockSize);
+                               zeroPad(ret[i], blockSize);
+                       }
+                       groovy = true;
+               } finally {
+                       if (!groovy) {
+                               freeBuckets(bf, ret);
+                       }
+               }
+               return ret;
+       }
+
+       public final static int[] nullIndices(Bucket[] array) {
+               List list = new ArrayList();
+               for (int i = 0; i < array.length; i++) {
+                       if (array[i] == null) {
+                               list.add(new Integer(i));
+                       }
+               }
+
+               int[] ret = new int[list.size()];
+               for (int i = 0; i < list.size(); i++) {
+                       ret[i] = ((Integer) list.get(i)).intValue();
+               }
+               return ret;
+       }
+
+       public final static int[] nonNullIndices(Bucket[] array) {
+               List list = new ArrayList();
+               for (int i = 0; i < array.length; i++) {
+                       if (array[i] != null) {
+                               list.add(new Integer(i));
+                       }
+               }
+
+               int[] ret = new int[list.size()];
+               for (int i = 0; i < list.size(); i++) {
+                       ret[i] = ((Integer) list.get(i)).intValue();
+               }
+               return ret;
+       }
+
+       public final static Bucket[] nonNullBuckets(Bucket[] array) {
+               List list = new ArrayList(array.length);
+               for (int i = 0; i < array.length; i++) {
+                       if (array[i] != null) {
+                               list.add(array[i]);
+                       }
+               }
+
+               Bucket[] ret = new Bucket[list.size()];
+               return (Bucket[]) list.toArray(ret);
+       }
+
+       /**
+        * Read the entire bucket in as a byte array.
+        * Not a good idea unless it is very small!
+        * Don't call if concurrent writes may be happening.
+        * @throws IOException If there was an error reading from the bucket.
+        * @throws OutOfMemoryError If it was not possible to allocate enough 
+        * memory to contain the entire bucket.
+        */
+       public final static byte[] toByteArray(Bucket bucket) throws 
IOException {
+               long size = bucket.size();
+               if(size > Integer.MAX_VALUE) throw new OutOfMemoryError();
+               byte[] data = new byte[(int)size];
+               InputStream is = bucket.getInputStream();
+               try {
+                       DataInputStream dis = new DataInputStream(is);
+                       dis.readFully(data);
+               } finally {
+                       is.close();
+               }
+               return data;
+       }
+
+       public static int toByteArray(Bucket bucket, byte[] output) throws 
IOException {
+               long size = bucket.size();
+               if(size > output.length)
+                       throw new IllegalArgumentException("Data does not fit 
in provided buffer");
+               InputStream is = bucket.getInputStream();
+               int moved = 0;
+               while(true) {
+                       if(moved == size) return moved;
+                       int x = is.read(output, moved, (int)(size - moved));
+                       if(x == -1) return moved;
+                       moved += x;
+               }
+       }
+       
+       public static Bucket makeImmutableBucket(BucketFactory bucketFactory, 
byte[] data) throws IOException {
+               Bucket bucket = bucketFactory.makeBucket(data.length);
+               OutputStream os = bucket.getOutputStream();
+               os.write(data);
+               os.close();
+               bucket.setReadOnly();
+               return bucket;
+       }
+
+       public static byte[] hash(Bucket data) throws IOException {
+               InputStream is = null;
+               try {
+                       MessageDigest md = MessageDigest.getInstance("SHA-256");
+                       is = data.getInputStream();
+                       long bucketLength = data.size();
+                       long bytesRead = 0;
+                       byte[] buf = new byte[4096];
+                       while((bytesRead < bucketLength) || (bucketLength == 
-1)) {
+                               int readBytes = is.read(buf);
+                               if(readBytes < 0) break;
+                               bytesRead += readBytes;
+                               md.update(buf, 0, readBytes);
+                       }
+                       if((bytesRead < bucketLength) && (bucketLength > 0))
+                               throw new EOFException();
+                       if((bytesRead != bucketLength) && (bucketLength > 0))
+                               throw new IOException("Read "+bytesRead+" but 
bucket length "+bucketLength+"!");
+                       return md.digest();
+               } catch (NoSuchAlgorithmException e) {
+                       Logger.error(BucketTools.class, "No such digest: 
SHA-256 !!");
+                       throw new Error("No such digest: SHA-256 !!");
+               } finally {
+                       if(is != null) is.close();
+               }
+       }
+
+       /** Copy the given quantity of data from the given bucket to the given 
OutputStream. 
+        * @throws IOException If there was an error reading from the bucket or 
writing to the stream. */
+       public static void copyTo(Bucket decodedData, OutputStream os, long 
truncateLength) throws IOException {
+               if(truncateLength == 0) return;
+               if(truncateLength < 0) truncateLength = Long.MAX_VALUE;
+               InputStream is = decodedData.getInputStream();
+               try {
+                       byte[] buf = new byte[4096];
+                       long moved = 0;
+                       while(moved < truncateLength) {
+                               // DO NOT move the (int) inside the Math.min()! 
big numbers truncate to negative numbers.
+                               int bytes = (int) Math.min(buf.length, 
truncateLength - moved);
+                               if(bytes <= 0)
+                                       throw new 
IllegalStateException("bytes="+bytes+", truncateLength="+truncateLength+", 
moved="+moved);
+                               bytes = is.read(buf, 0, bytes);
+                               if(bytes <= 0) {
+                                       if(truncateLength == Long.MAX_VALUE)
+                                               break;
+                                       throw new IOException("Could not move 
required quantity of data: "+bytes+" (moved "+moved+" of "+truncateLength+")");
+                               }
+                               os.write(buf, 0, bytes);
+                               moved += bytes;
+                       }
+               } finally {
+                       is.close();
+               }
+       }
+
+       /** Copy data from an InputStream into a Bucket. */
+       public static void copyFrom(Bucket bucket, InputStream is, long 
truncateLength) throws IOException {
+               OutputStream os = bucket.getOutputStream();
+               byte[] buf = new byte[4096];
+               if(truncateLength < 0) truncateLength = Long.MAX_VALUE;
+               try {
+                       long moved = 0;
+                       while(moved < truncateLength) {
+                               // DO NOT move the (int) inside the Math.min()! 
big numbers truncate to negative numbers.
+                               int bytes = (int) Math.min(buf.length, 
truncateLength - moved);
+                               if(bytes <= 0)
+                                       throw new 
IllegalStateException("bytes="+bytes+", truncateLength="+truncateLength+", 
moved="+moved);
+                               bytes = is.read(buf, 0, bytes);
+                               if(bytes <= 0) {
+                                       if(truncateLength == Long.MAX_VALUE)
+                                               break;
+                                       throw new IOException("Could not move 
required quantity of data: "+bytes+" (moved "+moved+" of "+truncateLength+")");
+                               }
+                               os.write(buf, 0, bytes);
+                               moved += bytes;
+                       }
+               } finally {
+                       os.close();
+               }
+       }
+
+       /**
+        * Split the data into a series of read-only Bucket's.
+        * @param origData The original data Bucket.
+        * @param splitSize The number of bytes to put into each bucket.
+        * 
+        * FIXME This could be made many orders of magnitude more efficient on
+        * time and space if the underlying Bucket happens to be a passed-in
+        * plaintext file!
+        * 
+        * Note that this method will allocate a buffer of size splitSize.
+        * @throws IOException If there is an error creating buckets, reading 
from
+        * the provided bucket, or writing to created buckets.
+        */
+       public static Bucket[] split(Bucket origData, int splitSize, 
BucketFactory bf) throws IOException {
+               if(origData instanceof FileBucket) {
+                       return ((FileBucket)origData).split(splitSize);
+               }
+               long length = origData.size();
+               if(length > ((long)Integer.MAX_VALUE) * splitSize)
+                       throw new IllegalArgumentException("Way too big!: 
"+length+" for "+splitSize);
+               int bucketCount = (int) (length / splitSize);
+               if(length % splitSize > 0) bucketCount++;
+               Bucket[] buckets = new Bucket[bucketCount];
+               InputStream is = origData.getInputStream();
+               try {
+                       DataInputStream dis = new DataInputStream(is);
+                       long remainingLength = length;
+                       byte[] buf = new byte[splitSize];
+                       for(int i=0;i<bucketCount;i++) {
+                               int len = (int) Math.min(splitSize, 
remainingLength);
+                               Bucket bucket = bf.makeBucket(len);
+                               buckets[i] = bucket;
+                               dis.readFully(buf, 0, len);
+                               remainingLength -= len;
+                               OutputStream os = bucket.getOutputStream();
+                               try {
+                                       os.write(buf, 0, len);
+                               } finally {
+                                       os.close();
+                               }
+                       }
+               } finally {
+                       is.close();
+               }
+               return buckets;
+       }
+}

Modified: trunk/freenet/src/freenet/support/io/FileBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/FileBucket.java        2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/io/FileBucket.java        2006-07-25 
16:18:57 UTC (rev 9752)
@@ -9,9 +9,7 @@
 import java.io.OutputStream;

 import freenet.crypt.RandomSource;
-import freenet.support.Bucket;
 import freenet.support.Logger;
-import freenet.support.ReadOnlyFileSliceBucket;
 import freenet.support.SimpleFieldSet;

 /**

Modified: trunk/freenet/src/freenet/support/io/FileBucketFactory.java
===================================================================
--- trunk/freenet/src/freenet/support/io/FileBucketFactory.java 2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/io/FileBucketFactory.java 2006-07-25 
16:18:57 UTC (rev 9752)
@@ -4,8 +4,6 @@
 import java.io.IOException;
 import java.util.Vector;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
 import freenet.support.Logger;

 public class FileBucketFactory implements BucketFactory {

Modified: trunk/freenet/src/freenet/support/io/NullBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/NullBucket.java        2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/io/NullBucket.java        2006-07-25 
16:18:57 UTC (rev 9752)
@@ -2,7 +2,6 @@
 import java.io.InputStream;
 import java.io.OutputStream;

-import freenet.support.Bucket;
 import freenet.support.SimpleFieldSet;

 public class NullBucket implements Bucket, SerializableToFieldSetBucket {

Copied: 
trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java 
(from rev 9743, 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java)
===================================================================
--- trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java     
2006-07-25 01:25:46 UTC (rev 9743)
+++ trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java  
2006-07-25 16:18:57 UTC (rev 9752)
@@ -0,0 +1,363 @@
+package freenet.support.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.spaceroots.mantissa.random.MersenneTwister;
+
+import freenet.crypt.PCFBMode;
+import freenet.crypt.RandomSource;
+import freenet.crypt.UnsupportedCipherException;
+import freenet.crypt.ciphers.Rijndael;
+import freenet.support.HexUtil;
+import freenet.support.Logger;
+import freenet.support.SimpleFieldSet;
+
+/**
+ * A proxy Bucket which adds:
+ * - Encryption with the supplied cipher, and a random, ephemeral key.
+ * - Padding to the next PO2 size.
+ */
+public class PaddedEphemerallyEncryptedBucket implements Bucket, 
SerializableToFieldSetBucket {
+
+       private final Bucket bucket;
+       private final int minPaddedSize;
+       private final RandomSource origRandom;
+       private final Rijndael aes;
+       /** The decryption key. May be null. */
+       private final byte[] key;
+       private long dataLength;
+       private boolean readOnly;
+       private int lastOutputStream;
+       
+       /**
+        * Create a padded encrypted proxy bucket.
+        * @param bucket The bucket which we are proxying to. Must be empty.
+        * @param pcfb The encryption mode with which to encipher/decipher the 
data.
+        * @param minSize The minimum padded size of the file (after it has 
been closed).
+        * @param origRandom Hard random number generator from which to obtain 
a seed for padding.
+        * @throws UnsupportedCipherException 
+        */
+       public PaddedEphemerallyEncryptedBucket(Bucket bucket, int minSize, 
RandomSource origRandom, boolean forgetKey) {
+               this.origRandom = origRandom;
+               this.bucket = bucket;
+               if(bucket.size() != 0) throw new 
IllegalArgumentException("Bucket must be empty");
+               try {
+                       aes = new Rijndael(256, 256);
+               } catch (UnsupportedCipherException e) {
+                       throw new Error(e);
+               }
+               byte[] tempKey = new byte[32];
+               origRandom.nextBytes(tempKey);
+               aes.initialize(tempKey);
+               if(forgetKey) {
+                       // Might as well blank it
+                       for(int i=0;i<tempKey.length;i++) tempKey[i] = 0;
+                       this.key = null;
+               } else {
+                       this.key = tempKey;
+               }
+               this.minPaddedSize = minSize;
+               readOnly = false;
+               lastOutputStream = 0;
+       }
+
+       /**
+        * Load an existing PaddedEphemerallyEncryptedBucket, with a key.
+        * The bucket can and should already exist.
+        * @param bucket
+        * @param minSize
+        * @param knownSize The size of the data. This cannot be deduced from 
the bucket
+        * alone and must be specified. If the bucket is smaller than this, we 
throw.
+        * @param key
+        * @param origRandom
+        * @throws IOException 
+        */
+       public PaddedEphemerallyEncryptedBucket(Bucket bucket, int minSize, 
long knownSize, byte[] key, RandomSource origRandom) throws IOException {
+               if(bucket.size() < knownSize)
+                       throw new IOException("Bucket is too small on disk - 
knownSize="+knownSize+" but bucket.size="+bucket.size()+" for "+bucket);
+               this.dataLength = knownSize;
+               this.origRandom = origRandom;
+               this.bucket = bucket;
+               try {
+                       aes = new Rijndael(256, 256);
+               } catch (UnsupportedCipherException e) {
+                       throw new Error(e);
+               }
+               aes.initialize(key);
+               this.key = key;
+               this.minPaddedSize = minSize;
+               readOnly = false;
+               lastOutputStream = 0;
+       }
+
+       public PaddedEphemerallyEncryptedBucket(SimpleFieldSet fs, RandomSource 
origRandom, PersistentFileTracker f) throws CannotCreateFromFieldSetException {
+               this.origRandom = origRandom;
+               String tmp = fs.get("DataLength");
+               if(tmp == null)
+                       throw new CannotCreateFromFieldSetException("No 
DataLength");
+               try {
+                       dataLength = Long.parseLong(tmp);
+               } catch (NumberFormatException e) {
+                       throw new CannotCreateFromFieldSetException("Corrupt 
dataLength: "+tmp, e);
+               }
+               SimpleFieldSet underlying = fs.subset("Underlying");
+               if(underlying == null)
+                       throw new CannotCreateFromFieldSetException("No 
underlying bucket");
+               bucket = SerializableToFieldSetBucketUtil.create(underlying, 
origRandom, f);
+               tmp = fs.get("DecryptKey");
+               if(tmp == null)
+                       throw new CannotCreateFromFieldSetException("No key");
+               key = HexUtil.hexToBytes(tmp);
+               try {
+                       aes = new Rijndael(256, 256);
+               } catch (UnsupportedCipherException e) {
+                       throw new Error(e);
+               }
+               aes.initialize(key);
+               tmp = fs.get("MinPaddedSize");
+               if(tmp == null)
+                       minPaddedSize = 1024; // FIXME throw! back 
compatibility hack
+               else {
+                       try {
+                               minPaddedSize = Integer.parseInt(tmp);
+                       } catch (NumberFormatException e) {
+                               throw new 
CannotCreateFromFieldSetException("Corrupt dataLength: "+tmp, e);
+                       }
+               }
+               if(dataLength > bucket.size())
+                       throw new CannotCreateFromFieldSetException("Underlying 
bucket is too small: should be "+dataLength+" actually "+bucket.size());
+       }
+
+       public OutputStream getOutputStream() throws IOException {
+               if(readOnly) throw new IOException("Read only");
+               OutputStream os = bucket.getOutputStream();
+               synchronized(this) {
+                       dataLength = 0;
+               }
+               return new PaddedEphemerallyEncryptedOutputStream(os, 
++lastOutputStream);
+       }
+
+       private class PaddedEphemerallyEncryptedOutputStream extends 
OutputStream {
+
+               final PCFBMode pcfb;
+               final OutputStream out;
+               final int streamNumber;
+               private boolean closed;
+               
+               public PaddedEphemerallyEncryptedOutputStream(OutputStream out, 
int streamNumber) {
+                       this.out = out;
+                       dataLength = 0;
+                       this.streamNumber = streamNumber;
+                       pcfb = new PCFBMode(aes);
+               }
+               
+               public void write(int b) throws IOException {
+                       if(closed) throw new IOException("Already closed!");
+                       if(streamNumber != lastOutputStream)
+                               throw new IllegalStateException("Writing to old 
stream in "+getName());
+                       if((b < 0) || (b > 255))
+                               throw new IllegalArgumentException();
+                       int toWrite = pcfb.encipher(b);
+                       synchronized(PaddedEphemerallyEncryptedBucket.this) {
+                               out.write(toWrite);
+                               dataLength++;
+                       }
+               }
+               
+               public void write(byte[] buf, int offset, int length) throws 
IOException {
+                       if(closed) throw new IOException("Already closed!");
+                       if(streamNumber != lastOutputStream)
+                               throw new IllegalStateException("Writing to old 
stream in "+getName());
+                       byte[] enc = new byte[length];
+                       System.arraycopy(buf, offset, enc, 0, length);
+                       pcfb.blockEncipher(enc, 0, enc.length);
+                       synchronized(PaddedEphemerallyEncryptedBucket.this) {
+                               out.write(enc, 0, enc.length);
+                               dataLength += enc.length;
+                       }
+               }
+               
+               // Override this or FOS will use write(int)
+               public void write(byte[] buf) throws IOException {
+                       if(closed) throw new IOException("Already closed!");
+                       if(streamNumber != lastOutputStream)
+                               throw new IllegalStateException("Writing to old 
stream in "+getName());
+                       write(buf, 0, buf.length);
+               }
+               
+               public void close() throws IOException {
+                       if(closed) return;
+                       try {
+                               if(streamNumber != lastOutputStream) {
+                                       Logger.normal(this, "Not padding out to 
length because have been superceded: "+getName());
+                                       return;
+                               }
+                               
synchronized(PaddedEphemerallyEncryptedBucket.this) {
+                                       MersenneTwister paddingSource = new 
MersenneTwister(origRandom.nextLong());
+                                       long finalLength = paddedLength();
+                                       long padding = finalLength - dataLength;
+                                       byte[] buf = new byte[4096];
+                                       long writtenPadding = 0;
+                                       while(writtenPadding < padding) {
+                                               int left = Math.min((int) 
(padding - writtenPadding), buf.length);
+                                               paddingSource.nextBytes(buf);
+                                               out.write(buf, 0, left);
+                                               writtenPadding += left;
+                                       }
+                               }
+                       } finally {
+                               closed = true;
+                               out.close();
+                       }
+               }
+       }
+
+       public InputStream getInputStream() throws IOException {
+               return new 
PaddedEphemerallyEncryptedInputStream(bucket.getInputStream());
+       }
+
+       private class PaddedEphemerallyEncryptedInputStream extends InputStream 
{
+
+               final InputStream in;
+               final PCFBMode pcfb;
+               long ptr;
+               
+               public PaddedEphemerallyEncryptedInputStream(InputStream in) {
+                       this.in = in;
+                       pcfb = new PCFBMode(aes);
+                       ptr = 0;
+               }
+               
+               public int read() throws IOException {
+                       if(ptr > dataLength) return -1;
+                       int x = in.read();
+                       if(x == -1) return x;
+                       ptr++;
+                       return pcfb.decipher(x);
+               }
+               
+               public final int available() {
+                       int x = (int)(dataLength - ptr);
+                       return (x < 0) ? 0 : x;
+               }
+               
+               public int read(byte[] buf, int offset, int length) throws 
IOException {
+                       // FIXME remove debugging
+                       if((length+offset > buf.length) || (offset < 0) || 
(length < 0))
+                               throw new 
ArrayIndexOutOfBoundsException("a="+offset+", b="+length+", length 
"+buf.length);
+                       int x = available();
+                       if(x <= 0) return -1;
+                       length = Math.min(length, x);
+                       int readBytes = in.read(buf, offset, length);
+                       if(readBytes <= 0) return readBytes;
+                       ptr += readBytes;
+                       pcfb.blockDecipher(buf, offset, readBytes);
+                       return readBytes;
+               }
+
+               public int read(byte[] buf) throws IOException {
+                       return read(buf, 0, buf.length);
+               }
+               
+               public long skip(long bytes) throws IOException {
+                       byte[] buf = new byte[(int)Math.min(4096, bytes)];
+                       long skipped = 0;
+                       while(skipped < bytes) {
+                               int x = read(buf, 0, 
(int)Math.min(bytes-skipped, buf.length));
+                               if(x <= 0) return skipped;
+                               skipped += x;
+                       }
+                       return skipped;
+               }
+               
+               public void close() throws IOException {
+                       in.close();
+               }
+       }
+
+       /**
+        * Return the length of the data in the proxied bucket, after padding.
+        */
+       public synchronized long paddedLength() {
+               long size = dataLength;
+               if(size < minPaddedSize) size = minPaddedSize;
+               if(size == minPaddedSize) return size;
+               long min = minPaddedSize;
+               long max = minPaddedSize << 1;
+               while(true) {
+                       if(max < 0)
+                               throw new Error("Impossible size: "+size+" - 
min="+min+", max="+max);
+                       if(size < min)
+                               throw new IllegalStateException("???");
+                       if((size >= min) && (size <= max)) {
+                               Logger.minor(this, "Padded: "+max+" was: 
"+dataLength+" for "+getName());
+                               return max;
+                       }
+                       min = max;
+                       max = max << 1;
+               }
+       }
+
+       public String getName() {
+               return "Encrypted:"+bucket.getName();
+       }
+
+       public String toString() {
+               return super.toString()+":"+bucket.toString();
+       }
+       
+       public synchronized long size() {
+               return dataLength;
+       }
+
+       public boolean isReadOnly() {
+               return readOnly;
+       }
+       
+       public void setReadOnly() {
+               readOnly = true;
+       }
+
+       /**
+        * @return The underlying Bucket.
+        */
+       public Bucket getUnderlying() {
+               return bucket;
+       }
+
+       public void free() {
+               bucket.free();
+       }
+
+       /**
+        * Get the decryption key. May have been blanked out.
+        */
+       public byte[] getKey() {
+               return key;
+       }
+
+       public SimpleFieldSet toFieldSet() {
+               SimpleFieldSet fs = new SimpleFieldSet(true);
+               fs.put("Type", "PaddedEphemerallyEncryptedBucket");
+               synchronized(this) {
+                       fs.put("DataLength", dataLength);
+               }
+               if(key != null) {
+                       fs.put("DecryptKey", HexUtil.bytesToHex(key));
+               } else {
+                       Logger.error(this, "Cannot serialize because no key");
+                       return null;
+               }
+               if(bucket instanceof SerializableToFieldSetBucket) {
+                       fs.put("Underlying", 
((SerializableToFieldSetBucket)bucket).toFieldSet());
+               } else {
+                       Logger.error(this, "Cannot serialize underlying bucket: 
"+bucket);
+                       return null;
+               }
+               fs.put("MinPaddedSize", minPaddedSize);
+               return fs;
+       }
+
+}

Copied: 
trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java
 (from rev 9743, 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java)
===================================================================
--- 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java  
    2006-07-25 01:25:46 UTC (rev 9743)
+++ 
trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java
   2006-07-25 16:18:57 UTC (rev 9752)
@@ -0,0 +1,31 @@
+package freenet.support.io;
+
+import java.io.IOException;
+
+import freenet.crypt.RandomSource;
+
+/**
+ * Factory wrapper for PaddedEphemerallyEncryptedBucket's, which are themselves
+ * wrappers.
+ */
+public class PaddedEphemerallyEncryptedBucketFactory implements BucketFactory {
+
+       final BucketFactory baseFactory;
+       final RandomSource random;
+       final int minSize;
+       
+       public PaddedEphemerallyEncryptedBucketFactory(BucketFactory factory, 
RandomSource r, int minSize) {
+               baseFactory = factory;
+               this.minSize = minSize;
+               this.random = r;
+       }
+
+       public Bucket makeBucket(long size) throws IOException {
+               return new 
PaddedEphemerallyEncryptedBucket(baseFactory.makeBucket(size), minSize, random, 
true);
+       }
+
+       public void freeBucket(Bucket b) throws IOException {
+               
baseFactory.freeBucket(((PaddedEphemerallyEncryptedBucket)b).getUnderlying());
+       }
+
+}

Modified: 
trunk/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java
===================================================================
--- 
trunk/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java  
    2006-07-25 16:14:02 UTC (rev 9751)
+++ 
trunk/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java  
    2006-07-25 16:18:57 UTC (rev 9752)
@@ -2,8 +2,6 @@

 import java.io.IOException;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;

 public class PersistentEncryptedTempBucketFactory implements BucketFactory {


Modified: trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
===================================================================
--- trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java       
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/io/PersistentTempBucketFactory.java       
2006-07-25 16:18:57 UTC (rev 9752)
@@ -7,10 +7,7 @@
 import java.util.LinkedList;

 import freenet.crypt.RandomSource;
-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
 import freenet.support.Logger;
-import freenet.support.PaddedEphemerallyEncryptedBucket;

 /**
  * Handles persistent temp files. These are used for e.g. persistent downloads.

Copied: trunk/freenet/src/freenet/support/io/RandomAccessFileBucket.java (from 
rev 9746, trunk/freenet/src/freenet/support/RandomAccessFileBucket.java)
===================================================================
--- trunk/freenet/src/freenet/support/RandomAccessFileBucket.java       
2006-07-25 14:10:01 UTC (rev 9746)
+++ trunk/freenet/src/freenet/support/io/RandomAccessFileBucket.java    
2006-07-25 16:18:57 UTC (rev 9752)
@@ -0,0 +1,466 @@
+// REDFLAG: test and javadoc
+package freenet.support.io;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.util.Vector;
+
+import freenet.support.Logger;
+import freenet.support.SimpleFieldSet;
+
+/**
+ * Bucket implementation that can efficiently access any arbitrary byte-range
+ * of a file.
+ *
+ **/
+public class RandomAccessFileBucket implements Bucket, 
SerializableToFieldSetBucket {
+
+    private final File file;
+    private final long offset;
+    private long localOffset = 0;
+    private final long len;
+    private boolean readOnly = false;
+    private boolean released = false;
+    private Vector streams = new Vector();
+    
+    public RandomAccessFileBucket(File file, long offset, long len, boolean 
readOnly)
+        throws IOException {
+        if (!(file.exists() && file.canRead())) {
+            throw new IOException("Can't read file: " + 
file.getAbsolutePath());
+        } 
+        
+        if ((!file.canWrite()) && (!readOnly)) {
+            throw new IOException("Can't write to file: " + 
file.getAbsolutePath());
+        } 
+
+        this.file = file;
+        this.readOnly = readOnly;
+        this.offset = offset;
+        this.len = len;
+    }
+
+    public RandomAccessFileBucket(SimpleFieldSet fs, PersistentFileTracker f) 
throws CannotCreateFromFieldSetException {
+               String tmp = fs.get("Filename");
+               if(tmp == null) throw new CannotCreateFromFieldSetException("No 
filename");
+               this.file = new File(tmp);
+               tmp = fs.get("Length");
+               if(tmp == null) throw new CannotCreateFromFieldSetException("No 
length");
+               try {
+                       len = Long.parseLong(tmp);
+               } catch (NumberFormatException e) {
+                       throw new CannotCreateFromFieldSetException("Corrupt 
length "+tmp, e);
+               }
+               tmp = fs.get("Offset");
+               if(tmp == null) throw new CannotCreateFromFieldSetException("No 
offset");
+               try {
+                       offset = Long.parseLong(tmp);
+               } catch (NumberFormatException e) {
+                       throw new CannotCreateFromFieldSetException("Corrupt 
offset "+tmp, e);
+               }
+       }
+
+    public static class Range {
+        Range(long offset, long len) {
+            this.offset = offset;
+            this.len = len;
+        }
+
+        public long offset;
+        public long len;
+    }
+
+    public final synchronized Range getRange() {
+        return new Range(offset, len);
+    }
+    
+    // hmmm make protected???
+    public final synchronized boolean hasOpenStreams() {
+        return streams.size() > 0;
+    }
+
+    // Wrap non-const members so we can tell
+    // when code touches the Bucket after it
+    // has been released.
+    public synchronized InputStream getInputStream() throws IOException {
+        if (isReleased()) {
+            throw new IOException("Attempt to use a released 
RandomAccessFileBucket: " + getName() );
+        }
+
+        InputStream newIn = new RAInputStream(file.getAbsolutePath());
+        streams.addElement(newIn);
+        return newIn;
+    }
+
+    public synchronized OutputStream getOutputStream() throws IOException {
+        if (isReleased()) {
+            throw new IOException("Attempt to use a released 
RandomAccessBucket: " + getName() );
+        }
+
+        if (readOnly) {
+            throw new IOException("Tried to write a read-only Bucket.");
+        }
+
+        OutputStream newOut = new RAOutputStream(file.getAbsolutePath());
+        streams.addElement(newOut);
+        return newOut;
+    }
+
+    public String getName() {
+        return file.getAbsolutePath() + " [" + offset + ", " + 
+            (offset + len - 1) + "]";
+    }
+        
+    public synchronized void resetWrite() {
+        if (isReleased()) {
+            throw new RuntimeException("Attempt to use a released 
RandomAccessFileBucket: " + getName() );
+        }
+        // REDFLAG: implicit assumptions
+        // 0) Bucket is only written to at a time.
+        // 1) The output stream is closed before the
+        //    next is open. Ouch. This may cause problems...
+        localOffset = 0;
+    }
+
+    public long size() { return len; }
+
+    public synchronized boolean release() {
+        if (released) {
+            return true;
+        }
+
+        // Force all open streams closed. 
+        // Windows won't let us delete the file unless we
+        // do this.
+        for (int i =0; i < streams.size(); i++) {
+            try {
+                if (streams.elementAt(i) instanceof InputStream) {
+                    ((InputStream)streams.elementAt(i)).close();
+
+                    Logger.debug(this, "closed open InputStream !: " + 
+                               file.getAbsolutePath());
+                }
+                else if (streams.elementAt(i) instanceof OutputStream) {
+                    ((OutputStream)streams.elementAt(i)).close();
+                    Logger.debug(this, "closed open OutputStream !: " + 
+                               file.getAbsolutePath());
+                }
+            }
+            catch (IOException ioe) {
+            }
+        }
+        streams.removeAllElements();
+        streams.trimToSize();
+        // We don't delete anything because we don't own anything.
+        released = true;
+        return true;
+    }
+
+    public synchronized final boolean isReleased() { return released; }
+
+    public void finalize() throws Throwable {
+       synchronized(this) {
+               if(released) return;
+       }
+       release();
+    }
+
+    // REDFLAG: RETEST
+    // set blocks = -1 for until end.
+    // last block may have length < blockSize
+    public static Bucket[] segment(File file, int blockSize, 
+                                   long offset, int blocks,  boolean readOnly) 
+        throws IOException {
+        
+        if (!(file.exists() && file.canRead())) {
+            throw new IOException("Can't read file: " + 
file.getAbsolutePath());
+        } 
+        
+        if ((!file.canWrite()) && (!readOnly)) {
+            throw new IOException("Can't write to file: " + 
file.getAbsolutePath());
+        } 
+        
+        if ((offset < 0) || (offset >= file.length() - 1)) {
+            throw new IllegalArgumentException("offset: " + offset);
+        }
+
+        long length = file.length() - offset;
+        int nBlocks = (int) (length / blockSize);
+        if ((length % blockSize) != 0) {
+            nBlocks++;
+        }        
+        
+        if (blocks == -1) {
+            blocks = nBlocks;
+        }
+        else if ((blocks > nBlocks) || (blocks < 1)) {
+            throw new IllegalArgumentException("blocks: " + blocks);
+        } 
+
+        Bucket[] ret = new Bucket[blocks];
+        
+        for (int i = 0; i < blocks; i++) {
+            final long localOffset = i * blockSize + offset;
+            int blockLen = blockSize;
+            if (i == nBlocks - 1) {
+                blockLen = (int) (length - (nBlocks - 1) * blockSize);
+            }
+            ret[i] = new RandomAccessFileBucket(file, localOffset, blockLen, 
readOnly);
+        }
+        
+        return ret;
+    }
+
+    ////////////////////////////////////////////////////////////
+    // InputStream and OutputStream implementations
+    //
+    private final static boolean vociferous = false;
+
+    class RAInputStream extends InputStream  {
+        public RAInputStream(String prefix) throws IOException {
+            raf = new RandomAccessFile(file, "r");
+            raf.seek(offset);
+            println(" -- Created new InputStream [" + offset + 
+                    ", " + (offset + len -1) + "]" );
+        }
+        
+        ////////////////////////////////////////////////////////////
+        // FilterInput implementation
+
+        private final int bytesLeft() throws IOException {
+                       synchronized (RandomAccessFileBucket.this) {
+                               return (int)(offset + len - 
raf.getFilePointer());
+                       }
+        }
+
+        public int read() throws java.io.IOException {
+            synchronized (RandomAccessFileBucket.this) {
+                println(".read()");
+                checkValid();
+                if (bytesLeft() < 1) {
+                    return -1; // EOF
+                } 
+                return raf.read();
+            }
+        }
+        
+        public int read(byte[] bytes) throws java.io.IOException {
+            synchronized (RandomAccessFileBucket.this) {
+                println(".read(byte[])");
+                checkValid();
+                int nAvailable = bytesLeft();
+                if (nAvailable < 1) {
+                    return -1; // EOF
+                } 
+                if (nAvailable > bytes.length) {
+                    nAvailable = bytes.length;
+                }
+                return raf.read(bytes, 0, nAvailable);
+            }
+        }
+        
+        public int read(byte[] bytes, int a, int b) throws java.io.IOException 
{
+            synchronized (RandomAccessFileBucket.this) {
+                println(".read(byte[], int, int)");
+                checkValid();
+                int nAvailable = bytesLeft();
+                if (nAvailable < 1) {
+                    return -1; // EOF
+                } 
+                if (nAvailable > b) {
+                    nAvailable = b;
+                }
+                return raf.read(bytes, a, nAvailable);
+            }
+        }
+        
+        public long skip(long a) throws java.io.IOException {
+            synchronized (RandomAccessFileBucket.this) {
+                println(".skip(long)");
+                checkValid();
+                int nAvailable = bytesLeft();
+                if (nAvailable < 1) {
+                    return -1; // EOF
+                } 
+                if (nAvailable > a) {
+                    nAvailable = (int)a;
+                }
+
+                return raf.skipBytes(nAvailable);
+            }
+        }
+        
+        public int available() throws java.io.IOException {
+            synchronized (RandomAccessFileBucket.this) {
+                println(".available()");
+                checkValid();
+                return bytesLeft();
+            }
+        }
+        
+        public void close() throws java.io.IOException {
+            synchronized (RandomAccessFileBucket.this) {
+                println(".close()");
+                checkValid();       
+                raf.close();
+                if (streams.contains(RAInputStream.this)) {
+                    streams.removeElement(RAInputStream.this);
+                }
+                streams.trimToSize();
+            }
+        }
+        
+        // LATER: support if really needed.
+        public  void mark(int a) {
+            // NOP
+        }
+
+        public void reset() {
+            // NOP
+        }
+        
+        public boolean markSupported() {
+            return false;
+        }
+
+        private final void println(String text) {
+            if (vociferous) {
+                Logger.debug(this, text);
+            }
+        }
+        
+        private final void checkValid() throws IOException {
+                       synchronized(RandomAccessFileBucket.this) {
+                               if (released) {
+                                       throw new IOException("Attempt to use a 
released RandomAccessFileBucket: " + prefix);
+                               }
+                       }
+        }
+
+        ////////////////////////////////////////////////////////////
+        private RandomAccessFile raf = null;
+        private String prefix = "";
+    }
+
+    private class RAOutputStream extends OutputStream {
+        public RAOutputStream(String pref) throws IOException {
+            raf = new RandomAccessFile(file, "rw");
+            raf.seek(offset + localOffset);
+            println(" -- Created new OutputStream [" + offset + ", " 
+                    + (offset + len -1) + "]" );
+        }
+    
+        ////////////////////////////////////////////////////////////
+        // OutputStream implementation
+        public void write(int b) throws IOException {
+            synchronized (RandomAccessFileBucket.this) {
+                println(".write(b)");
+                checkValid();
+                int nAvailable = bytesLeft();
+                if (nAvailable < 1) {
+                    throw new IOException("Attempt to write past end of 
Bucket.");
+                }
+                raf.write(b);
+            }
+        }
+    
+        public void write(byte[] buf) throws IOException {
+            synchronized (RandomAccessFileBucket.this) {
+                println(".write(buf)");
+                checkValid();
+                int nAvailable = bytesLeft();
+                if (nAvailable < buf.length) {
+                    throw new IOException("Attempt to write past end of 
Bucket.");
+                }
+                raf.write(buf);
+            }
+        }
+    
+        public void write(byte[] buf, int off, int len) throws IOException {
+            synchronized (RandomAccessFileBucket.this) {
+                println(".write(buf,off,len)");
+                checkValid();
+                int nAvailable = bytesLeft();
+                if (nAvailable < len) {
+                    throw new IOException("Attempt to write past end of 
Bucket.");
+                }
+                raf.write(buf, off, len);
+            }
+        }
+    
+        public void flush() throws IOException {
+            synchronized (RandomAccessFileBucket.this) {
+                println(".flush()");
+                checkValid();
+                // NOP? Bytes written immediately?
+                // REDFLAG: double check.
+            }
+        }
+    
+        public void close() throws IOException {
+            synchronized (RandomAccessFileBucket.this) {
+                println(".close()");
+                checkValid();
+                if (streams.contains(RAOutputStream.this)) {
+                    streams.removeElement(RAOutputStream.this);
+                }
+                streams.trimToSize();
+                long added = raf.getFilePointer() - offset;
+                if (added > 0) {
+                    // To get proper append behavior.
+                    localOffset = added;
+                }
+                
+                raf.close();
+            }
+        }
+
+        ////////////////////////////////////////////////////////////
+        private void println(String text) {
+            if (vociferous) {
+                Logger.debug(this, text);
+            }
+        }
+
+        private final void checkValid() throws IOException {
+                       synchronized (RandomAccessFileBucket.this) {
+                               if (isReleased()) {
+                                       throw new IOException("Attempt to use a 
released RandomAccessFileBucket: " + prefix);
+                               }
+                       }
+        }
+        private final int bytesLeft() throws IOException {
+                       synchronized (RandomAccessFileBucket.this) {
+                               return (int)(offset + len - 
raf.getFilePointer());
+                       }
+        }
+
+        private RandomAccessFile raf = null;
+        private String prefix = "";
+
+    }
+    ////////////////////////////////////////////////////////////
+
+    public synchronized boolean isReadOnly() {
+       return readOnly;
+    }
+    
+    public synchronized void setReadOnly() {
+       readOnly = true;
+    }
+
+       public void free() {
+               release();
+       }
+
+       public synchronized SimpleFieldSet toFieldSet() {
+               SimpleFieldSet fs = new SimpleFieldSet(true);
+               fs.put("Type", "RandomAccessFileBucket");
+               fs.put("Filename", file.toString());
+               fs.put("Offset", offset);
+               fs.put("Length", len);
+               return fs;
+       }
+}

Copied: trunk/freenet/src/freenet/support/io/ReadOnlyFileSliceBucket.java (from 
rev 9743, trunk/freenet/src/freenet/support/ReadOnlyFileSliceBucket.java)
===================================================================
--- trunk/freenet/src/freenet/support/ReadOnlyFileSliceBucket.java      
2006-07-25 01:25:46 UTC (rev 9743)
+++ trunk/freenet/src/freenet/support/io/ReadOnlyFileSliceBucket.java   
2006-07-25 16:18:57 UTC (rev 9752)
@@ -0,0 +1,120 @@
+package freenet.support.io;
+
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+
+
+/**
+ * FIXME: implement a hash verifying version of this.
+ */
+public class ReadOnlyFileSliceBucket implements Bucket {
+
+       private final File file;
+       private final long startAt;
+       private final long length;
+       
+       public ReadOnlyFileSliceBucket(File f, long startAt, long length) {
+               this.file = f;
+               this.startAt = startAt;
+               this.length = length;
+       }
+       
+       public OutputStream getOutputStream() throws IOException {
+               throw new IOException("Bucket is read-only");
+       }
+
+       public InputStream getInputStream() throws IOException {
+               return new MyInputStream();
+       }
+
+       public String getName() {
+               return "ROFS:"+file.getAbsolutePath()+":"+startAt+":"+length;
+       }
+
+       public long size() {
+               return length;
+       }
+
+       public boolean isReadOnly() {
+               return true;
+       }
+
+       public void setReadOnly() {
+               // Do nothing
+       }
+
+       class MyInputStream extends InputStream {
+
+               private RandomAccessFile f;
+               private long ptr; // relative to startAt
+               
+               MyInputStream() throws IOException {
+                       try {
+                               this.f = new RandomAccessFile(file,"r");
+                               f.seek(startAt);
+                               if(f.length() < (startAt+length))
+                                       throw new 
ReadOnlyFileSliceBucketException("File truncated? Length "+f.length()+" but 
start at "+startAt+" for "+length+" bytes");
+                               ptr = 0;
+                       } catch (FileNotFoundException e) {
+                               throw new ReadOnlyFileSliceBucketException(e);
+                       }
+               }
+               
+               public int read() throws IOException {
+                       if(ptr > length)
+                               throw new EOFException();
+                       int x = f.read();
+                       ptr++;
+                       return x;
+               }
+               
+               public int read(byte[] buf, int offset, int len) throws 
IOException {
+                       if(ptr > length)
+                               throw new EOFException();
+                       len = (int) Math.min(len, length - ptr);
+                       int x = f.read(buf, offset, len);
+                       ptr += x;
+                       return x;
+               }
+               
+               public int read(byte[] buf) throws IOException {
+                       return read(buf, 0, buf.length);
+               }
+
+               public void close() throws IOException {
+                       f.close();
+               }
+               
+               public void finalize() {
+                       try {
+                               close();
+                       } catch (IOException e) {
+                               // Ignore
+                       }
+               }
+       }
+
+       public class ReadOnlyFileSliceBucketException extends IOException {
+               private static final long serialVersionUID = -1;
+               
+               public ReadOnlyFileSliceBucketException(FileNotFoundException 
e) {
+                       super("File not found: "+e.getMessage());
+                       initCause(e);
+               }
+
+               public ReadOnlyFileSliceBucketException(String string) {
+                       super(string);
+               }
+               
+       }
+
+       public void free() {
+               // Do nothing
+       }
+       
+}

Modified: trunk/freenet/src/freenet/support/io/SerializableToFieldSetBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/SerializableToFieldSetBucket.java      
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/io/SerializableToFieldSetBucket.java      
2006-07-25 16:18:57 UTC (rev 9752)
@@ -1,6 +1,5 @@
 package freenet.support.io;

-import freenet.support.Bucket;
 import freenet.support.SimpleFieldSet;

 public interface SerializableToFieldSetBucket extends Bucket {

Modified: 
trunk/freenet/src/freenet/support/io/SerializableToFieldSetBucketUtil.java
===================================================================
--- trunk/freenet/src/freenet/support/io/SerializableToFieldSetBucketUtil.java  
2006-07-25 16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/io/SerializableToFieldSetBucketUtil.java  
2006-07-25 16:18:57 UTC (rev 9752)
@@ -1,9 +1,6 @@
 package freenet.support.io;

 import freenet.crypt.RandomSource;
-import freenet.support.Bucket;
-import freenet.support.PaddedEphemerallyEncryptedBucket;
-import freenet.support.RandomAccessFileBucket;
 import freenet.support.SimpleFieldSet;

 public class SerializableToFieldSetBucketUtil {

Modified: trunk/freenet/src/freenet/support/io/TempBucketFactory.java
===================================================================
--- trunk/freenet/src/freenet/support/io/TempBucketFactory.java 2006-07-25 
16:14:02 UTC (rev 9751)
+++ trunk/freenet/src/freenet/support/io/TempBucketFactory.java 2006-07-25 
16:18:57 UTC (rev 9752)
@@ -3,8 +3,6 @@
 import java.io.File;
 import java.io.IOException;

-import freenet.support.Bucket;
-import freenet.support.BucketFactory;
 import freenet.support.Logger;

 /*


Reply via email to