Author: kryptos
Date: 2007-08-21 20:26:59 +0000 (Tue, 21 Aug 2007)
New Revision: 14828
Added:
branches/freenet-jfk/src/freenet/client/ArchiveExtractCallback.java
branches/freenet-jfk/src/freenet/client/async/BlockSet.java
branches/freenet-jfk/src/freenet/client/async/SimpleBlockSet.java
branches/freenet-jfk/src/freenet/clients/http/ConnectionsToadlet.java
branches/freenet-jfk/src/freenet/clients/http/LinkEnabledCallback.java
branches/freenet-jfk/src/freenet/clients/http/OpennetConnectionsToadlet.java
branches/freenet-jfk/src/freenet/io/comm/MessageCore.java
branches/freenet-jfk/src/freenet/io/comm/PacketSocketHandler.java
branches/freenet-jfk/src/freenet/io/comm/SocketHandler.java
branches/freenet-jfk/src/freenet/io/comm/UdpSocketHandler.java
branches/freenet-jfk/src/freenet/l10n/freenet.l10n.de.properties
branches/freenet-jfk/src/freenet/pluginmanager/FredPluginHTTPAdvanced.java
branches/freenet-jfk/src/freenet/support/Executor.java
branches/freenet-jfk/src/freenet/support/HTMLEntities.java
branches/freenet-jfk/src/freenet/support/MutableBoolean.java
branches/freenet-jfk/src/freenet/support/PooledExecutor.java
branches/freenet-jfk/src/freenet/support/WeakHashSet.java
branches/freenet-jfk/src/freenet/support/io/BaseFileBucket.java
branches/freenet-jfk/src/freenet/support/io/MultiReaderBucket.java
branches/freenet-jfk/src/freenet/support/io/PersistentTempFileBucket.java
branches/freenet-jfk/src/freenet/tools/MergeSFS.java
branches/freenet-jfk/test/freenet/support/
branches/freenet-jfk/test/freenet/support/Base64Test.java
branches/freenet-jfk/test/freenet/support/BitArrayTest.java
branches/freenet-jfk/test/freenet/support/HTMLEncoderDecoderTest.java
branches/freenet-jfk/test/freenet/support/HTMLNodeTest.java
branches/freenet-jfk/test/freenet/support/HexUtilTest.java
branches/freenet-jfk/test/freenet/support/LRUHashtableTest.java
branches/freenet-jfk/test/freenet/support/LRUQueueTest.java
branches/freenet-jfk/test/freenet/support/MultiValueTableTest.java
branches/freenet-jfk/test/freenet/support/SimpleFieldSetTest.java
branches/freenet-jfk/test/freenet/support/SizeUtilTest.java
branches/freenet-jfk/test/freenet/support/TimeUtilTest.java
branches/freenet-jfk/test/freenet/support/URIPreEncoderTest.java
branches/freenet-jfk/test/freenet/support/URLEncoderDecoderTest.java
branches/freenet-jfk/test/freenet/utils/
branches/freenet-jfk/test/freenet/utils/UTFUtil.java
Removed:
branches/freenet-jfk/src/freenet/io/comm/UdpSocketManager.java
branches/freenet-jfk/src/freenet/support/io/FileBucketFactory.java
branches/freenet-jfk/src/freenet/support/io/RandomAccessFileBucket.java
branches/freenet-jfk/src/freenet/support/io/SpyInputStream.java
branches/freenet-jfk/src/freenet/support/io/SpyOutputStream.java
branches/freenet-jfk/src/freenet/support/io/TempBucketHook.java
branches/freenet-jfk/test/freenet/support/Base64Test.java
branches/freenet-jfk/test/freenet/support/BitArrayTest.java
branches/freenet-jfk/test/freenet/support/HTMLEncoderDecoderTest.java
branches/freenet-jfk/test/freenet/support/HTMLNodeTest.java
branches/freenet-jfk/test/freenet/support/HexUtilTest.java
branches/freenet-jfk/test/freenet/support/LRUHashtableTest.java
branches/freenet-jfk/test/freenet/support/LRUQueueTest.java
branches/freenet-jfk/test/freenet/support/MultiValueTableTest.java
branches/freenet-jfk/test/freenet/support/SimpleFieldSetTest.java
branches/freenet-jfk/test/freenet/support/SizeUtilTest.java
branches/freenet-jfk/test/freenet/support/TimeUtilTest.java
branches/freenet-jfk/test/freenet/support/URIPreEncoderTest.java
branches/freenet-jfk/test/freenet/support/URLEncoderDecoderTest.java
branches/freenet-jfk/test/freenet/utils/UTFUtil.java
Modified:
branches/freenet-jfk/.classpath
branches/freenet-jfk/.settings/org.eclipse.core.resources.prefs
branches/freenet-jfk/src/freenet/client/ArchiveManager.java
branches/freenet-jfk/src/freenet/client/ArchiveStoreContext.java
branches/freenet-jfk/src/freenet/client/ArchiveStoreItem.java
branches/freenet-jfk/src/freenet/client/ClientMetadata.java
branches/freenet-jfk/src/freenet/client/ErrorArchiveStoreItem.java
branches/freenet-jfk/src/freenet/client/FECCodec.java
branches/freenet-jfk/src/freenet/client/FetchContext.java
branches/freenet-jfk/src/freenet/client/FetchException.java
branches/freenet-jfk/src/freenet/client/HighLevelSimpleClientImpl.java
branches/freenet-jfk/src/freenet/client/InsertContext.java
branches/freenet-jfk/src/freenet/client/Metadata.java
branches/freenet-jfk/src/freenet/client/MetadataParseException.java
branches/freenet-jfk/src/freenet/client/RealArchiveStoreItem.java
branches/freenet-jfk/src/freenet/client/TempStoreElement.java
branches/freenet-jfk/src/freenet/client/async/BaseSingleFileFetcher.java
branches/freenet-jfk/src/freenet/client/async/BinaryBlob.java
branches/freenet-jfk/src/freenet/client/async/BinaryBlobFormatException.java
branches/freenet-jfk/src/freenet/client/async/BinaryBlobInserter.java
branches/freenet-jfk/src/freenet/client/async/ClientGetter.java
branches/freenet-jfk/src/freenet/client/async/ClientRequestScheduler.java
branches/freenet-jfk/src/freenet/client/async/SimpleManifestPutter.java
branches/freenet-jfk/src/freenet/client/async/SimpleSingleFileFetcher.java
branches/freenet-jfk/src/freenet/client/async/SingleBlockInserter.java
branches/freenet-jfk/src/freenet/client/async/SingleFileFetcher.java
branches/freenet-jfk/src/freenet/client/async/SingleFileInserter.java
branches/freenet-jfk/src/freenet/client/async/SplitFileFetcher.java
branches/freenet-jfk/src/freenet/client/async/SplitFileFetcherSegment.java
branches/freenet-jfk/src/freenet/client/async/SplitFileFetcherSubSegment.java
branches/freenet-jfk/src/freenet/client/async/USKChecker.java
branches/freenet-jfk/src/freenet/client/async/USKFetcher.java
branches/freenet-jfk/src/freenet/client/async/USKInserter.java
branches/freenet-jfk/src/freenet/client/async/USKManager.java
branches/freenet-jfk/src/freenet/client/async/USKProxyCompletionCallback.java
branches/freenet-jfk/src/freenet/clients/http/BookmarkEditorToadlet.java
branches/freenet-jfk/src/freenet/clients/http/BrowserTestToadlet.java
branches/freenet-jfk/src/freenet/clients/http/ConfigToadlet.java
branches/freenet-jfk/src/freenet/clients/http/DarknetConnectionsToadlet.java
branches/freenet-jfk/src/freenet/clients/http/FProxyToadlet.java
branches/freenet-jfk/src/freenet/clients/http/FirstTimeWizardToadlet.java
branches/freenet-jfk/src/freenet/clients/http/HTTPRequestImpl.java
branches/freenet-jfk/src/freenet/clients/http/LocalFileInsertToadlet.java
branches/freenet-jfk/src/freenet/clients/http/N2NTMToadlet.java
branches/freenet-jfk/src/freenet/clients/http/PageMaker.java
branches/freenet-jfk/src/freenet/clients/http/PluginToadlet.java
branches/freenet-jfk/src/freenet/clients/http/PproxyToadlet.java
branches/freenet-jfk/src/freenet/clients/http/QueueToadlet.java
branches/freenet-jfk/src/freenet/clients/http/SimpleToadletServer.java
branches/freenet-jfk/src/freenet/clients/http/StatisticsToadlet.java
branches/freenet-jfk/src/freenet/clients/http/SymlinkerToadlet.java
branches/freenet-jfk/src/freenet/clients/http/Toadlet.java
branches/freenet-jfk/src/freenet/clients/http/ToadletContainer.java
branches/freenet-jfk/src/freenet/clients/http/ToadletContextImpl.java
branches/freenet-jfk/src/freenet/clients/http/TranslationToadlet.java
branches/freenet-jfk/src/freenet/clients/http/TrivialToadlet.java
branches/freenet-jfk/src/freenet/clients/http/WelcomeToadlet.java
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkCategories.java
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkCategory.java
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkItem.java
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkItems.java
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkManager.java
branches/freenet-jfk/src/freenet/config/FreenetFilePersistentConfig.java
branches/freenet-jfk/src/freenet/config/PersistentConfig.java
branches/freenet-jfk/src/freenet/config/SubConfig.java
branches/freenet-jfk/src/freenet/crypt/DSAPrivateKey.java
branches/freenet-jfk/src/freenet/crypt/DiffieHellman.java
branches/freenet-jfk/src/freenet/crypt/KEProtocol.java
branches/freenet-jfk/src/freenet/crypt/PCFBMode.java
branches/freenet-jfk/src/freenet/crypt/SHA256.java
branches/freenet-jfk/src/freenet/crypt/Yarrow.java
branches/freenet-jfk/src/freenet/crypt/ciphers/Rijndael_Algorithm.java
branches/freenet-jfk/src/freenet/crypt/ciphers/Rijndael_Properties.java
branches/freenet-jfk/src/freenet/io/Inet6AddressMatcher.java
branches/freenet-jfk/src/freenet/io/NetworkInterface.java
branches/freenet-jfk/src/freenet/io/comm/DMT.java
branches/freenet-jfk/src/freenet/io/comm/FreenetInetAddress.java
branches/freenet-jfk/src/freenet/io/comm/IOStatisticCollector.java
branches/freenet-jfk/src/freenet/io/comm/MessageFilter.java
branches/freenet-jfk/src/freenet/io/comm/MessageType.java
branches/freenet-jfk/src/freenet/io/comm/Peer.java
branches/freenet-jfk/src/freenet/io/comm/PeerContext.java
branches/freenet-jfk/src/freenet/io/comm/RetrievalException.java
branches/freenet-jfk/src/freenet/io/xfer/BlockReceiver.java
branches/freenet-jfk/src/freenet/io/xfer/BlockTransmitter.java
branches/freenet-jfk/src/freenet/io/xfer/BulkReceiver.java
branches/freenet-jfk/src/freenet/io/xfer/BulkTransmitter.java
branches/freenet-jfk/src/freenet/io/xfer/PartiallyReceivedBulk.java
branches/freenet-jfk/src/freenet/keys/ClientCHK.java
branches/freenet-jfk/src/freenet/keys/ClientSSKBlock.java
branches/freenet-jfk/src/freenet/keys/FreenetURI.java
branches/freenet-jfk/src/freenet/keys/Key.java
branches/freenet-jfk/src/freenet/keys/NodeCHK.java
branches/freenet-jfk/src/freenet/keys/TooBigException.java
branches/freenet-jfk/src/freenet/keys/USK.java
branches/freenet-jfk/src/freenet/l10n/L10n.java
branches/freenet-jfk/src/freenet/l10n/freenet.l10n.en.properties
branches/freenet-jfk/src/freenet/l10n/freenet.l10n.fr.properties
branches/freenet-jfk/src/freenet/l10n/freenet.l10n.it.properties
branches/freenet-jfk/src/freenet/l10n/freenet.l10n.no.properties
branches/freenet-jfk/src/freenet/l10n/freenet.l10n.se.properties
branches/freenet-jfk/src/freenet/pluginmanager/AccessDeniedPluginHTTPException.java
branches/freenet-jfk/src/freenet/pluginmanager/DownloadPluginHTTPException.java
branches/freenet-jfk/src/freenet/pluginmanager/FredPlugin.java
branches/freenet-jfk/src/freenet/pluginmanager/NotFoundPluginHTTPException.java
branches/freenet-jfk/src/freenet/pluginmanager/PluginHTTPException.java
branches/freenet-jfk/src/freenet/pluginmanager/PluginHandler.java
branches/freenet-jfk/src/freenet/pluginmanager/PluginManager.java
branches/freenet-jfk/src/freenet/pluginmanager/RedirectPluginHTTPException.java
branches/freenet-jfk/src/freenet/store/BerkeleyDBFreenetStore.java
branches/freenet-jfk/src/freenet/support/BitArray.java
branches/freenet-jfk/src/freenet/support/Fields.java
branches/freenet-jfk/src/freenet/support/FileLoggerHook.java
branches/freenet-jfk/src/freenet/support/HTMLDecoder.java
branches/freenet-jfk/src/freenet/support/HTMLEncoder.java
branches/freenet-jfk/src/freenet/support/HTMLNode.java
branches/freenet-jfk/src/freenet/support/HexUtil.java
branches/freenet-jfk/src/freenet/support/LRUHashtable.java
branches/freenet-jfk/src/freenet/support/LRUQueue.java
branches/freenet-jfk/src/freenet/support/RandomGrabArray.java
branches/freenet-jfk/src/freenet/support/ShortBuffer.java
branches/freenet-jfk/src/freenet/support/SimpleFieldSet.java
branches/freenet-jfk/src/freenet/support/StringArray.java
branches/freenet-jfk/src/freenet/support/TimeUtil.java
branches/freenet-jfk/src/freenet/support/TokenBucket.java
branches/freenet-jfk/src/freenet/support/URLDecoder.java
branches/freenet-jfk/src/freenet/support/compress/GzipCompressor.java
branches/freenet-jfk/src/freenet/support/io/ArrayBucket.java
branches/freenet-jfk/src/freenet/support/io/FileBucket.java
branches/freenet-jfk/src/freenet/support/io/FileUtil.java
branches/freenet-jfk/src/freenet/support/io/FilenameGenerator.java
branches/freenet-jfk/src/freenet/support/io/NullPersistentFileTracker.java
branches/freenet-jfk/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java
branches/freenet-jfk/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java
branches/freenet-jfk/src/freenet/support/io/PersistentFileTracker.java
branches/freenet-jfk/src/freenet/support/io/PersistentTempBucketFactory.java
branches/freenet-jfk/src/freenet/support/io/RandomAccessFileWrapper.java
branches/freenet-jfk/src/freenet/support/io/RandomAccessThing.java
branches/freenet-jfk/src/freenet/support/io/SerializableToFieldSetBucketUtil.java
branches/freenet-jfk/src/freenet/support/io/TempBucketFactory.java
branches/freenet-jfk/src/freenet/support/io/TempFileBucket.java
branches/freenet-jfk/src/freenet/support/math/TimeDecayingRunningAverage.java
branches/freenet-jfk/src/org/spaceroots/mantissa/random/MersenneTwister.java
Log:
Merged with trunk(r14796) and r13448:Link level encryption using JFK
Modified: branches/freenet-jfk/.classpath
===================================================================
--- branches/freenet-jfk/.classpath 2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/.classpath 2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry
excluding="freenet/node/*Test.java|org/spaceroots/mantissa/random/MersenneTwisterTest.java|plugins/JSTUN/**|test/**"
kind="src" path="src"/>
- <classpathentry including="freenet/**/*java" kind="src" path="test"/>
+ <classpathentry
excluding="freenet/node/*Test.java|plugins/JSTUN/**|test/**" kind="src"
path="src"/>
+ <classpathentry including="freenet/|org/" kind="src" path="test"/>
<classpathentry exported="true" kind="lib" path="lib/freenet-ext.jar"/>
<classpathentry kind="con"
path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="/usr/share/java/junit.jar"/>
Modified: branches/freenet-jfk/.settings/org.eclipse.core.resources.prefs
===================================================================
--- branches/freenet-jfk/.settings/org.eclipse.core.resources.prefs
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/.settings/org.eclipse.core.resources.prefs
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,5 +1,6 @@
-#Thu May 31 21:45:29 BST 2007
+#Fri Jul 27 18:21:13 BST 2007
eclipse.preferences.version=1
+encoding//src/freenet/l10n/freenet.l10n.de.properties=UTF-8
encoding//src/freenet/l10n/freenet.l10n.en.properties=UTF-8
encoding//src/freenet/l10n/freenet.l10n.fr.properties=UTF-8
encoding//src/freenet/l10n/freenet.l10n.it.properties=UTF-8
Copied: branches/freenet-jfk/src/freenet/client/ArchiveExtractCallback.java
(from rev 14796, trunk/freenet/src/freenet/client/ArchiveExtractCallback.java)
===================================================================
--- branches/freenet-jfk/src/freenet/client/ArchiveExtractCallback.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/client/ArchiveExtractCallback.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,15 @@
+package freenet.client;
+
+import freenet.support.api.Bucket;
+
+/** Called when we have extracted an archive, and a specified file either is
+ * or isn't in it. */
+public interface ArchiveExtractCallback {
+
+ /** Got the data */
+ public void gotBucket(Bucket data);
+
+ /** Not in the archive */
+ public void notInArchive();
+
+}
Modified: branches/freenet-jfk/src/freenet/client/ArchiveManager.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/ArchiveManager.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/ArchiveManager.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -17,11 +17,12 @@
import freenet.keys.FreenetURI;
import freenet.support.LRUHashtable;
import freenet.support.Logger;
+import freenet.support.MutableBoolean;
import freenet.support.api.Bucket;
import freenet.support.io.BucketTools;
-import freenet.support.io.FileBucket;
import freenet.support.io.FilenameGenerator;
import freenet.support.io.PaddedEphemerallyEncryptedBucket;
+import freenet.support.io.TempFileBucket;
/**
* Cache of recently decoded archives:
@@ -34,11 +35,33 @@
*/
public class ArchiveManager {
+ public static final String METADATA_NAME = ".metadata";
private static boolean logMINOR;
+ final RandomSource random;
+ final long maxArchiveSize;
+ final long maxArchivedFileSize;
+
+ // ArchiveHandler's
+ final int maxArchiveHandlers;
+ private final LRUHashtable archiveHandlers;
+
+ // Data cache
+ /** Maximum number of cached ArchiveStoreItems */
+ final int maxCachedElements;
+ /** Maximum cached data in bytes */
+ final long maxCachedData;
+ /** Currently cached data in bytes */
+ private long cachedData;
+ /** Map from ArchiveKey to ArchiveStoreElement */
+ private final LRUHashtable storedData;
+ /** Filename generator */
+ private final FilenameGenerator filenameGenerator;
+
/**
* Create an ArchiveManager.
- * @param maxHandlers The maximum number of cached ArchiveHandler's.
+ * @param maxHandlers The maximum number of cached ArchiveHandler's
i.e. the
+ * maximum number of containers to track.
* @param maxCachedData The maximum size of the cache directory, in
bytes.
* @param maxArchiveSize The maximum size of an archive.
* @param maxArchivedFileSize The maximum extracted size of a single
file in any
@@ -52,7 +75,6 @@
public ArchiveManager(int maxHandlers, long maxCachedData, long
maxArchiveSize, long maxArchivedFileSize, int maxCachedElements, RandomSource
random, FilenameGenerator filenameGenerator) {
maxArchiveHandlers = maxHandlers;
archiveHandlers = new LRUHashtable();
- cachedElements = new LRUHashtable();
this.maxCachedElements = maxCachedElements;
this.maxCachedData = maxCachedData;
storedData = new LRUHashtable();
@@ -63,16 +85,6 @@
logMINOR = Logger.shouldLog(Logger.MINOR, this);
}
- final RandomSource random;
- final long maxArchiveSize;
- final long maxArchivedFileSize;
-
-
- // ArchiveHandler's
-
- final int maxArchiveHandlers;
- final LRUHashtable archiveHandlers;
-
/** Add an ArchiveHandler by key */
private synchronized void putCached(FreenetURI key, ArchiveHandler zip)
{
if(logMINOR) Logger.minor(this, "Put cached AH for "+key+" :
"+zip);
@@ -90,24 +102,6 @@
return handler;
}
- // Element cache
-
- /** Cache of ArchiveElement's by MyKey */
- final LRUHashtable cachedElements;
- /** Maximum number of cached ArchiveElement's */
- final int maxCachedElements;
-
- // Data cache
-
- /** Maximum cached data in bytes */
- final long maxCachedData;
- /** Currently cached data in bytes */
- private long cachedData;
- /** Map from ArchiveKey to ArchiveStoreElement */
- final LRUHashtable storedData;
- /** Filename generator */
- final FilenameGenerator filenameGenerator;
-
/**
* Create an archive handler. This does not need to know how to
* fetch the key, because the methods called later will ask.
@@ -138,24 +132,30 @@
if(logMINOR) Logger.minor(this, "Fetch cached: "+key+ ' '
+filename);
ArchiveKey k = new ArchiveKey(key, filename);
ArchiveStoreItem asi = null;
- synchronized (storedData) {
+ synchronized (this) {
asi = (ArchiveStoreItem) storedData.get(k);
if(asi == null) return null;
// Promote to top of LRU
storedData.push(k, asi);
}
if(logMINOR) Logger.minor(this, "Found data");
- return asi.getDataOrThrow();
+ return asi.getReaderBucket();
}
/**
- * Remove a file from the cache.
+ * Remove a file from the cache. Called after it has been removed from
its
+ * ArchiveHandler.
* @param item The ArchiveStoreItem to remove.
*/
- void removeCachedItem(ArchiveStoreItem item) {
- synchronized (storedData) {
- storedData.removeKey(item.key);
- }
+ synchronized void removeCachedItem(ArchiveStoreItem item) {
+ long size = item.spaceUsed();
+ storedData.removeKey(item.key);
+ // Hard disk space limit = remove it here.
+ // Soft disk space limit would be to remove it outside the lock.
+ // Soft disk space limit = we go over the limit significantly
when we
+ // are overloaded.
+ cachedData -= size;
+ item.close();
}
/**
@@ -165,15 +165,19 @@
* @param data The actual data fetched.
* @param archiveContext The context for the whole fetch process.
* @param ctx The ArchiveStoreContext for this key.
+ * @param element A particular element that the caller is especially
interested in, or null.
+ * @param callback A callback to be called if we find that element, or
if we don't.
* @throws ArchiveFailureException If we could not extract the data, or
it was too big, etc.
* @throws ArchiveRestartException
* @throws ArchiveRestartException If the request needs to be restarted
because the archive
* changed.
*/
- public void extractToCache(FreenetURI key, short archiveType, Bucket
data, ArchiveContext archiveContext, ArchiveStoreContext ctx) throws
ArchiveFailureException, ArchiveRestartException {
+ public void extractToCache(FreenetURI key, short archiveType, Bucket
data, ArchiveContext archiveContext, ArchiveStoreContext ctx, String element,
ArchiveExtractCallback callback) throws ArchiveFailureException,
ArchiveRestartException {
logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ MutableBoolean gotElement = element != null ? new
MutableBoolean() : null;
+
if(logMINOR) Logger.minor(this, "Extracting "+key);
ctx.onExtract();
ctx.removeAllCachedItems(); // flush cache anyway
@@ -211,7 +215,7 @@
// MINOR: Assumes the first entry in the zip is a
directory.
ZipEntry entry;
- byte[] buf = new byte[4096];
+ byte[] buf = new byte[32768];
HashSet names = new HashSet();
boolean gotMetadata = false;
@@ -249,16 +253,22 @@
out.close();
if(name.equals(".metadata"))
gotMetadata = true;
- addStoreElement(ctx, key, name, temp);
+ addStoreElement(ctx, key, name, temp,
gotElement, element, callback);
names.add(name);
+ trimStoredData();
}
}
// If no metadata, generate some
if(!gotMetadata) {
- generateMetadata(ctx, key, names);
+ generateMetadata(ctx, key, names, gotElement,
element, callback);
+ trimStoredData();
}
if(throwAtExit) throw new
ArchiveRestartException("Archive changed on re-fetch");
+
+ if((!gotElement.value) && element != null)
+ callback.notInArchive();
+
} catch (IOException e) {
throw new ArchiveFailureException("Error reading
archive: "+e.getMessage(), e);
} finally {
@@ -277,9 +287,12 @@
* @param ctx The context object.
* @param key The key from which the archive we are unpacking was
fetched.
* @param names Set of names in the archive.
+ * @param element2
+ * @param gotElement
+ * @param callbackName If we generate a
* @throws ArchiveFailureException
*/
- private void generateMetadata(ArchiveStoreContext ctx, FreenetURI key,
HashSet names) throws ArchiveFailureException {
+ private ArchiveStoreItem generateMetadata(ArchiveStoreContext ctx,
FreenetURI key, HashSet names, MutableBoolean gotElement, String element2,
ArchiveExtractCallback callback) throws ArchiveFailureException {
/* What we have to do is to:
* - Construct a filesystem tree of the names.
* - Turn each level of the tree into a Metadata object,
including those below it, with
@@ -304,21 +317,21 @@
OutputStream os =
element.bucket.getOutputStream();
os.write(buf);
os.close();
- addStoreElement(ctx, key, ".metadata", element);
- break;
+ return addStoreElement(ctx, key, ".metadata",
element, gotElement, element2, callback);
} catch (MetadataUnresolvedException e) {
try {
- x = resolve(e, x, element, ctx, key);
+ x = resolve(e, x, element, ctx, key,
gotElement, element2, callback);
} catch (IOException e1) {
throw new
ArchiveFailureException("Failed to create metadata: "+e1, e1);
}
} catch (IOException e1) {
+ Logger.error(this, "Failed to create metadata:
"+e1, e1);
throw new ArchiveFailureException("Failed to
create metadata: "+e1, e1);
}
}
}
- private int resolve(MetadataUnresolvedException e, int x,
TempStoreElement element, ArchiveStoreContext ctx, FreenetURI key) throws
IOException {
+ private int resolve(MetadataUnresolvedException e, int x,
TempStoreElement element, ArchiveStoreContext ctx, FreenetURI key,
MutableBoolean gotElement, String element2, ArchiveExtractCallback callback)
throws IOException, ArchiveFailureException {
Metadata[] m = e.mustResolve;
for(int i=0;i<m.length;i++) {
try {
@@ -326,9 +339,9 @@
OutputStream os =
element.bucket.getOutputStream();
os.write(buf);
os.close();
- addStoreElement(ctx, key, ".metadata-"+(x++),
element);
+ addStoreElement(ctx, key, ".metadata-"+(x++),
element, gotElement, element2, callback);
} catch (MetadataUnresolvedException e1) {
- x = resolve(e, x, element, ctx, key);
+ x = resolve(e, x, element, ctx, key,
gotElement, element2, callback);
}
}
return x;
@@ -350,7 +363,7 @@
} else
after = name.substring(x+1, name.length());
Object o = dir.get(before);
- HashMap map;
+ HashMap map = (HashMap) o;
if(o == null) {
map = new HashMap();
dir.put(before, map);
@@ -358,7 +371,6 @@
if(o instanceof String) {
throw new ArchiveFailureException("Invalid
archive: contains "+name+" as both file and dir");
}
- map = (HashMap) o;
addToDirectory(map, after, prefix + before + '/');
}
}
@@ -375,21 +387,51 @@
private void addErrorElement(ArchiveStoreContext ctx, FreenetURI key,
String name, String error) {
ErrorArchiveStoreItem element = new ErrorArchiveStoreItem(ctx,
key, name, error);
if(logMINOR) Logger.minor(this, "Adding error element:
"+element+" for "+key+ ' ' +name);
- synchronized (storedData) {
+ ArchiveStoreItem oldItem;
+ synchronized (this) {
+ oldItem = (ArchiveStoreItem)
storedData.get(element.key);
storedData.push(element.key, element);
+ if(oldItem != null) {
+ oldItem.close();
+ cachedData -= oldItem.spaceUsed();
+ }
}
}
/**
* Add a store element.
+ * @param callbackName If set, the name of the file for which we must
call the callback if this file happens to
+ * match.
+ * @param gotElement Flag indicating whether we've already found the
file for the callback. If so we must not call
+ * it again.
+ * @param callback Callback to be called if we do find it. We must
getReaderBucket() before adding the data to the
+ * LRU, otherwise it may be deleted before it reaches the client.
+ * @throws ArchiveFailureException If a failure occurred resulting in
the data not being readable. Only happens if
+ * callback != null.
*/
- private void addStoreElement(ArchiveStoreContext ctx, FreenetURI key,
String name, TempStoreElement temp) {
- RealArchiveStoreItem element = new RealArchiveStoreItem(this,
ctx, key, name, temp);
+ private ArchiveStoreItem addStoreElement(ArchiveStoreContext ctx,
FreenetURI key, String name, TempStoreElement temp, MutableBoolean gotElement,
String callbackName, ArchiveExtractCallback callback) throws
ArchiveFailureException {
+ RealArchiveStoreItem element = new RealArchiveStoreItem(ctx,
key, name, temp);
if(logMINOR) Logger.minor(this, "Adding store element:
"+element+" ( "+key+ ' ' +name+" size "+element.spaceUsed()+" )");
- synchronized (storedData) {
+ ArchiveStoreItem oldItem;
+ // Let it throw, if it does something is drastically wrong
+ Bucket matchBucket = null;
+ if((!gotElement.value) && name.equals(callbackName)) {
+ matchBucket = element.getReaderBucket();
+ }
+ synchronized (this) {
+ oldItem = (ArchiveStoreItem)
storedData.get(element.key);
storedData.push(element.key, element);
+ cachedData += element.spaceUsed();
+ if(oldItem != null) {
+ cachedData -= oldItem.spaceUsed();
+ oldItem.close();
+ }
}
- trimStoredData();
+ if(matchBucket != null) {
+ callback.gotBucket(matchBucket);
+ gotElement.value = true;
+ }
+ return element;
}
/**
@@ -397,15 +439,25 @@
* Call synchronized on storedData.
*/
private void trimStoredData() {
+ synchronized(this) {
while(true) {
- synchronized(this) {
+ ArchiveStoreItem item;
if(cachedData <= maxCachedData &&
storedData.size() <= maxCachedElements) return;
- }
- ArchiveStoreItem e = (ArchiveStoreItem)
storedData.popValue();
+ if(storedData.isEmpty()) {
+ // Race condition? cachedData out of
sync?
+ Logger.error(this, "storedData is empty
but still over limit: cachedData="+cachedData+" / "+maxCachedData);
+ return;
+ }
+ item = (ArchiveStoreItem) storedData.popValue();
+ long space = item.spaceUsed();
+ cachedData -= space;
+ // Hard limits = delete file within lock, soft
limits = delete outside of lock
+ // Here we use a hard limit
if(logMINOR)
- Logger.minor(this, "Dropping "+e+" :
cachedData="+cachedData+" of "+maxCachedData);
- e.close();
+ Logger.minor(this, "Dropping "+item+" :
cachedData="+cachedData+" of "+maxCachedData+" stored items :
"+storedData.size()+" of "+maxCachedElements);
+ item.close();
}
+ }
}
/**
@@ -415,12 +467,13 @@
* go over the maximum size. Will obviously keep its key when we move
it to main.
*/
private TempStoreElement makeTempStoreBucket(long size) {
- File myFile = filenameGenerator.makeRandomFilename();
- FileBucket fb = new FileBucket(myFile, false, false, true,
true, true);
+ long id = filenameGenerator.makeRandomFilename();
+ File myFile = filenameGenerator.getFilename(id);
+ TempFileBucket fb = new TempFileBucket(id, filenameGenerator);
byte[] cipherKey = new byte[32];
random.nextBytes(cipherKey);
- PaddedEphemerallyEncryptedBucket encryptedBucket = new
PaddedEphemerallyEncryptedBucket(fb, 1024, random, true);
+ PaddedEphemerallyEncryptedBucket encryptedBucket = new
PaddedEphemerallyEncryptedBucket(fb, 1024, random);
return new TempStoreElement(myFile, fb, encryptedBucket);
}
@@ -440,12 +493,4 @@
return Metadata.ARCHIVE_ZIP;
else throw new IllegalArgumentException();
}
-
- synchronized void decrementSpace(long spaceUsed) {
- cachedData -= spaceUsed;
- }
-
- synchronized void incrementSpace(long spaceUsed) {
- cachedData += spaceUsed;
- }
}
Modified: branches/freenet-jfk/src/freenet/client/ArchiveStoreContext.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/ArchiveStoreContext.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/ArchiveStoreContext.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -26,6 +26,15 @@
private FreenetURI key;
private short archiveType;
private boolean forceRefetchArchive;
+ /** Archive size */
+ private long lastSize = -1;
+ /** Archive hash */
+ private byte[] lastHash;
+ /** Index of still-cached ArchiveStoreItems with this key.
+ * Note that we never ever hold this and then take another lock! In
particular
+ * we must not take the ArchiveManager lock while holding this lock. It
must be
+ * the inner lock to avoid deadlocks. */
+ private final DoublyLinkedListImpl myItems;
public ArchiveStoreContext(ArchiveManager manager, FreenetURI key,
short archiveType, boolean forceRefetchArchive) {
this.manager = manager;
@@ -46,6 +55,8 @@
/**
* Fetch a file in an archive.
+ * @return A Bucket containing the data. This will not be freed until
the
+ * client is finished with it i.e. calls free() or it is finalized.
*/
public Bucket get(String internalName, ArchiveContext archiveContext,
ClientMetadata dm, int recursionLevel,
boolean dontEnterImplicitArchives) throws
ArchiveFailureException, ArchiveRestartException, MetadataParseException,
FetchException {
@@ -67,9 +78,6 @@
return null;
}
- // Archive size
- long lastSize = -1;
-
/** Returns the size of the archive last time we fetched it, or -1 */
long getLastSize() {
return lastSize;
@@ -80,10 +88,7 @@
lastSize = size;
}
- // Archive hash
- byte[] lastHash;
-
/** Returns the hash of the archive last time we fetched it, or null */
public byte[] getLastHash() {
return lastHash;
@@ -93,11 +98,6 @@
public void setLastHash(byte[] realHash) {
lastHash = realHash;
}
-
- // Index of still-cached ArchiveStoreItems with this key
-
- /** Index of still-cached ArchiveStoreItems with this key */
- final DoublyLinkedListImpl myItems;
/**
* Remove all ArchiveStoreItems with this key from the cache.
@@ -110,7 +110,6 @@
}
if(item == null) break;
manager.removeCachedItem(item);
- item.context.removeItem(item);
}
}
@@ -121,14 +120,14 @@
}
}
- /** Notify that an archive store item with this key has been expelled
from the cache. */
+ /** Notify that an archive store item with this key has been expelled
from the
+ * cache. Remove it from our local cache and ask it to free the bucket
if
+ * necessary. */
public void removeItem(ArchiveStoreItem item) {
- long spaceUsed = item.spaceUsed();
synchronized(myItems) {
if(myItems.remove(item) == null) return; // only
removed once
}
item.innerClose();
- manager.decrementSpace(spaceUsed);
}
public short getArchiveType() {
@@ -139,10 +138,11 @@
return key;
}
- public void extractToCache(Bucket bucket, ArchiveContext actx) throws
ArchiveFailureException, ArchiveRestartException {
- manager.extractToCache(key, archiveType, bucket, actx, this);
+ public void extractToCache(Bucket bucket, ArchiveContext actx, String
element, ArchiveExtractCallback callback) throws ArchiveFailureException,
ArchiveRestartException {
+ manager.extractToCache(key, archiveType, bucket, actx, this,
element, callback);
}
+ /** Called just before extracting this container to the cache */
public void onExtract() {
forceRefetchArchive = false;
}
Modified: branches/freenet-jfk/src/freenet/client/ArchiveStoreItem.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/ArchiveStoreItem.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/ArchiveStoreItem.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -20,7 +20,10 @@
context.addItem(this);
}
- /** Delete any stored data on disk etc. Override in subtypes for
specific cleanup. */
+ /** Delete any stored data on disk etc.
+ * Override in subtypes for specific cleanup.
+ * Will be called with locks held, so should only do low level
operations
+ * such as deletes.. */
void innerClose() { } // override in subtypes for cleanup
/**
@@ -36,7 +39,14 @@
abstract Bucket getDataOrThrow() throws ArchiveFailureException;
/**
- * Return the amount of cache space used by the item.
+ * Return the amount of cache space used by the item. May be called
inside
+ * locks so should not take any nontrivial locks or take long.
*/
abstract long spaceUsed();
+
+ /**
+ * Get the data as a Bucket, and guarantee that it won't be freed until
the
+ * returned object is either finalized or freed.
+ */
+ abstract Bucket getReaderBucket() throws ArchiveFailureException;
}
Modified: branches/freenet-jfk/src/freenet/client/ClientMetadata.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/ClientMetadata.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/ClientMetadata.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -52,4 +52,18 @@
public String toString() {
return getMIMEType();
}
+
+ public void clear() {
+ mimeType = null;
+ }
+
+ public String getMIMETypeNoParams() {
+ String s = mimeType;
+ if(s == null) return null;
+ int i = s.indexOf(';');
+ if(i > -1) {
+ s = s.substring(i);
+ }
+ return s;
+ }
}
Modified: branches/freenet-jfk/src/freenet/client/ErrorArchiveStoreItem.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/ErrorArchiveStoreItem.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/ErrorArchiveStoreItem.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -35,5 +35,9 @@
public long spaceUsed() {
return 0;
}
+
+ Bucket getReaderBucket() throws ArchiveFailureException {
+ throw new ArchiveFailureException(error);
+ }
}
Modified: branches/freenet-jfk/src/freenet/client/FECCodec.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/FECCodec.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/FECCodec.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -343,7 +343,7 @@
synchronized (_awaitingJobs) {
if(fecRunnerThread == null) {
if(fecRunnerThread != null)
Logger.error(FECCodec.class, "The callback died!! restarting a new one, please
report that error.");
- fecRunnerThread = new Thread(fecRunner, "FEC
Pool");
+ fecRunnerThread = new Thread(fecRunner, "FEC
Pool "+(fecPoolCounter++));
fecRunnerThread.setDaemon(true);
fecRunnerThread.setPriority(Thread.MIN_PRIORITY);
@@ -361,6 +361,7 @@
private static final LinkedList _awaitingJobs = new LinkedList();
private static final FECRunner fecRunner = new FECRunner();
private static Thread fecRunnerThread;
+ private static int fecPoolCounter;
/**
* A private Thread started by {@link FECCodec}...
Modified: branches/freenet-jfk/src/freenet/client/FetchContext.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/FetchContext.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/FetchContext.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -3,11 +3,16 @@
* http://www.gnu.org/ for further details of the GPL. */
package freenet.client;
+import java.util.Set;
+
+import freenet.client.async.BlockSet;
import freenet.client.async.HealingQueue;
import freenet.client.async.USKManager;
import freenet.client.events.ClientEventProducer;
import freenet.client.events.SimpleEventProducer;
import freenet.crypt.RandomSource;
+import freenet.node.Ticker;
+import freenet.support.Executor;
import freenet.support.api.BucketFactory;
/** Context for a Fetcher. Contains all the settings a Fetcher needs to know
about. */
@@ -45,6 +50,11 @@
public boolean returnZIPManifests;
public final HealingQueue healingQueue;
public final boolean ignoreTooManyPathComponents;
+ /** If set, contains a set of blocks to be consulted before checking
the datastore. */
+ public BlockSet blocks;
+ public Set allowedMIMETypes;
+ public final Ticker ticker;
+ public final Executor executor;
public FetchContext(long curMaxLength,
long curMaxTempLength, int maxMetadataSize, int
maxRecursionLevel, int maxArchiveRestarts, int maxArchiveLevels,
@@ -53,7 +63,10 @@
boolean allowSplitfiles, boolean followRedirects,
boolean localRequestOnly,
int maxDataBlocksPerSegment, int
maxCheckBlocksPerSegment,
RandomSource random, ArchiveManager archiveManager,
BucketFactory bucketFactory,
- ClientEventProducer producer, boolean
cacheLocalRequests, USKManager uskManager, HealingQueue hq, boolean
ignoreTooManyPathComponents) {
+ ClientEventProducer producer, boolean
cacheLocalRequests, USKManager uskManager,
+ HealingQueue hq, boolean ignoreTooManyPathComponents,
Ticker ticker, Executor executor) {
+ this.ticker = ticker;
+ this.executor = executor;
this.maxOutputLength = curMaxLength;
this.uskManager = uskManager;
this.maxTempLength = curMaxTempLength;
@@ -85,8 +98,12 @@
this.eventProducer = ctx.eventProducer;
else
this.eventProducer = new SimpleEventProducer();
+ this.ticker = ctx.ticker;
+ this.executor = ctx.executor;
this.uskManager = ctx.uskManager;
this.ignoreTooManyPathComponents =
ctx.ignoreTooManyPathComponents;
+ this.blocks = ctx.blocks;
+ this.allowedMIMETypes = ctx.allowedMIMETypes;
if(maskID == IDENTICAL_MASK) {
this.maxOutputLength = ctx.maxOutputLength;
this.maxMetadataSize = ctx.maxMetadataSize;
Modified: branches/freenet-jfk/src/freenet/client/FetchException.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/FetchException.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/FetchException.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -127,6 +127,18 @@
Logger.minor(this,
"FetchException("+getMessage(mode)+"): "+t.getMessage(),t);
}
+ public FetchException(int mode, String reason, Throwable t) {
+ super(reason+" : "+getMessage(mode)+": "+t.getMessage());
+ extraMessage = t.getMessage();
+ this.mode = mode;
+ errorCodes = null;
+ initCause(t);
+ newURI = null;
+ expectedSize = -1;
+ if(Logger.shouldLog(Logger.MINOR, this))
+ Logger.minor(this,
"FetchException("+getMessage(mode)+"): "+t.getMessage(),t);
+ }
+
public FetchException(int mode, FailureCodeTracker errorCodes) {
super(getMessage(mode));
extraMessage = null;
@@ -182,6 +194,18 @@
this.finalizedSizeAndMimeType = e.finalizedSizeAndMimeType;
}
+ public FetchException(FetchException e, FreenetURI uri) {
+ super(e.getMessage());
+ initCause(e);
+ this.mode = e.mode;
+ this.newURI = uri;
+ this.errorCodes = e.errorCodes;
+ this.expectedMimeType = e.expectedMimeType;
+ this.expectedSize = e.expectedSize;
+ this.extraMessage = e.extraMessage;
+ this.finalizedSizeAndMimeType = e.finalizedSizeAndMimeType;
+ }
+
public static String getShortMessage(int mode) {
String ret = L10n.getString("FetchException.shortError."+mode);
if(ret == null)
@@ -273,6 +297,10 @@
public static final int ARCHIVE_RESTART = 26;
/** There is a more recent version of the USK, ~= HTTP 301; FProxy will
turn this into a 301 */
public static final int PERMANENT_REDIRECT = 27;
+ /** Requestor specified a list of allowed MIME types, and the key's
type wasn't in the list */
+ public static final int WRONG_MIME_TYPE = 29;
+ /** A node killed the request because it had recently been tried and
had DNFed */
+ public static final int RECENTLY_FAILED = 30;
/** Is an error fatal i.e. is there no point retrying? */
public boolean isFatal() {
@@ -307,6 +335,7 @@
case REJECTED_OVERLOAD:
case TRANSFER_FAILED:
case ALL_DATA_NOT_FOUND:
+ case RECENTLY_FAILED: // wait a bit, but fine
// Not usually fatal
case SPLITFILE_ERROR:
return false;
@@ -320,6 +349,7 @@
case CANCELLED:
case ARCHIVE_RESTART:
case PERMANENT_REDIRECT:
+ case WRONG_MIME_TYPE:
// Fatal
return true;
Modified: branches/freenet-jfk/src/freenet/client/HighLevelSimpleClientImpl.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/HighLevelSimpleClientImpl.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/HighLevelSimpleClientImpl.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -191,7 +191,7 @@
MAX_SPLITFILE_BLOCKS_PER_SEGMENT,
MAX_SPLITFILE_CHECK_BLOCKS_PER_SEGMENT,
random, archiveManager, bucketFactory,
globalEventProducer,
cacheLocalRequests, core.uskManager,
healingQueue,
- forceDontIgnoreTooManyPathComponents ? false :
core.ignoreTooManyPathComponents);
+ forceDontIgnoreTooManyPathComponents ? false :
core.ignoreTooManyPathComponents, core.getTicker(), core.getExecutor());
}
public InsertContext getInsertContext(boolean forceNonPersistent) {
@@ -199,6 +199,6 @@
forceNonPersistent ? new
NullPersistentFileTracker() : persistentFileTracker,
random, INSERT_RETRIES,
CONSECUTIVE_RNFS_ASSUME_SUCCESS,
SPLITFILE_INSERT_THREADS,
SPLITFILE_BLOCKS_PER_SEGMENT, SPLITFILE_CHECK_BLOCKS_PER_SEGMENT,
- globalEventProducer, cacheLocalRequests,
core.uskManager, blockEncoder);
+ globalEventProducer, cacheLocalRequests,
core.uskManager, blockEncoder, core.getExecutor());
}
}
Modified: branches/freenet-jfk/src/freenet/client/InsertContext.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/InsertContext.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/InsertContext.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -8,6 +8,7 @@
import freenet.client.events.ClientEventProducer;
import freenet.client.events.SimpleEventProducer;
import freenet.crypt.RandomSource;
+import freenet.support.Executor;
import freenet.support.api.BucketFactory;
import freenet.support.io.NullPersistentFileTracker;
import freenet.support.io.PersistentFileTracker;
@@ -32,10 +33,11 @@
public final boolean cacheLocalRequests;
public final USKManager uskManager;
public final BackgroundBlockEncoder backgroundBlockEncoder;
+ public final Executor executor;
public InsertContext(BucketFactory bf, BucketFactory persistentBF,
PersistentFileTracker tracker, RandomSource random,
int maxRetries, int rnfsToSuccess, int maxThreads, int
splitfileSegmentDataBlocks, int splitfileSegmentCheckBlocks,
- ClientEventProducer eventProducer, boolean
cacheLocalRequests, USKManager uskManager, BackgroundBlockEncoder blockEncoder)
{
+ ClientEventProducer eventProducer, boolean
cacheLocalRequests, USKManager uskManager, BackgroundBlockEncoder blockEncoder,
Executor executor) {
this.bf = bf;
this.persistentFileTracker = tracker;
this.persistentBucketFactory = persistentBF;
@@ -51,6 +53,7 @@
this.splitfileSegmentCheckBlocks = splitfileSegmentCheckBlocks;
this.cacheLocalRequests = cacheLocalRequests;
this.backgroundBlockEncoder = blockEncoder;
+ this.executor = executor;
}
public InsertContext(InsertContext ctx, SimpleEventProducer producer,
boolean forceNonPersistent) {
@@ -69,6 +72,7 @@
this.splitfileSegmentCheckBlocks =
ctx.splitfileSegmentCheckBlocks;
this.cacheLocalRequests = ctx.cacheLocalRequests;
this.backgroundBlockEncoder = ctx.backgroundBlockEncoder;
+ this.executor = ctx.executor;
}
public InsertContext(InsertContext ctx, SimpleEventProducer producer) {
@@ -87,6 +91,7 @@
this.splitfileSegmentCheckBlocks =
ctx.splitfileSegmentCheckBlocks;
this.cacheLocalRequests = ctx.cacheLocalRequests;
this.backgroundBlockEncoder = ctx.backgroundBlockEncoder;
+ this.executor = ctx.executor;
}
}
Modified: branches/freenet-jfk/src/freenet/client/Metadata.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/Metadata.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/Metadata.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -157,8 +157,9 @@
}
/** Parse some metadata from a byte[].
- * @throws IOException If the data is incomplete, or something wierd
happens. */
- private Metadata(byte[] data) throws IOException {
+ * @throws IOException If the data is incomplete, or something wierd
happens.
+ * @throws MetadataParseException */
+ private Metadata(byte[] data) throws IOException,
MetadataParseException {
this(new DataInputStream(new ByteArrayInputStream(data)),
data.length);
}
@@ -848,6 +849,7 @@
unresolvedMetadata = new
LinkedList();
for(int j=0;j<m.length;j++)
unresolvedMetadata.addFirst(m[j]);
+ kill = true;
}
}
if(kill) {
@@ -916,4 +918,10 @@
public boolean isResolved() {
return resolvedURI != null;
}
+
+ public void setArchiveManifest() {
+ archiveType =
ArchiveManager.getArchiveType(clientMetadata.getMIMEType());
+ clientMetadata.clear();
+ documentType = ZIP_MANIFEST;
+ }
}
Modified: branches/freenet-jfk/src/freenet/client/MetadataParseException.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/MetadataParseException.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/MetadataParseException.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -6,7 +6,7 @@
import java.io.IOException;
/** Thrown when Metadata parse fails. */
-public class MetadataParseException extends IOException {
+public class MetadataParseException extends Exception {
private static final long serialVersionUID = 4910650977022715220L;
Modified: branches/freenet-jfk/src/freenet/client/RealArchiveStoreItem.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/RealArchiveStoreItem.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/RealArchiveStoreItem.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -7,16 +7,14 @@
import freenet.keys.FreenetURI;
import freenet.support.api.Bucket;
-import freenet.support.io.FileBucket;
import freenet.support.io.FileUtil;
-import freenet.support.io.PaddedEphemerallyEncryptedBucket;
+import freenet.support.io.MultiReaderBucket;
class RealArchiveStoreItem extends ArchiveStoreItem {
- private final ArchiveManager manager;
private final File myFilename;
- private final PaddedEphemerallyEncryptedBucket bucket;
- private final FileBucket underBucket;
+ private final MultiReaderBucket mb;
+ private final Bucket bucket;
private final long spaceUsed;
/**
@@ -26,15 +24,13 @@
* @param temp The TempStoreElement currently storing the data.
* @param manager The parent ArchiveManager within which this item is
stored.
*/
- RealArchiveStoreItem(ArchiveManager manager, ArchiveStoreContext ctx,
FreenetURI key2, String realName, TempStoreElement temp) {
+ RealArchiveStoreItem(ArchiveStoreContext ctx, FreenetURI key2, String
realName, TempStoreElement temp) {
super(new ArchiveKey(key2, realName), ctx);
- this.manager = manager;
- this.bucket = temp.bucket;
- this.underBucket = temp.underBucket;
- underBucket.setReadOnly();
- this.myFilename = underBucket.getFile();
- spaceUsed = FileUtil.estimateUsage(myFilename,
underBucket.size());
- this.manager.incrementSpace(spaceUsed);
+ mb = new MultiReaderBucket(temp.bucket);
+ this.bucket = mb.getReaderBucket();
+ temp.underBucket.setReadOnly();
+ this.myFilename = temp.underBucket.getFile();
+ spaceUsed = FileUtil.estimateUsage(myFilename,
temp.underBucket.size());
}
/**
@@ -59,10 +55,14 @@
}
void innerClose() {
- underBucket.free();
+ bucket.free();
}
Bucket getDataOrThrow() throws ArchiveFailureException {
return dataAsBucket();
}
+
+ Bucket getReaderBucket() throws ArchiveFailureException {
+ return mb.getReaderBucket();
+ }
}
Modified: branches/freenet-jfk/src/freenet/client/TempStoreElement.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/TempStoreElement.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/TempStoreElement.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -5,15 +5,15 @@
import java.io.File;
-import freenet.support.io.FileBucket;
import freenet.support.io.PaddedEphemerallyEncryptedBucket;
+import freenet.support.io.TempFileBucket;
class TempStoreElement {
final File myFilename;
final PaddedEphemerallyEncryptedBucket bucket;
- final FileBucket underBucket;
+ final TempFileBucket underBucket;
- TempStoreElement(File myFile, FileBucket fb,
PaddedEphemerallyEncryptedBucket encryptedBucket) {
+ TempStoreElement(File myFile, TempFileBucket fb,
PaddedEphemerallyEncryptedBucket encryptedBucket) {
this.myFilename = myFile;
this.underBucket = fb;
this.bucket = encryptedBucket;
Modified:
branches/freenet-jfk/src/freenet/client/async/BaseSingleFileFetcher.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/BaseSingleFileFetcher.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/BaseSingleFileFetcher.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -6,9 +6,11 @@
import freenet.client.FetchContext;
import freenet.keys.ClientKey;
import freenet.keys.ClientSSK;
+import freenet.keys.Key;
+import freenet.keys.KeyBlock;
+import freenet.keys.KeyVerifyException;
import freenet.node.SendableGet;
import freenet.support.Logger;
-import freenet.support.RandomGrabArray;
public abstract class BaseSingleFileFetcher extends SendableGet {
@@ -80,8 +82,7 @@
synchronized(this) {
cancelled = true;
}
- RandomGrabArray arr = getParentGrabArray();
- if(arr != null) arr.remove(this);
+ super.unregister();
}
public synchronized boolean isCancelled() {
@@ -101,4 +102,20 @@
return true;
}
+ public void onGotKey(Key key, KeyBlock block) {
+ synchronized(this) {
+ if(isCancelled()) return;
+ if(!key.equals(this.key.getNodeKey())) {
+ Logger.normal(this, "Got sent key "+key+" but
want "+this.key+" for "+this);
+ return;
+ }
+ }
+ try {
+ onSuccess(Key.createKeyBlock(this.key, block), false,
0);
+ } catch (KeyVerifyException e) {
+ Logger.error(this, "onGotKey("+key+","+block+") got
"+e+" for "+this, e);
+ // FIXME if we get rid of the direct route this must
call onFailure()
+ }
+ }
+
}
Modified: branches/freenet-jfk/src/freenet/client/async/BinaryBlob.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/BinaryBlob.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/BinaryBlob.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,10 +1,15 @@
package freenet.client.async;
+import java.io.DataInputStream;
import java.io.DataOutputStream;
+import java.io.EOFException;
import java.io.IOException;
+import com.onionnetworks.util.FileUtil;
+
import freenet.keys.Key;
import freenet.keys.KeyBlock;
+import freenet.keys.KeyVerifyException;
public abstract class BinaryBlob {
@@ -46,4 +51,70 @@
writeBlobHeader(binaryBlobStream, BinaryBlob.BLOB_END,
BinaryBlob.BLOB_END_VERSION, 0);
}
+ public static void readBinaryBlob(DataInputStream dis, BlockSet blocks,
boolean tolerant) throws IOException, BinaryBlobFormatException {
+ long magic = dis.readLong();
+ if(magic != BinaryBlob.BINARY_BLOB_MAGIC)
+ throw new BinaryBlobFormatException("Bad magic");
+ short version = dis.readShort();
+ if(version != BinaryBlob.BINARY_BLOB_OVERALL_VERSION)
+ throw new BinaryBlobFormatException("Unknown overall
version");
+
+ int i=0;
+ while(true) {
+ long blobLength;
+ try {
+ blobLength = dis.readInt() & 0xFFFFFFFFL;
+ } catch (EOFException e) {
+ // End of file
+ dis.close();
+ break;
+ }
+ short blobType = dis.readShort();
+ short blobVer = dis.readShort();
+
+ if(blobType == BinaryBlob.BLOB_END) {
+ dis.close();
+ break;
+ } else if(blobType == BinaryBlob.BLOB_BLOCK) {
+ if(blobVer != BinaryBlob.BLOB_BLOCK_VERSION)
+ // Even if tolerant, if we can't read a
blob there probably isn't much we can do.
+ throw new
BinaryBlobFormatException("Unknown block blob version");
+ if(blobLength < 9)
+ throw new
BinaryBlobFormatException("Block blob too short");
+ short keyType = dis.readShort();
+ int keyLen = dis.readUnsignedByte();
+ int headersLen = dis.readUnsignedShort();
+ int dataLen = dis.readUnsignedShort();
+ int pubkeyLen = dis.readUnsignedShort();
+ int total = 9 + keyLen + headersLen + dataLen +
pubkeyLen;
+ if(blobLength != total)
+ throw new
BinaryBlobFormatException("Binary blob not same length as data:
blobLength="+blobLength+" total="+total);
+ byte[] keyBytes = new byte[keyLen];
+ byte[] headersBytes = new byte[headersLen];
+ byte[] dataBytes = new byte[dataLen];
+ byte[] pubkeyBytes = new byte[pubkeyLen];
+ dis.readFully(keyBytes);
+ dis.readFully(headersBytes);
+ dis.readFully(dataBytes);
+ dis.readFully(pubkeyBytes);
+ KeyBlock block;
+ try {
+ block = Key.createBlock(keyType,
keyBytes, headersBytes, dataBytes, pubkeyBytes);
+ } catch (KeyVerifyException e) {
+ throw new
BinaryBlobFormatException("Invalid key: "+e.getMessage(), e);
+ }
+
+ blocks.add(block);
+
+ } else {
+ if(tolerant) {
+ FileUtil.skipFully(dis, blobLength);
+ } else {
+ throw new
BinaryBlobFormatException("Unknown blob type: "+blobType);
+ }
+ }
+ i++;
+ }
+
+ }
}
Modified:
branches/freenet-jfk/src/freenet/client/async/BinaryBlobFormatException.java
===================================================================
---
branches/freenet-jfk/src/freenet/client/async/BinaryBlobFormatException.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/client/async/BinaryBlobFormatException.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -4,6 +4,11 @@
public class BinaryBlobFormatException extends Exception {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
public BinaryBlobFormatException(String message) {
super(message);
}
Modified: branches/freenet-jfk/src/freenet/client/async/BinaryBlobInserter.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/BinaryBlobInserter.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/BinaryBlobInserter.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,19 +1,16 @@
package freenet.client.async;
import java.io.DataInputStream;
-import java.io.EOFException;
import java.io.IOException;
+import java.util.Iterator;
import java.util.Vector;
-import com.onionnetworks.util.FileUtil;
-
import freenet.client.FailureCodeTracker;
import freenet.client.InsertContext;
import freenet.client.InsertException;
import freenet.keys.CHKBlock;
import freenet.keys.Key;
import freenet.keys.KeyBlock;
-import freenet.keys.KeyVerifyException;
import freenet.keys.SSKBlock;
import freenet.node.LowLevelPutException;
import freenet.node.SimpleSendableInsert;
@@ -44,74 +41,24 @@
this.parent = parent;
this.clientContext = clientContext;
this.errors = new FailureCodeTracker(true);
- Vector myInserters = new Vector();
DataInputStream dis = new
DataInputStream(blob.getInputStream());
- long magic = dis.readLong();
- if(magic != BinaryBlob.BINARY_BLOB_MAGIC)
- throw new BinaryBlobFormatException("Bad magic");
- short version = dis.readShort();
- if(version != BinaryBlob.BINARY_BLOB_OVERALL_VERSION)
- throw new BinaryBlobFormatException("Unknown overall
version");
- int i=0;
- while(true) {
- long blobLength;
- try {
- blobLength = dis.readInt() & 0xFFFFFFFFL;
- } catch (EOFException e) {
- // End of file
- dis.close();
- break;
- }
- short blobType = dis.readShort();
- short blobVer = dis.readShort();
-
- if(blobType == BinaryBlob.BLOB_END) {
- dis.close();
- break;
- } else if(blobType == BinaryBlob.BLOB_BLOCK) {
- if(blobVer != BinaryBlob.BLOB_BLOCK_VERSION)
- // Even if tolerant, if we can't read a
blob there probably isn't much we can do.
- throw new
BinaryBlobFormatException("Unknown block blob version");
- if(blobLength < 9)
- throw new
BinaryBlobFormatException("Block blob too short");
- short keyType = dis.readShort();
- int keyLen = dis.readUnsignedByte();
- int headersLen = dis.readUnsignedShort();
- int dataLen = dis.readUnsignedShort();
- int pubkeyLen = dis.readUnsignedShort();
- int total = 9 + keyLen + headersLen + dataLen +
pubkeyLen;
- if(blobLength != total)
- throw new
BinaryBlobFormatException("Binary blob not same length as data:
blobLength="+blobLength+" total="+total);
- byte[] keyBytes = new byte[keyLen];
- byte[] headersBytes = new byte[headersLen];
- byte[] dataBytes = new byte[dataLen];
- byte[] pubkeyBytes = new byte[pubkeyLen];
- dis.readFully(keyBytes);
- dis.readFully(headersBytes);
- dis.readFully(dataBytes);
- dis.readFully(pubkeyBytes);
- KeyBlock block;
- try {
- block = Key.createBlock(keyType,
keyBytes, headersBytes, dataBytes, pubkeyBytes);
- } catch (KeyVerifyException e) {
- throw new
BinaryBlobFormatException("Invalid key: "+e.getMessage(), e);
- }
-
- MySendableInsert inserter =
- new MySendableInsert(i, block,
prioClass, getScheduler(block), clientContext);
-
- myInserters.add(inserter);
-
- } else {
- if(tolerant) {
- FileUtil.skipFully(dis, blobLength);
- } else {
- throw new
BinaryBlobFormatException("Unknown blob type: "+blobType);
- }
- }
- i++;
+ BlockSet blocks = new SimpleBlockSet();
+
+ BinaryBlob.readBinaryBlob(dis, blocks, tolerant);
+
+ Vector myInserters = new Vector();
+ Iterator i = blocks.keys().iterator();
+
+ int x=0;
+ while(i.hasNext()) {
+ Key key = (Key) i.next();
+ KeyBlock block = blocks.get(key);
+ MySendableInsert inserter =
+ new MySendableInsert(x++, block, prioClass,
getScheduler(block), clientContext);
+ myInserters.add(inserter);
}
+
inserters = (MySendableInsert[]) myInserters.toArray(new
MySendableInsert[myInserters.size()]);
parent.addMustSucceedBlocks(inserters.length);
parent.notifyClients();
Copied: branches/freenet-jfk/src/freenet/client/async/BlockSet.java (from rev
14796, trunk/freenet/src/freenet/client/async/BlockSet.java)
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/BlockSet.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/client/async/BlockSet.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,42 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.client.async;
+
+import java.util.Set;
+
+import freenet.keys.ClientKey;
+import freenet.keys.ClientKeyBlock;
+import freenet.keys.Key;
+import freenet.keys.KeyBlock;
+
+/**
+ * A set of KeyBlock's.
+ * @author toad
+ */
+public interface BlockSet {
+
+ /**
+ * Get a block by its key.
+ * @param key The key of the block to get.
+ * @return A block, or null if there is no block with that key.
+ */
+ public KeyBlock get(Key key);
+
+ /**
+ * Add a block.
+ * @param block The block to add.
+ */
+ public void add(KeyBlock block);
+
+ /**
+ * Get the set of all the keys of all the blocks.
+ * @return A set of the keys of the blocks in the BlockSet. Not
guaranteed to be
+ * kept up to date. Read only.
+ */
+ public Set keys();
+
+ /** Get a high level block, given a high level key */
+ public ClientKeyBlock get(ClientKey key);
+
+}
Modified: branches/freenet-jfk/src/freenet/client/async/ClientGetter.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/ClientGetter.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/ClientGetter.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -3,6 +3,7 @@
* http://www.gnu.org/ for further details of the GPL. */
package freenet.client.async;
+import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
@@ -10,14 +11,13 @@
import freenet.client.ArchiveContext;
import freenet.client.ClientMetadata;
+import freenet.client.FetchContext;
import freenet.client.FetchException;
import freenet.client.FetchResult;
-import freenet.client.FetchContext;
import freenet.client.events.SplitfileProgressEvent;
import freenet.keys.ClientKeyBlock;
import freenet.keys.FreenetURI;
import freenet.keys.Key;
-import freenet.keys.KeyBlock;
import freenet.support.Logger;
import freenet.support.api.Bucket;
import freenet.support.io.BucketTools;
@@ -41,7 +41,7 @@
/** If not null, HashSet to track keys already added for a binary blob
*/
final HashSet binaryBlobKeysAddedAlready;
private DataOutputStream binaryBlobStream;
-
+
/**
* Fetch a key.
* @param client
@@ -98,10 +98,10 @@
if(currentState != null && !finished) {
if(binaryBlobBucket != null) {
try {
- binaryBlobStream = new
DataOutputStream(binaryBlobBucket.getOutputStream());
+ binaryBlobStream = new
DataOutputStream(new BufferedOutputStream(binaryBlobBucket.getOutputStream()));
BinaryBlob.writeBinaryBlobHeader(binaryBlobStream);
} catch (IOException e) {
- onFailure(new
FetchException(FetchException.BUCKET_ERROR, "Failed to open binary blob
bucket"), null);
+ onFailure(new
FetchException(FetchException.BUCKET_ERROR, "Failed to open binary blob
bucket", e), null);
return false;
}
}
@@ -142,7 +142,13 @@
if(returnBucket != null &&
Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "client.async returned data
in returnBucket");
}
- client.onSuccess(result, this);
+ final FetchResult res = result;
+ ctx.executor.execute(new Runnable() {
+ public void run() {
+ client.onSuccess(res, ClientGetter.this);
+ }
+ }, "ClientGetter onSuccess callback");
+
}
public void onFailure(FetchException e, ClientGetState state) {
@@ -170,13 +176,20 @@
}
synchronized(this) {
finished = true;
+ currentState = null;
}
if(e.errorCodes != null && e.errorCodes.isOneCodeOnly())
e = new
FetchException(e.errorCodes.getFirstCode(), e);
if(e.mode == FetchException.DATA_NOT_FOUND &&
super.successfulBlocks > 0)
e = new FetchException(e,
FetchException.ALL_DATA_NOT_FOUND);
Logger.minor(this, "onFailure("+e+", "+state+") on
"+this+" for "+uri, e);
- client.onFailure(e, this);
+ final FetchException e1 = e;
+ ctx.executor.execute(new Runnable() {
+ public void run() {
+ client.onFailure(e1, ClientGetter.this);
+ }
+ }, "ClientGetter onFailure callback");
+
return;
}
}
@@ -267,8 +280,9 @@
* called onFailure() with an appropriate error.
*/
private boolean closeBinaryBlobStream() {
- if(binaryBlobBucket == null) return true;
+ if(binaryBlobKeysAddedAlready == null) return true;
synchronized(binaryBlobKeysAddedAlready) {
+ if(binaryBlobStream == null) return true;
try {
BinaryBlob.writeEndBlob(binaryBlobStream);
binaryBlobStream.close();
Modified:
branches/freenet-jfk/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/ClientRequestScheduler.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/ClientRequestScheduler.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -14,6 +14,8 @@
import freenet.crypt.RandomSource;
import freenet.keys.ClientKey;
import freenet.keys.ClientKeyBlock;
+import freenet.keys.Key;
+import freenet.keys.KeyBlock;
import freenet.keys.KeyVerifyException;
import freenet.node.LowLevelGetException;
import freenet.node.Node;
@@ -24,8 +26,8 @@
import freenet.node.SendableRequest;
import freenet.support.Logger;
import freenet.support.RandomGrabArray;
+import freenet.support.SectoredRandomGrabArrayWithInt;
import freenet.support.SectoredRandomGrabArrayWithObject;
-import freenet.support.SectoredRandomGrabArrayWithInt;
import freenet.support.SortedVectorByNumber;
import freenet.support.api.StringCallback;
@@ -94,6 +96,11 @@
public final String name;
private final LinkedList /* <WeakReference <RandomGrabArray> > */
recentSuccesses = new LinkedList();
+ /** All pending gets by key. Used to automatically satisfy pending
requests when either the key is fetched by
+ * an overlapping request, or it is fetched by a request from another
node. Operations on this are synchronized on
+ * itself. */
+ private final HashMap /* <Key, SendableGet[]> */ pendingKeys;
+
public static final String PRIORITY_NONE = "NONE";
public static final String PRIORITY_SOFT = "SOFT";
public static final String PRIORITY_HARD = "HARD";
@@ -159,6 +166,10 @@
this.isSSKScheduler = forSSKs;
priorities = new
SortedVectorByNumber[RequestStarter.NUMBER_OF_PRIORITY_CLASSES];
allRequestsByClientRequest = new HashMap();
+ if(forInserts)
+ pendingKeys = null;
+ else
+ pendingKeys = new HashMap();
this.name = name;
sc.register(name+"_priority_policy", PRIORITY_HARD,
name.hashCode(), true, false,
@@ -190,15 +201,22 @@
int[] keyTokens = getter.allKeys();
for(int i=0;i<keyTokens.length;i++) {
int tok = keyTokens[i];
- ClientKeyBlock block;
+ ClientKeyBlock block = null;
try {
ClientKey key =
getter.getKey(tok);
if(key == null) {
if(logMINOR)
Logger.minor(this, "No key for "+tok+" for "+getter+" - already finished?");
continue;
- } else
- block =
node.fetchKey(key, getter.dontCache());
+ } else {
+
if(getter.getContext().blocks != null)
+ block =
getter.getContext().blocks.get(key);
+ if(block == null)
+ block =
node.fetchKey(key, getter.dontCache());
+ if(block == null) {
+
addPendingKey(key, getter);
+ }
+ }
} catch (KeyVerifyException e) {
// Verify exception, probably
bogus at source;
// verifies at low-level, but
not at decode.
@@ -223,6 +241,36 @@
}
}
+ private void addPendingKey(ClientKey key, SendableGet getter) {
+ Key nodeKey = key.getNodeKey();
+ synchronized(pendingKeys) {
+ Object o = pendingKeys.get(nodeKey);
+ if(o == null) {
+ pendingKeys.put(nodeKey, getter);
+ } else if(o instanceof SendableGet) {
+ SendableGet oldGet = (SendableGet) o;
+ if(oldGet != getter) {
+ pendingKeys.put(nodeKey, new
SendableGet[] { oldGet, getter });
+ }
+ } else {
+ SendableGet[] gets = (SendableGet[]) o;
+ boolean found = false;
+ for(int j=0;j<gets.length;j++) {
+ if(gets[j] == getter) {
+ found = true;
+ break;
+ }
+ }
+ if(!found) {
+ SendableGet[] newGets = new
SendableGet[gets.length+1];
+ System.arraycopy(gets, 0, newGets, 0,
gets.length);
+ newGets[gets.length] = getter;
+ pendingKeys.put(nodeKey, newGets);
+ }
+ }
+ }
+ }
+
private synchronized void innerRegister(SendableRequest req) {
if(logMINOR) Logger.minor(this, "Still registering "+req+" at
prio "+req.getPriorityClass()+" retry "+req.getRetryCount());
addToGrabArray(req.getPriorityClass(), req.getRetryCount(),
req.getClient(), req.getClientRequest(), req);
@@ -384,6 +432,9 @@
allRequestsByClientRequest.remove(cr);
if(logMINOR) Logger.minor(this,
"Removed from HashSet for "+cr+" which now has "+v.size()+" elements");
}
+ if(!isInsertScheduler) {
+ removePendingKeys((SendableGet)
req, true);
+ }
}
if(logMINOR) Logger.minor(this, "removeFirst()
returning "+req);
return req;
@@ -393,6 +444,71 @@
return null;
}
+ public void removePendingKey(SendableGet getter, boolean complain, Key
key) {
+ synchronized(pendingKeys) {
+ Object o = pendingKeys.get(key);
+ if(o == null) {
+ if(complain)
+ Logger.normal(this, "Not found:
"+getter+" for "+key+" removing (no such key)");
+ } else if(o instanceof SendableGet) {
+ SendableGet oldGet = (SendableGet) o;
+ if(oldGet != getter) {
+ if(complain)
+ Logger.normal(this, "Not found:
"+getter+" for "+key+" removing (1 getter)");
+ } else {
+ pendingKeys.remove(key);
+ }
+ } else {
+ SendableGet[] gets = (SendableGet[]) o;
+ SendableGet[] newGets = new
SendableGet[gets.length-1];
+ boolean found = false;
+ int x = 0;
+ for(int j=0;j<gets.length;j++) {
+ if(j > newGets.length) {
+ if(!found) {
+ if(complain)
+
Logger.normal(this, "Not found: "+getter+" for "+key+" removing
("+gets.length+" getters)");
+ return; // not here
+ }
+ if(gets[j] == getter || gets[j]
== null || gets[j].isCancelled()) continue;
+ newGets[x++] = gets[j];
+ }
+ }
+ if(x != gets.length-1) {
+ SendableGet[] newNewGets = new
SendableGet[x];
+ System.arraycopy(newGets, 0,
newNewGets, 0, x);
+ newGets = newNewGets;
+ }
+ if(newGets.length == 0) {
+ pendingKeys.remove(key);
+ } else if(newGets.length == 1) {
+ pendingKeys.put(key, newGets[0]);
+ } else {
+ pendingKeys.put(key, newGets);
+ }
+ }
+ }
+ }
+
+ /**
+ * Remove a SendableGet from the list of getters we maintain for each
key, indicating that we are no longer interested
+ * in that key.
+ * @param getter
+ * @param complain
+ */
+ public void removePendingKeys(SendableGet getter, boolean complain) {
+ int[] keyTokens = getter.allKeys();
+ for(int i=0;i<keyTokens.length;i++) {
+ int tok = keyTokens[i];
+ ClientKey ckey = getter.getKey(tok);
+ if(ckey == null) {
+ Logger.error(this, "Key "+tok+" is null for
"+getter);
+ continue;
+ }
+ removePendingKey(getter, complain, ckey.getNodeKey());
+ }
+ }
+
public void reregisterAll(ClientRequester request) {
SendableRequest[] reqs;
synchronized(this) {
@@ -403,8 +519,7 @@
for(int i=0;i<reqs.length;i++) {
SendableRequest req = reqs[i];
- RandomGrabArray array = req.getParentGrabArray();
- if(array != null) array.remove(req);
+ req.unregister();
innerRegister(req);
}
synchronized(starter) {
@@ -425,4 +540,34 @@
recentSuccesses.removeLast();
}
}
+
+ public void tripPendingKey(final KeyBlock block) {
+ final Key key = block.getKey();
+ final SendableGet[] gets;
+ Object o;
+ synchronized(pendingKeys) {
+ o = pendingKeys.get(key);
+ }
+ if(o == null) return;
+ if(o instanceof SendableGet) {
+ gets = new SendableGet[] { (SendableGet) o };
+ } else {
+ gets = (SendableGet[]) o;
+ }
+ if(gets == null) return;
+ Runnable r = new Runnable() {
+ public void run() {
+ for(int i=0;i<gets.length;i++) {
+ gets[i].onGotKey(key, block);
+ }
+ }
+ };
+ node.getTicker().queueTimedJob(r, 0); // FIXME ideally these
would be completed on a single thread; when we have 1.5, use a dedicated
non-parallel Executor
+ }
+
+ public boolean anyWantKey(Key key) {
+ synchronized(pendingKeys) {
+ return pendingKeys.get(key) != null;
+ }
+ }
}
Copied: branches/freenet-jfk/src/freenet/client/async/SimpleBlockSet.java (from
rev 14796, trunk/freenet/src/freenet/client/async/SimpleBlockSet.java)
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/SimpleBlockSet.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/client/async/SimpleBlockSet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,45 @@
+package freenet.client.async;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import freenet.keys.ClientKey;
+import freenet.keys.ClientKeyBlock;
+import freenet.keys.Key;
+import freenet.keys.KeyBlock;
+import freenet.keys.KeyVerifyException;
+import freenet.support.Logger;
+
+/**
+ * Simple BlockSet implementation, keeps all keys in RAM.
+ *
+ * @author toad
+ */
+public class SimpleBlockSet implements BlockSet {
+
+ private final HashMap blocksByKey = new HashMap();
+
+ public synchronized void add(KeyBlock block) {
+ blocksByKey.put(block.getKey(), block);
+ }
+
+ public synchronized KeyBlock get(Key key) {
+ return (KeyBlock) blocksByKey.get(key);
+ }
+
+ public synchronized Set keys() {
+ return blocksByKey.keySet();
+ }
+
+ public ClientKeyBlock get(ClientKey key) {
+ KeyBlock block = get(key.getNodeKey());
+ if(block == null) return null;
+ try {
+ return Key.createKeyBlock(key, block);
+ } catch (KeyVerifyException e) {
+ Logger.error(this, "Caught decoding block with "+key+"
: "+e, e);
+ return null;
+ }
+ }
+
+}
Modified:
branches/freenet-jfk/src/freenet/client/async/SimpleManifestPutter.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/SimpleManifestPutter.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/SimpleManifestPutter.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,5 +1,6 @@
package freenet.client.async;
+import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
@@ -404,7 +405,7 @@
// Only the *decoding* is generic at present.
Bucket zipBucket = ctx.bf.makeBucket(-1);
- OutputStream os = zipBucket.getOutputStream();
+ OutputStream os = new
BufferedOutputStream(zipBucket.getOutputStream());
ZipOutputStream zos = new ZipOutputStream(os);
ZipEntry ze;
Modified:
branches/freenet-jfk/src/freenet/client/async/SimpleSingleFileFetcher.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/SimpleSingleFileFetcher.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/SimpleSingleFileFetcher.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -47,6 +47,9 @@
case LowLevelGetException.DATA_NOT_FOUND_IN_STORE:
onFailure(new
FetchException(FetchException.DATA_NOT_FOUND));
return;
+ case LowLevelGetException.RECENTLY_FAILED:
+ onFailure(new
FetchException(FetchException.RECENTLY_FAILED));
+ return;
case LowLevelGetException.DECODE_FAILED:
onFailure(new
FetchException(FetchException.BLOCK_DECODE_ERROR));
return;
@@ -95,6 +98,7 @@
}
}
// :(
+ unregister();
if(e.isFatal() || forceFatal)
parent.fatallyFailedBlock();
else
@@ -104,6 +108,7 @@
/** Will be overridden by SingleFileFetcher */
protected void onSuccess(FetchResult data) {
+ unregister();
if(parent.isCancelled()) {
data.asBucket().free();
onFailure(new FetchException(FetchException.CANCELLED));
Modified: branches/freenet-jfk/src/freenet/client/async/SingleBlockInserter.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/SingleBlockInserter.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/SingleBlockInserter.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -21,7 +21,6 @@
import freenet.node.RequestScheduler;
import freenet.node.SendableInsert;
import freenet.support.Logger;
-import freenet.support.RandomGrabArray;
import freenet.support.SimpleFieldSet;
import freenet.support.api.Bucket;
@@ -163,7 +162,7 @@
Logger.error(this, "Unknown LowLevelPutException code:
"+e.code);
errors.inc(InsertException.INTERNAL_ERROR);
}
- if(e.code == LowLevelPutException.ROUTE_NOT_FOUND) {
+ if(e.code == LowLevelPutException.ROUTE_NOT_FOUND || e.code ==
LowLevelPutException.ROUTE_REALLY_NOT_FOUND) {
consecutiveRNFs++;
if(logMINOR) Logger.minor(this, "Consecutive RNFs:
"+consecutiveRNFs+" / "+ctx.consecutiveRNFsCountAsSuccess);
if(consecutiveRNFs ==
ctx.consecutiveRNFsCountAsSuccess) {
@@ -276,8 +275,7 @@
if(finished) return;
finished = true;
}
- RandomGrabArray arr = getParentGrabArray();
- if(arr != null) arr.remove(this);
+ super.unregister();
cb.onFailure(new InsertException(InsertException.CANCELLED),
this);
}
Modified: branches/freenet-jfk/src/freenet/client/async/SingleFileFetcher.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/SingleFileFetcher.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/SingleFileFetcher.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -8,7 +8,9 @@
import java.util.LinkedList;
import freenet.client.ArchiveContext;
+import freenet.client.ArchiveExtractCallback;
import freenet.client.ArchiveFailureException;
+import freenet.client.ArchiveManager;
import freenet.client.ArchiveRestartException;
import freenet.client.ArchiveStoreContext;
import freenet.client.ClientMetadata;
@@ -158,23 +160,12 @@
onFailure(new
FetchException(FetchException.BUCKET_ERROR, e));
return;
}
- try {
- handleMetadata();
- } catch (MetadataParseException e) {
- onFailure(new FetchException(e));
- return;
- } catch (FetchException e) {
- onFailure(e);
- return;
- } catch (ArchiveFailureException e) {
- onFailure(new FetchException(e));
- } catch (ArchiveRestartException e) {
- onFailure(new FetchException(e));
- }
+ wrapHandleMetadata(false);
}
}
protected void onSuccess(FetchResult result) {
+ unregister();
if(parent.isCancelled()) {
if(logMINOR)
Logger.minor(this, "Parent is cancelled");
@@ -227,20 +218,29 @@
}
}
- private void handleMetadata() throws FetchException,
MetadataParseException, ArchiveFailureException, ArchiveRestartException {
+ /**
+ * Handle the current metadata. I.e. do something with it: transition
to a splitfile, look up a manifest, etc.
+ * LOCKING: Synchronized as it changes so many variables; if we want to
write the structure to disk, we don't
+ * want this running at the same time.
+ * @throws FetchException
+ * @throws MetadataParseException
+ * @throws ArchiveFailureException
+ * @throws ArchiveRestartException
+ */
+ private synchronized void handleMetadata() throws FetchException,
MetadataParseException, ArchiveFailureException, ArchiveRestartException {
while(true) {
if(metadata.isSimpleManifest()) {
if(logMINOR) Logger.minor(this, "Is simple
manifest");
String name;
if(metaStrings.isEmpty())
- throw new
FetchException(FetchException.NOT_ENOUGH_PATH_COMPONENTS);
+ throw new
FetchException(FetchException.NOT_ENOUGH_PATH_COMPONENTS, -1, false, null,
thisKey.addMetaStrings(new String[] { "" }));
else name = removeMetaString();
// Since metadata is a document, we just
replace metadata here
if(logMINOR) Logger.minor(this, "Next
meta-string: "+name);
if(name == null) {
metadata =
metadata.getDefaultDocument();
if(metadata == null)
- throw new
FetchException(FetchException.NOT_ENOUGH_PATH_COMPONENTS);
+ throw new
FetchException(FetchException.NOT_ENOUGH_PATH_COMPONENTS, -1, false, null,
thisKey.addMetaStrings(new String[] { "" }));
} else {
metadata = metadata.getDocument(name);
thisKey = thisKey.pushMetaString(name);
@@ -274,13 +274,35 @@
throw new
FetchException(FetchException.BUCKET_ERROR, e);
}
} else {
- fetchArchive(false, archiveMetadata);
// will result in this function being called again
+ fetchArchive(false, archiveMetadata,
ArchiveManager.METADATA_NAME, new ArchiveExtractCallback() {
+ public void gotBucket(Bucket
data) {
+ try {
+ metadata =
Metadata.construct(data);
+ } catch
(MetadataParseException e) {
+ // Invalid
metadata
+ onFailure(new
FetchException(FetchException.INVALID_METADATA, e));
+ return;
+ } catch (IOException e)
{
+ // Bucket error?
+ onFailure(new
FetchException(FetchException.BUCKET_ERROR, e));
+ return;
+ }
+
wrapHandleMetadata(true);
+ }
+ public void notInArchive() {
+ onFailure(new
FetchException(FetchException.INTERNAL_ERROR, "No metadata in container! Cannot
happen as ArchiveManager should synthesise some!"));
+ }
+ }); // will result in this function
being called again
return;
}
continue;
} else if(metadata.isArchiveInternalRedirect()) {
if(logMINOR) Logger.minor(this, "Is
archive-internal redirect");
clientMetadata.mergeNoOverwrite(metadata.getClientMetadata());
+ if(metaStrings.isEmpty() && isFinal &&
clientMetadata.getMIMETypeNoParams() != null && ctx.allowedMIMETypes != null &&
+
!ctx.allowedMIMETypes.contains(clientMetadata.getMIMETypeNoParams())) {
+ throw new
FetchException(FetchException.WRONG_MIME_TYPE, -1, false,
clientMetadata.getMIMEType());
+ }
// Fetch it from the archive
if(ah == null)
throw new
FetchException(FetchException.UNKNOWN_METADATA, "Archive redirect not in an
archive manifest");
@@ -289,30 +311,56 @@
Bucket dataBucket = ah.get(filename, actx,
null, recursionLevel+1, true);
if(dataBucket != null) {
if(logMINOR) Logger.minor(this,
"Returning data");
- // The client may free it, which is
bad, or it may hang on to it for so long that it gets
- // freed by us, which is also bad.
- // So copy it.
- // FIXME this is stupid, reconsider how
we determine when to free buckets; refcounts maybe?
- Bucket out;
+ final Bucket out;
try {
- if(returnBucket != null)
+ // Data will not be freed until
client is finished with it.
+ if(returnBucket != null) {
out = returnBucket;
- else
- out =
ctx.bucketFactory.makeBucket(dataBucket.size());
- BucketTools.copy(dataBucket,
out);
+
BucketTools.copy(dataBucket, out);
+ dataBucket.free();
+ } else {
+ out = dataBucket;
+ }
} catch (IOException e) {
- onFailure(new
FetchException(FetchException.BUCKET_ERROR));
- return;
+ throw new
FetchException(FetchException.BUCKET_ERROR);
}
// Return the data
- onSuccess(new
FetchResult(this.clientMetadata, out));
+ ctx.executor.execute(new Runnable() {
+ public void run() {
+ onSuccess(new
FetchResult(clientMetadata, out));
+ }
+ }, "SingleFileFetcher onSuccess
callback for "+this);
+
return;
} else {
if(logMINOR) Logger.minor(this,
"Fetching archive (thisKey="+thisKey+ ')');
// Metadata cannot contain pointers to
files which don't exist.
// We enforce this in ArchiveHandler.
// Therefore, the archive needs to be
fetched.
- fetchArchive(true, archiveMetadata);
+ fetchArchive(true, archiveMetadata,
filename, new ArchiveExtractCallback() {
+ public void gotBucket(Bucket
data) {
+ if(logMINOR)
Logger.minor(this, "Returning data");
+ Bucket out;
+ try {
+ // Data will
not be freed until client is finished with it.
+ if(returnBucket
!= null) {
+ out =
returnBucket;
+
BucketTools.copy(data, out);
+
data.free();
+ } else {
+ out =
data;
+ }
+ } catch (IOException e)
{
+ onFailure(new
FetchException(FetchException.BUCKET_ERROR));
+ return;
+ }
+ // Return the data
+ onSuccess(new
FetchResult(clientMetadata, out));
+ }
+ public void notInArchive() {
+ onFailure(new
FetchException(FetchException.NOT_IN_ARCHIVE));
+ }
+ });
// Will call back into this function
when it has been fetched.
return;
}
@@ -321,14 +369,31 @@
// Fetch on a second SingleFileFetcher, like
with archives.
Metadata newMeta = (Metadata) metadata.clone();
newMeta.setSimpleRedirect();
- SingleFileFetcher f = new
SingleFileFetcher(this, newMeta, new MultiLevelMetadataCallback(), ctx);
- f.handleMetadata();
+ final SingleFileFetcher f = new
SingleFileFetcher(this, newMeta, new MultiLevelMetadataCallback(), ctx);
+ ctx.ticker.queueTimedJob(new Runnable() {
+ public void run() {
+ f.wrapHandleMetadata(true);
+ }
+ }, 0);
return;
} else if(metadata.isSingleFileRedirect()) {
if(logMINOR) Logger.minor(this, "Is single-file
redirect");
clientMetadata.mergeNoOverwrite(metadata.getClientMetadata()); // even
splitfiles can have mime types!
- // FIXME implement implicit archive support
+
+ String mimeType =
clientMetadata.getMIMETypeNoParams();
+ if(mimeType != null &&
ArchiveManager.isUsableArchiveType(mimeType) && metaStrings.size() > 0) {
+ // Looks like an implicit archive,
handle as such
+ metadata.setArchiveManifest();
+ // Pick up MIME type from inside archive
+ clientMetadata.clear();
+ continue;
+ }
+ if(metaStrings.isEmpty() && isFinal && mimeType
!= null && ctx.allowedMIMETypes != null &&
+
!ctx.allowedMIMETypes.contains(mimeType)) {
+ throw new
FetchException(FetchException.WRONG_MIME_TYPE, -1, false,
clientMetadata.getMIMEType());
+ }
+
// Simple redirect
// Just create a new SingleFileFetcher
// Which will then fetch the target URI, and
call the rcd.success
@@ -358,7 +423,7 @@
}
// **FIXME** Is key in the call to
SingleFileFetcher here supposed to be this.key or the same key used in the try
block above? MultiLevelMetadataCallback.onSuccess() below uses this.key, thus
the question
- SingleFileFetcher f = new
SingleFileFetcher(parent, rcb, clientMetadata, key, metaStrings, this.uri,
addedMetaStrings, ctx, actx, ah, maxRetries, recursionLevel, false, token,
true, returnBucket, isFinal);
+ final SingleFileFetcher f = new
SingleFileFetcher(parent, rcb, clientMetadata, key, metaStrings, this.uri,
addedMetaStrings, ctx, actx, ah, maxRetries, recursionLevel, false, token,
true, returnBucket, isFinal);
if((key instanceof ClientCHK) &&
!((ClientCHK)key).isMetadata())
rcb.onBlockSetFinished(this);
if(metadata.isCompressed()) {
@@ -366,15 +431,32 @@
f.addDecompressor(codec);
}
parent.onTransition(this, f);
- f.schedule();
+ ctx.executor.execute(new Runnable() {
+ public void run() {
+ f.schedule();
+ }
+ }, "Schedule");
// All done! No longer our problem!
return;
} else if(metadata.isSplitfile()) {
if(logMINOR) Logger.minor(this, "Fetching
splitfile");
- // FIXME implicit archive support
clientMetadata.mergeNoOverwrite(metadata.getClientMetadata()); // even
splitfiles can have mime types!
+ String mimeType =
clientMetadata.getMIMETypeNoParams();
+ if(mimeType != null &&
ArchiveManager.isUsableArchiveType(mimeType) && metaStrings.size() > 0) {
+ // Looks like an implicit archive,
handle as such
+ metadata.setArchiveManifest();
+ // Pick up MIME type from inside archive
+ clientMetadata.clear();
+ continue;
+ }
+
+ if(metaStrings.isEmpty() && isFinal && mimeType
!= null && ctx.allowedMIMETypes != null &&
+
!ctx.allowedMIMETypes.contains(mimeType)) {
+ throw new
FetchException(FetchException.WRONG_MIME_TYPE,
metadata.uncompressedDataLength(), false, clientMetadata.getMIMEType());
+ }
+
// Splitfile (possibly compressed)
if(metadata.isCompressed()) {
@@ -410,8 +492,7 @@
if((len > ctx.maxOutputLength) ||
(len > ctx.maxTempLength)) {
- onFailure(new
FetchException(FetchException.TOO_BIG, len, isFinal && decompressors.size() <=
(metadata.isCompressed() ? 1 : 0), clientMetadata.getMIMEType()));
- return;
+ throw new
FetchException(FetchException.TOO_BIG, len, isFinal && decompressors.size() <=
(metadata.isCompressed() ? 1 : 0), clientMetadata.getMIMEType());
}
SplitFileFetcher sf = new
SplitFileFetcher(metadata, rcb, parent, ctx,
@@ -440,7 +521,7 @@
decompressors.addLast(codec);
}
- private void fetchArchive(boolean forData, Metadata meta) throws
FetchException, MetadataParseException, ArchiveFailureException,
ArchiveRestartException {
+ private void fetchArchive(boolean forData, Metadata meta, String
element, ArchiveExtractCallback callback) throws FetchException,
MetadataParseException, ArchiveFailureException, ArchiveRestartException {
if(logMINOR) Logger.minor(this, "fetchArchive()");
// Fetch the archive
// How?
@@ -450,42 +531,61 @@
// reschedules us.
Metadata newMeta = (Metadata) meta.clone();
newMeta.setSimpleRedirect();
- SingleFileFetcher f;
- f = new SingleFileFetcher(this, newMeta, new
ArchiveFetcherCallback(forData), new FetchContext(ctx,
FetchContext.SET_RETURN_ARCHIVES, true));
- f.handleMetadata();
- // When it is done (if successful), the ArchiveCallback will
re-call this function.
- // Which will then discover that the metadata *is* available.
- // And will also discover that the data is available, and will
complete.
+ final SingleFileFetcher f;
+ f = new SingleFileFetcher(this, newMeta, new
ArchiveFetcherCallback(forData, element, callback), new FetchContext(ctx,
FetchContext.SET_RETURN_ARCHIVES, true));
+ ctx.ticker.queueTimedJob(new Runnable() {
+ public void run() {
+ // Fetch the archive. The archive fetcher
callback will unpack it, and either call the element
+ // callback, or just go back around
handleMetadata() on this, which will see that the data is now
+ // available.
+ f.wrapHandleMetadata(true);
+ }
+ }, 0);
}
+ /**
+ * Call handleMetadata(), and deal with any resulting exceptions
+ */
+ private void wrapHandleMetadata(boolean notFinalizedSize) {
+ try {
+ handleMetadata();
+ } catch (MetadataParseException e) {
+ onFailure(new FetchException(e));
+ } catch (FetchException e) {
+ if(notFinalizedSize)
+ e.setNotFinalizedSize();
+ onFailure(e);
+ } catch (ArchiveFailureException e) {
+ onFailure(new FetchException(e));
+ } catch (ArchiveRestartException e) {
+ onFailure(new FetchException(e));
+ }
+ }
+
class ArchiveFetcherCallback implements GetCompletionCallback {
private final boolean wasFetchingFinalData;
+ private final String element;
+ private final ArchiveExtractCallback callback;
- ArchiveFetcherCallback(boolean wasFetchingFinalData) {
+ ArchiveFetcherCallback(boolean wasFetchingFinalData, String
element, ArchiveExtractCallback cb) {
this.wasFetchingFinalData = wasFetchingFinalData;
+ this.element = element;
+ this.callback = cb;
}
public void onSuccess(FetchResult result, ClientGetState state)
{
try {
- ah.extractToCache(result.asBucket(), actx);
+ ah.extractToCache(result.asBucket(), actx,
element, callback);
} catch (ArchiveFailureException e) {
SingleFileFetcher.this.onFailure(new
FetchException(e));
+ return;
} catch (ArchiveRestartException e) {
SingleFileFetcher.this.onFailure(new
FetchException(e));
+ return;
}
- try {
- handleMetadata();
- } catch (MetadataParseException e) {
- SingleFileFetcher.this.onFailure(new
FetchException(e));
- } catch (FetchException e) {
- e.setNotFinalizedSize();
- SingleFileFetcher.this.onFailure(e);
- } catch (ArchiveFailureException e) {
- SingleFileFetcher.this.onFailure(new
FetchException(e));
- } catch (ArchiveRestartException e) {
- SingleFileFetcher.this.onFailure(new
FetchException(e));
- }
+ if(callback != null) return;
+ wrapHandleMetadata(true);
}
public void onFailure(FetchException e, ClientGetState state) {
@@ -510,22 +610,15 @@
public void onSuccess(FetchResult result, ClientGetState state)
{
try {
metadata =
Metadata.construct(result.asBucket());
- handleMetadata();
} catch (MetadataParseException e) {
- SingleFileFetcher.this.onFailure(new
FetchException(e));
+ SingleFileFetcher.this.onFailure(new
FetchException(FetchException.INVALID_METADATA, e));
return;
} catch (IOException e) {
// Bucket error?
SingleFileFetcher.this.onFailure(new
FetchException(FetchException.BUCKET_ERROR, e));
return;
- } catch (FetchException e) {
- e.setNotFinalizedSize();
- onFailure(e, SingleFileFetcher.this);
- } catch (ArchiveFailureException e) {
- onFailure(new
FetchException(FetchException.ARCHIVE_FAILURE), SingleFileFetcher.this);
- } catch (ArchiveRestartException e) {
- onFailure(new
FetchException(FetchException.ARCHIVE_RESTART), SingleFileFetcher.this);
}
+ wrapHandleMetadata(true);
}
public void onFailure(FetchException e, ClientGetState state) {
Modified: branches/freenet-jfk/src/freenet/client/async/SingleFileInserter.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/SingleFileInserter.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/SingleFileInserter.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -106,10 +106,7 @@
if(data.size() > COMPRESS_OFF_THREAD_LIMIT) {
// Run off thread
OffThreadCompressor otc = new OffThreadCompressor();
- Thread t = new Thread(otc, "Compressor for "+this);
- if(logMINOR) Logger.minor(this, "Compressing
off-thread: "+t);
- t.setDaemon(true);
- t.start();
+ ctx.executor.execute(otc, "Compressor for "+this);
} else {
tryCompress();
}
@@ -214,7 +211,7 @@
boolean fitsInOneBlockAsIs = bestCodec == null ?
compressedDataSize < blockSize : compressedDataSize < oneBlockCompressedSize;
boolean fitsInOneCHK = bestCodec == null ? compressedDataSize <
CHKBlock.DATA_LENGTH : compressedDataSize < CHKBlock.MAX_COMPRESSED_DATA_LENGTH;
- if(block.getData().size() > Integer.MAX_VALUE)
+ if((fitsInOneBlockAsIs || fitsInOneCHK) &&
block.getData().size() > Integer.MAX_VALUE)
throw new
InsertException(InsertException.INTERNAL_ERROR, "2GB+ should not encode to one
block!", null);
boolean noMetadata = ((block.clientMetadata == null) ||
block.clientMetadata.isTrivial()) && targetFilename == null;
Modified: branches/freenet-jfk/src/freenet/client/async/SplitFileFetcher.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/SplitFileFetcher.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/SplitFileFetcher.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -46,10 +46,6 @@
final int segmentCount;
/** The detailed information on each segment */
final SplitFileFetcherSegment[] segments;
- /** The splitfile data blocks. */
- final ClientCHK[] splitfileDataBlocks;
- /** The splitfile check blocks. */
- final ClientCHK[] splitfileCheckBlocks;
/** Maximum temporary length */
final long maxTempLength;
/** Have all segments finished? Access synchronized. */
@@ -77,8 +73,8 @@
throw new FetchException(FetchException.CANCELLED);
overrideLength = metadata.dataLength();
this.splitfileType = metadata.getSplitfileType();
- splitfileDataBlocks = metadata.getSplitfileDataKeys();
- splitfileCheckBlocks = metadata.getSplitfileCheckKeys();
+ ClientCHK[] splitfileDataBlocks =
metadata.getSplitfileDataKeys();
+ ClientCHK[] splitfileCheckBlocks =
metadata.getSplitfileCheckKeys();
for(int i=0;i<splitfileDataBlocks.length;i++)
if(splitfileDataBlocks[i] == null) throw new
MetadataParseException("Null: data block "+i+" of "+splitfileDataBlocks.length);
for(int i=0;i<splitfileCheckBlocks.length;i++)
@@ -283,13 +279,11 @@
}
public void scheduleOffThread() {
- Thread t = new Thread(new Runnable() {
+ fetchContext.executor.execute(new Runnable() {
public void run() {
schedule();
}
}, "Splitfile scheduler thread for "+this);
- t.setDaemon(true);
- t.start();
}
}
Modified:
branches/freenet-jfk/src/freenet/client/async/SplitFileFetcherSegment.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/SplitFileFetcherSegment.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/SplitFileFetcherSegment.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -22,6 +22,7 @@
import freenet.keys.ClientCHK;
import freenet.keys.ClientCHKBlock;
import freenet.keys.ClientKeyBlock;
+import freenet.keys.NodeCHK;
import freenet.support.Logger;
import freenet.support.api.Bucket;
import freenet.support.io.BucketTools;
@@ -190,13 +191,6 @@
// Now decode
if(logMINOR) Logger.minor(this, "Decoding
"+SplitFileFetcherSegment.this);
- boolean[] dataBlocksSucceeded = new boolean[dataBuckets.length];
- boolean[] checkBlocksSucceeded = new
boolean[checkBuckets.length];
- for(int i=0;i<dataBuckets.length;i++)
- dataBlocksSucceeded[i] = dataBuckets[i].data != null;
- for(int i=0;i<checkBuckets.length;i++)
- checkBlocksSucceeded[i] = checkBuckets[i].data != null;
-
codec = FECCodec.getCodec(splitfileType, dataKeys.length,
checkKeys.length);
if(splitfileType != Metadata.SPLITFILE_NONREDUNDANT) {
@@ -210,7 +204,12 @@
if(isCollectingBinaryBlob()) {
for(int i=0;i<dataBuckets.length;i++) {
Bucket data = dataBuckets[i].getData();
- maybeAddToBinaryBlob(data, i, false);
+ try {
+ maybeAddToBinaryBlob(data, i,
false);
+ } catch (FetchException e) {
+ fail(e);
+ return;
+ }
}
}
decodedData = fetchContext.bucketFactory.makeBucket(-1);
@@ -268,7 +267,12 @@
for(int i=0;i<checkBuckets.length;i++) {
boolean heal = false;
Bucket data = checkBuckets[i].getData();
- maybeAddToBinaryBlob(data, i, true);
+ try {
+ maybeAddToBinaryBlob(data, i, true);
+ } catch (FetchException e) {
+ fail(e);
+ return;
+ }
if(checkRetries[i] > 0)
heal = true;
if(heal) {
@@ -291,7 +295,7 @@
} else return false;
}
- private void maybeAddToBinaryBlob(Bucket data, int i, boolean check) {
+ private void maybeAddToBinaryBlob(Bucket data, int i, boolean check)
throws FetchException {
if(parentFetcher.parent instanceof ClientGetter) {
ClientGetter getter = (ClientGetter)
(parentFetcher.parent);
if(getter.collectingBinaryBlob()) {
@@ -301,11 +305,9 @@
getter.addKeyToBinaryBlob(block);
} catch (CHKEncodeException e) {
Logger.error(this, "Failed to encode
(collecting binary blob) "+(check?"check":"data")+" block "+i+": "+e, e);
- fail(new
FetchException(FetchException.INTERNAL_ERROR, "Failed to encode for binary
blob: "+e));
- return;
+ throw new
FetchException(FetchException.INTERNAL_ERROR, "Failed to encode for binary
blob: "+e);
} catch (IOException e) {
- fail(new
FetchException(FetchException.BUCKET_ERROR, "Failed to encode for binary blob:
"+e));
- return;
+ throw new
FetchException(FetchException.BUCKET_ERROR, "Failed to encode for binary blob:
"+e);
}
}
}
@@ -321,6 +323,9 @@
logMINOR = Logger.shouldLog(Logger.MINOR, this);
if(logMINOR) Logger.minor(this, "Permanently failed block:
"+blockNo+" on "+this+" : "+e, e);
boolean allFailed;
+ // Since we can't keep the key, we need to unregister for it at
this point to avoid a memory leak
+ NodeCHK key = getBlockNodeKey(blockNo);
+ if(key != null) seg.unregisterKey(key);
synchronized(this) {
if(isFinishing()) return; // this failure is now
irrelevant, and cleanup will occur on the decoder thread
if(blockNo < dataKeys.length) {
@@ -345,11 +350,13 @@
failedBlocks++;
parentFetcher.parent.failedBlock();
}
- allFailed = failedBlocks + fatallyFailedBlocks <=
(dataKeys.length + checkKeys.length - minFetched);
+ // Once it is no longer possible to have a successful
fetch, fail...
+ allFailed = failedBlocks + fatallyFailedBlocks >
(dataKeys.length + checkKeys.length - minFetched);
}
if(allFailed)
fail(new FetchException(FetchException.SPLITFILE_ERROR,
errors));
- seg.possiblyRemoveFromParent();
+ else
+ seg.possiblyRemoveFromParent();
}
/** A request has failed non-fatally, so the block may be retried */
@@ -418,6 +425,7 @@
checkBuckets[i] = null;
}
}
+ removeSubSegments();
parentFetcher.segmentFinished(this);
}
@@ -449,11 +457,19 @@
}
public ClientCHK getBlockKey(int blockNum) {
- if(blockNum < dataKeys.length)
+ if(blockNum < 0) return null;
+ else if(blockNum < dataKeys.length)
return dataKeys[blockNum];
- else
+ else if(blockNum < dataKeys.length + checkKeys.length)
return checkKeys[blockNum - dataKeys.length];
+ else return null;
}
+
+ public NodeCHK getBlockNodeKey(int blockNum) {
+ ClientCHK key = getBlockKey(blockNum);
+ if(key != null) return key.getNodeCHK();
+ else return null;
+ }
public synchronized void removeSeg(SplitFileFetcherSubSegment segment) {
for(int i=0;i<subSegments.size();i++) {
@@ -464,4 +480,11 @@
}
}
+ private void removeSubSegments() {
+ for(int i=0;i<subSegments.size();i++) {
+ SplitFileFetcherSubSegment seg =
(SplitFileFetcherSubSegment) subSegments.get(i);
+ seg.kill();
+ }
+ }
+
}
Modified:
branches/freenet-jfk/src/freenet/client/async/SplitFileFetcherSubSegment.java
===================================================================
---
branches/freenet-jfk/src/freenet/client/async/SplitFileFetcherSubSegment.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/client/async/SplitFileFetcherSubSegment.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -7,7 +7,10 @@
import freenet.client.FetchException;
import freenet.keys.ClientKey;
import freenet.keys.ClientKeyBlock;
+import freenet.keys.Key;
+import freenet.keys.KeyBlock;
import freenet.keys.KeyDecodeException;
+import freenet.keys.KeyVerifyException;
import freenet.keys.TooBigException;
import freenet.node.LowLevelGetException;
import freenet.node.SendableGet;
@@ -96,6 +99,9 @@
case LowLevelGetException.DATA_NOT_FOUND_IN_STORE:
onFailure(new
FetchException(FetchException.DATA_NOT_FOUND), token);
return;
+ case LowLevelGetException.RECENTLY_FAILED:
+ onFailure(new
FetchException(FetchException.RECENTLY_FAILED), token);
+ return;
case LowLevelGetException.DECODE_FAILED:
onFailure(new
FetchException(FetchException.BLOCK_DECODE_ERROR), token);
return;
@@ -253,9 +259,46 @@
return
super.toString()+":"+retryCount+"/"+segment+'('+blockNums.size()+')';
}
- public synchronized void possiblyRemoveFromParent() {
- if(blockNums.isEmpty())
- segment.removeSeg(this);
+ public void possiblyRemoveFromParent() {
+ synchronized(this) {
+ if(!blockNums.isEmpty()) return;
+ }
+ segment.removeSeg(this);
+ unregister();
}
+
+ public void onGotKey(Key key, KeyBlock block) {
+ int blockNum = -1;
+ ClientKey ckey = null;
+ synchronized(this) {
+ for(int i=0;i<blockNums.size();i++) {
+ int num =
((Integer)blockNums.get(i)).intValue();
+ ckey = segment.getBlockKey(num);
+ if(ckey == null) return; // Already got this key
+ Key k = ckey.getNodeKey();
+ if(k.equals(key)) {
+ blockNum = num;
+ blockNums.remove(i);
+ break;
+ }
+ }
+ }
+ if(blockNum == -1) return;
+ try {
+ onSuccess(Key.createKeyBlock(ckey, block), false,
blockNum);
+ } catch (KeyVerifyException e) {
+ // FIXME if we ever abolish the direct route, this must
be turned into an onFailure().
+ Logger.error(this, "Failed to parse in
onGotKey("+key+","+block+") - believed to be "+ckey+" (block #"+blockNum+")");
+ }
+ }
+ public void kill() {
+ // Do unregister() first so can get and unregister each key and
avoid a memory leak
+ unregister();
+ synchronized(this) {
+ blockNums.clear();
+ }
+ segment.removeSeg(this);
+ }
+
}
Modified: branches/freenet-jfk/src/freenet/client/async/USKChecker.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/USKChecker.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/USKChecker.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -26,6 +26,7 @@
}
public void onSuccess(ClientKeyBlock block, boolean fromStore, int
token) {
+ unregister();
cb.onSuccess((ClientSSKBlock)block);
}
@@ -42,6 +43,7 @@
break;
case LowLevelGetException.DATA_NOT_FOUND:
case LowLevelGetException.DATA_NOT_FOUND_IN_STORE:
+ case LowLevelGetException.RECENTLY_FAILED:
dnfs++;
canRetry = true;
break;
@@ -61,7 +63,7 @@
if(canRetry && retry()) return;
// Ran out of retries.
-
+ unregister();
if(e.code == LowLevelGetException.CANCELLED){
cb.onCancelled();
return;
Modified: branches/freenet-jfk/src/freenet/client/async/USKFetcher.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/USKFetcher.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/USKFetcher.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -150,9 +150,10 @@
}
public void schedule() {
- if(checker == null)
- Logger.error(this, "Checker == null in
schedule()", new Exception("error"));
- else
+ if(checker == null) {
+ if(logMINOR)
+ Logger.minor(this, "Checker == null in
schedule() for "+this, new Exception("debug"));
+ } else
checker.schedule();
}
Modified: branches/freenet-jfk/src/freenet/client/async/USKInserter.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/USKInserter.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/USKInserter.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -69,11 +69,13 @@
* The Fetcher must be insert-mode, in other words, it must know that
we want the latest edition,
* including author errors and so on.
*/
- private synchronized void scheduleFetcher() {
- if(Logger.shouldLog(Logger.MINOR, this))
- Logger.minor(this, "scheduling fetcher for
"+pubUSK.getURI());
- if(finished) return;
- fetcher =
ctx.uskManager.getFetcherForInsertDontSchedule(pubUSK, parent.priorityClass,
this, parent.getClient());
+ private void scheduleFetcher() {
+ synchronized(this) {
+ if(Logger.shouldLog(Logger.MINOR, this))
+ Logger.minor(this, "scheduling fetcher for
"+pubUSK.getURI());
+ if(finished) return;
+ fetcher =
ctx.uskManager.getFetcherForInsertDontSchedule(pubUSK, parent.priorityClass,
this, parent.getClient());
+ }
fetcher.schedule();
}
Modified: branches/freenet-jfk/src/freenet/client/async/USKManager.java
===================================================================
--- branches/freenet-jfk/src/freenet/client/async/USKManager.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/client/async/USKManager.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -10,6 +10,7 @@
import freenet.keys.USK;
import freenet.node.NodeClientCore;
import freenet.node.RequestStarter;
+import freenet.node.Ticker;
import freenet.support.LRUQueue;
import freenet.support.Logger;
@@ -40,6 +41,8 @@
final FetchContext backgroundFetchContext;
final ClientRequestScheduler chkRequestScheduler;
final ClientRequestScheduler sskRequestScheduler;
+
+ final Ticker ticker;
public USKManager(NodeClientCore core) {
@@ -54,6 +57,7 @@
checkersByUSK = new HashMap();
backgroundFetchersByClearUSK = new HashMap();
temporaryBackgroundFetchersLRU = new LRUQueue();
+ ticker = core.getTicker();
}
/**
@@ -125,11 +129,11 @@
if(sched != null) sched.schedule();
}
- void update(USK origUSK, long number) {
+ void update(final USK origUSK, final long number) {
boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
if(logMINOR) Logger.minor(this, "Updating "+origUSK.getURI()+"
: "+number);
USK clear = origUSK.clearCopy();
- USKCallback[] callbacks;
+ final USKCallback[] callbacks;
synchronized(this) {
Long l = (Long) latestVersionByClearUSK.get(clear);
if(logMINOR) Logger.minor(this, "Old value: "+l);
@@ -141,9 +145,14 @@
callbacks = (USKCallback[])
subscribersByClearUSK.get(clear);
}
if(callbacks != null) {
- USK usk = origUSK.copy(number);
- for(int i=0;i<callbacks.length;i++)
- callbacks[i].onFoundEdition(number, usk);
+ // Run off-thread, because of locking, and because
client callbacks may take some time
+ ticker.queueTimedJob(new Runnable() {
+ public void run() {
+ USK usk = origUSK.copy(number);
+ for(int i=0;i<callbacks.length;i++)
+
callbacks[i].onFoundEdition(number, usk);
+ }
+ }, 0);
}
}
@@ -163,6 +172,8 @@
if(callbacks == null)
callbacks = new USKCallback[1];
else {
+ for(int i=0;i<callbacks.length;i++)
+ if(callbacks[i] == cb) return;
USKCallback[] newCallbacks = new
USKCallback[callbacks.length+1];
System.arraycopy(callbacks, 0, newCallbacks, 0,
callbacks.length);
callbacks = newCallbacks;
@@ -181,8 +192,14 @@
}
if(curEd > ed)
cb.onFoundEdition(curEd, origUSK.copy(curEd));
- if(sched != null)
- sched.schedule();
+ final USKFetcher fetcher = sched;
+ if(fetcher != null) {
+ ticker.queueTimedJob(new Runnable() {
+ public void run() {
+ fetcher.schedule();
+ }
+ }, 0);
+ }
}
public void unsubscribe(USK origUSK, USKCallback cb, boolean
runBackgroundFetch) {
Modified:
branches/freenet-jfk/src/freenet/client/async/USKProxyCompletionCallback.java
===================================================================
---
branches/freenet-jfk/src/freenet/client/async/USKProxyCompletionCallback.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/client/async/USKProxyCompletionCallback.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -5,6 +5,7 @@
import freenet.client.FetchException;
import freenet.client.FetchResult;
+import freenet.keys.FreenetURI;
import freenet.keys.USK;
public class USKProxyCompletionCallback implements GetCompletionCallback {
@@ -25,6 +26,11 @@
}
public void onFailure(FetchException e, ClientGetState state) {
+ FreenetURI uri = e.newURI;
+ if(uri != null) {
+ uri = usk.turnMySSKIntoUSK(uri);
+ e = new FetchException(e, uri);
+ }
cb.onFailure(e, state);
}
Modified:
branches/freenet-jfk/src/freenet/clients/http/BookmarkEditorToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/BookmarkEditorToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/BookmarkEditorToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -16,6 +16,9 @@
import freenet.node.NodeClientCore;
import freenet.client.HighLevelSimpleClient;
import freenet.support.HTMLNode;
+import freenet.support.URLDecoder;
+import freenet.support.URLEncodedFormatException;
+import freenet.support.URLEncoder;
import freenet.support.api.HTTPRequest;
public class BookmarkEditorToadlet extends Toadlet {
@@ -29,7 +32,7 @@
private final BookmarkManager bookmarkManager;
private String cutedPath;
-
+
BookmarkEditorToadlet(HighLevelSimpleClient client, NodeClientCore core)
{
super(client);
@@ -37,39 +40,39 @@
this.bookmarkManager = core.bookmarkManager;
this.cutedPath = null;
}
-
+
private void addCategoryToList(BookmarkCategory cat, String path,
HTMLNode list)
{
BookmarkItems items = cat.getItems();
-
- String edit = L10n.getString("BookmarkEditorToadlet.edit");
- String delete = L10n.getString("BookmarkEditorToadlet.delete");
- String cut = L10n.getString("BookmarkEditorToadlet.cut");
- String moveUp = L10n.getString("BookmarkEditorToadlet.moveUp");
- String moveDown =
L10n.getString("BookmarkEditorToadlet.moveDown");
- String paste = L10n.getString("BookmarkEditorToadlet.paste");
- String addBookmark =
L10n.getString("BookmarkEditorToadlet.addBookmark");
- String addCategory =
L10n.getString("BookmarkEditorToadlet.addCategory");
-
+
+ final String edit =
L10n.getString("BookmarkEditorToadlet.edit");
+ final String delete =
L10n.getString("BookmarkEditorToadlet.delete");
+ final String cut = L10n.getString("BookmarkEditorToadlet.cut");
+ final String moveUp =
L10n.getString("BookmarkEditorToadlet.moveUp");
+ final String moveDown =
L10n.getString("BookmarkEditorToadlet.moveDown");
+ final String paste =
L10n.getString("BookmarkEditorToadlet.paste");
+ final String addBookmark =
L10n.getString("BookmarkEditorToadlet.addBookmark");
+ final String addCategory =
L10n.getString("BookmarkEditorToadlet.addCategory");
+
for(int i = 0; i < items.size(); i++) {
- String itemPath = path + items.get(i).getName();
- HTMLNode li = new HTMLNode("li", "class","item" ,
items.get(i).getName());
+ String itemPath = URLEncoder.encode(path +
items.get(i).getName());
+ HTMLNode li = new HTMLNode("li", "class", "item" ,
items.get(i).getName());
HTMLNode actions = new HTMLNode("span", "class",
"actions");
actions.addChild("a", "href", "?action=edit&bookmark="
+ itemPath).addChild("img", new String[] {"src", "alt", "title"}, new String[]
{"/static/icon/edit.png", edit, edit});
-
+
actions.addChild("a", "href", "?action=del&bookmark=" +
itemPath).addChild("img", new String[] {"src", "alt", "title"}, new String[]
{"/static/icon/delete.png", delete, delete});
-
+
if(cutedPath == null)
actions.addChild("a", "href",
"?action=cut&bookmark=" + itemPath).addChild("img", new String[] {"src", "alt",
"title"}, new String[] {"/static/icon/cut.png", cut, cut});
-
+
if(i != 0)
actions.addChild("a", "href",
"?action=up&bookmark=" + itemPath).addChild("img", new String[] {"src", "alt",
"title"}, new String[] {"/static/icon/go-up.png", moveUp, moveUp});
-
+
if(i != items.size()-1)
actions.addChild("a", "href",
"?action=down&bookmark=" + itemPath).addChild("img", new String[] {"src",
"alt", "title"}, new String[] {"/static/icon/go-down.png", moveDown, moveDown});
-
+
li.addChild(actions);
list.addChild(li);
}
@@ -77,32 +80,32 @@
BookmarkCategories cats = cat.getSubCategories();
for(int i = 0; i < cats.size(); i++) {
- String catPath = path + cats.get(i).getName() + "/";
-
+ String catPath = URLEncoder.encode(path +
cats.get(i).getName() + "/");
+
HTMLNode subCat = list.addChild("li", "class", "cat",
cats.get(i).getName());
HTMLNode actions = new HTMLNode("span", "class",
"actions");
-
+
actions.addChild("a", "href", "?action=edit&bookmark="
+ catPath).addChild("img", new String[] {"src", "alt", "title"}, new String[]
{"/static/icon/edit.png", edit, edit});
-
+
actions.addChild("a", "href", "?action=del&bookmark=" +
catPath).addChild("img", new String[] {"src", "alt", "title"}, new String[]
{"/static/icon/delete.png", delete, delete});
-
+
actions.addChild("a", "href",
"?action=addItem&bookmark=" + catPath).addChild("img", new String[] {"src",
"alt", "title"}, new String[] {"/static/icon/bookmark-new.png", addBookmark,
addBookmark});
-
+
actions.addChild("a", "href",
"?action=addCat&bookmark=" + catPath).addChild("img", new String[] {"src",
"alt", "title"}, new String[] {"/static/icon/folder-new.png", addCategory,
addCategory});
-
+
if(cutedPath == null)
actions.addChild("a", "href",
"?action=cut&bookmark=" + catPath).addChild("img", new String[] {"src", "alt",
"title"}, new String[] {"/static/icon/cut.png", cut, cut});
-
+
if(i != 0)
actions.addChild("a", "href",
"?action=up&bookmark=" + catPath).addChild("img", new String[] {"src", "alt",
"title"}, new String[] {"/static/icon/go-up.png", moveUp, moveUp});
-
+
if(i != cats.size() -1)
actions.addChild("a", "href",
"?action=down&bookmark=" + catPath).addChild("img", new String[] {"src", "alt",
"title"}, new String[] {"/static/icon/go-down.png", moveDown, moveDown});
if(cutedPath != null && ! catPath.startsWith(cutedPath)
&& ! catPath.equals(bookmarkManager.parentPath(cutedPath)))
actions.addChild("a", "href",
"?action=paste&bookmark=" + catPath).addChild("img", new String[] {"src",
"alt", "title"}, new String[] {"/static/icon/paste.png", paste, paste});
-
+
subCat.addChild(actions);
if(cats.get(i).size() != 0)
addCategoryToList(cats.get(i), catPath,
list.addChild("li").addChild("ul"));
@@ -112,111 +115,120 @@
public HTMLNode getBookmarksList()
{
HTMLNode bookmarks = new HTMLNode("ul", "id", "bookmarks");
-
- HTMLNode root = bookmarks.addChild("li", "class", "cat,root",
"/");
+
+ HTMLNode root = bookmarks.addChild("li", "class", "cat root",
"/");
HTMLNode actions = new HTMLNode("span", "class", "actions");
String addBookmark =
L10n.getString("BookmarkEditorToadlet.addBookmark");
String addCategory =
L10n.getString("BookmarkEditorToadlet.addCategory");
String paste = L10n.getString("BookmarkEditorToadlet.paste");
actions.addChild("a", "href",
"?action=addItem&bookmark=/").addChild("img", new String[] {"src", "alt",
"title"}, new String[] {"/static/icon/bookmark-new.png", addBookmark,
addBookmark});
actions.addChild("a", "href",
"?action=addCat&bookmark=/").addChild("img", new String[] {"src", "alt",
"title"}, new String[] {"/static/icon/folder-new.png", addCategory,
addCategory});
-
+
if(cutedPath != null && !
"/".equals(bookmarkManager.parentPath(cutedPath)))
actions.addChild("a", "href",
"?action=paste&bookmark=/").addChild("img", new String[] {"src", "alt",
"title"}, new String[] {"/static/icon/paste.png", paste, paste});
-
+
root.addChild(actions);
- addCategoryToList(bookmarkManager.getMainCategory(), "/",
root.addChild("li").addChild("ul"));
-
+ addCategoryToList(bookmarkManager.getMainCategory(), "/",
root.addChild("ul"));
+
return bookmarks;
}
-
+
public void handleGet(URI uri, HTTPRequest req, ToadletContext ctx)
- throws ToadletContextClosedException, IOException
+ throws ToadletContextClosedException, IOException
{
-
+
String editorTitle =
L10n.getString("BookmarkEditorToadlet.title");
String error = L10n.getString("BookmarkEditorToadlet.error");
HTMLNode pageNode = ctx.getPageMaker().getPageNode(editorTitle,
ctx);
HTMLNode content = ctx.getPageMaker().getContentNode(pageNode);
-
+
if (req.getParam("action").length() > 0 &&
req.getParam("bookmark").length() > 0) {
String action = req.getParam("action");
- String bookmarkPath = req.getParam("bookmark");
+ String bookmarkPath;
+ try {
+ bookmarkPath =
URLDecoder.decode(req.getParam("bookmark"), false);
+ } catch (URLEncodedFormatException e) {
+ HTMLNode errorBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-error", error));
+ errorBox.addChild("#",
L10n.getString("BookmarkEditorToadlet.urlDecodeError"));
+ writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
+ return;
+ }
Bookmark bookmark;
-
+
if (bookmarkPath.endsWith("/"))
bookmark =
bookmarkManager.getCategoryByPath(bookmarkPath);
else
bookmark =
bookmarkManager.getItemByPath(bookmarkPath);
-
+
if(bookmark == null) {
HTMLNode errorBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-error", error));
errorBox.addChild("#",
L10n.getString("BookmarkEditorToadlet.bookmarkDoesNotExist", new String[] {
"bookmark" }, new String[] { bookmarkPath }));
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
+ return;
} else {
-
- if(action.equals("del")){
-
- String[] bm = new String[] { "bookmark" };
- String[] path = new String[] { bookmarkPath };
- String queryTitle =
L10n.getString("BookmarkEditorToadlet." + ((bookmark instanceof BookmarkItem) ?
"deleteBookmark" : "deleteCategory"));
- HTMLNode infoBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-query", queryTitle));
- String query =
L10n.getString("BookmarkEditorToadlet." + ((bookmark instanceof BookmarkItem) ?
"deleteBookmarkConfirm" : "deleteCategoryConfirm"), bm, path);
- infoBox.addChild("p").addChild("#", query);
-
- HTMLNode confirmForm =
ctx.addFormChild(infoBox.addChild("p"), "", "confirmDeleteForm");
- confirmForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "hidden", "bookmark", bookmarkPath});
- confirmForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel") });
- confirmForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "confirmdelete",
L10n.getString("BookmarkEditorToadlet.confirmDelete") });
-
- } else if (action.equals("cut")) {
+ if("del".equals(action)){
- cutedPath = bookmarkPath;
+ String[] bm = new String[] { "bookmark"
};
+ String[] path = new String[] {
bookmarkPath };
+ String queryTitle =
L10n.getString("BookmarkEditorToadlet." + ((bookmark instanceof BookmarkItem) ?
"deleteBookmark" : "deleteCategory"));
+ HTMLNode infoBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-query", queryTitle));
- } else if ("paste".equals(action) && cutedPath != null)
{
-
- bookmarkManager.moveBookmark(cutedPath,
bookmarkPath, true);
- cutedPath = null;
-
- } else if (action.equals("edit") ||
action.equals("addItem") || action.equals("addCat")) {
-
- String header;
- if(action.equals("edit")) {
- header =
L10n.getString("BookmarkEditorToadlet.edit" + ((bookmark instanceof
BookmarkItem) ? "Bookmark" : "Category") + "Title");
- } else if(action.equals("addItem")) {
- header =
L10n.getString("BookmarkEditorToadlet.addNewBookmark");
- } else {
- header =
L10n.getString("BookmarkEditorToadlet.addNewCategory");
+ String query =
L10n.getString("BookmarkEditorToadlet." + ((bookmark instanceof BookmarkItem) ?
"deleteBookmarkConfirm" : "deleteCategoryConfirm"), bm, path);
+ infoBox.addChild("p").addChild("#",
query);
+
+ HTMLNode confirmForm =
ctx.addFormChild(infoBox.addChild("p"), "", "confirmDeleteForm");
+ confirmForm.addChild("input", new
String[] { "type", "name", "value" }, new String[] { "hidden", "bookmark",
bookmarkPath});
+ confirmForm.addChild("input", new
String[] { "type", "name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel") });
+ confirmForm.addChild("input", new
String[] { "type", "name", "value" }, new String[] { "submit", "confirmdelete",
L10n.getString("BookmarkEditorToadlet.confirmDelete") });
+
+ } else if ("cut".equals(action)) {
+
+ cutedPath = bookmarkPath;
+
+ } else if ("paste".equals(action) && cutedPath
!= null) {
+
+ bookmarkManager.moveBookmark(cutedPath,
bookmarkPath, true);
+ cutedPath = null;
+
+ } else if ("edit".equals(action) ||
"addItem".equals(action) || "addCat".equals(action)) {
+
+ String header;
+ if("edit".equals(action)) {
+ header =
L10n.getString("BookmarkEditorToadlet.edit" + ((bookmark instanceof
BookmarkItem) ? "Bookmark" : "Category") + "Title");
+ } else if("addItem".equals(action)) {
+ header =
L10n.getString("BookmarkEditorToadlet.addNewBookmark");
+ } else {
+ header =
L10n.getString("BookmarkEditorToadlet.addNewCategory");
+ }
+
+ HTMLNode actionBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-query", header));
+
+ HTMLNode form =
ctx.addFormChild(actionBox, "", "editBookmarkForm");
+
+ form.addChild("label", "for", "name",
(L10n.getString("BookmarkEditorToadlet.nameLabel") + ' '));
+ form.addChild("input", new
String[]{"type", "id", "name", "size", "value"}, new String []{"text", "name",
"name", "20", "edit".equals(action)?bookmark.getName():""});
+
+ form.addChild("br");
+ if (("edit".equals(action) && bookmark
instanceof BookmarkItem) || "addItem".equals(action)) {
+ String key =
(action.equals("edit") ? ((BookmarkItem) bookmark).getKey() : "");
+ form.addChild("label", "for",
"key", (L10n.getString("BookmarkEditorToadlet.keyLabel") + ' '));
+ form.addChild("input", new
String[]{"type", "id", "name", "size", "value"}, new String []{"text", "key",
"key", "50", key});
+ }
+
+ form.addChild("input", new String[]
{"type", "name", "value"}, new String[] {"hidden", "bookmark",bookmarkPath});
+
+ form.addChild("input", new String[]
{"type", "name", "value"}, new String[] {"hidden",
"action",req.getParam("action")});
+
+ form.addChild("br");
+ form.addChild("input", new
String[]{"type", "value"}, new String[]{"submit",
L10n.getString("BookmarkEditorToadlet.save")});
+ } else if ("up".equals(action)) {
+
bookmarkManager.moveBookmarkUp(bookmarkPath, true);
+ } else if("down".equals(action)) {
+
bookmarkManager.moveBookmarkDown(bookmarkPath, true);
}
-
- HTMLNode actionBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-query", header));
-
- HTMLNode form = ctx.addFormChild(actionBox, "",
"editBookmarkForm");
-
- form.addChild("label", "for", "name",
(L10n.getString("BookmarkEditorToadlet.nameLabel") + ' '));
- form.addChild("input", new String[]{"type",
"id", "name", "size", "value"}, new String []{"text", "name", "name", "20",
action.equals("edit")?bookmark.getName():""});
-
- form.addChild("br");
- if ((action.equals("edit") && bookmark
instanceof BookmarkItem) || action.equals("addItem")) {
- String key = (action.equals("edit") ?
((BookmarkItem) bookmark).getKey() : "");
- form.addChild("label", "for", "key",
(L10n.getString("BookmarkEditorToadlet.keyLabel") + ' '));
- form.addChild("input", new
String[]{"type", "id", "name", "size", "value"}, new String []{"text", "key",
"key", "50", key});
- }
-
- form.addChild("input", new String[] {"type",
"name", "value"}, new String[] {"hidden", "bookmark",bookmarkPath});
-
- form.addChild("input", new String[] {"type",
"name", "value"}, new String[] {"hidden", "action",req.getParam("action")});
-
- form.addChild("br");
- form.addChild("input", new String[]{"type",
"value"}, new String[]{"submit", L10n.getString("BookmarkEditorToadlet.save")});
- } else if (action.equals("up") ||
action.equals("down")) {
- if(action.equals("up"))
-
bookmarkManager.moveBookmarkUp(bookmarkPath, true);
- else
-
bookmarkManager.moveBookmarkDown(bookmarkPath, true);
}
- }
-
+
}
if(cutedPath != null) {
@@ -225,90 +237,90 @@
HTMLNode cancelForm =
ctx.addFormChild(infoBox.addChild("p"), "", "cancelCutForm");
cancelForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "cancelCut",
L10n.getString("BookmarkEditorToadlet.cancelCut") });
}
-
+
HTMLNode bookmarksBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-normal",
L10n.getString("BookmarkEditorToadlet.myBookmarksTitle")));
bookmarksBox.addChild(getBookmarksList());
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}
-
+
public void handlePost(URI uri, HTTPRequest req, ToadletContext ctx)
- throws ToadletContextClosedException, IOException
+ throws ToadletContextClosedException, IOException
{
HTMLNode pageNode =
ctx.getPageMaker().getPageNode(L10n.getString("BookmarkEditorToadlet.title"),
ctx);
HTMLNode content = ctx.getPageMaker().getContentNode(pageNode);
-
+
String passwd = req.getPartAsString("formPassword", 32);
boolean noPassword = (passwd == null) ||
!passwd.equals(core.formPassword);
if(noPassword)
return;
-
-
+
+
String bookmarkPath = req.getPartAsString("bookmark",
MAX_BOOKMARK_PATH_LENGTH);
try {
-
+
Bookmark bookmark;
if(bookmarkPath.endsWith("/"))
bookmark =
bookmarkManager.getCategoryByPath(bookmarkPath);
else
bookmark =
bookmarkManager.getItemByPath(bookmarkPath);
-
+ if(bookmark == null) {
+ HTMLNode errorBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-error",
L10n.getString("BookmarkEditorToadlet.error")));
+ errorBox.addChild("#",
L10n.getString("BookmarkEditorToadlet.bookmarkDoesNotExist", new String[] {
"bookmark" } , new String[] { bookmarkPath }));
+ return;
+ }
+
+
String action = req.getPartAsString("action",
MAX_ACTION_LENGTH);
-
+
if (req.isPartSet("confirmdelete")) {
bookmarkManager.removeBookmark(bookmarkPath,
true);
HTMLNode successBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-success",
L10n.getString("BookmarkEditorToadlet.deleteSucceededTitle")));
successBox.addChild("p",
L10n.getString("BookmarkEditorToadlet.deleteSucceeded"));
-
+
} else if (req.isPartSet("cancelCut")) {
cutedPath = null;
-
- } else if (action.equals("edit") ||
action.equals("addItem") || action.equals("addCat")) {
-
+
+ } else if ("edit".equals(action) ||
"addItem".equals(action) || "addCat".equals(action)) {
+
String name = "unnamed";
if (req.getPartAsString("name",
MAX_NAME_LENGTH).length() > 0)
name = req.getPartAsString("name",
MAX_NAME_LENGTH);
-
- if(action.equals("edit")) {
+
+ if("edit".equals(action)) {
bookmarkManager.renameBookmark(bookmarkPath, name);
if(bookmark instanceof BookmarkItem)
((BookmarkItem)
bookmark).setKey(new FreenetURI(req.getPartAsString("key", MAX_KEY_LENGTH)));
-
+
HTMLNode successBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-success",
L10n.getString("BookmarkEditorToadlet.changesSavedTitle")));
successBox.addChild("p",
L10n.getString("BookmarkEditorToadlet.changesSaved"));
-
- } else if (action.equals("addItem") ||
action.equals("addCat")) {
-
+
+ } else if ("addItem".equals(action) ||
"addCat".equals(action)) {
+
Bookmark newBookmark;
- if(action.equals("addItem")) {
+ if("addItem".equals(action)) {
FreenetURI key = new
FreenetURI(req.getPartAsString("key", MAX_KEY_LENGTH));
newBookmark = new
BookmarkItem(key, name, core.alerts);
} else
newBookmark = new
BookmarkCategory(name);
-
+
bookmarkManager.addBookmark(bookmarkPath, newBookmark, true);
-
+
HTMLNode successBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-success",
L10n.getString("BookmarkEditorToadlet.addedNewBookmarkTitle")));
successBox.addChild("p",
L10n.getString("BookmarkEditorToadlet.addedNewBookmark"));
-
}
-
}
-
- } catch (NullPointerException npo) {
- HTMLNode errorBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-error",
L10n.getString("BookmarkEditorToadlet.error")));
- errorBox.addChild("#",
L10n.getString("BookmarkEditorToadlet.bookmarkDoesNotExist", new String[] {
"bookmark" } , new String[] { bookmarkPath }));
} catch (MalformedURLException mue) {
HTMLNode errorBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-error",
L10n.getString("BookmarkEditorToadlet.invalidKeyTitle")));
errorBox.addChild("#",
L10n.getString("BookmarkEditorToadlet.invalidKey"));
}
HTMLNode bookmarksBox =
content.addChild(ctx.getPageMaker().getInfobox("infobox-normal",
L10n.getString("BookmarkEditorToadlet.myBookmarksTitle")));
bookmarksBox.addChild(getBookmarksList());
-
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+
+ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}
-
+
public String supportedMethods()
{
return "GET, POST";
Modified: branches/freenet-jfk/src/freenet/clients/http/BrowserTestToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/BrowserTestToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/BrowserTestToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -178,7 +178,7 @@
// Yes, we need that in order to test the browser (number of
connections per server)
if (request.isParameterSet("wontload")) return;
else if (request.isParameterSet("mimeTest")){
- this.writeReply(ctx, 200, "text/html", "OK",
imgWarningMime);
+ this.writeHTMLReply(ctx, 200, "OK", imgWarningMime);
return;
}
@@ -210,7 +210,7 @@
jsTest.addChild("img", new String[]{"id", "src", "alt"}, new
String[]{"JSTEST", "/static/themes/clean/success.gif", "fail!"});
jsTest.addChild("script", "type",
"text/javascript").addChild("%", "document.getElementById('JSTEST').src =
'/static/themes/clean/warning.gif';");
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}
public String supportedMethods() {
Modified: branches/freenet-jfk/src/freenet/clients/http/ConfigToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/ConfigToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/ConfigToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -11,6 +11,7 @@
import freenet.config.BooleanOption;
import freenet.config.Config;
import freenet.config.EnumerableOptionCallback;
+import freenet.config.InvalidConfigValueException;
import freenet.config.Option;
import freenet.config.SubConfig;
import freenet.l10n.L10n;
@@ -73,7 +74,9 @@
if(logMINOR) Logger.minor(this,
"Setting "+prefix+ '.' +configName+" to "+value);
try{
o[j].setValue(value);
- }catch(Exception e){
+ } catch
(InvalidConfigValueException e) {
+
errbuf.append(o[j].getName()).append(' ').append(e.getMessage()).append('\n');
+ } catch (Exception e){
errbuf.append(o[j].getName()).append('
').append(e).append('\n');
Logger.error(this,
"Caught "+e, e);
}
@@ -103,7 +106,7 @@
content.addChild("br");
addHomepageLink(content);
- writeReply(ctx, 200, "text/html", "OK", pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}
@@ -130,6 +133,7 @@
if(advancedModeEnabled){
HTMLNode navigationBar =
ctx.getPageMaker().getInfobox("navbar", l10n("configNavTitle"));
HTMLNode navigationContent =
ctx.getPageMaker().getContentNode(navigationBar).addChild("ul");
+ navigationContent.addChild("a", "href",
TranslationToadlet.TOADLET_URL, l10n("contributeTranslation"));
HTMLNode navigationTable =
navigationContent.addChild("table", "class", "config_navigation");
HTMLNode navigationTableRow =
navigationTable.addChild("tr");
HTMLNode nextTableCell = navigationTableRow;
@@ -158,7 +162,7 @@
HTMLNode configItemNode =
configGroupUlNode.addChild("li");
configItemNode.addChild("span", new
String[]{ "class", "title", "style" },
- new String[]{
"configshortdesc", L10n.getString("ConfigToadlet.defaultIs", new String[] {
"default" }, new String[] { o[j].getDefault() }),
+ new String[]{
"configshortdesc", L10n.getString("ConfigToadlet.defaultIs", new String[] {
"default" }, new String[] { o[j].getDefault() }) + (advancedModeEnabled ? "
["+sc[i].getPrefix() + '.' + o[j].getName() + ']' : ""),
"cursor: help;"
}).addChild(L10n.getHTMLNode(o[j].getShortDesc()));
HTMLNode configItemValueNode =
configItemNode.addChild("span", "class", "config");
if(o[j].getValueString() == null){
@@ -179,7 +183,7 @@
if(displayedConfigElements>0) {
formNode.addChild("div", "class",
"configprefix", sc[i].getPrefix());
- formNode.addChild("a", "name",
sc[i].getPrefix());
+ formNode.addChild("a", "id", sc[i].getPrefix());
formNode.addChild(configGroupUlNode);
}
}
@@ -187,7 +191,7 @@
formNode.addChild("input", new String[] { "type", "value" },
new String[] { "submit", l10n("apply")});
formNode.addChild("input", new String[] { "type", "value" },
new String[] { "reset", l10n("reset")});
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}
public String supportedMethods() {
Copied: branches/freenet-jfk/src/freenet/clients/http/ConnectionsToadlet.java
(from rev 14796, trunk/freenet/src/freenet/clients/http/ConnectionsToadlet.java)
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/ConnectionsToadlet.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/clients/http/ConnectionsToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,872 @@
+package freenet.clients.http;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import freenet.client.HighLevelSimpleClient;
+import freenet.io.comm.PeerParseException;
+import freenet.io.comm.ReferenceSignatureVerificationException;
+import freenet.io.xfer.PacketThrottle;
+import freenet.l10n.L10n;
+import freenet.node.DarknetPeerNode;
+import freenet.node.FSParseException;
+import freenet.node.Node;
+import freenet.node.NodeClientCore;
+import freenet.node.NodeStats;
+import freenet.node.PeerManager;
+import freenet.node.PeerNode;
+import freenet.node.PeerNodeStatus;
+import freenet.node.Version;
+import freenet.support.HTMLNode;
+import freenet.support.Logger;
+import freenet.support.MultiValueTable;
+import freenet.support.SimpleFieldSet;
+import freenet.support.SizeUtil;
+import freenet.support.TimeUtil;
+import freenet.support.api.HTTPRequest;
+
+public abstract class ConnectionsToadlet extends Toadlet {
+
+ protected class ComparatorByStatus implements Comparator {
+
+ protected final String sortBy;
+ protected final boolean reversed;
+
+ ComparatorByStatus(String sortBy, boolean reversed) {
+ this.sortBy = sortBy;
+ this.reversed = reversed;
+ }
+
+ public int compare(Object first, Object second) {
+ int result = 0;
+ boolean isSet = true;
+ PeerNodeStatus firstNode = (PeerNodeStatus) first;
+ PeerNodeStatus secondNode = (PeerNodeStatus) second;
+
+ if(sortBy != null){
+ result = customCompare(firstNode, secondNode,
sortBy);
+ isSet = (result != 0);
+
+ }else
+ isSet=false;
+
+ if(!isSet){
+ int statusDifference =
firstNode.getStatusValue() - secondNode.getStatusValue();
+ if (statusDifference != 0)
+ result = (statusDifference < 0 ? -1 :
1);
+ else
+ result = lastResortCompare(firstNode,
secondNode);
+ }
+
+ if(result == 0){
+ return 0;
+ }else if(reversed){
+ isReversed = true;
+ return result > 0 ? -1 : 1;
+ }else{
+ isReversed = false;
+ return result < 0 ? -1 : 1;
+ }
+ }
+
+ protected int customCompare(PeerNodeStatus firstNode,
PeerNodeStatus secondNode, String sortBy2) {
+ if(sortBy.equals("address")){
+ return
firstNode.getPeerAddress().compareToIgnoreCase(secondNode.getPeerAddress());
+ }else if(sortBy.equals("location")){
+ return compareLocations(firstNode, secondNode);
+ }else if(sortBy.equals("version")){
+ return
Version.getArbitraryBuildNumber(firstNode.getVersion()) -
Version.getArbitraryBuildNumber(secondNode.getVersion());
+ }else
+ return 0;
+ }
+
+ private int compareLocations(PeerNodeStatus firstNode,
PeerNodeStatus secondNode) {
+ double diff = firstNode.getLocation() -
secondNode.getLocation(); // Can occasionally be the same, and we must have a
consistent sort order
+ if(Double.MIN_VALUE*2 > Math.abs(diff)) return 0;
+ return diff > 0 ? 1 : -1;
+ }
+
+ /** Default comparison, after taking into account status */
+ protected int lastResortCompare(PeerNodeStatus firstNode,
PeerNodeStatus secondNode) {
+ return compareLocations(firstNode, secondNode);
+ }
+ }
+
+ protected final Node node;
+ protected final NodeClientCore core;
+ protected final NodeStats stats;
+ protected final PeerManager peers;
+ protected boolean isReversed = false;
+ protected final DecimalFormat fix1 = new DecimalFormat("##0.0%");
+
+ public String supportedMethods() {
+ if(this.acceptRefPosts())
+ return "GET, POST";
+ else
+ return "GET";
+ }
+
+ protected ConnectionsToadlet(Node n, NodeClientCore core,
HighLevelSimpleClient client) {
+ super(client);
+ this.node = n;
+ this.core = core;
+ this.stats = n.nodeStats;
+ this.peers = n.peers;
+ }
+
+ public void handleGet(URI uri, final HTTPRequest request,
ToadletContext ctx) throws ToadletContextClosedException, IOException,
RedirectException {
+ String path = uri.getPath();
+ if(path.endsWith("myref.fref")) {
+ SimpleFieldSet fs = getNoderef();
+ StringWriter sw = new StringWriter();
+ fs.writeTo(sw);
+ MultiValueTable extraHeaders = new MultiValueTable();
+ // Force download to disk
+ extraHeaders.put("Content-Disposition", "attachment;
filename=myref.fref");
+ this.writeReply(ctx, 200,
"application/x-freenet-reference", "OK", extraHeaders, sw.toString());
+ return;
+ }
+
+ if(path.endsWith("myref.txt")) {
+ SimpleFieldSet fs = getNoderef();
+ StringWriter sw = new StringWriter();
+ fs.writeTo(sw);
+ this.writeTextReply(ctx, 200, "OK", sw.toString());
+ return;
+ }
+
+ if(!ctx.isAllowedFullAccess()) {
+ super.sendErrorPage(ctx, 403, "Unauthorized",
L10n.getString("Toadlet.unauthorized"));
+ return;
+ }
+
+ final boolean advancedModeEnabled =
node.isAdvancedModeEnabled();
+ final boolean fProxyJavascriptEnabled =
node.isFProxyJavascriptEnabled();
+
+ /* gather connection statistics */
+ PeerNodeStatus[] peerNodeStatuses = getPeerNodeStatuses();
+ Arrays.sort(peerNodeStatuses,
comparator(request.getParam("sortBy", null),
request.isParameterSet("reversed")));
+
+ int numberOfConnected =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_CONNECTED);
+ int numberOfRoutingBackedOff =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_ROUTING_BACKED_OFF);
+ int numberOfTooNew =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_TOO_NEW);
+ int numberOfTooOld =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_TOO_OLD);
+ int numberOfDisconnected =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_DISCONNECTED);
+ int numberOfNeverConnected =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_NEVER_CONNECTED);
+ int numberOfDisabled =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_DISABLED);
+ int numberOfBursting =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_BURSTING);
+ int numberOfListening =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_LISTENING);
+ int numberOfListenOnly =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_LISTEN_ONLY);
+ int numberOfClockProblem =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_CLOCK_PROBLEM);
+ int numberOfConnError =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_CONN_ERROR);
+
+ int numberOfSimpleConnected = numberOfConnected +
numberOfRoutingBackedOff;
+ int numberOfNotConnected = numberOfTooNew + numberOfTooOld +
numberOfDisconnected + numberOfNeverConnected + numberOfDisabled +
numberOfBursting + numberOfListening + numberOfListenOnly +
numberOfClockProblem + numberOfConnError;
+ String titleCountString = null;
+ if(advancedModeEnabled) {
+ titleCountString = "(" + numberOfConnected + '/' +
numberOfRoutingBackedOff + '/' + numberOfTooNew + '/' + numberOfTooOld + '/' +
numberOfNotConnected + ')';
+ } else {
+ titleCountString = (numberOfNotConnected +
numberOfSimpleConnected)>0 ? String.valueOf(numberOfSimpleConnected) : "";
+ }
+
+ HTMLNode pageNode =
ctx.getPageMaker().getPageNode(getPageTitle(titleCountString,
node.getMyName()), ctx);
+ HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
+
+ // FIXME! We need some nice images
+ long now = System.currentTimeMillis();
+
+ if(ctx.isAllowedFullAccess())
+ contentNode.addChild(core.alerts.createSummary());
+
+ if(peerNodeStatuses.length>0){
+
+ /* node status values */
+ long nodeUptimeSeconds = (now - node.startupTime) /
1000;
+ int bwlimitDelayTime = (int)
stats.getBwlimitDelayTime();
+ int nodeAveragePingTime = (int)
stats.getNodeAveragePingTime();
+ int networkSizeEstimateSession =
stats.getNetworkSizeEstimate(-1);
+ int networkSizeEstimateRecent = 0;
+ if(nodeUptimeSeconds > (48*60*60)) { // 48 hours
+ networkSizeEstimateRecent =
stats.getNetworkSizeEstimate(now - (48*60*60*1000)); // 48 hours
+ }
+ DecimalFormat fix4 = new DecimalFormat("0.0000");
+ double routingMissDistance =
stats.routingMissDistance.currentValue();
+ double backedOffPercent =
stats.backedOffPercent.currentValue();
+ String nodeUptimeString =
TimeUtil.formatTime(nodeUptimeSeconds * 1000); // *1000 to convert to
milliseconds
+
+ // BEGIN OVERVIEW TABLE
+ HTMLNode overviewTable = contentNode.addChild("table",
"class", "column");
+ HTMLNode overviewTableRow =
overviewTable.addChild("tr");
+ HTMLNode nextTableCell =
overviewTableRow.addChild("td", "class", "first");
+
+ /* node status overview box */
+ if(advancedModeEnabled) {
+ HTMLNode overviewInfobox =
nextTableCell.addChild("div", "class", "infobox");
+ overviewInfobox.addChild("div", "class",
"infobox-header", "Node status overview");
+ HTMLNode overviewInfoboxContent =
overviewInfobox.addChild("div", "class", "infobox-content");
+ HTMLNode overviewList =
overviewInfoboxContent.addChild("ul");
+ overviewList.addChild("li",
"bwlimitDelayTime:\u00a0" + bwlimitDelayTime + "ms");
+ overviewList.addChild("li",
"nodeAveragePingTime:\u00a0" + nodeAveragePingTime + "ms");
+ overviewList.addChild("li",
"networkSizeEstimateSession:\u00a0" + networkSizeEstimateSession +
"\u00a0nodes");
+ if(nodeUptimeSeconds > (48*60*60)) { // 48
hours
+ overviewList.addChild("li",
"networkSizeEstimateRecent:\u00a0" + networkSizeEstimateRecent + "\u00a0nodes");
+ }
+ overviewList.addChild("li", "nodeUptime:\u00a0"
+ nodeUptimeString);
+ overviewList.addChild("li",
"routingMissDistance:\u00a0" + fix4.format(routingMissDistance));
+ overviewList.addChild("li",
"backedOffPercent:\u00a0" + fix1.format(backedOffPercent));
+ overviewList.addChild("li",
"pInstantReject:\u00a0" + fix1.format(stats.pRejectIncomingInstantly()));
+ nextTableCell = overviewTableRow.addChild("td");
+ }
+
+ // Activity box
+ int numARKFetchers = node.getNumARKFetchers();
+
+ HTMLNode activityInfobox =
nextTableCell.addChild("div", "class", "infobox");
+ activityInfobox.addChild("div", "class",
"infobox-header", l10n("activityTitle"));
+ HTMLNode activityInfoboxContent =
activityInfobox.addChild("div", "class", "infobox-content");
+ HTMLNode activityList =
StatisticsToadlet.drawActivity(activityInfoboxContent, node);
+ if (advancedModeEnabled && activityList != null) {
+ if (numARKFetchers > 0) {
+ activityList.addChild("li",
"ARK\u00a0Fetch\u00a0Requests:\u00a0" + numARKFetchers);
+ }
+ StatisticsToadlet.drawBandwidth(activityList,
node, nodeUptimeSeconds);
+ }
+
+ nextTableCell = advancedModeEnabled ?
overviewTableRow.addChild("td") : overviewTableRow.addChild("td", "class",
"last");
+
+ // Peer statistics box
+ HTMLNode peerStatsInfobox =
nextTableCell.addChild("div", "class", "infobox");
+ peerStatsInfobox.addChild("div", "class",
"infobox-header", l10nStats("peerStatsTitle"));
+ HTMLNode peerStatsContent =
peerStatsInfobox.addChild("div", "class", "infobox-content");
+ HTMLNode peerStatsList =
peerStatsContent.addChild("ul");
+ if (numberOfConnected > 0) {
+ HTMLNode peerStatsConnectedListItem =
peerStatsList.addChild("li").addChild("span");
+ peerStatsConnectedListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_connected",
l10n("connected"), "border-bottom: 1px dotted; cursor: help;" },
l10n("connectedShort"));
+ peerStatsConnectedListItem.addChild("span",
":\u00a0" + numberOfConnected);
+ }
+ if (numberOfRoutingBackedOff > 0) {
+ HTMLNode peerStatsRoutingBackedOffListItem =
peerStatsList.addChild("li").addChild("span");
+
peerStatsRoutingBackedOffListItem.addChild("span", new String[] { "class",
"title", "style" }, new String[] { "peer_backed_off", (advancedModeEnabled ?
l10n("backedOff") : l10n("busy")), "border-bottom: 1px dotted; cursor: help;"
}, advancedModeEnabled ? l10n("backedOffShort") : l10n("busyShort"));
+
peerStatsRoutingBackedOffListItem.addChild("span", ":\u00a0" +
numberOfRoutingBackedOff);
+ }
+ if (numberOfTooNew > 0) {
+ HTMLNode peerStatsTooNewListItem =
peerStatsList.addChild("li").addChild("span");
+ peerStatsTooNewListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_too_new",
l10n("tooNew"), "border-bottom: 1px dotted; cursor: help;" },
l10n("tooNewShort"));
+ peerStatsTooNewListItem.addChild("span",
":\u00a0" + numberOfTooNew);
+ }
+ if (numberOfTooOld > 0) {
+ HTMLNode peerStatsTooOldListItem =
peerStatsList.addChild("li").addChild("span");
+ peerStatsTooOldListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_too_old",
l10n("tooOld"), "border-bottom: 1px dotted; cursor: help;" },
l10n("tooOldShort"));
+ peerStatsTooOldListItem.addChild("span",
":\u00a0" + numberOfTooOld);
+ }
+ if (numberOfDisconnected > 0) {
+ HTMLNode peerStatsDisconnectedListItem =
peerStatsList.addChild("li").addChild("span");
+ peerStatsDisconnectedListItem.addChild("span",
new String[] { "class", "title", "style" }, new String[] { "peer_disconnected",
l10n("notConnected"), "border-bottom: 1px dotted; cursor: help;" },
l10n("notConnectedShort"));
+ peerStatsDisconnectedListItem.addChild("span",
":\u00a0" + numberOfDisconnected);
+ }
+ if (numberOfNeverConnected > 0) {
+ HTMLNode peerStatsNeverConnectedListItem =
peerStatsList.addChild("li").addChild("span");
+
peerStatsNeverConnectedListItem.addChild("span", new String[] { "class",
"title", "style" }, new String[] { "peer_never_connected",
l10n("neverConnected"), "border-bottom: 1px dotted; cursor: help;" },
l10n("neverConnectedShort"));
+
peerStatsNeverConnectedListItem.addChild("span", ":\u00a0" +
numberOfNeverConnected);
+ }
+ if (numberOfDisabled > 0) {
+ HTMLNode peerStatsDisabledListItem =
peerStatsList.addChild("li").addChild("span");
+ peerStatsDisabledListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_disabled",
l10n("disabled"), "border-bottom: 1px dotted; cursor: help;" },
l10n("disabledShort"));
+ peerStatsDisabledListItem.addChild("span",
":\u00a0" + numberOfDisabled);
+ }
+ if (numberOfBursting > 0) {
+ HTMLNode peerStatsBurstingListItem =
peerStatsList.addChild("li").addChild("span");
+ peerStatsBurstingListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_bursting",
l10n("bursting"), "border-bottom: 1px dotted; cursor: help;" },
l10n("burstingShort"));
+ peerStatsBurstingListItem.addChild("span",
":\u00a0" + numberOfBursting);
+ }
+ if (numberOfListening > 0) {
+ HTMLNode peerStatsListeningListItem =
peerStatsList.addChild("li").addChild("span");
+ peerStatsListeningListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_listening",
l10n("listening"), "border-bottom: 1px dotted; cursor: help;" },
l10n("listeningShort"));
+ peerStatsListeningListItem.addChild("span",
":\u00a0" + numberOfListening);
+ }
+ if (numberOfListenOnly > 0) {
+ HTMLNode peerStatsListenOnlyListItem =
peerStatsList.addChild("li").addChild("span");
+ peerStatsListenOnlyListItem.addChild("span",
new String[] { "class", "title", "style" }, new String[] { "peer_listen_only",
l10n("listenOnly"), "border-bottom: 1px dotted; cursor: help;" },
l10n("listenOnlyShort"));
+ peerStatsListenOnlyListItem.addChild("span",
":\u00a0" + numberOfListenOnly);
+ }
+ if (numberOfClockProblem > 0) {
+ HTMLNode peerStatsListenOnlyListItem =
peerStatsList.addChild("li").addChild("span");
+ peerStatsListenOnlyListItem.addChild("span",
new String[] { "class", "title", "style" }, new String[] {
"peer_clock_problem", l10n("clockProblem"), "border-bottom: 1px dotted; cursor:
help;" }, l10n("clockProblemShort"));
+ peerStatsListenOnlyListItem.addChild("span",
":\u00a0" + numberOfClockProblem);
+ }
+ if (numberOfConnError > 0) {
+ HTMLNode peerStatsListenOnlyListItem =
peerStatsList.addChild("li").addChild("span");
+ peerStatsListenOnlyListItem.addChild("span",
new String[] { "class", "title", "style" }, new String[] {
"peer_clock_problem", l10n("connError"), "border-bottom: 1px dotted; cursor:
help;" }, l10n("connErrorShort"));
+ peerStatsListenOnlyListItem.addChild("span",
":\u00a0" + numberOfConnError);
+ }
+
+ // Peer routing backoff reason box
+ if(advancedModeEnabled) {
+ nextTableCell = overviewTableRow.addChild("td",
"class", "last");
+ HTMLNode backoffReasonInfobox =
nextTableCell.addChild("div", "class", "infobox");
+ backoffReasonInfobox.addChild("div", "class",
"infobox-header", "Peer backoff reasons");
+ HTMLNode backoffReasonContent =
backoffReasonInfobox.addChild("div", "class", "infobox-content");
+ String [] routingBackoffReasons =
peers.getPeerNodeRoutingBackoffReasons();
+ if(routingBackoffReasons.length == 0) {
+ backoffReasonContent.addChild("#",
"Good, your node is not backed off from any peers!");
+ } else {
+ HTMLNode reasonList =
backoffReasonContent.addChild("ul");
+ for(int
i=0;i<routingBackoffReasons.length;i++) {
+ int reasonCount =
peers.getPeerNodeRoutingBackoffReasonSize(routingBackoffReasons[i]);
+ if(reasonCount > 0) {
+
reasonList.addChild("li", routingBackoffReasons[i] + '\u00a0' + reasonCount);
+ }
+ }
+ }
+ }
+ // END OVERVIEW TABLE
+
+ boolean enablePeerActions = showPeerActionsBox();
+
+ // BEGIN PEER TABLE
+ if(fProxyJavascriptEnabled) {
+ StringBuffer jsBuf = new StringBuffer();
+ // FIXME: There's probably some icky Javascript
in here (this is the first thing that worked for me); feel free to fix up to
Javascript guru standards
+ jsBuf.append( " function peerNoteChange() {\n"
);
+ jsBuf.append( " var theobj =
document.getElementById( \"action\" );\n" );
+ jsBuf.append( " var length =
theobj.options.length;\n" );
+ jsBuf.append( " for (var i = 0; i < length;
i++) {\n" );
+ jsBuf.append( " if(theobj.options[i] ==
\"update_notes\") {\n" );
+ jsBuf.append( " theobj.options[i].select
= true;\n" );
+ jsBuf.append( " } else {\n" );
+ jsBuf.append( " theobj.options[i].select
= false;\n" );
+ jsBuf.append( " }\n" );
+ jsBuf.append( " }\n" );
+ jsBuf.append( "
theobj.value=\"update_notes\";\n" );
+ //jsBuf.append( " document.getElementById(
\"peersForm\" ).submit();\n" );
+ jsBuf.append( " document.getElementById(
\"peersForm\" ).doAction.click();\n" );
+ jsBuf.append( " }\n" );
+ jsBuf.append( " function peerNoteBlur() {\n" );
+ jsBuf.append( " var theobj =
document.getElementById( \"action\" );\n" );
+ jsBuf.append( " var length =
theobj.options.length;\n" );
+ jsBuf.append( " for (var i = 0; i < length;
i++) {\n" );
+ jsBuf.append( " if(theobj.options[i] ==
\"update_notes\") {\n" );
+ jsBuf.append( " theobj.options[i].select
= true;\n" );
+ jsBuf.append( " } else {\n" );
+ jsBuf.append( " theobj.options[i].select
= false;\n" );
+ jsBuf.append( " }\n" );
+ jsBuf.append( " }\n" );
+ jsBuf.append( "
theobj.value=\"update_notes\";\n" );
+ jsBuf.append( " }\n" );
+ contentNode.addChild("script", "type",
"text/javascript").addChild("%", jsBuf.toString());
+ }
+ HTMLNode peerTableInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
+ HTMLNode peerTableInfoboxHeader =
peerTableInfobox.addChild("div", "class", "infobox-header");
+ peerTableInfoboxHeader.addChild("#",
getPeerListTitle());
+ if (advancedModeEnabled) {
+ if (!path.endsWith("displaymessagetypes.html"))
{
+ peerTableInfoboxHeader.addChild("#", "
");
+ peerTableInfoboxHeader.addChild("a",
"href", "displaymessagetypes.html", "(more detailed)");
+ }
+ }
+ HTMLNode peerTableInfoboxContent =
peerTableInfobox.addChild("div", "class", "infobox-content");
+
+ if (peerNodeStatuses.length == 0) {
+
L10n.addL10nSubstitution(peerTableInfoboxContent,
"DarknetConnectionsToadlet.noPeersWithHomepageLink",
+ new String[] { "link", "/link"
}, new String[] { "<a href=\"/\">", "</a>" });
+ } else {
+ HTMLNode peerForm = null;
+ HTMLNode peerTable;
+ if(enablePeerActions) {
+ peerForm =
ctx.addFormChild(peerTableInfoboxContent, ".", "peersForm");
+ peerTable = peerForm.addChild("table",
"class", "darknet_connections");
+ } else {
+ peerTable =
peerTableInfoboxContent.addChild("table", "class", "darknet_connections");
+ }
+ HTMLNode peerTableHeaderRow =
peerTable.addChild("tr");
+ if(enablePeerActions)
+ peerTableHeaderRow.addChild("th");
+ peerTableHeaderRow.addChild("th").addChild("a",
"href", sortString(isReversed, "status")).addChild("#", l10n("statusTitle"));
+ if(hasNameColumn())
+
peerTableHeaderRow.addChild("th").addChild("a", "href", sortString(isReversed,
"name")).addChild("span", new String[] { "title", "style" }, new String[] {
l10n("nameClickToMessage"), "border-bottom: 1px dotted; cursor: help;" },
l10n("nameTitle"));
+ if (advancedModeEnabled) {
+
peerTableHeaderRow.addChild("th").addChild("a", "href", sortString(isReversed,
"address")).addChild("span", new String[] { "title", "style" }, new String[] {
l10n("ipAddress"), "border-bottom: 1px dotted; cursor: help;" },
l10n("ipAddressTitle"));
+ }
+ peerTableHeaderRow.addChild("th").addChild("a",
"href", sortString(isReversed, "version")).addChild("#", l10n("versionTitle"));
+ if (advancedModeEnabled) {
+
peerTableHeaderRow.addChild("th").addChild("a", "href", sortString(isReversed,
"location")).addChild("#", "Location");
+
peerTableHeaderRow.addChild("th").addChild("span", new String[] { "title",
"style" }, new String[] { "Other node busy? Display: Percentage of time the
node is overloaded, Current wait time remaining (0=not overloaded)/total/last
overload reason", "border-bottom: 1px dotted; cursor: help;" }, "Backoff");
+
+
peerTableHeaderRow.addChild("th").addChild("span", new String[] { "title",
"style" }, new String[] { "Probability of the node rejecting a request due to
overload or causing a timeout.", "border-bottom: 1px dotted; cursor: help;" },
"Overload Probability");
+ }
+
peerTableHeaderRow.addChild("th").addChild("span", new String[] { "title",
"style" }, new String[] { l10n("idleTime"), "border-bottom: 1px dotted; cursor:
help;" }, l10n("idleTimeTitle"));
+ if(hasPrivateNoteColumn())
+
peerTableHeaderRow.addChild("th").addChild("a", "href", sortString(isReversed,
"privnote")).addChild("span", new String[] { "title", "style" }, new String[] {
l10n("privateNote"), "border-bottom: 1px dotted; cursor: help;" },
l10n("privateNoteTitle"));
+
+ if(advancedModeEnabled) {
+ peerTableHeaderRow.addChild("th",
"%\u00a0Time Routable");
+ peerTableHeaderRow.addChild("th",
"Total\u00a0Traffic\u00a0(in/out)");
+ peerTableHeaderRow.addChild("th",
"Congestion\u00a0Control");
+ peerTableHeaderRow.addChild("th",
"Time\u00a0Delta");
+ }
+
+ for (int peerIndex = 0, peerCount =
peerNodeStatuses.length; peerIndex < peerCount; peerIndex++) {
+
+ PeerNodeStatus peerNodeStatus =
peerNodeStatuses[peerIndex];
+ drawRow(peerTable, peerNodeStatus,
advancedModeEnabled, fProxyJavascriptEnabled, now, path, enablePeerActions);
+
+ }
+
+ if(peerForm != null) {
+ drawPeerActionSelectBox(peerForm,
advancedModeEnabled);
+ }
+ }
+ // END PEER TABLE
+ }
+
+ drawAddPeerBox(contentNode, ctx);
+
+ // our reference
+ if(shouldDrawNoderefBox(advancedModeEnabled))
+ drawNoderefBox(contentNode, ctx);
+
+ // our ports
+ HTMLNode portInfobox = contentNode.addChild("div", "class",
"infobox infobox-normal");
+ portInfobox.addChild("div", "class", "infobox-header",
l10n("nodePortsTitle"));
+ HTMLNode portInfoboxContent = portInfobox.addChild("div",
"class", "infobox-content");
+ HTMLNode portInfoList = portInfoboxContent.addChild("ul");
+ SimpleFieldSet fproxyConfig =
node.config.get("fproxy").exportFieldSet(true);
+ SimpleFieldSet fcpConfig =
node.config.get("fcp").exportFieldSet(true);
+ SimpleFieldSet tmciConfig =
node.config.get("console").exportFieldSet(true);
+ portInfoList.addChild("li",
L10n.getString("DarknetConnectionsToadlet.darknetFnpPort", new String[] {
"port" }, new String[] { Integer.toString(node.getFNPPort()) }));
+ int opennetPort = node.getOpennetFNPPort();
+ if(opennetPort > 0)
+ portInfoList.addChild("li",
L10n.getString("DarknetConnectionsToadlet.opennetFnpPort", new String[] {
"port" }, new String[] { Integer.toString(opennetPort) }));
+ try {
+ if(fproxyConfig.getBoolean("enabled", false)) {
+ portInfoList.addChild("li",
L10n.getString("DarknetConnectionsToadlet.fproxyPort", new String[] { "port" },
new String[] { Integer.toString(fproxyConfig.getInt("port")) }));
+ } else {
+ portInfoList.addChild("li",
l10n("fproxyDisabled"));
+ }
+ if(fcpConfig.getBoolean("enabled", false)) {
+ portInfoList.addChild("li",
L10n.getString("DarknetConnectionsToadlet.fcpPort", new String[] { "port" },
new String[] { Integer.toString(fcpConfig.getInt("port")) }));
+ } else {
+ portInfoList.addChild("li",
l10n("fcpDisabled"));
+ }
+ if(tmciConfig.getBoolean("enabled", false)) {
+ portInfoList.addChild("li",
L10n.getString("DarknetConnectionsToadlet.tmciPort", new String[] { "port" },
new String[] { Integer.toString(tmciConfig.getInt("port")) }));
+ } else {
+ portInfoList.addChild("li",
l10n("tmciDisabled"));
+ }
+ } catch (FSParseException e) {
+ // ignore
+ }
+
+ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
+ }
+
+ protected abstract boolean acceptRefPosts();
+
+ /** Where to redirect to if there is an error */
+ protected abstract String defaultRedirectLocation();
+
+ public void handlePost(URI uri, final HTTPRequest request,
ToadletContext ctx) throws ToadletContextClosedException, IOException,
RedirectException {
+ boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
+
+ if(!acceptRefPosts()) {
+ super.sendErrorPage(ctx, 403, "Unauthorized",
L10n.getString("Toadlet.unauthorized"));
+ return;
+ }
+
+ if(!ctx.isAllowedFullAccess()) {
+ super.sendErrorPage(ctx, 403, "Unauthorized",
L10n.getString("Toadlet.unauthorized"));
+ return;
+ }
+
+ String pass = request.getPartAsString("formPassword", 32);
+ if((pass == null) || !pass.equals(core.formPassword)) {
+ MultiValueTable headers = new MultiValueTable();
+ headers.put("Location", defaultRedirectLocation());
+ ctx.sendReplyHeaders(302, "Found", headers, null, 0);
+ if(logMINOR) Logger.minor(this, "No password ("+pass+"
should be "+core.formPassword+ ')');
+ return;
+ }
+
+ if (request.isPartSet("add")) {
+ // add a new node
+ String urltext = request.getPartAsString("url", 100);
+ urltext = urltext.trim();
+ String reftext = request.getPartAsString("ref", 2000);
+ reftext = reftext.trim();
+ if (reftext.length() < 200) {
+ reftext = request.getPartAsString("reffile",
2000);
+ reftext = reftext.trim();
+ }
+ String privateComment = null;
+ if(!isOpennet())
+ privateComment =
request.getPartAsString("peerPrivateNote", 250).trim();
+
+ StringBuffer ref = new StringBuffer(1024);
+ if (urltext.length() > 0) {
+ // fetch reference from a URL
+ BufferedReader in = null;
+ try {
+ URL url = new URL(urltext);
+ URLConnection uc = url.openConnection();
+ // FIXME get charset encoding from
uc.getContentType()
+ in = new BufferedReader(new
InputStreamReader(uc.getInputStream()));
+ String line;
+ while ( (line = in.readLine()) != null)
{
+ ref.append( line ).append('\n');
+ }
+ } catch (IOException e) {
+ this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"),
L10n.getString("DarknetConnectionsToadlet.cantFetchNoderefURL", new String[] {
"url" }, new String[] { urltext }));
+ return;
+ } finally {
+ if( in != null ){
+ in.close();
+ }
+ }
+ } else if (reftext.length() > 0) {
+ // read from post data or file upload
+ // this slightly scary looking regexp chops any
extra characters off the beginning or ends of lines and removes extra line
breaks
+ ref = new
StringBuffer(reftext.replaceAll(".*?((?:[\\w,\\.]+\\=[^\r\n]+?)|(?:End))[
\\t]*(?:\\r?\\n)+", "$1\n"));
+ } else {
+ this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"), l10n("noRefOrURL"));
+ request.freeParts();
+ return;
+ }
+ ref = new StringBuffer(ref.toString().trim());
+
+ request.freeParts();
+ // we have a node reference in ref
+ SimpleFieldSet fs;
+
+ try {
+ fs = new SimpleFieldSet(ref.toString(), false,
true);
+ if(!fs.getEndMarker().endsWith("End")) {
+ sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"),
+
L10n.getString("DarknetConnectionsToadlet.cantParseWrongEnding", new String[] {
"end" }, new String[] { fs.getEndMarker() }));
+ return;
+ }
+ fs.setEndMarker("End"); // It's always End ;
the regex above doesn't always grok this
+ } catch (IOException e) {
+ this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"),
+
L10n.getString("DarknetConnectionsToadlet.cantParseTryAgain", new String[] {
"error" }, new String[] { e.toString() }));
+ return;
+ } catch (Throwable t) {
+ this.sendErrorPage(ctx,
l10n("failedToAddNodeInternalErrorTitle"),
l10n("failedToAddNodeInternalError"), t);
+ return;
+ }
+ PeerNode pn;
+ try {
+ if(isOpennet()) {
+ pn = node.createNewOpennetNode(fs);
+ } else {
+ pn = node.createNewDarknetNode(fs);
+
((DarknetPeerNode)pn).setPrivateDarknetCommentNote(privateComment);
+ }
+ } catch (FSParseException e1) {
+ this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"),
+
L10n.getString("DarknetConnectionsToadlet.cantParseTryAgain", new String[] {
"error" }, new String[] { e1.toString() }));
+ return;
+ } catch (PeerParseException e1) {
+ this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"),
+
L10n.getString("DarknetConnectionsToadlet.cantParseTryAgain", new String[] {
"error" }, new String[] { e1.toString() }));
+ return;
+ } catch (ReferenceSignatureVerificationException e1){
+ HTMLNode node = new HTMLNode("div");
+ node.addChild("#",
L10n.getString("DarknetConnectionsToadlet.invalidSignature", new String[] {
"error" }, new String[] { e1.toString() }));
+ node.addChild("br");
+ this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"), node);
+ return;
+ } catch (Throwable t) {
+ this.sendErrorPage(ctx,
l10n("failedToAddNodeInternalErrorTitle"),
l10n("failedToAddNodeInternalError"), t);
+ return;
+ }
+ if(Arrays.equals(pn.getIdentity(),
node.getDarknetIdentity())) {
+ this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"), l10n("triedToAddSelf"));
+ return;
+ }
+ if(!this.node.addPeerConnection(pn)) {
+ this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"), l10n("alreadyInReferences"));
+ return;
+ }
+
+ MultiValueTable headers = new MultiValueTable();
+ headers.put("Location", defaultRedirectLocation());
+ ctx.sendReplyHeaders(302, "Found", headers, null, 0);
+ return;
+ } else handleAltPost(uri, request, ctx, logMINOR);
+
+
+ }
+
+ /** Adding a darknet node or an opennet node? */
+ protected abstract boolean isOpennet();
+
+ /**
+ * Rest of handlePost() method - supplied by subclass.
+ * @throws IOException
+ * @throws ToadletContextClosedException
+ * @throws RedirectException
+ */
+ protected void handleAltPost(URI uri, HTTPRequest request,
ToadletContext ctx, boolean logMINOR) throws ToadletContextClosedException,
IOException, RedirectException {
+ // Do nothing - we only support adding nodes
+ handleGet(uri, new HTTPRequestImpl(uri), ctx);
+ }
+
+ /**
+ * What should the heading (before "(more detailed)") be on the peers
table?
+ */
+ protected abstract String getPeerListTitle();
+
+ /** Should there be a checkbox for each peer, and
drawPeerActionSelectBox() be called directly
+ * after drawing the peers list? */
+ protected abstract boolean showPeerActionsBox();
+
+ /** If showPeerActionsBox() is true, this will be called directly after
drawing the peers table.
+ * A form has been added, and checkboxes added for each peer. This
function should draw the rest
+ * of the form - any additional controls and one or more submit buttons.
+ */
+ protected abstract void drawPeerActionSelectBox(HTMLNode peerForm,
boolean advancedModeEnabled);
+
+ protected abstract boolean shouldDrawNoderefBox(boolean
advancedModeEnabled);
+
+ private void drawNoderefBox(HTMLNode contentNode, ToadletContext ctx) {
+ HTMLNode referenceInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
+ HTMLNode headerReferenceInfobox =
referenceInfobox.addChild("div", "class", "infobox-header");
+ // FIXME better way to deal with this sort of thing???
+ L10n.addL10nSubstitution(headerReferenceInfobox,
"DarknetConnectionsToadlet.myReferenceHeader",
+ new String[] { "linkref", "/linkref",
"linktext", "/linktext" },
+ new String[] { "<a href=\"myref.fref\">",
"</a>", "<a href=\"myref.txt\">", "</a>" });
+ HTMLNode warningSentence =
headerReferenceInfobox.addChild("pre");
+ L10n.addL10nSubstitution(warningSentence,
"DarknetConnectionsToadlet.referenceCopyWarning",
+ new String[] { "bold", "/bold" },
+ new String[] { "<b>", "</b>" });
+ referenceInfobox.addChild("div", "class",
"infobox-content").addChild("pre", "id", "reference", getNoderef().toString() +
'\n');
+ }
+
+ protected abstract String getPageTitle(String titleCountString, String
myName);
+
+ /** Draw the add a peer box. This comes immediately after the main
peers table and before the noderef box.
+ * Implementors may skip it by not doing anything in this method. */
+ protected void drawAddPeerBox(HTMLNode contentNode, ToadletContext ctx)
{
+ // BEGIN PEER ADDITION BOX
+ HTMLNode peerAdditionInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
+ peerAdditionInfobox.addChild("div", "class", "infobox-header",
l10n("addPeerTitle"));
+ HTMLNode peerAdditionContent =
peerAdditionInfobox.addChild("div", "class", "infobox-content");
+ HTMLNode peerAdditionForm =
ctx.addFormChild(peerAdditionContent, ".", "addPeerForm");
+ peerAdditionForm.addChild("#", l10n("pasteReference"));
+ peerAdditionForm.addChild("br");
+ peerAdditionForm.addChild("textarea", new String[] { "id",
"name", "rows", "cols" }, new String[] { "reftext", "ref", "8", "74" });
+ peerAdditionForm.addChild("br");
+ peerAdditionForm.addChild("#", (l10n("urlReference") + ' '));
+ peerAdditionForm.addChild("input", new String[] { "id", "type",
"name" }, new String[] { "refurl", "text", "url" });
+ peerAdditionForm.addChild("br");
+ peerAdditionForm.addChild("#", (l10n("fileReference") + ' '));
+ peerAdditionForm.addChild("input", new String[] { "id", "type",
"name" }, new String[] { "reffile", "file", "reffile" });
+ peerAdditionForm.addChild("br");
+ if(!isOpennet())
+ peerAdditionForm.addChild("#",
(l10n("enterDescription") + ' '));
+ peerAdditionForm.addChild("input", new String[] { "id", "type",
"name", "size", "maxlength", "value" }, new String[] { "peerPrivateNote",
"text", "peerPrivateNote", "16", "250", "" });
+ peerAdditionForm.addChild("br");
+ peerAdditionForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "add", l10n("add") });
+ }
+
+ protected Comparator comparator(String sortBy, boolean reversed) {
+ return new ComparatorByStatus(sortBy, reversed);
+ }
+
+ abstract protected PeerNodeStatus[] getPeerNodeStatuses();
+
+ abstract protected SimpleFieldSet getNoderef();
+
+ private void drawRow(HTMLNode peerTable, PeerNodeStatus peerNodeStatus,
boolean advancedModeEnabled, boolean fProxyJavascriptEnabled, long now, String
path, boolean enablePeerActions) {
+ HTMLNode peerRow = peerTable.addChild("tr");
+
+ if(enablePeerActions) {
+ // check box column
+ peerRow.addChild("td", "class",
"peer-marker").addChild("input", new String[] { "type", "name" }, new String[]
{ "checkbox", "node_" + peerNodeStatus.hashCode() });
+ }
+
+ // status column
+ String statusString = peerNodeStatus.getStatusName();
+ if (!advancedModeEnabled && (peerNodeStatus.getStatusValue() ==
PeerManager.PEER_NODE_STATUS_ROUTING_BACKED_OFF)) {
+ statusString = "BUSY";
+ }
+ peerRow.addChild("td", "class", "peer-status").addChild("span",
"class", peerNodeStatus.getStatusCSSName(), statusString +
(peerNodeStatus.isFetchingARK() ? "*" : ""));
+
+ drawNameColumn(peerRow, peerNodeStatus);
+
+ // address column
+ if (advancedModeEnabled) {
+ String pingTime = "";
+ if (peerNodeStatus.isConnected()) {
+ pingTime = " (" + (int)
peerNodeStatus.getAveragePingTime() + "ms)";
+ }
+ peerRow.addChild("td", "class",
"peer-address").addChild("#", ((peerNodeStatus.getPeerAddress() != null) ?
(peerNodeStatus.getPeerAddress() + ':' + peerNodeStatus.getPeerPort()) :
(l10n("unknownAddress"))) + pingTime);
+ }
+
+ // version column
+ if (peerNodeStatus.getStatusValue() !=
PeerManager.PEER_NODE_STATUS_NEVER_CONNECTED &&
(peerNodeStatus.isPublicInvalidVersion() ||
peerNodeStatus.isPublicReverseInvalidVersion())) { // Don't draw attention to
a version problem if NEVER CONNECTED
+ peerRow.addChild("td", "class",
"peer-version").addChild("span", "class", "peer_version_problem",
peerNodeStatus.getSimpleVersion());
+ } else {
+ peerRow.addChild("td", "class",
"peer-version").addChild("#", peerNodeStatus.getSimpleVersion());
+ }
+
+ // location column
+ if (advancedModeEnabled) {
+ peerRow.addChild("td", "class", "peer-location",
String.valueOf(peerNodeStatus.getLocation()));
+ }
+
+ if (advancedModeEnabled) {
+ // backoff column
+ HTMLNode backoffCell = peerRow.addChild("td", "class",
"peer-backoff");
+ backoffCell.addChild("#",
fix1.format(peerNodeStatus.getBackedOffPercent()));
+ int backoff = (int)
(Math.max(peerNodeStatus.getRoutingBackedOffUntil() - now, 0));
+ // Don't list the backoff as zero before it's actually
zero
+ if ((backoff > 0) && (backoff < 1000)) {
+ backoff = 1000;
+ }
+ backoffCell.addChild("#", ' ' + String.valueOf(backoff
/ 1000) + '/' + String.valueOf(peerNodeStatus.getRoutingBackoffLength() /
1000));
+ backoffCell.addChild("#",
(peerNodeStatus.getLastBackoffReason() == null) ? "" : ('/' +
(peerNodeStatus.getLastBackoffReason())));
+
+ // overload probability column
+ HTMLNode pRejectCell = peerRow.addChild("td", "class",
"peer-backoff"); // FIXME
+ pRejectCell.addChild("#",
fix1.format(peerNodeStatus.getPReject()));
+ }
+
+ // idle column
+ long idle = peerNodeStatus.getTimeLastRoutable();
+ if (peerNodeStatus.isRoutable()) {
+ idle = peerNodeStatus.getTimeLastConnectionCompleted();
+ } else if (peerNodeStatus.getStatusValue() ==
PeerManager.PEER_NODE_STATUS_NEVER_CONNECTED) {
+ idle = peerNodeStatus.getPeerAddedTime();
+ }
+ if(!peerNodeStatus.isConnected() && (now - idle) > (2 * 7 * 24
* 60 * 60 * (long) 1000)) { // 2 weeks
+ peerRow.addChild("td", "class",
"peer-idle").addChild("span", "class", "peer_idle_old", idleToString(now,
idle));
+ } else {
+ peerRow.addChild("td", "class", "peer-idle",
idleToString(now, idle));
+ }
+
+ if(hasPrivateNoteColumn())
+ drawPrivateNoteColumn(peerRow, peerNodeStatus,
fProxyJavascriptEnabled);
+
+ if(advancedModeEnabled) {
+ // percent of time connected column
+ peerRow.addChild("td", "class", "peer-idle" /* FIXME
*/).addChild("#",
fix1.format(peerNodeStatus.getPercentTimeRoutableConnection()));
+ // total traffic column
+ peerRow.addChild("td", "class", "peer-idle" /* FIXME
*/).addChild("#", SizeUtil.formatSize(peerNodeStatus.getTotalInputBytes())+" /
"+SizeUtil.formatSize(peerNodeStatus.getTotalOutputBytes()));
+ // congestion control
+ PacketThrottle t = peerNodeStatus.getThrottle();
+ String val;
+ if(t == null)
+ val = "none";
+ else
+ val = (int)((1000.0 / t.getDelay()) *
1024.0)+"B/sec delay "+
+ t.getDelay()+"ms (RTT
"+t.getRoundTripTime()+"ms window "+t.getWindowSize();
+ peerRow.addChild("td", "class", "peer-idle" /* FIXME
*/).addChild("#", val);
+ // time delta
+ peerRow.addChild("td", "class", "peer-idle" /* FIXME
*/).addChild("#", TimeUtil.formatTime(peerNodeStatus.getClockDelta()));
+ }
+
+ if (path.endsWith("displaymessagetypes.html")) {
+ drawMessageTypes(peerTable, peerNodeStatus);
+ }
+ }
+
+ /** Is there a name column? */
+ abstract protected boolean hasNameColumn();
+
+ /**
+ * Draw the name column, if there is one. This will be directly after
the status column.
+ */
+ abstract protected void drawNameColumn(HTMLNode peerRow, PeerNodeStatus
peerNodeStatus);
+
+ /**
+ * Is there a private note column?
+ */
+ abstract protected boolean hasPrivateNoteColumn();
+
+ /**
+ * Draw the private note column.
+ */
+ abstract protected void drawPrivateNoteColumn(HTMLNode peerRow,
PeerNodeStatus peerNodeStatus, boolean fProxyJavascriptEnabled);
+
+ private void drawMessageTypes(HTMLNode peerTable, PeerNodeStatus
peerNodeStatus) {
+ HTMLNode messageCountRow = peerTable.addChild("tr", "class",
"message-status");
+ messageCountRow.addChild("td", "colspan", "2");
+ HTMLNode messageCountCell = messageCountRow.addChild("td",
"colspan", "9"); // = total table row width - 2 from above colspan
+ HTMLNode messageCountTable = messageCountCell.addChild("table",
"class", "message-count");
+ HTMLNode countHeaderRow = messageCountTable.addChild("tr");
+ countHeaderRow.addChild("th", "Message");
+ countHeaderRow.addChild("th", "Incoming");
+ countHeaderRow.addChild("th", "Outgoing");
+ List messageNames = new ArrayList();
+ Map messageCounts = new HashMap();
+ for (Iterator incomingMessages =
peerNodeStatus.getLocalMessagesReceived().keySet().iterator();
incomingMessages.hasNext(); ) {
+ String messageName = (String) incomingMessages.next();
+ messageNames.add(messageName);
+ Long messageCount = (Long)
peerNodeStatus.getLocalMessagesReceived().get(messageName);
+ messageCounts.put(messageName, new Long[] {
messageCount, new Long(0) });
+ }
+ for (Iterator outgoingMessages =
peerNodeStatus.getLocalMessagesSent().keySet().iterator();
outgoingMessages.hasNext(); ) {
+ String messageName = (String) outgoingMessages.next();
+ if (!messageNames.contains(messageName)) {
+ messageNames.add(messageName);
+ }
+ Long messageCount = (Long)
peerNodeStatus.getLocalMessagesSent().get(messageName);
+ Long[] existingCounts = (Long[])
messageCounts.get(messageName);
+ if (existingCounts == null) {
+ messageCounts.put(messageName, new Long[] { new
Long(0), messageCount });
+ } else {
+ existingCounts[1] = messageCount;
+ }
+ }
+ Collections.sort(messageNames, new Comparator() {
+ public int compare(Object first, Object second) {
+ return ((String)
first).compareToIgnoreCase((String) second);
+ }
+ });
+ for (Iterator messageNamesIterator = messageNames.iterator();
messageNamesIterator.hasNext(); ) {
+ String messageName = (String)
messageNamesIterator.next();
+ Long[] messageCount = (Long[])
messageCounts.get(messageName);
+ HTMLNode messageRow = messageCountTable.addChild("tr");
+ messageRow.addChild("td", messageName);
+ messageRow.addChild("td", "class", "right-align",
String.valueOf(messageCount[0]));
+ messageRow.addChild("td", "class", "right-align",
String.valueOf(messageCount[1]));
+ }
+ }
+
+ private String idleToString(long now, long idle) {
+ if (idle <= 0) {
+ return " ";
+ }
+ long idleMilliseconds = now - idle;
+ return TimeUtil.formatTime(idleMilliseconds);
+ }
+
+ private static String l10n(String string) {
+ return L10n.getString("DarknetConnectionsToadlet."+string);
+ }
+
+ private static String l10nStats(String string) {
+ return L10n.getString("StatisticsToadlet."+string);
+ }
+
+ private String sortString(boolean isReversed, String type) {
+ return (isReversed ? ("?sortBy="+type) :
("?sortBy="+type+"&reversed"));
+ }
+
+
+}
Modified:
branches/freenet-jfk/src/freenet/clients/http/DarknetConnectionsToadlet.java
===================================================================
---
branches/freenet-jfk/src/freenet/clients/http/DarknetConnectionsToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/clients/http/DarknetConnectionsToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,735 +1,156 @@
package freenet.clients.http;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.StringWriter;
import java.net.URI;
-import java.net.URL;
-import java.net.URLConnection;
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
import freenet.client.HighLevelSimpleClient;
-import freenet.io.comm.PeerParseException;
-import freenet.io.comm.ReferenceSignatureVerificationException;
-import freenet.io.xfer.PacketThrottle;
import freenet.l10n.L10n;
-import freenet.node.FSParseException;
+import freenet.node.DarknetPeerNode;
+import freenet.node.DarknetPeerNodeStatus;
import freenet.node.Node;
import freenet.node.NodeClientCore;
-import freenet.node.NodeStats;
import freenet.node.PeerManager;
-import freenet.node.PeerNode;
import freenet.node.PeerNodeStatus;
-import freenet.node.Version;
import freenet.support.HTMLNode;
import freenet.support.Logger;
import freenet.support.MultiValueTable;
import freenet.support.SimpleFieldSet;
-import freenet.support.SizeUtil;
-import freenet.support.TimeUtil;
import freenet.support.api.HTTPRequest;
-public class DarknetConnectionsToadlet extends Toadlet {
+public class DarknetConnectionsToadlet extends ConnectionsToadlet {
- private final Node node;
- private final NodeClientCore core;
- private final NodeStats stats;
- private final PeerManager peers;
- private boolean isReversed = false;
-
- protected DarknetConnectionsToadlet(Node n, NodeClientCore core,
HighLevelSimpleClient client) {
- super(client);
- this.node = n;
- this.core = core;
- this.stats = n.nodeStats;
- this.peers = n.peers;
+ DarknetConnectionsToadlet(Node n, NodeClientCore core,
HighLevelSimpleClient client) {
+ super(n, core, client);
}
-
+
public String supportedMethods() {
return "GET, POST";
}
- public void handleGet(URI uri, final HTTPRequest request,
ToadletContext ctx) throws ToadletContextClosedException, IOException,
RedirectException {
- String path = uri.getPath();
- if(path.endsWith("myref.fref")) {
- SimpleFieldSet fs = node.exportPublicFieldSet();
- StringWriter sw = new StringWriter();
- fs.writeTo(sw);
- MultiValueTable extraHeaders = new MultiValueTable();
- // Force download to disk
- extraHeaders.put("Content-Disposition", "attachment;
filename=myref.fref");
- this.writeReply(ctx, 200,
"application/x-freenet-reference", "OK", extraHeaders, sw.toString());
- return;
- }
+ private static String l10n(String string) {
+ return L10n.getString("DarknetConnectionsToadlet."+string);
+ }
+
+ protected class DarknetComparator extends ComparatorByStatus {
- if(path.endsWith("myref.txt")) {
- SimpleFieldSet fs = node.exportPublicFieldSet();
- StringWriter sw = new StringWriter();
- fs.writeTo(sw);
- this.writeReply(ctx, 200, "text/plain", "OK",
sw.toString());
- return;
+ DarknetComparator(String sortBy, boolean reversed) {
+ super(sortBy, reversed);
}
+
+ protected int customCompare(PeerNodeStatus firstNode,
PeerNodeStatus secondNode, String sortBy) {
+ if(sortBy.equals("name")) {
+ return
((DarknetPeerNodeStatus)firstNode).getName().compareToIgnoreCase(((DarknetPeerNodeStatus)secondNode).getName());
+ }else if(sortBy.equals("privnote")){
+ return
((DarknetPeerNodeStatus)firstNode).getPrivateDarknetCommentNote().compareToIgnoreCase(((DarknetPeerNodeStatus)secondNode).getPrivateDarknetCommentNote());
+ } else
+ return super.customCompare(firstNode,
secondNode, sortBy);
+ }
- if(!ctx.isAllowedFullAccess()) {
- super.sendErrorPage(ctx, 403, "Unauthorized",
L10n.getString("Toadlet.unauthorized"));
- return;
+ /** Default comparison, after taking into account status */
+ protected int lastResortCompare(PeerNodeStatus firstNode,
PeerNodeStatus secondNode) {
+ return
((DarknetPeerNodeStatus)firstNode).getName().compareToIgnoreCase(((DarknetPeerNodeStatus)secondNode).getName());
}
+
+ }
+
+ protected Comparator comparator(String sortBy, boolean reversed) {
+ return new DarknetComparator(sortBy, reversed);
+ }
- final boolean advancedModeEnabled =
node.isAdvancedModeEnabled();
- final boolean fProxyJavascriptEnabled =
node.isFProxyJavascriptEnabled();
-
- /* gather connection statistics */
- PeerNodeStatus[] peerNodeStatuses = peers.getPeerNodeStatuses();
- Arrays.sort(peerNodeStatuses, new Comparator() {
- public int compare(Object first, Object second) {
- int result = 0;
- boolean isSet = true;
- PeerNodeStatus firstNode = (PeerNodeStatus)
first;
- PeerNodeStatus secondNode = (PeerNodeStatus)
second;
-
- if(request.isParameterSet("sortBy")){
- final String sortBy =
request.getParam("sortBy");
+ protected boolean hasNameColumn() {
+ return true;
+ }
+
+ protected void drawNameColumn(HTMLNode peerRow, PeerNodeStatus
peerNodeStatus) {
+ // name column
+ peerRow.addChild("td", "class", "peer-name").addChild("a",
"href", "/send_n2ntm/?peernode_hashcode=" + peerNodeStatus.hashCode(),
((DarknetPeerNodeStatus)peerNodeStatus).getName());
+ }
- if(sortBy.equals("name")){
- result =
firstNode.getName().compareToIgnoreCase(secondNode.getName());
- }else if(sortBy.equals("address")){
- result =
firstNode.getPeerAddress().compareToIgnoreCase(secondNode.getPeerAddress());
- }else if(sortBy.equals("location")){
- result =
(firstNode.getLocation() - secondNode.getLocation()) < 0 ? -1 : 1; // Shouldn't
be equal anyway
- }else if(sortBy.equals("version")){
- result =
Version.getArbitraryBuildNumber(firstNode.getVersion()) -
Version.getArbitraryBuildNumber(secondNode.getVersion());
- }else if(sortBy.equals("privnote")){
- result =
firstNode.getPrivateDarknetCommentNote().compareToIgnoreCase(secondNode.getPrivateDarknetCommentNote());
- }else
- isSet=false;
- }else
- isSet=false;
-
- if(!isSet){
- int statusDifference =
firstNode.getStatusValue() - secondNode.getStatusValue();
- if (statusDifference != 0)
- result = (statusDifference < 0
? -1 : 1);
- else
- result =
firstNode.getName().compareToIgnoreCase(secondNode.getName());
- }
+ protected boolean hasPrivateNoteColumn() {
+ return true;
+ }
- if(result == 0){
- return 0;
- }else if(request.isParameterSet("reversed")){
- isReversed = true;
- return result > 0 ? -1 : 1;
- }else{
- isReversed = false;
- return result < 0 ? -1 : 1;
- }
- }
- });
-
- int numberOfConnected =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_CONNECTED);
- int numberOfRoutingBackedOff =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_ROUTING_BACKED_OFF);
- int numberOfTooNew =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_TOO_NEW);
- int numberOfTooOld =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_TOO_OLD);
- int numberOfDisconnected =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_DISCONNECTED);
- int numberOfNeverConnected =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_NEVER_CONNECTED);
- int numberOfDisabled =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_DISABLED);
- int numberOfBursting =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_BURSTING);
- int numberOfListening =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_LISTENING);
- int numberOfListenOnly =
PeerNodeStatus.getPeerStatusCount(peerNodeStatuses,
PeerManager.PEER_NODE_STATUS_LISTEN_ONLY);
-
- int numberOfSimpleConnected = numberOfConnected +
numberOfRoutingBackedOff;
- int numberOfNotConnected = numberOfTooNew + numberOfTooOld +
numberOfDisconnected + numberOfNeverConnected + numberOfDisabled +
numberOfBursting + numberOfListening + numberOfListenOnly;
- String titleCountString = null;
- if(advancedModeEnabled) {
- titleCountString = "(" + numberOfConnected + '/' +
numberOfRoutingBackedOff + '/' + numberOfTooNew + '/' + numberOfTooOld + '/' +
numberOfNotConnected + ')';
+ protected void drawPrivateNoteColumn(HTMLNode peerRow, PeerNodeStatus
peerNodeStatus, boolean fProxyJavascriptEnabled) {
+ // private darknet node comment note column
+ DarknetPeerNodeStatus status = (DarknetPeerNodeStatus)
peerNodeStatus;
+ if(fProxyJavascriptEnabled) {
+ peerRow.addChild("td", "class",
"peer-private-darknet-comment-note").addChild("input", new String[] { "type",
"name", "size", "maxlength", "onBlur", "onChange", "value" }, new String[] {
"text", "peerPrivateNote_" + peerNodeStatus.hashCode(), "16", "250",
"peerNoteBlur();", "peerNoteChange();", status.getPrivateDarknetCommentNote()
});
} else {
- titleCountString = (numberOfNotConnected +
numberOfSimpleConnected)>0 ? String.valueOf(numberOfSimpleConnected) : "";
+ peerRow.addChild("td", "class",
"peer-private-darknet-comment-note").addChild("input", new String[] { "type",
"name", "size", "maxlength", "value" }, new String[] { "text",
"peerPrivateNote_" + peerNodeStatus.hashCode(), "16", "250",
status.getPrivateDarknetCommentNote() });
}
-
- HTMLNode pageNode =
ctx.getPageMaker().getPageNode(L10n.getString("DarknetConnectionsToadlet.fullTitle",
new String[] { "counts", "name" }, new String[] { titleCountString,
node.getMyName() } ), ctx);
- HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
-
- // FIXME! We need some nice images
- long now = System.currentTimeMillis();
-
- if(ctx.isAllowedFullAccess())
- contentNode.addChild(core.alerts.createSummary());
-
- if(peerNodeStatuses.length>0){
+ }
- /* node status values */
- long nodeUptimeSeconds = (now - node.startupTime) /
1000;
- int bwlimitDelayTime = (int)
stats.getBwlimitDelayTime();
- int nodeAveragePingTime = (int)
stats.getNodeAveragePingTime();
- int networkSizeEstimateSession =
stats.getNetworkSizeEstimate(-1);
- int networkSizeEstimateRecent = 0;
- if(nodeUptimeSeconds > (48*60*60)) { // 48 hours
- networkSizeEstimateRecent =
stats.getNetworkSizeEstimate(now - (48*60*60*1000)); // 48 hours
- }
- DecimalFormat fix4 = new DecimalFormat("0.0000");
- double routingMissDistance =
stats.routingMissDistance.currentValue();
- DecimalFormat fix1 = new DecimalFormat("##0.0%");
- double backedOffPercent =
stats.backedOffPercent.currentValue();
- String nodeUptimeString =
TimeUtil.formatTime(nodeUptimeSeconds * 1000); // *1000 to convert to
milliseconds
+ protected SimpleFieldSet getNoderef() {
+ return node.exportDarknetPublicFieldSet();
+ }
- // BEGIN OVERVIEW TABLE
- HTMLNode overviewTable = contentNode.addChild("table",
"class", "column");
- HTMLNode overviewTableRow =
overviewTable.addChild("tr");
- HTMLNode nextTableCell =
overviewTableRow.addChild("td", "class", "first");
+ protected PeerNodeStatus[] getPeerNodeStatuses() {
+ return node.peers.getDarknetPeerNodeStatuses();
+ }
- /* node status overview box */
- if(advancedModeEnabled) {
- HTMLNode overviewInfobox =
nextTableCell.addChild("div", "class", "infobox");
- overviewInfobox.addChild("div", "class",
"infobox-header", "Node status overview");
- HTMLNode overviewInfoboxContent =
overviewInfobox.addChild("div", "class", "infobox-content");
- HTMLNode overviewList =
overviewInfoboxContent.addChild("ul");
- overviewList.addChild("li",
"bwlimitDelayTime:\u00a0" + bwlimitDelayTime + "ms");
- overviewList.addChild("li",
"nodeAveragePingTime:\u00a0" + nodeAveragePingTime + "ms");
- overviewList.addChild("li",
"networkSizeEstimateSession:\u00a0" + networkSizeEstimateSession +
"\u00a0nodes");
- if(nodeUptimeSeconds > (48*60*60)) { // 48
hours
- overviewList.addChild("li",
"networkSizeEstimateRecent:\u00a0" + networkSizeEstimateRecent + "\u00a0nodes");
- }
- overviewList.addChild("li", "nodeUptime:\u00a0"
+ nodeUptimeString);
- overviewList.addChild("li",
"routingMissDistance:\u00a0" + fix4.format(routingMissDistance));
- overviewList.addChild("li",
"backedOffPercent:\u00a0" + fix1.format(backedOffPercent));
- overviewList.addChild("li",
"pInstantReject:\u00a0" + fix1.format(stats.pRejectIncomingInstantly()));
- nextTableCell = overviewTableRow.addChild("td");
- }
+ protected String getPageTitle(String titleCountString, String myName) {
+ return L10n.getString("DarknetConnectionsToadlet.fullTitle",
new String[] { "counts", "name" }, new String[] { titleCountString,
node.getMyName() } );
+ }
+
+ protected boolean shouldDrawNoderefBox(boolean advancedModeEnabled) {
+ return true;
+ }
- // Activity box
- int numARKFetchers = node.getNumARKFetchers();
+ protected boolean showPeerActionsBox() {
+ return true;
+ }
- HTMLNode activityInfobox =
nextTableCell.addChild("div", "class", "infobox");
- activityInfobox.addChild("div", "class",
"infobox-header", l10n("activityTitle"));
- HTMLNode activityInfoboxContent =
activityInfobox.addChild("div", "class", "infobox-content");
- HTMLNode activityList =
StatisticsToadlet.drawActivity(activityInfoboxContent, node);
- if (advancedModeEnabled && activityList != null) {
- if (numARKFetchers > 0) {
- activityList.addChild("li",
"ARK\u00a0Fetch\u00a0Requests:\u00a0" + numARKFetchers);
- }
- StatisticsToadlet.drawBandwidth(activityList,
node, nodeUptimeSeconds);
- }
-
- nextTableCell = advancedModeEnabled ?
overviewTableRow.addChild("td") : overviewTableRow.addChild("td", "class",
"last");
-
- // Peer statistics box
- HTMLNode peerStatsInfobox =
nextTableCell.addChild("div", "class", "infobox");
- peerStatsInfobox.addChild("div", "class",
"infobox-header", l10nStats("peerStatsTitle"));
- HTMLNode peerStatsContent =
peerStatsInfobox.addChild("div", "class", "infobox-content");
- HTMLNode peerStatsList =
peerStatsContent.addChild("ul");
- if (numberOfConnected > 0) {
- HTMLNode peerStatsConnectedListItem =
peerStatsList.addChild("li").addChild("span");
- peerStatsConnectedListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_connected",
l10n("connected"), "border-bottom: 1px dotted; cursor: help;" },
l10n("connectedShort"));
- peerStatsConnectedListItem.addChild("span",
":\u00a0" + numberOfConnected);
- }
- if (numberOfRoutingBackedOff > 0) {
- HTMLNode peerStatsRoutingBackedOffListItem =
peerStatsList.addChild("li").addChild("span");
-
peerStatsRoutingBackedOffListItem.addChild("span", new String[] { "class",
"title", "style" }, new String[] { "peer_backed_off", (advancedModeEnabled ?
l10n("backedOff") : l10n("busy")), "border-bottom: 1px dotted; cursor: help;"
}, advancedModeEnabled ? l10n("backedOffShort") : l10n("busyShort"));
-
peerStatsRoutingBackedOffListItem.addChild("span", ":\u00a0" +
numberOfRoutingBackedOff);
- }
- if (numberOfTooNew > 0) {
- HTMLNode peerStatsTooNewListItem =
peerStatsList.addChild("li").addChild("span");
- peerStatsTooNewListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_too_new",
l10n("tooNew"), "border-bottom: 1px dotted; cursor: help;" },
l10n("tooNewShort"));
- peerStatsTooNewListItem.addChild("span",
":\u00a0" + numberOfTooNew);
- }
- if (numberOfTooOld > 0) {
- HTMLNode peerStatsTooOldListItem =
peerStatsList.addChild("li").addChild("span");
- peerStatsTooOldListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_too_old",
l10n("tooOld"), "border-bottom: 1px dotted; cursor: help;" },
l10n("tooOldShort"));
- peerStatsTooOldListItem.addChild("span",
":\u00a0" + numberOfTooOld);
- }
- if (numberOfDisconnected > 0) {
- HTMLNode peerStatsDisconnectedListItem =
peerStatsList.addChild("li").addChild("span");
- peerStatsDisconnectedListItem.addChild("span",
new String[] { "class", "title", "style" }, new String[] { "peer_disconnected",
l10n("notConnected"), "border-bottom: 1px dotted; cursor: help;" },
l10n("notConnectedShort"));
- peerStatsDisconnectedListItem.addChild("span",
":\u00a0" + numberOfDisconnected);
- }
- if (numberOfNeverConnected > 0) {
- HTMLNode peerStatsNeverConnectedListItem =
peerStatsList.addChild("li").addChild("span");
-
peerStatsNeverConnectedListItem.addChild("span", new String[] { "class",
"title", "style" }, new String[] { "peer_never_connected",
l10n("neverConnected"), "border-bottom: 1px dotted; cursor: help;" },
l10n("neverConnectedShort"));
-
peerStatsNeverConnectedListItem.addChild("span", ":\u00a0" +
numberOfNeverConnected);
- }
- if (numberOfDisabled > 0) {
- HTMLNode peerStatsDisabledListItem =
peerStatsList.addChild("li").addChild("span");
- peerStatsDisabledListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_disabled",
l10n("disabled"), "border-bottom: 1px dotted; cursor: help;" },
l10n("disabledShort"));
- peerStatsDisabledListItem.addChild("span",
":\u00a0" + numberOfDisabled);
- }
- if (numberOfBursting > 0) {
- HTMLNode peerStatsBurstingListItem =
peerStatsList.addChild("li").addChild("span");
- peerStatsBurstingListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_bursting",
l10n("bursting"), "border-bottom: 1px dotted; cursor: help;" },
l10n("burstingShort"));
- peerStatsBurstingListItem.addChild("span",
":\u00a0" + numberOfBursting);
- }
- if (numberOfListening > 0) {
- HTMLNode peerStatsListeningListItem =
peerStatsList.addChild("li").addChild("span");
- peerStatsListeningListItem.addChild("span", new
String[] { "class", "title", "style" }, new String[] { "peer_listening",
l10n("listening"), "border-bottom: 1px dotted; cursor: help;" },
l10n("listeningShort"));
- peerStatsListeningListItem.addChild("span",
":\u00a0" + numberOfListening);
- }
- if (numberOfListenOnly > 0) {
- HTMLNode peerStatsListenOnlyListItem =
peerStatsList.addChild("li").addChild("span");
- peerStatsListenOnlyListItem.addChild("span",
new String[] { "class", "title", "style" }, new String[] { "peer_listen_only",
l10n("listenOnly"), "border-bottom: 1px dotted; cursor: help;" },
l10n("listenOnlyShort"));
- peerStatsListenOnlyListItem.addChild("span",
":\u00a0" + numberOfListenOnly);
- }
-
- // Peer routing backoff reason box
- if(advancedModeEnabled) {
- nextTableCell = overviewTableRow.addChild("td",
"class", "last");
- HTMLNode backoffReasonInfobox =
nextTableCell.addChild("div", "class", "infobox");
- backoffReasonInfobox.addChild("div", "class",
"infobox-header", "Peer backoff reasons");
- HTMLNode backoffReasonContent =
backoffReasonInfobox.addChild("div", "class", "infobox-content");
- String [] routingBackoffReasons =
peers.getPeerNodeRoutingBackoffReasons();
- if(routingBackoffReasons.length == 0) {
- backoffReasonContent.addChild("#",
"Good, your node is not backed off from any peers!");
- } else {
- HTMLNode reasonList =
backoffReasonContent.addChild("ul");
- for(int
i=0;i<routingBackoffReasons.length;i++) {
- int reasonCount =
peers.getPeerNodeRoutingBackoffReasonSize(routingBackoffReasons[i]);
- if(reasonCount > 0) {
-
reasonList.addChild("li", routingBackoffReasons[i] + '\u00a0' + reasonCount);
- }
- }
- }
- }
- // END OVERVIEW TABLE
-
- // BEGIN PEER TABLE
- if(fProxyJavascriptEnabled) {
- StringBuffer jsBuf = new StringBuffer();
- // FIXME: There's probably some icky Javascript
in here (this is the first thing that worked for me); feel free to fix up to
Javascript guru standards
- jsBuf.append( " function peerNoteChange() {\n"
);
- jsBuf.append( " var theobj =
document.getElementById( \"action\" );\n" );
- jsBuf.append( " var length =
theobj.options.length;\n" );
- jsBuf.append( " for (var i = 0; i < length;
i++) {\n" );
- jsBuf.append( " if(theobj.options[i] ==
\"update_notes\") {\n" );
- jsBuf.append( " theobj.options[i].select
= true;\n" );
- jsBuf.append( " } else {\n" );
- jsBuf.append( " theobj.options[i].select
= false;\n" );
- jsBuf.append( " }\n" );
- jsBuf.append( " }\n" );
- jsBuf.append( "
theobj.value=\"update_notes\";\n" );
- //jsBuf.append( " document.getElementById(
\"peersForm\" ).submit();\n" );
- jsBuf.append( " document.getElementById(
\"peersForm\" ).doAction.click();\n" );
- jsBuf.append( " }\n" );
- jsBuf.append( " function peerNoteBlur() {\n" );
- jsBuf.append( " var theobj =
document.getElementById( \"action\" );\n" );
- jsBuf.append( " var length =
theobj.options.length;\n" );
- jsBuf.append( " for (var i = 0; i < length;
i++) {\n" );
- jsBuf.append( " if(theobj.options[i] ==
\"update_notes\") {\n" );
- jsBuf.append( " theobj.options[i].select
= true;\n" );
- jsBuf.append( " } else {\n" );
- jsBuf.append( " theobj.options[i].select
= false;\n" );
- jsBuf.append( " }\n" );
- jsBuf.append( " }\n" );
- jsBuf.append( "
theobj.value=\"update_notes\";\n" );
- jsBuf.append( " }\n" );
- contentNode.addChild("script", "type",
"text/javascript").addChild("%", jsBuf.toString());
- }
- HTMLNode peerTableInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
- HTMLNode peerTableInfoboxHeader =
peerTableInfobox.addChild("div", "class", "infobox-header");
- peerTableInfoboxHeader.addChild("#", l10n("myFriends"));
- if (advancedModeEnabled) {
- if (!path.endsWith("displaymessagetypes.html"))
{
- peerTableInfoboxHeader.addChild("#", "
");
- peerTableInfoboxHeader.addChild("a",
"href", "displaymessagetypes.html", "(more detailed)");
- }
- }
- HTMLNode peerTableInfoboxContent =
peerTableInfobox.addChild("div", "class", "infobox-content");
-
- if (peerNodeStatuses.length == 0) {
-
L10n.addL10nSubstitution(peerTableInfoboxContent,
"DarknetConnectionsToadlet.noPeersWithHomepageLink",
- new String[] { "link", "/link"
}, new String[] { "<a href=\"/\">", "</a>" });
- } else {
- HTMLNode peerForm =
ctx.addFormChild(peerTableInfoboxContent, ".", "peersForm");
- HTMLNode peerTable = peerForm.addChild("table",
"class", "darknet_connections");
- HTMLNode peerTableHeaderRow =
peerTable.addChild("tr");
- peerTableHeaderRow.addChild("th");
- peerTableHeaderRow.addChild("th").addChild("a",
"href", sortString(isReversed, "status")).addChild("#", l10n("statusTitle"));
- peerTableHeaderRow.addChild("th").addChild("a",
"href", sortString(isReversed, "name")).addChild("span", new String[] {
"title", "style" }, new String[] { l10n("nameClickToMessage"), "border-bottom:
1px dotted; cursor: help;" }, l10n("nameTitle"));
- if (advancedModeEnabled) {
-
peerTableHeaderRow.addChild("th").addChild("a", "href", sortString(isReversed,
"address")).addChild("span", new String[] { "title", "style" }, new String[] {
l10n("ipAddress"), "border-bottom: 1px dotted; cursor: help;" },
l10n("ipAddressTitle"));
- }
- peerTableHeaderRow.addChild("th").addChild("a",
"href", sortString(isReversed, "version")).addChild("#", l10n("versionTitle"));
- if (advancedModeEnabled) {
-
peerTableHeaderRow.addChild("th").addChild("a", "href", sortString(isReversed,
"location")).addChild("#", "Location");
-
peerTableHeaderRow.addChild("th").addChild("span", new String[] { "title",
"style" }, new String[] { "Other node busy? Display: Percentage of time the
node is overloaded, Current wait time remaining (0=not overloaded)/total/last
overload reason", "border-bottom: 1px dotted; cursor: help;" }, "Backoff");
-
-
peerTableHeaderRow.addChild("th").addChild("span", new String[] { "title",
"style" }, new String[] { "Probability of the node rejecting a request due to
overload or causing a timeout.", "border-bottom: 1px dotted; cursor: help;" },
"Overload Probability");
- }
-
peerTableHeaderRow.addChild("th").addChild("span", new String[] { "title",
"style" }, new String[] { l10n("idleTime"), "border-bottom: 1px dotted; cursor:
help;" }, l10n("idleTimeTitle"));
- peerTableHeaderRow.addChild("th").addChild("a",
"href", sortString(isReversed, "privnote")).addChild("span", new String[] {
"title", "style" }, new String[] { l10n("privateNote"), "border-bottom: 1px
dotted; cursor: help;" }, l10n("privateNoteTitle"));
-
- if(advancedModeEnabled) {
- peerTableHeaderRow.addChild("th",
"%\u00a0Time Routable");
- peerTableHeaderRow.addChild("th",
"Total\u00a0Traffic\u00a0(in/out)");
- peerTableHeaderRow.addChild("th",
"Congestion\u00a0Control");
- }
-
- for (int peerIndex = 0, peerCount =
peerNodeStatuses.length; peerIndex < peerCount; peerIndex++) {
- PeerNodeStatus peerNodeStatus =
peerNodeStatuses[peerIndex];
- HTMLNode peerRow =
peerTable.addChild("tr");
-
- // check box column
- peerRow.addChild("td", "class",
"peer-marker").addChild("input", new String[] { "type", "name" }, new String[]
{ "checkbox", "node_" + peerNodeStatus.hashCode() });
-
- // status column
- String statusString =
peerNodeStatus.getStatusName();
- if (!advancedModeEnabled &&
(peerNodeStatus.getStatusValue() ==
PeerManager.PEER_NODE_STATUS_ROUTING_BACKED_OFF)) {
- statusString = "BUSY";
- }
- peerRow.addChild("td", "class",
"peer-status").addChild("span", "class", peerNodeStatus.getStatusCSSName(),
statusString + (peerNodeStatus.isFetchingARK() ? "*" : ""));
-
- // name column
- peerRow.addChild("td", "class",
"peer-name").addChild("a", "href", "/send_n2ntm/?peernode_hashcode=" +
peerNodeStatus.hashCode(), peerNodeStatus.getName());
-
- // address column
- if (advancedModeEnabled) {
- String pingTime = "";
- if
(peerNodeStatus.isConnected()) {
- pingTime = " (" + (int)
peerNodeStatus.getAveragePingTime() + "ms)";
- }
- peerRow.addChild("td", "class",
"peer-address").addChild("#", ((peerNodeStatus.getPeerAddress() != null) ?
(peerNodeStatus.getPeerAddress() + ':' + peerNodeStatus.getPeerPort()) :
(l10n("unknownAddress"))) + pingTime);
- }
-
- // version column
- if (peerNodeStatus.getStatusValue() !=
PeerManager.PEER_NODE_STATUS_NEVER_CONNECTED &&
(peerNodeStatus.isPublicInvalidVersion() ||
peerNodeStatus.isPublicReverseInvalidVersion())) { // Don't draw attention to
a version problem if NEVER CONNECTED
- peerRow.addChild("td", "class",
"peer-version").addChild("span", "class", "peer_version_problem",
peerNodeStatus.getSimpleVersion());
- } else {
- peerRow.addChild("td", "class",
"peer-version").addChild("#", peerNodeStatus.getSimpleVersion());
- }
-
- // location column
- if (advancedModeEnabled) {
- peerRow.addChild("td", "class",
"peer-location", String.valueOf(peerNodeStatus.getLocation()));
- }
-
- if (advancedModeEnabled) {
- // backoff column
- HTMLNode backoffCell =
peerRow.addChild("td", "class", "peer-backoff");
- backoffCell.addChild("#",
fix1.format(peerNodeStatus.getBackedOffPercent()));
- int backoff = (int)
(Math.max(peerNodeStatus.getRoutingBackedOffUntil() - now, 0));
- // Don't list the backoff as
zero before it's actually zero
- if ((backoff > 0) && (backoff <
1000)) {
- backoff = 1000;
- }
- backoffCell.addChild("#", ' ' +
String.valueOf(backoff / 1000) + '/' +
String.valueOf(peerNodeStatus.getRoutingBackoffLength() / 1000));
- backoffCell.addChild("#",
(peerNodeStatus.getLastBackoffReason() == null) ? "" : ('/' +
(peerNodeStatus.getLastBackoffReason())));
-
- // overload probability column
- HTMLNode pRejectCell =
peerRow.addChild("td", "class", "peer-backoff"); // FIXME
- pRejectCell.addChild("#",
fix1.format(peerNodeStatus.getPReject()));
- }
-
- // idle column
- long idle =
peerNodeStatus.getTimeLastRoutable();
- if (peerNodeStatus.isRoutable()) {
- idle =
peerNodeStatus.getTimeLastConnectionCompleted();
- } else if
(peerNodeStatus.getStatusValue() ==
PeerManager.PEER_NODE_STATUS_NEVER_CONNECTED) {
- idle =
peerNodeStatus.getPeerAddedTime();
- }
- if(!peerNodeStatus.isConnected() &&
(now - idle) > (2 * 7 * 24 * 60 * 60 * (long) 1000)) { // 2 weeks
- peerRow.addChild("td", "class",
"peer-idle").addChild("span", "class", "peer_idle_old", idleToString(now,
idle));
- } else {
- peerRow.addChild("td", "class",
"peer-idle", idleToString(now, idle));
- }
-
- // private darknet node comment note
column
- if(fProxyJavascriptEnabled) {
- peerRow.addChild("td", "class",
"peer-private-darknet-comment-note").addChild("input", new String[] { "type",
"name", "size", "maxlength", "onBlur", "onChange", "value" }, new String[] {
"text", "peerPrivateNote_" + peerNodeStatus.hashCode(), "16", "250",
"peerNoteBlur();", "peerNoteChange();",
peerNodeStatus.getPrivateDarknetCommentNote() });
- } else {
- peerRow.addChild("td", "class",
"peer-private-darknet-comment-note").addChild("input", new String[] { "type",
"name", "size", "maxlength", "value" }, new String[] { "text",
"peerPrivateNote_" + peerNodeStatus.hashCode(), "16", "250",
peerNodeStatus.getPrivateDarknetCommentNote() });
- }
-
- if(advancedModeEnabled) {
- // percent of time connected
column
- peerRow.addChild("td", "class",
"peer-idle" /* FIXME */).addChild("#",
fix1.format(peerNodeStatus.getPercentTimeRoutableConnection()));
- // total traffic column
- peerRow.addChild("td", "class",
"peer-idle" /* FIXME */).addChild("#",
SizeUtil.formatSize(peerNodeStatus.getTotalInputBytes())+" /
"+SizeUtil.formatSize(peerNodeStatus.getTotalOutputBytes()));
- // congestion control
- PacketThrottle t =
peerNodeStatus.getThrottle();
- String val;
- if(t == null)
- val = "none";
- else
- val = (int)((1000.0 /
t.getDelay()) * 1024.0)+"B/sec delay "+
-
t.getDelay()+"ms (RTT "+t.getRoundTripTime()+"ms window "+t.getWindowSize();
- peerRow.addChild("td", "class",
"peer-idle" /* FIXME */).addChild("#", val);
- }
-
- if
(path.endsWith("displaymessagetypes.html")) {
- HTMLNode messageCountRow =
peerTable.addChild("tr", "class", "message-status");
- messageCountRow.addChild("td",
"colspan", "2");
- HTMLNode messageCountCell =
messageCountRow.addChild("td", "colspan", String.valueOf(advancedModeEnabled ?
9 : 5)); // = total table row width - 2 from above colspan
- HTMLNode messageCountTable =
messageCountCell.addChild("table", "class", "message-count");
- HTMLNode countHeaderRow =
messageCountTable.addChild("tr");
- countHeaderRow.addChild("th",
"Message");
- countHeaderRow.addChild("th",
"Incoming");
- countHeaderRow.addChild("th",
"Outgoing");
- List messageNames = new
ArrayList();
- Map messageCounts = new
HashMap();
- for (Iterator incomingMessages
= peerNodeStatus.getLocalMessagesReceived().keySet().iterator();
incomingMessages.hasNext(); ) {
- String messageName =
(String) incomingMessages.next();
-
messageNames.add(messageName);
- Long messageCount =
(Long) peerNodeStatus.getLocalMessagesReceived().get(messageName);
-
messageCounts.put(messageName, new Long[] { messageCount, new Long(0) });
- }
- for (Iterator outgoingMessages
= peerNodeStatus.getLocalMessagesSent().keySet().iterator();
outgoingMessages.hasNext(); ) {
- String messageName =
(String) outgoingMessages.next();
- if
(!messageNames.contains(messageName)) {
-
messageNames.add(messageName);
- }
- Long messageCount =
(Long) peerNodeStatus.getLocalMessagesSent().get(messageName);
- Long[] existingCounts =
(Long[]) messageCounts.get(messageName);
- if (existingCounts ==
null) {
-
messageCounts.put(messageName, new Long[] { new Long(0), messageCount });
- } else {
-
existingCounts[1] = messageCount;
- }
- }
- Collections.sort(messageNames,
new Comparator() {
- public int
compare(Object first, Object second) {
- return
((String) first).compareToIgnoreCase((String) second);
- }
- });
- for (Iterator
messageNamesIterator = messageNames.iterator(); messageNamesIterator.hasNext();
) {
- String messageName =
(String) messageNamesIterator.next();
- Long[] messageCount =
(Long[]) messageCounts.get(messageName);
- HTMLNode messageRow =
messageCountTable.addChild("tr");
-
messageRow.addChild("td", messageName);
-
messageRow.addChild("td", "class", "right-align",
String.valueOf(messageCount[0]));
-
messageRow.addChild("td", "class", "right-align",
String.valueOf(messageCount[1]));
- }
- }
- }
-
- HTMLNode actionSelect =
peerForm.addChild("select", new String[] { "id", "name" }, new String[] {
"action", "action" });
- actionSelect.addChild("option", "value", "",
l10n("selectAction"));
- actionSelect.addChild("option", "value",
"send_n2ntm", l10n("sendMessageToPeers"));
- actionSelect.addChild("option", "value",
"update_notes", l10n("updateChangedPrivnotes"));
- if(advancedModeEnabled) {
- actionSelect.addChild("option",
"value", "enable", "Enable selected peers");
- actionSelect.addChild("option",
"value", "disable", "Disable selected peers");
- actionSelect.addChild("option",
"value", "set_burst_only", "On selected peers, set BurstOnly (only set this if
you have a static IP and are not NATed and neither is the peer)");
- actionSelect.addChild("option",
"value", "clear_burst_only", "On selected peers, clear BurstOnly");
- actionSelect.addChild("option",
"value", "set_listen_only", "On selected peers, set ListenOnly (not
recommended)");
- actionSelect.addChild("option",
"value", "clear_listen_only", "On selected peers, clear ListenOnly");
- actionSelect.addChild("option",
"value", "set_allow_local", "On selected peers, set allowLocalAddresses (useful
if you are connecting to another node on the same LAN)");
- actionSelect.addChild("option",
"value", "clear_allow_local", "On selected peers, clear allowLocalAddresses");
- actionSelect.addChild("option",
"value", "set_ignore_source_port", "On selected peers, set ignoreSourcePort
(try this if behind an evil corporate firewall; otherwise not recommended)");
- actionSelect.addChild("option",
"value", "clear_ignore_source_port", "On selected peers, clear
ignoreSourcePort");
- }
- actionSelect.addChild("option", "value", "",
l10n("separator"));
- actionSelect.addChild("option", "value",
"remove", l10n("removePeers"));
- peerForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "doAction", l10n("go") });
-
- }
- // END PEER TABLE
+ protected void drawPeerActionSelectBox(HTMLNode peerForm, boolean
advancedModeEnabled) {
+ HTMLNode actionSelect = peerForm.addChild("select", new
String[] { "id", "name" }, new String[] { "action", "action" });
+ actionSelect.addChild("option", "value", "",
l10n("selectAction"));
+ actionSelect.addChild("option", "value", "send_n2ntm",
l10n("sendMessageToPeers"));
+ actionSelect.addChild("option", "value", "update_notes",
l10n("updateChangedPrivnotes"));
+ if(advancedModeEnabled) {
+ actionSelect.addChild("option", "value", "enable",
"Enable selected peers");
+ actionSelect.addChild("option", "value", "disable",
"Disable selected peers");
+ actionSelect.addChild("option", "value",
"set_burst_only", "On selected peers, set BurstOnly (only set this if you have
a static IP and are not NATed and neither is the peer)");
+ actionSelect.addChild("option", "value",
"clear_burst_only", "On selected peers, clear BurstOnly");
+ actionSelect.addChild("option", "value",
"set_listen_only", "On selected peers, set ListenOnly (not recommended)");
+ actionSelect.addChild("option", "value",
"clear_listen_only", "On selected peers, clear ListenOnly");
+ actionSelect.addChild("option", "value",
"set_allow_local", "On selected peers, set allowLocalAddresses (useful if you
are connecting to another node on the same LAN)");
+ actionSelect.addChild("option", "value",
"clear_allow_local", "On selected peers, clear allowLocalAddresses");
+ actionSelect.addChild("option", "value",
"set_ignore_source_port", "On selected peers, set ignoreSourcePort (try this if
behind an evil corporate firewall; otherwise not recommended)");
+ actionSelect.addChild("option", "value",
"clear_ignore_source_port", "On selected peers, clear ignoreSourcePort");
}
+ actionSelect.addChild("option", "value", "", l10n("separator"));
+ actionSelect.addChild("option", "value", "remove",
l10n("removePeers"));
+ peerForm.addChild("input", new String[] { "type", "name",
"value" }, new String[] { "submit", "doAction", l10n("go") });
+ }
- // BEGIN PEER ADDITION BOX
- HTMLNode peerAdditionInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
- peerAdditionInfobox.addChild("div", "class", "infobox-header",
l10n("addPeerTitle"));
- HTMLNode peerAdditionContent =
peerAdditionInfobox.addChild("div", "class", "infobox-content");
- HTMLNode peerAdditionForm =
ctx.addFormChild(peerAdditionContent, ".", "addPeerForm");
- peerAdditionForm.addChild("#", l10n("pasteReference"));
- peerAdditionForm.addChild("br");
- peerAdditionForm.addChild("textarea", new String[] { "id",
"name", "rows", "cols" }, new String[] { "reftext", "ref", "8", "74" });
- peerAdditionForm.addChild("br");
- peerAdditionForm.addChild("#", (l10n("urlReference") + ' '));
- peerAdditionForm.addChild("input", new String[] { "id", "type",
"name" }, new String[] { "refurl", "text", "url" });
- peerAdditionForm.addChild("br");
- peerAdditionForm.addChild("#", (l10n("fileReference") + ' '));
- peerAdditionForm.addChild("input", new String[] { "id", "type",
"name" }, new String[] { "reffile", "file", "reffile" });
- peerAdditionForm.addChild("br");
- peerAdditionForm.addChild("#", (l10n("enterDescription") + '
'));
- peerAdditionForm.addChild("input", new String[] { "id", "type",
"name", "size", "maxlength", "value" }, new String[] { "peerPrivateNote",
"text", "peerPrivateNote", "16", "250", "" });
- peerAdditionForm.addChild("br");
- peerAdditionForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "add", l10n("add") });
-
- // our reference
- HTMLNode referenceInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
- HTMLNode headerReferenceInfobox =
referenceInfobox.addChild("div", "class", "infobox-header");
- // FIXME better way to deal with this sort of thing???
- L10n.addL10nSubstitution(headerReferenceInfobox,
"DarknetConnectionsToadlet.myReferenceHeader",
- new String[] { "linkref", "/linkref",
"linktext", "/linktext" },
- new String[] { "<a href=\"myref.fref\">",
"</a>", "<a href=\"myref.txt\">", "</a>" });
- HTMLNode warningSentence =
headerReferenceInfobox.addChild("pre");
- L10n.addL10nSubstitution(warningSentence,
"DarknetConnectionsToadlet.referenceCopyWarning",
- new String[] { "bold", "/bold" },
- new String[] { "<b>", "</b>" });
- referenceInfobox.addChild("div", "class",
"infobox-content").addChild("pre", "id", "reference",
node.exportPublicFieldSet().toString());
-
- // our ports
- HTMLNode portInfobox = contentNode.addChild("div", "class",
"infobox infobox-normal");
- portInfobox.addChild("div", "class", "infobox-header",
l10n("nodePortsTitle"));
- HTMLNode portInfoboxContent = portInfobox.addChild("div",
"class", "infobox-content");
- HTMLNode portInfoList = portInfoboxContent.addChild("ul");
- SimpleFieldSet fproxyConfig =
node.config.get("fproxy").exportFieldSet(true);
- SimpleFieldSet fcpConfig =
node.config.get("fcp").exportFieldSet(true);
- SimpleFieldSet tmciConfig =
node.config.get("console").exportFieldSet(true);
- portInfoList.addChild("li",
L10n.getString("DarknetConnectionsToadlet.fnpPort", new String[] { "port" },
new String[] { Integer.toString(node.getFNPPort()) }));
- try {
- if(fproxyConfig.getBoolean("enabled", false)) {
- portInfoList.addChild("li",
L10n.getString("DarknetConnectionsToadlet.fproxyPort", new String[] { "port" },
new String[] { Integer.toString(fproxyConfig.getInt("port")) }));
- } else {
- portInfoList.addChild("li",
l10n("fproxyDisabled"));
- }
- if(fcpConfig.getBoolean("enabled", false)) {
- portInfoList.addChild("li",
L10n.getString("DarknetConnectionsToadlet.fcpPort", new String[] { "port" },
new String[] { Integer.toString(fcpConfig.getInt("port")) }));
- } else {
- portInfoList.addChild("li",
l10n("fcpDisabled"));
- }
- if(tmciConfig.getBoolean("enabled", false)) {
- portInfoList.addChild("li",
L10n.getString("DarknetConnectionsToadlet.tmciPort", new String[] { "port" },
new String[] { Integer.toString(tmciConfig.getInt("port")) }));
- } else {
- portInfoList.addChild("li",
l10n("tmciDisabled"));
- }
- } catch (FSParseException e) {
- // ignore
- }
-
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ protected String getPeerListTitle() {
+ return l10n("myFriends");
}
-
- private static String l10n(String string) {
- return L10n.getString("DarknetConnectionsToadlet."+string);
+
+ protected boolean acceptRefPosts() {
+ return true;
}
-
- private static String l10nStats(String string) {
- return L10n.getString("StatisticsToadlet."+string);
- }
- private String sortString(boolean isReversed, String type) {
- return (isReversed ? ("?sortBy="+type) :
("?sortBy="+type+"&reversed"));
+ protected String defaultRedirectLocation() {
+ return "/friends/"; // FIXME
}
- public void handlePost(URI uri, final HTTPRequest request,
ToadletContext ctx) throws ToadletContextClosedException, IOException,
RedirectException {
- boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
-
- if(!ctx.isAllowedFullAccess()) {
- super.sendErrorPage(ctx, 403, "Unauthorized",
L10n.getString("Toadlet.unauthorized"));
- return;
- }
-
- String pass = request.getPartAsString("formPassword", 32);
- if((pass == null) || !pass.equals(core.formPassword)) {
- MultiValueTable headers = new MultiValueTable();
- headers.put("Location", "/friends/");
- ctx.sendReplyHeaders(302, "Found", headers, null, 0);
- if(logMINOR) Logger.minor(this, "No password ("+pass+"
should be "+core.formPassword+ ')');
- return;
- }
-
- if (request.isPartSet("add")) {
- // add a new node
- String urltext = request.getPartAsString("url", 100);
- urltext = urltext.trim();
- String reftext = request.getPartAsString("ref", 2000);
- reftext = reftext.trim();
- if (reftext.length() < 200) {
- reftext = request.getPartAsString("reffile",
2000);
- reftext = reftext.trim();
- }
- String privateComment =
request.getPartAsString("peerPrivateNote", 250).trim();
-
- StringBuffer ref = new StringBuffer(1024);
- if (urltext.length() > 0) {
- // fetch reference from a URL
- BufferedReader in = null;
- try {
- URL url = new URL(urltext);
- URLConnection uc = url.openConnection();
- in = new BufferedReader(new
InputStreamReader(uc.getInputStream()));
- String line;
- while ( (line = in.readLine()) != null)
{
- ref.append( line ).append('\n');
- }
- } catch (IOException e) {
- this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"),
L10n.getString("DarknetConnectionsToadlet.cantFetchNoderefURL", new String[] {
"url" }, new String[] { urltext }));
- return;
- } finally {
- if( in != null ){
- in.close();
- }
- }
- } else if (reftext.length() > 0) {
- // read from post data or file upload
- // this slightly scary looking regexp chops any
extra characters off the beginning or ends of lines and removes extra line
breaks
- ref = new
StringBuffer(reftext.replaceAll(".*?((?:[\\w,\\.]+\\=[^\r\n]+?)|(?:End))[
\\t]*(?:\\r?\\n)+", "$1\n"));
- } else {
- this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"), l10n("noRefOrURL"));
- request.freeParts();
- return;
- }
- ref = new StringBuffer(ref.toString().trim());
-
- request.freeParts();
- // we have a node reference in ref
- SimpleFieldSet fs;
-
- try {
- fs = new SimpleFieldSet(ref.toString(), false,
true);
- if(!fs.getEndMarker().endsWith("End")) {
- sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"),
-
L10n.getString("DarknetConnectionsToadlet.cantParseWrongEnding", new String[] {
"end" }, new String[] { fs.getEndMarker() }));
- return;
- }
- fs.setEndMarker("End"); // It's always End ;
the regex above doesn't always grok this
- } catch (IOException e) {
- this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"),
-
L10n.getString("DarknetConnectionsToadlet.cantParseTryAgain", new String[] {
"error" }, new String[] { e.toString() }));
- return;
- } catch (Throwable t) {
- this.sendErrorPage(ctx,
l10n("failedToAddNodeInternalErrorTitle"),
l10n("failedToAddNodeInternalError"), t);
- return;
- }
- PeerNode pn;
- try {
- pn = new PeerNode(fs, node, node.peers, false);
- pn.setPrivateDarknetCommentNote(privateComment);
- } catch (FSParseException e1) {
- this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"),
-
L10n.getString("DarknetConnectionsToadlet.cantParseTryAgain", new String[] {
"error" }, new String[] { e1.toString() }));
- return;
- } catch (PeerParseException e1) {
- this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"),
-
L10n.getString("DarknetConnectionsToadlet.cantParseTryAgain", new String[] {
"error" }, new String[] { e1.toString() }));
- return;
- } catch (ReferenceSignatureVerificationException e1){
- HTMLNode node = new HTMLNode("div");
- node.addChild("#",
L10n.getString("DarknetConnectionsToadlet.invalidSignature", new String[] {
"error" }, new String[] { e1.toString() }));
- node.addChild("br");
- this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"), node);
- return;
- } catch (Throwable t) {
- this.sendErrorPage(ctx,
l10n("failedToAddNodeInternalErrorTitle"),
l10n("failedToAddNodeInternalError"), t);
- return;
- }
- if(pn.getIdentityHash()==node.getIdentityHash()) {
- this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"), l10n("triedToAddSelf"));
- return;
- }
- if(!this.node.addDarknetConnection(pn)) {
- this.sendErrorPage(ctx, 200,
l10n("failedToAddNodeTitle"), l10n("alreadyInReferences"));
- return;
- }
-
- MultiValueTable headers = new MultiValueTable();
- headers.put("Location", "/friends/");
- ctx.sendReplyHeaders(302, "Found", headers, null, 0);
- return;
- } else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("send_n2ntm")) {
+ /**
+ * Implement other post actions than adding nodes.
+ * @throws IOException
+ * @throws ToadletContextClosedException
+ * @throws RedirectException
+ */
+ protected void handleAltPost(URI uri, HTTPRequest request,
ToadletContext ctx, boolean logMINOR) throws ToadletContextClosedException,
IOException, RedirectException {
+ if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("send_n2ntm")) {
HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("sendMessageTitle"), ctx);
HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
HashMap peers = new HashMap();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
- PeerNode pn = peerNodes[i];
+ DarknetPeerNode pn = peerNodes[i];
String peer_name = pn.getName();
String peer_hash = "" + pn.hashCode();
if(!peers.containsKey(peer_hash)) {
@@ -738,12 +159,12 @@
}
}
N2NTMToadlet.createN2NTMSendForm( pageNode,
contentNode, ctx, peers);
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK", pageNode.generate());
return;
} else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("update_notes")) {
//int hashcode =
Integer.decode(request.getParam("node")).intValue();
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("peerPrivateNote_"+peerNodes[i].hashCode())) {
if(!request.getPartAsString("peerPrivateNote_"+peerNodes[i].hashCode(),250).equals(peerNodes[i].getPrivateDarknetCommentNote()))
{
@@ -758,7 +179,7 @@
} else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("enable")) {
//int hashcode =
Integer.decode(request.getParam("node")).intValue();
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
peerNodes[i].enablePeer();
@@ -771,7 +192,7 @@
} else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("disable")) {
//int hashcode =
Integer.decode(request.getParam("node")).intValue();
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
peerNodes[i].disablePeer();
@@ -784,7 +205,7 @@
} else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("set_burst_only")) {
//int hashcode =
Integer.decode(request.getParam("node")).intValue();
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
peerNodes[i].setBurstOnly(true);
@@ -797,7 +218,7 @@
} else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("clear_burst_only")) {
//int hashcode =
Integer.decode(request.getParam("node")).intValue();
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
peerNodes[i].setBurstOnly(false);
@@ -810,7 +231,7 @@
} else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("set_ignore_source_port")) {
//int hashcode =
Integer.decode(request.getParam("node")).intValue();
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
peerNodes[i].setIgnoreSourcePort(true);
@@ -823,7 +244,7 @@
} else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("clear_ignore_source_port")) {
//int hashcode =
Integer.decode(request.getParam("node")).intValue();
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
peerNodes[i].setIgnoreSourcePort(false);
@@ -836,7 +257,7 @@
} else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("set_listen_only")) {
//int hashcode =
Integer.decode(request.getParam("node")).intValue();
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
peerNodes[i].setListenOnly(true);
@@ -849,7 +270,7 @@
} else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("clear_listen_only")) {
//int hashcode =
Integer.decode(request.getParam("node")).intValue();
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
peerNodes[i].setListenOnly(false);
@@ -862,7 +283,7 @@
} else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("set_allow_local")) {
//int hashcode =
Integer.decode(request.getParam("node")).intValue();
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
peerNodes[i].setAllowLocalAddresses(true);
@@ -875,7 +296,7 @@
} else if (request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("clear_allow_local")) {
//int hashcode =
Integer.decode(request.getParam("node")).intValue();
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
peerNodes[i].setAllowLocalAddresses(false);
@@ -888,15 +309,15 @@
} else if (request.isPartSet("remove") ||
(request.isPartSet("doAction") &&
request.getPartAsString("action",25).equals("remove"))) {
if(logMINOR) Logger.minor(this, "Remove node");
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for(int i = 0; i < peerNodes.length; i++) {
if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
if((peerNodes[i].timeLastConnectionCompleted() < (System.currentTimeMillis() -
1000*60*60*24*7) /* one week */) || (peerNodes[i].peerNodeStatus ==
PeerManager.PEER_NODE_STATUS_NEVER_CONNECTED) || request.isPartSet("forceit")){
-
this.node.removeDarknetConnection(peerNodes[i]);
+
this.node.removePeerConnection(peerNodes[i]);
if(logMINOR) Logger.minor(this,
"Removed node: node_"+peerNodes[i].hashCode());
}else{
if(logMINOR) Logger.minor(this,
"Refusing to remove : node_"+peerNodes[i].hashCode()+" (trying to prevent
network churn) : let's display the warning message.");
- HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("Please confirm"), ctx);
+ HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("confirmRemoveNodeTitle"), ctx);
HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
HTMLNode infobox =
contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-warning",
l10n("confirmRemoveNodeWarningTitle")));
HTMLNode content =
ctx.getPageMaker().getContentNode(infobox);
@@ -908,7 +329,7 @@
removeForm.addChild("input",
new String[] { "type", "name", "value" }, new String[] { "submit", "remove",
l10n("remove") });
removeForm.addChild("input",
new String[] { "type", "name", "value" }, new String[] { "hidden", "forceit",
l10n("forceRemove") });
- writeReply(ctx, 200,
"text/html", "OK", pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return; // FIXME: maybe it
breaks multi-node removing
}
} else {
@@ -919,16 +340,41 @@
headers.put("Location", "/friends/");
ctx.sendReplyHeaders(302, "Found", headers, null, 0);
return;
+ } else if (request.isPartSet("acceptTransfer")) {
+ // FIXME this is ugly, should probably move both this
code and the PeerNode code somewhere.
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
+ for(int i = 0; i < peerNodes.length; i++) {
+ if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
+ long id =
Long.parseLong(request.getPartAsString("id", 32)); // FIXME handle
NumberFormatException
+ peerNodes[i].acceptTransfer(id);
+ break;
+ }
+ }
+ MultiValueTable headers = new MultiValueTable();
+ headers.put("Location", "/friends/");
+ ctx.sendReplyHeaders(302, "Found", headers, null, 0);
+ return;
+ } else if (request.isPartSet("rejectTransfer")) {
+ // FIXME this is ugly, should probably move both this
code and the PeerNode code somewhere.
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
+ for(int i = 0; i < peerNodes.length; i++) {
+ if
(request.isPartSet("node_"+peerNodes[i].hashCode())) {
+ long id =
Long.parseLong(request.getPartAsString("id", 32)); // FIXME handle
NumberFormatException
+ peerNodes[i].rejectTransfer(id);
+ break;
+ }
+ }
+ MultiValueTable headers = new MultiValueTable();
+ headers.put("Location", "/friends/");
+ ctx.sendReplyHeaders(302, "Found", headers, null, 0);
+ return;
} else {
this.handleGet(uri, new HTTPRequestImpl(uri), ctx);
}
}
-
- private String idleToString(long now, long idle) {
- if (idle <= 0) {
- return " ";
- }
- long idleMilliseconds = now - idle;
- return TimeUtil.formatTime(idleMilliseconds);
+
+ protected boolean isOpennet() {
+ return false;
}
+
}
Modified: branches/freenet-jfk/src/freenet/clients/http/FProxyToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/FProxyToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/FProxyToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -241,6 +241,7 @@
if(checkForString(buf, "<rss")) return true;
if(checkForString(buf, "<feed")) return true;
if(checkForString(buf, "<rdf:RDF")) return true;
+ is.close();
return false;
}
@@ -318,13 +319,18 @@
}
return;
}else if(ks.equals("/robots.txt") && ctx.doRobots()){
- this.writeReply(ctx, 200, "text/plain", "Ok",
"User-agent: *\nDisallow: /");
+ this.writeTextReply(ctx, 200, "Ok", "User-agent:
*\nDisallow: /");
return;
}else if(ks.startsWith("/darknet/")) { //TODO: remove when
obsolete
MultiValueTable headers = new MultiValueTable();
headers.put("Location", "/friends/");
ctx.sendReplyHeaders(301, "Permanent Redirect",
headers, null, 0);
return;
+ }else if(ks.startsWith("/opennet/")) { //TODO: remove when
obsolete
+ MultiValueTable headers = new MultiValueTable();
+ headers.put("Location", "/strangers/");
+ ctx.sendReplyHeaders(301, "Permanent Redirect",
headers, null, 0);
+ return;
}
if(ks.startsWith("/"))
@@ -349,7 +355,7 @@
errorContent.addChild("br");
addHomepageLink(errorContent);
- this.writeReply(ctx, 400, "text/html",
l10n("invalidKeyTitle"), pageNode.generate());
+ this.writeHTMLReply(ctx, 400, l10n("invalidKeyTitle"),
pageNode.generate());
return;
}
String requestedMimeType = httprequest.getParam("type", null);
@@ -372,9 +378,7 @@
String msg = e.getMessage();
if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Failed to fetch "+uri+" :
"+e);
- if(e.mode == FetchException.NOT_ENOUGH_PATH_COMPONENTS)
{
- this.writePermanentRedirect(ctx,
l10n("notEnoughMetaStrings"), '/' + key.toString() + '/' + override);
- } else if(e.newURI != null) {
+ if(e.newURI != null) {
this.writePermanentRedirect(ctx, msg, '/'
+e.newURI.toString() + override);
} else if(e.mode == FetchException.TOO_BIG) {
HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("fileInformationTitle"), ctx);
@@ -412,7 +416,7 @@
}
optionList.addChild("li").addChild("a", new
String[] { "href", "title" }, new String[] { "/", "FProxy home page" },
l10n("abortToHomepage"));
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
} else {
HTMLNode pageNode =
ctx.getPageMaker().getPageNode(FetchException.getShortMessage(e.mode), ctx);
HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
@@ -460,8 +464,8 @@
option = optionList.addChild("li");
option.addChild(ctx.getPageMaker().createBackLink(ctx, l10n("goBackToPrev")));
- this.writeReply(ctx, 500 /* close enough -
FIXME probably should depend on status code */,
- "text/html",
FetchException.getShortMessage(e.mode), pageNode.generate());
+ this.writeHTMLReply(ctx, 500 /* close enough -
FIXME probably should depend on status code */,
+ "Internal Error",
pageNode.generate());
}
} catch (SocketException e) {
// Probably irrelevant
@@ -562,34 +566,35 @@
return f;
}
- public static void maybeCreateFProxyEtc(NodeClientCore core, Node node,
Config config, SubConfig fproxyConfig) throws IOException,
InvalidConfigValueException {
+ public static SimpleToadletServer maybeCreateFProxyEtc(NodeClientCore
core, Node node, Config config, SubConfig fproxyConfig) throws IOException,
InvalidConfigValueException {
+ SimpleToadletServer server = null;
+
// FIXME how to change these on the fly when the interface
language is changed?
try {
- SimpleToadletServer server = new
SimpleToadletServer(fproxyConfig, core);
+ server = new SimpleToadletServer(fproxyConfig, core);
HighLevelSimpleClient client =
core.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS, true);
- core.setToadletContainer(server);
random = new byte[32];
core.random.nextBytes(random);
FProxyToadlet fproxy = new FProxyToadlet(client, core);
core.setFProxy(fproxy);
- server.register(fproxy, "/", false,
l10n("welcomeTitle"), l10n("welcome"), false);
+ server.register(fproxy, "/", false,
"FProxyToadlet.welcomeTitle", "FProxyToadlet.welcome", false, null);
- PproxyToadlet pproxy = new PproxyToadlet(client,
node.pluginManager, core);
- server.register(pproxy, "/plugins/", true,
l10n("pluginsTitle"), l10n("plugins"), true);
+ PproxyToadlet pproxy = new PproxyToadlet(client, node,
core);
+ server.register(pproxy, "/plugins/", true,
"FProxyToadlet.pluginsTitle", "FProxyToadlet.plugins", true, null);
- WelcomeToadlet welcometoadlet = new
WelcomeToadlet(client, node);
+ WelcomeToadlet welcometoadlet = new
WelcomeToadlet(client, core, node);
server.register(welcometoadlet, "/welcome/", true,
false);
PluginToadlet pluginToadlet = new PluginToadlet(client,
node.pluginManager2, core);
server.register(pluginToadlet, "/plugin/", true, true);
ConfigToadlet configtoadlet = new ConfigToadlet(client,
config, node, core);
- server.register(configtoadlet, "/config/", true,
l10n("configTitle"), l10n("config"), true);
+ server.register(configtoadlet, "/config/", true,
"FProxyToadlet.configTitle", "FProxyToadlet.config", true, null);
StaticToadlet statictoadlet = new StaticToadlet(client);
server.register(statictoadlet, "/static/", true, false);
@@ -599,16 +604,20 @@
DarknetConnectionsToadlet friendsToadlet = new
DarknetConnectionsToadlet(node, core, client);
// server.register(friendsToadlet, "/darknet/", true,
l10n("friendsTitle"), l10n("friends"), true);
- server.register(friendsToadlet, "/friends/", true,
l10n("friendsTitle"), l10n("friends"), true);
+ server.register(friendsToadlet, "/friends/", true,
"FProxyToadlet.friendsTitle", "FProxyToadlet.friends", true, null);
+ OpennetConnectionsToadlet opennetToadlet = new
OpennetConnectionsToadlet(node, core, client);
+// server.register(opennetToadlet, "/opennet/", true,
l10n("opennetTitle"), l10n("opennet"), true, opennetToadlet);
+ server.register(opennetToadlet, "/strangers/", true,
"FProxyToadlet.opennetTitle", "FProxyToadlet.opennet", true, opennetToadlet);
+
N2NTMToadlet n2ntmToadlet = new N2NTMToadlet(node,
core, client);
server.register(n2ntmToadlet, "/send_n2ntm/", true,
true);
QueueToadlet queueToadlet = new QueueToadlet(core,
core.getFCPServer(), client);
- server.register(queueToadlet, "/queue/", true,
l10n("queueTitle"), l10n("queue"), false);
+ server.register(queueToadlet, "/queue/", true,
"FProxyToadlet.queueTitle", "FProxyToadlet.queue", false, null);
StatisticsToadlet statisticsToadlet = new
StatisticsToadlet(node, core, client);
- server.register(statisticsToadlet, "/stats/", true,
l10n("statsTitle"), l10n("stats"), true);
+ server.register(statisticsToadlet, "/stats/", true,
"FProxyToadlet.statsTitle", "FProxyToadlet.stats", true, null);
LocalFileInsertToadlet localFileInsertToadlet = new
LocalFileInsertToadlet(core, client);
server.register(localFileInsertToadlet, "/files/",
true, false);
@@ -620,14 +629,11 @@
server.register(browsertTestToadlet, "/test/", true,
false);
TranslationToadlet translationToadlet = new
TranslationToadlet(client, core);
- server.register(translationToadlet,
TranslationToadlet.TOADLET_URL, true, l10n("translationTitle"),
l10n("translation"), true);
+ server.register(translationToadlet,
TranslationToadlet.TOADLET_URL, true, true);
- FirstTimeWizardToadlet firstTimeWizardToadlet = new
FirstTimeWizardToadlet(client, node);
+ FirstTimeWizardToadlet firstTimeWizardToadlet = new
FirstTimeWizardToadlet(client, node, core);
server.register(firstTimeWizardToadlet,
FirstTimeWizardToadlet.TOADLET_URL, true, false);
- // Now start the server.
- server.start();
-
}catch (BindException e){
Logger.error(core,"Failed to start FProxy port already
bound: isn't Freenet already running ?");
System.err.println("Failed to start FProxy port already
bound: isn't Freenet already running ?");
@@ -637,6 +643,8 @@
}
fproxyConfig.finishedInitialization();
+
+ return server; // caller must start server
}
/**
Modified:
branches/freenet-jfk/src/freenet/clients/http/FirstTimeWizardToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/FirstTimeWizardToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/FirstTimeWizardToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -4,6 +4,7 @@
package freenet.clients.http;
import java.io.IOException;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URI;
@@ -16,6 +17,7 @@
import freenet.node.Node;
import freenet.node.NodeClientCore;
import freenet.support.Base64;
+import freenet.support.Fields;
import freenet.support.HTMLNode;
import freenet.support.Logger;
import freenet.support.api.HTTPRequest;
@@ -32,9 +34,9 @@
private final Config config;
- FirstTimeWizardToadlet(HighLevelSimpleClient client, Node node) {
+ FirstTimeWizardToadlet(HighLevelSimpleClient client, Node node,
NodeClientCore core) {
super(client);
- this.core = node.clientCore;
+ this.core = core;
this.config = node.config;
}
@@ -52,6 +54,26 @@
HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("step1Title"), false, ctx);
HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
+ HTMLNode opennetInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
+ HTMLNode opennetInfoboxHeader =
opennetInfobox.addChild("div", "class", "infobox-header");
+ HTMLNode opennetInfoboxContent =
opennetInfobox.addChild("div", "class", "infobox-content");
+
+ opennetInfoboxHeader.addChild("#",
l10n("connectToStrangers"));
+ opennetInfoboxContent.addChild("#",
l10n("connectToStrangersLong"));
+ HTMLNode opennetForm =
ctx.addFormChild(opennetInfoboxContent, ".", "opennetForm");
+
+ HTMLNode opennetDiv = opennetForm.addChild("div",
"class", "opennetDiv");
+ opennetDiv.addChild("#", l10n("enableOpennet"));
+ opennetDiv.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "radio", "enableOpennet", "true" },
L10n.getString("Toadlet.yes"));
+ opennetDiv.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "radio", "enableOpennet", "false" },
L10n.getString("Toadlet.no"));
+ opennetForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "opennetF",
L10n.getString("FirstTimeWizardToadlet.continue")});
+ opennetForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel")});
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
+ return;
+ } else if(currentStep == 2) {
+ HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("step2Title"), false, ctx);
+ HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
+
HTMLNode nnameInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
HTMLNode nnameInfoboxHeader =
nnameInfobox.addChild("div", "class", "infobox-header");
HTMLNode nnameInfoboxContent =
nnameInfobox.addChild("div", "class", "infobox-content");
@@ -61,12 +83,12 @@
HTMLNode nnameForm =
ctx.addFormChild(nnameInfoboxContent, ".", "nnameForm");
nnameForm.addChild("input", "name", "nname");
- nnameForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "nnameF",
L10n.getString("Toadlet.clickHere")});
+ nnameForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "nnameF",
L10n.getString("FirstTimeWizardToadlet.continue")});
nnameForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel")});
- this.writeReply(ctx, 200, "text/html; charset=utf-8",
"OK", pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
- } else if(currentStep == 2) {
- HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("step2Title"), false, ctx);
+ } else if(currentStep == 3) {
+ HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("step3Title"), false, ctx);
HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
HTMLNode bandwidthInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
@@ -78,20 +100,20 @@
HTMLNode bandwidthForm =
ctx.addFormChild(bandwidthInfoboxContent, ".", "bwForm");
HTMLNode result = bandwidthForm.addChild("select",
"name", "bw");
- result.addChild("option", new String[] { "value",
"selected" }, new String[] { "15", "selected" }, "I don't know");
+ result.addChild("option", new String[] { "value",
"selected" }, new String[] { "15K", "selected" }, "I don't know");
result.addChild("option", "value", "8K", "lower speed");
- result.addChild("option", "value", "12K", "1024+/128
kbps");
+ result.addChild("option", "value", "12K", "512+/128
kbps");
result.addChild("option", "value", "24K", "1024+/256
kbps");
result.addChild("option", "value", "48K", "1024+/512
kbps");
result.addChild("option", "value", "96K", "1024+/1024
kbps");
result.addChild("option", "value", "1000K", "higher
speed");
- bandwidthForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "bwF",
L10n.getString("Toadlet.clickHere")});
+ bandwidthForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "bwF",
L10n.getString("FirstTimeWizardToadlet.continue")});
bandwidthForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel")});
- this.writeReply(ctx, 200, "text/html; charset=utf-8",
"OK", pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
- } else if(currentStep == 3) {
- HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("step3Title"), false, ctx);
+ } else if(currentStep == 4) {
+ HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("step4Title"), false, ctx);
HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
HTMLNode bandwidthInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
@@ -113,12 +135,12 @@
result.addChild("option", "value", "50G", "50GiB");
result.addChild("option", "value", "100G", "100GiB");
- bandwidthForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "dsF",
L10n.getString("Toadlet.clickHere")});
+ bandwidthForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "dsF",
L10n.getString("FirstTimeWizardToadlet.continue")});
bandwidthForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel")});
- this.writeReply(ctx, 200, "text/html; charset=utf-8",
"OK", pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
- } else if(currentStep == 4) {
- HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("step4Title"), false, ctx);
+ } else if(currentStep == 5) {
+ HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("step5Title"), false, ctx);
HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
HTMLNode networkInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
@@ -156,12 +178,12 @@
}
ctx.addFormChild(networkInfoboxContent, ".",
"networkForm").addChild(networkForm);
- networkForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "networkF",
L10n.getString("Toadlet.clickHere")});
+ networkForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "networkF",
L10n.getString("FirstTimeWizardToadlet.continue")});
networkForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel")});
- this.writeReply(ctx, 200, "text/html; charset=utf-8",
"OK", pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
- }else if(currentStep == 5) {
- HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("step5Title"), true, ctx);
+ }else if(currentStep == 6) {
+ HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("step6Title"), true, ctx);
HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
HTMLNode congratzInfobox = contentNode.addChild("div",
"class", "infobox infobox-normal");
@@ -171,7 +193,7 @@
congratzInfoboxHeader.addChild("#", l10n("congratz"));
congratzInfoboxContent.addChild("#",
l10n("congratzLong"));
- this.writeReply(ctx, 200, "text/html; charset=utf-8",
"OK", pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
}
@@ -185,12 +207,12 @@
HTMLNode firstParagraph = welcomeInfoboxContent.addChild("p");
firstParagraph.addChild("#", l10n("welcomeInfoboxContent1") + '
');
- firstParagraph.addChild("a", "href", "?step=1").addChild("#",
L10n.getString("Toadlet.clickHere"));
+ firstParagraph.addChild("a", "href", "?step=1").addChild("#",
L10n.getString("FirstTimeWizardToadlet.continue"));
HTMLNode secondParagraph = welcomeInfoboxContent.addChild("p");
secondParagraph.addChild("a", "href", "/").addChild("#",
l10n("skipWizard"));
- this.writeReply(ctx, 200, "text/html; charset=utf-8", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}
public void handlePost(URI uri, HTTPRequest request, ToadletContext
ctx) throws ToadletContextClosedException, IOException {
@@ -208,7 +230,27 @@
return;
}
- if(request.isPartSet("nnameF")) {
+
+ if(request.isPartSet("enableOpennet")) {
+ String isOpennetEnabled =
request.getPartAsString("enableOpennet", 255);
+ boolean enable;
+ try {
+ enable = Fields.stringToBool(isOpennetEnabled);
+ } catch (NumberFormatException e) {
+ Logger.error(this, "Invalid opennetEnabled:
"+isOpennetEnabled);
+ super.writeTemporaryRedirect(ctx, "step1",
TOADLET_URL+"?step=1");
+ return;
+ }
+ try {
+ config.get("node.opennet").set("enabled",
enable);
+ } catch (InvalidConfigValueException e) {
+ Logger.error(this, "Should not happen setting
opennet.enabled="+enable+" please repot: "+e, e);
+ super.writeTemporaryRedirect(ctx, "step1",
TOADLET_URL+"?step=1");
+ return;
+ }
+ super.writeTemporaryRedirect(ctx, "step1",
TOADLET_URL+"?step=2");
+ return;
+ } else if(request.isPartSet("nnameF")) {
String selectedNName = request.getPartAsString("nname",
255);
try {
@@ -217,7 +259,7 @@
} catch (InvalidConfigValueException e) {
Logger.error(this, "Should not happen, please
report!" + e);
}
- super.writeTemporaryRedirect(ctx, "step2",
TOADLET_URL+"?step=2");
+ super.writeTemporaryRedirect(ctx, "step3",
TOADLET_URL+"?step=3");
return;
} else if(request.isPartSet("bwF")) {
String selectedUploadSpeed
=request.getPartAsString("bw", 6);
@@ -228,7 +270,7 @@
} catch (InvalidConfigValueException e) {
Logger.error(this, "Should not happen, please
report!" + e);
}
- super.writeTemporaryRedirect(ctx, "step3",
TOADLET_URL+"?step=3");
+ super.writeTemporaryRedirect(ctx, "step4",
TOADLET_URL+"?step=4");
return;
} else if(request.isPartSet("dsF")) {
String selectedStoreSize =request.getPartAsString("ds",
6);
@@ -239,13 +281,14 @@
} catch (InvalidConfigValueException e) {
Logger.error(this, "Should not happen, please
report!" + e);
}
- super.writeTemporaryRedirect(ctx, "step3",
TOADLET_URL+"?step=4");
+ super.writeTemporaryRedirect(ctx, "step5",
TOADLET_URL+"?step=5");
return;
} else if(request.isPartSet("networkF")) {
StringBuffer sb = new StringBuffer();
// prevent the user from locking himself out
- sb.append("127.0.0.1,0:0:0:0:0:0:0:1");
+ sb.append("127.0.0.1");
short ifCount = 0;
+ boolean hasIPV6 = false;
Enumeration interfaces =
NetworkInterface.getNetworkInterfaces();
while(interfaces.hasMoreElements()) {
@@ -255,6 +298,9 @@
Enumeration ipAddresses =
currentIF.getInetAddresses();
while(ipAddresses.hasMoreElements()) {
InetAddress currentInetAddress =
(InetAddress) ipAddresses.nextElement();
+ if(currentInetAddress instanceof
Inet6Address)
+ hasIPV6 = true;
+
if((currentInetAddress == null) ||
(currentInetAddress.isLoopbackAddress())) continue;
String isIFSelected
=request.getPartAsString(Base64.encode(currentInetAddress.getAddress()), 255);
@@ -266,6 +312,9 @@
}
}
+ if(hasIPV6)
+ sb.append(",0:0:0:0:0:0:0:1");
+
if(ifCount > 0) {
try {
// Java doesn't provide a way to get
the netmask : workaround and bind only to trusted if
@@ -284,7 +333,7 @@
}
}
- super.writeTemporaryRedirect(ctx, "step4",
TOADLET_URL+"?step=5");
+ super.writeTemporaryRedirect(ctx, "step6",
TOADLET_URL+"?step=6");
return;
}
Modified: branches/freenet-jfk/src/freenet/clients/http/HTTPRequestImpl.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/HTTPRequestImpl.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/HTTPRequestImpl.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -375,10 +375,11 @@
* params, whereas if it is multipart/form-data it will be separated
into buckets.
*/
private void parseMultiPartData() throws IOException {
+ boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
if(data == null) return;
String ctype = (String) this.headers.get("content-type");
if (ctype == null) return;
- if(Logger.shouldLog(Logger.MINOR, this))
+ if(logMINOR)
Logger.minor(this, "Uploaded content-type: "+ctype);
String[] ctypeparts = ctype.split(";");
if(ctypeparts[0].equalsIgnoreCase("application/x-www-form-urlencoded")) {
@@ -408,6 +409,9 @@
boundary = "--"+boundary;
+ if(logMINOR)
+ Logger.minor(this, "Boundary is: "+boundary);
+
InputStream is = this.data.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is, 32768);
LineReadingInputStream lis = new LineReadingInputStream(bis);
@@ -487,8 +491,12 @@
// offset bytes matched, but no more
// write the bytes that matched, then
the non-matching byte
bbos.write(bbound, 0, offset);
- bbos.write((int) b & 0xff);
offset = 0;
+ if(b == bbound[0]) {
+ offset = 1;
+ } else {
+ bbos.write((int) b & 0xff);
+ }
} else {
bbos.write((int) b & 0xff);
}
@@ -497,7 +505,7 @@
bbos.close();
parts.put(name, filedata);
- if(Logger.shouldLog(Logger.MINOR, this))
+ if(logMINOR)
Logger.minor(this, "Name = "+name+" length =
"+filedata.size()+" filename = "+filename);
if (filename != null) {
uploadedFiles.put(name, new
HTTPUploadedFileImpl(filename, contentType, filedata));
Copied: branches/freenet-jfk/src/freenet/clients/http/LinkEnabledCallback.java
(from rev 14796,
trunk/freenet/src/freenet/clients/http/LinkEnabledCallback.java)
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/LinkEnabledCallback.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/clients/http/LinkEnabledCallback.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,8 @@
+package freenet.clients.http;
+
+public interface LinkEnabledCallback {
+
+ /** Whether to show the link? */
+ boolean isEnabled();
+
+}
Modified:
branches/freenet-jfk/src/freenet/clients/http/LocalFileInsertToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/LocalFileInsertToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/LocalFileInsertToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -140,7 +140,7 @@
ulNode.addChild("li", l10n("checkPathReadable"));
}
- writeReply(toadletContext, 200, "text/html; charset=utf-8",
"OK", pageNode.generate());
+ writeHTMLReply(toadletContext, 200, "OK", pageNode.generate());
}
private String l10n(String key, String pattern, String value) {
Modified: branches/freenet-jfk/src/freenet/clients/http/N2NTMToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/N2NTMToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/N2NTMToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -10,36 +10,25 @@
import java.util.Iterator;
import freenet.client.HighLevelSimpleClient;
-import freenet.io.comm.DMT;
-import freenet.io.comm.Message;
-import freenet.io.comm.NotConnectedException;
-import freenet.io.comm.UdpSocketManager;
import freenet.l10n.L10n;
+import freenet.node.DarknetPeerNode;
import freenet.node.Node;
import freenet.node.NodeClientCore;
import freenet.node.PeerManager;
-import freenet.node.PeerNode;
-import freenet.support.Base64;
import freenet.support.HTMLNode;
import freenet.support.Logger;
import freenet.support.MultiValueTable;
-import freenet.support.SimpleFieldSet;
import freenet.support.api.HTTPRequest;
public class N2NTMToadlet extends Toadlet {
-
private Node node;
-
private NodeClientCore core;
- private UdpSocketManager usm;
-
protected N2NTMToadlet(Node n, NodeClientCore core,
HighLevelSimpleClient client) {
super(client);
this.node = n;
this.core = core;
- this.usm = n.getUSM();
}
public String supportedMethods() {
@@ -72,7 +61,7 @@
// ignore here, handle below
}
if (input_hashcode != -1) {
- PeerNode[] peerNodes =
node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
for (int i = 0; i < peerNodes.length; i++) {
int peer_hashcode =
peerNodes[i].hashCode();
if (peer_hashcode == input_hashcode) {
@@ -85,14 +74,14 @@
contentNode.addChild(createPeerInfobox("infobox-error",
l10n("peerNotFoundTitle"),
l10n("peerNotFoundWithHash",
"hash",
input_hashcode_string)));
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode
+ this.writeHTMLReply(ctx, 200, "OK", pageNode
.generate());
return;
}
HashMap peers = new HashMap();
peers.put(input_hashcode_string, peernode_name);
createN2NTMSendForm(pageNode, contentNode, ctx, peers);
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
}
MultiValueTable headers = new MultiValueTable();
@@ -146,7 +135,7 @@
String message = request.getPartAsString("message", 5 *
1024);
message = message.trim();
if (message.length() > 1024) {
- this.writeReply(ctx, 400, "text/plain",
l10n("tooLongTitle"),
+ this.writeTextReply(ctx, 400, "Bad request",
l10n("tooLong"));
return;
}
@@ -155,15 +144,15 @@
HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
HTMLNode peerTableInfobox = contentNode.addChild("div",
"class",
"infobox infobox-normal");
- PeerNode[] peerNodes = node.getDarknetConnections();
+ DarknetPeerNode[] peerNodes =
node.getDarknetConnections();
String fnam = request.getPartAsString("filename", 1024);
File filename = null;
- if(fnam != null) {
+ if(fnam != null && fnam.length() > 0) {
filename = new File(fnam);
if(!(filename.exists() && filename.canRead())) {
peerTableInfobox.addChild("#",
l10n("noSuchFileOrCannotRead"));
Toadlet.addHomepageLink(peerTableInfobox);
- this.writeReply(ctx, 400, "text/html",
"OK", pageNode.generate());
+ this.writeHTMLReply(ctx, 400, "OK",
pageNode.generate());
return;
}
}
@@ -174,7 +163,7 @@
peerTableHeaderRow.addChild("th", l10n("sendStatus"));
for (int i = 0; i < peerNodes.length; i++) {
if (request.isPartSet("node_" +
peerNodes[i].hashCode())) {
- PeerNode pn = peerNodes[i];
+ DarknetPeerNode pn = peerNodes[i];
int status;
@@ -184,7 +173,7 @@
} catch (IOException e) {
peerTableInfobox.addChild("#", l10n("noSuchFileOrCannotRead"));
Toadlet.addHomepageLink(peerTableInfobox);
- this.writeReply(ctx,
400, "text/html", "OK", pageNode.generate());
+
this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
return;
}
} else {
@@ -234,7 +223,7 @@
list.addChild("li").addChild("a", new String[] {
"href", "title" },
new String[] { "/friends/",
l10n("returnToFriends") },
l10n("friends"));
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
}
MultiValueTable headers = new MultiValueTable();
Copied:
branches/freenet-jfk/src/freenet/clients/http/OpennetConnectionsToadlet.java
(from rev 14796,
trunk/freenet/src/freenet/clients/http/OpennetConnectionsToadlet.java)
===================================================================
---
branches/freenet-jfk/src/freenet/clients/http/OpennetConnectionsToadlet.java
(rev 0)
+++
branches/freenet-jfk/src/freenet/clients/http/OpennetConnectionsToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,83 @@
+package freenet.clients.http;
+
+import freenet.client.HighLevelSimpleClient;
+import freenet.l10n.L10n;
+import freenet.node.Node;
+import freenet.node.NodeClientCore;
+import freenet.node.PeerNodeStatus;
+import freenet.support.HTMLNode;
+import freenet.support.SimpleFieldSet;
+
+public class OpennetConnectionsToadlet extends ConnectionsToadlet implements
LinkEnabledCallback {
+
+ protected OpennetConnectionsToadlet(Node n, NodeClientCore core,
HighLevelSimpleClient client) {
+ super(n, core, client);
+ }
+
+ protected void drawNameColumn(HTMLNode peerRow,
+ PeerNodeStatus peerNodeStatus) {
+ // Do nothing - no names on opennet
+ }
+
+ protected void drawPrivateNoteColumn(HTMLNode peerRow,
+ PeerNodeStatus peerNodeStatus, boolean
fProxyJavascriptEnabled) {
+ // Do nothing - no private notes either (no such thing as
negative trust in cyberspace)
+ }
+
+ protected boolean hasNameColumn() {
+ return false;
+ }
+
+ protected boolean hasPrivateNoteColumn() {
+ return false;
+ }
+
+ protected SimpleFieldSet getNoderef() {
+ return node.exportOpennetPublicFieldSet();
+ }
+
+ protected PeerNodeStatus[] getPeerNodeStatuses() {
+ return node.peers.getOpennetPeerNodeStatuses();
+ }
+
+ public boolean isEnabled() {
+ return node.isOpennetEnabled();
+ }
+
+ protected String getPageTitle(String titleCountString, String myName) {
+ return L10n.getString("OpennetConnectionsToadlet.fullTitle",
new String[] { "counts", "name" }, new String[] { titleCountString,
node.getMyName() } );
+ }
+
+ protected boolean shouldDrawNoderefBox(boolean advancedModeEnabled) {
+ // Developers may want to see the noderef.
+ // Users as well until the announcement protocol is implemented
+ return true;
+ }
+
+ protected boolean showPeerActionsBox() {
+ // No per-peer actions supported on opennet - there's no point,
they'll only reconnect,
+ // possibly as a different identity. And we don't want to be
able to send N2NTM spam either.
+ return false;
+ }
+
+ protected void drawPeerActionSelectBox(HTMLNode peerForm, boolean
advancedModeEnabled) {
+ // Do nothing, see showPeerActionsBox().
+ }
+
+ protected String getPeerListTitle() {
+ return
L10n.getString("OpennetConnectionsToadlet.peersListTitle");
+ }
+
+ protected boolean acceptRefPosts() {
+ return true;
+ }
+
+ protected String defaultRedirectLocation() {
+ return "/opennet/";
+ }
+
+ protected boolean isOpennet() {
+ return true;
+ }
+
+}
Modified: branches/freenet-jfk/src/freenet/clients/http/PageMaker.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/PageMaker.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/PageMaker.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -32,6 +32,7 @@
private final Map navigationLinkTitles = new HashMap();
private final Map navigationLinks = new HashMap();
private final Map contentNodes = new HashMap();
+ private final Map /* <String, LinkEnabledCallback> */
navigationLinkCallbacks = new HashMap();
/** Cache for themes read from the JAR file. */
private List jarThemesCache = null;
@@ -56,12 +57,14 @@
}
}
- public void addNavigationLink(String path, String name, String title,
boolean fullOnly) {
+ public void addNavigationLink(String path, String name, String title,
boolean fullOnly, LinkEnabledCallback cb) {
navigationLinkTexts.add(name);
if(!fullOnly)
navigationLinkTextsNonFull.add(name);
navigationLinkTitles.put(name, title);
navigationLinks.put(name, path);
+ if(cb != null)
+ navigationLinkCallbacks.put(name, cb);
}
public void removeNavigationLink(String name) {
@@ -109,10 +112,12 @@
HTMLNode navbarUl = navbarDiv.addChild("ul", "id",
"navlist");
for (Iterator navigationLinkIterator = fullAccess ?
navigationLinkTexts.iterator() : navigationLinkTextsNonFull.iterator();
navigationLinkIterator.hasNext();) {
String navigationLink = (String)
navigationLinkIterator.next();
+ LinkEnabledCallback cb = (LinkEnabledCallback)
navigationLinkCallbacks.get(navigationLink);
+ if(cb != null && !cb.isEnabled()) continue;
String navigationTitle = (String)
navigationLinkTitles.get(navigationLink);
String navigationPath = (String)
navigationLinks.get(navigationLink);
HTMLNode listItem = navbarUl.addChild("li");
- listItem.addChild("a", new String[] { "href",
"title" }, new String[] { navigationPath, navigationTitle }, navigationLink);
+ listItem.addChild("a", new String[] { "href",
"title" }, new String[] { navigationPath, L10n.getString(navigationTitle) },
L10n.getString(navigationLink));
}
}
HTMLNode contentDiv = pageDiv.addChild("div", "id", "content");
Modified: branches/freenet-jfk/src/freenet/clients/http/PluginToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/PluginToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/PluginToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -73,11 +73,11 @@
if (plugin instanceof HttpPlugin) {
((HttpPlugin)
plugin).handleGet(httpRequest, ctx);
} else {
- writeReply(ctx, 220, "text/html;
charset=utf-8", "OK", createBox(ctx, l10n("noWebInterfaceTitle"),
l10n("noWebInterface")).toString());
+ writeHTMLReply(ctx, 220, "OK",
createBox(ctx, l10n("noWebInterfaceTitle"), l10n("noWebInterface")).toString());
}
return;
}
- writeReply(ctx, 220, "text/html; charset=utf-8", "OK",
createBox(ctx, l10n("pluginNotFoundTitle"), l10n("pluginNotFound")).toString());
+ writeHTMLReply(ctx, 220, "OK", createBox(ctx,
l10n("pluginNotFoundTitle"), l10n("pluginNotFound")).toString());
return;
}
@@ -96,10 +96,10 @@
if ("list".equals(action)) {
replyBuffer.append(listPlugins(ctx));
} else {
- writeReply(ctx, 220, "text/html; charset=utf-8", "OK",
createBox(ctx, l10n("unsupportedMethodTitle"),
l10n("unsupportedMethod")).toString());
+ writeHTMLReply(ctx, 220, "OK", createBox(ctx,
l10n("unsupportedMethodTitle"), l10n("unsupportedMethod")).toString());
return;
}
- writeReply(ctx, 220, "text/html; charset=utf-8", "OK",
replyBuffer.toString());
+ writeHTMLReply(ctx, 220, "OK", replyBuffer.toString());
}
private String l10n(String key) {
@@ -119,11 +119,11 @@
if (plugin instanceof HttpPlugin) {
((HttpPlugin)
plugin).handlePost(httpRequest, ctx);
} else {
- writeReply(ctx, 220, "text/html;
charset=utf-8", "OK", createBox(ctx, l10n("noWebInterfaceTitle"),
l10n("noWebInterface")).toString());
+ writeHTMLReply(ctx, 220, "OK",
createBox(ctx, l10n("noWebInterfaceTitle"), l10n("noWebInterface")).toString());
}
return;
}
- writeReply(ctx, 220, "text/html; charset=utf-8", "OK",
createBox(ctx, l10n("pluginNotFoundTitle") ,
l10n("pluginNotFound")).toString());
+ writeHTMLReply(ctx, 220, "OK", createBox(ctx,
l10n("pluginNotFoundTitle") , l10n("pluginNotFound")).toString());
return;
}
@@ -149,6 +149,7 @@
StringBuffer replyBuffer = new StringBuffer();
if ("add".equals(action)) {
pluginName = httpRequest.getPartAsString("pluginName",
MAX_PLUGIN_NAME_LENGTH);
+
boolean added = false;
try {
pluginManager.addPlugin(pluginName, true);
@@ -176,7 +177,7 @@
writePermanentRedirect(ctx, l10n("pluginList"),
"?action=list");
return;
}
- writeReply(ctx, 220, "text/html; charset=utf-8", "OK",
replyBuffer.toString());
+ writeHTMLReply(ctx, 220, "OK", replyBuffer.toString());
}
/**
@@ -227,7 +228,7 @@
tableRow.addChild("td", plugin.getPluginName());
tableRow.addChild("td", internalName);
if (plugin instanceof HttpPlugin) {
- tableRow.addChild("td").addChild("form", new
String[] { "action", "method", "target" }, new String[] { internalName, "get",
"_new" }).addChild("input", new String[] { "type", "value" }, new String[] {
"submit", l10n("visit") });
+ tableRow.addChild("td").addChild("form", new
String[] { "action", "method", "target" }, new String[] { internalName, "get",
"_new" }).addChild("div").addChild("input", new String[] { "type", "value" },
new String[] { "submit", l10n("visit") });
} else {
tableRow.addChild("td");
}
Modified: branches/freenet-jfk/src/freenet/clients/http/PproxyToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/PproxyToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/PproxyToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -7,6 +7,7 @@
import freenet.client.HighLevelSimpleClient;
import freenet.l10n.L10n;
+import freenet.node.Node;
import freenet.node.NodeClientCore;
import freenet.pluginmanager.AccessDeniedPluginHTTPException;
import freenet.pluginmanager.DownloadPluginHTTPException;
@@ -22,12 +23,12 @@
public class PproxyToadlet extends Toadlet {
private static final int MAX_PLUGIN_NAME_LENGTH = 1024;
- private final PluginManager pm;
+ private final Node node;
private final NodeClientCore core;
- public PproxyToadlet(HighLevelSimpleClient client, PluginManager pm,
NodeClientCore core) {
+ public PproxyToadlet(HighLevelSimpleClient client, Node node,
NodeClientCore core) {
super(client);
- this.pm = pm;
+ this.node = node;
this.core = core;
}
@@ -61,6 +62,8 @@
if(Logger.shouldLog(Logger.MINOR, this)) Logger.minor(this,
"Pproxy received POST on "+path);
+ PluginManager pm = node.pluginManager;
+
if(path.length()>0)
{
try
@@ -77,28 +80,28 @@
plugin = path.substring(0, to);
}
- writeReply(ctx, 200, "text/html", "OK",
pm.handleHTTPPost(plugin, request));
+ writeHTMLReply(ctx, 200, "OK",
pm.handleHTTPPost(plugin, request));
}
catch (RedirectPluginHTTPException e) {
writeTemporaryRedirect(ctx, e.message,
e.newLocation);
}
catch (NotFoundPluginHTTPException e) {
- sendErrorPage(ctx, e.code, e.message,
e.location);
+ sendErrorPage(ctx,
NotFoundPluginHTTPException.code, e.message, e.location);
}
catch (AccessDeniedPluginHTTPException e) {
- sendErrorPage(ctx, e.code, e.message,
e.location);
+ sendErrorPage(ctx,
AccessDeniedPluginHTTPException.code, e.message, e.location);
}
catch (DownloadPluginHTTPException e) {
// FIXME: maybe it ought to be defined like
sendErrorPage : in toadlets
MultiValueTable head = new MultiValueTable();
head.put("Content-Disposition", "attachment;
filename=\"" + e.filename + '"');
- ctx.sendReplyHeaders(e.code, "Found", head,
e.mimeType, e.data.length);
+
ctx.sendReplyHeaders(DownloadPluginHTTPException.CODE, "Found", head,
e.mimeType, e.data.length);
ctx.writeData(e.data);
}
catch(PluginHTTPException e)
{
- sendErrorPage(ctx, e.code, e.message,
e.location);
+ sendErrorPage(ctx, PluginHTTPException.code,
e.message, e.location);
}
catch(Throwable t)
{
@@ -130,7 +133,7 @@
infoboxContent.addChild("#",
l10n("pluginUnloadedWithName", "name", request.getPartAsString("remove",
MAX_PLUGIN_NAME_LENGTH)));
infoboxContent.addChild("br");
infoboxContent.addChild("a", "href",
"/plugins/", l10n("returnToPluginPage"));
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
}if (request.getPartAsString("unload",
MAX_PLUGIN_NAME_LENGTH).length() > 0) {
HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("plugins"), ctx);
@@ -144,7 +147,7 @@
unloadForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel") });
unloadForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "hidden", "unloadconfirm",
request.getPartAsString("unload", MAX_PLUGIN_NAME_LENGTH) });
unloadForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "confirm", l10n("unload")
});
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
}else if (request.getPartAsString("reload",
MAX_PLUGIN_NAME_LENGTH).length() > 0) {
String fn = null;
@@ -196,11 +199,13 @@
if(path.startsWith("/")) path = path.substring(1);
if(path.startsWith("plugins/")) path =
path.substring("plugins/".length());
+ PluginManager pm = node.pluginManager;
+
if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Pproxy fetching "+path);
try {
if (path.equals("")) {
- this.showPluginList(ctx, request);
+ this.showPluginList(ctx, request, pm);
} else {
// split path into plugin class name and 'data'
path for plugin
int to = path.indexOf("/");
@@ -213,7 +218,7 @@
// Plugin may need to know where it was
accessed from, so it can e.g. produce relative URLs.
//writeReply(ctx, 200, "text/html", "OK",
mkPage("plugin", pm.handleHTTPGet(plugin, data)));
- writeReply(ctx, 200, "text/html", "OK",
pm.handleHTTPGet(plugin, request));
+ writeHTMLReply(ctx, 200, "OK",
pm.handleHTTPGet(plugin, request));
}
//FetchResult result = fetch(key);
@@ -221,24 +226,24 @@
} catch (RedirectPluginHTTPException e) {
writeTemporaryRedirect(ctx, e.message, e.newLocation);
} catch (NotFoundPluginHTTPException e) {
- sendErrorPage(ctx, e.code, e.message, e.location);
+ sendErrorPage(ctx, NotFoundPluginHTTPException.code,
e.message, e.location);
} catch (AccessDeniedPluginHTTPException e) {
- sendErrorPage(ctx, e.code, e.message, e.location);
+ sendErrorPage(ctx,
AccessDeniedPluginHTTPException.code, e.message, e.location);
} catch (DownloadPluginHTTPException e) {
// FIXME: maybe it ought to be defined like
sendErrorPage : in toadlets
MultiValueTable head = new MultiValueTable();
head.put("Content-Disposition", "attachment;
filename=\"" + e.filename + '"');
- ctx.sendReplyHeaders(e.code, "Found", head, e.mimeType,
e.data.length);
+ ctx.sendReplyHeaders(DownloadPluginHTTPException.CODE,
"Found", head, e.mimeType, e.data.length);
ctx.writeData(e.data);
} catch(PluginHTTPException e) {
- sendErrorPage(ctx, e.code, e.message, e.location);
+ sendErrorPage(ctx, PluginHTTPException.code, e.message,
e.location);
} catch (Throwable t) {
writeInternalError(t, ctx);
}
}
- private void showPluginList(ToadletContext ctx, HTTPRequest request)
throws ToadletContextClosedException, IOException {
+ private void showPluginList(ToadletContext ctx, HTTPRequest request,
PluginManager pm) throws ToadletContextClosedException, IOException {
if(!ctx.isAllowedFullAccess()) {
super.sendErrorPage(ctx, 403, "Unauthorized",
L10n.getString("Toadlet.unauthorized"));
return;
@@ -289,7 +294,7 @@
loadDiv.addChild("#", (l10n("loadPluginLabel") + ' '));
loadDiv.addChild("input", new String[] { "type",
"name", "size" }, new String[] { "text", "load", "40" });
loadDiv.addChild("input", new String[] { "type",
"value" }, new String[] { "submit", "Load" });
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}
}
}
Modified: branches/freenet-jfk/src/freenet/clients/http/QueueToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/QueueToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/QueueToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -106,6 +106,7 @@
new
String[]{ "id", "message" },
new
String[]{ identifier, e.getMessage()}
));
+ return;
}
writePermanentRedirect(ctx, "Done", "/queue/");
return;
@@ -207,7 +208,10 @@
insertURI = new FreenetURI("CHK@");
} else if ("ksk".equals(keyType)) {
try {
- insertURI = new
FreenetURI(request.getPartAsString("key", 128));
+ String u =
request.getPartAsString("key", 128);
+ insertURI = new FreenetURI(u);
+ if(logMINOR)
+ Logger.minor(this,
"Inserting key: "+insertURI+" ("+u+")");
} catch (MalformedURLException mue1) {
writeError(L10n.getString("QueueToadlet.errorInvalidURI"),
L10n.getString("QueueToadlet.errorInvalidURIToU"), ctx);
return;
@@ -293,12 +297,12 @@
HTMLNode alertContent = ctx.getPageMaker().getContentNode(alertNode);
alertContent.addChild("#",
L10n.getString("QueueToadlet.warningUnsafeContentExplanation"));
HTMLNode optionListNode = alertContent.addChild("ul");
-
HTMLNode optionForm = ctx.addFormChild(optionListNode, "/queue/",
"queueDownloadNotFilteredConfirmForm");
+
HTMLNode optionForm = ctx.addFormChild(optionListNode, "/queue/",
"queueDownloadNotFilteredConfirmForm-" + identifier.hashCode());
optionForm.addChild("input", new String[] { "type", "name", "value" }, new
String[] { "hidden", "identifier", identifier });
optionForm.addChild("input", new String[] { "type", "name", "value" }, new
String[] { "hidden", "forceDownload",
String.valueOf(System.currentTimeMillis()) });
optionForm.addChild("input", new String[] { "type", "name", "value" }, new
String[] { "submit", "get", "Download anyway" });
optionForm.addChild("input", new String[] { "type", "name", "value" }, new
String[] { "submit", "return", "Return to queue page" });
-
writeReply(ctx, 200, "text/html; charset=utf-8", "OK", pageNode.generate());
+
writeHTMLReply(ctx, 200, "OK", pageNode.generate());
return;
}
}
@@ -326,7 +330,7 @@
HTMLNode infoboxContent = pageMaker.getContentNode(infobox);
infoboxContent.addChild("#", message);
infoboxContent.addChild("div").addChildren(new HTMLNode[] { new
HTMLNode("#", "Return to "), new HTMLNode("a", "href", "/queue/", "queue
page"), new HTMLNode("#", ".") });
- writeReply(context, 400, "text/html; charset=utf-8", "Error",
pageNode.generate());
+ writeHTMLReply(context, 400, "Bad request",
pageNode.generate());
}
public void handleGet(URI uri, final HTTPRequest request,
ToadletContext ctx)
@@ -396,7 +400,7 @@
HTMLNode infoboxContent =
pageMaker.getContentNode(infobox);
infoboxContent.addChild("#",
L10n.getString("QueueToadlet.noTaskOnGlobalQueue"));
contentNode.addChild(createInsertBox(pageMaker, ctx));
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK", pageNode.generate());
return;
}
@@ -578,7 +582,7 @@
boolean advancedModeEnabled = core.isAdvancedModeEnabled();
if (!completedDownloadToTemp.isEmpty()) {
- contentNode.addChild("a", "name",
"completedDownloadToTemp");
+ contentNode.addChild("a", "id",
"completedDownloadToTemp");
HTMLNode completedDownloadsTempInfobox =
contentNode.addChild(pageMaker.getInfobox("completed_requests",
L10n.getString("QueueToadlet.completedDinTempDirectory", new String[]{ "size"
}, new String[]{ String.valueOf(completedDownloadToTemp.size()) })));
HTMLNode completedDownloadsToTempContent =
pageMaker.getContentNode(completedDownloadsTempInfobox);
if (advancedModeEnabled) {
@@ -589,7 +593,7 @@
}
if (!completedDownloadToDisk.isEmpty()) {
- contentNode.addChild("a", "name",
"completedDownloadToDisk");
+ contentNode.addChild("a", "id",
"completedDownloadToDisk");
HTMLNode completedToDiskInfobox =
contentNode.addChild(pageMaker.getInfobox("completed_requests",
L10n.getString("QueueToadlet.completedDinDownloadDirectory", new String[]{
"size" }, new String[]{ String.valueOf(completedDownloadToDisk.size()) })));
HTMLNode completedToDiskInfoboxContent =
pageMaker.getContentNode(completedToDiskInfobox);
if (advancedModeEnabled) {
@@ -600,7 +604,7 @@
}
if (!completedUpload.isEmpty()) {
- contentNode.addChild("a", "name", "completedUpload");
+ contentNode.addChild("a", "id", "completedUpload");
HTMLNode completedUploadInfobox =
contentNode.addChild(pageMaker.getInfobox("completed_requests",
L10n.getString("QueueToadlet.completedU", new String[]{ "size" }, new String[]{
String.valueOf(completedUpload.size()) })));
HTMLNode completedUploadInfoboxContent =
pageMaker.getContentNode(completedUploadInfobox);
if (advancedModeEnabled) {
@@ -611,7 +615,7 @@
}
if (!completedDirUpload.isEmpty()) {
- contentNode.addChild("a", "name", "completedDirUpload");
+ contentNode.addChild("a", "id", "completedDirUpload");
HTMLNode completedUploadDirInfobox =
contentNode.addChild(pageMaker.getInfobox("completed_requests",
L10n.getString("QueueToadlet.completedUDirectory", new String[]{ "size" }, new
String[]{ String.valueOf(completedDirUpload.size()) })));
HTMLNode completedUploadDirContent =
pageMaker.getContentNode(completedUploadDirInfobox);
if (advancedModeEnabled) {
@@ -622,7 +626,7 @@
}
if (!failedDownload.isEmpty()) {
- contentNode.addChild("a", "name", "failedDownload");
+ contentNode.addChild("a", "id", "failedDownload");
HTMLNode failedInfobox =
contentNode.addChild(pageMaker.getInfobox("failed_requests",
L10n.getString("QueueToadlet.failedD", new String[]{ "size" }, new String[]{
String.valueOf(failedDownload.size()) })));
HTMLNode failedContent =
pageMaker.getContentNode(failedInfobox);
if (advancedModeEnabled) {
@@ -633,7 +637,7 @@
}
if (!failedUpload.isEmpty()) {
- contentNode.addChild("a", "name", "failedUpload");
+ contentNode.addChild("a", "id", "failedUpload");
HTMLNode failedInfobox =
contentNode.addChild(pageMaker.getInfobox("failed_requests",
L10n.getString("QueueToadlet.failedU", new String[]{ "size" }, new String[]{
String.valueOf(failedUpload.size()) })));
HTMLNode failedContent =
pageMaker.getContentNode(failedInfobox);
if (advancedModeEnabled) {
@@ -644,7 +648,7 @@
}
if (!failedDirUpload.isEmpty()) {
- contentNode.addChild("a", "name", "failedDirUpload");
+ contentNode.addChild("a", "id", "failedDirUpload");
HTMLNode failedInfobox =
contentNode.addChild(pageMaker.getInfobox("failed_requests",
L10n.getString("QueueToadlet.failedU", new String[]{ "size" }, new String[]{
String.valueOf(failedDirUpload.size()) })));
HTMLNode failedContent =
pageMaker.getContentNode(failedInfobox);
if (advancedModeEnabled) {
@@ -655,7 +659,7 @@
}
if (!uncompletedDownload.isEmpty()) {
- contentNode.addChild("a", "name",
"uncompletedDownload");
+ contentNode.addChild("a", "id", "uncompletedDownload");
HTMLNode uncompletedInfobox =
contentNode.addChild(pageMaker.getInfobox("requests_in_progress",
L10n.getString("QueueToadlet.wipD", new String[]{ "size" }, new String[]{
String.valueOf(uncompletedDownload.size()) })));
HTMLNode uncompletedContent =
pageMaker.getContentNode(uncompletedInfobox);
if (advancedModeEnabled) {
@@ -666,7 +670,7 @@
}
if (!uncompletedUpload.isEmpty()) {
- contentNode.addChild("a", "name", "uncompletedUpload");
+ contentNode.addChild("a", "id", "uncompletedUpload");
HTMLNode uncompletedInfobox =
contentNode.addChild(pageMaker.getInfobox("requests_in_progress",
L10n.getString("QueueToadlet.wipU", new String[]{ "size" }, new String[]{
String.valueOf(uncompletedUpload.size()) })));
HTMLNode uncompletedContent =
pageMaker.getContentNode(uncompletedInfobox);
if (advancedModeEnabled) {
@@ -677,7 +681,7 @@
}
if (!uncompletedDirUpload.isEmpty()) {
- contentNode.addChild("a", "name",
"uncompletedDirUpload");
+ contentNode.addChild("a", "id", "uncompletedDirUpload");
HTMLNode uncompletedInfobox =
contentNode.addChild(pageMaker.getInfobox("requests_in_progress",
L10n.getString("QueueToadlet.wipDU", new String[]{ "size" }, new String[]{
String.valueOf(uncompletedDirUpload.size()) })));
HTMLNode uncompletedContent =
pageMaker.getContentNode(uncompletedInfobox);
if (advancedModeEnabled) {
@@ -688,7 +692,7 @@
}
MultiValueTable pageHeaders = new MultiValueTable();
- this.writeReply(ctx, 200, "text/html", "OK", pageHeaders,
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK", pageHeaders,
pageNode.generate());
}
@@ -761,7 +765,7 @@
private HTMLNode createPriorityCell(PageMaker pageMaker, String
identifier, short priorityClass, ToadletContext ctx, String[] priorityClasses) {
HTMLNode priorityCell = new HTMLNode("td", "class",
"request-priority nowrap");
- HTMLNode priorityForm = ctx.addFormChild(priorityCell,
"/queue/", "queueChangePriorityCell");
+ HTMLNode priorityForm = ctx.addFormChild(priorityCell,
"/queue/", "queueChangePriorityCell-" + identifier.hashCode());
priorityForm.addChild("input", new String[] { "type", "name",
"value" }, new String[] { "hidden", "identifier", identifier });
HTMLNode prioritySelect = priorityForm.addChild("select",
"name", "priority");
for (int p = 0; p < RequestStarter.NUMBER_OF_PRIORITY_CLASSES;
p++) {
@@ -777,14 +781,14 @@
private HTMLNode createDeleteCell(PageMaker pageMaker, String
identifier, ClientRequest clientRequest, ToadletContext ctx) {
HTMLNode deleteNode = new HTMLNode("td", "class",
"request-delete");
- HTMLNode deleteForm = ctx.addFormChild(deleteNode, "/queue/",
"queueDeleteForm");
+ HTMLNode deleteForm = ctx.addFormChild(deleteNode, "/queue/",
"queueDeleteForm-" + identifier.hashCode());
deleteForm.addChild("input", new String[] { "type", "name",
"value" }, new String[] { "hidden", "identifier", identifier });
deleteForm.addChild("input", new String[] { "type", "name",
"value" }, new String[] { "submit", "remove_request",
L10n.getString("QueueToadlet.remove") });
// If it's failed, offer to restart it
if(clientRequest.hasFinished() && !clientRequest.hasSucceeded()
&& clientRequest.canRestart()) {
- HTMLNode retryForm = ctx.addFormChild(deleteNode,
"/queue/", "queueRestartForm");
+ HTMLNode retryForm = ctx.addFormChild(deleteNode,
"/queue/", "queueRestartForm-" + identifier.hashCode());
String restartName = L10n.getString(clientRequest
instanceof ClientGet && ((ClientGet)clientRequest).hasPermRedirect() ?
"QueueToadlet.follow" : "QueueToadlet.restart");
retryForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "hidden", "identifier", identifier });
retryForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "restart_request", restartName });
Modified: branches/freenet-jfk/src/freenet/clients/http/SimpleToadletServer.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/SimpleToadletServer.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/SimpleToadletServer.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -29,6 +29,7 @@
import freenet.io.NetworkInterface;
import freenet.l10n.L10n;
import freenet.node.NodeClientCore;
+import freenet.support.HTMLNode;
import freenet.support.Logger;
import freenet.support.OOMHandler;
import freenet.support.StringArray;
@@ -339,9 +340,9 @@
this.advancedModeEnabled =
fproxyConfig.getBoolean("advancedModeEnabled");
toadlets = new LinkedList();
- core.setToadletContainer(this); // even if not enabled, because
of config
- this.networkInterface = NetworkInterface.create(port,
this.bindTo, fproxyConfig.getString("allowedHosts"));
+ this.networkInterface = NetworkInterface.create(port,
this.bindTo, fproxyConfig.getString("allowedHosts"), core.getExecutor());
+
if(!enabled) {
Logger.normal(core, "Not starting FProxy as it's
disabled");
System.out.println("Not starting FProxy as it's
disabled");
@@ -349,6 +350,7 @@
myThread = new Thread(this, "SimpleToadletServer");
myThread.setDaemon(true);
}
+
}
public boolean doRobots() {
@@ -364,16 +366,16 @@
}
public void register(Toadlet t, String urlPrefix, boolean atFront,
boolean fullOnly) {
- register(t, urlPrefix, atFront, null, null, fullOnly);
+ register(t, urlPrefix, atFront, null, null, fullOnly, null);
}
- public void register(Toadlet t, String urlPrefix, boolean atFront,
String name, String title, boolean fullOnly) {
+ public void register(Toadlet t, String urlPrefix, boolean atFront,
String name, String title, boolean fullOnly, LinkEnabledCallback cb) {
ToadletElement te = new ToadletElement(t, urlPrefix);
if(atFront) toadlets.addFirst(te);
else toadlets.addLast(te);
t.container = this;
if (name != null) {
- pageMaker.addNavigationLink(urlPrefix, name, title,
fullOnly);
+ pageMaker.addNavigationLink(urlPrefix, name, title,
fullOnly, cb);
}
}
@@ -419,9 +421,7 @@
}
void start() {
- Thread t = new Thread(this,
"SimpleToadletServer$SocketHandler");
- t.setDaemon(true);
- t.start();
+ core.getExecutor().execute(this,
"SimpleToadletServer$SocketHandler@"+hashCode());
}
public void run() {
@@ -482,4 +482,14 @@
return L10n.getString("SimpleToadletServer."+key);
}
+ public HTMLNode addFormChild(HTMLNode parentNode, String target, String
id) {
+ HTMLNode formNode =
+ parentNode.addChild("form", new String[] { "action",
"method", "enctype", "id", "accept-charset" },
+ new String[] { target, "post",
"multipart/form-data", id, "utf-8"} ).addChild("div");
+ formNode.addChild("input", new String[] { "type", "name",
"value" },
+ new String[] { "hidden", "formPassword",
getFormPassword() });
+
+ return formNode;
+ }
+
}
Modified: branches/freenet-jfk/src/freenet/clients/http/StatisticsToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/StatisticsToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/StatisticsToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -16,6 +16,7 @@
import freenet.config.SubConfig;
import freenet.io.comm.IOStatisticCollector;
import freenet.l10n.L10n;
+import freenet.node.Location;
import freenet.node.Node;
import freenet.node.NodeClientCore;
import freenet.node.NodeStarter;
@@ -121,7 +122,7 @@
if (statusDifference != 0) {
return statusDifference;
}
- return
firstNode.getName().compareToIgnoreCase(secondNode.getName());
+ return 0;
}
});
@@ -288,7 +289,7 @@
addNodeCircle(nodeCircleTable);
}
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}
private void drawRejectReasonsBox(HTMLNode nextTableCell) {
@@ -410,7 +411,7 @@
"\u00a0(" + ((storeHits*100) /
(storeAccesses)) + "%)");
storeSizeList.addChild("li",
- "Avg. access rate:\u00a0" +
thousendPoint.format(overallAccesses/nodeUptimeSeconds) + "/s");
+ "Avg. access rate:\u00a0" +
thousendPoint.format(overallAccesses/nodeUptimeSeconds) + "/sec");
}
@@ -870,7 +871,7 @@
for (int peerIndex = 0; peerIndex < peerCount; peerIndex++) {
peerNodeStatus = peerNodeStatuses[peerIndex];
peerLocation = peerNodeStatus.getLocation();
- peerDistance = PeerManager.distance( myLocation,
peerLocation );
+ peerDistance = Location.distance( myLocation,
peerLocation );
histogramIndex = (int) (Math.floor(peerDistance *
HISTOGRAM_LENGTH * 2));
if (peerNodeStatus.isConnected()) {
histogramConnected[histogramIndex]++;
Modified: branches/freenet-jfk/src/freenet/clients/http/SymlinkerToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/SymlinkerToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/SymlinkerToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -118,7 +118,7 @@
// TODO redirect to errorpage
if ((foundtarget == null) || (foundkey == null)) {
- writeReply(ctx, 404, "text/html",
L10n.getString("StaticToadlet.pathNotFoundTitle"),
+ writeTextReply(ctx, 404, "Not found",
L10n.getString("StaticToadlet.pathNotFound"));
return;
}
@@ -130,7 +130,7 @@
path, uri.getQuery(), uri.getFragment());
} catch (URISyntaxException e) {
// TODO Handle error somehow
- writeReply(ctx, 200, "text/html", "OK", e.getMessage());
+ writeHTMLReply(ctx, 200, "OK", e.getMessage());
return;
}
Modified: branches/freenet-jfk/src/freenet/clients/http/Toadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/Toadlet.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/Toadlet.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -147,6 +147,22 @@
writeReply(ctx, code, mimeType, desc, null, reply);
}
+ protected void writeHTMLReply(ToadletContext ctx, int code, String
desc, String reply) throws ToadletContextClosedException, IOException {
+ writeReply(ctx, code, "text/html; charset=utf-8", desc, null,
reply);
+ }
+
+ protected void writeTextReply(ToadletContext ctx, int code, String
desc, String reply) throws ToadletContextClosedException, IOException {
+ writeReply(ctx, code, "text/plain; charset=utf-8", desc, null,
reply);
+ }
+
+ protected void writeHTMLReply(ToadletContext ctx, int code, String
desc, MultiValueTable headers, String reply) throws
ToadletContextClosedException, IOException {
+ writeReply(ctx, code, "text/html; charset=utf-8", desc,
headers, reply);
+ }
+
+ protected void writeTextReply(ToadletContext ctx, int code, String
desc, MultiValueTable headers, String reply) throws
ToadletContextClosedException, IOException {
+ writeReply(ctx, code, "text/plain; charset=utf-8", desc,
headers, reply);
+ }
+
protected void writeReply(ToadletContext context, int code, String
mimeType, String desc, MultiValueTable headers, String reply) throws
ToadletContextClosedException, IOException {
byte[] buffer = reply.getBytes("UTF-8");
writeReply(context, code, mimeType, desc, headers, buffer, 0,
buffer.length);
@@ -219,7 +235,7 @@
infoboxContent.addChild("a", "href", ".",
l10n("returnToPrevPage"));
addHomepageLink(infoboxContent);
- writeReply(ctx, code, "text/html; charset=UTF-8", desc,
pageNode.generate());
+ writeHTMLReply(ctx, code, desc, pageNode.generate());
}
/**
@@ -250,7 +266,7 @@
infoboxContent.addChild("a", "href", ".",
l10n("returnToPrevPage"));
addHomepageLink(infoboxContent);
- writeReply(ctx, 500, "text/html; charset=UTF-8", desc,
pageNode.generate());
+ writeHTMLReply(ctx, 500, desc, pageNode.generate());
}
protected void writeInternalError(Throwable t, ToadletContext ctx)
throws ToadletContextClosedException, IOException {
@@ -262,7 +278,7 @@
t.printStackTrace(pw);
pw.flush();
msg = msg + sw.toString() + "</pre></body></html>";
- writeReply(ctx, 500, "text/html", "Internal Error", msg);
+ writeHTMLReply(ctx, 500, "Internal Error", msg);
}
protected static void addHomepageLink(HTMLNode content) {
Modified: branches/freenet-jfk/src/freenet/clients/http/ToadletContainer.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/ToadletContainer.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/ToadletContainer.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -6,6 +6,8 @@
import java.net.InetAddress;
import java.net.URI;
+import freenet.support.HTMLNode;
+
/** Interface for toadlet containers. Toadlets should register here. */
public interface ToadletContainer {
@@ -36,4 +38,6 @@
/** Whether to tell spiders to go away */
public boolean doRobots();
+
+ public HTMLNode addFormChild(HTMLNode parentNode, String target, String
name);
}
Modified: branches/freenet-jfk/src/freenet/clients/http/ToadletContextImpl.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/ToadletContextImpl.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/ToadletContextImpl.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,5 +1,6 @@
package freenet.clients.http;
+import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -214,7 +215,7 @@
*/
public static void handle(Socket sock, ToadletContainer container,
BucketFactory bf, PageMaker pageMaker) {
try {
- InputStream is = sock.getInputStream();
+ InputStream is = new
BufferedInputStream(sock.getInputStream(), 4096);
LineReadingInputStream lis = new
LineReadingInputStream(is);
@@ -372,6 +373,8 @@
} catch (ToadletContextClosedException e) {
Logger.error(ToadletContextImpl.class,
"ToadletContextClosedException while handling connection!");
return;
+ } catch (Throwable t) {
+ Logger.error(ToadletContextImpl.class, "Caught error:
"+t+" handling socket", t);
}
}
@@ -425,13 +428,7 @@
}
public HTMLNode addFormChild(HTMLNode parentNode, String target, String
name) {
- HTMLNode formNode =
- parentNode.addChild("form", new String[] { "action",
"method", "enctype", "id", "name", "accept-charset" },
- new String[] { target, "post",
"multipart/form-data", name, name, "utf-8"} );
- formNode.addChild("input", new String[] { "type", "name",
"value" },
- new String[] { "hidden", "formPassword",
container.getFormPassword() });
-
- return formNode;
+ return container.addFormChild(parentNode, target, name);
}
public boolean isAllowedFullAccess() {
Modified: branches/freenet-jfk/src/freenet/clients/http/TranslationToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/TranslationToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/TranslationToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -83,7 +83,7 @@
footer.addChild("%", " ");
footer.addChild("a", "href", TOADLET_URL +
(showEverything ? "" : "?toTranslateOnly")).addChild("#",
l10n("returnToTranslations"));
- this.writeReply(ctx, 200, "text/html; charset=utf-8",
"OK", pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
} else if (request.isParameterSet("translate")) {
String key = request.getParam("translate");
@@ -126,7 +126,7 @@
updateForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "hidden", "toTranslateOnly", key });
updateForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel") });
- this.writeReply(ctx, 200, "text/html; charset=utf-8",
"OK", pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
} else if (request.isParameterSet("remove")) {
String key = request.getParam("remove");
@@ -145,7 +145,7 @@
removeForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "remove_confirmed", l10n("remove")
});
removeForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel") });
- this.writeReply(ctx, 200, "text/html; charset=utf-8",
"OK", pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
}
@@ -188,7 +188,7 @@
}
}
- this.writeReply(ctx, 200, "text/html; charset=utf-8", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}
public void handlePost(URI uri, HTTPRequest request, ToadletContext
ctx) throws ToadletContextClosedException, IOException {
Modified: branches/freenet-jfk/src/freenet/clients/http/TrivialToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/TrivialToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/TrivialToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -19,7 +19,7 @@
String reply = "<html><head><title>You requested "+encFetched+
"</title></head><body>You fetched <a
href=\""+encFetched+"\">"+
encFetched+"</a>.</body></html>";
- this.writeReply(ctx, 200, "text/html", "OK", reply);
+ this.writeHTMLReply(ctx, 200, "OK", reply);
}
public String supportedMethods() {
Modified: branches/freenet-jfk/src/freenet/clients/http/WelcomeToadlet.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/WelcomeToadlet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/WelcomeToadlet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -47,10 +47,10 @@
final Node node;
final BookmarkManager bookmarkManager;
- WelcomeToadlet(HighLevelSimpleClient client, Node node) {
+ WelcomeToadlet(HighLevelSimpleClient client, NodeClientCore core, Node
node) {
super(client);
this.node = node;
- this.core = node.clientCore;
+ this.core = core;
this.bookmarkManager = core.bookmarkManager;
try {
manageBookmarksURI = new
URI("/welcome/?managebookmarks");
@@ -109,7 +109,7 @@
HTMLNode content =
ctx.getPageMaker().getContentNode(infobox);
content.addChild("p").addChild("#", l10n("updating"));
content.addChild("p").addChild("#", l10n("thanks"));
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK", pageNode.generate());
Logger.normal(this, "Node is updating/restarting");
node.getNodeUpdater().arm();
}else if
(request.getPartAsString(GenericReadFilterCallback.magicHTTPEscapeString,
MAX_URL_LENGTH).length()>0){
@@ -132,7 +132,7 @@
HTMLNode updateForm = ctx.addFormChild(content, "/",
"updateConfirmForm");
updateForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel")});
updateForm.addChild("input", new String[] { "type",
"name", "value" }, new String[] { "submit", "updateconfirm", l10n("update") });
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}else if(request.isPartSet("getThreadDump")) {
if(noPassword) {
redirectToRoot(ctx);
@@ -149,7 +149,7 @@
HTMLNode infobox =
contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-error",l10n("threadDumpSubTitle")));
ctx.getPageMaker().getContentNode(infobox).addChild("#",
l10n("threadDumpNotUsingWrapper"));
}
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
}else if(request.isPartSet("getJEStatsDump")) {
if(noPassword) {
redirectToRoot(ctx);
@@ -164,7 +164,7 @@
System.out.println(">>>>>>>>>>>>>>>>>>>>>>> END
DATABASE STATS <<<<<<<<<<<<<<<<<<<<<<<");
ctx.getPageMaker().getContentNode(infobox).addChild("#",
l10n("writtenDatabaseStats"));
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
}else if(request.isPartSet("disable")){
if(noPassword) {
redirectToRoot(ctx);
@@ -183,10 +183,10 @@
Logger.normal(this,"Disabling
the userAlert "+alert.hashCode());
alert.isValid(false);
}
-
- writePermanentRedirect(ctx,
l10n("disabledAlert"), "/");
}
}
+ writePermanentRedirect(ctx, l10n("disabledAlert"), "/");
+ return;
} else
if(request.isPartSet("boardname")&&(request.isPartSet("filename")||request.isPartSet("message")))
{
// Inserting into a frost board FIN
// boardname
@@ -239,7 +239,7 @@
postForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel") });
postForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "finconfirm", l10n("post")
});
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
}
@@ -282,7 +282,7 @@
content.addChild("br");
addHomepageLink(content);
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK", pageNode.generate());
request.freeParts();
}else
if(request.isPartSet("key")&&request.isPartSet("filename")){
if(noPassword) {
@@ -335,7 +335,7 @@
content.addChild("br");
addHomepageLink(content);
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK", pageNode.generate());
request.freeParts();
bucket.free();
}else if (request.isPartSet("shutdownconfirm")) {
@@ -413,7 +413,7 @@
while((read = reader.read(buffer)) != -1)
sw.write(buffer, 0, read);
- this.writeReply(ctx, 200, "text/plain", "OK",
sw.toString());
+ this.writeHTMLReply(ctx, 200, "OK",
sw.toString());
return;
} else if (request.isParameterSet("terminated")) {
if((!request.isParameterSet("formPassword")) ||
!request.getParam("formPassword").equals(core.formPassword)) {
@@ -426,7 +426,7 @@
HTMLNode infobox =
contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-information",
l10n("shutdownDone")));
HTMLNode infoboxContent =
ctx.getPageMaker().getContentNode(infobox);
infoboxContent.addChild("#", l10n("thanks"));
- this.writeReply(ctx, 200, "text/html;
charset=utf-8", "OK", pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
} else if (request.isParameterSet("restarted")) {
if((!request.isParameterSet("formPassword")) ||
!request.getParam("formPassword").equals(core.formPassword)) {
@@ -439,7 +439,7 @@
HTMLNode infobox =
contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-information",
l10n("restartingTitle")));
HTMLNode infoboxContent =
ctx.getPageMaker().getContentNode(infobox);
infoboxContent.addChild("#",
l10n("restarting"));
- writeReply(ctx, 200, "text/html;
charset=utf-8", "OK", pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
Logger.normal(this, "Node is restarting");
return;
} else if (request.getParam("newbookmark").length() >
0) {
@@ -457,7 +457,7 @@
addForm.addChild("input", new String[]
{"type", "name", "value"}, new String[] {"hidden", "bookmark", "/"});
addForm.addChild("input", new String[] {"type",
"name", "value"}, new String[] {"hidden", "action", "addItem"});
addForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "addbookmark",
L10n.getString("BookmarkEditorToadlet.addBookmark") });
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
} else if
(request.getParam(GenericReadFilterCallback.magicHTTPEscapeString).length() >
0) {
HTMLNode pageNode =
ctx.getPageMaker().getPageNode( l10n("confirmExternalLinkTitle"), ctx);
@@ -471,7 +471,7 @@
externalLinkForm.addChild("input", new String[]
{ "type", "name", "value" }, new String[] { "hidden",
GenericReadFilterCallback.magicHTTPEscapeString, target });
externalLinkForm.addChild("input", new String[]
{ "type", "name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel") });
externalLinkForm.addChild("input", new String[]
{ "type", "name", "value" }, new String[] { "submit", "Go",
l10n("goToExternalLink") });
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
} else if (request.isParameterSet("exit")) {
HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("shutdownConfirmTitle"), ctx);
@@ -482,7 +482,7 @@
HTMLNode shutdownForm =
ctx.addFormChild(content.addChild("p"), "/", "confirmShutdownForm");
shutdownForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel") });
shutdownForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "shutdownconfirm",
l10n("shutdown") });
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
}else if (request.isParameterSet("restart")) {
HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("restartConfirmTitle"), ctx);
@@ -493,7 +493,7 @@
HTMLNode restartForm =
ctx.addFormChild(content.addChild("p"), "/", "confirmRestartForm");
restartForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "cancel",
L10n.getString("Toadlet.cancel") });
restartForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "restartconfirm",
l10n("restart") });
- writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
return;
}
}
@@ -526,8 +526,8 @@
HTMLNode fetchKeyBox =
contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-normal",
l10n("fetchKeyLabel")));
HTMLNode fetchKeyContent =
ctx.getPageMaker().getContentNode(fetchKeyBox);
fetchKeyContent.addAttribute("id", "keyfetchbox");
- HTMLNode fetchKeyForm = fetchKeyContent.addChild("form", new
String[] { "action", "method" }, new String[] { "/", "get" });
- fetchKeyForm.addChild("#", "Key: ");
+ HTMLNode fetchKeyForm = fetchKeyContent.addChild("form", new
String[] { "action", "method" }, new String[] { "/", "get" }).addChild("div");
+ fetchKeyForm.addChild("#", l10n("keyRequestLabel")+' ');
fetchKeyForm.addChild("input", new String[] { "type", "size",
"name" }, new String[] { "text", "80", "key" });
fetchKeyForm.addChild("input", new String[] { "type", "value"
}, new String[] { "submit", l10n("fetch") });
@@ -563,11 +563,11 @@
}
versionContent.addChild("br");
if(ctx.isAllowedFullAccess()){
- HTMLNode shutdownForm = versionContent.addChild("form",
new String[] { "action", "method" }, new String[] { ".", "get" });
+ HTMLNode shutdownForm = versionContent.addChild("form",
new String[] { "action", "method" }, new String[] { ".", "get"
}).addChild("div");
shutdownForm.addChild("input", new String[] { "type",
"name" }, new String[] { "hidden", "exit" });
shutdownForm.addChild("input", new String[] { "type",
"value" }, new String[] { "submit", l10n("shutdownNode") });
if(node.isUsingWrapper()){
- HTMLNode restartForm =
versionContent.addChild("form", new String[] { "action", "method" }, new
String[] { ".", "get" });
+ HTMLNode restartForm =
versionContent.addChild("form", new String[] { "action", "method" }, new
String[] { ".", "get" }).addChild("div");
restartForm.addChild("input", new String[] {
"type", "name" }, new String[] { "hidden", "restart" });
restartForm.addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "restart2",
l10n("restartNode") });
}
@@ -584,7 +584,7 @@
activityList.addChild("li", l10n("arkFetchCount",
"total", Integer.toString(node.getNumARKFetchers())));
}
- this.writeReply(ctx, 200, "text/html", "OK",
pageNode.generate());
+ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}
public String supportedMethods() {
Modified:
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkCategories.java
===================================================================
---
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkCategories.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkCategories.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,17 +1,10 @@
package freenet.clients.http.bookmark;
import java.util.Vector;
-import java.util.Iterator;
-public final class BookmarkCategories // implements Iterator
-{
+public final class BookmarkCategories {
+ private final Vector categories = new Vector();
- Vector categories;
-
- public BookmarkCategories() {
- categories = new Vector();
- }
-
public BookmarkCategory get(int i) {
return (BookmarkCategory) categories.get(i);
}
@@ -28,8 +21,4 @@
public int size() {
return categories.size();
}
-
- public Iterator iterator() {
- return categories.iterator();
- }
}
Modified:
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkCategory.java
===================================================================
---
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkCategory.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkCategory.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,22 +1,18 @@
package freenet.clients.http.bookmark;
import java.util.Vector;
-import java.util.Iterator;
import freenet.support.StringArray;
-public class BookmarkCategory extends Bookmark // implements Iterator
-{
+public class BookmarkCategory extends Bookmark {
- private final Vector bookmarks;
+ private final Vector bookmarks = new Vector();
public BookmarkCategory(String name) {
- bookmarks = new Vector();
setName(name);
}
public BookmarkCategory(String name, String desc) {
- bookmarks = new Vector();
setName(name);
setDesc(desc);
}
@@ -127,9 +123,4 @@
for (int i = 0; i < size(); i++)
subCategories.get(i).setPrivate(bool);
}
-
- public Iterator iterator() {
- return bookmarks.iterator();
- }
-
}
Modified:
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkItem.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkItem.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkItem.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -17,13 +17,10 @@
public class BookmarkItem extends Bookmark {
private FreenetURI key;
-
private boolean updated;
-
private final BookmarkUpdatedUserAlert alert;
+ private final UserAlertManager alerts;
- private UserAlertManager alerts;
-
public BookmarkItem(FreenetURI k, String n, UserAlertManager uam)
throws MalformedURLException {
this.key = k;
@@ -135,11 +132,7 @@
}
public String getName() {
- if (name.equals("")) {
- return l10n("unnamedBookmark");
- } else {
- return name;
- }
+ return ("".equals(name) ? l10n("unnamedBookmark") : name);
}
public void setPrivate(boolean bool) {
@@ -147,7 +140,7 @@
}
public String toString() {
- return this.name + "=" + this.key.toString();
+ return this.name + '=' + this.key.toString();
}
public synchronized void setEdition(long ed, NodeClientCore node) {
Modified:
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkItems.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkItems.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkItems.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,17 +1,10 @@
package freenet.clients.http.bookmark;
import java.util.Vector;
-import java.util.Iterator;
-public class BookmarkItems // implements Iterator
-{
+public class BookmarkItems {
+ private final Vector items = new Vector();
- Vector items;
-
- public BookmarkItems() {
- items = new Vector();
- }
-
public BookmarkItem get(int i) {
return (BookmarkItem) items.get(i);
}
@@ -28,8 +21,4 @@
public int size() {
return items.size();
}
-
- public Iterator iterator() {
- return (items).iterator();
- }
}
Modified:
branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkManager.java
===================================================================
--- branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkManager.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/clients/http/bookmark/BookmarkManager.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -20,106 +20,65 @@
public class BookmarkManager {
private final NodeClientCore node;
+ private final USKUpdatedCallback uskCB = new USKUpdatedCallback();
+ private final StringArrCallback configCB = new BookmarkCallback();
+ private static final BookmarkCategory MAIN_CATEGORY = new
BookmarkCategory("/");;
+ private final HashMap bookmarks = new HashMap();
- private USKUpdatedCallback uskcb;
-
- private boolean started;
-
- private BookmarkCategory mainCategory;
-
- private HashMap bookmarks;
-
- private SubConfig sc;
-
public BookmarkManager(NodeClientCore n, SubConfig sc) {
-
- bookmarks = new HashMap();
- mainCategory = new BookmarkCategory("/");
- bookmarks.put("/", mainCategory);
-
- this.uskcb = new USKUpdatedCallback();
+ bookmarks.put("/", MAIN_CATEGORY);
this.node = n;
- this.sc = sc;
try {
-
BookmarkCategory defaultRoot = new
BookmarkCategory("/");
-
- BookmarkCategory indexes = (BookmarkCategory)
defaultRoot
- .addBookmark(new
BookmarkCategory("Indexes"));
- indexes
- .addBookmark(new BookmarkItem(
- new FreenetURI(
- "USK at
7H66rhYmxIFgMyw5Dl11JazXGHPhp7dSN7WMa1pbtEo,jQHUQUPTkeRcjmjgrc7t5cDRdDkK3uKkrSzuw5CO9uk,AQACAAE/ENTRY.POINT/25/"),
+ BookmarkCategory indexes = (BookmarkCategory)
defaultRoot.addBookmark(new BookmarkCategory("Indexes"));
+ indexes.addBookmark(new BookmarkItem(
+ new FreenetURI(
+ "USK at
7H66rhYmxIFgMyw5Dl11JazXGHPhp7dSN7WMa1pbtEo,jQHUQUPTkeRcjmjgrc7t5cDRdDkK3uKkrSzuw5CO9uk,AQACAAE/ENTRY.POINT/25/"),
"Entry point (freesites
with descriptions but no categories)",
node.alerts));
- indexes
- .addBookmark(new BookmarkItem(
- new FreenetURI(
- "USK at
zQyF2O1o8B4y40w7Twz8y2I9haW3d2DTlxjTHPu7zc8,h2mhQNNE9aQvF~2yKAmKV1uorr7141-QOroBf5hrlbw,AQACAAE/AnotherIndex/3/"),
+ indexes.addBookmark(new BookmarkItem(
+ new FreenetURI(
+ "USK at
zQyF2O1o8B4y40w7Twz8y2I9haW3d2DTlxjTHPu7zc8,h2mhQNNE9aQvF~2yKAmKV1uorr7141-QOroBf5hrlbw,AQACAAE/AnotherIndex/3/"),
"Another Index
(freesites with categories but no descriptions)",
node.alerts));
- BookmarkCategory flog = (BookmarkCategory) defaultRoot
- .addBookmark(new
BookmarkCategory("Freenet devel's flogs"));
- flog
- .addBookmark(new BookmarkItem(
- new FreenetURI(
- "USK at
yGvITGZzrY1vUZK-4AaYLgcjZ7ysRqNTMfdcO8gS-LY,-ab5bJVD3Lp-LXEQqBAhJpMKrKJ19RnNaZMIkusU79s,AQACAAE/toad/2/"),
+ BookmarkCategory flog = (BookmarkCategory)
defaultRoot.addBookmark(new BookmarkCategory("Freenet devel's flogs"));
+ flog.addBookmark(new BookmarkItem(
+ new FreenetURI(
+ "USK at
yGvITGZzrY1vUZK-4AaYLgcjZ7ysRqNTMfdcO8gS-LY,-ab5bJVD3Lp-LXEQqBAhJpMKrKJ19RnNaZMIkusU79s,AQACAAE/toad/2/"),
"Toad", node.alerts));
- flog
- .addBookmark(new BookmarkItem(
- new FreenetURI(
- "USK at
hM9XRwjXIzU8xTSBXNZvTn2KuvTSRFnVn4EER9FQnpM,gsth24O7ud4gL4NwNuYJDUqfaWASOG2zxZY~ChtgPxc,AQACAAE/Flog/4/"),
+ flog.addBookmark(new BookmarkItem(
+ new FreenetURI(
+ "USK at
hM9XRwjXIzU8xTSBXNZvTn2KuvTSRFnVn4EER9FQnpM,gsth24O7ud4gL4NwNuYJDUqfaWASOG2zxZY~ChtgPxc,AQACAAE/Flog/4/"),
"Nextgen$",
node.alerts));
- BookmarkCategory apps = (BookmarkCategory) defaultRoot
- .addBookmark(new BookmarkCategory(
- "Freenet related
software"));
- apps
- .addBookmark(new BookmarkItem(
- new FreenetURI(
- "USK at
QRZAI1nSm~dAY2hTdzVWXmEhkaI~dso0OadnppBR7kE,wq5rHGBI7kpChBe4yRmgBChIGDug7Xa5SG9vYGXdxR0,AQACAAE/frost/1"),
+ BookmarkCategory apps = (BookmarkCategory)
defaultRoot.addBookmark(new BookmarkCategory("Freenet related software"));
+ apps.addBookmark(new BookmarkItem(
+ new FreenetURI(
+ "USK at
QRZAI1nSm~dAY2hTdzVWXmEhkaI~dso0OadnppBR7kE,wq5rHGBI7kpChBe4yRmgBChIGDug7Xa5SG9vYGXdxR0,AQACAAE/frost/1"),
"Frost", node.alerts));
- sc.register("bookmarks", defaultRoot.toStrings(), 0,
true, false,
- "BookmarkManager.list",
"BookmarkManager.listLong",
- makeCB());
-
- if (!importOldBookmarks())
- makeCB().set(
-
(sc.getStringArr("bookmarks").length == 0 ? defaultRoot
- .toStrings() :
sc.getStringArr("bookmarks")));
-
+ sc.register("bookmarks", defaultRoot.toStrings(), 0,
true, false,"BookmarkManager.list", "BookmarkManager.listLong", configCB);
+
+ configCB.set(sc.getStringArr("bookmarks"));
} catch (MalformedURLException mue) {
- // just ignore that one
} catch (InvalidConfigValueException icve) {
- // TODO
icve.printStackTrace();
}
-
- synchronized (this) {
- started = true;
- }
}
public class BookmarkCallback implements StringArrCallback {
- private final Pattern pattern = Pattern
- .compile("/(.*/)([^/]*)=([A-Z]{3}@.*).*");
+ private final Pattern pattern =
Pattern.compile("/(.*/)([^/]*)=([A-Z]{3}@.*).*");
public String[] get() {
-
synchronized (BookmarkManager.this) {
-
- return mainCategory.toStrings();
-
+ return MAIN_CATEGORY.toStrings();
}
}
public void set(String[] newVals) throws
InvalidConfigValueException {
- clear();
-
FreenetURI key;
for (int i = 0; i < newVals.length; i++) {
try {
@@ -143,10 +102,9 @@
private class USKUpdatedCallback implements USKCallback {
public void onFoundEdition(long edition, USK key) {
- BookmarkItems items = mainCategory.getAllItems();
+ BookmarkItems items = MAIN_CATEGORY.getAllItems();
for (int i = 0; i < items.size(); i++) {
-
- if (!items.get(i).getKeyType().equals("USK"))
+ if (!"USK".equals(items.get(i).getKeyType()))
continue;
try {
@@ -164,39 +122,12 @@
}
}
- private boolean importOldBookmarks() {
- String[] strs = sc.getStringArr("bookmarks");
-
- final Pattern pattern = Pattern.compile("([A-Z]{3}@.*)=(.*)");
- for (int i = 0; i < strs.length; i++) {
- Matcher matcher = pattern.matcher(strs[i]);
- if (matcher.matches() && matcher.groupCount() == 2) {
- if (getCategoryByPath("/Imported/") == null)
- addBookmark("/", new
BookmarkCategory("Imported"), false);
- try {
- addBookmark("/Imported/", new
BookmarkItem(new FreenetURI(
- matcher.group(1)),
matcher.group(2), node.alerts),
- false);
- } catch (MalformedURLException mue) {
- }
- } else
- return false;
- }
-
- node.storeConfig();
- return true;
- }
-
public String l10n(String key) {
return L10n.getString("BookmarkManager."+key);
}
- public BookmarkCallback makeCB() {
- return new BookmarkCallback();
- }
-
public BookmarkCategory getMainCategory() {
- return mainCategory;
+ return MAIN_CATEGORY;
}
public String parentPath(String path) {
@@ -226,45 +157,40 @@
return null;
}
- public void addBookmark(String parentPath, Bookmark bookmark, boolean
store)
- throws NullPointerException {
+ public void addBookmark(String parentPath, Bookmark bookmark, boolean
store) {
BookmarkCategory parent = getCategoryByPath(parentPath);
- if (parent == null)
- throw new NullPointerException();
- else {
- parent.addBookmark(bookmark);
- putPaths(parentPath + bookmark.getName()
- + ((bookmark instanceof
BookmarkCategory) ? "/" : ""),
- bookmark);
+ parent.addBookmark(bookmark);
+ putPaths(parentPath + bookmark.getName()
+ + ((bookmark instanceof BookmarkCategory) ? "/"
: ""),
+ bookmark);
- if (bookmark instanceof BookmarkItem && ((BookmarkItem)
bookmark).getKeyType().equals("USK")) {
- try {
- USK u = ((BookmarkItem)
bookmark).getUSK();
- this.node.uskManager.subscribe(u,
this.uskcb, true, this);
- } catch (MalformedURLException mue) {
- }
+ if (bookmark instanceof BookmarkItem && ((BookmarkItem)
bookmark).getKeyType().equals("USK")) {
+ try {
+ USK u = ((BookmarkItem) bookmark).getUSK();
+ this.node.uskManager.subscribe(u, this.uskCB,
true, this);
+ } catch (MalformedURLException mue) {
}
}
if (store)
node.storeConfig();
}
- // TODO
public void renameBookmark(String path, String newName) {
Bookmark bookmark = getBookmarkByPath(path);
+
+ String oldName = bookmark.getName();
+ String oldPath = '/' + oldName + '/';
+ String newPath = oldPath.substring(0, oldPath.indexOf(oldName))
+ newName + '/';
+
bookmark.setName(newName);
- if (bookmark instanceof BookmarkCategory) {
- try {
- makeCB().set(makeCB().get());
+
+ bookmarks.remove(path);
+ bookmarks.put(newPath, bookmark);
- } catch (InvalidConfigValueException icve) {
- }
- }
-
+ node.storeConfig();
}
- public void moveBookmark(String bookmarkPath, String newParentPath,
- boolean store) {
+ public void moveBookmark(String bookmarkPath, String newParentPath,
boolean store) {
Bookmark b = getBookmarkByPath(bookmarkPath);
addBookmark(newParentPath, b, false);
@@ -273,7 +199,6 @@
if (store)
node.storeConfig();
-
}
public void removeBookmark(String path, boolean store) {
@@ -286,15 +211,15 @@
for (int i = 0; i < cat.size(); i++) {
removeBookmark(
path
- +
cat.get(i).getName()
- + ((cat.get(i)
instanceof BookmarkCategory) ? "/"
-
: ""), false);
+ + cat.get(i).getName()
+ + ((cat.get(i) instanceof
BookmarkCategory) ? "/"
+ : ""), false);
}
} else {
if (((BookmarkItem)
bookmark).getKeyType().equals("USK")) {
try {
USK u = ((BookmarkItem)
bookmark).getUSK();
- this.node.uskManager.unsubscribe(u,
this.uskcb, true);
+ this.node.uskManager.unsubscribe(u,
this.uskCB, true);
} catch (MalformedURLException mue) {
}
}
@@ -306,7 +231,6 @@
if (store)
node.storeConfig();
-
}
public void moveBookmarkUp(String path, boolean store) {
@@ -366,17 +290,13 @@
}
public void clear() {
-
removeBookmark("/", false);
bookmarks.clear();
-
- mainCategory = new BookmarkCategory("/");
- bookmarks.put("/", mainCategory);
-
+ bookmarks.put("/", MAIN_CATEGORY);
}
public FreenetURI[] getBookmarkURIs() {
- BookmarkItems items = mainCategory.getAllItems();
+ BookmarkItems items = MAIN_CATEGORY.getAllItems();
FreenetURI[] uris = new FreenetURI[items.size()];
for (int i = 0; i < items.size(); i++) {
uris[i] = items.get(i).getURI();
@@ -384,36 +304,4 @@
return uris;
}
-
- /*
- * public void addBookmark(Bookmark b, boolean store) {
- * this.bookmarks.add(b); if (b.getKeyType().equals("USK")) { try { USK
u =
- * b.getUSK(); this.node.uskManager.subscribe(u, this.uskcb, true,
this); }
- * catch (MalformedURLException mue) {
- * } } if(store && started) node.storeConfig(); }
- *
- * public void removeBookmark(Bookmark b, boolean store) { if
- * (b.getKeyType().equals("USK")) { try { USK u = b.getUSK();
- * this.node.uskManager.unsubscribe(u, this.uskcb, true); } catch
- * (MalformedURLException mue) {
- * } } this.bookmarks.remove(b); if(store && started)
node.storeConfig(); }
- *
- * public void moveBookmarkDown (Bookmark b, boolean store) { int i =
- * this.bookmarks.indexOf(b); if (i == -1) return;
- *
- * Bookmark bk = (Bookmark)this.bookmarks.get(i);
this.bookmarks.remove(i);
- * this.bookmarks.add((i+1)%(this.bookmarks.size()+1), bk);
- *
- * if(store && started) node.storeConfig(); }
- *
- * public void moveBookmarkUp (Bookmark b, boolean store) { int i =
- * this.bookmarks.indexOf(b); if (i == -1) return;
- *
- * Bookmark bk = (Bookmark)this.bookmarks.get(i);
this.bookmarks.remove(i);
- * if (--i < 0) i = this.bookmarks.size(); this.bookmarks.add(i, bk);
- *
- * if(store && started) node.storeConfig(); }
- *
- * public int getSize() { return this.bookmarks.size(); }
- */
}
Modified:
branches/freenet-jfk/src/freenet/config/FreenetFilePersistentConfig.java
===================================================================
--- branches/freenet-jfk/src/freenet/config/FreenetFilePersistentConfig.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/config/FreenetFilePersistentConfig.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -48,7 +48,7 @@
public void store() {
synchronized(this) {
if(!finishedInit) {
- Logger.error(this, "Initialization not
finished, refusing to write config", new Exception("error"));
+ Logger.minor(this, "Initialization not
finished, refusing to write config", new Exception("error"));
return;
}
}
Modified: branches/freenet-jfk/src/freenet/config/PersistentConfig.java
===================================================================
--- branches/freenet-jfk/src/freenet/config/PersistentConfig.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/config/PersistentConfig.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -39,12 +39,16 @@
return
exportFieldSet(Config.CONFIG_REQUEST_TYPE_CURRENT_SETTINGS, withDefaults);
}
- public synchronized SimpleFieldSet exportFieldSet(int
configRequestType, boolean withDefaults) {
+ public SimpleFieldSet exportFieldSet(int configRequestType, boolean
withDefaults) {
SimpleFieldSet fs = new SimpleFieldSet(true);
- Iterator configsIterator = configsByPrefix.keySet().iterator();
+ SubConfig[] configs;
+ synchronized(this) {
+ // FIXME maybe keep a cache of this?
+ configs = (SubConfig[])
configsByPrefix.values().toArray(new SubConfig[configsByPrefix.size()]);
+ }
SubConfig current;
- while (configsIterator.hasNext()) {
- current = (SubConfig)
configsByPrefix.get(configsIterator.next());
+ for(int i=0;i<configs.length;i++) {
+ current = configs[i];
SimpleFieldSet scfs =
current.exportFieldSet(configRequestType, withDefaults);
fs.tput(current.prefix, scfs);
}
Modified: branches/freenet-jfk/src/freenet/config/SubConfig.java
===================================================================
--- branches/freenet-jfk/src/freenet/config/SubConfig.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/config/SubConfig.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -7,6 +7,7 @@
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import java.util.Map.Entry;
import freenet.l10n.L10n;
import freenet.support.Logger;
@@ -199,13 +200,16 @@
public SimpleFieldSet exportFieldSet(int configRequestType, boolean
withDefaults) {
SimpleFieldSet fs = new SimpleFieldSet(true);
- Set entrySet = map.entrySet();
- Iterator i = entrySet.iterator();
+ // FIXME is any locking at all necessary here? After it has
finished init, it's constant...
+ Map.Entry[] entries;
+ synchronized(this) {
+ entries = (Entry[]) map.entrySet().toArray(new
Map.Entry[map.size()]);
+ }
boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
if(logMINOR)
Logger.minor(this, "Prefix="+prefix);
- while(i.hasNext()) {
- Map.Entry entry = (Map.Entry) i.next();
+ for(int i=0;i<entries.length;i++) {
+ Map.Entry entry = (Map.Entry) entries[i];
String key = (String) entry.getKey();
Option o = (Option) entry.getValue();
// if(logMINOR)
@@ -261,6 +265,11 @@
o.setValue(value);
}
+ public void set(String name, boolean value) throws
InvalidConfigValueException {
+ BooleanOption o = (BooleanOption) map.get(name);
+ o.set(value);
+ }
+
/**
* If the option's value is equal to the provided old default, then set
it to the
* new default. Used to deal with changes to important options where
this is not
@@ -303,9 +312,14 @@
}
public String getRawOption(String name) {
- if(config instanceof PersistentConfig)
- return ((PersistentConfig)
config).origConfigFileContents.get(prefix + SimpleFieldSet.MULTI_LEVEL_CHAR +
name);
- else return null;
+ if(config instanceof PersistentConfig) {
+ PersistentConfig pc = (PersistentConfig) config;
+ if(pc.finishedInit)
+ throw new
IllegalStateException("getRawOption("+name+") on "+this+" but persistent config
has been finishedInit() already!");
+ SimpleFieldSet fs = pc.origConfigFileContents;
+ if(fs == null) return null;
+ return fs.get(prefix + SimpleFieldSet.MULTI_LEVEL_CHAR
+ name);
+ } else return null;
}
}
Modified: branches/freenet-jfk/src/freenet/crypt/DSAPrivateKey.java
===================================================================
--- branches/freenet-jfk/src/freenet/crypt/DSAPrivateKey.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/crypt/DSAPrivateKey.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -35,7 +35,7 @@
BigInteger tempX;
do {
tempX = new NativeBigInteger(256, r);
- } while (tempX.compareTo(g.getQ()) > -1);
+ } while (tempX.compareTo(g.getQ()) > -1 ||
tempX.equals(BigInteger.ZERO));
this.x = tempX;
}
Modified: branches/freenet-jfk/src/freenet/crypt/DiffieHellman.java
===================================================================
--- branches/freenet-jfk/src/freenet/crypt/DiffieHellman.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/crypt/DiffieHellman.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -44,7 +44,7 @@
private static class PrecalcBufferFill extends Thread {
public PrecalcBufferFill() {
- setName("Diffie-Helman-Precalc");
+ setName("Diffie-Hellman-Precalc");
setDaemon(true);
}
Modified: branches/freenet-jfk/src/freenet/crypt/KEProtocol.java
===================================================================
--- branches/freenet-jfk/src/freenet/crypt/KEProtocol.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/crypt/KEProtocol.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -9,7 +9,7 @@
/**
* Defines the interface that must be implemented by key-exchange protocols
- * such as RSA and Diffie-Helman
+ * such as RSA and Diffie-Hellman
*/
public abstract class KEProtocol {
protected RandomSource randomSource;
Modified: branches/freenet-jfk/src/freenet/crypt/PCFBMode.java
===================================================================
--- branches/freenet-jfk/src/freenet/crypt/PCFBMode.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/crypt/PCFBMode.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -11,6 +11,11 @@
* Control mechanism for the Periodic Cipher Feed Back mode. This is
* a CFB variant used apparently by a number of programs, including PGP.
* Thanks to Hal for suggesting it.
+ *
+ * http://www.streamsec.com/pcfb1.pdf
+ *
+ * NOTE: This is identical to CFB if block size = key size. As of Freenet 0.7,
+ * we use it with block size = key size.
*
* @author Scott
*/
Modified: branches/freenet-jfk/src/freenet/crypt/SHA256.java
===================================================================
--- branches/freenet-jfk/src/freenet/crypt/SHA256.java 2007-08-21 19:57:05 UTC
(rev 14827)
+++ branches/freenet-jfk/src/freenet/crypt/SHA256.java 2007-08-21 20:26:59 UTC
(rev 14828)
@@ -48,6 +48,7 @@
import org.tanukisoftware.wrapper.WrapperManager;
import freenet.node.Node;
+import freenet.node.NodeInitException;
import freenet.support.HexUtil;
import freenet.support.Logger;
@@ -372,7 +373,7 @@
System.err.println("Check your JVM settings especially the
JCE!"+e2);
e2.printStackTrace();
}
- WrapperManager.stop(Node.EXIT_CRAPPY_JVM);
+ WrapperManager.stop(NodeInitException.EXIT_CRAPPY_JVM);
throw new RuntimeException();
}
@@ -386,8 +387,6 @@
if(!(algo.equals("SHA-256") || algo.equals("SHA256")))
throw new IllegalArgumentException("Should be SHA-256
but is "+algo);
md256.reset();
- if(Logger.shouldLog(Logger.DEBUG, SHA256.class))
- Logger.debug(SHA256.class, "Returning message digest
"+md256, new Exception());
digests.add(md256);
}
Modified: branches/freenet-jfk/src/freenet/crypt/Yarrow.java
===================================================================
--- branches/freenet-jfk/src/freenet/crypt/Yarrow.java 2007-08-21 19:57:05 UTC
(rev 14827)
+++ branches/freenet-jfk/src/freenet/crypt/Yarrow.java 2007-08-21 20:26:59 UTC
(rev 14828)
@@ -3,6 +3,7 @@
* http://www.gnu.org/ for further details of the GPL. */
package freenet.crypt;
+import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -55,7 +56,7 @@
private static final int Pg = 10;
private final SecureRandom sr;
- private final File seedfile; //A file to which seed data should be
dumped periodically
+ public final File seedfile; //A file to which seed data should be
dumped periodically
public Yarrow() {
this("prng.seed", "SHA1", "Rijndael",true);
@@ -121,6 +122,7 @@
}
}
+ boolean isSystemEntropyAvailable = true;
// Read some bits from /dev/urandom
try {
fis = new FileInputStream("/dev/urandom");
@@ -131,6 +133,9 @@
consumeBytes(buf);
} catch (Throwable t) {
Logger.normal(this, "Can't read /dev/urandom: "+t, t);
+ // We can't read it; let's skip /dev/random and seed from
SecureRandom.generateSeed()
+ canBlock = true;
+ isSystemEntropyAvailable = false;
} finally {
try {
if(fis != null)
@@ -139,7 +144,7 @@
dis.close();
} catch (IOException e) {}
}
- if(canBlock) {
+ if(canBlock && isSystemEntropyAvailable) {
// Read some bits from /dev/random
try {
fis = new FileInputStream("/dev/random");
@@ -214,40 +219,70 @@
*/
private void read_seed(File filename) {
try {
- DataInputStream dis =
- new DataInputStream(new
FileInputStream(filename));
- EntropySource seedFile = new EntropySource();
+ FileInputStream fis = null;
+ BufferedInputStream bis = null;
+ DataInputStream dis = null;
+
try {
- for (int i = 0; i < 32; i++)
- acceptEntropy(seedFile, dis.readLong(),
64);
- } catch (EOFException f) {
+ fis = new FileInputStream(filename);
+ bis = new BufferedInputStream(fis);
+ dis = new DataInputStream(bis);
+
+ EntropySource seedFile = new EntropySource();
+ try {
+ for (int i = 0; i < 32; i++)
+ acceptEntropy(seedFile,
dis.readLong(), 64);
+ } catch (EOFException f) {}
+
+ } catch (IOException e) {
+ Logger.error(this, "IOE trying to read the
seedfile from disk : " + e.getMessage());
+ } finally {
+ if(dis != null) dis.close();
+ if(bis != null) bis.close();
+ if(fis != null) fis.close();
}
- dis.close();
- } catch (Exception e) {
- }
+ } catch (Exception e) {}
fast_pool_reseed();
}
private long timeLastWroteSeed = -1;
- private void write_seed(File filename) {
- synchronized(this) {
- long now = System.currentTimeMillis();
- if(now - timeLastWroteSeed <= 60*1000) {
- return;
- } else
- timeLastWroteSeed = now;
+ public void write_seed(File filename) {
+ write_seed(filename, false);
+ }
+
+ public void write_seed(File filename, boolean force) {
+ if(!force) {
+ synchronized(this) {
+ long now = System.currentTimeMillis();
+ if(now - timeLastWroteSeed <= 60*60*1000 /*
once per hour */) {
+ return;
+ } else
+ timeLastWroteSeed = now;
+ }
}
try {
- DataOutputStream dos =
- new DataOutputStream(new
BufferedOutputStream(new FileOutputStream(filename)));
- for (int i = 0; i < 32; i++)
- dos.writeLong(nextLong());
- dos.close();
- } catch (Exception e) {
- }
-
+ FileOutputStream fos = null;
+ BufferedOutputStream bos = null;
+ DataOutputStream dos = null;
+
+ try {
+ fos = new FileOutputStream(filename);
+ bos = new BufferedOutputStream(fos);
+ dos = new DataOutputStream(bos);
+
+ for (int i = 0; i < 32; i++)
+ dos.writeLong(nextLong());
+
+ }catch (IOException e) {
+ Logger.error(this, "IOE while saving the seed
file! : "+e.getMessage());
+ } finally {
+ if(dos != null) dos.close();
+ if(bos != null) bos.close();
+ if(fos != null) fos.close();
+ }
+ } catch (Exception e) {}
}
/**
Modified: branches/freenet-jfk/src/freenet/crypt/ciphers/Rijndael_Algorithm.java
===================================================================
--- branches/freenet-jfk/src/freenet/crypt/ciphers/Rijndael_Algorithm.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/crypt/ciphers/Rijndael_Algorithm.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -25,7 +25,7 @@
*
* License is apparently available from
http://www.cryptix.org/docs/license.html
*/
-public final class Rijndael_Algorithm // implicit no-argument constructor
+final class Rijndael_Algorithm // implicit no-argument constructor
{
// Debugging methods and variables
//
...........................................................................
@@ -293,17 +293,6 @@
//
...........................................................................
/**
- * Convenience method to expand a user-supplied key material into a
- * session key, assuming Rijndael's default block size (128-bit).
- *
- * @param k The 128/192/256-bit user-key to use.
- * @exception InvalidKeyException If the key is invalid.
- */
- private static final Object makeKey (byte[] k) throws
InvalidKeyException {
- return makeKey(k, BLOCK_SIZE);
- }
-
- /**
* Convenience method to encrypt exactly one block of plaintext,
assuming
* Rijndael's default block size (128-bit).
*
Modified:
branches/freenet-jfk/src/freenet/crypt/ciphers/Rijndael_Properties.java
===================================================================
--- branches/freenet-jfk/src/freenet/crypt/ciphers/Rijndael_Properties.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/crypt/ciphers/Rijndael_Properties.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -26,7 +26,7 @@
* @author Jill Baker
* @author Raif S. Naffah
*/
-public class Rijndael_Properties // implicit no-argument constructor
+class Rijndael_Properties // implicit no-argument constructor
{
// Constants and variables with relevant static code
//
...........................................................................
Modified: branches/freenet-jfk/src/freenet/io/Inet6AddressMatcher.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/Inet6AddressMatcher.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/Inet6AddressMatcher.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -54,6 +54,7 @@
bits = Math.max(bits - 8, 0);
}
}
+ if(Arrays.equals(netmask, FULL_MASK)) netmask =
FULL_MASK;
} else {
address = convertToBytes(pattern);
netmask = FULL_MASK;
Modified: branches/freenet-jfk/src/freenet/io/NetworkInterface.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/NetworkInterface.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/NetworkInterface.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -29,6 +29,7 @@
import java.util.StringTokenizer;
import freenet.io.AddressIdentifier.AddressType;
+import freenet.support.Executor;
import freenet.support.Logger;
/**
@@ -60,9 +61,11 @@
/** The number of running acceptors. */
private int runningAcceptors = 0;
+
+ private final Executor executor;
- public static NetworkInterface create(int port, String bindTo, String
allowedHosts) throws IOException {
- NetworkInterface iface = new NetworkInterface(port,
allowedHosts);
+ public static NetworkInterface create(int port, String bindTo, String
allowedHosts, Executor executor) throws IOException {
+ NetworkInterface iface = new NetworkInterface(port,
allowedHosts, executor);
try {
iface.setBindTo(bindTo);
} catch (IOException e) {
@@ -86,9 +89,10 @@
* @param allowedHosts
* A comma-separated list of allowed addresses
*/
- private NetworkInterface(int port, String allowedHosts) throws
IOException {
+ private NetworkInterface(int port, String allowedHosts, Executor
executor) throws IOException {
this.port = port;
this.allowedHosts = new AllowedHosts(allowedHosts);
+ this.executor = executor;
}
/**
@@ -128,19 +132,12 @@
acceptors.add(acceptor);
}
setSoTimeout(timeout);
- List tempThreads = new ArrayList();
synchronized (syncObject) {
Iterator acceptors = this.acceptors.iterator();
while (acceptors.hasNext()) {
- Thread t = new Thread((Acceptor)
acceptors.next(), "Network Interface Acceptor");
- t.setDaemon(true);
- tempThreads.add(t);
+ executor.execute((Acceptor) acceptors.next(),
"Network Interface Acceptor");
}
}
- for (Iterator i = tempThreads.iterator(); i.hasNext();) {
- ((Thread) i.next()).start();
- runningAcceptors++;
- }
}
public void setAllowedHosts(String allowedHosts) {
Modified: branches/freenet-jfk/src/freenet/io/comm/DMT.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/DMT.java 2007-08-21 19:57:05 UTC
(rev 14827)
+++ branches/freenet-jfk/src/freenet/io/comm/DMT.java 2007-08-21 20:26:59 UTC
(rev 14828)
@@ -78,6 +78,7 @@
public static final String TYPE = "type";
public static final String PAYLOAD = "payload";
public static final String COUNTER = "counter";
+ public static final String LINEAR_COUNTER = "linearCounter";
public static final String RETURN_LOCATION = "returnLocation";
public static final String BLOCK_HEADERS = "blockHeaders";
public static final String DATA_INSERT_REJECTED_REASON =
"dataInsertRejectedReason";
@@ -96,7 +97,26 @@
public static final String MY_UID = "myUID";
public static final String PEER_LOCATIONS = "peerLocations";
public static final String PEER_UIDS = "peerUIDs";
-
+ public static final String BEST_LOCATIONS_NOT_VISITED =
"bestLocationsNotVisited";
+ public static final String MAIN_JAR_KEY = "mainJarKey";
+ public static final String EXTRA_JAR_KEY = "extraJarKey";
+ public static final String REVOCATION_KEY = "revocationKey";
+ public static final String HAVE_REVOCATION_KEY = "haveRevocationKey";
+ public static final String MAIN_JAR_VERSION = "mainJarVersion";
+ public static final String EXTRA_JAR_VERSION = "extJarVersion";
+ public static final String REVOCATION_KEY_TIME_LAST_TRIED =
"revocationKeyTimeLastTried";
+ public static final String REVOCATION_KEY_DNF_COUNT =
"revocationKeyDNFCount";
+ public static final String REVOCATION_KEY_FILE_LENGTH =
"revocationKeyFileLength";
+ public static final String MAIN_JAR_FILE_LENGTH = "mainJarFileLength";
+ public static final String EXTRA_JAR_FILE_LENGTH = "extraJarFileLength";
+ public static final String PING_TIME = "pingTime";
+ public static final String BWLIMIT_DELAY_TIME = "bwlimitDelayTime";
+ public static final String TIME = "time";
+ public static final String FORK_COUNT = "forkCount";
+ public static final String TIME_LEFT = "timeLeft";
+ public static final String PREV_UID = "prevUID";
+ public static final String OPENNET_NODEREF = "opennetNoderef";
+
//Diagnostic
public static final MessageType ping = new MessageType("ping") {{
addField(SEND_TIME, Long.class);
@@ -505,6 +525,18 @@
return msg;
}
+ public static final MessageType FNPRecentlyFailed = new
MessageType("FNPRecentlyFailed") {{
+ addField(UID, Long.class);
+ addField(TIME_LEFT, Integer.class);
+ }};
+
+ public static final Message createFNPRecentlyFailed(long id, int
timeLeft) {
+ Message msg = new Message(FNPRecentlyFailed);
+ msg.set(UID, id);
+ msg.set(TIME_LEFT, timeLeft);
+ return msg;
+ }
+
public static final MessageType FNPCHKDataFound = new
MessageType("FNPCHKDataFound") {{
addField(UID, Long.class);
addField(BLOCK_HEADERS, ShortBuffer.class);
@@ -685,6 +717,58 @@
return msg;
}
+ // Opennet completions (not sent to darknet nodes)
+
+ /** Sent when a request to an opennet node is completed, but the data
source does not want to
+ * path fold */
+ public static MessageType FNPOpennetCompletedAck = new
MessageType("FNPOpennetCompletedAck") {{
+ addField(UID, Long.class);
+ }};
+
+ public static Message createFNPOpennetCompletedAck(long uid) {
+ Message msg = new Message(FNPOpennetCompletedAck);
+ msg.set(UID, uid);
+ return msg;
+ }
+
+ /** Sent when a request completes and the data source does want to path
fold */
+ public static MessageType FNPOpennetConnectDestination = new
MessageType("FNPOpennetConnectDestination") {{
+ addField(UID, Long.class);
+ addField(OPENNET_NODEREF, ShortBuffer.class);
+ }};
+
+ public static Message createFNPOpennetConnectDestination(long uid,
ShortBuffer buf) {
+ Message msg = new Message(FNPOpennetConnectDestination);
+ msg.set(UID, uid);
+ msg.set(OPENNET_NODEREF, buf);
+ return msg;
+ }
+
+ /** Path folding response */
+ public static MessageType FNPOpennetConnectReply = new
MessageType("FNPOpennetConnectReply") {{
+ addField(UID, Long.class);
+ addField(OPENNET_NODEREF, ShortBuffer.class);
+ }};
+
+ public static Message createFNPOpennetConnectReply(long uid,
ShortBuffer buf) {
+ Message msg = new Message(FNPOpennetConnectReply);
+ msg.set(UID, uid);
+ msg.set(OPENNET_NODEREF, buf);
+ return msg;
+ }
+
+ // Key offers (ULPRs)
+
+ public static MessageType FNPOfferKey = new MessageType("FNPOfferKey")
{{
+ addField(KEY, Key.class);
+ }};
+
+ public static Message createFNPOfferKey(Key key) {
+ Message msg = new Message(FNPOfferKey);
+ msg.set(KEY, key);
+ return msg;
+ }
+
public static final MessageType FNPPing = new MessageType("FNPPing") {{
addField(PING_SEQNO, Integer.class);
}};
@@ -732,10 +816,11 @@
addField(BEST_LOCATION, Double.class);
addField(HTL, Short.class);
addField(COUNTER, Short.class);
+ addField(LINEAR_COUNTER, Short.class);
}};
public static final Message createFNPProbeRequest(long uid, double
target, double nearest,
- double best, short htl, short counter) {
+ double best, short htl, short counter, short
linearCounter) {
Message msg = new Message(FNPProbeRequest);
msg.set(UID, uid);
msg.set(TARGET_LOCATION, target);
@@ -743,6 +828,7 @@
msg.set(BEST_LOCATION, best);
msg.set(HTL, htl);
msg.set(COUNTER, counter);
+ msg.set(LINEAR_COUNTER, linearCounter);
return msg;
}
@@ -757,9 +843,13 @@
addField(MY_UID, Long.class);
addField(PEER_LOCATIONS, ShortBuffer.class);
addField(PEER_UIDS, ShortBuffer.class);
+ addField(FORK_COUNT, Short.class);
+ addField(LINEAR_COUNTER, Short.class);
+ addField(REASON, String.class);
+ addField(PREV_UID, Long.class);
}};
- public static Message createFNPProbeTrace(long uid, double target,
double nearest, double best, short htl, short counter, double myLoc, long
swapIdentifier, double[] peerLocs, long[] peerUIDs) {
+ public static Message createFNPProbeTrace(long uid, double target,
double nearest, double best, short htl, short counter, double myLoc, long
swapIdentifier, double[] peerLocs, long[] peerUIDs, short forkCount, short
linearCounter, String reason, long prevUID) {
Message msg = new Message(FNPProbeTrace);
msg.set(UID, uid);
msg.set(TARGET_LOCATION, target);
@@ -771,6 +861,10 @@
msg.set(MY_UID, swapIdentifier);
msg.set(PEER_LOCATIONS, new
ShortBuffer(Fields.doublesToBytes(peerLocs)));
msg.set(PEER_UIDS, new
ShortBuffer(Fields.longsToBytes(peerUIDs)));
+ msg.set(FORK_COUNT, forkCount);
+ msg.set(LINEAR_COUNTER, linearCounter);
+ msg.set(REASON, reason);
+ msg.set(PREV_UID, prevUID);
return msg;
}
@@ -780,16 +874,18 @@
addField(NEAREST_LOCATION, Double.class);
addField(BEST_LOCATION, Double.class);
addField(COUNTER, Short.class);
+ addField(LINEAR_COUNTER, Short.class);
}};
public static final Message createFNPProbeReply(long uid, double
target, double nearest,
- double best, short counter) {
+ double best, short counter, short linearCounter) {
Message msg = new Message(FNPProbeReply);
msg.set(UID, uid);
msg.set(TARGET_LOCATION, target);
msg.set(NEAREST_LOCATION, nearest);
msg.set(BEST_LOCATION, best);
msg.set(COUNTER, counter);
+ msg.set(LINEAR_COUNTER, linearCounter);
return msg;
}
@@ -801,10 +897,11 @@
addField(HTL, Short.class);
addField(COUNTER, Short.class);
addField(REASON, Short.class);
+ addField(LINEAR_COUNTER, Short.class);
}};
public static final Message createFNPProbeRejected(long uid, double
target, double nearest,
- double best, short counter, short htl, short reason) {
+ double best, short counter, short htl, short reason,
short linearCounter) {
Message msg = new Message(FNPProbeRejected);
msg.set(UID, uid);
msg.set(TARGET_LOCATION, target);
@@ -813,6 +910,7 @@
msg.set(HTL, htl);
msg.set(COUNTER, counter);
msg.set(REASON, reason);
+ msg.set(LINEAR_COUNTER, linearCounter);
return msg;
}
@@ -936,6 +1034,16 @@
return msg;
}
+ public static final MessageType FNPTime = new MessageType("FNPTime") {{
+ addField(TIME, Long.class);
+ }};
+
+ public static final Message createFNPTime(long time) {
+ Message msg = new Message(FNPTime);
+ msg.set(TIME, time);
+ return msg;
+ }
+
public static final MessageType FNPVoid = new MessageType("FNPVoid") {{
}};
@@ -944,6 +1052,130 @@
return msg;
}
+ // Update over mandatory. Not strictly part of FNP. Only goes between
nodes at the link
+ // level, and will be sent, and parsed, even if the node is out of
date. Should be stable
+ // long-term.
+
+ // Sent on connect
+ public static final MessageType UOMAnnounce = new
MessageType("UOMAnnounce") {{
+ addField(MAIN_JAR_KEY, String.class);
+ addField(EXTRA_JAR_KEY, String.class);
+ addField(REVOCATION_KEY, String.class);
+ addField(HAVE_REVOCATION_KEY, Boolean.class);
+ addField(MAIN_JAR_VERSION, Long.class);
+ addField(EXTRA_JAR_VERSION, Long.class);
+ // Last time (ms ago) we had 3 DNFs in a row on the revocation
checker.
+ addField(REVOCATION_KEY_TIME_LAST_TRIED, Long.class);
+ // Number of DNFs so far this time.
+ addField(REVOCATION_KEY_DNF_COUNT, Integer.class);
+ // For convenience, may change
+ addField(REVOCATION_KEY_FILE_LENGTH, Long.class);
+ addField(MAIN_JAR_FILE_LENGTH, Long.class);
+ addField(EXTRA_JAR_FILE_LENGTH, Long.class);
+ addField(PING_TIME, Integer.class);
+ addField(BWLIMIT_DELAY_TIME, Integer.class);
+ }};
+
+ public static final Message createUOMAnnounce(String mainKey, String
extraKey, String revocationKey,
+ boolean haveRevocation, long mainJarVersion, long
extraJarVersion, long timeLastTriedRevocationFetch,
+ int revocationDNFCount, long revocationKeyLength, long
mainJarLength, long extraJarLength, int pingTime, int bwlimitDelayTime) {
+ Message msg = new Message(UOMAnnounce);
+
+ msg.set(MAIN_JAR_KEY, mainKey);
+ msg.set(EXTRA_JAR_KEY, extraKey);
+ msg.set(REVOCATION_KEY, revocationKey);
+ msg.set(HAVE_REVOCATION_KEY, haveRevocation);
+ msg.set(MAIN_JAR_VERSION, mainJarVersion);
+ msg.set(EXTRA_JAR_VERSION, extraJarVersion);
+ msg.set(REVOCATION_KEY_TIME_LAST_TRIED,
timeLastTriedRevocationFetch);
+ msg.set(REVOCATION_KEY_DNF_COUNT, revocationDNFCount);
+ msg.set(REVOCATION_KEY_FILE_LENGTH, revocationKeyLength);
+ msg.set(MAIN_JAR_FILE_LENGTH, mainJarLength);
+ msg.set(EXTRA_JAR_FILE_LENGTH, extraJarLength);
+ msg.set(PING_TIME, pingTime);
+ msg.set(BWLIMIT_DELAY_TIME, bwlimitDelayTime);
+
+ return msg;
+ }
+
+ public static final MessageType UOMRequestRevocation = new
MessageType("UOMRequestRevocation") {{
+ addField(UID, Long.class);
+ }};
+
+ public static final Message createUOMRequestRevocation(long uid) {
+ Message msg = new Message(UOMRequestRevocation);
+ msg.set(UID, uid);
+ return msg;
+ }
+
+ public static final MessageType UOMRequestMain = new
MessageType("UOMRequestMain") {{
+ addField(UID, Long.class);
+ }};
+
+ public static final Message createUOMRequestMain(long uid) {
+ Message msg = new Message(UOMRequestMain);
+ msg.set(UID, uid);
+ return msg;
+ }
+
+ public static final MessageType UOMRequestExtra = new
MessageType("UOMRequestExtra") {{
+ addField(UID, Long.class);
+ }};
+
+ public static final Message createUOMRequestExtra(long uid) {
+ Message msg = new Message(UOMRequestExtra);
+ msg.set(UID, uid);
+ return msg;
+ }
+
+ public static final MessageType UOMSendingRevocation = new
MessageType("UOMSendingRevocation") {{
+ addField(UID, Long.class);
+ // Probably excessive, but lengths are always long's, and
wasting a few bytes here
+ // doesn't matter in the least, as it's very rarely called.
+ addField(FILE_LENGTH, Long.class);
+ addField(REVOCATION_KEY, String.class);
+ }};
+
+ public static final Message createUOMSendingRevocation(long uid, long
length, String key) {
+ Message msg = new Message(UOMSendingRevocation);
+ msg.set(UID, uid);
+ msg.set(FILE_LENGTH, length);
+ msg.set(REVOCATION_KEY, key);
+ return msg;
+ }
+
+ public static final MessageType UOMSendingMain = new
MessageType("UOMSendingMain") {{
+ addField(UID, Long.class);
+ addField(FILE_LENGTH, Long.class);
+ addField(MAIN_JAR_KEY, String.class);
+ addField(MAIN_JAR_VERSION, Integer.class);
+ }};
+
+ public static final Message createUOMSendingMain(long uid, long length,
String key, int version) {
+ Message msg = new Message(UOMSendingMain);
+ msg.set(UID, uid);
+ msg.set(FILE_LENGTH, length);
+ msg.set(MAIN_JAR_KEY, key);
+ msg.set(MAIN_JAR_VERSION, version);
+ return msg;
+ }
+
+ public static final MessageType UOMSendingExtra = new
MessageType("UOMSendingExtra") {{
+ addField(UID, Long.class);
+ addField(FILE_LENGTH, Long.class);
+ addField(EXTRA_JAR_KEY, String.class);
+ addField(EXTRA_JAR_VERSION, Integer.class);
+ }};
+
+ public static final Message createUOMSendingExtra(long uid, long
length, String key, int version) {
+ Message msg = new Message(UOMSendingExtra);
+ msg.set(UID, uid);
+ msg.set(FILE_LENGTH, length);
+ msg.set(EXTRA_JAR_KEY, key);
+ msg.set(EXTRA_JAR_VERSION, version);
+ return msg;
+ }
+
// Secondary messages (debug messages attached to primary messages)
public static final MessageType FNPSwapNodeUIDs = new
MessageType("FNPSwapNodeUIDs") {{
@@ -956,6 +1188,36 @@
return msg;
}
+ public static final Message createFNPSwapLocations(long[] uids) {
+ Message msg = new Message(FNPSwapNodeUIDs);
+ msg.set(NODE_UIDS, new ShortBuffer(Fields.longsToBytes(uids)));
+ return msg;
+ }
+
+ // More permanent secondary messages (should perhaps be replaced by new
main messages when stable)
+
+ public static final MessageType FNPBestRoutesNotTaken = new
MessageType("FNPBestRoutesNotTaken") {{
+ // Maybe this should be some sort of typed array?
+ // It's just a bunch of double's anyway.
+ addField(BEST_LOCATIONS_NOT_VISITED, ShortBuffer.class);
+ }};
+
+ public static final Message createFNPBestRoutesNotTaken(byte[] locs) {
+ Message msg = new Message(FNPBestRoutesNotTaken);
+ msg.set(BEST_LOCATIONS_NOT_VISITED, new ShortBuffer(locs));
+ return msg;
+ }
+
+ public static final Message createFNPBestRoutesNotTaken(double[] locs) {
+ return createFNPBestRoutesNotTaken(Fields.doublesToBytes(locs));
+ }
+
+ public static Message createFNPBestRoutesNotTaken(Double[] doubles) {
+ double[] locs = new double[doubles.length];
+ for(int i=0;i<locs.length;i++) locs[i] =
doubles[i].doubleValue();
+ return createFNPBestRoutesNotTaken(locs);
+ }
+
public static void init() { }
}
Modified: branches/freenet-jfk/src/freenet/io/comm/FreenetInetAddress.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/FreenetInetAddress.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/comm/FreenetInetAddress.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -248,6 +248,13 @@
return _address.getHostAddress();
}
}
+
+ public String toStringPrefNumeric() {
+ if(_address != null)
+ return _address.getHostAddress();
+ else
+ return hostname;
+ }
public void writeToDataOutputStream(DataOutputStream dos, boolean
oldForm) throws IOException {
InetAddress addr = this.getAddress();
Modified: branches/freenet-jfk/src/freenet/io/comm/IOStatisticCollector.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/IOStatisticCollector.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/comm/IOStatisticCollector.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -16,6 +16,7 @@
private long lastrotate;
private static IOStatisticCollector _currentSC;
+ private static boolean logDEBUG;
private long totalbytesin;
private long totalbytesout;
private final LinkedHashMap targets;
@@ -28,6 +29,7 @@
// This should only happen once
//SNMPAgent.create();
//SNMPStarter.initialize();
+ logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
}
private static IOStatisticCollector getSC() {
@@ -59,8 +61,8 @@
synchronized(this) {
totalbytesout += (outbytes>0)?outbytes:0;
totalbytesin += (inbytes>0)?inbytes:0;
- if(Logger.shouldLog(Logger.MINOR,
IOStatisticCollector.class))
- Logger.minor(IOStatisticCollector.class,
"Add("+key+ ',' +inbytes+ ',' +outbytes+" -> "+totalbytesin+" :
"+totalbytesout);
+ if(logDEBUG)
+ Logger.debug(IOStatisticCollector.class,
"Add("+key+ ',' +inbytes+ ',' +outbytes+" -> "+totalbytesin+" :
"+totalbytesout);
}
}
Copied: branches/freenet-jfk/src/freenet/io/comm/MessageCore.java (from rev
14796, trunk/freenet/src/freenet/io/comm/MessageCore.java)
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/MessageCore.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/io/comm/MessageCore.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,502 @@
+/*
+ * Dijjer - A Peer to Peer HTTP Cache
+ * Copyright (C) 2004,2005 Change.Tv, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+package freenet.io.comm;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Vector;
+
+import freenet.node.PeerNode;
+import freenet.node.Ticker;
+import freenet.support.Logger;
+import freenet.support.TimeUtil;
+
+public class MessageCore {
+
+ public static final String VERSION = "$Id: MessageCore.java,v 1.22
2005/08/25 17:28:19 amphibian Exp $";
+ private static boolean logMINOR;
+ private Dispatcher _dispatcher;
+ /** _filters serves as lock for both */
+ private final LinkedList _filters = new LinkedList();
+ private final LinkedList _unclaimed = new LinkedList();
+ private static final int MAX_UNMATCHED_FIFO_SIZE = 50000;
+ private static final long MAX_UNCLAIMED_FIFO_ITEM_LIFETIME =
10*60*1000; // 10 minutes; maybe this should be per message type??
+ // Every second, remove all timed out filters
+ private static final int FILTER_REMOVE_TIME = 1000;
+ private long startedTime;
+
+ public synchronized long getStartedTime() {
+ return startedTime;
+ }
+
+ public MessageCore() {
+ _timedOutFilters = new Vector(32);
+ logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ }
+
+ /**
+ * Decode a packet from data and a peer.
+ * Can be called by IncomingPacketFilter's.
+ * @param data
+ * @param offset
+ * @param length
+ * @param peer
+ */
+ public Message decodeSingleMessage(byte[] data, int offset, int length,
PeerContext peer, int overhead) {
+ try {
+ return Message.decodeMessageFromPacket(data, offset, length, peer,
overhead);
+ } catch (Throwable t) {
+ Logger.error(this, "Could not decode packet: "+t, t);
+ return null;
+ }
+ }
+
+ /** Only used by removeTimedOutFilters() - if future code uses this
elsewhere, we need to
+ * reconsider its locking. */
+ private final Vector _timedOutFilters;
+
+ public void start(final Ticker ticker) {
+ synchronized(this) {
+ startedTime = System.currentTimeMillis();
+ }
+ ticker.queueTimedJob(new Runnable() {
+
+ public void run() {
+ try {
+ removeTimedOutFilters();
+ } catch (Throwable t) {
+ Logger.error(this, "Failed to remove
timed out filters: "+t, t);
+ } finally {
+ ticker.queueTimedJob(this,
FILTER_REMOVE_TIME);
+ }
+ // TODO Auto-generated method stub
+
+ }
+
+ }, FILTER_REMOVE_TIME);
+ }
+
+ /**
+ * Remove timed out filters.
+ */
+ void removeTimedOutFilters() {
+ long tStart = System.currentTimeMillis();
+ synchronized (_filters) {
+ for (ListIterator i = _filters.listIterator();
i.hasNext();) {
+ MessageFilter f = (MessageFilter) i.next();
+ if (f.timedOut()) {
+ i.remove();
+ _timedOutFilters.add(f);
+ } else { // Because _filters are in order of
timeout, we
+ // can abort the iteration as soon as
we find one that
+ // doesn't timeout
+ break;
+ }
+ }
+ }
+
+ for(int i=0;i<_timedOutFilters.size();i++) {
+ MessageFilter f = (MessageFilter)
_timedOutFilters.get(i);
+ f.setMessage(null);
+ f.onTimedOut();
+ }
+ _timedOutFilters.clear();
+
+ long tEnd = System.currentTimeMillis();
+ if(tEnd - tStart > 50) {
+ if(tEnd - tStart > 3000)
+ Logger.error(this, "removeTimedOutFilters took
"+(tEnd-tStart)+"ms");
+ else
+ if(logMINOR) Logger.minor(this,
"removeTimedOutFilters took "+(tEnd-tStart)+"ms");
+ }
+ }
+
+ /**
+ * Dispatch a message to a waiting filter, or feed it to the
+ * Dispatcher if none are found.
+ * @param m The Message to dispatch.
+ */
+ public void checkFilters(Message m, PacketSocketHandler from) {
+ long tStart = System.currentTimeMillis();
+ if(logMINOR) Logger.minor(this, "checkFilters: "+m+" from
"+m.getSource());
+ if ((m.getSource()) instanceof PeerNode)
+ {
+
((PeerNode)m.getSource()).addToLocalNodeReceivedMessagesFromStatistic(m);
+ }
+ boolean matched = false;
+ if ((!(m.getSpec().equals(DMT.packetTransmit))) && logMINOR) {
+ if ((m.getSpec().equals(DMT.ping) ||
m.getSpec().equals(DMT.pong)) && Logger.shouldLog(Logger.DEBUG, this)) {
+ Logger.debug(this, "" +
(System.currentTimeMillis() % 60000) + ' ' + from + " <- "
+ + m.getSource() + " : " + m);
+ } else {
+ if(logMINOR) Logger.minor(this, "" +
(System.currentTimeMillis() % 60000) + ' ' + from + " <- "
+ + m.getSource() + " : " + m);
+ }
+ }
+ MessageFilter match = null;
+ synchronized (_filters) {
+ for (ListIterator i = _filters.listIterator();
i.hasNext();) {
+ MessageFilter f = (MessageFilter) i.next();
+ if (f.match(m)) {
+ matched = true;
+ i.remove();
+ match = f;
+ if(logMINOR) Logger.minor(this,
"Matched: "+f);
+ break; // Only one match permitted per
message
+ }
+ }
+ }
+ if(match != null) {
+ match.setMessage(m);
+ match.onMatched();
+ }
+ // Feed unmatched messages to the dispatcher
+ if ((!matched) && (_dispatcher != null)) {
+ try {
+ if(logMINOR) Logger.minor(this, "Feeding to dispatcher:
"+m);
+ matched = _dispatcher.handleMessage(m);
+ } catch (Throwable t) {
+ Logger.error(this, "Dispatcher threw "+t, t);
+ }
+ }
+ // Keep the last few _unclaimed messages around in case the
intended receiver isn't receiving yet
+ if (!matched) {
+ if(logMINOR) Logger.minor(this, "Unclaimed: "+m);
+ /** Check filters and then add to _unmatched is ATOMIC
+ * It has to be atomic, because otherwise we can get a
+ * race condition that results in timeouts on MFs.
+ *
+ * Specifically:
+ * - Thread A receives packet
+ * - Thread A checks filters. It doesn't match any.
+ * - Thread A feeds to Dispatcher.
+ * - Thread B creates filter.
+ * - Thread B checks _unmatched.
+ * - Thread B adds filter.
+ * - Thread B sleeps.
+ * - Thread A returns from Dispatcher. Which didn't match.
+ * - Thread A adds to _unmatched.
+ *
+ * OOPS!
+ * The only way to fix this is to have checking the
+ * filters and unmatched be a single atomic operation.
+ * Another race is possible if we merely recheck the
+ * filters after we return from dispatcher, for example.
+ */
+ synchronized (_filters) {
+ if(logMINOR) Logger.minor(this, "Rechecking
filters and adding message");
+ for (ListIterator i = _filters.listIterator();
i.hasNext();) {
+ MessageFilter f = (MessageFilter)
i.next();
+ if (f.match(m)) {
+ matched = true;
+ match = f;
+ i.remove();
+ if(logMINOR) Logger.minor(this,
"Matched: "+f);
+ break; // Only one match
permitted per message
+ }
+ }
+ if(!matched) {
+ while (_unclaimed.size() >
MAX_UNMATCHED_FIFO_SIZE) {
+ Message removed =
(Message)_unclaimed.removeFirst();
+ long messageLifeTime =
System.currentTimeMillis() - removed.localInstantiationTime;
+ if ((removed.getSource()) instanceof
PeerNode) {
+ Logger.normal(this, "Dropping
unclaimed from "+removed.getSource().getPeer()+", lived
"+TimeUtil.formatTime(messageLifeTime, 2, true)+" (quantity)"+": "+removed);
+ } else {
+ Logger.normal(this, "Dropping
unclaimed, lived "+TimeUtil.formatTime(messageLifeTime, 2, true)+"
(quantity)"+": "+removed);
+ }
+ }
+ _unclaimed.addLast(m);
+ if(logMINOR) Logger.minor(this, "Done");
+ }
+ }
+ if(match != null) {
+ match.setMessage(m);
+ match.onMatched();
+ }
+ }
+ long tEnd = System.currentTimeMillis();
+ if(tEnd - tStart > 50) {
+ if(tEnd - tStart > 3000)
+ Logger.error(this, "checkFilters took
"+(tEnd-tStart)+"ms with unclaimedFIFOSize of "+_unclaimed.size()+" for
matched: "+matched);
+ else
+ if(logMINOR) Logger.minor(this, "checkFilters
took "+(tEnd-tStart)+"ms with unclaimedFIFOSize of "+_unclaimed.size()+" for
matched: "+matched);
+ }
+ }
+
+ /** IncomingPacketFilter should call this when a node is disconnected.
*/
+ public void onDisconnect(PeerContext ctx) {
+ Vector droppedFilters = null; // rare operation, we can waste
objects for better locking
+ synchronized(_filters) {
+ ListIterator i = _filters.listIterator();
+ while (i.hasNext()) {
+ MessageFilter f = (MessageFilter) i.next();
+ if(f.matchesDroppedConnection(ctx)) {
+ if(droppedFilters == null)
+ droppedFilters = new Vector();
+ droppedFilters.add(f);
+ i.remove();
+ }
+ }
+ }
+ if(droppedFilters != null) {
+ for(int i=0;i<droppedFilters.size();i++) {
+ MessageFilter mf = (MessageFilter)
droppedFilters.get(i);
+ mf.onDroppedConnection(ctx);
+ }
+ }
+ }
+
+ /** IncomingPacketFilter should call this when a node connects with a
new boot ID */
+ public void onRestart(PeerContext ctx) {
+ Vector droppedFilters = null; // rare operation, we can waste
objects for better locking
+ synchronized(_filters) {
+ ListIterator i = _filters.listIterator();
+ while (i.hasNext()) {
+ MessageFilter f = (MessageFilter) i.next();
+ if(f.matchesRestartedConnection(ctx)) {
+ if(droppedFilters == null)
+ droppedFilters = new Vector();
+ droppedFilters.add(f);
+ i.remove();
+ }
+ }
+ }
+ if(droppedFilters != null) {
+ for(int i=0;i<droppedFilters.size();i++) {
+ MessageFilter mf = (MessageFilter)
droppedFilters.get(i);
+ mf.onRestartedConnection(ctx);
+ }
+ }
+ }
+
+ public void addAsyncFilter(MessageFilter filter,
AsyncMessageFilterCallback callback) throws DisconnectedException {
+ filter.setAsyncCallback(callback);
+ filter.onStartWaiting();
+ boolean logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
+ if(logDEBUG) Logger.debug(this, "Adding async filter "+filter+"
for "+callback);
+ Message ret = null;
+ if(filter._source != null && (!filter._source.isConnected()) &&
+ filter.matchesDroppedConnection(filter._source))
+ throw new DisconnectedException();
+ // Check to see whether the filter matches any of the recently
_unclaimed messages
+ // Drop any _unclaimed messages that the filter doesn't match
that are also older than MAX_UNCLAIMED_FIFO_ITEM_LIFETIME
+ long now = System.currentTimeMillis();
+ long messageDropTime = now - MAX_UNCLAIMED_FIFO_ITEM_LIFETIME;
+ long messageLifeTime = 0;
+ synchronized (_filters) {
+ if(logMINOR) Logger.minor(this, "Checking _unclaimed");
+ for (ListIterator i = _unclaimed.listIterator();
i.hasNext();) {
+ Message m = (Message) i.next();
+ if (filter.match(m)) {
+ i.remove();
+ ret = m;
+ if(logMINOR) Logger.debug(this,
"Matching from _unclaimed");
+ break;
+ } else if (m.localInstantiationTime <
messageDropTime) {
+ i.remove();
+ messageLifeTime = now -
m.localInstantiationTime;
+ if ((m.getSource()) instanceof
PeerNode) {
+ Logger.normal(this, "Dropping
unclaimed from "+m.getSource().getPeer()+", lived
"+TimeUtil.formatTime(messageLifeTime, 2, true)+" (age)"+": "+m);
+ } else {
+ Logger.normal(this, "Dropping
unclaimed, lived "+TimeUtil.formatTime(messageLifeTime, 2, true)+" (age)"+":
"+m);
+ }
+ }
+ }
+ if (ret == null) {
+ if(logMINOR) Logger.minor(this, "Not in
_unclaimed");
+ // Insert filter into filter list in order of
timeout
+ ListIterator i = _filters.listIterator();
+ while (true) {
+ if (!i.hasNext()) {
+ i.add(filter);
+ if(logMINOR) Logger.minor(this,
"Added at end");
+ break;
+ }
+ MessageFilter mf = (MessageFilter)
i.next();
+ if (mf.getTimeout() >
filter.getTimeout()) {
+ i.previous();
+ i.add(filter);
+ if(logMINOR) Logger.minor(this,
"Added in middle - mf timeout="+mf.getTimeout()+" - my
timeout="+filter.getTimeout());
+ break;
+ }
+ }
+ }
+ }
+ if(ret != null) {
+ filter.onMatched();
+ filter.clearMatched();
+ }
+ }
+
+ /**
+ * Wait for a filter to trigger, or timeout. Blocks until either the
trigger is activated, or it times
+ * out, or the peer is disconnected.
+ * @param filter The filter to wait for.
+ * @param ctr Byte counter to add bytes from the message to.
+ * @return Either a message, or null if the filter timed out.
+ * @throws DisconnectedException If the single peer being waited for
disconnects.
+ */
+ public Message waitFor(MessageFilter filter, ByteCounter ctr) throws
DisconnectedException {
+ boolean logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
+ if(logDEBUG) Logger.debug(this, "Waiting for "+filter);
+ long startTime = System.currentTimeMillis();
+ filter.onStartWaiting();
+ Message ret = null;
+ if(filter._source != null && (!filter._source.isConnected()) &&
+ filter.matchesDroppedConnection(filter._source))
+ throw new DisconnectedException();
+ // Check to see whether the filter matches any of the recently
_unclaimed messages
+ // Drop any _unclaimed messages that the filter doesn't match
that are also older than MAX_UNCLAIMED_FIFO_ITEM_LIFETIME
+ long now = System.currentTimeMillis();
+ long messageDropTime = now - MAX_UNCLAIMED_FIFO_ITEM_LIFETIME;
+ long messageLifeTime = 0;
+ synchronized (_filters) {
+ if(logMINOR) Logger.minor(this, "Checking _unclaimed");
+ for (ListIterator i = _unclaimed.listIterator();
i.hasNext();) {
+ Message m = (Message) i.next();
+ if (filter.match(m)) {
+ i.remove();
+ ret = m;
+ if(logMINOR) Logger.debug(this,
"Matching from _unclaimed");
+ break;
+ } else if (m.localInstantiationTime <
messageDropTime) {
+ i.remove();
+ messageLifeTime = now -
m.localInstantiationTime;
+ if ((m.getSource()) instanceof
PeerNode) {
+ Logger.normal(this, "Dropping
unclaimed from "+m.getSource().getPeer()+", lived
"+TimeUtil.formatTime(messageLifeTime, 2, true)+" (age)"+": "+m);
+ } else {
+ Logger.normal(this, "Dropping
unclaimed, lived "+TimeUtil.formatTime(messageLifeTime, 2, true)+" (age)"+":
"+m);
+ }
+ }
+ }
+ if (ret == null) {
+ if(logMINOR) Logger.minor(this, "Not in
_unclaimed");
+ // Insert filter into filter list in order of
timeout
+ ListIterator i = _filters.listIterator();
+ while (true) {
+ if (!i.hasNext()) {
+ i.add(filter);
+ if(logMINOR) Logger.minor(this,
"Added at end");
+ break;
+ }
+ MessageFilter mf = (MessageFilter)
i.next();
+ if (mf.getTimeout() >
filter.getTimeout()) {
+ i.previous();
+ i.add(filter);
+ if(logMINOR) Logger.minor(this,
"Added in middle - mf timeout="+mf.getTimeout()+" - my
timeout="+filter.getTimeout());
+ break;
+ }
+ }
+ }
+ }
+ long tEnd = System.currentTimeMillis();
+ if(tEnd - now > 50) {
+ if(tEnd - now > 3000)
+ Logger.error(this, "waitFor _unclaimed
iteration took "+(tEnd-now)+"ms with unclaimedFIFOSize of "+_unclaimed.size()+"
for ret of "+ret);
+ else
+ if(logMINOR) Logger.minor(this, "waitFor
_unclaimed iteration took "+(tEnd-now)+"ms with unclaimedFIFOSize of
"+_unclaimed.size()+" for ret of "+ret);
+ }
+ // Unlock to wait on filter
+ // Waiting on the filter won't release the outer lock
+ // So we have to release it here
+ if(ret == null) {
+ if(logMINOR) Logger.minor(this, "Waiting...");
+ synchronized (filter) {
+ try {
+ // Precaution against filter getting
matched between being added to _filters and
+ // here - bug discovered by Mason
+ boolean fmatched = false;
+ while(!(fmatched = (filter.matched() ||
(filter.droppedConnection() != null)))) {
+ long wait =
filter.getTimeout()-System.currentTimeMillis();
+ if(wait > 0)
+ filter.wait(wait);
+ else break;
+ }
+ if(filter.droppedConnection() != null)
+ throw new DisconnectedException();
+ if(logMINOR) Logger.minor(this, "Matched:
"+fmatched);
+ } catch (InterruptedException e) {
+ }
+ ret = filter.getMessage();
+ filter.clearMatched();
+ }
+ if(logDEBUG) Logger.debug(this, "Returning "+ret+" from
"+filter);
+ } else {
+ // Matched an unclaimed packet
+ filter.onMatched();
+ filter.clearMatched();
+ }
+ // Probably get rid...
+// if (Dijjer.getDijjer().getDumpMessageWaitTimes() != null) {
+//
Dijjer.getDijjer().getDumpMessageWaitTimes().println(filter.toString() + "\t" +
filter.getInitialTimeout() + "\t"
+// + (System.currentTimeMillis() -
startTime));
+// Dijjer.getDijjer().getDumpMessageWaitTimes().flush();
+// }
+ long endTime = System.currentTimeMillis();
+ if(logDEBUG) Logger.debug(this, "Returning in
"+(endTime-startTime)+"ms");
+ if((ctr != null) && (ret != null))
+ ctr.receivedBytes(ret._receivedByteCount);
+ return ret;
+ }
+
+ /**
+ * Send a Message to a PeerContext.
+ * @throws NotConnectedException If we are not currently connected to
the node.
+ */
+ public void send(PeerContext destination, Message m, ByteCounter ctr)
throws NotConnectedException {
+ if(m.getSpec().isInternalOnly()) {
+ Logger.error(this, "Trying to send internal-only message "+m+"
of spec "+m.getSpec(), new Exception("debug"));
+ return;
+ }
+ destination.sendAsync(m, null, 0, ctr);
+ }
+
+ public void setDispatcher(Dispatcher d) {
+ _dispatcher = d;
+ }
+
+ /**
+ * @return the number of received messages that are currently unclaimed
+ */
+ public int getUnclaimedFIFOSize() {
+ synchronized (_filters){
+ return _unclaimed.size();
+ }
+ }
+
+ public Map getUnclaimedFIFOMessageCounts() {
+ Map messageCounts = new HashMap();
+ synchronized(_filters) {
+ for (ListIterator i = _unclaimed.listIterator();
i.hasNext();) {
+ Message m = (Message) i.next();
+ String messageName = m.getSpec().getName();
+ Integer messageCount = (Integer)
messageCounts.get(messageName);
+ if (messageCount == null) {
+ messageCounts.put(messageName, new
Integer(1) );
+ } else {
+ messageCount = new
Integer(messageCount.intValue() + 1);
+ messageCounts.put(messageName,
messageCount );
+ }
+ }
+ }
+ return messageCounts;
+ }
+}
Modified: branches/freenet-jfk/src/freenet/io/comm/MessageFilter.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/MessageFilter.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/comm/MessageFilter.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -29,7 +29,7 @@
* To change the template for this generated type comment go to Window -
Preferences - Java - Code Generation - Code and
* Comments
*/
-public class MessageFilter {
+public final class MessageFilter {
public static final String VERSION = "$Id: MessageFilter.java,v 1.7
2005/08/25 17:28:19 amphibian Exp $";
@@ -41,6 +41,9 @@
private Vector _fieldList = new Vector(1,1);
PeerContext _source;
private long _timeout;
+ /** If true, timeouts are relative to the start of waiting, if false, they
are relative to
+ * the time of calling setTimeout() */
+ private boolean _timeoutFromWait;
private int _initialTimeout;
private MessageFilter _or;
private Message _message;
@@ -52,13 +55,34 @@
setTimeout(DEFAULT_TIMEOUT);
_matchesDroppedConnections = true; // on by default
_matchesRestartedConnections = true; // also on by default
+ _timeoutFromWait = true;
}
public static MessageFilter create() {
return new MessageFilter();
}
+ void onStartWaiting() {
+ synchronized(this) {
+ if(_initialTimeout > 0 && _timeoutFromWait)
+ _timeout = System.currentTimeMillis() + _initialTimeout;
+ }
+ if(_or != null)
+ _or.onStartWaiting();
+ }
+
/**
+ * Set whether the timeout is relative to the creation of the filter, or
the start of
+ * waitFor().
+ * @param b If true, the timeout is relative to the time at which
setTimeout() was called,
+ * if false, it's relative to the start of waitFor().
+ */
+ public MessageFilter setTimeoutRelativeToCreation(boolean b) {
+ _timeoutFromWait = !b;
+ return this;
+ }
+
+ /**
* This filter will expire after the specificed amount of time. Note also
that where two or more filters match the
* same message, the one with the nearer expiry time will get priority
*
@@ -118,7 +142,7 @@
}
public MessageFilter or(MessageFilter or) {
- if((or != null) && (_or != null)) {
+ if((or != null) && (_or != null) && or != _or) {
// FIXME maybe throw? this is almost certainly a bug,
and a nasty one too!
Logger.error(this, "or() replacement: "+_or+" -> "+or,
new Exception("error"));
}
@@ -142,6 +166,7 @@
}
public boolean match(Message m) {
+ if(timedOut()) return false;
if ((_or != null) && (_or.match(m))) {
_matched = true;
return true;
@@ -171,11 +196,15 @@
return _matched;
}
+ /**
+ * Which connection dropped or was restarted?
+ */
public PeerContext droppedConnection() {
return _droppedConnection;
}
public boolean timedOut() {
+ if(_matched) return false;
if(_callback != null && _callback.shouldTimeout())
_timeout = -1; // timeout immediately
return _timeout < System.currentTimeMillis();
@@ -225,6 +254,7 @@
* @param ctx
*/
public synchronized void onDroppedConnection(PeerContext ctx) {
+ _droppedConnection = ctx;
notifyAll();
}
@@ -234,6 +264,7 @@
* @param ctx
*/
public synchronized void onRestartedConnection(PeerContext ctx) {
+ _droppedConnection = ctx;
notifyAll();
}
Modified: branches/freenet-jfk/src/freenet/io/comm/MessageType.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/MessageType.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/comm/MessageType.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -92,7 +92,9 @@
if (!(o instanceof MessageType)) {
return false;
}
- return ((MessageType) o)._name.equals(_name);
+ // We can only register one MessageType for each name.
+ // So we can do == here.
+ return ((MessageType) o)._name == _name;
}
public int hashCode() {
Copied: branches/freenet-jfk/src/freenet/io/comm/PacketSocketHandler.java (from
rev 14796, trunk/freenet/src/freenet/io/comm/PacketSocketHandler.java)
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/PacketSocketHandler.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/io/comm/PacketSocketHandler.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,32 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.io.comm;
+
+import freenet.io.comm.Peer.LocalAddressException;
+
+/**
+ * Base class for UdpSocketHandler and any other datagram-based transports.
+ */
+public interface PacketSocketHandler extends SocketHandler {
+
+ /** The maximum size of a packet, not including transport layer headers
*/
+ int getMaxPacketSize();
+
+ /**
+ * Send a block of encoded bytes to a peer. This is called by
+ * send, and by IncomingPacketFilter.processOutgoing(..).
+ * @param blockToSend The data block to send.
+ * @param destination The peer to send it to.
+ */
+ public void sendPacket(byte[] blockToSend, Peer destination, boolean
allowLocalAddresses) throws LocalAddressException;
+
+ /**
+ * Get the size of the transport layer headers, for byte accounting
purposes.
+ */
+ int getHeadersLength();
+
+ /** Set the decryption filter to which incoming packets will be fed */
+ public void setLowLevelFilter(IncomingPacketFilter f);
+
+}
Modified: branches/freenet-jfk/src/freenet/io/comm/Peer.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/Peer.java 2007-08-21 19:57:05 UTC
(rev 14827)
+++ branches/freenet-jfk/src/freenet/io/comm/Peer.java 2007-08-21 20:26:59 UTC
(rev 14828)
@@ -92,6 +92,7 @@
public Peer(FreenetInetAddress addr, int port) {
this.addr = addr;
+ if(addr == null) throw new NullPointerException();
this._port = port;
}
@@ -194,4 +195,11 @@
public boolean isRealInternetAddress(boolean lookup, boolean
defaultVal) {
return addr.isRealInternetAddress(lookup, defaultVal);
}
+
+ /**
+ * Get the address:port string, but prefer numeric IPs - don't return
the name.
+ */
+ public String toStringPrefNumeric() {
+ return addr.toStringPrefNumeric()+':'+_port;
+ }
}
\ No newline at end of file
Modified: branches/freenet-jfk/src/freenet/io/comm/PeerContext.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/PeerContext.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/comm/PeerContext.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -4,6 +4,7 @@
package freenet.io.comm;
import freenet.io.xfer.PacketThrottle;
+import freenet.node.OutgoingPacketMangler;
/**
* @author amphibian
@@ -36,4 +37,10 @@
/** Get the PacketThrottle for the node's current address for the
standard packet size (if the
* address changes then we get a new throttle). */
public PacketThrottle getThrottle();
+
+ /** Get the SocketHandler which handles incoming packets from this node
*/
+ SocketHandler getSocketHandler();
+
+ /** Get the OutgoingPacketMangler which encrypts outgoing packets to
this node */
+ OutgoingPacketMangler getOutgoingMangler();
}
Modified: branches/freenet-jfk/src/freenet/io/comm/RetrievalException.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/RetrievalException.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/comm/RetrievalException.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -39,6 +39,7 @@
public static final int ALREADY_CACHED = 6;
public static final int SENDER_DISCONNECTED = 7;
public static final int NO_DATAINSERT = 8;
+ public static final int CANCELLED_BY_RECEIVER = 9;
int _reason;
String _cause;
Copied: branches/freenet-jfk/src/freenet/io/comm/SocketHandler.java (from rev
14796, trunk/freenet/src/freenet/io/comm/SocketHandler.java)
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/SocketHandler.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/io/comm/SocketHandler.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,14 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.io.comm;
+
+/**
+ * Base class for all transports. We have a single object of this type for
both incoming and
+ * outgoing packets, but multiple instances for different instances of the
transport e.g. on
+ * different ports, with different crypto backends etc.
+ * @author toad
+ */
+public interface SocketHandler {
+
+}
Copied: branches/freenet-jfk/src/freenet/io/comm/UdpSocketHandler.java (from
rev 14796, trunk/freenet/src/freenet/io/comm/UdpSocketHandler.java)
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/UdpSocketHandler.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/io/comm/UdpSocketHandler.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,375 @@
+package freenet.io.comm;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.util.Random;
+
+import org.tanukisoftware.wrapper.WrapperManager;
+
+import freenet.io.comm.Peer.LocalAddressException;
+import freenet.node.LoggingConfigHandler;
+import freenet.node.Node;
+import freenet.node.NodeInitException;
+import freenet.support.FileLoggerHook;
+import freenet.support.Logger;
+import freenet.support.OOMHandler;
+
+public class UdpSocketHandler extends Thread implements PacketSocketHandler {
+
+ private final DatagramSocket _sock;
+ private final InetAddress _bindTo;
+ private IncomingPacketFilter lowLevelFilter;
+ /** RNG for debugging, used with _dropProbability.
+ * NOT CRYPTO SAFE. DO NOT USE FOR THINGS THAT NEED CRYPTO SAFE RNG!
+ */
+ private Random dropRandom;
+ /** If >0, 1 in _dropProbability chance of dropping a packet; for
debugging */
+ private int _dropProbability;
+ // Icky layer violation, but we need to know the Node to work around
the EvilJVMBug.
+ private final Node node;
+ private static boolean logMINOR;
+ private volatile int lastTimeInSeconds;
+ private boolean _isDone;
+ private boolean _active = true;
+
+ public UdpSocketHandler(int listenPort, InetAddress bindto, Node node)
throws SocketException {
+ super("MessageCore packet receiver thread on port " +
listenPort);
+ this.node = node;
+ _bindTo = bindto;
+ // Keep the Updater code in, just commented out, for now
+ // We may want to be able to do on-line updates.
+// if (Updater.hasResource()) {
+// _sock = (DatagramSocket) Updater.getResource();
+// } else {
+ _sock = new DatagramSocket(listenPort, bindto);
+ int sz = _sock.getReceiveBufferSize();
+ if(sz < 32768)
+ _sock.setReceiveBufferSize(32768);
+ try {
+ // Exit reasonably quickly
+ _sock.setSoTimeout(1000);
+ } catch (SocketException e) {
+ throw new RuntimeException(e);
+ }
+// }
+ // Only used for debugging, no need to seed from Yarrow
+ dropRandom = new Random();
+ logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ }
+
+ /** Must be called, or we will NPE in run() */
+ public void setLowLevelFilter(IncomingPacketFilter f) {
+ lowLevelFilter = f;
+ }
+
+ public InetAddress getBindTo() {
+ return _bindTo;
+ }
+
+ public void run() { // Listen for packets
+ try {
+ runLoop();
+ } catch (Throwable t) {
+ // Impossible? It keeps on exiting. We get the below,
+ // but not this...
+ try {
+ System.err.print(t.getClass().getName());
+ System.err.println();
+ } catch (Throwable tt) {};
+ try {
+ System.err.print(t.getMessage());
+ System.err.println();
+ } catch (Throwable tt) {};
+ try {
+ System.gc();
+ System.runFinalization();
+ System.gc();
+ System.runFinalization();
+ } catch (Throwable tt) {}
+ try {
+ Runtime r = Runtime.getRuntime();
+ System.err.print(r.freeMemory());
+ System.err.println();
+ System.err.print(r.totalMemory());
+ System.err.println();
+ } catch (Throwable tt) {};
+ try {
+ t.printStackTrace();
+ } catch (Throwable tt) {};
+ } finally {
+ System.err.println("run() exiting for UdpSocketHandler
on port "+_sock.getLocalPort());
+ Logger.error(this, "run() exiting for UdpSocketHandler
on port "+_sock.getLocalPort());
+ synchronized (this) {
+ _isDone = true;
+ notifyAll();
+ }
+ }
+ }
+
+ private void runLoop() {
+ byte[] buf = new byte[MAX_RECEIVE_SIZE];
+ DatagramPacket packet = new DatagramPacket(buf, buf.length);
+ while (/*_active*/true) {
+ synchronized(this) {
+ if(!_active) return; // Finished
+ }
+ try {
+ lastTimeInSeconds = (int)
(System.currentTimeMillis() / 1000);
+ realRun(packet);
+ } catch (OutOfMemoryError e) {
+ OOMHandler.handleOOM(e);
+ System.err.println("Will retry above failed
operation...");
+ } catch (Throwable t) {
+ System.err.println("Caught "+t);
+ t.printStackTrace(System.err);
+ Logger.error(this, "Caught " + t, t);
+ }
+ }
+ }
+
+ private void realRun(DatagramPacket packet) {
+ // Single receiving thread
+ boolean gotPacket = getPacket(packet);
+ if (gotPacket) {
+ long startTime = System.currentTimeMillis();
+ Peer peer = new Peer(packet.getAddress(),
packet.getPort());
+ long endTime = System.currentTimeMillis();
+ if(endTime - startTime > 50) {
+ if(endTime-startTime > 3000)
+ Logger.error(this, "packet creation
took "+(endTime-startTime)+"ms");
+ else
+ if(logMINOR) Logger.minor(this, "packet
creation took "+(endTime-startTime)+"ms");
+ }
+ byte[] data = packet.getData();
+ int offset = packet.getOffset();
+ int length = packet.getLength();
+ try {
+ if(logMINOR) Logger.minor(this, "Processing
packet of length "+length+" from "+peer);
+ startTime = System.currentTimeMillis();
+ lowLevelFilter.process(data, offset, length,
peer);
+ endTime = System.currentTimeMillis();
+ if(endTime - startTime > 50) {
+ if(endTime-startTime > 3000)
+ Logger.error(this, "processing
packet took "+(endTime-startTime)+"ms");
+ else
+ if(logMINOR) Logger.minor(this,
"processing packet took "+(endTime-startTime)+"ms");
+ }
+ if(logMINOR) Logger.minor(this,
+ "Successfully handled packet
length " + length);
+ } catch (Throwable t) {
+ Logger.error(this, "Caught " + t + " from "
+ + lowLevelFilter, t);
+ }
+ } else if(logMINOR) Logger.minor(this, "Null packet");
+ }
+
+ // FIXME necessary to deal with bugs around build 1000; arguably necessary
to deal with large node names in connection setup
+ // Revert to 1500?
+ private static final int MAX_RECEIVE_SIZE = 2048;
+
+ private boolean getPacket(DatagramPacket packet) {
+ try {
+ _sock.receive(packet);
+ // TODO: keep?
+ IOStatisticCollector.addInfo(packet.getAddress() + ":"
+ packet.getPort(),
+ packet.getLength(), 0);
+ } catch (SocketTimeoutException e1) {
+ return false;
+ } catch (IOException e2) {
+ throw new RuntimeException(e2);
+ }
+ if(logMINOR) Logger.minor(this, "Received packet");
+ return true;
+ }
+
+ /**
+ * Send a block of encoded bytes to a peer. This is called by
+ * send, and by IncomingPacketFilter.processOutgoing(..).
+ * @param blockToSend The data block to send.
+ * @param destination The peer to send it to.
+ */
+ public void sendPacket(byte[] blockToSend, Peer destination, boolean
allowLocalAddresses) throws LocalAddressException {
+ assert(blockToSend != null);
+ // there should be no DNS needed here, but go ahead if we can,
but complain doing it
+ if( destination.getAddress(false, allowLocalAddresses) == null
) {
+ Logger.error(this, "Tried sending to destination
without pre-looked up IP address(needs a real Peer.getHostname()): null:" +
destination.getPort(), new Exception("error"));
+ if( destination.getAddress(true, allowLocalAddresses)
== null ) {
+ Logger.error(this, "Tried sending to bad
destination address: null:" + destination.getPort(), new Exception("error"));
+ return;
+ }
+ }
+ if (_dropProbability > 0) {
+ if (dropRandom.nextInt() % _dropProbability == 0) {
+ if(logMINOR) Logger.minor(this, "DROPPED: " +
_sock.getLocalPort() + " -> " + destination.getPort());
+ return;
+ }
+ }
+ InetAddress address = destination.getAddress(false,
allowLocalAddresses);
+ assert(address != null);
+ int port = destination.getPort();
+ DatagramPacket packet = new DatagramPacket(blockToSend,
blockToSend.length);
+ packet.setAddress(address);
+ packet.setPort(port);
+
+ // TODO: keep?
+ // packet.length() is simply the size of the buffer, it knows
nothing of UDP headers
+ IOStatisticCollector.addInfo(address + ":" + port, 0,
blockToSend.length + UDP_HEADERS_LENGTH);
+
+ try {
+ _sock.send(packet);
+ } catch (IOException e) {
+ if(packet.getAddress() instanceof Inet6Address)
+ Logger.normal(this, "Error while sending packet
to IPv6 address: "+destination+": "+e, e);
+ else
+ Logger.error(this, "Error while sending packet
to " + destination+": "+e, e);
+ }
+ }
+
+ // CompuServe use 1400 MTU; AOL claim 1450; DFN at home use 1448.
+ // http://info.aol.co.uk/broadband/faqHomeNetworking.adp
+ //
http://www.compuserve.de/cso/hilfe/linux/hilfekategorien/installation/contentview.jsp?conid=385700
+ // http://www.studenten-ins-netz.net/inhalt/service_faq.html
+ // officially GRE is 1476 and PPPoE is 1492.
+ // unofficially, PPPoE is often 1472 (seen in the wild). Also PPPoATM
is sometimes 1472.
+ static final int MAX_ALLOWED_MTU = 1400;
+ // FIXME this is different for IPv6 (check all uses of constant when
fixing)
+ public static final int UDP_HEADERS_LENGTH = 28;
+
+ /**
+ * @return The maximum packet size supported by this SocketManager, not
including transport (UDP/IP) headers.
+ */
+ public int getMaxPacketSize() { //FIXME: what about passing a peerNode
though and doing it on a per-peer basis?
+ final int minAdvertisedMTU = node.ipDetector.getMinimumDetectedMTU();
+
+ // We don't want the MTU detection thingy to prevent us to send
PacketTransmits!
+ if(minAdvertisedMTU < 1100){
+ Logger.error(this, "It shouldn't happen : we disabled the MTU
detection algorithm because the advertised MTU is smallish !!
("+node.ipDetector.getMinimumDetectedMTU()+')');
+ return MAX_ALLOWED_MTU - UDP_HEADERS_LENGTH;
+ } else
+ return Math.min(MAX_ALLOWED_MTU, minAdvertisedMTU) -
UDP_HEADERS_LENGTH;
+ // UDP/IP header is 28 bytes.
+ }
+
+ public void start() {
+ start(false);
+ }
+
+ public void start(boolean disableHangChecker) {
+ lastTimeInSeconds = (int) (System.currentTimeMillis() / 1000);
+ setDaemon(true);
+ setPriority(Thread.MAX_PRIORITY);
+ super.start();
+ if(!disableHangChecker) {
+ Thread checker = new Thread(new USMChecker(),
"MessageCore$USMChecker");
+ checker.setDaemon(true);
+ checker.setPriority(Thread.MAX_PRIORITY);
+ checker.start();
+ }
+ }
+
+ public class USMChecker implements Runnable {
+ public void run() {
+ while(true) {
+ if(_isDone) return; // don't synchronize
because don't want to deadlock - this is our recovery mechanism
+ logMINOR = Logger.shouldLog(Logger.MINOR,
UdpSocketHandler.this);
+ try {
+ Thread.sleep(10*1000);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ if(UdpSocketHandler.this.isAlive()) {
+ if(logMINOR) Logger.minor(this, "PING
on "+UdpSocketHandler.this);
+ long time = System.currentTimeMillis();
+ int timeSecs = (int) (time / 1000);
+ if(timeSecs - lastTimeInSeconds > 3*60)
{
+
+ // USM has hung.
+ // Probably caused by the
EvilJVMBug (see PacketSender).
+ // We'd better restart... :(
+
+ LoggingConfigHandler lch =
Node.logConfigHandler;
+ FileLoggerHook flh = lch ==
null ? null : lch.getFileLoggerHook();
+ boolean hasRedirected = flh ==
null ? false : flh.hasRedirectedStdOutErrNoLock();
+
+ if(!hasRedirected)
+
System.err.println("Restarting node: MessageCore froze for 3 minutes!");
+
+ try {
+
if(node.isUsingWrapper()){
+
WrapperManager.requestThreadDump();
+
WrapperManager.restart();
+ }else{
+
if(!hasRedirected)
+
System.err.println("Exiting on deadlock, but not running in the wrapper! Please
restart the node manually.");
+
+ // No wrapper :
we don't want to let it harm the network!
+ node.exit("USM
deadlock");
+ }
+ } catch (Throwable t) {
+ if(!hasRedirected) {
+
System.err.println("Error : can't restart the node : consider installing the
wrapper. PLEASE REPORT THAT ERROR TO devl at freenetproject.org");
+
t.printStackTrace();
+ }
+ node.exit("USM deadlock
and error");
+ }
+ }
+ } else {
+ if(_isDone) return;
+ // Final check
+ synchronized(this) {
+ if(_isDone) return;
+ }
+ Logger.error(this, "MAIN LOOP
TERMINATED");
+ System.err.println("MAIN LOOP
TERMINATED!");
+
node.exit(NodeInitException.EXIT_MAIN_LOOP_LOST);
+ }
+ }
+ }
+ }
+
+ public void close(boolean exit) {
+ Logger.normal(this, "Closing.", new Exception("error"));
+ synchronized (this) {
+ _active = false;
+ while (!_isDone) {
+ try {
+ wait(2000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ if (exit) {
+ _sock.close();
+ } else {
+ Logger.fatal(this, 10, "Not implemented: close(false)");
+ //Updater.saveResource(_sock);
+ }
+ }
+
+ public int getDropProbability() {
+ return _dropProbability;
+ }
+
+ public void setDropProbability(int dropProbability) {
+ _dropProbability = dropProbability;
+ }
+
+ public int getPortNumber() {
+ return _sock.getLocalPort();
+ }
+
+ public String toString() {
+ return _sock.getLocalAddress() + ":" + _sock.getLocalPort();
+ }
+
+ public int getHeadersLength() {
+ return UDP_HEADERS_LENGTH;
+ }
+
+}
Deleted: branches/freenet-jfk/src/freenet/io/comm/UdpSocketManager.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/comm/UdpSocketManager.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/comm/UdpSocketManager.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,851 +0,0 @@
-/*
- * Dijjer - A Peer to Peer HTTP Cache
- * Copyright (C) 2004,2005 Change.Tv, Inc
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-package freenet.io.comm;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import org.tanukisoftware.wrapper.WrapperManager;
-
-import freenet.io.comm.Peer.LocalAddressException;
-import freenet.node.LoggingConfigHandler;
-import freenet.node.Node;
-import freenet.node.PeerNode;
-import freenet.support.FileLoggerHook;
-import freenet.support.Logger;
-import freenet.support.OOMHandler;
-import freenet.support.TimeUtil;
-
-public class UdpSocketManager extends Thread {
-
- public static final String VERSION = "$Id: UdpSocketManager.java,v 1.22
2005/08/25 17:28:19 amphibian Exp $";
- private static boolean logMINOR;
- private Dispatcher _dispatcher;
- private final DatagramSocket _sock;
- /** _filters serves as lock for both */
- private final LinkedList _filters = new LinkedList();
- private final LinkedList _unclaimed = new LinkedList();
- private int _dropProbability;
- private IncomingPacketFilter lowLevelFilter;
- /** RNG for debugging, used with _dropProbability.
- * NOT CRYPTO SAFE. DO NOT USE FOR THINGS THAT NEED CRYPTO SAFE RNG!
- */
- private Random dropRandom;
- private boolean _isDone;
- private static UdpSocketManager _usm;
- private static final int MAX_UNMATCHED_FIFO_SIZE = 50000;
- private static final long MAX_UNCLAIMED_FIFO_ITEM_LIFETIME =
60*60*1000; // 1 hour
- private volatile int lastTimeInSeconds;
- private final InetAddress _bindTo;
-
- // Icky layer violation, but we need to know the Node to work around
the EvilJVMBug.
- private final Node node;
-
- public void start() {
- start(false);
- }
-
- public void start(boolean disableHangChecker) {
- lastTimeInSeconds = (int) (System.currentTimeMillis() / 1000);
- setDaemon(true);
- setPriority(Thread.MAX_PRIORITY);
- super.start();
- if(!disableHangChecker) {
- Thread checker = new Thread(new USMChecker(),
"UdpSocketManager$USMChecker");
- checker.setDaemon(true);
- checker.setPriority(Thread.MAX_PRIORITY);
- checker.start();
- }
- }
-
- public class USMChecker implements Runnable {
- public void run() {
- while(true) {
- logMINOR = Logger.shouldLog(Logger.MINOR,
UdpSocketManager.this);
- try {
- Thread.sleep(10*1000);
- } catch (InterruptedException e) {
- // Ignore
- }
- if(UdpSocketManager.this.isAlive()) {
- if(logMINOR) Logger.minor(this, "PING
on "+UdpSocketManager.this);
- long time = System.currentTimeMillis();
- int timeSecs = (int) (time / 1000);
- if(timeSecs - lastTimeInSeconds > 3*60)
{
-
- // USM has hung.
- // Probably caused by the
EvilJVMBug (see PacketSender).
- // We'd better restart... :(
-
- LoggingConfigHandler lch =
Node.logConfigHandler;
- FileLoggerHook flh = lch ==
null ? null : lch.getFileLoggerHook();
- boolean hasRedirected = flh ==
null ? false : flh.hasRedirectedStdOutErrNoLock();
-
- if(!hasRedirected)
-
System.err.println("Restarting node: UdpSocketManager froze for 3 minutes!");
-
- try {
-
if(node.isUsingWrapper()){
-
WrapperManager.requestThreadDump();
-
WrapperManager.restart();
- }else{
-
if(!hasRedirected)
-
System.err.println("Exiting on deadlock, but not running in the wrapper! Please
restart the node manually.");
-
- // No wrapper :
we don't want to let it harm the network!
- node.exit("USM
deadlock");
- }
- } catch (Throwable t) {
- if(!hasRedirected) {
-
System.err.println("Error : can't restart the node : consider installing the
wrapper. PLEASE REPORT THAT ERROR TO devl at freenetproject.org");
-
t.printStackTrace();
- }
- node.exit("USM deadlock
and error");
- }
- }
- } else {
- Logger.error(this, "MAIN LOOP
TERMINATED");
- System.err.println("MAIN LOOP
TERMINATED!");
- node.exit(Node.EXIT_MAIN_LOOP_LOST);
- }
- }
- }
- }
-
- public UdpSocketManager(int listenPort, InetAddress bindto, Node node)
throws SocketException {
- super("UdpSocketManager packet receiver thread on port " +
listenPort);
- this.node = node;
- _bindTo = bindto;
- // Keep the Updater code in, just commented out, for now
- // We may want to be able to do on-line updates.
-// if (Updater.hasResource()) {
-// _sock = (DatagramSocket) Updater.getResource();
-// } else {
- _sock = new DatagramSocket(listenPort, bindto);
- int sz = _sock.getReceiveBufferSize();
- if(sz < 32768)
- _sock.setReceiveBufferSize(32768);
- try {
- // We make it timeout every 100ms so that we can check
for
- // _filters which have timed out, this
- // is ugly but our only option without resorting to
java.nio
- // because there is no way to forcefully
- // interrupt a socket wait operation
- _sock.setSoTimeout(100);
- } catch (SocketException e) {
- throw new RuntimeException(e);
- }
-// }
- // Only used for debugging, no need to seed from Yarrow
- dropRandom = new Random();
- _timedOutFilters = new Vector(32);
- logMINOR = Logger.shouldLog(Logger.MINOR, this);
- }
-
- public InetAddress getBindTo() {
- return _bindTo;
- }
-
- public void run() { // Listen for packets
- try {
- runLoop();
- } catch (Throwable t) {
- // Impossible? It keeps on exiting. We get the below,
- // but not this...
- try {
- System.err.print(t.getClass().getName());
- System.err.println();
- } catch (Throwable tt) {};
- try {
- System.err.print(t.getMessage());
- System.err.println();
- } catch (Throwable tt) {};
- try {
- System.gc();
- System.runFinalization();
- System.gc();
- System.runFinalization();
- } catch (Throwable tt) {}
- try {
- Runtime r = Runtime.getRuntime();
- System.err.print(r.freeMemory());
- System.err.println();
- System.err.print(r.totalMemory());
- System.err.println();
- } catch (Throwable tt) {};
- try {
- t.printStackTrace();
- } catch (Throwable tt) {};
- } finally {
- System.err.println("run() exiting");
- Logger.error(this, "run() exiting");
- synchronized (this) {
- _isDone = true;
- notifyAll();
- }
- }
- }
-
- private void runLoop() {
- byte[] buf = new byte[MAX_RECEIVE_SIZE];
- DatagramPacket packet = new DatagramPacket(buf, buf.length);
- while (/*_active*/true) {
- try {
- lastTimeInSeconds = (int)
(System.currentTimeMillis() / 1000);
- realRun(packet);
- } catch (OutOfMemoryError e) {
- OOMHandler.handleOOM(e);
- System.err.println("Will retry above failed
operation...");
- } catch (Throwable t) {
- System.err.println("Caught "+t);
- t.printStackTrace(System.err);
- Logger.error(this, "Caught " + t, t);
- }
- }
- }
-
- private void realRun(DatagramPacket packet) {
- // Single receiving thread
- boolean gotPacket = getPacket(packet);
- // Check for timedout _filters
- removeTimedOutFilters();
- if (gotPacket) {
- long startTime = System.currentTimeMillis();
- Peer peer = new Peer(packet.getAddress(),
packet.getPort());
- long endTime = System.currentTimeMillis();
- if(endTime - startTime > 50) {
- if(endTime-startTime > 3000)
- Logger.error(this, "packet creation
took "+(endTime-startTime)+"ms");
- else
- if(logMINOR) Logger.minor(this, "packet
creation took "+(endTime-startTime)+"ms");
- }
- byte[] data = packet.getData();
- int offset = packet.getOffset();
- int length = packet.getLength();
- try {
- if(logMINOR) Logger.minor(this, "Processing
packet of length "+length+" from "+peer);
- startTime = System.currentTimeMillis();
- lowLevelFilter.process(data, offset, length,
peer);
- endTime = System.currentTimeMillis();
- if(endTime - startTime > 50) {
- if(endTime-startTime > 3000)
- Logger.error(this, "processing
packet took "+(endTime-startTime)+"ms");
- else
- if(logMINOR) Logger.minor(this,
"processing packet took "+(endTime-startTime)+"ms");
- }
- if(logMINOR) Logger.minor(this,
- "Successfully handled packet
length " + length);
- } catch (Throwable t) {
- Logger.error(this, "Caught " + t + " from "
- + lowLevelFilter, t);
- }
- } else if(logMINOR) Logger.minor(this, "Null packet");
- }
-
- /**
- * Decode a packet from data and a peer.
- * Can be called by IncomingPacketFilter's.
- * @param data
- * @param offset
- * @param length
- * @param peer
- */
- public Message decodeSingleMessage(byte[] data, int offset, int length,
PeerContext peer, int overhead) {
- try {
- return Message.decodeMessageFromPacket(data, offset, length, peer,
overhead);
- } catch (Throwable t) {
- Logger.error(this, "Could not decode packet: "+t, t);
- return null;
- }
- }
-
- // FIXME necessary to deal with bugs around build 1000; arguably necessary
to deal with large node names in connection setup
- // Revert to 1500?
- private static final int MAX_RECEIVE_SIZE = 2048;
-
- private boolean getPacket(DatagramPacket packet) {
- try {
- _sock.receive(packet);
- // TODO: keep?
- IOStatisticCollector.addInfo(packet.getAddress() + ":"
+ packet.getPort(),
- packet.getLength(), 0);
- } catch (SocketTimeoutException e1) {
- return false;
- } catch (IOException e2) {
- throw new RuntimeException(e2);
- }
- if(logMINOR) Logger.minor(this, "Received packet");
- return true;
- }
-
- /** Only used by removeTimedOutFilters() - if future code uses this
elsewhere, we need to
- * reconsider its locking. */
- private final Vector _timedOutFilters;
-
- /**
- * Remove timed out filters.
- * Only called by realRun(), so it can move timed out filters to the
_timedOutFilters array,
- * and then tell them that they are timed out without holding locks.
- *
- */
- private void removeTimedOutFilters() {
- long tStart = System.currentTimeMillis();
- synchronized (_filters) {
- for (ListIterator i = _filters.listIterator();
i.hasNext();) {
- MessageFilter f = (MessageFilter) i.next();
- if (f.timedOut()) {
- i.remove();
- _timedOutFilters.add(f);
- } else { // Because _filters are in order of
timeout, we
- // can abort the iteration as soon as
we find one that
- // doesn't timeout
- break;
- }
- }
- }
-
- for(int i=0;i<_timedOutFilters.size();i++) {
- MessageFilter f = (MessageFilter)
_timedOutFilters.get(i);
- f.setMessage(null);
- f.onTimedOut();
- }
- _timedOutFilters.clear();
-
- long tEnd = System.currentTimeMillis();
- if(tEnd - tStart > 50) {
- if(tEnd - tStart > 3000)
- Logger.error(this, "removeTimedOutFilters took
"+(tEnd-tStart)+"ms");
- else
- if(logMINOR) Logger.minor(this,
"removeTimedOutFilters took "+(tEnd-tStart)+"ms");
- }
- }
-
- /**
- * Dispatch a message to a waiting filter, or feed it to the
- * Dispatcher if none are found.
- * @param m The Message to dispatch.
- */
- public void checkFilters(Message m) {
- long tStart = System.currentTimeMillis();
- if(logMINOR) Logger.minor(this, "checkFilters: "+m+" from
"+m.getSource());
- if ((m.getSource()) instanceof PeerNode)
- {
-
((PeerNode)m.getSource()).addToLocalNodeReceivedMessagesFromStatistic(m);
- }
- boolean matched = false;
- if ((!(m.getSpec().equals(DMT.packetTransmit))) && logMINOR) {
- if ((m.getSpec().equals(DMT.ping) ||
m.getSpec().equals(DMT.pong)) && Logger.shouldLog(Logger.DEBUG, this)) {
- Logger.debug(this, "" +
(System.currentTimeMillis() % 60000) + ' ' + _sock.getLocalPort() + " <- "
- + m.getSource() + " : " + m);
- } else {
- if(logMINOR) Logger.minor(this, "" +
(System.currentTimeMillis() % 60000) + ' ' + _sock.getLocalPort() + " <- "
- + m.getSource() + " : " + m);
- }
- }
- MessageFilter match = null;
- synchronized (_filters) {
- for (ListIterator i = _filters.listIterator();
i.hasNext();) {
- MessageFilter f = (MessageFilter) i.next();
- if (f.match(m)) {
- matched = true;
- i.remove();
- match = f;
- if(logMINOR) Logger.minor(this,
"Matched: "+f);
- break; // Only one match permitted per
message
- }
- }
- }
- if(match != null) {
- match.setMessage(m);
- match.onMatched();
- }
- // Feed unmatched messages to the dispatcher
- if ((!matched) && (_dispatcher != null)) {
- try {
- if(logMINOR) Logger.minor(this, "Feeding to dispatcher:
"+m);
- matched = _dispatcher.handleMessage(m);
- } catch (Throwable t) {
- Logger.error(this, "Dispatcher threw "+t, t);
- }
- }
- // Keep the last few _unclaimed messages around in case the
intended receiver isn't receiving yet
- if (!matched) {
- if(logMINOR) Logger.minor(this, "Unclaimed: "+m);
- /** Check filters and then add to _unmatched is ATOMIC
- * It has to be atomic, because otherwise we can get a
- * race condition that results in timeouts on MFs.
- *
- * Specifically:
- * - Thread A receives packet
- * - Thread A checks filters. It doesn't match any.
- * - Thread A feeds to Dispatcher.
- * - Thread B creates filter.
- * - Thread B checks _unmatched.
- * - Thread B adds filter.
- * - Thread B sleeps.
- * - Thread A returns from Dispatcher. Which didn't match.
- * - Thread A adds to _unmatched.
- *
- * OOPS!
- * The only way to fix this is to have checking the
- * filters and unmatched be a single atomic operation.
- * Another race is possible if we merely recheck the
- * filters after we return from dispatcher, for example.
- */
- synchronized (_filters) {
- if(logMINOR) Logger.minor(this, "Rechecking
filters and adding message");
- for (ListIterator i = _filters.listIterator();
i.hasNext();) {
- MessageFilter f = (MessageFilter)
i.next();
- if (f.match(m)) {
- matched = true;
- match = f;
- i.remove();
- if(logMINOR) Logger.minor(this,
"Matched: "+f);
- break; // Only one match
permitted per message
- }
- }
- if(!matched) {
- while (_unclaimed.size() >
MAX_UNMATCHED_FIFO_SIZE) {
- Message removed =
(Message)_unclaimed.removeFirst();
- long messageLifeTime =
System.currentTimeMillis() - removed.localInstantiationTime;
- if ((removed.getSource()) instanceof
PeerNode) {
- Logger.normal(this, "Dropping
unclaimed from "+removed.getSource().getPeer()+", lived
"+TimeUtil.formatTime(messageLifeTime, 2, true)+" (quantity)"+": "+removed);
- } else {
- Logger.normal(this, "Dropping
unclaimed, lived "+TimeUtil.formatTime(messageLifeTime, 2, true)+"
(quantity)"+": "+removed);
- }
- }
- _unclaimed.addLast(m);
- if(logMINOR) Logger.minor(this, "Done");
- }
- }
- if(match != null) {
- match.setMessage(m);
- match.onMatched();
- }
- }
- long tEnd = System.currentTimeMillis();
- if(tEnd - tStart > 50) {
- if(tEnd - tStart > 3000)
- Logger.error(this, "checkFilters took
"+(tEnd-tStart)+"ms with unclaimedFIFOSize of "+_unclaimed.size()+" for
matched: "+matched);
- else
- if(logMINOR) Logger.minor(this, "checkFilters
took "+(tEnd-tStart)+"ms with unclaimedFIFOSize of "+_unclaimed.size()+" for
matched: "+matched);
- }
- }
-
- /** IncomingPacketFilter should call this when a node is disconnected.
*/
- public void onDisconnect(PeerContext ctx) {
- Vector droppedFilters = null; // rare operation, we can waste
objects for better locking
- synchronized(_filters) {
- ListIterator i = _filters.listIterator();
- while (i.hasNext()) {
- MessageFilter f = (MessageFilter) i.next();
- if(f.matchesDroppedConnection(ctx)) {
- if(droppedFilters == null)
- droppedFilters = new Vector();
- droppedFilters.add(f);
- i.remove();
- }
- }
- }
- if(droppedFilters != null) {
- for(int i=0;i<droppedFilters.size();i++) {
- MessageFilter mf = (MessageFilter)
droppedFilters.get(i);
- mf.onDroppedConnection(ctx);
- }
- }
- }
-
- /** IncomingPacketFilter should call this when a node connects with a
new boot ID */
- public void onRestart(PeerContext ctx) {
- Vector droppedFilters = null; // rare operation, we can waste
objects for better locking
- synchronized(_filters) {
- ListIterator i = _filters.listIterator();
- while (i.hasNext()) {
- MessageFilter f = (MessageFilter) i.next();
- if(f.matchesRestartedConnection(ctx)) {
- if(droppedFilters == null)
- droppedFilters = new Vector();
- droppedFilters.add(f);
- i.remove();
- }
- }
- }
- if(droppedFilters != null) {
- for(int i=0;i<droppedFilters.size();i++) {
- MessageFilter mf = (MessageFilter)
droppedFilters.get(i);
- mf.onRestartedConnection(ctx);
- }
- }
- }
-
- public void addAsyncFilter(MessageFilter filter,
AsyncMessageFilterCallback callback) throws DisconnectedException {
- filter.setAsyncCallback(callback);
- boolean logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
- if(logDEBUG) Logger.debug(this, "Adding async filter "+filter+"
for "+callback);
- Message ret = null;
- if((lowLevelFilter != null) && (filter._source != null) &&
- filter.matchesDroppedConnection(filter._source) &&
- lowLevelFilter.isDisconnected(filter._source))
- throw new DisconnectedException();
- // Check to see whether the filter matches any of the recently
_unclaimed messages
- // Drop any _unclaimed messages that the filter doesn't match
that are also older than MAX_UNCLAIMED_FIFO_ITEM_LIFETIME
- long now = System.currentTimeMillis();
- long messageDropTime = now - MAX_UNCLAIMED_FIFO_ITEM_LIFETIME;
- long messageLifeTime = 0;
- synchronized (_filters) {
- if(logMINOR) Logger.minor(this, "Checking _unclaimed");
- for (ListIterator i = _unclaimed.listIterator();
i.hasNext();) {
- Message m = (Message) i.next();
- if (filter.match(m)) {
- i.remove();
- ret = m;
- if(logMINOR) Logger.debug(this,
"Matching from _unclaimed");
- break;
- } else if (m.localInstantiationTime <
messageDropTime) {
- i.remove();
- messageLifeTime = now -
m.localInstantiationTime;
- if ((m.getSource()) instanceof
PeerNode) {
- Logger.normal(this, "Dropping
unclaimed from "+m.getSource().getPeer()+", lived
"+TimeUtil.formatTime(messageLifeTime, 2, true)+" (age)"+": "+m);
- } else {
- Logger.normal(this, "Dropping
unclaimed, lived "+TimeUtil.formatTime(messageLifeTime, 2, true)+" (age)"+":
"+m);
- }
- }
- }
- if (ret == null) {
- if(logMINOR) Logger.minor(this, "Not in
_unclaimed");
- // Insert filter into filter list in order of
timeout
- ListIterator i = _filters.listIterator();
- while (true) {
- if (!i.hasNext()) {
- i.add(filter);
- if(logMINOR) Logger.minor(this,
"Added at end");
- break;
- }
- MessageFilter mf = (MessageFilter)
i.next();
- if (mf.getTimeout() >
filter.getTimeout()) {
- i.previous();
- i.add(filter);
- if(logMINOR) Logger.minor(this,
"Added in middle - mf timeout="+mf.getTimeout()+" - my
timeout="+filter.getTimeout());
- break;
- }
- }
- }
- }
- if(ret != null) {
- filter.onMatched();
- filter.clearMatched();
- }
- }
-
- /**
- * Wait for a filter to trigger, or timeout. Blocks until either the
trigger is activated, or it times
- * out, or the peer is disconnected.
- * @param filter The filter to wait for.
- * @param ctr Byte counter to add bytes from the message to.
- * @return Either a message, or null if the filter timed out.
- * @throws DisconnectedException If the single peer being waited for
disconnects.
- */
- public Message waitFor(MessageFilter filter, ByteCounter ctr) throws
DisconnectedException {
- boolean logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
- if(logDEBUG) Logger.debug(this, "Waiting for "+filter);
- long startTime = System.currentTimeMillis();
- Message ret = null;
- if((lowLevelFilter != null) && (filter._source != null) &&
- filter.matchesDroppedConnection(filter._source) &&
- lowLevelFilter.isDisconnected(filter._source))
- throw new DisconnectedException();
- // Check to see whether the filter matches any of the recently
_unclaimed messages
- // Drop any _unclaimed messages that the filter doesn't match
that are also older than MAX_UNCLAIMED_FIFO_ITEM_LIFETIME
- long now = System.currentTimeMillis();
- long messageDropTime = now - MAX_UNCLAIMED_FIFO_ITEM_LIFETIME;
- long messageLifeTime = 0;
- synchronized (_filters) {
- if(logMINOR) Logger.minor(this, "Checking _unclaimed");
- for (ListIterator i = _unclaimed.listIterator();
i.hasNext();) {
- Message m = (Message) i.next();
- if (filter.match(m)) {
- i.remove();
- ret = m;
- if(logMINOR) Logger.debug(this,
"Matching from _unclaimed");
- break;
- } else if (m.localInstantiationTime <
messageDropTime) {
- i.remove();
- messageLifeTime = now -
m.localInstantiationTime;
- if ((m.getSource()) instanceof
PeerNode) {
- Logger.normal(this, "Dropping
unclaimed from "+m.getSource().getPeer()+", lived
"+TimeUtil.formatTime(messageLifeTime, 2, true)+" (age)"+": "+m);
- } else {
- Logger.normal(this, "Dropping
unclaimed, lived "+TimeUtil.formatTime(messageLifeTime, 2, true)+" (age)"+":
"+m);
- }
- }
- }
- if (ret == null) {
- if(logMINOR) Logger.minor(this, "Not in
_unclaimed");
- // Insert filter into filter list in order of
timeout
- ListIterator i = _filters.listIterator();
- while (true) {
- if (!i.hasNext()) {
- i.add(filter);
- if(logMINOR) Logger.minor(this,
"Added at end");
- break;
- }
- MessageFilter mf = (MessageFilter)
i.next();
- if (mf.getTimeout() >
filter.getTimeout()) {
- i.previous();
- i.add(filter);
- if(logMINOR) Logger.minor(this,
"Added in middle - mf timeout="+mf.getTimeout()+" - my
timeout="+filter.getTimeout());
- break;
- }
- }
- }
- }
- long tEnd = System.currentTimeMillis();
- if(tEnd - now > 50) {
- if(tEnd - now > 3000)
- Logger.error(this, "waitFor _unclaimed
iteration took "+(tEnd-now)+"ms with unclaimedFIFOSize of "+_unclaimed.size()+"
for ret of "+ret);
- else
- if(logMINOR) Logger.minor(this, "waitFor
_unclaimed iteration took "+(tEnd-now)+"ms with unclaimedFIFOSize of
"+_unclaimed.size()+" for ret of "+ret);
- }
- // Unlock to wait on filter
- // Waiting on the filter won't release the outer lock
- // So we have to release it here
- if(ret == null) {
- if(logMINOR) Logger.minor(this, "Waiting...");
- synchronized (filter) {
- try {
- // Precaution against filter getting
matched between being added to _filters and
- // here - bug discovered by Mason
- boolean fmatched = false;
- while(!(fmatched = (filter.matched() ||
(filter.droppedConnection() != null)))) {
- long wait =
filter.getTimeout()-System.currentTimeMillis();
- if(wait > 0)
- filter.wait(wait);
- else break;
- }
- if(filter.droppedConnection() != null)
- throw new DisconnectedException();
- if(logMINOR) Logger.minor(this, "Matched:
"+fmatched);
- } catch (InterruptedException e) {
- }
- ret = filter.getMessage();
- filter.clearMatched();
- }
- if(logDEBUG) Logger.debug(this, "Returning "+ret+" from
"+filter);
- } else {
- // Matched an unclaimed packet
- filter.onMatched();
- filter.clearMatched();
- }
- // Probably get rid...
-// if (Dijjer.getDijjer().getDumpMessageWaitTimes() != null) {
-//
Dijjer.getDijjer().getDumpMessageWaitTimes().println(filter.toString() + "\t" +
filter.getInitialTimeout() + "\t"
-// + (System.currentTimeMillis() -
startTime));
-// Dijjer.getDijjer().getDumpMessageWaitTimes().flush();
-// }
- long endTime = System.currentTimeMillis();
- if(logDEBUG) Logger.debug(this, "Returning in
"+(endTime-startTime)+"ms");
- if((ctr != null) && (ret != null))
- ctr.receivedBytes(ret._receivedByteCount);
- return ret;
- }
-
- /**
- * Send a Message to a PeerContext.
- * @throws NotConnectedException If we are not currently connected to
the node.
- */
- public void send(PeerContext destination, Message m, ByteCounter ctr)
throws NotConnectedException {
- if(m.getSpec().isInternalOnly()) {
- Logger.error(this, "Trying to send internal-only message "+m+"
of spec "+m.getSpec(), new Exception("debug"));
- return;
- }
- if ((m.getSpec().equals(DMT.ping) ||
m.getSpec().equals(DMT.pong)) && logMINOR) {
- if(Logger.shouldLog(Logger.DEBUG, this))
- Logger.debug(this, "" +
(System.currentTimeMillis() % 60000) + ' ' + _sock.getPort() + " -> " +
destination
- + " : " + m);
- } else {
- if(logMINOR) Logger.minor(this, "" +
(System.currentTimeMillis() % 60000) + ' ' + _sock.getPort() + " -> " +
destination
- + " : " + m);
- }
-// byte[] blockToSend = m.encodeToPacket(lowLevelFilter,
destination);
-// if(lowLevelFilter != null) {
-// try {
-// lowLevelFilter.processOutgoing(blockToSend, 0,
blockToSend.length, destination);
-// return;
-// } catch (IncomingPacketFilterException t) {
-// Logger.error(this, "Caught "+t+" sending "+m+"
to "+destination, t);
-// destination.forceDisconnect();
-// throw new NotConnectedException("Error
"+t.toString()+" forced disconnect");
-// }
-// } else {
-// sendPacket(blockToSend, destination.getPeer());
-// }
- destination.sendAsync(m, null, 0, ctr);
- }
-
- /**
- * Send a block of encoded bytes to a peer. This is called by
- * send, and by IncomingPacketFilter.processOutgoing(..).
- * @param blockToSend The data block to send.
- * @param destination The peer to send it to.
- */
- public void sendPacket(byte[] blockToSend, Peer destination, boolean
allowLocalAddresses) throws LocalAddressException {
- assert(blockToSend != null);
- // there should be no DNS needed here, but go ahead if we can,
but complain doing it
- if( destination.getAddress(false, allowLocalAddresses) == null
) {
- Logger.error(this, "Tried sending to destination
without pre-looked up IP address(needs a real Peer.getHostname()): null:" +
destination.getPort(), new Exception("error"));
- if( destination.getAddress(true, allowLocalAddresses)
== null ) {
- Logger.error(this, "Tried sending to bad
destination address: null:" + destination.getPort(), new Exception("error"));
- return;
- }
- }
- if (_dropProbability > 0) {
- if (dropRandom.nextInt() % _dropProbability == 0) {
- if(logMINOR) Logger.minor(this, "DROPPED: " +
_sock.getLocalPort() + " -> " + destination.getPort());
- return;
- }
- }
- InetAddress address = destination.getAddress(false,
allowLocalAddresses);
- assert(address != null);
- int port = destination.getPort();
- DatagramPacket packet = new DatagramPacket(blockToSend,
blockToSend.length);
- packet.setAddress(address);
- packet.setPort(port);
-
- // TODO: keep?
- // packet.length() is simply the size of the buffer, it knows
nothing of UDP headers
- IOStatisticCollector.addInfo(address + ":" + port, 0,
blockToSend.length + UDP_HEADERS_LENGTH);
-
- try {
- _sock.send(packet);
- } catch (IOException e) {
- if(packet.getAddress() instanceof Inet6Address)
- Logger.normal(this, "Error while sending packet
to IPv6 address: "+destination+": "+e, e);
- else
- Logger.error(this, "Error while sending packet
to " + destination+": "+e, e);
- }
- }
-
- public void close(boolean exit) {
- Logger.error(this, "Closing.", new Exception("error"));
- synchronized (this) {
- while (!_isDone) {
- try {
- wait(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- if (exit) {
- _sock.close();
- } else {
- Logger.fatal(this, 10, "Not implemented: close(false)");
- //Updater.saveResource(_sock);
- }
- }
-
- public void setDispatcher(Dispatcher d) {
- _dispatcher = d;
- }
-
- /** Must be called, or we will NPE */
- public void setLowLevelFilter(IncomingPacketFilter f) {
- lowLevelFilter = f;
- }
-
- public String toString() {
- return _sock.getLocalAddress() + ":" + _sock.getLocalPort();
- }
-
- public void setDropProbability(int dropProbability) {
- _dropProbability = dropProbability;
- }
-
- public static UdpSocketManager getUdpSocketManager()
- {
- return _usm;
- }
-
-// public static void init(int externalListenPort, InetAddress bindto)
-// throws SocketException
-// {
-// _usm = new UdpSocketManager(externalListenPort, bindto);
-// }
-//
- public int getPortNumber() {
- return _sock.getLocalPort();
- }
-
-
- // CompuServe use 1400 MTU; AOL claim 1450; DFN at home use 1448.
- // http://info.aol.co.uk/broadband/faqHomeNetworking.adp
- //
http://www.compuserve.de/cso/hilfe/linux/hilfekategorien/installation/contentview.jsp?conid=385700
- // http://www.studenten-ins-netz.net/inhalt/service_faq.html
- // officially GRE is 1476 and PPPoE is 1492.
- // unofficially, PPPoE is often 1472 (seen in the wild). Also PPPoATM
is sometimes 1472.
- static final int MAX_ALLOWED_MTU = 1400;
- // FIXME this is different for IPv6 (check all uses of constant when
fixing)
- public static final int UDP_HEADERS_LENGTH = 28;
-
- /**
- * @return The maximum packet size supported by this SocketManager, not
including transport (UDP/IP) headers.
- */
- public int getMaxPacketSize() { //FIXME: what about passing a peerNode
though and doing it on a per-peer basis?
- final int minAdvertisedMTU = node.ipDetector.getMinimumDetectedMTU();
-
- // We don't want the MTU detection thingy to prevent us to send
PacketTransmits!
- if(minAdvertisedMTU < 1100){
- Logger.error(this, "It shouldn't happen : we disabled the MTU
detection algorithm because the advertised MTU is smallish !!
("+node.ipDetector.getMinimumDetectedMTU()+')');
- return MAX_ALLOWED_MTU - UDP_HEADERS_LENGTH;
- } else
- return (minAdvertisedMTU < MAX_ALLOWED_MTU ? minAdvertisedMTU :
MAX_ALLOWED_MTU) - UDP_HEADERS_LENGTH;
- // UDP/IP header is 28 bytes.
- }
-
- /**
- * @return the number of received messages that are currently unclaimed
- */
- public int getUnclaimedFIFOSize() {
- synchronized (_filters){
- return _unclaimed.size();
- }
- }
-
- public Map getUnclaimedFIFOMessageCounts() {
- Map messageCounts = new HashMap();
- synchronized(_filters) {
- for (ListIterator i = _unclaimed.listIterator();
i.hasNext();) {
- Message m = (Message) i.next();
- String messageName = m.getSpec().getName();
- Integer messageCount = (Integer)
messageCounts.get(messageName);
- if (messageCount == null) {
- messageCounts.put(messageName, new
Integer(1) );
- } else {
- messageCount = new
Integer(messageCount.intValue() + 1);
- messageCounts.put(messageName,
messageCount );
- }
- }
- }
- return messageCounts;
- }
-
- public int getDropProbability() {
- return _dropProbability;
- }
-}
Modified: branches/freenet-jfk/src/freenet/io/xfer/BlockReceiver.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/xfer/BlockReceiver.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/xfer/BlockReceiver.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -29,7 +29,7 @@
import freenet.io.comm.NotConnectedException;
import freenet.io.comm.PeerContext;
import freenet.io.comm.RetrievalException;
-import freenet.io.comm.UdpSocketManager;
+import freenet.io.comm.MessageCore;
import freenet.support.BitArray;
import freenet.support.Buffer;
import freenet.support.Logger;
@@ -47,12 +47,12 @@
PartiallyReceivedBlock _prb;
PeerContext _sender;
long _uid;
- UdpSocketManager _usm;
+ MessageCore _usm;
/** packet : Integer -> reportTime : Long * */
HashMap _recentlyReportedMissingPackets = new HashMap();
ByteCounter _ctr;
- public BlockReceiver(UdpSocketManager usm, PeerContext sender, long
uid, PartiallyReceivedBlock prb, ByteCounter ctr) {
+ public BlockReceiver(MessageCore usm, PeerContext sender, long uid,
PartiallyReceivedBlock prb, ByteCounter ctr) {
_sender = sender;
_prb = prb;
_uid = uid;
Modified: branches/freenet-jfk/src/freenet/io/xfer/BlockTransmitter.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/xfer/BlockTransmitter.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/xfer/BlockTransmitter.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -26,16 +26,17 @@
import freenet.io.comm.DMT;
import freenet.io.comm.DisconnectedException;
import freenet.io.comm.Message;
+import freenet.io.comm.MessageCore;
import freenet.io.comm.MessageFilter;
import freenet.io.comm.NotConnectedException;
import freenet.io.comm.PeerContext;
-import freenet.io.comm.UdpSocketManager;
-import freenet.node.FNPPacketMangler;
import freenet.node.PeerNode;
import freenet.support.BitArray;
import freenet.support.DoubleTokenBucket;
+import freenet.support.Executor;
import freenet.support.Logger;
import freenet.support.TimeUtil;
+import freenet.support.transport.ip.IPUtil;
/**
* @author ian
@@ -45,22 +46,22 @@
public static final int SEND_TIMEOUT = 60000;
public static final int PING_EVERY = 8;
- UdpSocketManager _usm;
- PeerContext _destination;
- boolean _sendComplete;
- long _uid;
- PartiallyReceivedBlock _prb;
- LinkedList _unsent;
- Thread _receiverThread, _senderThread;
- BitArray _sentPackets;
+ final MessageCore _usm;
+ final PeerContext _destination;
+ private boolean _sendComplete;
+ final long _uid;
+ final PartiallyReceivedBlock _prb;
+ private LinkedList _unsent;
+ private Runnable _senderThread;
+ private BitArray _sentPackets;
boolean failedByOverload;
final PacketThrottle throttle;
- long timeAllSent = -1;
+ private long timeAllSent = -1;
final DoubleTokenBucket _masterThrottle;
final ByteCounter _ctr;
final int PACKET_SIZE;
- public BlockTransmitter(UdpSocketManager usm, PeerContext destination,
long uid, PartiallyReceivedBlock source, DoubleTokenBucket masterThrottle,
ByteCounter ctr) {
+ public BlockTransmitter(MessageCore usm, PeerContext destination, long
uid, PartiallyReceivedBlock source, DoubleTokenBucket masterThrottle,
ByteCounter ctr) {
_usm = usm;
_destination = destination;
_uid = uid;
@@ -68,7 +69,7 @@
_ctr = ctr;
_masterThrottle = masterThrottle;
PACKET_SIZE = DMT.packetTransmitSize(_prb._packetSize,
_prb._packets)
- + FNPPacketMangler.FULL_HEADERS_LENGTH_ONE_MESSAGE;
+ +
destination.getOutgoingMangler().fullHeadersLengthOneMessage();
try {
_sentPackets = new BitArray(_prb.getNumPackets());
} catch (AbortedException e) {
@@ -76,7 +77,7 @@
// Will throw on running
}
throttle = _destination.getThrottle();
- _senderThread = new Thread("_senderThread for "+_uid+ " to
"+_destination.getPeer()) {
+ _senderThread = new Runnable() {
public void run() {
while (!_sendComplete) {
@@ -144,7 +145,8 @@
// Get the current inter-packet delay
long end =
throttle.scheduleDelay(startThrottle);
- _masterThrottle.blockingGrab(PACKET_SIZE);
+
if(IPUtil.isValidAddress(_destination.getPeer().getAddress(), false))
+
_masterThrottle.blockingGrab(PACKET_SIZE);
long now = System.currentTimeMillis();
@@ -172,16 +174,13 @@
}
}
};
- _senderThread.setDaemon(true);
}
public void sendAborted(int reason, String desc) throws
NotConnectedException {
_usm.send(_destination, DMT.createSendAborted(_uid, reason,
desc), _ctr);
}
- public boolean send() {
- _receiverThread = Thread.currentThread();
-
+ public boolean send(Executor executor) {
PartiallyReceivedBlock.PacketReceivedListener myListener;
try {
@@ -206,7 +205,7 @@
}
});
}
- _senderThread.start();
+ executor.execute(_senderThread, "BlockTransmitter
sender for "+_uid);
while (true) {
if (_prb.isAborted()) {
@@ -230,7 +229,7 @@
}
if(logMINOR) Logger.minor(this, "Got "+msg);
if(!_destination.isConnected()) {
- Logger.normal(this, "Terminating send
"+_uid+" to "+_destination+" from "+_usm.getPortNumber()+" because node
disconnected while waiting");
+ Logger.normal(this, "Terminating send
"+_uid+" to "+_destination+" from "+_destination.getSocketHandler()+" because
node disconnected while waiting");
synchronized(_senderThread) {
_sendComplete = true;
_senderThread.notifyAll();
@@ -247,7 +246,7 @@
_sendComplete = true;
_senderThread.notifyAll();
}
- Logger.error(this, "Terminating
send "+_uid+" to "+_destination+" from "+_usm.getPortNumber()+" as we haven't
heard from receiver in "+TimeUtil.formatTime((now - timeAllSent), 2, true)+
'.');
+ Logger.error(this, "Terminating
send "+_uid+" to "+_destination+" from "+_destination.getSocketHandler()+" as
we haven't heard from receiver in "+TimeUtil.formatTime((now - timeAllSent), 2,
true)+ '.');
return false;
} else {
if(logMINOR) Logger.minor(this,
"Ignoring timeout: timeAllSent="+timeAllSent+" ("+(System.currentTimeMillis() -
timeAllSent)+"), getNumSent="+getNumSent()+ '/' +_prb.getNumPackets());
@@ -310,12 +309,10 @@
/**
* Send the data, off-thread.
*/
- public void sendAsync() {
- Runnable r = new Runnable() {
- public void run() { send(); } };
- Thread t = new Thread(r, "BlockTransmitter:sendAsync() for
"+this);
- t.setDaemon(true);
- t.start();
+ public void sendAsync(final Executor executor) {
+ executor.execute(new Runnable() {
+ public void run() { send(executor); } },
+ "BlockTransmitter:sendAsync() for "+this);
}
public void waitForComplete() {
Modified: branches/freenet-jfk/src/freenet/io/xfer/BulkReceiver.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/xfer/BulkReceiver.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/xfer/BulkReceiver.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -54,9 +54,9 @@
* @return True if the whole file was received, false otherwise.
*/
public boolean receive() {
- MessageFilter mfSendKilled =
MessageFilter.create().setSource(peer).setType(DMT.FNPBulkSendAborted)
.setField(DMT.UID, uid).setTimeout(TIMEOUT);
- MessageFilter mfPacket =
MessageFilter.create().setSource(peer).setType(DMT.FNPBulkPacketSend)
.setField(DMT.UID, uid).setTimeout(TIMEOUT);
while(true) {
+ MessageFilter mfSendKilled =
MessageFilter.create().setSource(peer).setType(DMT.FNPBulkSendAborted)
.setField(DMT.UID, uid).setTimeout(TIMEOUT);
+ MessageFilter mfPacket =
MessageFilter.create().setSource(peer).setType(DMT.FNPBulkPacketSend)
.setField(DMT.UID, uid).setTimeout(TIMEOUT);
if(prb.hasWholeFile()) {
try {
peer.sendAsync(DMT.createFNPBulkReceivedAll(uid), null, 0, null);
Modified: branches/freenet-jfk/src/freenet/io/xfer/BulkTransmitter.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/xfer/BulkTransmitter.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/xfer/BulkTransmitter.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -13,6 +13,7 @@
import freenet.support.BitArray;
import freenet.support.DoubleTokenBucket;
import freenet.support.Logger;
+import freenet.support.transport.ip.IPUtil;
/**
* Bulk data transfer (not block). Bulk transfer is designed for files which
may be much bigger than a
@@ -40,6 +41,7 @@
final DoubleTokenBucket masterThrottle;
private boolean sentCancel;
private boolean finished;
+ final int packetSize;
public BulkTransmitter(PartiallyReceivedBulk prb, PeerContext peer,
long uid, DoubleTokenBucket masterThrottle) throws DisconnectedException {
this.prb = prb;
@@ -87,6 +89,8 @@
cancel();
throw e;
}
+ packetSize = DMT.bulkPacketTransmitSize(prb.blockSize) +
+ peer.getOutgoingMangler().fullHeadersLengthOneMessage();
}
/**
@@ -145,7 +149,6 @@
* @return True if the file was successfully sent. False otherwise.
*/
public boolean send() {
- int packetSize = prb.getPacketSize();
long lastSentPacket = System.currentTimeMillis();
while(true) {
if(prb.isAborted()) return false;
@@ -191,7 +194,8 @@
long now = System.currentTimeMillis();
long waitUntil = peer.getThrottle().scheduleDelay(now);
- masterThrottle.blockingGrab(packetSize);
+ if(IPUtil.isValidAddress(peer.getPeer().getAddress(),
false))
+ masterThrottle.blockingGrab(packetSize);
while((now = System.currentTimeMillis()) < waitUntil) {
long sleepTime = waitUntil - now;
Modified: branches/freenet-jfk/src/freenet/io/xfer/PartiallyReceivedBulk.java
===================================================================
--- branches/freenet-jfk/src/freenet/io/xfer/PartiallyReceivedBulk.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/io/xfer/PartiallyReceivedBulk.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -5,10 +5,8 @@
import java.io.IOException;
-import freenet.io.comm.DMT;
+import freenet.io.comm.MessageCore;
import freenet.io.comm.RetrievalException;
-import freenet.io.comm.UdpSocketManager;
-import freenet.node.FNPPacketMangler;
import freenet.support.BitArray;
import freenet.support.Logger;
import freenet.support.io.RandomAccessThing;
@@ -31,11 +29,10 @@
private final BitArray blocksReceived;
final int blocks;
private BulkTransmitter[] transmitters;
- final UdpSocketManager usm;
+ final MessageCore usm;
/** The one and only BulkReceiver */
private BulkReceiver recv;
private int blocksReceivedCount;
- final int packetSize;
// Abort status
boolean _aborted;
int _abortReason;
@@ -49,7 +46,7 @@
* @param initialState If true, assume all blocks have been received.
If false, assume no blocks have
* been received.
*/
- public PartiallyReceivedBulk(UdpSocketManager usm, long size, int
blockSize, RandomAccessThing raf, boolean initialState) {
+ public PartiallyReceivedBulk(MessageCore usm, long size, int blockSize,
RandomAccessThing raf, boolean initialState) {
this.size = size;
this.blockSize = blockSize;
this.raf = raf;
@@ -63,8 +60,6 @@
blocksReceived.setAllOnes();
blocksReceivedCount = this.blocks;
}
- packetSize = DMT.bulkPacketTransmitSize(blockSize) +
- FNPPacketMangler.FULL_HEADERS_LENGTH_ONE_MESSAGE; //
FIXME generalise
}
/**
@@ -99,9 +94,11 @@
* @param offset The start of the data in the buffer.
*/
void received(int blockNum, byte[] data, int offset, int length) {
+ if(Logger.shouldLog(Logger.MINOR, this))
+ Logger.minor(this, "Received block "+blockNum);
BulkTransmitter[] notifyBTs;
long fileOffset = (long)blockNum * (long)blockSize;
- int bs = (int) Math.max(blockSize, size - fileOffset);
+ int bs = (int) Math.min(blockSize, size - fileOffset);
if(length < bs) {
String err = "Data too short! Should be "+bs+" actually
"+length;
Logger.error(this, err+" for "+this);
@@ -127,7 +124,7 @@
}
}
- void abort(int errCode, String why) {
+ public void abort(int errCode, String why) {
BulkTransmitter[] notifyBTs;
BulkReceiver notifyBR;
synchronized(this) {
@@ -144,23 +141,20 @@
}
if(notifyBR != null)
notifyBR.onAborted();
+ raf.close();
}
public synchronized boolean isAborted() {
return _aborted;
}
- public int getPacketSize() {
- return packetSize;
- }
-
public boolean hasWholeFile() {
return blocksReceivedCount >= blocks;
}
public byte[] getBlockData(int blockNum) {
long fileOffset = (long)blockNum * (long)blockSize;
- int bs = (int) Math.max(blockSize, size - fileOffset);
+ int bs = (int) Math.min(blockSize, size - fileOffset);
byte[] data = new byte[bs];
try {
raf.pread(fileOffset, data, 0, bs);
@@ -173,6 +167,11 @@
}
public synchronized void remove(BulkTransmitter remove) {
+ boolean found = false;
+ for(int i=0;i<transmitters.length;i++) {
+ if(transmitters[i] == remove) found = true;
+ }
+ if(!found) return;
BulkTransmitter[] newTrans = new
BulkTransmitter[transmitters.length-1];
int j = 0;
for(int i=0;i<transmitters.length;i++) {
Modified: branches/freenet-jfk/src/freenet/keys/ClientCHK.java
===================================================================
--- branches/freenet-jfk/src/freenet/keys/ClientCHK.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/keys/ClientCHK.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -136,6 +136,9 @@
}
public NodeCHK getNodeCHK() {
+ // This costs us more or less nothing: we have to keep the
routingKey anyway.
+ // Therefore, keeping a NodeCHK as well is a net saving, since
it's frequently
+ // asked for. (A SoftReference would cost more).
if(nodeKey == null)
nodeKey = new NodeCHK(routingKey, cryptoAlgorithm);
return nodeKey;
Modified: branches/freenet-jfk/src/freenet/keys/ClientSSKBlock.java
===================================================================
--- branches/freenet-jfk/src/freenet/keys/ClientSSKBlock.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/keys/ClientSSKBlock.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -34,8 +34,12 @@
this.key = key;
}
- public ClientSSKBlock(SSKBlock block, ClientSSK key) throws
SSKVerifyException {
- this(block.data, block.headers, key, false);
+ public static ClientSSKBlock construct(SSKBlock block, ClientSSK key)
throws SSKVerifyException {
+ // Constructor expects clientkey to have the pubkey.
+ // In the case of binary blobs, the block may have it instead.
+ if(key.getPubKey() == null && block.getPubKey() != null)
+ key.setPublicKey(block.getPubKey());
+ return new ClientSSKBlock(block.data, block.headers, key,
false);
}
/**
Modified: branches/freenet-jfk/src/freenet/keys/FreenetURI.java
===================================================================
--- branches/freenet-jfk/src/freenet/keys/FreenetURI.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/keys/FreenetURI.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -728,9 +728,12 @@
boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
Logger.minor(this, "Getting preferred filename for "+this);
Vector names = new Vector();
- if(keyType != null && (keyType.equals("KSK") ||
keyType.equals("SSK"))) {
+ if(keyType != null && (keyType.equals("KSK") ||
keyType.equals("SSK") || keyType.equals("USK"))) {
if(logMINOR) Logger.minor(this, "Adding docName:
"+docName);
names.add(docName);
+ if(keyType.equals("USK")) {
+ names.add(Long.toString(suggestedEdition));
+ }
}
if(metaStr != null)
for(int i=0;i<metaStr.length;i++) {
Modified: branches/freenet-jfk/src/freenet/keys/Key.java
===================================================================
--- branches/freenet-jfk/src/freenet/keys/Key.java 2007-08-21 19:57:05 UTC
(rev 14827)
+++ branches/freenet-jfk/src/freenet/keys/Key.java 2007-08-21 20:26:59 UTC
(rev 14828)
@@ -249,4 +249,11 @@
public byte[] getKeyBytes() {
return routingKey;
}
+
+ public static ClientKeyBlock createKeyBlock(ClientKey key, KeyBlock
block) throws KeyVerifyException {
+ if(key instanceof ClientSSK)
+ return ClientSSKBlock.construct((SSKBlock)block,
(ClientSSK)key);
+ else //if(key instanceof ClientCHK
+ return new ClientCHKBlock((CHKBlock)block,
(ClientCHK)key);
+ }
}
Modified: branches/freenet-jfk/src/freenet/keys/NodeCHK.java
===================================================================
--- branches/freenet-jfk/src/freenet/keys/NodeCHK.java 2007-08-21 19:57:05 UTC
(rev 14827)
+++ branches/freenet-jfk/src/freenet/keys/NodeCHK.java 2007-08-21 20:26:59 UTC
(rev 14828)
@@ -7,8 +7,6 @@
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
-import java.util.Arrays;
-
import freenet.support.Base64;
/**
Modified: branches/freenet-jfk/src/freenet/keys/TooBigException.java
===================================================================
--- branches/freenet-jfk/src/freenet/keys/TooBigException.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/keys/TooBigException.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -4,6 +4,11 @@
public class TooBigException extends IOException {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
public TooBigException(String msg) {
super(msg);
}
Modified: branches/freenet-jfk/src/freenet/keys/USK.java
===================================================================
--- branches/freenet-jfk/src/freenet/keys/USK.java 2007-08-21 19:57:05 UTC
(rev 14827)
+++ branches/freenet-jfk/src/freenet/keys/USK.java 2007-08-21 20:26:59 UTC
(rev 14828)
@@ -139,4 +139,27 @@
public String toString() {
return super.toString()+ ':' +getURI();
}
+
+ public FreenetURI turnMySSKIntoUSK(FreenetURI uri) {
+ if(uri.getKeyType().equals("SSK") &&
+ Arrays.equals(uri.getRoutingKey(), pubKeyHash)
&&
+ Arrays.equals(uri.getCryptoKey(), cryptoKey) &&
+ Arrays.equals(uri.getExtra(),
ClientSSK.getExtraBytes(cryptoAlgorithm)) &&
+ uri.getDocName() != null &&
+ uri.getDocName().startsWith(siteName)) {
+ String doc = uri.getDocName();
+ doc = doc.substring(siteName.length());
+ if(doc.length() < 2 || doc.charAt(0) != '-') return uri;
+ long edition;
+ try {
+ edition = Long.parseLong(doc);
+ } catch (NumberFormatException e) {
+ Logger.normal(this, "Trying to turn SSK back
into USK: "+uri+" doc="+doc+" caught "+e, e);
+ return uri;
+ }
+ if(!doc.equals(Long.toString(edition))) return uri;
+ return new FreenetURI("USK", siteName,
uri.getAllMetaStrings(), pubKeyHash, cryptoKey,
ClientSSK.getExtraBytes(cryptoAlgorithm), edition);
+ }
+ return uri;
+ }
}
Modified: branches/freenet-jfk/src/freenet/l10n/L10n.java
===================================================================
--- branches/freenet-jfk/src/freenet/l10n/L10n.java 2007-08-21 19:57:05 UTC
(rev 14827)
+++ branches/freenet-jfk/src/freenet/l10n/L10n.java 2007-08-21 20:26:59 UTC
(rev 14828)
@@ -37,7 +37,7 @@
// English has to remain the first one!
public static final String FALLBACK_DEFAULT = "en";
- public static final String[] AVAILABLE_LANGUAGES = { "en", "fr", "pl",
"it", "se", "no", "unlisted" };
+ public static final String[] AVAILABLE_LANGUAGES = { "en", "de", "fr",
"it", "no", "pl", "se", "unlisted" };
private final String selectedLanguage;
private static SimpleFieldSet currentTranslation = null;
@@ -223,8 +223,10 @@
}
if(result != null)
return result;
- else
+ else {
+ Logger.normal(CLASS_NAME, "The translation for " + key
+ " hasn't been found ("+getSelectedLanguage()+")! please tell the
maintainer.");
return (returnNullIfNotFound ? null :
getDefaultString(key));
+ }
}
/**
@@ -262,11 +264,10 @@
}
if(result != null) {
- Logger.normal(CLASS_NAME, "The translation for " + key
+ " hasn't been found! please tell the maintainer.");
return result;
}
- Logger.error(CLASS_NAME, "The translation for " + key + "
hasn't been found!");
- System.err.println("The translation for " + key + " hasn't been
found!");
+ Logger.error(CLASS_NAME, "The default translation for " + key +
" hasn't been found!");
+ System.err.println("The default translation for " + key + "
hasn't been found!");
new Exception().printStackTrace();
return key;
}
@@ -316,6 +317,7 @@
*/
public static String getSelectedLanguage() {
synchronized (sync) {
+ if(currentClass == null) return null;
return currentClass.selectedLanguage;
}
}
@@ -339,7 +341,7 @@
if(in != null)
result = SimpleFieldSet.readFrom(in, false,
false);
} catch (Exception e) {
- Logger.error("L10n", "Error while loading the l10n file
from " + name + " :" + e.getMessage());
+ Logger.error("L10n", "Error while loading the l10n file
from " + name + " :" + e.getMessage(), e);
result = null;
} finally {
if (in != null) try { in.close(); } catch (Throwable
ignore) {}
Copied: branches/freenet-jfk/src/freenet/l10n/freenet.l10n.de.properties (from
rev 14796, trunk/freenet/src/freenet/l10n/freenet.l10n.de.properties)
===================================================================
--- branches/freenet-jfk/src/freenet/l10n/freenet.l10n.de.properties
(rev 0)
+++ branches/freenet-jfk/src/freenet/l10n/freenet.l10n.de.properties
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,993 @@
+BookmarkEditorToadlet.addBookmark=Lesezeichen hinzuf?gen
+BookmarkEditorToadlet.addCategory=Kategorie hinzuf?gen
+BookmarkEditorToadlet.addNewBookmark=Ein neues Lesezeichen hinzuf?gen
+BookmarkEditorToadlet.addNewCategory=Eine neue Kategorie hinzuf?gen
+BookmarkEditorToadlet.addedNewBookmark=Das neue Lesezeichen wurde erfolgreich
hinzugef?gt.
+BookmarkEditorToadlet.addedNewBookmarkTitle=Neues Lesezeichen hinzugef?gt
+BookmarkEditorToadlet.bookmarkDoesNotExist=Das Lesezeichen "${bookmark}"
existiert nicht.
+BookmarkEditorToadlet.cancelCut=Ausschneiden abbrechen
+BookmarkEditorToadlet.changesSaved=Die ?nderungen wurden erfolgreich
gespeichert.
+BookmarkEditorToadlet.changesSavedTitle=?nderungen gespeichert
+BookmarkEditorToadlet.confirmDelete=L?schen
+BookmarkEditorToadlet.cut=Ausschneiden
+BookmarkEditorToadlet.delete=L?schen
+BookmarkEditorToadlet.deleteBookmark=Lesezeichen l?schen
+BookmarkEditorToadlet.deleteBookmarkConfirm=Sind Sie sich sicher, dass Sie
${bookmark} l?schen wollen?
+BookmarkEditorToadlet.deleteCategory=Kategorie l?schen
+BookmarkEditorToadlet.deleteCategoryConfirm=Sind Sie sich sicher, dass Sie
${bookmark} und alle Untergeordneten l?schen wollen?
+BookmarkEditorToadlet.deleteSucceeded=Das Lesezeichen wurde erfolgreich
gel?scht.
+BookmarkEditorToadlet.deleteSucceededTitle=L?schen erfolgreich
+BookmarkEditorToadlet.edit=?ndern
+BookmarkEditorToadlet.editBookmarkTitle=Lesezeichen ?ndern
+BookmarkEditorToadlet.editCategoryTitle=Kategorie bearbeiten
+BookmarkEditorToadlet.error=Fehler
+BookmarkEditorToadlet.invalidKey=Der Freenet-Schl?ssel ist ung?ltig.
+BookmarkEditorToadlet.invalidKeyTitle=Ung?ltiger Schl?ssel
+BookmarkEditorToadlet.invalidKeyWithReason=Ung?ltiger Freenet-Schl?ssel.
+BookmarkEditorToadlet.keyLabel=Schl?ssel:
+BookmarkEditorToadlet.moveDown=Runter
+BookmarkEditorToadlet.moveUp=Hoch
+BookmarkEditorToadlet.myBookmarksTitle=Meine Lesezeichen
+BookmarkEditorToadlet.nameLabel=Name:
+BookmarkEditorToadlet.paste=Einf?gen
+BookmarkEditorToadlet.pasteOrCancel=Klicken Sie auf ein Einf?gen-Symbol oder
Abbrechen.
+BookmarkEditorToadlet.pasteTitle=Ausschneiden/Einf?gen
+BookmarkEditorToadlet.save=Speichern
+BookmarkEditorToadlet.title=Lesezeichen-Editor
+BookmarkEditorToadlet.urlDecodeError=URL-Dekodier-Fehler
+BookmarkItem.bookmarkUpdated=Die in den Lesezeichen gespeicherte Seite ${name}
wurde auf die Ausgabe ${edition} aktualisiert.
+BookmarkItem.bookmarkUpdatedTitle=Lesezeichen aktualisiert: ${name}
+BookmarkItem.bookmarkUpdatedWithLink=Die in den Lesezeichen gespeicherte Seite
${link}${name}${/link} wurde auf die Ausgabe ${edition} aktualisiert.
+BookmarkItem.deleteBookmarkUpdateNotification=Benachrichtigung l?schen
+BookmarkItem.unnamedBookmark=Unbenanntes Lesezeichen
+BookmarkManager.list=Liste von Lesezeichen
+BookmarkManager.listLong=Eine Liste von Lesezeichen von Freesites
+BookmarkManager.malformedBookmark=Missgebildetes Lesezeichen
+BooleanOption.parseError=Unbekannter Boolescher Wert: ${val} - versuchen Sie
true oder false
+BuildOldAgeUserAlert.tooOld=Die Software dieses Knotens ist ?lter, als die
?lteste Version (Build #${lastgood}), die von dem neusten Partner, zu dem
Kontakt aufgenommen wird, akzeptiert wird. Bitte aktualisieren Sie ihren
Knoten so bald wie m?glich, da Sie keinen Kontakt zu Partnern aufnehmen k?nnen,
welche mit "ZU NEU" gekennzeichnet sind, bis Sie dies tun. (Freenet k?nnte
ihren Knoten im "Staub der Vergangenheit" zur?cklassen, wenn Sie ihn nicht
aktualisieren.)
+BuildOldAgeUserAlert.tooOldTitle=Build (Version) zu alt.
+CSSTokenizerFilter.deletedDisallowedString=Nicht erlaubte Zeichenfolge gel?scht
+CSSTokenizerFilter.deletedUnmatchedChar=Unerreichbare Zeichen ignoriert:
+CSSTokenizerFilter.deletedUnofficialIdent=Inoffizieller Bezeichner gel?scht
+CSSTokenizerFilter.deletedUnofficialIdentWithURL=Inoffizieller Bezeichner mit
url gel?scht
+CSSTokenizerFilter.invalidURLContents=Ung?ltige Inhalte der url()
+CSSTokenizerFilter.supplementalCharsNotSupported=UCS-4-ZEICHEN OBERHALB VON
0xFFFF WERDEN NICHT UNTERST?TZT!
+CSSTokenizerFilter.unknownAtIdentifierLabel=Unbekannter @Bezeichner:
+ConfigToadlet.appliedFailureExceptions=Ihre ?nderungen der Konfiguration
wurden, mit folgenden Ausnahmen, ?bernommen:
+ConfigToadlet.appliedFailureTitle=Konfiguration nicht ?bernommen
+ConfigToadlet.appliedSuccess=Die ?nderungen in der Konfiguration wurden
erfolgreich ?bernommen.
+ConfigToadlet.appliedTitle=Konfiguration wurde ?bernommen
+ConfigToadlet.apply=?bernehmen
+ConfigToadlet.configNavTitle=Konfigurations-Navigation
+ConfigToadlet.contributeTranslation=Zur ?bersetzung beitragen
+ConfigToadlet.defaultIs=Der Standard-Wert f?r diese Einstellung ist:
"${default}".
+ConfigToadlet.fullTitle=Freenet-Knoten-Konfiguration von ${name}
+ConfigToadlet.possibilitiesTitle=Ihre M?glichkeiten
+ConfigToadlet.reset=Zur?cksetzen
+ConfigToadlet.returnToNodeConfig=Zur?ck zur Knoten-Konfiguration
+ConfigToadlet.shortTitle=Konfiguration
+ConfigToadlet.title=Freenet-Knoten-Konfiguration
+ConfigurablePersister.doesNotExistCannotCreate=Datei existiert nicht und kann
nicht erzeugt werden
+ConfigurablePersister.existsCannotReadWrite=Datei existiert und kann nicht
gelesen/geschrieben werden
+ContentDataFilter.unknownCharset=Die Seite, die Sie ansehen wollen, hat einen
unbekannten Zeichensatz. Das hei?t, dass wir nicht die M?glichkeit haben, die
Seite zu filtern und es kann sein, dass dies Ihre Anonymit?t gef?hrdet.
+ContentDataFilter.unknownCharsetTitle=Unbekannter Zeichensatz!
+ContentDataFilter.warningUnknownCharsetTitle=Warnung: Unbekannter Zeichensatz
(${charset})
+ContentFilter.applicationPdfReadAdvice=Adobe(R) PDF-Dokument - SEHR GEF?HRLICH!
+ContentFilter.applicationPdfWriteAdvice=Adobe(R) PDF-Dokument - SEHR
GEF?HRLICH!
+ContentFilter.imageGifReadAdvice=GIF-Bild - wahrscheinlich nicht gef?hrlich
+ContentFilter.imageGifWriteAdvice=GIF-Bild - wahrscheinlich nicht gef?hrlich,
aber Sie sollten alle Kommentare l?schen
+ContentFilter.imageIcoReadAdvice=Icon(=Symbol)-Datei - wahrscheinlich nicht
gef?hrlich
+ContentFilter.imageIcoWriteAdvice=Icon(=Symbol)-Datei - wahrscheinlich nicht
gef?hrlich (aber kann, aufgrund des Offsets, andere Daten enthalten)
+ContentFilter.imageJpegReadAdvice=JPEG-Bild - wahrscheinlich nicht gef?hrlich
+ContentFilter.imageJpegWriteAdvice=JPEG-Bild - wahrscheinlich nicht
gef?hrlich, aber kann EXIF-Daten enthalten
+ContentFilter.imagePngReadAdvice=PNG-Bild - wahrscheinlich nicht gef?hrlich
+ContentFilter.imagePngWriteAdvice=PNG-Bild - wahrscheinlich nicht gef?hrlich,
aber Sie sollten alle Kommentare oder Text-Bl?cke entfernen
+ContentFilter.textCssReadAdvice=CSS (cascading style sheet, wird normalerweise
mit HTML verwendet) - wahrscheinlich nicht gef?hrlich wenn gefiltert, aber der
Filter ist kein Whitelist-Filter, also Vorsicht
+ContentFilter.textCssWriteAdvice=CSS (cascading style sheet, wird
normalerweise mit HTML genutzt) - dies kann wahrscheinlich Meta-Daten
enthalten, pr?fen Sie dies manuell
+ContentFilter.textHtmlReadAdvice=HTML - nicht gef?hrlich wenn gefiltert
+ContentFilter.textHtmlWriteAdvice=HTML - kann gef?hrliche Meta-Daten usw.
enthalten; es wird vorgeschlagen dies manuell zu pr?fen
+ContentFilter.textPlainReadAdvice=Flie?text - nicht gef?hrlich, es sei denn
Ihr Browser ist unf?hig/dumm (z.B. Internet Explorer)
+ContentFilter.textPlainWriteAdvice=Flie?text - nicht gef?hlich, es sei denn,
er enth?lt kompromittierende (~blo?stellende) Informationen
+DarknetConnectionsToadlet.activityTitle=Derzeitige Aktivit?t
+DarknetConnectionsToadlet.add=Hinzuf?gen
+DarknetConnectionsToadlet.addPeerTitle=Einen weiteren Partner hinzuf?gen
+DarknetConnectionsToadlet.alreadyInReferences=Wir haben die gegebene Referenz
bereits.
+DarknetConnectionsToadlet.backedOff=Verbunden aber zur?ckgezogen: Diese
Partner sind verbunden aber wir haben uns vor Ihnen zur?ckgezogen, der Knoten
leitet deshalb keine Anfragen an sie weiter.
+DarknetConnectionsToadlet.backedOffShort=Zur?ckgezogen
+DarknetConnectionsToadlet.bursting=Nicht verbunden und berstend: Dieser Knoten
versucht sich, f?r eine kurze Zeit, mit diesen Partnern zu verbinden, weil der
Benutzer sie auf BurstOnly (nur bersten) gesetzt hat.
+DarknetConnectionsToadlet.burstingShort=Berstend
+DarknetConnectionsToadlet.busy=Besch?ftigt: Diese Partner sind verbunden, aber
sie sind zu besch?ftigt um unsere Anfragen zu bearbeiten, der Knoten leitet
deshalb keine Anfragen an sie weiter.
+DarknetConnectionsToadlet.busyShort=Besch?ftigt
+DarknetConnectionsToadlet.cantFetchNoderefURL=Nicht in der Lage die
Knoten-Referenz von ${url} abzurufen. Bitte versuchen Sie es noch einmal.
+DarknetConnectionsToadlet.cantParseTryAgain=Nicht in der Lage den gegebenen
Text als Knoten-Referenz zu erkennen: (${error}). Bitte versuchen Sie es noch
einmal.
+DarknetConnectionsToadlet.cantParseWrongEnding=Nicht in der Lage die
Knoten-Referenz zu erkennen: Sie sollte mit "End" in einer separaten Zeile
enden, aber sie endet mit: ${end}
+DarknetConnectionsToadlet.clockProblem=Ihre Uhrzeit und die des Knotens
unterscheiden sich um mehr als 24 Stunden. Wir haben die Verbindung
deaktiviert, da dies Probleme mit der Aktualisierung und den Clients
hervorrufen k?nnte.
+DarknetConnectionsToadlet.clockProblemShort=Uhrzeit-Problem
+DarknetConnectionsToadlet.confirmRemoveNode=Sind Sie sich sicher, dass Sie
"${name}" entfernen wollen? Es ist nicht zu empfehlen dies zu tun, bevor er
nicht mindestens eine Woche Ausfallzeit hat, da er nur tempor?r
ausgefallen/abgeschaltet sein k?nnte und viele Benutzer ihren Knoten nicht rund
um die Uhr betreiben k?nnen.
+DarknetConnectionsToadlet.confirmRemoveNodeTitle=Bitte best?tigen
+DarknetConnectionsToadlet.confirmRemoveNodeWarningTitle=Entfernen des Knotens
+DarknetConnectionsToadlet.connError=Verbinden fehlgeschlagen (fehlerhafter
Knoten?)
+DarknetConnectionsToadlet.connErrorShort=Verbindungs-Fehler
+DarknetConnectionsToadlet.connected=Verbunden: Wir sind erfolgreich mit diesen
Knoten verbunden
+DarknetConnectionsToadlet.connectedShort=Verbunden
+DarknetConnectionsToadlet.darknetFnpPort=Darknet-FNP: ${port}/UDP (wird
benutzt um sich mit vertrauensw?rdigen Partnern d.h. Freunden zu verbinden;
leiten Sie diesen Port weiter wenn Sie k?nnen)
+DarknetConnectionsToadlet.disabled=Nicht verbunden und deaktiviert: weil der
Benutzer den Knoten angewiesen hat sich nicht mit diesen Partnern zu verbinden.
+DarknetConnectionsToadlet.disabledShort=Deaktiviert
+DarknetConnectionsToadlet.enterDescription=Beschreibung eingeben:
+DarknetConnectionsToadlet.failedToAddNodeInternalError=Nicht in der Lage den
gegebenen Text als Knoten-Referenz zu erkennen. Bitte melden Sie folgendes an
die Entwickler:
+DarknetConnectionsToadlet.failedToAddNodeInternalErrorTitle=Hinzuf?gen des
Knotens fehlgeschlagen: Interner Fehler
+DarknetConnectionsToadlet.failedToAddNodeTitle=Hinzuf?gen des Knotens
fehlgeschlagen
+DarknetConnectionsToadlet.fcpDisabled=FCP ist deaktiviert (f?r Freenet-Clients
wie z.B. Frost und Thaw)
+DarknetConnectionsToadlet.fcpPort=FCP: ${port}/TCP (f?r Freenet-Clients wie
z.B. Frost und Thaw)
+DarknetConnectionsToadlet.fileReference=W?hlen Sie hier die Datei aus, die die
Referenz enth?lt:
+DarknetConnectionsToadlet.forceRemove=Entfernen erzwingen
+DarknetConnectionsToadlet.fproxyDisabled=FProxy ist deaktiviert (diese
Web-Schnittstelle)
+DarknetConnectionsToadlet.fproxyPort=FProxy: ${port}/TCP (diese
Web-Schnittstelle)
+DarknetConnectionsToadlet.fullTitle=${counts} Freunde (vertrauensw?rdige
Partner) von ${name}
+DarknetConnectionsToadlet.go=Los
+DarknetConnectionsToadlet.idleTime=Zeit seit sich der Knoten verband oder
zuletzt gesehen wurde
+DarknetConnectionsToadlet.idleTimeTitle=Verbunden / Unt?tig
+DarknetConnectionsToadlet.invalidSignature=Nicht in der Lage die Signatur der
gegebenen Referenz zu verifizieren (${error}).
+DarknetConnectionsToadlet.ipAddress=Die Netzwerk-Adresse des Knotens in der
Form IP:Port
+DarknetConnectionsToadlet.ipAddressTitle=Adresse
+DarknetConnectionsToadlet.listenOnly=Nicht verbunden und nur h?rend: Dieser
Knoten wird nicht versuchen sich mit diesen Partnern zu verbinden, weil der
Benutzer sie auf ListenOnly (nur h?ren) gesetzt hat.
+DarknetConnectionsToadlet.listenOnlyShort=Nur H?ren
+DarknetConnectionsToadlet.listening=Nicht verbunden aber h?rend: Dieser Knoten
wird nicht oft versuchen sich mit diesen Partnern zu verbinden, weil der
Benutzer sie auf BurstOnly (nur bersten) gesetzt hat.
+DarknetConnectionsToadlet.listeningShort=H?rend
+DarknetConnectionsToadlet.myFriends=Meine Freunde (von mir hinzugef?gte
zuverl?ssige Partner)
+DarknetConnectionsToadlet.myReferenceHeader=${linkref}Meine
Knoten-Referenz${/linkref} (${linktext}als Text${/linktext})
+DarknetConnectionsToadlet.nameClickToMessage=Der Name des Knotens. Klicken Sie
auf den Namens-Link um dem Knoten eine N2NTM (Knoten-zu-Knoten-Text-Nachricht)
zu senden
+DarknetConnectionsToadlet.nameTitle=Name
+DarknetConnectionsToadlet.neverConnected=Niemals verbunden: Der Knoten hat
sich noch nie mit diesen Partnern verbunden.
+DarknetConnectionsToadlet.neverConnectedShort=Niemals verbunden
+DarknetConnectionsToadlet.noPeersWithHomepageLink=Freenet kann nicht arbeiten,
da Sie noch keine Partner hinzugef?gt haben. Bitte gehen Sie zur
${link}Knoten-Startseite${/link} und lesen Sie den oberen Informations-Kasten
um zu erfahren wie das geht.
+DarknetConnectionsToadlet.noRefOrURL=Konnte weder eine Knoten-Referenz noch
eine URL erkennen. Bitte versuchen Sie es noch einmal.
+DarknetConnectionsToadlet.nodePortsTitle=Vom Knoten verwendete Ports
+DarknetConnectionsToadlet.notConnected=Nicht verbunden: Bis jetzt noch keine
Verbindung, aber dieser Knoten versucht kontinuierlich sich zu verbinden.
+DarknetConnectionsToadlet.notConnectedShort=Nicht verbunden
+DarknetConnectionsToadlet.opennetFnpPort=Opennet-FNP: ${port}/UDP (wird
benutzt um sich mit nicht vertrauensw?rdigen Partnern d.h. Fremden zu
verbinden; leiten Sie diesen Port weiter wenn Sie k?nnen)
+DarknetConnectionsToadlet.pasteReference=Die Referenz hier einf?gen:
+DarknetConnectionsToadlet.privateNote=Eine, diesen Partner betreffende,
private Notiz
+DarknetConnectionsToadlet.privateNoteTitle=Private Notiz
+DarknetConnectionsToadlet.referenceCopyWarning=Die Knoten-Referenz muss
${bold}SO WIE SIE IST${/bold} kopiert werden. Eine Ver?nderung macht sie
${bold}unbrauchbar${/bold}.
+DarknetConnectionsToadlet.remove=Entfernen!
+DarknetConnectionsToadlet.removePeers=Ausgew?hlte Partner entfernen
+DarknetConnectionsToadlet.selectAction=-- Aktion ausw?hlen --
+DarknetConnectionsToadlet.sendMessageTitle=Knoten-zu-Knoten-Text-Nachricht
(N2NTM) senden
+DarknetConnectionsToadlet.sendMessageToPeers=N2NTM an die ausgew?hlten Partner
senden
+DarknetConnectionsToadlet.separator=-- -- --
+DarknetConnectionsToadlet.statusTitle=Status
+DarknetConnectionsToadlet.tmciDisabled=TMCI ist deaktiviert (einfache
Telnet-basierte Kommandozeilen-Schnittstelle)
+DarknetConnectionsToadlet.tmciPort=TMCI: ${port}/TCP (einfache Telnet-basierte
Kommandozeilen-Schnittstelle)
+DarknetConnectionsToadlet.tooNew=Verbunden aber zu neu: Das minimal geforderte
Build dieser Partner ist h?her als die Build-Nummer dieses Knotens.
+DarknetConnectionsToadlet.tooNewShort=Zu neu
+DarknetConnectionsToadlet.tooOld=Verbunden aber zu alt: Der von diesem Knoten
geforderte minimale Build (Version) ist h?her als die Build-Nummer dieser
Partner. Der Knoten leitet keine Anfragen an diese weiter.
+DarknetConnectionsToadlet.tooOldShort=Zu alt
+DarknetConnectionsToadlet.triedToAddSelf=Sie k?nnen Ihren eigenen Knoten nicht
zur Liste der (entfernten) Partner hinzuf?gen.
+DarknetConnectionsToadlet.unknownAddress=(unbekannte Adresse)
+DarknetConnectionsToadlet.updateChangedPrivnotes=Ge?nderte private Notizen
aktualisieren
+DarknetConnectionsToadlet.urlReference=Die URL der Referenz hier eingeben:
+DarknetConnectionsToadlet.versionTitle=Version
+ExtOldAgeUserAlert.extTooOld=Ihre freenet-ext.jar-Datei scheint veraltet zu
sein: wir raten Ihnen dringend, Sie mit dieser
http://downloads.freenetproject.org/alpha/freenet-ext.jar zu aktualisieren.
+ExtOldAgeUserAlert.extTooOldTitle=Freenet-ext ist zu alt
+FProxyToadlet.abortToHomepage=Abbrechen und zur FProxy-Startseite zur?ckkehren
+FProxyToadlet.backToFProxy=${link}Klicken Sie hier${/link} um zur
FProxy-Startseite zu gehen.
+FProxyToadlet.backToReferrer=${link}Klicken Sie hier${/link} um zur
verweisenden Seite zur?ckzukehren.
+FProxyToadlet.cantBindPort=FProxy kann diesen Port nicht benutzen!
+FProxyToadlet.config=Ihren Knoten konfigurieren
+FProxyToadlet.configTitle=Konfiguration
+FProxyToadlet.dangerousContentTitle=Potenziell gef?hrlicher Inhalt
+FProxyToadlet.dangerousRSS=Freenet hat erkannt, dass die Datei, die Sie
versucht haben abzurufen, eine RSS-Datei sein k?nnte. RSS kann von Freenet
nicht richtig gefiltert werden und k?nnte Web-Bugs (Web-Programmfehler)
(integrierte Bilder usw. welche Ihre IP-Adresse einem b?swilligen
Seiten-Betreiber preisgeben und deshalb Ihre Anonymit?t verletzen k?nnten)
enthalten. Firefox 2.0 und Internet Explorer 7.0 werden die Datei als RSS-Datei
?ffnen, obwohl ihr Inhalts-Typ "${type}" ist.
+FProxyToadlet.dangerousRSSSubtitle=RSS-Feed, k?nnte gef?hrlich sein
+FProxyToadlet.dangerousRSSTitle=Potenziell gef?hrlicher Inhalt (RSS)
+FProxyToadlet.downloadInBackgroundToDisk=Im Hintergrund herunterladen und im
Downloads-Verzeichnis speichern
+FProxyToadlet.errorIsFatal=Dies ist ein schwerer Fehler. Es ist
unwahrscheinlich, dass ein neuer Versuch das Problem l?sen wird.
+FProxyToadlet.errorWithReason=Fehler: ${error}
+FProxyToadlet.expectedKeyButGot=Erwartete einen Freenet-Schl?ssel, aber bekam:
+FProxyToadlet.expectedMimeType=Erwarteter MIME-Typ: ${mime}
+FProxyToadlet.explanationTitle=Erkl?rung
+FProxyToadlet.fetchLargeFileAnywayAndDisplay=Trotzdem abrufen und die Datei im
Browser anzeigen
+FProxyToadlet.fileInformationTitle=Datei-Informationen
+FProxyToadlet.filenameLabel=Dateiname:
+FProxyToadlet.friends=f2f(Freund-zu-Freund)-Verbindungen verwalten
+FProxyToadlet.friendsTitle=Freunde
+FProxyToadlet.goBack=Zur?ck
+FProxyToadlet.goBackToPrev=Zur?ck zur vorherigen Seite
+FProxyToadlet.invalidKeyTitle=Ung?ltiger Schl?ssel
+FProxyToadlet.invalidKeyWithReason=Ung?ltiger Schl?ssel: ${reason}
+FProxyToadlet.largeFile=Gro?e Datei
+FProxyToadlet.largeFileExplanationAndOptions=Der Freenet-Schl?ssel, den Sie
angefordert haben, verweist auf eine gro?e Datei. Dateien dieser Gr??e, k?nnen
allgemein nicht direkt an Ihren Browser gesendet werden, da sie f?r Ihren
Freenet-Knoten beim Abrufen zu lange brauchen. Die folgenden M?glichkeiten sind
verf?gbar:
+FProxyToadlet.mayChange=(k?nnte sich ?ndern)
+FProxyToadlet.mimeType=MIME-Typ: ${mime}
+FProxyToadlet.notEnoughMetaStrings=Nicht genug Meta-Zeichenfolgen
+FProxyToadlet.notFoundTitle=Nicht gefunden
+FProxyToadlet.openAsText=${link}Klicken Sie hier${/link} um die Datei als
Flie?text zu ?ffnen (dies sollte nicht gef?hrlich, k?nnte allerdings
durcheinander/unleserlich sein).
+FProxyToadlet.openForce=${link}Klicken Sie hier${/link} um die Datei als
${mime} zu ?ffnen (lesen Sie die obenstehende Warnung!).
+FProxyToadlet.openForceDisk=${link}Klicken Sie hier${/link} um Ihren Browser
zu zwingen, die Datei auf einen Datentr?ger herunterzuladen.
+FProxyToadlet.openPossRSSAsPlainText=${link}Klicken Sie hier${/link} um die
Datei als Flie?text zu ?ffnen (dies ${bold}kann gef?hrlich sein${/bold} wenn
Sie Internet Explorer 7 oder Firefox 2 benutzen).
+FProxyToadlet.openPossRSSForceDisk=${link}Klicken Sie hier${/link} um Ihren
Browser zu zwingen, die Datei auf einen Datentr?ger herunterzuladen
(${bold}dies k?nnte auch gef?hrlich sein${/bold} wenn Sie Firefox 2.0.0
benutzen, 2.0.1 sollte dies beheben).
+FProxyToadlet.openRSSAsRSS=${link}Klicken Sie hier${/link} um die Datei als
RSS-Datei zu ?ffnen (dies ${bold}ist gef?hrlich${/bold} wenn der
Seiten-Betreiber b?swillig ist, da Freenet bis jetzt noch nicht wei?, wie man
RSS filtert).
+FProxyToadlet.openRSSForce=${link}Klicken Sie hier${/link} um die Datei als
${mime} zu ?ffnen (dies ${bold}kann gef?hrlich sein${/bold} wenn Sie Internet
Explorer 7 oder Firefox 2 benutzen).
+FProxyToadlet.opennet=Nicht vertrauensw?rdige Verbindungen verwalten
+FProxyToadlet.opennetTitle=Fremde
+FProxyToadlet.options=Ihre M?glichkeiten sind:
+FProxyToadlet.pathNotFound=Der angegebene Pfad existiert nicht.
+FProxyToadlet.pathNotFoundTitle=Pfad nicht gefunden
+FProxyToadlet.plugins=Plugins (Erweiterungen) konfigurieren und verwalten
+FProxyToadlet.pluginsTitle=Plugins
+FProxyToadlet.queue=Wartende/eingereihte Anfragen verwalten
+FProxyToadlet.queueTitle=Warteschlange
+FProxyToadlet.retryNow=Jetzt nochmal versuchen
+FProxyToadlet.sizeLabel=Gr??e:
+FProxyToadlet.sizeUnknown=Gr??e: unbekannt
+FProxyToadlet.stats=Statistiken anzeigen
+FProxyToadlet.statsTitle=Statistiken
+FProxyToadlet.unableToRetrieve=Freenet war nicht in der Lage, diese Datei
abzurufen.
+FProxyToadlet.unknownMIMEType=MIME-Typ: unbekannt
+FProxyToadlet.welcome=Startseite
+FProxyToadlet.welcomeTitle=Startseite
+FcpServer.allowedHosts=Erlaubte Hosts (lesen Sie die Warnung!)
+FcpServer.allowedHostsFullAccess=Hosts mit vollem Zugriff
+FcpServer.allowedHostsFullAccessLong=IP-Adressen welchen der volle Zugriff auf
den Knoten erlaubt ist. Clients (Nutzer) auf diesen IPs k?nnen den Knoten
neustarten, rekonfigurieren usw. Beachten Sie, dass es ALLEN Clients erlaubt
ist, direkte Datentr?ger-I/O (E/A) zu betreiben!
+FcpServer.allowedHostsLong=IP-Adressen welchen es erlaubt ist sich mit dem
FCP-Server zu verbinden. Kann eine Komma-getrennte Liste von einzelnen IPs und
CIDR-maskierten IPs, wie 192.168.0.0/24, sein. WARNUNG! Jeder, der Zugang zum
FCP hat, kann jede Datei hochladen, auf welche der Knoten Zugriff hat, oder
Dateien auf den Datentr?ger herunterladen (aber der Knoten wird versuchen
vorhandene Dateien nicht zu ?berschreiben).
+FcpServer.assumeDownloadDDAIsAllowed=Annehmen, dass das Herunterladen von DDA
erlaubt ist?
+FcpServer.assumeDownloadDDAIsAllowedLong=Annehmen, dass das Herunterladen von
DDA erlaubt ist? Wenn nicht (false), m?ssen sie eine TestDDARequest
(TestDDAAnfrage) ausl?sen, bevor Sie einen DDA-Zugriff ausf?hren.
+FcpServer.assumeUploadDDAIsAllowed=Annehmen, dass das Hochladen von DDA
erlaubt ist?
+FcpServer.assumeUploadDDAIsAllowedLong=Annehmen, dass das Hochladen von DDA
erlaubt ist? Wenn nicht (false), m?ssen sie eine TestDDARequest
(TestDDAAnfrage) ausl?sen, bevor Sie einen DDA-Zugriff ausf?hren.
+FcpServer.bindTo=Zu benutzende IP-Adresse
+FcpServer.bindToLong=IP-Adresse die der FCP-Server benutzen soll.
+FcpServer.cannotStartOrStopOnTheFly=Der FCP-Server kann nicht im laufenden
Betrieb gestartet oder gestoppt werden
+FcpServer.couldNotChangeBindTo=Konnte die zu benutzende FCP-Adresse nicht
?ndern: ${error}.
+FcpServer.downloadsFileCanCreateCannotReadOrWrite=Datei erstellt, kann aber
weder gelesen noch geschrieben werden
+FcpServer.downloadsFileDoesNotExistCannotCreate=Datei existiert nicht und kann
nicht erstellt werden
+FcpServer.downloadsFileExistsCannotReadOrWrite=Die Datei existiert, aber kann
weder gelesen noch geschrieben werden
+FcpServer.downloadsFileIsDirectory=Ung?ltiger Datei-Name f?r die
Download-Liste: Ist ein Verzeichnis
+FcpServer.downloadsFileParentDoesNotExist=Oberverzeichnis existiert nicht
+FcpServer.downloadsFileUnreadable=Datei existiert aber kann nicht gelesen
(zugegriffen) werden
+FcpServer.enablePersistentDownload=Persistente Downloads aktivieren?
+FcpServer.enablePersistentDownloadLong=Ob f?r FCP-Anfragen Persistence=forever
(Persistenz/Speicher-Dauer=f?r immer) aktiviert werden darf. Soll hei?en, ob
Anfragen unterst?tzt werden sollen, welche ?ber Knoten-Neustarts hinaus
andauern; diese m?ssen auf den Datentr?ger geschrieben werden und dies k?nnte
f?r manche Leute ein Sicherheits-Problem darstellen.
+FcpServer.filenameToStorePData=Name der Datei in welcher persistente Downloads
gespeichert werden
+FcpServer.filenameToStorePDataLong=Name der Datei, in der Details zu
persistenten (dauerhaften) Downloads gespeichert werden.
+FcpServer.intervalBetweenWrites=Zeitraum zwischen dem Schreiben persistenter
Downloads auf den Datentr?ger.
+FcpServer.intervalBetweenWritesLong=Zeitraum zwischen dem Schreiben
persistenter (dauerhafter) Downloads auf den Datentr?ger.
+FcpServer.isEnabled=Ist der FCP-Server aktiviert?
+FcpServer.isEnabledLong=Ist der FCP-Server aktiviert?
+FcpServer.portNumber=FCP-Port-Nummer
+FcpServer.portNumberLong=FCP-Port-Nummer.
+FetchException.longError.1=Zu viele Ebenen von Rekursion (Schachtelung) in den
Archiven
+FetchException.longError.10=Datei nicht im Archiv
+FetchException.longError.11=Zu viele Pfad-Komponenten - kein Manifest(???)?
Versuchen Sie eine zu entfernen
+FetchException.longError.12=Interner Fehler in den tempor?ren Dateien,
vielleicht ist der Datentr?ger voll oder es besteht ein Rechte-Problem?
+FetchException.longError.13=Daten nicht gefunden
+FetchException.longError.14=Route nicht gefunden - konnte nicht gen?gend
Knoten finden um sicher zu gehen, dass die Daten nicht existieren
+FetchException.longError.15=Ein Knoten war ?berlastet oder verursachte eine
Zeit?berschreitung
+FetchException.longError.16=Zu viele Weiter-/Umleitungen - Schleife?
+FetchException.longError.17=Interner Fehler, wahrscheinlich ein Programmfehler
+FetchException.longError.18=Datei gefunden, aber w?hrend dem Empfang der Daten
verloren
+FetchException.longError.19=Teil-Datei-Fehler
+FetchException.longError.2=Wei? nicht was mit der Teil-Datei zu tun ist
+FetchException.longError.20=Ung?ltiger URI
+FetchException.longError.21=Zu gro?
+FetchException.longError.22=Metadaten zu gro?
+FetchException.longError.23=Zu viele Bl?cke pro Segment
+FetchException.longError.24=F?gen Sie dem URI mehr Metadaten
(Pfad-Komponenten) hinzu
+FetchException.longError.25=Abgebrochen
+FetchException.longError.26=Archiv neugestartet
+FetchException.longError.27=Permanente Weiter-/Umleitung: Benutzen Sie den
neuen URI
+FetchException.longError.28=Nicht genug Daten gefunden; es wurden ein paar
Daten abgerufen aber die Weiter-/Umleitung k?nnte ins Nirgendwo zeigen
+FetchException.longError.29=Falscher MIME-Typ: Der Schl?ssel war nicht in der
Liste der erlaubten MIME-Typen, die vom Client zur Verf?gung gestellt wurde.
+FetchException.longError.3=Wei? nicht was mit den Metadaten zu tun ist
+FetchException.longError.30=Die Anfrage wurde von einem Knoten terminiert,
weil er vor kurzem eine Anfrage nach dem selben Schl?ssel bekam und diese
Anfrage fehlschlug
+FetchException.longError.4=Analyse der Metadaten fehlgeschlagen
+FetchException.longError.5=Fehler beim Entpacken von Dateien aus einem Archiv
+FetchException.longError.6=Das Dekodieren eines Blocks ist fehlgeschlagen
+FetchException.longError.7=Zu viele Ebenen von geteilten Metadaten
+FetchException.longError.8=Die Anfrage wurde, aufgrund von
Archiv-Ver?nderungen, zu oft neugestartet
+FetchException.longError.9=Zu viele Weiter-/Umleitungen (zu viel Rekursion)
+FetchException.shortError.1=Zu tiefe Archiv-Rekursion
+FetchException.shortError.10=Nicht im Archiv
+FetchException.shortError.11=Zu viele Pfad-Komponenten
+FetchException.shortError.12="Tempor?re Dateien"-Fehler
+FetchException.shortError.13=Daten nicht gefunden
+FetchException.shortError.14=Route nicht gefunden
+FetchException.shortError.15=Zeit?berschreitung oder ?berlastung
+FetchException.shortError.16=Zu viele Weiter-/Umleitungen
+FetchException.shortError.17=Interner Fehler
+FetchException.shortError.18=Transfer fehlgeschlagen
+FetchException.shortError.19=Teil-Datei-Fehler
+FetchException.shortError.2=Unbekannte Teil-Datei-Metadaten
+FetchException.shortError.20=Ung?ltiger URI
+FetchException.shortError.21=Zu gro?
+FetchException.shortError.22=Metadaten zu gro?
+FetchException.shortError.23=Zu viele Bl?cke pro Segment
+FetchException.shortError.24=Nicht genug Meta-Zeichenfolgen
+FetchException.shortError.25=Abbruch durch den Aufrufer
+FetchException.shortError.26=Archiv neugestartet
+FetchException.shortError.27=Neuer URI
+FetchException.shortError.28=Alle Daten nicht gefunden
+FetchException.shortError.29=Falscher MIME-Typ
+FetchException.shortError.3=Unbekannte Metadaten
+FetchException.shortError.30=Daten nicht gefunden (vor kurzem fehlgeschlagen)
+FetchException.shortError.4=Ung?ltige Metadaten
+FetchException.shortError.5=Archiv versagt
+FetchException.shortError.6=Block-Dekodierungs-Fehler
+FetchException.shortError.7=Zu viele Metadaten-Ebenen
+FetchException.shortError.8=Zu viele Archiv-Neustarts
+FetchException.shortError.9=Zu viel Rekursion
+FileOffer.acceptTransferButton=?bertragung akzeptieren
+FileOffer.askUserTitle=Direkte Datei-?bertragung
+FileOffer.commentLabel=Kommentar:
+FileOffer.failedReceiveHeader=Die ?bertragung der Datei ${filename} von
${node} ist fehlgeschlagen.
+FileOffer.failedReceiveTitle=Empfang der Datei fehlgeschlagen
+FileOffer.fileLabel=Datei:
+FileOffer.mimeLabel=MIME-Typ:
+FileOffer.offeredFileHeader=Der Knoten ${name} hat eine Datei angeboten:
+FileOffer.rejectTransferButton=?bertragung ablehnen
+FileOffer.senderLabel=Sender:
+FileOffer.sizeLabel=Gr??e:
+FileOffer.succeededReceiveHeader=Die ?bertragung der Datei ${filename} von
${node} war erfolgreich.
+FileOffer.succeededReceiveTitle=Datei erfolgreich empfangen
+FirstTimeWizardToadlet.bandwidthLimit=Bandbreiten-Limits
+FirstTimeWizardToadlet.bandwidthLimitLong=Bitte w?hlen Sie Ihren
Internet-Verbindungs-Typ und -Geschwindigkeit aus der unten befindlichen
Dropdown-Liste.
+FirstTimeWizardToadlet.chooseNodeName=Knoten-Name ben?tigt!
+FirstTimeWizardToadlet.chooseNodeNameLong=Bitte geben Sie einen Knoten-Namen
in das unten stehende Feld ein. Dieser Name wird f?r niemanden, au?er den
Partnern mit denen Sie verbunden sind, sichtbar sein. Wir empfehlen Ihnen,
Ihren wahren Namen oder IRC-Nickname (Spitznamen), m?glicherweise mit
Kontakt-Informationen, sodass Sie erreichbar sind wenn ein Problem auftritt,
anzugeben (z.B.: "Max Mustermann <niemand at nirgendwo.de>").
+FirstTimeWizardToadlet.congratz=Willkommen an Bord!
+FirstTimeWizardToadlet.congratzLong=Herzlichen Gl?ckwunsch, die
Basis-Konfiguration Ihres Freenet-Knotens ist nun abgeschlossen. Sie k?nnen
alle Parameter, die Sie soeben eingestellt haben, ?ndern indem Sie auf die
"Konfiguration"s-Seite gehen, diese ist jederzeit vom Men? auf der linken Seite
der Oberfl?che zu erreichen. Wir w?nschen Ihnen ein angenehmes Freenet-Erlebnis.
+FirstTimeWizardToadlet.connectToStrangers=Mit Fremden verbinden?
+FirstTimeWizardToadlet.connectToStrangersLong=Wenn Sie Freenet sich mit
Fremden verbinden lassen, wird Freenet f?r Sie weniger sicher sein, jeder kann
herausfinden, dass Sie Freenet benutzen und jeder b?se Mensch kann sich mit
Ihrem Knoten verbinden. Wenn Sie dies nicht tun, werden Sie mindestens drei
andere Freunde (Leute, die Sie schon kennen), die Freenet benutzen, manuell
kontaktieren und sich mit Ihnen verbinden m?ssen.
+FirstTimeWizardToadlet.continue=Fortfahren
+FirstTimeWizardToadlet.datastoreSize=Gr??e des Datenspeichers
+FirstTimeWizardToadlet.datastoreSizeLong=Bitte w?hlen Sie eine Gr??e f?r Ihren
Datenspeicher. Der Datenspeicher verh?lt sich wie ein Zwischenspeicher (Cache);
Daten f?r das Netzwerk zu speichern wird Ihnen zu einem besseren
Daten-Durchsatz verhelfen, wenn Sie popul?re Dateien anfordern. Je mehr Platz
Sie zur Verf?gung stellen k?nnen, desto besser ist es f?r die Gemeinschaft und
desto schneller wird Ihr Knoten.
+FirstTimeWizardToadlet.enableOpennet=Automatisch mit Knoten von nicht
vertrauensw?rdigen Fremden verbinden?
+FirstTimeWizardToadlet.homepageTitle=Freenet-Einrichtungs-Assistent!
+FirstTimeWizardToadlet.iDoTrust=Trauen Sie Leuten die mit ${interface} (${ip})
verbunden sind?
+FirstTimeWizardToadlet.isNetworkTrusted=Ist Ihr lokales Netzwerk
vertrauensw?rdig?
+FirstTimeWizardToadlet.isNetworkTrustedLong=Ist Ihr lokales Netzwerk
vertrauensw?rdig? Wenn Sie hier mit Ja antworten, werden alle Dienste, die Ihr
Knoten anbietet, f?r jeden der vom lokalen Netzwerk auf sie zugreifen will,
frei zug?nglich sein. Sie werden die M?glichkeit haben, selektive
Zugangs-Kontrollen auf der Konfigurations-Seite einzurichten, wenn der
Assistent beendet ist.
+FirstTimeWizardToadlet.noNetworkIF=Keine zus?tzliche Netzwerk-Schnittstelle
gefunden
+FirstTimeWizardToadlet.noNetworkIFLong=Freenet hat keine zus?tzliche
Netzwerk-Schnittstelle gefunden. Es wird annehmen, dass Sie sich von Ihrem
Computer (und nur von Ihrem Computer) mit ihm verbinden.
+FirstTimeWizardToadlet.skipWizard=Ich bin kein Neuling, bitte ?berspringe den
Assistenten!
+FirstTimeWizardToadlet.step1Title=Freenet-Einrichtungs-Assistent! - Freunde
und Fremde
+FirstTimeWizardToadlet.step2Title=Freenet-Einrichtungs-Assistent! - W?hlen Sie
einen Knoten-Namen
+FirstTimeWizardToadlet.step3Title=Freenet-Einrichtungs-Assistent! -
Bandbreiten-Limits
+FirstTimeWizardToadlet.step4Title=Freenet-Einrichtungs-Assistent! - Gr??e des
Datenspeichers
+FirstTimeWizardToadlet.step5Title=Freenet-Einrichtungs-Assistent! -
Netzwerk-Konfiguration
+FirstTimeWizardToadlet.step6Title=Freenet-Einrichtungs-Assistent! - Herzlichen
Gl?ckwunsch, Ihr Knoten ist nun konfiguriert
+FirstTimeWizardToadlet.welcomeInfoboxContent1=Willkommen beim
Freenet-Einrichtungs-Assistent. Dieses Werkzeug erlaubt es Ihnen, Ihren Knoten
schnell und einfach f?r den ersten Betrieb einzurichten. Bitte
+FirstTimeWizardToadlet.welcomeInfoboxTitle=Willkommen zum
Freenet-Einrichtungs-Assistent!
+GIFFilter.invalidHeader=Die Datei enth?lt keinen g?ltigen GIF-Header
(Dateikopf).
+GIFFilter.invalidHeaderTitle=Ung?ltiger Header
+GIFFilter.notGif=Die Datei, die Sie versucht haben abzurufen, ist keine
GIF-Datei. Es k?nnte sich um ein anderes Datei-Format handeln und Ihr Browser
k?nnte etwas gef?hrliches damit tun, deshalb haben wir sie blockiert.
+GIFFilter.tooShort=Die Datei ist zu klein um eine GIF-Datei zu sein.
+GIFFilter.tooShortTitle=Zu klein
+GenericReadFilterCallback.couldNotParseAbsoluteFreenetURI=Konnte nicht als
absolute Freenet-URI erkannt werden
+GenericReadFilterCallback.couldNotParseFormURIWithError=Der Filter konnte die
Form des URI nicht analysieren: ${error}
+GenericReadFilterCallback.couldNotParseRelativeFreenetURI=Konnte nicht als
relative Freenet-URI erkannt werden
+GenericReadFilterCallback.couldNotParseURIWithError=Der Filter konnte den URI
nicht analysieren: ${error}
+GenericReadFilterCallback.invalidFormURI=Ung?ltige Form des URI: zeigt auf
externe Ressource
+GenericReadFilterCallback.invalidFormURIAttemptToEscape=Versuch, aus der
Verzeichnis-Struktur auszubrechen
+GenericReadFilterCallback.malformedAbsoluteURL=Falsch aufgebaute URL
(absolut): ${error}
+GenericReadFilterCallback.malformedRelativeURL=Falsch aufgebaute URL
(relativ): ${error}
+GenericReadFilterCallback.protocolNotEscaped=Kein escape-Protokoll: ${protocol}
+HTMLFilter.couldNotParseStyle=Der Eingabe-Stil konnte nicht abgeglichen werden
+HTMLFilter.deletedUnknownStyle=unbekannter Stil gel?scht
+HTMLFilter.failedToParseLabel=Der HTML-Filter konnte die Seite nicht
analysieren
+HTMLFilter.tooManyNestedStyleOrScriptTags=Zu viele verschachtelte Stil- oder
Script-Tags (Markierungen) - mehrdeutig oder ung?ltige Analyse
+HTMLFilter.tooManyNestedStyleOrScriptTagsLong=Zu viele verschachtelte
</style>-Tags (Markierungen) - mehrdeutig oder ung?ltige Analyse, es kann nicht
zuverl?ssig gefiltert werden, deshalb werden die inneren Tags entfernt - es
kann sein, dass der Browser Unfug anzeigt
+HTMLFilter.unknownTag=unbekannter Tag (Markierung) ${tag}
+IPDetectorPluginManager.direct=Sie scheinen direkt mit dem Internet verbunden
zu sein. Herzlichen Gl?ckwunsch, Sie sollten in der Lage sein, sich mit jedem
anderen Freenet-Knoten zu verbinden.
+IPDetectorPluginManager.directTitle=Direkte Internet-Verbindung erkannt
+IPDetectorPluginManager.fullCone=Ihre Internet-Verbindung scheint sich hinter
einem "full cone"-NAT (Router) zu befinden. Herzlichen Gl?ckwunsch, Ihr Knoten
sollte in der Lage sein, sich mit jedem anderen Knoten zu verbinden.
+IPDetectorPluginManager.fullConeTitle="Full cone"-NAT erkannt
+IPDetectorPluginManager.noConnectivity=Ihre Internet-Verbindung scheint UDP
nicht zu unterst?tzen. Wenn diese Erkennung richtig ist, wird Freenet auf Ihrem
Computer derzeit wahrscheinlich nicht funktionieren.
+IPDetectorPluginManager.noConnectivityTitle=Keine UDP-Konnektivit?t
+IPDetectorPluginManager.portRestricted=Ihre Internet-Verbindung scheint sich
hinter einem "port-restricted cone"-NAT (Router) zu befinden. Sie werden in der
Lage sein sich mit den meisten anderen Benutzern zu verbinden, aber nicht mit
denen, die sich hinter einem symmetrischen NAT befinden.
+IPDetectorPluginManager.portRestrictedTitle="Port restricted cone"-NAT erkannt
+IPDetectorPluginManager.restricted=Ihre Internet-Verbindung scheint sich
hinter einem "restricted cone"-NAT (Router) zu befinden. Sie sollten in der
Lage sein, sich mit den meisten anderen Benutzern zu verbinden.
+IPDetectorPluginManager.restrictedTitle="Restricted cone"-NAT erkannt
+IPDetectorPluginManager.suggestForwardPort=Sie m?chten vielleicht den Port
(UDP-Port Nummer ${port}) manuell weiterleiten (siehe
http://wiki.freenetproject.org/deFirewallAndRouterIssues ).
+IPDetectorPluginManager.suggestForwardPortWithLink=Sie m?chten vielleicht den
Port (UDP-Port Nummer ${port}) ${link}manuell weiterleiten${/link} (es kann
sein, dass Sie dies schon getan haben, Freenet kann dies nicht sicher erkennen).
+IPDetectorPluginManager.symmetric=Ihre Internet-Verbindung scheint sich hinter
einem symmetrischen NAT (Router) oder einer Firewall zu befinden. Sie werden
wahrscheinlich nur in der Lage sein, sich mit Benutzern zu verbinden, die
direkt oder ?ber "restricted cone"-NATs mit dem Internet verbunden sind.
+IPDetectorPluginManager.symmetricTitle=Symmetrische Firewall erkannt
+IPUndetectedUserAlert.detecting=Freenet versucht gerade Ihre externe
IP-Adresse zu ermitteln. Wenn dies mehr als ein paar Minuten dauert, l?uft
etwas schief...
+IPUndetectedUserAlert.detectingWithConfigLink=Freenet versucht gerade Ihre
externe IP-Adresse zu ermitteln. Wenn dies mehr als ein paar Minuten dauert,
dann l?uft etwas schief und Sie k?nnen die "Hinweis auf tempor?re
IP-Adresse"-${link}Einstellung${/link} benutzen. Es w?re auch eine gute Idee,
den UDP-Port ${port} in Ihrem Router weiterzuleiten, um es Anderen zu
erleichtern zu Ihrem Knoten Kontakt aufzunehmen.
+IPUndetectedUserAlert.unknownAddress=Freenet war nicht imstande Ihre
IP-Adresse zu ermitteln (oder die IP-Adresse ihrer Firewall oder Ihres
NAT-Ger?ts (Router)). Sie k?nnen immer noch Referenzen mit anderen Menschen
austauschen, dies wird aber nur funktionieren, wenn der andere Benutzer sich
nicht hinter einem NAT-Ger?t oder einer Firewall befindet. Sobald Sie sich auf
diesem Weg mit einem anderen Benutzer verbunden haben, wird Freenet in der Lage
sein ihre externe IP-Adresse zu ermitteln. Sie k?nnen auch ihre momentane
IP-Adresse feststellen und diese Ihrem Knoten mit der "Hinweis auf tempor?re
IP-Adresse"-${link}Einstellung${/link} mitteilen. Es w?re auch eine gute Idee,
den UDP-Port ${port} in Ihrem Router weiterzuleiten, um es Anderen zu
erleichtern zu Ihrem Knoten Kontakt aufzunehmen.
+IPUndetectedUserAlert.unknownAddressTitle=Unbekannte externe Adresse
+IPUndetectedUserAlert.unknownAddressWithConfigLink=Freenet war nicht imstande
Ihre IP-Adresse zu ermitteln (oder die IP-Adresse ihrer Firewall oder Ihres
NAT-Ger?ts (Router)). Sie k?nnen immer noch Referenzen mit anderen Menschen
austauschen, dies wird aber nur funktionieren, wenn der andere Benutzer sich
nicht hinter einem NAT-Ger?t oder einer Firewall befindet. Sobald Sie sich auf
diesem Weg mit einem anderen Benutzer verbunden haben, wird Freenet in der Lage
sein ihre externe IP-Adresse zu ermitteln. Sie k?nnen auch ihre momentane
IP-Adresse feststellen und diese Ihrem Knoten mit der "Hinweis auf tempor?re
IP-Adresse"-${link}Einstellung${/link} mitteilen. Es w?re auch eine gute Idee,
den UDP-Port ${port} in Ihrem Router weiterzuleiten, um es Anderen zu
erleichtern zu Ihrem Knoten Kontakt aufzunehmen.
+InsertException.longError.1=Der Aufrufer lieferte einen URI den wir nicht
benutzen k?nnen"
+InsertException.longError.10=Abbruch durch den Benutzer
+InsertException.longError.11=Im URI wurde eine Meta-Zeichenfolge
(wahrscheinlich ein '/') benutzt
+InsertException.longError.12=Bin?rer Klumpen-Format-Fehler (binary blob format
error)
+InsertException.longError.2=Interner Speicher(bucket)-Fehler: kein freier
Speicherplatz/Problem mit den Zugriffsrechten?
+InsertException.longError.3=Interner Fehler
+InsertException.longError.4=Ein nachgelagerter Knoten hatte eine
Zeit?berschreitung oder war ernsthaft ?berlastet
+InsertException.longError.5=Konnte die Einf?ge-Operation nicht bei gen?gend
Knoten bekannt machen (normal bei kleinen Netzwerken, versuche trotzdem sie
abzurufen)
+InsertException.longError.6=Fatale Fehler beim Einf?gen einer Teildatei
+InsertException.longError.7=Konnte die Teil-Datei nicht einf?gen: Es sind
keine Wiederholungs-Versuche mehr ?brig (nicht-fatale Fehler)
+InsertException.longError.8=Die Einf?ge-Operation konnte den Knoten nicht
verlassen
+InsertException.longError.9=Einf?ge-Operation kollidierte mit verschiedenen,
vorher existierenden Daten beim selben Schl?ssel
+InsertException.shortError.1=Ung?ltiger URI
+InsertException.shortError.10=Abgebrochen
+InsertException.shortError.11=Im Schl?ssel wurde eine Meta-Zeichenfolge benutzt
+InsertException.shortError.12=Bin?rer Klumpen-Format-Fehler
+InsertException.shortError.2="Tempor?re Dateien"-Fehler
+InsertException.shortError.3=Interner Fehler
+InsertException.shortError.4=Zeit?berschreitung oder ?berlastung
+InsertException.shortError.5=Route nicht gefunden
+InsertException.shortError.6=Manche Bl?cke wiesen fatale Fehler auf
+InsertException.shortError.7=Manche Bl?cke hatten keine Wiederholungs-Versuche
mehr
+InsertException.shortError.8=Anfrage konnte den Knoten nicht verlassen
+InsertException.shortError.9=Kollision mit existierenden Daten
+IntOption.parseError=Der gegebene Wert konnte nicht als 32-bit-Ganzzahl
erkannt werden: ${val}
+JPEGFilter.notJpeg=Die Datei, die Sie versucht haben abzurufen, ist keine
JPEG-Datei. Es k?nnte sich um ein anderes Format handeln und Ihr Browser k?nnte
etwas gef?hrliches damit tun, deshalb haben wir sie blockiert.
+JPEGFilter.tooShort=Die Datei ist zu klein um eine JPEG-Datei zu sein.
+JPEGFilter.tooShortTitle=Zu klein
+KnownUnsafeContentTypeException.dangerousInlines=Dieser Inhalts-Typ kann
eingebundene Bilder oder Videos enthalten, und somit Inhalte vom nicht-anonymen
offenen Web (Internet) herunterladen, wobei Ihre IP-Adresse offen gelegt wird.
+KnownUnsafeContentTypeException.dangerousInlinesLabel=Gef?hrliche eingebettete
Dateien:
+KnownUnsafeContentTypeException.dangerousLinks=Dieser Inhalts-Typ kann Links
ins nicht-anonyme Web (Internet) enthalten; wenn Sie diese anklicken (und sie
k?nnten getarnt sein), k?nnte dies Ihre IP-Adresse offen legen.
+KnownUnsafeContentTypeException.dangerousLinksLabel=Gef?hrliche Links:
+KnownUnsafeContentTypeException.dangerousMetadata=Dieser Inhalts-Typ kann
Meta-Daten enthalten (welche von manchen Browsern oder anderer Software
angezeigt werden k?nnten), welche gef?hrliche Links oder eingebettete Dateien
enthalten k?nnen.
+KnownUnsafeContentTypeException.dangerousMetadataLabel=Gef?hrliche Meta-Daten:
+KnownUnsafeContentTypeException.dangerousScripts=Dieser Inhalts-Typ kann
gef?hrliche Scripts (ausf?hrbare Inhalte) enthalten, welche, wenn sie
ausgef?hrt werden, Ihre Anonymit?t kompromittieren (blo?stellen/offen legen)
k?nnten indem sie Verbindung zum offenen Web (Internet) aufnehmen, oder auf
andere Weise die Sicherheit verletzen.
+KnownUnsafeContentTypeException.dangerousScriptsLabel=Gef?hrliches Scripting:
+KnownUnsafeContentTypeException.knownUnsafe=Dies ist ein potenziell
gef?hrlicher MIME-Typ. Wenn der Knoten ihn durchl?sst, k?nnte Ihr Browser
schlechte Dinge tun, welche zu einer Kompromittierung
(Blo?stellung/Offenlegung) Ihrer Anonymit?t und Offenlegung ihrer IP-Adresse in
Verbindung mit dieser Seite f?hren k?nnten. Im speziellen:
+KnownUnsafeContentTypeException.noFilter=Da es keinen eingebauten Filter f?r
diese Daten gibt, sollten Sie ?u?erst vorsichtig sein!
+KnownUnsafeContentTypeException.title=Bekannter gef?hrlicher Typ: ${type}
+LocalFileInsertToadlet.checkPathExist=Stellen Sie sicher, dass der angegebene
Pfad existiert.
+LocalFileInsertToadlet.checkPathIsDir=Stellen Sie sicher, dass der angegebene
Pfad ein Verzeichnis ist.
+LocalFileInsertToadlet.checkPathReadable=Stellen Sie sicher, dass auf den
angegebenen Pfad, von dem Benutzer der den Knoten ausf?hrt, zugegriffen werden
kann.
+LocalFileInsertToadlet.dirAccessDenied=Sie k?nnen dieses Verzeichnis nicht
durchsuchen
+LocalFileInsertToadlet.dirCannotBeRead=Das Verzeichnis "${path}" kann nicht
gelesen werden.
+LocalFileInsertToadlet.fileHeader=Datei
+LocalFileInsertToadlet.insert=Einf?gen
+LocalFileInsertToadlet.listing=Verzeichnis-Liste: ${path}
+LocalFileInsertToadlet.listingTitle=Auflistung von ${path}
+LocalFileInsertToadlet.sizeHeader=Gr??e
+LogConfigHandler.detaildPriorityThreshold=Detaillierte Priorit?ts-Schwellen
+LogConfigHandler.detaildPriorityThresholdLong=Detaillierte
Priorit?ts-Schwellwerte, zum Beispiel freenet:normal,freenet.node:minor
+LogConfigHandler.dirName=Protokoll-Verzeichnis
+LogConfigHandler.dirNameLong=Verzeichnis in dem Protokoll-Dateien gespeichert
werden
+LogConfigHandler.enabled=Protokollierung (Logging) aktivieren?
+LogConfigHandler.enabledLong=Auf false (falsch) setzen um die Protokollierung
komplett abzuschalten
+LogConfigHandler.maxCachedBytes=Maximal im RAM zwischengespeicherte
Protokoll-Bytes
+LogConfigHandler.maxCachedBytesLong=Maximale Anzahl von Bytes der
Protokollierung, die im RAM (Hauptspeicher) zwischengespeichert werden
+LogConfigHandler.maxCachedLines=Maximal im RAM zwischengespeicherte
Protokoll-Zeilen
+LogConfigHandler.maxCachedLinesLong=Maximale Anzahl von Zeilen der
Protokollierung, die im RAM (Hauptspeicher) zwischengespeichert werden
+LogConfigHandler.maxZippedLogsSize=Maximaler von alten Protokoll-Dateien
belegter Speicherplatz
+LogConfigHandler.maxZippedLogsSizeLong=Maximaler von alten Log-Dateien
belegter Speicherplatz
+LogConfigHandler.minLoggingPriority=Minimale Priorit?t ab der Nachrichten
protokolliert werden
+LogConfigHandler.minLoggingPriorityLong=Minimale Priorit?t ab der Nachrichten
protokolliert werden. Zur Auswahl stehen debug (Fehleranalyse), minor
(unwichtig), normal und error (Fehler).
+LogConfigHandler.rotationInterval=Protokoll-Wechsel-Intervall
+LogConfigHandler.rotationIntervalLong=Protokoll-Wechsel-Intervall - Zeitraum
nach dem die Protokolle gewechselt werden. Wir behalten die letzten zwei
Protokoll-Dateien (current (aktuell) und prev (vorhergehend)) und viele
komprimierte Protokoll-Dateien bis zu maxZippedLogsSize
(maxKomprimierteProtokollGr??e)
+LoggerHook.unrecognizedPriority=Unbekannter Priorit?ts-Name: ${name}.
+LongOption.parseError=Der angegebene Wert konnte nicht als eine, 64-bit lange,
ganze Zahl erkannt werden: ${val}
+MeaningfulNodeNameUserAlert.noNodeNick=Anscheinend kennt Ihr Knoten Ihren
Nickname (Spitznamen) nicht. Ihre E-Mail-Adresse oder IRC-Nickname hier
einzuf?gen, ist allgemein gesprochen, eine gute Idee und hilft ihren Freunden
ihren Knoten zu identifizieren. (Beachten Sie, dass nur Ihre darknet-Partner,
die auf der Freunde-Seite aufgelistet sind, Ihren Knoten-Namen sehen k?nnen,
Fremde k?nnen ihn nicht einsehen).
+MeaningfulNodeNameUserAlert.noNodeNickTitle=Ihr Knoten-Name ist nicht gesetzt.
+N2NTMToadlet.composingMessageLabel=N2NTM zum Senden an die folgenden Partner
verfassen:
+N2NTMToadlet.delayed=Zur?ckgezogen: Das Senden der Nachricht zum Partner
erfolgt m?glicherweise verz?gert
+N2NTMToadlet.delayedTitle=Verz?gert
+N2NTMToadlet.failed=Nachricht nicht an Partner gesendet: Partner nicht
verbunden
+N2NTMToadlet.failedTitle=Fehlgeschlagen
+N2NTMToadlet.friends=Freunde
+N2NTMToadlet.noSuchFileOrCannotRead=Nicht in der Lage die Datei zu senden:
Entweder existiert sie nicht, oder sie kann nicht gelesen (zugegriffen) werden.
+N2NTMToadlet.peerName=Name des Partners
+N2NTMToadlet.peerNotFoundTitle=Partner nicht gefunden
+N2NTMToadlet.peerNotFoundWithHash=Der Partner mit dem Hash-Code
\u201c${hash}\u201d konnte nicht gefunden werden.
+N2NTMToadlet.processingSend=Senden der Knoten-zu-Knoten-Text-Nachricht in
Bearbeitung
+N2NTMToadlet.queued=Eingereiht: Der Partner ist nicht verbunden, deshalb wurde
die Nachricht in die Warteschlange eingereiht, f?r den Zeitpunkt wenn er sich
verbindet.
+N2NTMToadlet.queuedTitle=Eingereiht
+N2NTMToadlet.returnToFriends=Zur?ck zur Freundes-Liste
+N2NTMToadlet.sendMessage=Knoten-zu-Knoten-Text-Nachricht (N2NTM) senden
+N2NTMToadlet.sendMessageShort=Nachricht senden
+N2NTMToadlet.sendStatus=N2NTM-Sende-Status
+N2NTMToadlet.sent=Nachricht wurde an den Partner gesendet
+N2NTMToadlet.sentTitle=Gesendet
+N2NTMToadlet.tooLong=N2NTMs sind auf 1024 Zeichen beschr?nkt
+N2NTMToadlet.tooLongTitle=Zu lang
+N2NTMUserAlert.delete=L?schen
+N2NTMUserAlert.header=Von: ${from} (erstellt ${composed} | gesendet ${sent} |
empfangen ${received})
+N2NTMUserAlert.reply=Antworten
+N2NTMUserAlert.title=Knoten-zu-Knoten-Text-Nachricht ${number} von ${peername}
(${peer})
+Node.alwaysAllowLocalAddresses=Das Verbinden mit Knoten ?ber lokale Adressen
immer erlauben?
+Node.alwaysAllowLocalAddressesLong=Wenn aktiviert, wird der Knoten versuchen
sich sowohl ?ber die lokalen Adressen (localhost, LAN) als auch ?ber die
?ffentlichen IPs mit den Knoten zu verbinden. Wenn dies nicht aktiviert ist,
k?nnen Sie es immer noch f?r spezifische Darknet-Partner einschalten (aber
nicht f?r Opennet-Partner). Aktivieren Sie dies, wenn Sie sich mit anderen
Knoten im selben LAN (Netzwerk) oder Computer verbinden wollen und es Ihnen
nichts ausmacht, dass fehlerhafte Referenzen Ihren Knoten dazu veranlassen
k?nnen, UDP-Pakete zu Ger?ten in Ihrem LAN zu senden.
+Node.bandwidthLimitMustBePositiveOrMinusOne=Das Bandbreiten-Limit muss positiv
oder -1 sein
+Node.bindTo=Zu benutzende IP-Adresse(n)
+Node.bindToLong=Zu benutzende IP-Adresse(n)
+Node.buggyJVM=Die JVM, die Sie benutzen (${version}), ist bekannterma?en
fehlerhaft. Sie kann OutOfMemoryError's (KeinVerbleibenderSpeicherFehler)
verursachen obwohl noch mehr als genug Speicher verf?gbar ist. Bitte
aktualisieren Sie mindestens auf Sun Java 1.4.2_13, 1.5.0_10 oder 1.6
(empfohlen). Siehe http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4855795 .
+Node.buggyJVMTitle=Warnung vor fehlerhafter JVM
+Node.buggyJVMWithLink=Die JVM, die Sie benutzen (${version}), ist
bekannterma?en ${link}fehlerhaft${/link}. Sie kann OutOfMemoryError's
(KeinVerbleibenderSpeicherFehler) verursachen obwohl noch mehr als genug
Speicher verf?gbar ist. Bitte aktualisieren Sie mindestens auf Sun Java
1.4.2_13, 1.5.0_10 oder 1.6 (empfohlen).
+Node.bwlimitMustBePositive=Das Bandbreiten-Limit muss positiv sein
+Node.databaseMemory=Maximale Speichernutzung des Datenspeichers
+Node.databaseMemoryLong=Maximale Speichernutzung der Datenbank die die
Datenspeicher-Indizies vorh?lt. 0 bedeutet kein Limit (auf ~30% der maximalen
Speicherkapazit?t begrenzt)
+Node.deadlockTitle=M?gliches Einfrieren aufgrund fehlerhafter
JVM/Kernel-Kombination
+Node.deadlockWarning=WARNUNG: Ihr System scheint eine Sun JVM mit NTPL
auszuf?hren. Es ist bekannt, dass dies den Knoten, dadurch, dass die JVM eine
Sperre verliert, zum einfrieren bringen kann. Bitte deaktivieren Sie NTPL,
falls m?glich, indem Sie die folgende Umgebungsvariable setzen
LD_ASSUME_KERNEL=2.4.1 . Neuere Versionen des Freenet-Installationsprogramms
sollten dies bereits beinhalten; installieren Sie Freenet entweder neu, oder
bearbeiten Sie die run.sh
(https://emu.freenetproject.org/svn/trunk/apps/installer/installclasspath/run.sh).
Auf manchen Systemen m?ssen Sie vielleicht die pthreads-Bibliotheken
installieren, damit es funktioniert. Beachten Sie, dass der Knoten automatisch
versuchen wird sich selbst neu zu starten, wenn es zu einem Deadlock
(Verklemmung) kommt, aber dies ist nicht 100%-ig zuverl?ssig und ben?tigt Zeit.
+Node.disableHangCheckers=Alle Funktions-Pr?fungen ausschalten
+Node.disableHangCheckersLong=Alle ?berpr?fungs-/?berwachungs-Funktionen
ausschalten (werden haupts?chlich benutzt um die Funktionst?chtigkeit des
Knotens zu ?berpr?fen). Aktivieren Sie dies wenn Sie ein
Anti-Profiling-Fanatiker sind.
+Node.disablePHTLS=Wahrscheinlichkeitsbasierte HTL ausschalten
+Node.disablePHTLSLong=Wahrscheinlichkeitsbasierte HTL ausschalten (ver?ndern
Sie dies nur wenn Sie genau wissen was Sie tun)
+Node.dropPacketEvery=Paket-Verlust-Frequenz f?r Tests
+Node.dropPacketEveryLong=Frequenz mit der Pakete vernichtet werden.
Test-Option die von den Entwicklern genutzt wird um Paket-Verlust zu
simulieren. 0 bedeutet, dass kein Paket k?nstlich "verloren" wird. Bitte nicht
ver?ndern!
+Node.errorApplyingConfig=Fehler beim Anwenden der neuen Konfiguration: ${error}
+Node.extraPeerDir=Partner-Daten-Verzeichnis
+Node.extraPeerDirLong=Name des Verzeichnis in dem zus?tzliche Partner-Daten
gespeichert werden.
+Node.forceBigShrink=Gro?e Daten-Kompressionen sofort ausf?hren
+Node.forceBigShrinkLong=Wenn aktiviert, werden gro?e Speicher-Komprimierungen
(?ber 10%) sofort ausgef?hrt (anstatt auf den n?chsten Neustart des Knotens zu
warten). Komprimierungen im laufenden Betrieb bewahren nicht die zuletzt
benutzten Daten, daher ist dies nicht empfehlenswert; benutzen Sie dies nur,
wenn Sie ein sofortiges Ergebnis haben m?ssen.
+Node.inBWLimit=Limit f?r ausgehende Bandbreite (Bytes pro Sekunde)
+Node.inBWLimitLong=Limit f?r die hereinkommende Bandbreite (Bytes/Sek); der
Knoten wird versuchen dieses nicht zu ?berschreiten; -1 = 4x das gesetzte Limit
f?r die ausgehende Bandbreite
+Node.invalidStoreSize=Die Speicher-Gr??e muss mindestens 32MB betragen
+Node.l10nLanguage=Die Sprache die der Knoten benutzt um Nachrichten anzuzeigen
+Node.l10nLanguageLong=Diese Einstellung ?ndert die Sprache in der Nachrichten
angezeigt werden. Beachten Sie, dass manche Zeichenfolgen erst beim n?chsten
Start des Knotens ?bersetzt werden.
+Node.maxHTL=Maximale HTL
+Node.maxHTLLong=Maximale HTL (NUR F?R ENTWICKLUNGS-ZWECKE BENUTZEN!)
+Node.mustBePositive=Der Konfigurations-Wert muss positiv sein
+Node.nodeDir=Knoten-Verzeichnis
+Node.nodeDirLong=Der Name des Verzeichnisses in welchem Knoten-bezogene
Dateien (z.B. die Partner-Liste) gespeichert werden
+Node.nodeName=Spitzname f?r diesen Freenet-Knoten
+Node.nodeNameLong=Knoten-Name (Nickname). Dieser wird nur f?r Ihre Freunde
sichtbar sein.
+Node.oneConnectionPerIP=Auf eine Verbindung pro Adresse beschr?nken?
+Node.oneConnectionPerIPLong=Nicht mehr als eine Verbindung pro Adresse
erlauben? Dies wird es Angreifern ein bisschen schwerer machen sich, als
verschiedene Identit?ten, mehr als einmal mit Ihrem Knoten zu verbinden, um Ihr
Routing (Weiterleitungs-Strategie) zu beherrschen oder Harvesting (Sammeln von
Daten) zu erleichtern. Es verhindert auch gleichzeitig mit demselben Knoten
?ber darknet und opennet verbunden zu sein.
+Node.opennetEnabled=Promiskuitiven Modus einschalten (automatisch mit nicht
vertrauensw?rdigen Knoten verbinden)?
+Node.opennetEnabledLong=Promiskuitiven Modus einschalten? Wenn dies aktiviert
ist, wird der Knoten automatisch Referenzen mit anderen nicht
vertrauensw?rdigen Knoten (Fremden im Gegensatz zu Freunden) austauschen. Dies
bedeutet aber, dass die Tatsache, dass Sie einen Knoten betreiben, nicht l?nger
vertraulich ist und viele Attacken viel einfacher sind. Wenn Sie gen?gend Leute
kennen, die Freenet benutzen, sollten Sie bei vertrauensw?rdigen (Freunde)
Verbindungen mit ihnen bleiben.
+Node.outBWLimit=Limit f?r die ausgehende Bandbreite (Bytes pro Sekunde)
+Node.outBWLimitLong=Strenges Limit f?r die ausgehende Bandbreite (Bytes/Sek);
der Knoten sollte dies fast niemals ?berschreiten
+Node.passOpennetPeersThroughDarknet=Opennet-Knotenreferenzen ?ber
Darknet-Partner weiterleiten?
+Node.passOpennetPeersThroughDarknetLong=Wenn aktiviert, werden
Opennet-Knotenreferenzen (NIEMALS unsere eigene Darknet-Knotenreferenz) ?ber
unsere Darknet-Partner weitergeleitet. Sodass ein Knoten (dieser Knoten oder
seine Partner) Opennet-Partner von seinen Darknet-Partnern bekommen kann. Dies
ist n?tzlich, da es uns erlaubt einen Bootstrap (Erlangung neuer Quellen ohne
vorher welche zu haben) mit neuen Opennet-Partnern durchzuf?hren nachdem wir
unsere Partner, zum Beispiel durch Ausfallzeiten, verloren haben. Jedoch kann
es eine Traffic(Verkehrs)-Analyse etwas erleichtern, deshalb sollten Sie es
ausschalten wenn Sie paranoid sind.
+Node.port=FNP-Port Nummer (UDP)
+Node.portLong=UDP-Port f?r Knoten-zu-Knoten Kommunikationen
(Freenet-Knoten-Protokoll)
+Node.storeDirectory=Speicher-Verzeichnis
+Node.storeDirectoryLong=Name des Verzeichnisses in welchem die
Speicher-Dateien platziert werden
+Node.storeMaxMemTooHigh=Mehr als 80% Ihres RAMs (Hauptspeichers) an BDB
(Datenbank) abzugeben ist wahrscheinlich nicht das was Sie tun wollen!
+Node.storeSize=Speicher-Gr??e in Bytes
+Node.storeSizeLong=Gr??e des Speichers in Bytes.
+Node.swapRInterval=Tausch-Anfragen-Sende-Intervall (ms)
+Node.swapRIntervalLong=Intervall in dem Tausch-Anfragen gesendet werden in
Millisekunden. Lassen Sie dies in Ruhe!
+NodeClientCore.allowInsecureCHK=Unsichere CHKs erlauben?
+NodeClientCore.allowInsecureCHKLong=Vor (Version) 1010, waren alle CHKs
unsicher (nur halb verschl?sselt). Alte CHKs erlauben?
+NodeClientCore.allowInsecureSSK=Unsichere SSKs erlauben?
+NodeClientCore.allowInsecureSSKLong=Vor (Version) 1010, waren alle SSKs
unsicher (nur halb verschl?sselt). Alte SSKs erlauben?
+NodeClientCore.couldNotFindOrCreateDir=Das Verzeichnis konnte weder gefunden
noch angelegt werden
+NodeClientCore.downloadAllowedDirs=Verzeichnisse in welche das Herunterladen
erlaubt ist
+NodeClientCore.downloadAllowedDirsLong=Per Semikolon getrennte Liste von
Verzeichnissen, in welche das Herunterladen erlaubt ist. "downloads" steht f?r
das Download-Verzeichnis, wenn das Feld leer ist bedeutet dies, dass keine
Dateien auf Datentr?ger heruntergeladen werden d?rfen, "all" erlaubt das
Herunterladen ?berall hin. WARNUNG! Wenn diese Option auf "all" gesetzt wird,
kann jeder Benutzer jede Datei an jeden Ort auf Ihrem Computer herunterladen!
+NodeClientCore.downloadDir=Standard Download-Verzeichnis
+NodeClientCore.downloadDirLong=Das Verzeichnis in welchem heruntergeladene
Dateien standardm??ig gespeichert werden
+NodeClientCore.fileForClientStats=Datei in welcher die Statistiken gespeichert
werden
+NodeClientCore.fileForClientStatsLong=Datei in der die Drosselungs-Statistiken
gespeichert werden (wird ben?tigt um herauszufinden wie oft Anfragen gesendet
werden sollen).
+NodeClientCore.ignoreTooManyPathComponents=Zu viele Pfad-Komponenten ignorieren
+NodeClientCore.ignoreTooManyPathComponentsLong=Wenn aktiviert, wird der Knoten
keine "TOO_MANY_PATH_COMPONENTS"-Fehler erzeugen wenn er einen URI bekommt,
welcher am Ende dessen was zum abrufen des Schl?ssels notwendig ist,
zus?tzliche, sinnlose Unterverzeichnisse (/blah/blah) enth?lt (zum Beispiel
haben alte CHKs oft Dateinamen am Ende welche nicht Teil der urspr?nglichen
Einf?geoperation waren; dies ist ?berholt, weil man nun den Dateinamen mit
angeben kann und es verwirrend ist willk?rliche Zeichenketten zu einem URI
hinzuf?gen zu k?nnen, und es macht es schwer sie zu vergleichen). Aktivieren
Sie diese Einstellung nur, wenn Sie dies f?r die Kompatibilit?t mit anderen
Anwendungen ben?tigen; sie wird in K?rze entfernt.
+NodeClientCore.lazyResume=Vervollst?ndige das Laden persistenter Anfragen beim
Start? (Braucht mehr Speicher)
+NodeClientCore.lazyResumeLong=Der Knoten kann persistente (dauerhafte)
anstehende Anfragen beim Starten laden, oder er kann die Daten in den Speicher
einlesen und dann die Anfragen nachdem der Knoten vollst?ndig gestartet ist
komplettieren. K?rzere Start-Zeiten, braucht aber mehr Speicher.
+NodeClientCore.maxUSKFetchers=Maximal erlaubte Anzahl von USK-Abrufern
+NodeClientCore.maxUSKFetchersLong=Maximale Anzahl zugelassener USK-Abrufer
+NodeClientCore.maxUSKFetchersMustBeGreaterThanZero=Muss gr??er als Null sein
+NodeClientCore.movingTempDirOnTheFlyNotSupported=Das Verschieben des
tempor?ren Verzeichnisses im laufenden Betrieb, wird im Moment (noch?) nicht
unterst?tzt
+NodeClientCore.persistentTempDir=Verzeichnis f?r persistente tempor?re Dateien
+NodeClientCore.persistentTempDirLong=Name des Verzeichnisses in welchem
persistente (dauerhafte) tempor?re Dateien gespeichert werden
+NodeClientCore.tempDir=Tempor?res Verzeichnis
+NodeClientCore.tempDirLong=Name des Verzeichnisses, in dem die tempor?ren
Dateien gespeichert werden
+NodeClientCore.uploadAllowedDirs=Verzeichnisse von denen das Hochladen erlaubt
ist
+NodeClientCore.uploadAllowedDirsLong=Per Semikolon getrennte Liste von
Verzeichnissen, von denen das Hochladen erlaubt ist. Ein leeres Feld bedeutet,
dass das Hochladen von Datentr?gern nicht erlaubt ist, "all" bedeutet, dass
Dateien von jedem Ort hochgeladen werden d?rfen (inklusive System-Dateien
usw.!). WARNUNG! Wenn diese Option auf "all" gesetzt ist, kann jede Datei auf
Ihrem Computer von jedem Benutzer hochgeladen werden.
+NodeIPDectector.inclLocalAddress=Lokale Adressen zur noderef (Knoten ID)
hinzuf?gen
+NodeIPDectector.inclLocalAddressLong=Lokale Adressen (LAN und localhost) zur
noderef (Knoten-ID) hinzuf?gen. Dies ist nur dann von Nutzen, wenn beide Seiten
f?r die entsprechenden Knoten-IDs "allowLocalAddresses=true"
(=erlaubeLokaleAdressen) gesetzt haben (dies k?nnen Sie im erweiterten Modus
auf der Freunde-Seite tun).
+NodeIPDectector.ipOverride=IP-Adresse ?berschreiben
+NodeIPDectector.ipOverrideLong=IP-Adresse ?berschreiben (normalerweise nicht
ben?tigt) - aktivieren Sie dies, wenn Sie eine *statische* IP-Adresse oder eine
Domain (z.B. per DynDNS) haben, und sich hinter einer Firewall befinden.
+NodeIPDectector.tempAddressHint=Hinweis auf tempor?re IP-Adresse
+NodeIPDectector.tempAddressHintLong=Tempor?rer Hinweis wie die aktuelle
IP-Adresse lauten k?nnte; wird nach Gebrauch gel?scht.
+NodeIPDetector.maybeSymmetric=Es scheint als ob Ihr Knoten hinter einer
symmetrischen NAT (Router) sein k?nnte. Sie k?nnten Verbindungs-Probleme haben:
Wenn Sie sich hinter einer symmetrischen NAT befinden, werden Sie sich
wahrscheinlich nur mit Partnern verbinden k?nnen, die offen im Internet (direkt
mit dem Internet verbunden) sind.
+NodeIPDetector.maybeSymmetricTitle=Verbindungs-Probleme
+NodeIPDetector.unknownHostErrorInIPOverride=Unbekannter Host (Computer):
${error}
+NodeStat.aggressiveGC="Aggressiver GC"-Modifikator
+NodeStat.aggressiveGCLong=Erlaubt es dem Benutzer die Zeit zwischen GC
(Garbage-Collection) und gezwungenem Abschluss anzupassen. SOLLTE NICHT
VER?NDERT WERDEN es sei denn Sie wissen genau was Sie tun! -1 bedeutet:
gezwungenen Aufruf von System.gc() und System.runFinalization() deaktivieren
+NodeStat.freeHeapBytesThreshold="Freier Heap-Speicher"-Schwelle
+NodeStat.freeHeapBytesThresholdLong=Der Knoten wird versuchen, die Anzahl
seiner freien Heap(Halden-Speicher)-Bytes ?ber dem Schwellwert zu halten, indem
er neue Anfragen ablehnt
+NodeStat.freeHeapPercentThreshold="Freier Heap-Anteil"-Schwelle (in %)
+NodeStat.freeHeapPercentThresholdLong=Der Knoten wird versuchen, seinen
Prozentsatz an freiem Heap (Halden-Speicher) (von der maximal erlaubten
Heap-Gr??e) ?ber dem Schwellwert zu halten, indem er neue Anfragen ablehnt
+NodeStat.memCheck=Speicher-?berpr?fung einschalten
+NodeStat.memCheckLong=Speicher-?berpr?fung einschalten (schreibt eine
Nachricht in die Log-Datei, Voraussetzung damit der aggressiveGCModificator
("aggressiver Garbage-Collector"-Modifikator) Wirkung zeigt!)
+NodeStat.statsPersister=Datei in der die Knoten-Statistiken gespeichert werden
+NodeStat.statsPersisterLong=Datei, in der die Knoten-Statistiken gespeichert
werden (nicht die Client(Kunden)-Statistiken, und diese werden benutzt um zu
entscheiden ob Anfragen akzeptiert werden, deshalb bitte nicht l?schen)
+NodeStat.threadLimit=Thread-Limit
+NodeStat.threadLimitLong=Der Knoten wird versuchen seinen
Thread(Prozess-Strang)-Gebrauch auf den angegebenen Wert zu beschr?nken, indem
er neue Anfragen ablehnt
+NodeStats.mustBePercentValueNotFull=Dieser Wert muss eine Prozent-Zahl
zwischen 0 und 99 sein.
+NodeStats.valueTooLow=Dieser Wert ist zu niedrig f?r diese Einstellung,
erh?hen Sie ihn!
+NodeUpdateManager.enabled=Auf neue Versionen pr?fen und herunterladen
+NodeUpdateManager.enabledLong=Soll Ihr Knoten automatisch nach neuen Versionen
von Freenet suchen? Wenn ja, werden neue Versionen automatisch erkannt und
heruntergeladen, aber nicht unbedingt installiert. Diese Einstellung stellt
sich immer wieder auf "false" (falsch), es sei denn der Knoten l?uft innerhalb
des Wrappers (Schutz-/Hilfsumgebung).
+NodeUpdateManager.extURI=Wo soll der Knoten nach Aktualisierungen f?r
freenet-ext.jar suchen?
+NodeUpdateManager.extURILong=Wo soll der Knoten nach Aktualisierungen f?r
freenet-ext.jar suchen?
+NodeUpdateManager.installNewVersions=Neue Versionen automatisch installieren
+NodeUpdateManager.installNewVersionsLong=Soll ihr Knoten sich automatisch auf
die neuste Version von Freenet aktualisieren ohne Nachzufragen?
+NodeUpdateManager.invalidExtURI=Ung?ltiger externer URI: ${error}
+NodeUpdateManager.invalidRevocationURI=Ung?ltiger Widerrufs-URI: ${error}
+NodeUpdateManager.invalidUpdateURI=Ung?ltiger Aktualisierungs-URI: ${error}
+NodeUpdateManager.noUpdateWithoutWrapper=Kann den Knoten nicht aktualisieren,
da er nicht unter dem Wrapper (Schutz-/Hilfsumgebung) ausgef?hrt wird
+NodeUpdateManager.revocationURI=Wo soll der Knoten nach dem
Widerrufs-Schl?ssel suchen?
+NodeUpdateManager.revocationURILong=URI f?r den Widerrufs-Schl?ssel. Wenn
dieser gefunden wird, wird der Knoten den Inhalt anzeigen und die automatischen
Aktualisierungen deaktivieren.
+NodeUpdateManager.updateCatastropheTitle=Katastrophaler Fehler bei der
Aktualisierung!
+NodeUpdateManager.updateFailed=Aktualisierung fehlgeschlagen: ${reason}
+NodeUpdateManager.updateFailedTitle=Aktualisierung fehlgeschlagen!
+NodeUpdateManager.updateURI=Wo soll der Knoten nach Aktualisierungen suchen?
+NodeUpdateManager.updateURILong=Wo soll der Knoten nach Aktualisierungen
suchen?
+OpennetConnectionsToadlet.fullTitle=${counts} Fremde (nicht vertrauensw?rdige
Partner) von ${name}
+OpennetConnectionsToadlet.peersListTitle=Meine Opennet-Partner (nicht
vertrauensw?rdige Partner die vom Knoten im promiskuitiven Modus hinzugef?gt
wurden)
+OpennetUserAlert.warning=Ihr Knoten l?uft gerade im promiskuitiven Modus. Er
wird sich mit Fremden verbinden und dies bedeutet, dass jeder herausfinden
kann, dass Sie einen Knoten betreiben. Die meisten Attacken sind einfacher, das
blockieren Ihres Knotens (zum Beispiel durch eine nationale Firewall) ist sehr
viel einfacher und Sie haben keine Kontrolle ?ber wen sich Ihr Knoten
verbindet. Wir empfehlen Ihnen dringend, dass Sie Verbindungen mit Freunden
(vertrauensw?rdigen Knoten, die von Leuten die Sie bereits kennen betrieben
werden) bekommen; der promiskuitive Modus ist nur als eine tempor?re (zeitlich
beschr?nkte) Ma?nahme gedacht, bis Sie in der Lage sind, sich nur noch mit
Ihren Freunden zu verbinden. Wenn Sie sich nur mit Ihren Freunden verbinden,
ist es weniger wahrscheinlich, obwohl es ihnen m?glich ist, dass Sie
angegriffen werden, als wenn Ihr Knoten jeder Regierungs-Beh?rde (Geheimdienst)
oder anderen b?sen Menschen ausgesetzt ist, die sich mit ihm verbinden wollen.
Beachten Sie, dass das Hinzuf?gen eines Partners in der Freundes-Liste nicht
viel hilft, wenn der Partner nicht jemandem geh?rt, den Sie kennen (aus
Routing(Weiterleitungs)- und Sicherheits-Gr?nden)!
+OpennetUserAlert.warningTitle=Warnung: Promiskuitiver Modus aktiviert: Ihr
Knoten wird sich mit Fremden verbinden
+PNGFilter.invalidHeader=Die Datei, die Sie versucht haben abzurufen, ist keine
PNG-Datei. Sie enth?lt keinen g?ltigen PNG-Header (Dateikopf). Es k?nnte sich
um ein anderes Dateiformat handeln und Ihr Browser k?nnte etwas gef?hrliches
damit tun, deshalb wurde sie blockiert.
+PNGFilter.invalidHeaderTitle=Keine PNG-Datei - ung?ltiger Header
+PeerManagerUserAlert.clockProblem=${count} Ihrer Knoten sind nicht in der Lage
sich zu verbinden, weil ihre System-Zeit sich um mehr als 24 Stunden von Ihrer
unterscheidet. Bitte ?berpr?fen Sie, ob Ihr Computer die korrekte Zeit hat.
Eine inkorrekte Zeit wird das Fehlschlagen von vielen Knoten- und
Client-Mechanismen verursachen.
+PeerManagerUserAlert.clockProblemTitle=Zeit-Problem
+PeerManagerUserAlert.connError=${count} Ihrer Partner k?nnen sich aus einer
unbekannten Ursache nicht verbinden, m?glicherweise aufgrund eines fehlerhaften
Knotens oder einer besch?digten Knoten-Referenz.
+PeerManagerUserAlert.connErrorTitle=Einige Partner k?nnen sich nicht verbinden
+PeerManagerUserAlert.noConns=Dieser Knoten war bis jetzt nicht in der Lage,
sich mit anderen Knoten zu verbinden; er wird nicht normal funktionieren.
Hoffentlich werden sich ein paar Ihrer Partner bald verbinden; wenn nicht,
versuchen Sie einige weitere Partner zu finden. Sie brauchen zu jedem Zeitpunkt
mindestens 3 (verbundene) Partner und sollten 5-10 anstreben.
+PeerManagerUserAlert.noConnsTitle=Keine offenen Verbindungen
+PeerManagerUserAlert.noPeersDarknet=Dieser Knoten hat keine Partner mit denen
er sich verbinden kann, deshalb wird er nicht normal funktionieren. Im
Idealfall sollten Sie sich mit Partner-Knoten verbinden, die von Leuten
betrieben werden die Sie kennen (wenn Sie paranoid sind, dann Leute denen Sie
vertrauen; wenn nicht, dann zumindest Leute mit denen Sie gesprochen haben).
Sie brauchen zu jeder Zeit mindestens 3 verbundene Partner und im Idealfall
5-10. Sie k?nnten sich auf irc.freenode.net im Kanal #freenet-refs einloggen
und nach jemandem zum Verbinden fragen, aber bedenken Sie, dass Sie gegen?ber
denen, mit denen Sie direkt verbunden sind, verletzbar sind. (Dies gilt vor
allem f?r diese fr?he Alpha-Version von Freenet 0.7...) GEHEN SIE SICHER, DASS
DIE ANDERE PERSON IHRE REFERENZ AUCH HINZUGEF?GT HAT, DA EINSEITIGE
VERBINDUNGEN NICHT FUNKTIONIEREN WERDEN!
+PeerManagerUserAlert.noPeersTestnet=Dieser Knoten hat keine Partner mit denen
er sich verbinden kann, deshalb wird er nicht normal funktionieren. Im
Idealfall sollten Sie sich mit Partner-Knoten verbinden, die von Leuten
betrieben werden die Sie kennen (wenn Sie paranoid sind, dann Leute denen Sie
vertrauen; wenn nicht, dann zumindest Leute mit denen Sie gesprochen haben).
Sie brauchen zu jeder Zeit mindestens 3 verbundene Partner und im Idealfall
5-10. Aber da dies ein Testnet-Knoten ist, schlagen wir Ihnen vor, sich auf
irc.freenode.net im Kanal #freenet-refs einzuloggen und nach jemandem zum
Verbinden zu fragen.
+PeerManagerUserAlert.noPeersTitle=Keine Partner gefunden
+PeerManagerUserAlert.oneConn=Dieser Knoten hat nur eine Verbindung. Die
Leistung wird beeintr?chtigt sein und Sie haben weder Anonymit?t noch
glaubw?rdige Abstreitbarkeit wenn diese Person b?swillig ist. Ihr Knoten ist
wie ein "Blatt" mit dem Netzwerk verbunden und tr?gt nicht zur Gesundheit des
Netzwerks bei. Versuchen Sie zu jedem Zeitpunkt mindestens 3 (im Idealfall
mehr, wie 5-10) verbundene Partner zu bekommen.
+PeerManagerUserAlert.onlyFewConnsTitle=Nur ${count} offene Verbindung(en)
+PeerManagerUserAlert.tooHighBwlimitDelayTime=Dieser Knoten muss zu lange auf
verf?gbare Bandbreite warten (${delay}ms > ${max}ms). Erh?hen Sie ihre
ausgehende Bandbreite und/oder entfernen Sie ein paar Partner (von der
Freundes-Liste) um die Situation zu verbessern.
+PeerManagerUserAlert.tooHighBwlimitDelayTimeTitle=bwlimitDelayTime zu hoch
+PeerManagerUserAlert.tooHighPingTime=Dieser Knoten hat Schwierigkeiten schnell
genug mit seinen Partnern zu kommunizieren (${ping}ms > ${max}ms). Erh?hen Sie
ihre ausgehende Bandbreite und/oder entfernen Sie ein paar Partner (von der
Freundes-Liste) um die Situation zu verbessern.
+PeerManagerUserAlert.tooHighPingTimeTitle=nodeAveragePingTime
(knotenDurchschnittsAntwortZeit) zu hoch
+PeerManagerUserAlert.tooManyConns=Dieser Knoten hat zu viele Verbindungen
(${count} > ${max}). Gro?e Mengen von Knoten automatisch (zur Freundes-Liste)
hinzuzuf?gen, bildet keine Small-World-Topologie (Kleine-Welt-Netzstruktur),
schadet dem Routing (weiterleiten von Anfragen) und riskiert
Single-Points-of-Failure (einzelne Fehlerstellen) zu bilden.
+PeerManagerUserAlert.tooManyConnsTitle=Zu viele offene Verbindungen
+PeerManagerUserAlert.tooManyDisconnected=Dieser Knoten hat zu viele nicht
verbundene Partner (${count} > ${max}). Dies wird einen leichten Einfluss auf
die Leistung haben, da nicht verbundene Partner auch einen kleinen Teil der
Bandbreite und CPU (Rechenleistung) verbrauchen. Ziehen Sie ein "S?ubern" Ihrer
Freundes-Liste in Betracht. Beachten Sie, dass Sie sich idealerweise mit
Leuten, die Sie kennen, verbinden sollten. Selbst wenn nicht, das Hinzuf?gen
von gro?en Mengen von Knoten ist schlecht, da es keine optimale Topologie
(Netzstruktur) herstellt.
+PeerManagerUserAlert.tooManyDisconnectedTitle=Zu viele nicht verbundene Partner
+PeerManagerUserAlert.tooManyNeverConnected=Viele Partner dieses Knotens haben
sich nicht ein einziges Mal verbunden: ${count}. Sie sollten Partner nicht
hinzuf?gen, wenn Sie nicht wissen, dass diese Ihre Referenz auch hinzugef?gt
haben. Andernfalls werden diese sich nicht verbinden.
+PeerManagerUserAlert.tooManyNeverConnectedTitle=Viele Partner haben sich noch
nicht ein einziges Mal verbunden
+PeerManagerUserAlert.tooManyNeverConnectedWithLink=Viele Partner dieses
Knotens haben sich nicht ein einziges Mal verbunden: ${count}. Sie sollten
Partner nicht hinzuf?gen, wenn Sie nicht wissen, dass diese ${link}Ihre
Referenz${/link} auch hinzugef?gt haben. Andernfalls werden diese sich nicht
verbinden.
+PeerManagerUserAlert.tooManyPeers=Dieser Knoten hat zu viele Partner (${count}
> ${max}). Wir empfehlen nicht, "?ber-Knoten" mit automatischem Hinzuf?gen von
Partnern zu betreiben; Dies bildet keine Small-World-Topologie
(Kleine-Welt-Netzstruktur). Dies wird au?erdem Ihre Leistung marginal
beeinflussen, da nicht verbundene Partner einen kleinen Teil der Bandbreite und
CPU (Rechenleistung) verbrauchen. Ziehen Sie ein "S?ubern" Ihrer Freundes-Liste
in Betracht.
+PeerManagerUserAlert.tooManyPeersTitle=Zu viele Partner
+PeerManagerUserAlert.tooOldNeverConnectedPeers=Ein oder mehrere Partner Ihres
Knotens haben sich in den zwei Wochen, seit Sie hinzugef?gt wurden, niemals
verbunden. Ziehen Sie in Betracht sie zu entfernen, da sie die Leistung
marginal beeinflussen (es werden Pakete daran verschwendet, mit Knoten zu
kommunizieren, die nicht da sind).
+PeerManagerUserAlert.tooOldNeverConnectedPeersTitle=Zu alte(r), niemals
verbundene(r) Partner
+PeerManagerUserAlert.twoConns=Dieser Knoten hat nur zwei Verbindungen.
Leistung und Sicherheit werden nicht sehr gut sein, und ihr Knoten betreibt
kein Routing (Weiterleiten von Anfragen) f?r andere Knoten. Ihr Knoten ist im
Netzwerk wie in einer "Kette" eingebunden und tr?gt nicht (viel) zur Gesundheit
des Netzwerks bei. Versuchen Sie zu jeder Zeit mindestens 3 (im Idealfall mehr,
wie 5-10) verbundene Partner zu bekommen.
+PeersSayKeyBlownAlert.connectedSayBlownLabel=Diese verbundenen Knoten melden,
dass der Schl?ssel unbrauchbar gemacht wurde (wir versuchen das
Widerrufs-Zertifikat von Ihnen herunterzuladen):
+PeersSayKeyBlownAlert.disconnectedSayBlownLabel=Diese Knoten meldeten uns,
dass der Schl?ssel unbrauchbar w?re, trennten jedoch dann die Verbindung,
weshalb wir das Widerrufs-Zertifikat nicht abrufen konnten:
+PeersSayKeyBlownAlert.failedFetch=Ihr Knoten war nicht in der Lage, das
Widerrufs-Zertifikat herunterzuladen. M?gliche Ursachen beinhalten eine Attacke
auf Ihren Knoten um zu versuchen Sie zum Aktualisieren zu bewegen obwohl der
Schl?ssel unbrauchbar ist, oder dass Ihre Knoten, bez?glich des unbrauchbaren
Schl?ssels, l?gen. Bitte kontaktieren Sie die Entwickler oder andere
Freenet-Benutzer um dieses Durcheinander zu l?sen.
+PeersSayKeyBlownAlert.failedTransferSayBlownLabel=Diese Knoten meldeten uns,
dass der Schl?ssel unbrauchbar sei, scheiterten aber darin das
Widerrufs-Zertifikat zu ?bertragen:
+PeersSayKeyBlownAlert.fetching=Ihr Knoten versucht gerade das
Widerrufs-Zertifikat herunterzuladen, um mehr Details in Erfahrung zu bringen.
+PeersSayKeyBlownAlert.intro=Ein oder mehrere Ihrer Partner melden, dass der
Schl?ssel der automatischen Aktualisierung unbrauchbar sei! Dies bedeutet, dass
ein Angreifer den privaten Schl?ssel f?r das automatische
Aktualisierungs-System kennen k?nnte und deshalb Ihren Knoten zur Ausf?hrung
von Code seiner Wahl veranlassen k?nnte (wenn Sie aktualisieren)! Das
automatische Aktualisierungs-System wurde ausgeschaltet. Es ist auch m?glich,
dass Ihre Partner diesbez?glich bewusst l?gen.
+PeersSayKeyBlownAlert.titleWithCount=Laut ${count} Partner(n) ist der
Schl?ssel der automatischen Aktualisierung unbrauchbar!
+PluginManager.cannotSetOnceLoaded=Kann die Plugin(=Erweiterungs)-Liste nicht
modifizieren sobald sie geladen wurde
+PluginManager.loadedOnStartup=Plugins die beim Start geladen werden
+PluginManager.loadedOnStartupLong=Klassenpfad, Name und Verzeichnis f?r
Plugins (Erweiterungen) die beim Start des Knotens geladen werden sollen
+PluginManager.loadedPlugins=Plugins die beim Start geladen werden
+PluginManager.loadedPluginsLong=Eine Liste von Plugins (Erweiterungen) die
gestartet werden wenn der Knoten startet
+PluginManager.pluginReqNewerJVM=Das Plugin (Erweiterung) ${name} scheint eine
neuere JVM zu ben?tigen. Bitte installieren Sie mindestens Sun Java 1.5, oder
entfernen Sie das Plugin.
+PluginManager.pluginReqNewerJVMTitle=Das Plugin (Erweiterung) ${name} ben?tigt
eine neuere JVM.
+PluginToadlet.addPluginTitle=Ein Plugin hinzuf?gen
+PluginToadlet.failedToLoadPlugin=Laden des Plugins fehlgeschlagen.
+PluginToadlet.failedToLoadPluginCheckClass=Das Plugin (Erweiterung) das Sie
angefordert haben konnte nicht geladen werden. Bitte ?berpr?fen Sie den Namen
der Klasse des Plugins und die URL, wenn Sie eine angegeben haben.
+PluginToadlet.failedToLoadPluginTitle=Laden des Plugins fehlgeschlagen
+PluginToadlet.internalNameTitle=Interner Name
+PluginToadlet.loadPluginCommand=Plugin laden
+PluginToadlet.noWebInterface=Das Plugin hat kein Web-Interface
(Web-Schnittstelle), deshalb gibt es nichts anzuzeigen.
+PluginToadlet.noWebInterfaceTitle=Plugin hat kein Web-Interface
+PluginToadlet.pluginList=Plugin-Liste
+PluginToadlet.pluginListTitle=Liste der Plugins (Erweiterungen)
+PluginToadlet.pluginNameTitle=Plugin-Name
+PluginToadlet.pluginNotFound=Das angeforderte Plugin konnte nicht gefunden
werden.
+PluginToadlet.pluginNotFoundTitle=Plugin nicht gefunden
+PluginToadlet.returnToPluginsWithLinks=Bitte gehen Sie ${link}zur?ck${/link}
zur Liste der Plugins.
+PluginToadlet.unsupportedMethod=Nicht unterst?tzte Methode.
+PluginToadlet.unsupportedMethodTitle=Nicht unterst?tzte Methode
+PluginToadlet.visit=Besuch
+PproxyToadlet.classNameTitle=Klassen-Name
+PproxyToadlet.internalIDTitle=Interne ID
+PproxyToadlet.loadPluginLabel=Plugin laden:
+PproxyToadlet.noPlugins=Keine Plugins geladen
+PproxyToadlet.pluginNotFoundReload=Das angegebene Plugin konnte nicht gefunden
werden um es neu zu laden.
+PproxyToadlet.pluginNotFoundReloadTitle=Plugin nicht gefunden (neu laden)
+PproxyToadlet.pluginUnloaded=Plugin entfernt
+PproxyToadlet.pluginUnloadedWithName=Das Plugin ${name} wurde entfernt.
+PproxyToadlet.plugins=Plugins
+PproxyToadlet.pluginsWithNodeName=Plugins von ${name}
+PproxyToadlet.reload=Neu laden
+PproxyToadlet.returnToPluginPage=Zur?ck zur Plugin-Seite
+PproxyToadlet.startedAtTitle=Gestartet um
+PproxyToadlet.unload=Entfernen
+PproxyToadlet.unloadPluginTitle=Plugin entfernen?
+PproxyToadlet.unloadPluginWithName=Sind Sie sich sicher, dass Sie ${name}
entfernen wollen?
+QueueToadlet.DUinProgress=Laufende Verzeichnis-Uploads
+QueueToadlet.DinProgress=Laufende Downloads
+QueueToadlet.UinProgress=Laufende Uploads
+QueueToadlet.change=?ndern
+QueueToadlet.completedDU=Vollst?ndige Verzeichnis-Uploads
+QueueToadlet.completedDinDownloadDirectory=Vollst?ndig: Downloads ins
Download-Verzeichnis (${size})
+QueueToadlet.completedDinTempDirectory=Vollst?ndig: Downloads in das tempor?re
Verzeichnis (${size})
+QueueToadlet.completedDtoDisk=Vollst?ndige Downloads auf einen Datentr?ger
+QueueToadlet.completedDtoTemp=Vollst?ndige Downloads ins Tempor?re Verzeichnis
+QueueToadlet.completedU=Vollst?ndig: Uploads (${size})
+QueueToadlet.completedUDirectory=Vollst?ndig: Verzeichnis-Uploads (${size})
+QueueToadlet.download=Download
+QueueToadlet.errorAccessDenied=Fehler: Zugriff verweigert!
+QueueToadlet.errorAccessDeniedFile=Die aktuelle Konfiguration des Knotens
untersagt Ihnen das Hochladen der Datei "${file}".
+QueueToadlet.errorDToDisk=Kann nicht auf den Datentr?ger herunterladen
+QueueToadlet.errorDToDiskConfig=Die aktuelle Konfiguration des Knotens
erlaubtes Ihnen nicht, Dateien in das Download-Verzeichnis herunterzuladen.
+QueueToadlet.errorDownloadNotCompleted=Download nicht abgeschlossen
+QueueToadlet.errorDownloadNotFound=Download nicht gefunden
+QueueToadlet.errorDownloadNotFoundExplanation=Der Download konnte nicht
gefunden werden. Vielleicht wurde er schon gel?scht?
+QueueToadlet.errorInvalidURI=Ung?ltiger URI
+QueueToadlet.errorInvalidURIToD=Der URI ist ung?ltig und kann nicht
heruntergeladen werden.
+QueueToadlet.errorInvalidURIToU=Sie haben keinen g?ltigen URI angegeben bei
dem die Datei eingef?gt wird.
+QueueToadlet.errorNoFileOrCannotRead=Die Datei existiert nicht oder kann nicht
gelesen (zugegriffen) werden
+QueueToadlet.errorNoFileSelected=Keine Datei ausgew?hlt
+QueueToadlet.errorNoFileSelectedU=Sie haben keine Datei zum Hochladen
angegeben.
+QueueToadlet.errorNoKey=Kein Schl?ssel zum Herunterladen angegeben
+QueueToadlet.errorNoKeyToD=Sie haben keinen Schl?ssel angegeben, der
heruntergeladen werden soll.
+QueueToadlet.failedD=Fehlgeschlagene Downloads
+QueueToadlet.failedDU=Fehlgeschlagene Verzeichnis-Uploads
+QueueToadlet.failedToRemove=Entfernen fehlgeschlagen ${id}: ${message}
+QueueToadlet.failedToRemoveId=Entfernen fehlgeschlagen: ${id}
+QueueToadlet.failedToRemoveRequest=Entfernen der Anfrage fehlgeschlagen
+QueueToadlet.failedToRestart=Neustart fehlgeschlagen: ${id}
+QueueToadlet.failedToRestartRequest=Neustart der Anfrage fehlgeschlagen
+QueueToadlet.failedU=Fehlgeschlagene Uploads
+QueueToadlet.fcpIsMissing=Der FCP-Server fehlt
+QueueToadlet.fileName=Dateiname
+QueueToadlet.files=Dateien
+QueueToadlet.follow=Umleitung folgen
+QueueToadlet.globalQueueIsEmpty=Die globale Warteschlange ist leer
+QueueToadlet.identifier=Bezeichnung
+QueueToadlet.insertAs=Einf?gen als:
+QueueToadlet.insertFile=Datei einf?gen
+QueueToadlet.key=Schl?ssel
+QueueToadlet.legend=Legende
+QueueToadlet.mimeType=MIME-Typ
+QueueToadlet.noTaskOnGlobalQueue=Im Moment ist keine Aufgabe in der globalen
Warteschlange.
+QueueToadlet.none=keine/r
+QueueToadlet.panicButton=Alarm-Knopf
+QueueToadlet.panicButtonConfirmation=Alle Anfragen ohne Best?tigung entfernen!
+QueueToadlet.persistence=Persistenz (Speicher-Dauer)
+QueueToadlet.persistenceForever=ewig
+QueueToadlet.persistenceNone=keine
+QueueToadlet.persistenceReboot=neustart
+QueueToadlet.pleaseEnableFCP=Sie m?ssen den FCP-Server einschalten um diese
Seite aufzurufen
+QueueToadlet.priority=Priorit?t
+QueueToadlet.priority0=Notfall
+QueueToadlet.priority1=sehr hoch
+QueueToadlet.priority2=hoch
+QueueToadlet.priority3=mittel
+QueueToadlet.priority4=niedrig
+QueueToadlet.priority5=sehr niedrig
+QueueToadlet.priority6=wird niemals fertiggestellt
+QueueToadlet.progress=Fortschritt
+QueueToadlet.progressbarAccurate=Dieser Fortschrittswert ist exakt
+QueueToadlet.progressbarNotAccurate=Dieser Fortschritts-Wert ver?ndert sich
wahrscheinlich, da der Datei-Download-Prozess noch nicht abgeschlossen ist
+QueueToadlet.reason=Grund
+QueueToadlet.remove=Entfernen
+QueueToadlet.requestNavigation=Anfragen-Navigation
+QueueToadlet.restart=Neustart
+QueueToadlet.size=Gr??e
+QueueToadlet.starting=STARTE
+QueueToadlet.title=Globale Warteschlange von ${nodeName}
+QueueToadlet.totalSize=Gesamt-Gr??e
+QueueToadlet.unknown=Unbekannt
+QueueToadlet.warningUnsafeContent=Potenziell unsicherer Inhalt
+QueueToadlet.warningUnsafeContentExplanation=Die Datei, die Sie herunterladen
wollen, wird zurzeit nicht von Freenets Inhalts-Filter ?berpr?ft! Dies
bedeutet, dass Ihre Anonymit?t durch das ?ffnen der Datei kompromittiert
(blo?gestellt) werden kann!
+QueueToadlet.wipD=In Arbeit: Downloads (${size})
+QueueToadlet.wipDU=In Arbeit: Verzeichnis-Uploads (${size})
+QueueToadlet.wipU=In Arbeit: Uploads (${size})
+RequestStarterGroup.scheduler=Priorit?ts-Verfahren des Planers
+RequestStarterGroup.schedulerLong=Das Priorit?ts-Verfahren, das vom Planer
genutzt wird, einstellen.
+RevocationKeyFoundUserAlert.text=Ihr Knoten hat den Widerrufs-Schl?ssel der
automatischen Aktualisierung im Netzwerk gefunden. Das hei?t, dass unser
automatisches Aktualisierungs-System wahrscheinlich KOMPROMITTIERT
(blo?gestellt/offen gelegt) wurde! Deshalb wurde es auf Ihrem Knoten
deaktiviert, um zu verhindern, dass "b?se Sachen" installiert werden. Wir
empfehlen Ihnen dringend, auf der Internet-Seite des Projekts nachzusehen ob
Aktualisierungen verf?gbar sind. Bitte achten Sie darauf zu pr?fen, dass die
Internet-Seite nicht gef?lscht wurde. Die Widerrufs-Nachricht lautet:
${message}.
+RevocationKeyFoundUserAlert.title=Der private Schl?ssel des Projekts wurde
kompromittiert (offengelegt)!
+ShortOption.parseError=Kann den Wert nicht als String-Array
(Zeichenfolgen-Feld) erkennen: ${error}
+SimpleToadletServer.advancedMode=Erweiterten Modus aktivieren?
+SimpleToadletServer.advancedModeLong=Ob Informationen f?r fortgeschrittene
Benutzer/Ger?te angezeigt werden sollen oder nicht. Diese Einstellung sollte in
den meisten F?llen auf false (falsch) stehen.
+SimpleToadletServer.allowedFullAccess=Hosts die vollen Zugriff auf FProxy
haben (Warnung lesen)
+SimpleToadletServer.allowedFullAccessLong=Hosts (Computer) die vollen Zugriff
(z.B. Konfiguration ?ndern, Neustarten usw.) auf den Knoten haben. WARNUNG:
Seien Sie vorsichtig wem Sie vollen FProxy-Zugriff geben!
+SimpleToadletServer.allowedHosts=Hostnamen oder IP-Adressen denen es erlaubt
ist sich mit FProxy zu verbinden.
+SimpleToadletServer.allowedHostsLong=Kann eine Komma-getrennte Liste von
einzelnen IPs und CIDR-maskierten IPs wie 192.168.0.0/24 sein. Beachten Sie,
dass diese, innerhalb der von anderen Optionen gesetzten Grenzen, auf die
Festplatte zugreifen k?nnen.
+SimpleToadletServer.bindTo=Zu benutzende IP-Adresse
+SimpleToadletServer.bindToLong=Zu benutzende IP-Adresse
+SimpleToadletServer.cannotChangePortOnTheFly=Kann die FProxy-Port-Nummer nicht
im laufenden Betrieb ?ndern
+SimpleToadletServer.couldNotChangeBindTo=Konnte die von FProxy zu benutzende
Adresse nicht ?ndern: ${error}.
+SimpleToadletServer.cssName=CSS-Name
+SimpleToadletServer.cssNameLong=Name des CSS das FProxy benutzen soll
+SimpleToadletServer.cssOverride=Das CSS durch eine benutzerdefiniertes
ersetzen (WARNUNG!)
+SimpleToadletServer.cssOverrideCantRead=Wir k?nnen die gegebene
CSS-Ersatz-Datei nicht lesen: ${filename}
+SimpleToadletServer.cssOverrideLong=Diese Einstellung erlaubt es Ihnen, die
CSS-Datei des Knotens mit einer benutzerdefinierten Datei zu ersetzen. WARNUNG:
CSS-Dateien k?nnen gef?hrlich sein und werden nicht gefiltert! Benutzung auf
eigene Gefahr. (denken Sie dar?ber nach devl at freenetproject zu kontaktieren
um sie in die Haupt-Distribution aufnehmen zu lassen ;-) )
+SimpleToadletServer.cssOverrideNotInUploads=Wir k?nnen Sie diese Einstellung
nicht setzen lassen: "${filename}" ist kein Verzeichnis, von welchem Uploads
(Hochladen) erlaubt sind!
+SimpleToadletServer.doRobots=Roboter mithilfe der robots.txt ausschlie?en?
+SimpleToadletServer.doRobotsLong=Ob eine /robots.txt bereitgehalten werden
soll, die Google, spiders, wget, usw. sagt, dass sie weggehen sollen
+SimpleToadletServer.enableJS=Benutzung von Javascript durch FProxy aktivieren?
+SimpleToadletServer.enableJSLong=Ob FProxy Javascript-"Helfer" benutzen soll
oder nicht. Diese Einstellung sollte in den meisten F?llen auf false (falsch)
gesetzt werden. Beachten Sie, dass Freesites kein Javascript benutzen k?nnen,
auch wenn dies aktiviert ist.
+SimpleToadletServer.enabled=FProxy aktivieren?
+SimpleToadletServer.enabledLong=Ob FProxy und verwandte HTTP-Dienste aktiviert
werden sollen
+SimpleToadletServer.illegalCSSName=CSS-Namen d?rfen keine Schr?gstriche oder
Doppelpunkte enthalten!
+SimpleToadletServer.panicButton=Den Alarm-Knopf anzeigen?
+SimpleToadletServer.panicButtonLong=Ob der Alarm-Knopf auf der
Warteschlangen-Seite (/queue/) angezeigt werden soll oder nicht.
+SimpleToadletServer.port=FProxy-Port-Nummer
+SimpleToadletServer.portLong=FProxy-Port-Nummer
+StaticToadlet.pathInvalidChars=Der angegebene URI enth?lt nicht erlaubte
Zeichen.
+StaticToadlet.pathNotFound=Der Pfad, den Sie angegeben haben, existiert nicht.
+StaticToadlet.pathNotFoundTitle=Pfad nicht gefunden
+StatisticsToadlet.activityInserts=Einf?gen: ${totalSenders} Sender insgesamt,
${CHKhandlers} CHK handler, ${SSKhandlers} SSK handler
+StatisticsToadlet.activityRequests=Anfragen: ${totalSenders} Sender insgesamt,
${CHKhandlers} CHK handler, ${SSKhandlers} SSK handler
+StatisticsToadlet.allocMemory=Zugewiesener Java-Speicher: ${memory}
+StatisticsToadlet.bandwidthTitle=Bandbreite
+StatisticsToadlet.cpus=Verf?gare CPUs: ${count}
+StatisticsToadlet.getLogs=Letzte Log-Datei des Knotens Abrufen
+StatisticsToadlet.inputRate=Eingehend: ${rate}/Sekunde (von ${max})
+StatisticsToadlet.jeDumpButton=JE-Dump generieren
+StatisticsToadlet.jvmInfoTitle=JVM-Info
+StatisticsToadlet.jvmVendor=JVM-Hersteller: ${vendor}
+StatisticsToadlet.jvmVersion=JVM-Version: ${version}
+StatisticsToadlet.maxMemory=Maximaler Java-Speicher: ${memory}
+StatisticsToadlet.noRequests=Ihr Knoten bearbeitet gerade keine Anfragen
+StatisticsToadlet.osArch=OS-Architektur: ${arch}
+StatisticsToadlet.osName=OS-Name: ${name}
+StatisticsToadlet.osVersion=OS-Version: ${version}
+StatisticsToadlet.outputRate=Ausgehend: ${rate}/Sekunde (von ${max})
+StatisticsToadlet.payloadOutput=Nutzlast ausgehend: ${total}
(${rate}/Sekunde)(${percent}%)
+StatisticsToadlet.peerStatsTitle=Partner-Statistiken
+StatisticsToadlet.threadDumpButton=Thread-Dump generieren
+StatisticsToadlet.threads=Laufende Threads: ${running}/${max}
+StatisticsToadlet.totalInput=Gesamt eingehend: ${total} (${rate}/Sekunde)
+StatisticsToadlet.totalOutput=Gesamt ausgehend: ${total} (${rate}/Sekunde)
+StatisticsToadlet.transferringRequests=?bertrage Anfragen: sende ${senders},
empfange ${receivers}
+StatisticsToadlet.usedMemory=Benutzter Java-Speicher: ${memory}
+StatisticsToadlet.versionTitle=Knoten-Versions-Informationen
+SymlinkerToadlet.symlinks=Verkn?pfungen im ToadletServer
+SymlinkerToadlet.symlinksLong=Eine Liste von "alias#target"'s
("Bezeichnung#Ziel") die eine Menge von Verkn?pfungen darstellt
+TestnetHandler.cannotEnableDisableOnTheFly=Aktivieren/deaktivieren des
Testnet-Modus im laufenden Betrieb unm?glich; starten Sie den Knoten neu und
erhalten Sie neue Verbindungen
+TestnetHandler.enable=Testnet-Modus einschalten? (GEF?HRLICH)
+TestnetHandler.enableLong=Testnet-Modus einschalten (GEF?HRLICH!). Der
Testnet-Modus macht ihre Anonymit?t zunichte, im Gegenzug hilft er den
Entwicklern enorm beim Debuggen (Fehler suchen) des Knotens.
+TestnetHandler.port=Testnet-Port
+TestnetHandler.portLong=Testnet-Portnummer (-1 = EmpfangsPort+1000)
+TextModeClientInterfaceServer.allowedHosts=Erlaubte Hosts
+TextModeClientInterfaceServer.allowedHostsLong=Host(Computer)-Namen oder
IP-Adressen denen es erlaubt ist sich mit dem TMCI zu verbinden. Dies kann eine
Komma-getrennte Liste von Host-Namen, einzelnen IPs und sogar CIDR-maskierten
IPs wie 192.168.0.0/24 sein
+TextModeClientInterfaceServer.bindTo=Zu benutzende IP-Adresse
+TextModeClientInterfaceServer.bindToLong=Zu benutzende IP-Adresse
+TextModeClientInterfaceServer.enableInputOutput=Auf stdout/stdin aktivieren?
+TextModeClientInterfaceServer.enableInputOutputLong=Text-Modus-Client-Schnittstelle
in der Standard-Ein-/Ausgabe aktivieren? (.enabled (.aktiviert) bezieht sich
auf das stellen eines Servers im Telnet-Stil, dieser f?hrt es ?ber einen Sockel
(Socket) aus)
+TextModeClientInterfaceServer.enabled=TMCI aktivieren
+TextModeClientInterfaceServer.enabledLong=Ob das TMCI aktiviert werden soll
+TextModeClientInterfaceServer.telnetPortNumber=Telnet-Port
+TextModeClientInterfaceServer.telnetPortNumberLong=Telnet-Port-Nummer
+TimeSkewDetectedUserAlert.text=Es wurde vom Knoten eine Zeitversetzung
erkannt. Das ist SEHR schlimm. Ihr Knoten wird nicht richtig laufen bis dies
behoben ist; h?ufige Ursachen sind ein falsch konfigurierter
Energie-Spar-Modus, Netzwerk-Zeit-Synchronisations-Programme, oder fehlerhafte
Hardware.
+TimeSkewDetectedUserAlert.title=Zeitversetzung erkannt!
+Toadlet.cancel=Abbrechen
+Toadlet.clickHere=Hier klicken
+Toadlet.homepage=Startseite
+Toadlet.internalErrorPleaseReport=Interner Fehler: Bitte melden Sie dies
+Toadlet.internalErrorTitle=Interner Fehler
+Toadlet.no=Nein
+Toadlet.nodeHomepage=Knoten-Startseite
+Toadlet.notSupportedTitle=Nicht unterst?tzt
+Toadlet.notSupportedWithClass=Ihr Browser hat eine Anfrage gesendet, die
Freenet (${class}) nicht verstehen konnte.
+Toadlet.ok=OK
+Toadlet.permRedirectWithReason=Permanente Weiter-/Umleitung: ${reason}
+Toadlet.returnToNodeHomepage=Zur?ck zur Knoten-Startseite
+Toadlet.returnToPrevPage=Zur?ck zur vorherigen Seite
+Toadlet.tempRedirectWithReason=Tempor?re Weiter-/Umleitung: ${reason}
+Toadlet.unauthorized=Der Zugriff aus diese Seite ist Ihnen nicht gestattet.
+Toadlet.yes=Ja
+ToadletContextImpl.cannotParseContentLength=Fehler beim Erkennen der
Inhalts-L?nge: ${error}
+ToadletContextImpl.headersLineTooLong=Zeile zu lang, beim Analysieren der
Header (Dateik?pfe)
+ToadletContextImpl.methodNotAllowed=HTTP-Methode (Funktion) nicht erlaubt
+ToadletContextImpl.noContentLengthInPOST=Keine Inhalts-L?nge im POST
+ToadletContextImpl.noSuchToadlet=Kein Toadlet mit diesem Namen
+ToadletContextImpl.parseErrorWithError=Erkennungs-Fehler: ${error}
+ToadletContextImpl.uriParseErrorTitle=URI-Erkennungs-Fehler
+TranslationToadlet.bracketRemoveOverride=(Die ?bersetzungs-Korrektur l?schen!)
+TranslationToadlet.bracketTranslateIt=(in Ihre Muttersprache ?bersetzen!)
+TranslationToadlet.bracketUpdateTranslation=(?bersetzung aktualisieren)
+TranslationToadlet.confirmRemoveOverride=Sind Sie sich sicher, dass Sie den
folgenden ?bersetzungs-Schl?ssel l?schen wollen: (${key} - ${value}) ?
+TranslationToadlet.contributingToLabelWithLang=Sie tragen gerade zur ${lang}
?bersetzung bei:
+TranslationToadlet.currentTranslationLabel=Aktuelle ?bersetzung
+TranslationToadlet.downloadTranslationsFile=Ihre ?bersetzungs-Datei
herunterladen
+TranslationToadlet.hideAlreadyTranslated=Bereits ?bersetzte Zeichenketten
verstecken
+TranslationToadlet.noCustomTranslations=Es ist keine spezielle ?bersetzung
verf?gbar.
+TranslationToadlet.originalVersionLabel=Original (Englische Version)
+TranslationToadlet.reEdit=?bersetzung ?ndern
+TranslationToadlet.remove=Entfernen
+TranslationToadlet.removeOverrideTitle=Einen ?bersetzungs-Korrektur-Schl?ssel
l?schen
+TranslationToadlet.removeOverrideWarningTitle=Sie sind dabei einen
?bersetzungs-Korrektur-Schl?ssel zu l?schen!
+TranslationToadlet.returnToTranslations=Zur?ck zur ?bersetzungs-Seite
+TranslationToadlet.showEverything=Alles anzeigen, auch schon ?bersetzte
Zeichenketten
+TranslationToadlet.translationKeyLabel=?bersetzungs-Schl?ssel
+TranslationToadlet.translationUpdateTitle=?bersetzung aktualisieren
+TranslationToadlet.translationUpdatedTitle=?bersetzung aktualisiert!
+TranslationToadlet.updateTranslationCommand=Die ?bersetzung aktualisieren!
+UnknownContentTypeException.explanation=Ihr Freenet-Knoten wei? nichts ?ber
diesen MIME-Typ. Das hei?t, dass Ihr Browser etwas gef?hrliches tun k?nnte,
wenn diese Datei heruntergeladen wird. Zum Beispiel k?nnen viele Formate
eingebettete Bilder oder Videos enthalten, welche aus dem Internet (genauer dem
Web) heruntergeladen werden; dies ist keineswegs harmlos, weil dies Ihre
Anonymit?t zunichte machen und Ihre IP-Adresse verraten kann(wenn der Angreifer
die Web-Seite betreibt oder Zugriff auf deren Log-Dateien hat). Links ins Web
(Internet) k?nnen auch eine Gefahr darstellen, aus fast denselben Gr?nden,
genau wie Scripting, aus diesen und anderen Gr?nden.
+UnknownContentTypeException.title=Unbekannter und potenziell gef?hrlicher
Inhaltstyp: ${type}
+UpdateDeployContext.cannotUpdateNoExtJar=Die freenet-ext.jar in der
wrapper.conf konnte nicht gefunden werden (gefunden wurde die freenet.jar:
${mainFilename})
+UpdateDeployContext.cannotUpdateNoJars=Konnte die Freenet-jars in der
wrapper.conf nicht finden
+UpdateDeployContext.cannotUpdateNoMainJar=Die freenet.jar in der wrapper.conf
konnte nicht gefunden werden (gefunden wurde die freenet-ext.jar:
${extFilename})
+UpdateDeployContext.updateCatastrophe=KATASTROPHALER FEHLER: ${old} wurde
gel?scht, ${new} konnte jedoch nicht zu ${old} umbenannt werden, deshalb WIRD
DER KNOTEN NICHT STARTEN! Bitte beheben Sie das Problem, indem Sie ${new}
manuell zu ${old} umbenennen.
+UpdateDeployContext.updateFailedCannotDeleteOldConfig=Die ${old} kann nicht
gel?scht werden, deshalb kann eine andere Datei nicht in ${old} umbenannt
werden. Aktualisierung fehlgeschlagen.
+UpdateDeployContext.updateFailedNonStandardConfig=Es ist, wegen einer nicht
dem Standard entsprechenden Konfiguration(s-Datei), nicht m?glich zu
Aktualisieren: gesetzt main=${main} ext=${ext} - dies sollte nicht passieren!
Berichten Sie dies den Entwicklern, f?gen Sie dabei Ihre wrapper.conf hinzu.
+UpdatedVersionAvailableUserAlert.alsoDownloadedNewExtJar=Ihr Knoten hat auch
eine neue Version der Freenet-Extra-Jar heruntergeladen, Version ${version}
+UpdatedVersionAvailableUserAlert.armed=Ihr Knoten wird automatisch neustarten,
sobald er die neue Version von Freenet fertig heruntergeladen und ?berpr?ft hat.
+UpdatedVersionAvailableUserAlert.clickToUpdateASAP=Klicken Sie unten um Ihren
Knoten zu aktualisieren sobald die Aktualisierung ?berpr?ft wurde.
+UpdatedVersionAvailableUserAlert.clickToUpdateNow=Klicken Sie unten, um Ihren
Knoten sofort zu aktualisieren.
+UpdatedVersionAvailableUserAlert.downloadedNewExtJar=Ihr Knoten hat eine neue
Version der Freenet-Extra-Jar heruntergeladen, Version ${version}.
+UpdatedVersionAvailableUserAlert.downloadedNewJar=Ihr Knoten hat eine neue
Version von Freenet heruntergeladen, Version ${version}.
+UpdatedVersionAvailableUserAlert.fetchingNewBoth=Ihr Knoten l?dt gerade eine
neue Version von Freenet herunter (Knoten-Version ${nodeVersion} und
Extra-Jar-Version ${extVersion}).
+UpdatedVersionAvailableUserAlert.fetchingNewExt=Ihr Knoten l?dt gerade eine
neue Version von Freenet herunter (Extra-Jar-Version ${extVersion}).
+UpdatedVersionAvailableUserAlert.fetchingNewNode=Ihr Knoten l?dt gerade eine
neue Version von Freenet herunter (Knoten-Version ${nodeVersion}).
+UpdatedVersionAvailableUserAlert.finalCheck=Ihr Knoten macht gerade einen
abschlie?enden Test um die Sicherheit der Aktualisierung zu ?berpr?fen
(${count} von ${max}, maximal verbleibende Zeit ${time}).
+UpdatedVersionAvailableUserAlert.notLatest=Ihr Knoten scheint nicht die neuste
Version der Software auszuf?hren.
+UpdatedVersionAvailableUserAlert.title=Eine neue stabile Version von Freenet
ist verf?gbar
+UpdatedVersionAvailableUserAlert.updateASAPButton=Sobald wie m?glich
aktualisieren
+UpdatedVersionAvailableUserAlert.updateASAPQuestion=M?chten Sie, dass der
Knoten automatisch neustartet sobald er die Aktualisierung heruntergeladen hat?
+UpdatedVersionAvailableUserAlert.updateNowButton=Jetzt aktualisieren!
+UserAlert.apply=?bernehmen
+UserAlert.hide=Verstecken
+UserAlert.reset=Zur?cksetzen
+UserAlertManager.alertsOnHomepage=| Betrachten Sie sie auf ${link}der
Freenet-Startseite${/link}.
+UserAlertManager.alertsTitle=Ausstehende Warnungen
+UserAlertManager.criticalErrorCountLabel=Kritische Fehler:
+UserAlertManager.errorCountLabel=Fehler:
+UserAlertManager.minorCountLabel=Unwichtig:
+UserAlertManager.totalLabel=Gesamt:
+UserAlertManager.warningCountLabel=Warnungen:
+WelcomeToadlet.activityTitle=Derzeitige Aktivit?t
+WelcomeToadlet.arkFetchCount=ARK-Abrufer: ${total}
+WelcomeToadlet.confirmAddBookmarkSubTitle=Hinzuf?gen des Lesezeichens
best?tigen
+WelcomeToadlet.confirmAddBookmarkTitle=Ein Lesezeichen hinzuf?gen
+WelcomeToadlet.confirmAddBookmarkWithKey=Bitte best?tigen Sie, dass Sie den
Schl?ssel ${key} zu Ihren Lesezeichen hinzuf?gen wollen und geben Sie die
Beschreibung, die Sie vorziehen, ein:
+WelcomeToadlet.confirmExternalLinkSubTitle=Externen Link best?tigen
+WelcomeToadlet.confirmExternalLinkTitle=WARNUNG: Externer Link
+WelcomeToadlet.confirmExternalLinkWithURL=Bitte best?tigen Sie, dass Sie auf
${url} gehen wollen. WARNUNG: Sie verlassen FREENET! Das Anklicken dieses Links
WIRD Ihre Anonymit?t ernsthaft aufs Spiel setzen! Es wird dringend empfohlen
dies nicht zu tun!
+WelcomeToadlet.confirmFIN=Wollen Sie die folgende Frost-Nachricht einf?gen?
+WelcomeToadlet.databaseStatsSubTitle=Datenbank-Statistiken
+WelcomeToadlet.databaseStatsTitle=JE-Statistiken abrufen
+WelcomeToadlet.disabledAlert=Alarm ausgeschaltet
+WelcomeToadlet.extVersion=Freenet-ext Build #${build} r${rev}
+WelcomeToadlet.extVersionWithRecommended=Freenet-ext Build #${build}
(${recbuild} ist empfohlen) r${rev}
+WelcomeToadlet.fetch=Abrufen
+WelcomeToadlet.fetchKeyLabel=Einen Schl?ssel abrufen
+WelcomeToadlet.finInsertSuccessWithKey=Die Nachricht wurde erfolgreich in
${key} eingef?gt.
+WelcomeToadlet.finInsertedTitle=Einf?gen
+WelcomeToadlet.finTitle=Frost-Sofort-Notiz einf?gen
+WelcomeToadlet.fromHeader=Von
+WelcomeToadlet.goToExternalLink=Zum angegebenen Link gehen
+WelcomeToadlet.homepageFullTitleWithName=Freenet-FProxy-Startseite von ${name}
+WelcomeToadlet.ieWarning=Sie scheinen Microsoft Internet Explorer zu benutzen.
Das bedeutet, dass manche Seiten im Freenet in der Lage sein k?nnten Ihre
Anonymit?t zu kompromittieren (gef?hrden)!
+WelcomeToadlet.ieWarningTitle=Sicherheits-Risiko!
+WelcomeToadlet.insertCount=Einf?gen: ${total}
+WelcomeToadlet.insertFailedTitle=Einf?gen fehlgeschlagen
+WelcomeToadlet.insertFailedWithMessage=Das Einf?gen schlug mit folgender
Nachricht fehl: ${message}
+WelcomeToadlet.insertSucceededTitle=Einf?gen erfolgreich
+WelcomeToadlet.insertedTitle=Einf?gen
+WelcomeToadlet.keyInsertedSuccessfullyWithKeyAndName=Der Schl?ssel
${link}${name}${/link} wurde erfolgreich eingef?gt.
+WelcomeToadlet.keyRequestLabel=Schl?ssel:
+WelcomeToadlet.messageHeader=Nachricht
+WelcomeToadlet.nodeUpdateConfirm=Sind Sie sich sicher, dass Sie Ihren
Freenet-Knoten aktualisieren wollen?
+WelcomeToadlet.nodeUpdateConfirmTitle=Knoten-Aktualisierung best?tigen
+WelcomeToadlet.post=Post
+WelcomeToadlet.privateKeyHeader=Privater Schl?ssel
+WelcomeToadlet.publicKeyHeader=?ffentlicher Schl?ssel
+WelcomeToadlet.requestCount=Anfragen: ${total}
+WelcomeToadlet.restart=Neustarten
+WelcomeToadlet.restartConfirm=Sind Sie sich sicher, dass Sie Ihren
Freenet-Knoten neustarten wollen?
+WelcomeToadlet.restartConfirmTitle=Knoten-Neustart
+WelcomeToadlet.restartNode=Den Knoten neustarten
+WelcomeToadlet.restarting=Bitte warten Sie, w?hrend der Knoten neugestartet
wird. Dies kann bis zu 3 Minuten dauern. Danke, dass Sie Freenet benutzen.
+WelcomeToadlet.restartingTitle=Der Freenet-Knoten wird neugestartet.
+WelcomeToadlet.shutdown=Herunterfahren
+WelcomeToadlet.shutdownConfirm=Sind Sie sich sicher, dass Sie Ihren
Freenet-Knoten herunterfahren wollen?
+WelcomeToadlet.shutdownConfirmTitle=Knoten herunterfahren
+WelcomeToadlet.shutdownDone=Der Freenet-Knoten wurde erfolgreich
heruntergefahren.
+WelcomeToadlet.shutdownNode=Den Knoten herunterfahren
+WelcomeToadlet.splitfileErrorLabel=Teil-Datei-spezifischer Fehler:
+WelcomeToadlet.startIndexHeader=Start-Index
+WelcomeToadlet.subjectHeader=Betreff
+WelcomeToadlet.targetBoardHeader=Ziel-Forum
+WelcomeToadlet.testnetWarning=L?uft im Testnet-Modus. Dies WIRD Ihre
Anonymit?t ernsthaft aufs Spiel setzen!
+WelcomeToadlet.testnetWarningTitle=Testnet-Modus
+WelcomeToadlet.thanks=Danke, dass Sie Freenet benutzen.
+WelcomeToadlet.threadDumpNotUsingWrapper=Es ist nicht m?glich, den Knoten
einen Thread-Dump (Prozess-Abbild) erstellen zu lassen, wenn Sie den Wrapper
(Schutz-/Hilfsumgebung) nicht benutzen!
+WelcomeToadlet.threadDumpSubTitle=Thread-Dump Erzeugung
+WelcomeToadlet.threadDumpTitle=Einen Thread-Dump abrufen
+WelcomeToadlet.threadDumpWithFilename=Ein Thread-Dump (Prozess-Abbild) wurde
erstellt, es ist verf?gbar in ${filename}.
+WelcomeToadlet.transferringRequestCount=?bertragungs-Anfragen: ${total}
+WelcomeToadlet.update=Aktualisieren
+WelcomeToadlet.updating=Der Freenet-Knoten wird aktualisiert und wird sich
selbst neustarten. Der Neustart kann bis zu 10 Minuten dauern, weil der Knoten
versuchen wird, vor der Aktualisierung einen Widerrufs-Schl?ssel abzurufen.
+WelcomeToadlet.updatingTitle=Knoten-Aktualisierung
+WelcomeToadlet.uriWouldHaveBeen=Der URI w?re gewesen: ${uri}
+WelcomeToadlet.version=Freenet ${fullVersion} Build #${build} r${rev}
+WelcomeToadlet.versionHeader=Versions-Informationen & Knoten-Steuerung
+WelcomeToadlet.writtenDatabaseStats=Datenbank-Laufzeit-Statistiken wurden in
die Wrapper-Protokoll-Datei geschrieben
+testing.test=test$(test1)test$(test2)test
+End
Modified: branches/freenet-jfk/src/freenet/l10n/freenet.l10n.en.properties
===================================================================
--- branches/freenet-jfk/src/freenet/l10n/freenet.l10n.en.properties
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/l10n/freenet.l10n.en.properties
2007-08-21 20:26:59 UTC (rev 14828)
@@ -24,6 +24,7 @@
BookmarkEditorToadlet.error=Error
BookmarkEditorToadlet.invalidKeyTitle=Invalid Key
BookmarkEditorToadlet.invalidKeyWithReason=Invalid Freenet key.
+BookmarkEditorToadlet.invalidKey=The Freenet key is invalid.
BookmarkEditorToadlet.keyLabel=Key:
BookmarkEditorToadlet.moveDown=Down
BookmarkEditorToadlet.moveUp=Up
@@ -34,6 +35,7 @@
BookmarkEditorToadlet.pasteTitle=Cut/Paste
BookmarkEditorToadlet.save=Save
BookmarkEditorToadlet.title=Bookmark Editor
+BookmarkEditorToadlet.urlDecodeError=URL Decode Error
BookmarkItem.bookmarkUpdated=The bookmarked site ${name} has been updated to
edition ${edition}.
BookmarkItem.bookmarkUpdatedTitle=Bookmark Updated: ${name}
BookmarkItem.bookmarkUpdatedWithLink=The bookmarked site
${link}${name}${/link} has been updated to edition ${edition}.
@@ -58,6 +60,7 @@
ConfigToadlet.appliedTitle=Configuration Applied
ConfigToadlet.apply=Apply
ConfigToadlet.configNavTitle=Configuration Navigation
+ConfigToadlet.contributeTranslation=Contribute to the translation
ConfigToadlet.defaultIs=The default for that configuration option is:
'${default}'.
ConfigToadlet.fullTitle=Freenet Node Configuration of ${name}
ConfigToadlet.possibilitiesTitle=Your Possibilities
@@ -99,25 +102,29 @@
DarknetConnectionsToadlet.cantFetchNoderefURL=Unable to retrieve node
reference from ${url}. Please try again.
DarknetConnectionsToadlet.cantParseTryAgain=Unable to parse the given text as
a node reference: (${error}). Please try again.
DarknetConnectionsToadlet.cantParseWrongEnding=Unable to parse the node
reference: It should end with End on a line by itself, but it ends with: ${end}
+DarknetConnectionsToadlet.clockProblem=Your clock and the node's clock differ
by more than 24 hours. We have disabled the connection as this may cause
problems with updating and clients.
+DarknetConnectionsToadlet.clockProblemShort=Clock Problem
DarknetConnectionsToadlet.confirmRemoveNode=Are you sure you wish to remove
"${name}" ? Before it has at least one week downtime, it's not recommended to
do so, as it may be down only temporarily, and many users cannot run their
nodes 24x7.
DarknetConnectionsToadlet.confirmRemoveNodeTitle=Please confirm
DarknetConnectionsToadlet.confirmRemoveNodeWarningTitle=Node Removal
DarknetConnectionsToadlet.connected=Connected: We're successfully connected to
these nodes
DarknetConnectionsToadlet.connectedShort=Connected
+DarknetConnectionsToadlet.darknetFnpPort=Darknet FNP: ${port}/UDP (used to
connect to trusted peers i.e. Friends; forward this port if you can)
DarknetConnectionsToadlet.disabled=Not connected and disabled: because the
user has instructed the node not to connect to these peers.
DarknetConnectionsToadlet.disabledShort=Disabled
DarknetConnectionsToadlet.enterDescription=Enter description:
+DarknetConnectionsToadlet.connError=Connection failed (buggy node?)
+DarknetConnectionsToadlet.connErrorShort=Connection Error
DarknetConnectionsToadlet.failedToAddNodeInternalError=Unable to parse the
given text as a node reference. Please report the following to the developers:
DarknetConnectionsToadlet.failedToAddNodeInternalErrorTitle=Failed to Add
Node: Internal Error
DarknetConnectionsToadlet.failedToAddNodeTitle=Failed To Add Node
DarknetConnectionsToadlet.fcpDisabled=FCP is disabled (for Freenet clients
such as Frost and Thaw)
DarknetConnectionsToadlet.fcpPort=FCP: ${port}/TCP (for Freenet clients such
as Frost and Thaw)
DarknetConnectionsToadlet.fileReference=Choose the file containing the
reference here:
-DarknetConnectionsToadlet.fnpPort=FNP: ${port}/UDP (between nodes; this is
usually the only port that you might want to port forward)
DarknetConnectionsToadlet.forceRemove=Force Remove
DarknetConnectionsToadlet.fproxyDisabled=FProxy is disabled (this web
interface)
DarknetConnectionsToadlet.fproxyPort=FProxy: ${port}/TCP (this web interface)
-DarknetConnectionsToadlet.fullTitle=${counts} Friends of ${name}
+DarknetConnectionsToadlet.fullTitle=${counts} Friends (Trusted Peers) of
${name}
DarknetConnectionsToadlet.go=Go
DarknetConnectionsToadlet.idleTime=How long since the node connected or was
last seen
DarknetConnectionsToadlet.idleTimeTitle=Connected / Idle
@@ -128,7 +135,7 @@
DarknetConnectionsToadlet.listenOnlyShort=Listen only
DarknetConnectionsToadlet.listening=Not connected but listening: this node
won't try to connect to these peers very often because the user has set
BurstOnly on it.
DarknetConnectionsToadlet.listeningShort=Listening
-DarknetConnectionsToadlet.myFriends=My Friends
+DarknetConnectionsToadlet.myFriends=My Friends (trusted peers added by me)
DarknetConnectionsToadlet.myReferenceHeader=${linkref}My Node
Reference${/linkref} (${linktext}as text${/linktext})
DarknetConnectionsToadlet.nameClickToMessage=The node's name. Click on the
name link to send the node a N2NTM (Node To Node Text Message)
DarknetConnectionsToadlet.nameTitle=Name
@@ -139,6 +146,7 @@
DarknetConnectionsToadlet.nodePortsTitle=Ports used by the Node
DarknetConnectionsToadlet.notConnected=Not connected: No connection so far but
this node is continuously trying to connect.
DarknetConnectionsToadlet.notConnectedShort=Disconnected
+DarknetConnectionsToadlet.opennetFnpPort=Opennet FNP: ${port}/UDP (used to
connect to untrusted peers i.e. Strangers; forward this port if you can)
DarknetConnectionsToadlet.pasteReference=Paste the reference here:
DarknetConnectionsToadlet.privateNote=A private note concerning this peer
DarknetConnectionsToadlet.privateNoteTitle=Private Note
@@ -165,25 +173,30 @@
ExtOldAgeUserAlert.extTooOldTitle=Freenet-ext too old
FirstTimeWizardToadlet.homepageTitle=Freenet first time wizard!
FirstTimeWizardToadlet.chooseNodeName=Node name required!
-FirstTimeWizardToadlet.chooseNodeNameLong=Please enter a node name in the
field below. This name won't be published to anyone except the peers you are
connected to. We recommend to put your real-name or IRC nick in there possibly
with some contact information so that you can be reached in case there is a
problem ("John Doe <noname at nowhere.com>").
-FirstTimeWizardToadlet.welcomeInfoboxTitle=Welcome to freenet first time
wizard!
-FirstTimeWizardToadlet.welcomeInfoboxContent1=Welcome to freenet first time
wizard. This tool will enable you to configure your node quickly and easily to
get you started. Please
+FirstTimeWizardToadlet.chooseNodeNameLong=Please enter a node name in the
field below (we recommend a nickname possibly with an email address). This is
so that your friends (trusted peers, which you have manually added) can easily
name your node. This is not visible to strangers (untrusted automatically added
peers). Note that any friend or stranger may trivially identify you from your
IP address, since you are connected to them, but they cannot easily tell what
you are requesting.
+FirstTimeWizardToadlet.connectToStrangers=Connect to strangers?
+FirstTimeWizardToadlet.connectToStrangersLong=If you let Freenet connect to
strangers, Freenet will be less secure for you, everybody can find out that you
are using Freenet, and any bad guy can connect to your node. If you don't, you
will have to manually contact at least three other friends (people you already
know) who are using Freenet and connect to them.
+FirstTimeWizardToadlet.enableOpennet=Automatically connect to untrusted
strangers' nodes?
+FirstTimeWizardToadlet.welcomeInfoboxTitle=Welcome to Freenet first time
wizard!
+FirstTimeWizardToadlet.welcomeInfoboxContent1=Welcome to Freenet first time
wizard. This tool will enable you to configure your node quickly and easily to
get you started. Please
FirstTimeWizardToadlet.bandwidthLimit=Bandwidth limits
FirstTimeWizardToadlet.bandwidthLimitLong=Please select your internet
connection type and speed from the dropdown menu below.
+FirstTimeWizardToadlet.continue=Continue
FirstTimeWizardToadlet.datastoreSize=Datastore size
-FirstTimeWizardToadlet.datastoreSizeLong=Please select a size for your
datastore. The datastore acts like a cache; storing data for the network will
help you to get better thoughput when requesting popular files. The more space
you can afford the better it is for the community and the faster your node will
go.
+FirstTimeWizardToadlet.datastoreSizeLong=Please select a size for your
datastore. The datastore acts like a cache; storing data for the network will
help you to get better throughput when requesting popular files. The more space
you can afford the better it is for the community and the faster your node will
go.
FirstTimeWizardToadlet.isNetworkTrusted=Is your local network trusted ?
FirstTimeWizardToadlet.isNetworkTrustedLong=Is your local network trusted ? If
you answer yes here all the services provided by your node will be wide open to
everyone willing to access them on the given network. You will be able to do
selective access controls from the configuration page when the wizard is over.
-FirstTimeWizardToadlet.noNetworkIF=No additionnal network interface found
-FirstTimeWizardToadlet.noNetworkIFLong=Freenet hasn't found any additionnal
network interface. It will assume that you will connect to it from your
computer and only from it.
+FirstTimeWizardToadlet.noNetworkIF=No additional network interface found
+FirstTimeWizardToadlet.noNetworkIFLong=Freenet hasn't found any additional
network interface. It will assume that you will connect to it from your
computer and only from it.
FirstTimeWizardToadlet.iDoTrust=Do you trust people connected to ${interface}
(${ip}) ?
FirstTimeWizardToadlet.congratz=Welcome on board!
-FirstTimeWizardToadlet.congratzLong=Contratulations, the base configuration of
your freenet node is now done. You can change and edit any of the parameters
you have just set going to the "configuration" page, reachable anytime from the
menu on the left of the interface. We wish you a pleasant freenet experience.
-FirstTimeWizardToadlet.step1Title=Freenet first time wizard! - Choose a node
name
-FirstTimeWizardToadlet.step2Title=Freenet first time wizard! - Bandwidth limits
-FirstTimeWizardToadlet.step3Title=Freenet first time wizard! - Datastore size
-FirstTimeWizardToadlet.step4Title=Freenet first time wizard! - Network
configuration
-FirstTimeWizardToadlet.step5Title=Freenet first time wizard! -
Congratulations, your node is now configured
+FirstTimeWizardToadlet.congratzLong=Congratulations, the base configuration of
your Freenet node is now done. You can change and edit any of the parameters
you have just set going to the "configuration" page, reachable anytime from the
menu on the left of the interface. We wish you a pleasant Freenet experience.
+FirstTimeWizardToadlet.step1Title=Freenet first time wizard! - Friends and
strangers
+FirstTimeWizardToadlet.step2Title=Freenet first time wizard! - Choose a node
name
+FirstTimeWizardToadlet.step3Title=Freenet first time wizard! - Bandwidth limits
+FirstTimeWizardToadlet.step4Title=Freenet first time wizard! - Datastore size
+FirstTimeWizardToadlet.step5Title=Freenet first time wizard! - Network
configuration
+FirstTimeWizardToadlet.step6Title=Freenet first time wizard! -
Congratulations, your node is now configured
FirstTimeWizardToadlet.skipWizard=I am not a newbie, please skip the wizard!
FProxyToadlet.abortToHomepage=Abort and return to the FProxy home page
FProxyToadlet.backToFProxy=${link}Click here${/link} to go to the FProxy home
page.
@@ -199,6 +212,7 @@
FProxyToadlet.errorIsFatal= This is a fatal error. It is unlikely that
retrying will solve the problem.
FProxyToadlet.errorWithReason=Error: ${error}
FProxyToadlet.expectedKeyButGot=Expected a Freenet key, but got:
+FProxyToadlet.expectedMimeType=Expected MIME type: ${mime}
FProxyToadlet.explanationTitle=Explanation
FProxyToadlet.fetchLargeFileAnywayAndDisplay=Fetch anyway and display file in
browser
FProxyToadlet.fileInformationTitle=File Information
@@ -212,17 +226,18 @@
FProxyToadlet.largeFile=Large file
FProxyToadlet.largeFileExplanationAndOptions=The Freenet key you requested
refers to a large file. Files of this size cannot generally be sent directly to
your browser since they take too long for your Freenet node to retrieve. The
following options are available:
FProxyToadlet.mayChange= (may change)
-FProxyToadlet.mimeType=Expected MIME type: ${mime}
FProxyToadlet.mimeType=MIME type: ${mime}
FProxyToadlet.notEnoughMetaStrings=Not enough meta-strings
FProxyToadlet.notFoundTitle=Not Found
FProxyToadlet.openAsText=${link}Click here${/link} to open the file as plain
text (this should not be dangerous but it may be garbled).
FProxyToadlet.openForce=${link}Click here${/link} to open the file as ${mime}
(read warning above!).
FProxyToadlet.openForceDisk=${link}Click here${/link} to force your browser to
download the file to disk.
-FProxyToadlet.openPossRSSAsForceDisk=${link}Click here${/link} to try to force
your browser to download the file to disk (this ${bold}this may also be
dangerous${/bold} if you run Firefox 2.0.0, 2.0.1 should fix this).
+FProxyToadlet.openPossRSSForceDisk=${link}Click here${/link} to try to force
your browser to download the file to disk (this ${bold}this may also be
dangerous${/bold} if you run Firefox 2.0.0, 2.0.1 should fix this).
FProxyToadlet.openPossRSSAsPlainText=${link}Click here${/link} to open the
file as plain text (this ${bold}may be dangerous${/bold} if you are running IE7
or FF2).
FProxyToadlet.openRSSAsRSS=${link}Click here${/link} to open the file as RSS
(this ${bold}is dangerous${/bold} if the site author is malicious as Freenet
does not know how to filter RSS yet).
FProxyToadlet.openRSSForce=${link}Click here${/link} to open the file as
${mime} (this ${bold}may be dangerous${/bold} on IE7 or FF2).
+FProxyToadlet.opennet=manage untrusted connections
+FProxyToadlet.opennetTitle=Strangers
FProxyToadlet.options=Your options are:
FProxyToadlet.pathNotFound=The specified path does not exist.
FProxyToadlet.pathNotFoundTitle=Path Not Found
@@ -235,8 +250,6 @@
FProxyToadlet.sizeUnknown=Size: unknown
FProxyToadlet.stats=view statistics
FProxyToadlet.statsTitle=Statistics
-FProxyToadlet.translation=helper to translate the node's interface into your
native language
-FProxyToadlet.translationTitle=Translation
FProxyToadlet.unableToRetrieve=Freenet was unable to retrieve this file.
FProxyToadlet.unknownMIMEType=MIME type: unknown
FProxyToadlet.welcome=homepage
@@ -289,7 +302,9 @@
FetchException.longError.26=Archive restarted
FetchException.longError.27=Permanent redirect: use the new URI
FetchException.longError.28=Not enough data found; some data was fetched but
redirect may point to nowhere
+FetchException.longError.29=Wrong MIME Type: The key was not in the list of
allowed MIME types provided by the client
FetchException.longError.2=Don't know what to do with splitfile
+FetchException.longError.30=The request was terminated by a node because it
had recently received a request for the same key and that request had failed
FetchException.longError.3=Don't know what to do with metadata
FetchException.longError.4=Failed to parse metadata
FetchException.longError.5=Failure in extracting files from an archive
@@ -317,7 +332,9 @@
FetchException.shortError.26=Archive restarted
FetchException.shortError.27=New URI
FetchException.shortError.28=All data not found
+FetchException.shortError.29=Wrong MIME type
FetchException.shortError.2=Unknown splitfile metadata
+FetchException.shortError.30=Data not found (recently failed)
FetchException.shortError.3=Unknown metadata
FetchException.shortError.4=Invalid metadata
FetchException.shortError.5=Archive failure
@@ -325,6 +342,19 @@
FetchException.shortError.7=Too many metadata levels
FetchException.shortError.8=Too many archive restarts
FetchException.shortError.9=Too much recursion
+FileOffer.askUserTitle=Direct file transfer
+FileOffer.offeredFileHeader=The node ${name} has offered a file:
+FileOffer.fileLabel=File:
+FileOffer.senderLabel=Sender:
+FileOffer.commentLabel=Comment:
+FileOffer.mimeLabel=MIME Type:
+FileOffer.sizeLabel=Size:
+FileOffer.acceptTransferButton=Accept Transfer
+FileOffer.rejectTransferButton=Reject Transfer
+FileOffer.failedReceiveHeader=The transfer of the file ${filename} from
${node} has failed.
+FileOffer.failedReceiveTitle=Failed to receive file
+FileOffer.succeededReceiveTitle=Successfully received file
+FileOffer.succeededReceiveHeader=The transfer of the file ${filename} from
${node} was a success.
GIFFilter.invalidHeader=The file does not contain a valid GIF header.
GIFFilter.invalidHeaderTitle=Invalid header
GIFFilter.notGif=The file you tried to fetch is not a GIF. It might be some
other file format, and your browser may do something dangerous with it,
therefore we have blocked it.
@@ -431,7 +461,7 @@
LogConfigHandler.rotationIntervalLong=Log rotation interval - period after
which logs are rotated. We keep the last two log files (current and prev), plus
lots of compressed logfiles up to maxZippedLogsSize
LoggerHook.unrecognizedPriority=Unrecognised priority name: ${name}.
LongOption.parseError=The value specified can't be parsed as a 64-bit integer
: ${val}
-MeaningfulNodeNameUserAlert.noNodeNick=It seems that your node doesn't know
your nickname. Putting your e-mail address or IRC nickname here is generally
speaking a good idea and helps your friends to identify your node (note that
only your darknet peers listed on the friends page can see your node name, it
will not be displayed to opennet peers).
+MeaningfulNodeNameUserAlert.noNodeNick=It seems that your node doesn't know
your nickname. Putting your e-mail address or IRC nickname here is generally
speaking a good idea and helps your friends to identify your node (note that
only your darknet peers listed on the friends page can see your node name, it
will not be displayed to strangers).
MeaningfulNodeNameUserAlert.noNodeNickTitle=Your node name isn't defined.
N2NTMToadlet.composingMessageLabel=Composing N2NTM to send to the following
peers:
N2NTMToadlet.delayed=Backed off: Sending of message possibly delayed to peer
@@ -458,6 +488,8 @@
N2NTMUserAlert.header=From: ${from} (composed ${composed} | sent ${sent} |
received ${received})
N2NTMUserAlert.reply=Reply
N2NTMUserAlert.title=Node to Node Text Message ${number} from ${peername}
(${peer})
+Node.alwaysAllowLocalAddresses=Always allow connecting to nodes via local
addresses?
+Node.alwaysAllowLocalAddressesLong=If true, the node will attempt to connect
to nodes via their local (localhost, LAN) addresses as well as their public
IPs. If this is not set, you can still enable it for specific darknet peers
(but not opennet peers). Set this if you want to connect to other nodes on the
same LAN or computer, and don't mind that bogus references can cause your node
to send UDP packets to machines on your LAN.
Node.bandwidthLimitMustBePositiveOrMinusOne=Bandwidth limit must be positive
or -1
Node.bindTo=IP address to bind to
Node.bindToLong=IP address to bind to
@@ -492,8 +524,14 @@
Node.nodeDirLong=Name of directory to put node-related files e.g. peers list in
Node.nodeName=Nickname for this Freenet node
Node.nodeNameLong=Node nickname. This will be visible to your friends only.
+Node.oneConnectionPerIP=Limit to one connection per address?
+Node.oneConnectionPerIPLong=Don't allow more than one connection per address?
This will make it slightly harder for an attacker to connect more than once to
your node as different identities, in order to dominate your routing or make
harvesting easier. Also prevents having the same node connected on darknet and
opennet simultaneously.
+Node.opennetEnabled=Enable promiscuous mode (automatically connect to
untrusted nodes)?
+Node.opennetEnabledLong=Enable promiscuous mode? If this is enabled, the node
will automatically exchange node references with other untrusted nodes
(Strangers as opposed to Friends). But this means that the fact that you are
running a node is no longer private, and many attacks are much easier. If you
know enough people running Freenet, you should stick to trusted (Friends)
connections to them.
Node.outBWLimit=Output bandwidth limit (bytes per second)
Node.outBWLimitLong=Hard output bandwidth limit (bytes/sec); the node should
almost never exceed this
+Node.passOpennetPeersThroughDarknet=Relay opennet noderefs through darknet
peers?
+Node.passOpennetPeersThroughDarknetLong=If true, opennet noderefs (NEVER our
own darknet noderef) will be relayed through our darknet peers. So a node (this
node, or its peers) can get opennet peers from its darknet peers. This is
useful because it allows us to bootstrap new opennet peers after having lost
our peers due to downtime, for example. However, it may make traffic analysis
slightly easier, so turn it off if you are paranoid.
Node.port=FNP port number (UDP)
Node.portLong=UDP port for node-to-node communications (Freenet Node Protocol)
Node.storeDirectory=Store directory
@@ -568,8 +606,16 @@
NodeUpdateManager.updateFailedTitle=Update Failed!
NodeUpdateManager.updateURI=Where should the node look for updates?
NodeUpdateManager.updateURILong=Where should the node look for updates?
+OpennetConnectionsToadlet.fullTitle=${counts} Strangers (Untrusted Peers) of
${name}
+OpennetConnectionsToadlet.peersListTitle=My Opennet Peers (untrusted peers
added by the node in promiscuous mode)
+OpennetUserAlert.warningTitle=Warning: Promiscuous Mode Enabled: Your node
will connect to Strangers
+OpennetUserAlert.warning=Your node is currently running in promiscuous mode.
It will connect to Strangers, and this means that anyone can find out that you
are running a node. Most attacks are easier, blocking your node (for example at
a national firewall) is much easier, and you have no control over who your node
connects to. We strongly recommend you get some connections to Friends (trusted
nodes run by people you already know); promiscuous mode is only intended as a
temporary measure until you are able to just connect to your Friends. If you
only connect to your friends, while it may be possible for them to attack you,
it is less likely than if your node is exposed to any government agency/other
bad guy who wants to connect to it. Note that adding a peer in the Friends
section does not help much unless that peer belongs to somebody you actually
know (both for routing and security reasons)!
PNGFilter.invalidHeader=The file you tried to fetch is not a PNG. It does not
include a valid PNG header. It might be some other file format, and your
browser may do something dangerous with it, therefore we have blocked it.
PNGFilter.invalidHeaderTitle=Not a PNG - invalid header
+PeerManagerUserAlert.connErrorTitle=Some peers cannot connect
+PeerManagerUserAlert.connError=${count} of your peers cannot connect for an
unknown reason, possibly because of a buggy node or a corrupt node reference.
+PeerManagerUserAlert.clockProblemTitle=Clock problem
+PeerManagerUserAlert.clockProblem=${count} of your nodes are unable to connect
because their system clock is more than 24 hours different to yours. Please
check whether your computer has the correct time. Incorrect time will cause
many node and client mechanisms to fail.
PeerManagerUserAlert.noConns=This node has not been able to connect to any
other nodes so far; it will not be able to function normally. Hopefully some of
your peers will connect soon; if not, try to get some more peers. You need at
least 3 peers at any time, and should aim for 5-10.
PeerManagerUserAlert.noConnsTitle=No open connections
PeerManagerUserAlert.noPeersDarknet=This node has no peers to connect to,
therefore it will not be able to function normally. Ideally you should connect
to peers run by people you know (if you are paranoid, then people you trust; if
not, then at least people you've talked to). You need at least 3 connected
peers at all times, and ideally 5-10. You could log on to irc.freenode.net
channel #freenet-refs and ask around for somebody to connect to, but remember
that you are vulnerable to those you are directly connected to. (This is
especially true in this early alpha of Freenet 0.7...) BE SURE THAT THE OTHER
PERSON HAS ADDED YOUR REFERENCE, TOO, AS ONE-WAY CONNECTIONS WON'T WORK!
@@ -593,6 +639,13 @@
PeerManagerUserAlert.tooOldNeverConnectedPeers=One or more of your node's
peers have never connected in the two weeks since they were added. Consider
removing them since they are marginally affecting performance (wasting packets
talking to nodes that aren't there).
PeerManagerUserAlert.tooOldNeverConnectedPeersTitle=Never connected peer(s)
too old
PeerManagerUserAlert.twoConns=This node has only two connections. Performance
and security will not be very good, and your node is not doing any routing for
other nodes. Your node is embedded like a 'chain' in the network and does not
contribute (much) to the network's health. Try to get at least 3 (ideally more
like 5-10) connected peers at any given time.
+PeersSayKeyBlownAlert.intro=One or more of your peers says that the
auto-update key is blown! This means that an attacker may know the private key
for the auto-update system and can therefore cause your node to run code of his
choice (if you update)! The auto-update system has been disabled. It is also
possible that your peers are deliberately lying about it.
+PeersSayKeyBlownAlert.fetching=Your node is attempting to download the
revocation certificate to find out more details.
+PeersSayKeyBlownAlert.failedFetch=Your node has been unable to download the
revocation certificate. Possible causes include an attack on your node to try
to get you to update despite the key being blown, or your nodes lying about the
key being blown. Please contact the developers or other Freenet users to sort
out this mess.
+PeersSayKeyBlownAlert.connectedSayBlownLabel=These connected nodes say that
the key has been blown (we are trying to download the revocation cert from
them):
+PeersSayKeyBlownAlert.disconnectedSayBlownLabel=These nodes told us that the
key has been blown, but then disconnected, so we could not fetch the revocation
certificate:
+PeersSayKeyBlownAlert.failedTransferSayBlownLabel=These nodes told us that the
key has been blown, but then failed to transfer the revocation certificate:
+PeersSayKeyBlownAlert.titleWithCount=Auto-update key blown according to
${count} peer(s)!
PluginManager.cannotSetOnceLoaded=Cannot set the plugins list once loaded
PluginManager.loadedOnStartup=Plugins to load on startup
PluginManager.loadedOnStartupLong=Classpath, name and location for plugins to
load when node starts up
@@ -689,7 +742,7 @@
QueueToadlet.persistence=Persistence
QueueToadlet.persistenceForever=forever
QueueToadlet.persistenceNone=none
-QueueToadlet.persistenceRebootr=reboot
+QueueToadlet.persistenceReboot=reboot
QueueToadlet.pleaseEnableFCP=You need to enable the FCP server to access this
page
QueueToadlet.priority0=emergency
QueueToadlet.priority1=very high
@@ -758,7 +811,7 @@
StatisticsToadlet.bandwidthTitle=Bandwidth
StatisticsToadlet.cpus=Available CPUs: ${count}
StatisticsToadlet.getLogs=Get latest node's logfile
-StatisticsToadlet.inputRate=Input Rate: ${rate}/second (of ${max})
+StatisticsToadlet.inputRate=Input Rate: ${rate}/sec (of ${max})
StatisticsToadlet.jeDumpButton=Generate a JE Dump
StatisticsToadlet.jvmInfoTitle=JVM Info
StatisticsToadlet.jvmVendor=JVM Vendor: ${vendor}
@@ -768,13 +821,13 @@
StatisticsToadlet.osArch=OS Architecture: ${arch}
StatisticsToadlet.osName=OS Name: ${name}
StatisticsToadlet.osVersion=OS Version: ${version}
-StatisticsToadlet.outputRate=Output Rate: ${rate}/second (of ${max})
-StatisticsToadlet.payloadOutput=Payload Output: ${total}
(${rate}/second)(${percent}%)
+StatisticsToadlet.outputRate=Output Rate: ${rate}/sec (of ${max})
+StatisticsToadlet.payloadOutput=Payload Output: ${total}
(${rate}/sec)(${percent}%)
StatisticsToadlet.peerStatsTitle=Peer statistics
StatisticsToadlet.threadDumpButton=Generate a Thread Dump
StatisticsToadlet.threads=Running threads: ${running}/${max}
-StatisticsToadlet.totalInput=Total Input: ${total} (${rate}/second)
-StatisticsToadlet.totalOutput=Total Output: ${total} (${rate}/second)
+StatisticsToadlet.totalInput=Total Input: ${total} (${rate}/sec)
+StatisticsToadlet.totalOutput=Total Output: ${total} (${rate}/sec)
StatisticsToadlet.transferringRequests=Transferring Requests: sending
${senders}, receiving ${receivers}
StatisticsToadlet.usedMemory=Used Java memory: ${memory}
StatisticsToadlet.versionTitle=Node Version Information
@@ -795,6 +848,8 @@
TextModeClientInterfaceServer.enabledLong=Whether to enable the TMCI
TextModeClientInterfaceServer.telnetPortNumber=Telnet port
TextModeClientInterfaceServer.telnetPortNumberLong=Telnet port number
+TimeSkewDetectedUserAlert.title=Time skew detected!
+TimeSkewDetectedUserAlert.text=A time skew has been detected by the node.
That's VERY bad. Your node won't perform correctly until it's fixed; Common
causes are missconfigured powersafe mode, network time synchronization clients
or buggy hardware.
Toadlet.yes=Yes
Toadlet.no=No
Toadlet.cancel=Cancel
@@ -804,6 +859,7 @@
Toadlet.nodeHomepage=Node Homepage
Toadlet.notSupportedTitle=Not Supported
Toadlet.notSupportedWithClass=Your browser sent a request that Freenet
(${class}) could not understand.
+Toadlet.ok=Ok
Toadlet.permRedirectWithReason=Permanent redirect: ${reason}
Toadlet.returnToNodeHomepage=Return to node homepage
Toadlet.returnToPrevPage=Return to the previous page
@@ -854,7 +910,7 @@
UpdatedVersionAvailableUserAlert.fetchingNewBoth=Your node is currently
downloading a new version of Freenet (node version ${nodeVersion} and extra jar
version ${extVersion}).
UpdatedVersionAvailableUserAlert.fetchingNewExt=Your node is currently
downloading a new version of Freenet (extra jar version ${extVersion}).
UpdatedVersionAvailableUserAlert.fetchingNewNode=Your node is currently
downloading a new version of Freenet (node version ${nodeVersion}).
-UpdatedVersionAvailableUserAlert.finalCheck=Your node is currently doing a
final check to verify the security of the update (${count} of ${max}).
+UpdatedVersionAvailableUserAlert.finalCheck=Your node is currently doing a
final check to verify the security of the update (${count} of ${max}, maximum
time remaining ${time}).
UpdatedVersionAvailableUserAlert.notLatest=It seems that your node isn't
running the latest version of the software.
UpdatedVersionAvailableUserAlert.title=A new stable version of Freenet is
available
UpdatedVersionAvailableUserAlert.updateASAPButton=Update ASAP
@@ -900,6 +956,7 @@
WelcomeToadlet.insertSucceededTitle=Insert Succeeded
WelcomeToadlet.insertedTitle=Insertion
WelcomeToadlet.keyInsertedSuccessfullyWithKeyAndName=The key
${link}${name}${/link} has been inserted successfully.
+WelcomeToadlet.keyRequestLabel=Key:
WelcomeToadlet.messageHeader=Message
WelcomeToadlet.nodeUpdateConfirm=Are you sure you wish to update your Freenet
node?
WelcomeToadlet.nodeUpdateConfirmTitle=Confirm Node Update
Modified: branches/freenet-jfk/src/freenet/l10n/freenet.l10n.fr.properties
===================================================================
--- branches/freenet-jfk/src/freenet/l10n/freenet.l10n.fr.properties
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/l10n/freenet.l10n.fr.properties
2007-08-21 20:26:59 UTC (rev 14828)
@@ -21,6 +21,7 @@
BookmarkEditorToadlet.editBookmarkTitle=Modifier un marque-page
BookmarkEditorToadlet.editCategoryTitle=Modifier cat?gorie
BookmarkEditorToadlet.error=Erreur
+BookmarkEditorToadlet.invalidKey=La cl? Freenet est invalide.
BookmarkEditorToadlet.invalidKeyTitle=Cl? invalide
BookmarkEditorToadlet.invalidKeyWithReason=Cl? Freenet invalide.
BookmarkEditorToadlet.keyLabel=Cl? :
@@ -33,6 +34,7 @@
BookmarkEditorToadlet.pasteTitle=Couper/Coller
BookmarkEditorToadlet.save=Enregistrer
BookmarkEditorToadlet.title=Editeur de marque-page
+BookmarkEditorToadlet.urlDecodeError=Erreur d'URL
BookmarkItem.bookmarkUpdated=L'?dition ${edition} du site ${name} a ?t?
publi?e.
BookmarkItem.bookmarkUpdatedTitle=Signet mis ? jour : ${name}
BookmarkItem.bookmarkUpdatedWithLink=Le signet ${link}${name}${/link} a ?t?
mis ? jour vers l'?dition ${edition}.
@@ -57,6 +59,7 @@
ConfigToadlet.appliedTitle=Configuration appliqu?e
ConfigToadlet.apply=Appliquer
ConfigToadlet.configNavTitle=Sections de configuration
+ConfigToadlet.contributeTranslation=Aider ? la traduction
ConfigToadlet.defaultIs=La valeur par d?faut est : '${default}'.
ConfigToadlet.fullTitle=Configuration du noeud ${name}
ConfigToadlet.possibilitiesTitle=Vos possibilit?s
@@ -98,11 +101,16 @@
DarknetConnectionsToadlet.cantFetchNoderefURL=Impossible de r?cup?rer une
r?f?rence ? partir de ${url}. Essayez ? nouveau.
DarknetConnectionsToadlet.cantParseTryAgain=Ce texte n'est pas une r?f?rence :
(${error}). Essayez ? nouveau.
DarknetConnectionsToadlet.cantParseWrongEnding=Impossible d'analyser cette
r?f?rence : elle devrait se terminer par une lige contenant "End", mais elle se
termine par : ${end}
-DarknetConnectionsToadlet.confirmRemoveNode=Etes-vous s?r de vouloir supprimer
"+peerNodes[i].getName()+" ? Ce n'est pas recommand? avant une semaine
d'inactivit?, cette inactivit? peut ?tre temporaire, et beaucoup d'utilisateurs
ne peuvent pas laisser leur noeud tourner 24h/24.
+DarknetConnectionsToadlet.clockProblem=Votre horloge et celle de ce noeud
pr?sentent plus de 24h de d?callage. Cette connexion a ?t? d?sactiv?e car cela
peut poser des probl?mes avec les mises ? jour et les clients.
+DarknetConnectionsToadlet.clockProblemShort=Probl?me d'horloge
+DarknetConnectionsToadlet.confirmRemoveNode=Etes-vous s?r de vouloir supprimer
"${name}" ? Ce n'est pas recommand? avant une semaine d'inactivit?, cette
inactivit? peut ?tre temporaire, et beaucoup d'utilisateurs ne peuvent pas
laisser leur noeud tourner 24h/24.
DarknetConnectionsToadlet.confirmRemoveNodeTitle=Veuillez confirmer
DarknetConnectionsToadlet.confirmRemoveNodeWarningTitle=Suppression de noeud
+DarknetConnectionsToadlet.connError=La connexion a ?chou? (noeud bugg? ?)
+DarknetConnectionsToadlet.connErrorShort=Connexion ?chou?e
DarknetConnectionsToadlet.connected=Connect?s : Vous ?tes connect?s ? ces
noeuds
DarknetConnectionsToadlet.connectedShort=Connect?
+DarknetConnectionsToadlet.darknetFnpPort=Darknet FNP : ${port}/UDP
(communication entre les noeuds ; vous voudrez sans doute ouvrir ce port dans
votre firewall)
DarknetConnectionsToadlet.disabled=Non connect?s et d?sactiv?s : le noeud a
re?u pour instruction de ne pas se connecter ? ces noeuds.
DarknetConnectionsToadlet.disabledShort=D?sactiv?
DarknetConnectionsToadlet.enterDescription=Entrez un commentaire :
@@ -116,7 +124,7 @@
DarknetConnectionsToadlet.forceRemove=Forcer la suppression
DarknetConnectionsToadlet.fproxyDisabled=FProxy est d?sactiv? (cette interface
web)
DarknetConnectionsToadlet.fproxyPort=FProxy: ${port}/TCP (cette interface web)
-DarknetConnectionsToadlet.fullTitle=${counts} amis de ${name}
+DarknetConnectionsToadlet.fullTitle=${counts} Amis (noeuds de confiance) de
${name}
DarknetConnectionsToadlet.go=Ex?cuter
DarknetConnectionsToadlet.idleTime=Depuis combien de temps on est connect? ?
ce noeud, ou quand il a ?t? vu pour la derni?re fois
DarknetConnectionsToadlet.idleTimeTitle=Connect? / en attente
@@ -127,7 +135,7 @@
DarknetConnectionsToadlet.listenOnlyShort=Ecouter seulement
DarknetConnectionsToadlet.listening=Non connect? mais ? l'?coute : le noeud
n'essaie pas de se connecter ? ces noeuds tr?s souvent car le mode rafale est
activ? sur eux.
DarknetConnectionsToadlet.listeningShort=A l'?coute
-DarknetConnectionsToadlet.myFriends=Mes amis
+DarknetConnectionsToadlet.myFriends=Mes Amis
DarknetConnectionsToadlet.myReferenceHeader=${linkref}Ma r?f?rence${/linkref}
(${linktext}en texte brut${/linktext})
DarknetConnectionsToadlet.nameClickToMessage=Le nom du noeud. Cliquez sur son
nom pour lui envoyer un message
DarknetConnectionsToadlet.nameTitle=Nom
@@ -138,6 +146,7 @@
DarknetConnectionsToadlet.nodePortsTitle=Ports utilis?s par le noeud
DarknetConnectionsToadlet.notConnected=Non connect? : Pas de connexion jusqu'?
pr?sent mais ce noeud continue d'essayer.
DarknetConnectionsToadlet.notConnectedShort=D?connect?
+DarknetConnectionsToadlet.opennetFnpPort=Opennet FNP : ${port}/UDP
(communication entre les noeuds ; vous voudrez sans doute ouvrir ce port dans
votre firewall)
DarknetConnectionsToadlet.pasteReference=Copiez/collez sa r?f?rence ici :
DarknetConnectionsToadlet.privateNote=Un commentaire priv? concernant ce noeud
DarknetConnectionsToadlet.privateNoteTitle=Commentaire priv?
@@ -176,11 +185,12 @@
FProxyToadlet.errorIsFatal=Cette erreur est fatale. Il y a peu de chances pour
que le probl?me se r?solve en r?essayant.
FProxyToadlet.errorWithReason=Erreur : ${error}
FProxyToadlet.expectedKeyButGot=Le noeud attendait une cl? Freenet et non pas :
+FProxyToadlet.expectedMimeType=Type MIME attendu : ${mime}
FProxyToadlet.explanationTitle=Explication
FProxyToadlet.fetchLargeFileAnywayAndDisplay=R?cup?rer quand m?me et afficher
le fichier dans le navigateur
FProxyToadlet.fileInformationTitle=Informations sur le fichier
FProxyToadlet.filenameLabel=Nom de fichier :
-FProxyToadlet.friends=G?rer les connexions avec les amis
+FProxyToadlet.friends=G?rer les connexions avec les Amis
FProxyToadlet.friendsTitle=Amis
FProxyToadlet.goBack=Retour
FProxyToadlet.goBackToPrev=Revenir ? la page pr?c?dente
@@ -197,8 +207,11 @@
FProxyToadlet.openForceDisk=${link}Cliquez ici${/link} pour force le
navigateur ? enregistrer le fichier sur le disque.
FProxyToadlet.openPossRSSAsForceDisk=${link}Cliquez ici${/link} pour essayer
de forcer votre navigateur ? enregistrer ce fichier sur le disque (${bold}ceci
peut ?tre dangereux${/bold} si vous utilisez Firefox 2.0.0, les versions
suivantes n'ont pas de probl?me).
FProxyToadlet.openPossRSSAsPlainText=${link}Cliquez ici${/link} pour ouvrir le
fichier en texte brut (cela ${bold}peut ?tre dangereux${/bold} si vous utilisez
Internet Explorer 7.0 ou Firefox 2.0.0).
-FProxyToadlet.openRSSAsRSS=${link}Cliquez ici${/link} pour ouvrir le fichier
en tant que RSS (ceci ${bold}est dangereux${/bold} dans le cas o? l'auteur du
site est malicieux car Freenet n'est pas encore capable de filtrer le RSS).
+FProxyToadlet.openPossRSSForceDisk=${link}Cliquez ici${/link} pour essayer de
forcer votre navigateur ? enregistrer ce fichier sur le disque (${bold}ceci
peut ?tre dangereux${/bold} si vous utilisez Firefox 2.0.0, la version 2.0.1
devrait corriger le probl?me).
+FProxyToadlet.openRSSAsRSS=${link}Cliquez ici${/link} pour ouvrir le fichier
en tant que RSS (ceci <b>est dangereux</b> dans le cas o? l'auteur du site est
malicieux car Freenet n'est pas encore capable de filtrer le RSS).
FProxyToadlet.openRSSForce=${link}Cliquez ici${/link} pour ouvrir le fichier
en tant que ${mime} (ceci ${bold}peut ?tre dangereux${/bold} avec IE7 et FF2).
+FProxyToadlet.opennet=G?rer les connexions aux Inconnus
+FProxyToadlet.opennetTitle=Inconnus
FProxyToadlet.options=Les choix possibles sont :
FProxyToadlet.pathNotFound=Le chemin sp?cifi? n'existe pas.
FProxyToadlet.pathNotFoundTitle=Chemin non trouv?
@@ -266,7 +279,9 @@
FetchException.longError.26=Archive red?marr?e
FetchException.longError.27=Redirection permanente : utilisez la nouvelle URI
FetchException.longError.28=Pas assez de donn?es trouv?es; des donn?es ont ?t?
trouv?es mais la redirection pointe dans le vide
+FetchException.longError.29=Type MIME invalide : La cl? n'?tait pas dans la
liste de types MIME autoris?s par le client
FetchException.longError.3=Ne sait pas quoi faire avec les m?ta-donn?es
+FetchException.longError.30=Cette requ?te a ?t? interrompu car le noeud a
r?cemment re?u une requ?te pour cette cl? et que cette requ?te avait ?chou?.
FetchException.longError.4=L'analyse des m?ta-donn?es a ?chou?
FetchException.longError.5=L'extraction du fichier de l'achive a ?chou?
FetchException.longError.6=Le d?codage d'un bloc a ?chou?
@@ -294,13 +309,55 @@
FetchException.shortError.26=Archive relanc?e
FetchException.shortError.27=Nouvelle URI
FetchException.shortError.28=Aucune donn?e trouv?e
+FetchException.shortError.29=Type MIME invalide
FetchException.shortError.3=M?ta-donn?e inconnue
+FetchException.shortError.30=Donn?e introuvable (?chec r?cent)
FetchException.shortError.4=M?ta-donn?e invalide
FetchException.shortError.5=Echec de l'archive
FetchException.shortError.6=Erreur de d?codage de bloc
FetchException.shortError.7=Trop de niveaux de m?ta-donn?es
FetchException.shortError.8=Trop de red?marrages
FetchException.shortError.9=Trop de r?cursivit?
+FileOffer.acceptTransferButton=Accepter le transfert
+FileOffer.askUserTitle=Transfert de fichier direct
+FileOffer.commentLabel=Commentaire :
+FileOffer.failedReceiveHeader=Le transfert du fichier ${filename} de ${node} a
?chou?.
+FileOffer.failedReceiveTitle=La r?ception a ?chou?
+FileOffer.fileLabel=Fichier :
+FileOffer.mimeLabel=Type MIME :
+FileOffer.offeredFileHeader=Le noeud ${name} vous propose un transfert de
fichier :
+FileOffer.rejectTransferButton=Refuser le transfert
+FileOffer.senderLabel=Exp?diteur :
+FileOffer.sizeLabel=Taille :
+FileOffer.succeededReceiveHeader=Le transfert du fichier ${filename} de
${node} a r?ussi.
+FileOffer.succeededReceiveTitle=Fichier re?u
+FirstTimeWizardToadlet.bandwidthLimit=Limites de bande passante
+FirstTimeWizardToadlet.bandwidthLimitLong=Veuillez choisir le type et la
vitesse de votre connexion dans la liste ci-dessous.
+FirstTimeWizardToadlet.chooseNodeName=Vous devez choisir un nom !
+FirstTimeWizardToadlet.chooseNodeNameLong=Veuillez choisir un nom pour votre
noeud. Ce nom ne sera visible que des noeuds auxquels vous vous connecterez.
Nous recommandons de mettre un nom ou un pseudo IRC, ?ventuellement des
informations permettant de vous contacter en cas de probl?me ("Thomas Durand
<tom93 at hotmail.com>).
+FirstTimeWizardToadlet.congratz=Bienvenue ? bord !
+FirstTimeWizardToadlet.congratzLong=F?licitations, la configuration de votre
noeud est termin?e. Vous pouvez modifier cette configuration ? tout moment en
cliquant sur le lien "Configuration" dans le menu de gauche. Bienvenue sur
Freenet.
+FirstTimeWizardToadlet.connectToStrangers=Se connecter aux Inconnus ?
+FirstTimeWizardToadlet.connectToStrangersLong=Si vous laissez votre noeud se
connecter aux Inconnus, vous serez moins en s?curit?, n'importe qui pourra
savoir que vous utilisez Freenet et tous les vilains pouront se connecter ?
votre noeud. Si vous ne le faites pas, vous devrez vous connecter manuellement
? au moins trois Amis (des gens que vous connaissez d?ja) qui utilisent Freenet.
+FirstTimeWizardToadlet.continue=Continuer
+FirstTimeWizardToadlet.datastoreSize=Taille du store
+FirstTimeWizardToadlet.datastoreSizeLong=Veuillez chosir une taille pour votre
datastore. Le datastore sert ? stocker les donn?es du r?seau. Plus vous stockez
de donn?es, plus vous aidez la communaut? et plus votre noeud sera rapide.
+FirstTimeWizardToadlet.enableOpennet=Se connecter automatiquement aux noeuds
Inconnus ?
+FirstTimeWizardToadlet.homepageTitle=Assistant premiers pas sur Freenet !
+FirstTimeWizardToadlet.iDoTrust=Faire confiance aux personnes connect?s par
${interface} (${ip}) ?
+FirstTimeWizardToadlet.isNetworkTrusted=Faire confiance au r?seau local ?
+FirstTimeWizardToadlet.isNetworkTrustedLong=Faire confiance au r?seau local ?
Si vous r?pondez oui, tous les services de notre noeud seront accessibles
depuis ce r?seau. Vous pourrez contr?ler pr?cisemment les droits d'acc?s depuis
la page de configuration.
+FirstTimeWizardToadlet.noNetworkIF=Pas de carte r?seau suppl?mentaire trouv?e
+FirstTimeWizardToadlet.noNetworkIFLong=Freenet n'a pas trouv? d'autre carte
r?seau. Il consid?rera que vous vous y connectez seulement depuis votre
ordinateur.
+FirstTimeWizardToadlet.skipWizard=Je ne suis pas un d?butant, passer
l'assistant !
+FirstTimeWizardToadlet.step1Title=Assistant premiers pas sur Freenet ! -
Choisissez le nom de votre noeud
+FirstTimeWizardToadlet.step2Title=Assistant premiers pas sur Freenet ! -
Limites de bande-passante
+FirstTimeWizardToadlet.step3Title=Assistant premiers pas sur Freenet ! -
Taille du store
+FirstTimeWizardToadlet.step4Title=Assistant premiers pas sur Freenet ! -
Configuration r?seau
+FirstTimeWizardToadlet.step5Title=Assistant premiers pas sur Freenet ! -
F?licitations, votre noeud est configur?
+FirstTimeWizardToadlet.step6Title=Assistant premiers pas sur Freenet ! -
F?licitations, votre noeud est configur?.
+FirstTimeWizardToadlet.welcomeInfoboxContent1=Bienvenue dans l'assistant
premiers pas sur Freenet . Cet outil vous permettra de configurer rapidement et
facilement votre noeud. Veuillez
+FirstTimeWizardToadlet.welcomeInfoboxTitle=Bienvenue sur l'assistant premiers
pas sur Freenet !
GIFFilter.invalidHeader=Ce fichier ne contient pas d'en-t?te GIF valide.
GIFFilter.invalidHeaderTitle=En-t?te invalide
GIFFilter.notGif=Ce fichier n'est pas un GIF. Il peut s'agir de n'importe quoi
et votre navigateur risque de faire n'importe quoi avec. Nous l'avons donc
bloqu?.
@@ -343,6 +400,7 @@
InsertException.longError.1=L'appelant a fourni une URI inutilisable "
InsertException.longError.10=Annul? par l'utilisateur
InsertException.longError.11=Cha?ne en trop (surement un '/') utilis?e dans
l'URI
+InsertException.longError.12=Erreur de format binaire
InsertException.longError.2=Erreur interne : disque plein ou probl?me de
permissions ?
InsertException.longError.3=Erreur interne
InsertException.longError.4=Un noeud sur le trajet retour ne r?pond pas ou est
surcharg?
@@ -354,6 +412,7 @@
InsertException.shortError.1=URI invalide
InsertException.shortError.10=Annul?
InsertException.shortError.11=La cl? contient une cha?ne en trop
+InsertException.shortError.12=Erreur de format binaire
InsertException.shortError.2=Erreur de fichiers temporaires
InsertException.shortError.3=Erreur interne
InsertException.shortError.4=D?lai d?pass? ou surcharge
@@ -405,7 +464,7 @@
LogConfigHandler.rotationIntervalLong=Intervalle de rotation des journaux. Les
deux derniers journaux (l'actuel et le pr?c?dent) sont conserv?s, on conserve
?galement maxZippedLogsSize journaux pr?c?dents, compress?s.
LoggerHook.unrecognizedPriority=Nom de priorit? non reconnu : ${name}.
LongOption.parseError=La valeur entr?e ne peut ?tre utilis?e comme un entier
sur 64 bits : ${val}
-MeaningfulNodeNameUserAlert.noNodeNick=Il semble que votre noeud n'ait pas de
nom. Mettre une adresse mail ou un surnom IRC est g?n?ralement une bonne ?a
aidera vos amis ? identifier votre node (le nom n'est affich? qu'aux amis, pas
aux noeuds connect?s par l'opennet).
+MeaningfulNodeNameUserAlert.noNodeNick=Il semble que votre noeud n'ait pas de
nom. Mettre une adresse mail ou un surnom IRC est g?n?ralement une bonne id?e,
?a aidera vos Amis ? identifier votre noeud (ce nom n'est affich? qu'aux Amis,
pas aux Inconnus connect?s par l'Opennet).
MeaningfulNodeNameUserAlert.noNodeNickTitle=Votre noeud n'a pas de nom.
N2NTMToadlet.composingMessageLabel=Message inter-noeud envoy? aux noeuds
suivants :
N2NTMToadlet.delayed=Repouss? : Le message sera envoy? prochainement
@@ -413,13 +472,14 @@
N2NTMToadlet.failed=Message non envoy? : ce noeud n'est pas connect?
N2NTMToadlet.failedTitle=Echou?
N2NTMToadlet.friends=Amis
+N2NTMToadlet.noSuchFileOrCannotRead=L'envoi du fichier a ?chou? : soit il
n'existe pas, soit il est illisible.
N2NTMToadlet.peerName=Nom du noeud
N2NTMToadlet.peerNotFoundTitle=Noeud introuvable
N2NTMToadlet.peerNotFoundWithHash=Le noeud ayant pour hash \u201c${hash}\u201d
est introuvable.
N2NTMToadlet.processingSend=Envoi du message inter-noeud en cours
N2NTMToadlet.queued=En attente : Ce pair n'est pas connect?, le message est en
attente jusqu'? ce qu'il se connecte
N2NTMToadlet.queuedTitle=En attente
-N2NTMToadlet.returnToFriends=Retour ? la liste des amis
+N2NTMToadlet.returnToFriends=Retour ? la liste des Amis
N2NTMToadlet.sendMessage=Envoyer le message inter-noeud
N2NTMToadlet.sendMessageShort=Envoyer le message
N2NTMToadlet.sendStatus=Etat de l'envoi de message inter-noeud
@@ -431,6 +491,8 @@
N2NTMUserAlert.header=De : ${from} (r?dig? ${composed} | envoy? ${sent} | re?u
${received})
N2NTMUserAlert.reply=R?pondre
N2NTMUserAlert.title=Message inter-noeud ${number} de ${peername} (${peer})
+Node.alwaysAllowLocalAddresses=Se connecter aux adresses locales ?
+Node.alwaysAllowLocalAddressesLong=Si activ?, le noeud essaiera de se
connecter aux autres en utilisant leur adresse locale (localhost, LAN) en plus
de leur adresse publique. Si vous ne l'activez pas, vous pourrez quand m?me
l'activer pour certains de vos Amis (mais pas les Inconnus). Activez ceci si
vous voulez vous connecter ? des noeuds pr?sents sur votre r?seau local, en
sachant que des r?f?rences bugg?es peuvent vous amener ? envoyer des paquets
UDP ? des machines de votre r?seau local.
Node.bandwidthLimitMustBePositiveOrMinusOne=La limite de bande passante doit
?tre un entier positif ou ?gal ? -1
Node.bindTo=Adresse IP o? ?couter
Node.bindToLong=Adresse IP o? ?couter
@@ -464,9 +526,15 @@
Node.nodeDir=Dossier du noeud
Node.nodeDirLong=Dossier o? placer la liste des noeuds
Node.nodeName=Nom de ce noeud freenet
-Node.nodeNameLong=Nom du noeud. Seuls vos amis pourront le voir.
+Node.nodeNameLong=Nom du noeud. Seuls les noeuds Amis pourront le voir.
+Node.oneConnectionPerIP=N'autoriser qu'une seule connexion par adresse IP ?
+Node.oneConnectionPerIPLong=Ne pas autoriser plus d'une connexion par adresse
IP ? Cela rendra les choses un peu plus difficile pour un attaquant qui
essaierait de se connecter plusieurs fois ? vous sous des identiti?s
diff?rentes, dans le but de nuire ? votre anonymat. Cela ?vite ?galement d'?tre
connect? en m?me temps par le darknet et par l'opennet ? un m?me noeud.
+Node.opennetEnabled=Activer l'Opennet ?
+Node.opennetEnabledLong=Activer l'Opennet ? Si vous faites cela, votre noeud
?changera automatiquement ses r?f?rences avec les autres noeuds. Cela implique
que tout le monde peut savoir que vous poss?dez un noeud Freenet et que
certaines attaques sont plus faciles. Si vous connaissez suffisamment de
personnes utilisant Freenet, vous devriez rester en Darknet.
Node.outBWLimit=Limite d'upload (octet/seconde)
Node.outBWLimitLong=Limite d'upload (octet/seconde); le noeud ne devrait
jamais la d?passer
+Node.passOpennetPeersThroughDarknet=Relayer les r?f?rences opennet ? travers
les connexions darknet ?
+Node.passOpennetPeersThroughDarknetLong=Si activ?, les r?f?rences opennet
(JAMAIS votre r?f?rence darknet) seront relay?es ? travers nos Amis (connexions
darknet). Cela permet ? un noeud (le votre ou celui de vos Amis) d'obtenir des
connexions opennet ? partir de ses connexions darknet. C'est utile car cela
nous permet de retrouver de nouvelles connexions opennet quand on les a toutes
perdues suite ? un arr?t prolong? du noeud. Cependant, cela rend l'analyse de
traffic l?g?rement plus facile ; d?sactivez-le si vous ?tes parano.
Node.port=Num?ro de port FNP (UDP)
Node.portLong=Port UDP des communications inter-noeuds (Freenet Node Protocol)
Node.storeDirectory=Dossier du store
@@ -491,6 +559,9 @@
NodeClientCore.ignoreTooManyPathComponentsLong=Si activ?, le noeud ne g?n?rera
plus d'erreurs TOO_MANY_PATH_COMPONENTS quand on lui soumet une URL avec trop
de noms de dossiers ? la fin (/bla/bla/), inutiles pour r?cup?rer la cl? (par
exemple, les anciennes CHK avaient souvent des noms de fichiers coll?es ? la
fin qui ne faisaient pas partie de l'insertion originale ; ?a ne sert plus ?
rien car on peut ajouter le nom de fichier maintenant). N'activez ceci que si
vous en avez besoin pour utiliser de vieilles applications ; cette option sera
retir?e bient?t.
NodeClientCore.lazyResume=Terminer le chargement des requ?tes persistantes
apr?s le d?marrage ? (Utilise plus de m?moire)
NodeClientCore.lazyResumeLong=Le noeud peut charger les requ?tes persistantes
en attente pendant le d?marrage, ou il peut lire les infos en m?moire et
relancer les requ?tes apr?s le d?marrage. Le d?marrage est plus rapide mais
cela consomme plus de m?moire.
+NodeClientCore.maxUSKFetchers=Nombre maximum de r?cup?rateurs d'USK
+NodeClientCore.maxUSKFetchersLong=Nombre maximum de r?cup?rateurs d'USK
+NodeClientCore.maxUSKFetchersMustBeGreaterThanZero=Doit ?tre sup?rieur ? z?ro
NodeClientCore.movingTempDirOnTheFlyNotSupported=D?placer le dossier
temporaire ? la vol?e n'est pas possible pour le moment
NodeClientCore.persistentTempDir=Dossier pour les fichiers temporaires
persistants
NodeClientCore.persistentTempDirLong=Dossier o? placer les fichiers
temporaires persistants
@@ -538,31 +609,46 @@
NodeUpdateManager.updateFailedTitle=Mise ? jour ?chou?e !
NodeUpdateManager.updateURI=O? le noeud doit-il chercher ses mises ? jour ?
NodeUpdateManager.updateURILong=O? le noeud doit il rechercher ses mises ?
jour ?
+OpennetConnectionsToadlet.fullTitle=${counts} Inconnus connect?s ? ${name}
+OpennetConnectionsToadlet.peersListTitle=Mes noeuds Opennet (Inconnus ajout?s
par mon noeud)
+OpennetUserAlert.warning=Votre noeud fonctionne en mode Opennet. Il se
connecte ? des Inconnus et cela veut dire que n'importe qui peut savoir que
vous utilisez Freenet. Il est plus facile de vous attaquer ou de vous bloquer
(au niveau d'un firewall national) et vous ne controlez pas ? qui votre noeud
se connecte. Nous vous recommandons de vous connecter ? des Amis (noeuds de
confiance appartenant ? des gens que vous connaissez d?j?) ; l'Opennet est
cens? n'?tre qu'une mesure transitoire en attendant de pouvoir vous connecter ?
vos Amis. Si vous ne vous connectez qu'? des Amis, et bien qu'il leur soit
possible de vous attaquer, c'est moins risqu? que si vous vous connectez ?
n'importe quel vilain appartenant ? une organisation gouvernementale ou pire.
Notez qu'ajouter un noeud ? votre liste d'Amis n'est utile (pour le routage et
la s?curit?) que s'il appartient ? quelqu'un que vous connaissez vraiment !
+OpennetUserAlert.warningTitle=Attention : Opennet activ?, votre noeud va se
connecter ? des Inconnus
PNGFilter.invalidHeader=Ce fichier n'est pas une image PNG. Il ne contient pas
d'en-t?te PNG valide. Il peut s'agir de n'importe quoi et votre navigateur
risque de faire quelque chose de dangereux avec. Nous l'avons donc bloqu?.
PNGFilter.invalidHeaderTitle=Ceci n'est pas une image PNG - en-t?te invalide
-PeerManagerUserAlert.noConns=Ce noeud ne peut pas fonctionner normalement car
il n'est pas parvenu ? se connecter ? un seul autre noeud jusqu'ici. Esp?rons
que certains de vos amis se connecteront bient?t. Sinon, essayez de vous
connecter ? d'autre noeuds. Il vous faut toujours 3 noeuds connect?s et vous
devriez essayer d'en avoir 5 ? 10.
+PeerManagerUserAlert.clockProblem=${count} noeuds ne peuvent pas se connecter
? vous car leur horloge et la votre sont d?call?es de plus de 24 heures.
Veuillez vous assurer que votre ordinateur est ? l'heure. Une heure erron?e
g?ne le fonctionnement du noeud et des clients.
+PeerManagerUserAlert.clockProblemTitle=Probl?me d'horloge
+PeerManagerUserAlert.connError=${count} noeud ne peuvent pas se connecter pour
une raison inconnue, peut-?tre parce que votre noeud est bugg? ou votre
r?f?rence corrompue.
+PeerManagerUserAlert.connErrorTitle=Impossible de se connecter ? certains
noeuds
+PeerManagerUserAlert.noConns=Ce noeud ne peut pas fonctionner normalement car
il n'est pas parvenu ? se connecter ? un seul autre noeud jusqu'ici. Esp?rons
que certains de vos Amis se connecteront bient?t. Sinon, essayez de vous
connecter ? d'autre noeuds. Il vous faut toujours 3 noeuds connect?s et vous
devriez essayer d'en avoir 5 ? 10.
PeerManagerUserAlert.noConnsTitle=Pas de connection ouverte
PeerManagerUserAlert.noPeersDarknet=Ce noeud ne peut pas encore fonctionner
car il n'est connect? ? aucun autre. Id?alement, vous devriez vous connecter ?
des noeuds appartenant ? des gens que vous connaissez (et en qui vous avez
confiance, si vous ?tes parano. Sinon, au moins des gens ? qui vous avez d?ja
parl?). Il vous faut au moins 3 noeuds connect?s ? tous moment, et id?alement
entre 5 et 10. Vous pourriez vous connecter ? irc.freenode.net, canal
#freenet-refs pour demander si quelqu'un veut se connecter ? vous, mais
rappelez-vous que vous ?tes vuln?rable ? ceux ? qui vous ?tes connect?s (C'est
particuli?rement vrai alors que Freenet 0.7 est tout jeune...). ASSUREZ-VOUS
QUE L'AUTRE PERSONNE AJOUTE, ELLE AUSSI, VOTRE REFERENCE. LES CONNEXIONS A SENS
UNIQUE NE FONCTIONNENT PAS.
PeerManagerUserAlert.noPeersTestnet=Ce noeud ne peut pas encore fonctionner
car il n'est connect? ? aucun autre. Id?alement, vous devriez vous connecter ?
des noeuds appartenant ? des gens que vous connaissez (et en qui vous avez
confiance, si vous ?tes parano. Sinon, au moins des gens ? qui vous avez d?ja
parl?). Il vous faut au moins 3 noeuds connect?s ? tous moment, et id?alement
entre 5 et 10. Mais comme il s'agit d'un noeud de test, nous vous sugg?rons de
vous connecter ? irc.freenode.net, canal #freenet-refs pour demander si
quelqu'un veut se connecter ? vous.
PeerManagerUserAlert.noPeersTitle=Aucun ami trouv?
PeerManagerUserAlert.oneConn=Ce noeud n'a qu'une seule connexion. Les
performances vont s'en ressentir et vous n'aurez aucun anonymat ou moyen de
nier si cette personne vous espionne. Votre noeud est attach? au r?seau comme
une "feuille" et ne contribue pas ? la sant? du r?seau. Essayez d'avoir au
moins 3 (id?alement entre 5 et 10) noeuds connect?s ? tout moment.
PeerManagerUserAlert.onlyFewConnsTitle=Seulement ${count} connexion(s)
ouverte(s)
-PeerManagerUserAlert.tooHighBwlimitDelayTime=Le noeud est oblig? d'attendre
trop longtemps avant de pouvoir communiquer (${delay}ms > ${max}ms). Augmentez
la limite d'upload et/ou retirez des amis pour am?liorer la situation.
+PeerManagerUserAlert.tooHighBwlimitDelayTime=Le noeud est oblig? d'attendre
trop longtemps avant de pouvoir communiquer (${delay}ms > ${max}ms). Augmentez
la limite d'upload et/ou retirez des connexions pour am?liorer la situation.
PeerManagerUserAlert.tooHighBwlimitDelayTimeTitle=bwlimitDelayTime trop ?lec?
-PeerManagerUserAlert.tooHighPingTime=Ce noeud a du mal ? communiquer avec les
autres assez rapidement (${ping}ms > ${max}ms). Augmentez la limite d'upload
et/ou supprimez des amis pour am?liorer la situation.
+PeerManagerUserAlert.tooHighPingTime=Ce noeud a du mal ? communiquer avec les
autres assez rapidement (${ping}ms > ${max}ms). Augmentez la limite d'upload
et/ou supprimez des connexions pour am?liorer la situation.
PeerManagerUserAlert.tooHighPingTimeTitle=Ping moyen trop ?lev?
PeerManagerUserAlert.tooManyConns=Ce noeud a trop de connexions (${count} >
${max}). Ajouter plein de noeuds automatiquement viole la th?orie du "petit
monde", nuit au routage et risque de produire des "points individuels de
d?faillance".
PeerManagerUserAlert.tooManyConnsTitle=Trop de connexions ouvertes
-PeerManagerUserAlert.tooManyDisconnected=Ce noeud a trop d'amis d?connect?s
(${count} > ${max}). Cela a une impact sensible sur les performances car les
amis d?connect?s consomment un peu de m?moire et de processeur. Vous devriez
peut-?tre "nettoyer" votre liste d'amis. Id?alement, vous ne devriez vous
connecter qu'? des gens que vous connaissez. M?me si vous ne le faites pas,
ajouter automatiquement des tas de noeuds est mauvais car cela nuit au
fonctionnement du r?seau.
+PeerManagerUserAlert.tooManyDisconnected=Ce noeud a trop de noeuds d?connect?s
(${count} > ${max}). Cela a un impact sensible sur les performances car les
noeuds d?connect?s consomment un peu de m?moire et de processeur. Vous devriez
peut-?tre "nettoyer" votre liste d'Amis. Id?alement, vous ne devriez vous
connecter qu'? des gens que vous connaissez. M?me si vous ne le faites pas,
ajouter automatiquement des tas de noeuds est mauvais car cela nuit au
fonctionnement du r?seau.
PeerManagerUserAlert.tooManyDisconnectedTitle=Trop de noeuds d?connect?s
PeerManagerUserAlert.tooManyNeverConnected=De nombreux noeuds ne se sont
jamais connect?s: ${count}. Vous ne devriez ajouter des noeuds que s'ils ont
?galement ajout? votre r?f?rence. Ils ne se connecteront pas sinon.
PeerManagerUserAlert.tooManyNeverConnectedTitle=De nombreux noeuds ne se sont
pas encore connect?s
-PeerManagerUserAlert.tooManyNeverConnectedWithLink=Beaucoup de vos amis ne se
sont m?me jamais connet?s : ${count}. Vous ne devriez ajouter des amis que si
vous savez qu'ils ont ?galement ajout? ${link}votre r?f?rence${/link}. Sinon,
ils ne se connecteront pas.
-PeerManagerUserAlert.tooManyPeers=Ce noeud a trop d'amis (${count} > ${max}).
Il n'est pas recommand? de faire fonctionner un "super-noeud" avec ajout d'amis
automatiques ; cela ne produit pas une topologie de type "petit monde". Cela va
?galement impacter les performances car les noeuds non connect?s consomment de
la bande passante et du CPU. Vous devriez "nettoyer" votre liste d'amis.
-PeerManagerUserAlert.tooManyPeersTitle=Trop d'amis
-PeerManagerUserAlert.tooOldNeverConnectedPeers=Un ou plusieurs noeuds amis ne
se sont pas connect?s dans les deux semaines suivant leur ajout. Vous devriez
les supprimer car ils affectent l?g?rement les performances (votre noeud g?che
des paquets en essayant de parler ? des noeuds qui ne sont pas l?).
+PeerManagerUserAlert.tooManyNeverConnectedWithLink=Beaucoup de vos Amis ne se
sont m?me jamais connect?s : ${count}. Vous ne devriez ajouter des Amis que si
vous savez qu'ils ont ?galement ajout? ${link}votre r?f?rence${/link}. Sinon,
ils ne se connecteront pas.
+PeerManagerUserAlert.tooManyPeers=Ce noeud a trop d'Amis (${count} > ${max}).
Il n'est pas recommand? de faire fonctionner un "super-noeud" avec ajout d'Amis
automatiques ; cela ne produit pas une topologie de type "petit monde". Cela va
?galement impacter les performances car les noeuds non connect?s consomment de
la bande passante et du CPU. Vous devriez "nettoyer" votre liste d'Amis.
+PeerManagerUserAlert.tooManyPeersTitle=Trop de noeuds connect?s
+PeerManagerUserAlert.tooOldNeverConnectedPeers=Un ou plusieurs noeuds Amis ne
se sont pas connect?s dans les deux semaines suivant leur ajout. Vous devriez
les supprimer car ils affectent l?g?rement les performances (votre noeud g?che
des paquets en essayant de parler ? des noeuds qui ne sont pas l?).
PeerManagerUserAlert.tooOldNeverConnectedPeersTitle=Noeuds jamais connect?s
depuis trop longtemps
PeerManagerUserAlert.twoConns=Ce noeud n'a que deux connexions. Les
performances et la s?curit? ne seront pas tr?s bons et votre noeud ne fait
aucun routage pour les autres. Votre noeud se comporte comme un "lien" dans le
r?seau et ne contribue pas (beaucoup) ? la sant? du r?seau. Essayez d'avoir au
moins 3 (id?alement entre 5 et 10) noeuds connect?s ? tout moment.
+PeersSayKeyBlownAlert.connectedSayBlownLabel=Ces noeuds disent que la cl? a
?t? compromise (nous essayons de r?cup?rer le certificat de r?vocation) :
+PeersSayKeyBlownAlert.disconnectedSayBlownLabel=Ces noeuds nous ont dit qua la
cl? ?tait compromise mais sont d?connect?s depuis. Impossible de r?cup?rer le
certificat de r?vocation :
+PeersSayKeyBlownAlert.failedFetch=Votre noeud n'est pas parvenu ? t?l?charger
le certificat de r?vocation. Cela peut venir d'une attaque contre vous visant ?
vous faire installer une mise ? jour frauduleuse, ou alors que votre noeud ment
? propos de la validit? de la cl?. Veuillez contacter un d?veloppeur ou un
autre utilisateur de Freenet afin de tirer les choses au clair.
+PeersSayKeyBlownAlert.failedTransferSayBlownLabel=Ces noeuds pr?tendent que la
cl? est compromise mais sont incapables de pr?senter le certificat de
r?vocation :
+PeersSayKeyBlownAlert.fetching=Votre noeud essaie de r?cup?rer le certificat
de r?vocation pour avoir plus de d?tails.
+PeersSayKeyBlownAlert.intro=Au moins un des noeuds auxquels vous ?tes connect?
affirme que la cl? de mise ? jour est compromise ! Cela signifie qu'il est
possible qu'un attaquant connaisse la cl? du syst?me de mise ? jour automatique
et l'utilise pour essayer de vous pirater (si vous acceptez la mise ? jour) !
Le syst?me de mise ? jour automatique a ?t? d?sactiv?. Il est aussi possible
que ces noeuds mentent d?lib?r?ment.
+PeersSayKeyBlownAlert.titleWithCount=${count} noeud(s) affirme(nt) que la cl?
de mise ? jour automatique est compromise !
PluginManager.cannotSetOnceLoaded=Impossible de d?finir la liste des plugins
une fois d?marr?
PluginManager.loadedOnStartup=Plugins ? charger au d?marrage
PluginManager.loadedOnStartupLong=Classpath, nom et emplacement des plugins ?
charger au d?marrage du node
@@ -657,6 +743,7 @@
QueueToadlet.persistence=Persistance
QueueToadlet.persistenceForever=toujours
QueueToadlet.persistenceNone=aucune
+QueueToadlet.persistenceReboot=Red?marrer
QueueToadlet.persistenceRebootr=Red?marrer
QueueToadlet.pleaseEnableFCP=Vous devez activer les serveur FCP pour acc?der ?
cette page
QueueToadlet.priority=Priorit?
@@ -671,6 +758,7 @@
QueueToadlet.progressbarAccurate=Cette valeur est pr?cise
QueueToadlet.progressbarNotAccurate=Cette valeur risque de changer car le
traitement du fichier n'est pas termin?e
QueueToadlet.reason=Raison
+QueueToadlet.remove=Supprimer
QueueToadlet.requestNavigation=Parcours des requ?tes
QueueToadlet.restart=Red?marrer
QueueToadlet.size=Taille
@@ -704,6 +792,8 @@
SimpleToadletServer.cssOverrideCantRead=Le fichier CSS personnalis? est
introuvable : ${filename}
SimpleToadletServer.cssOverrideLong=Ce param?tre vous permet d'utiliser un CSS
personnalis?. ATTENTION : les CSS peuvent ?tre dangereux et ne sont pas filtr?s
! Utilisez-le ? vos risques et p?rils. (vous devriez contacter devl at
freenetproject pour qu'il soit inclus dans la distribution principale ;) )
SimpleToadletServer.cssOverrideNotInUploads=Vous de pouvez pas configurer ce
param?tre : "${filename} n'est pas un r?pertoire d'o? l'upload est autoris? !
+SimpleToadletServer.doRobots=Exclure les robots dans robots.txt ?
+SimpleToadletServer.doRobotsLong=Pr?senter un fichier robots.txt disant ?
Google, aux spiders et ? wget d'aller voir ailleurs
SimpleToadletServer.enableJS=Autoriser FProxy ? utiliser du Javascript ?
SimpleToadletServer.enableJSLong=FProxy doit-il utiliser le Javascript ou non.
Ce param?tre devrait ?tre sur faux dans la plupart des cas. Les freesites ne
pourront pas utiliser de Javascript, m?me si ceci est activ?.
SimpleToadletServer.enabled=Activer FProxy ?
@@ -734,7 +824,7 @@
StatisticsToadlet.osVersion=Version de l'OS : ${version}
StatisticsToadlet.outputRate=Envoi : ${rate}/seconde (sur ${max}/seconde)
StatisticsToadlet.payloadOutput=Envoi utile : ${total} (${rate}/seconde)
(${percent}%)
-StatisticsToadlet.peerStatsTitle=Statistiques des amis
+StatisticsToadlet.peerStatsTitle=Statistiques des noeuds
StatisticsToadlet.threadDumpButton=G?n?rer un dump de processus
StatisticsToadlet.threads=Processus en cours : ${running}/${max}
StatisticsToadlet.totalInput=Total re?u : ${total} (${rate}/seconde)
@@ -759,18 +849,24 @@
TextModeClientInterfaceServer.enabledLong=Activer le serveur TMCI (interface
en ligne de commande) ou non
TextModeClientInterfaceServer.telnetPortNumber=Port telnet
TextModeClientInterfaceServer.telnetPortNumberLong=Num?ro de port telnet
+TimeSkewDetectedUserAlert.text=Un d?callage horaire a ?t? d?tect? par votre
noeud. C'est TRES mauvais. Votre noeud ne fonctionnera pas correctement tant
que ce ne sera pas corrig?. Les causes habituelles sont une mauvaise
configuration de la mise en veille, du client de synchronisation horaire ou un
probl?me mat?riel.
+TimeSkewDetectedUserAlert.title=D?callage horaire d?tect? !
Toadlet.cancel=Annuler
Toadlet.clickHere=Cliquez ici
+Toadlet.homepage=Page d'accueil
Toadlet.internalErrorPleaseReport=Erreur interne : merci de pr?venir les
d?veloppeurs
Toadlet.internalErrorTitle=Erreur interne
+Toadlet.no=Non
Toadlet.nodeHomepage=Page d'accueil
Toadlet.notSupportedTitle=Non support?
Toadlet.notSupportedWithClass=Votre navigateur a envoy? une requ?te que
Freenet (${class}) ne comprend pas.
+Toadlet.ok=Ok
Toadlet.permRedirectWithReason=Redirection permanente : ${reason}
Toadlet.returnToNodeHomepage=Revenir ? la page d'accueil
Toadlet.returnToPrevPage=Retour ? la page pr?c?dente
Toadlet.tempRedirectWithReason=Redirection temporaire : ${reason}
Toadlet.unauthorized=Vous n'?tes pas autoris? ? acc?der ? cette page.
+Toadlet.yes=Oui
ToadletContextImpl.cannotParseContentLength=Erreur de content-length : ${error}
ToadletContextImpl.headersLineTooLong=L'analyse des en-t?tes a rencontr? une
ligne trop longue
ToadletContextImpl.methodNotAllowed=La m?thode HTTP n'est pas autoris?e
@@ -861,6 +957,7 @@
WelcomeToadlet.insertSucceededTitle=Insertion r?ussie
WelcomeToadlet.insertedTitle=Insertion
WelcomeToadlet.keyInsertedSuccessfullyWithKeyAndName=La cl?
${link}${name}${/link} a ?t? ins?r?e avec succ?s.
+WelcomeToadlet.keyRequestLabel=Cl? :
WelcomeToadlet.messageHeader=Message
WelcomeToadlet.nodeUpdateConfirm=Etes-vous s?r de vouloir mettre ? jour votre
noeud Freenet ?
WelcomeToadlet.nodeUpdateConfirmTitle=Confirmation de mise ? jour
Modified: branches/freenet-jfk/src/freenet/l10n/freenet.l10n.it.properties
===================================================================
--- branches/freenet-jfk/src/freenet/l10n/freenet.l10n.it.properties
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/l10n/freenet.l10n.it.properties
2007-08-21 20:26:59 UTC (rev 14828)
@@ -22,6 +22,7 @@
BookmarkEditorToadlet.editBookmarkTitle=Modifica
BookmarkEditorToadlet.editCategoryTitle=Modifica Categoria
BookmarkEditorToadlet.error=Errore
+BookmarkEditorToadlet.invalidKey=La chiave Freenet non ? valida.
BookmarkEditorToadlet.invalidKeyTitle=Chiave non valida
BookmarkEditorToadlet.invalidKeyWithReason=Chiave Freenet non valida.
BookmarkEditorToadlet.keyLabel=Chiave :
@@ -34,6 +35,7 @@
BookmarkEditorToadlet.pasteTitle=Taglia/Incolla
BookmarkEditorToadlet.save=Salva
BookmarkEditorToadlet.title=Modifica Preferiti
+BookmarkEditorToadlet.urlDecodeError=URL Decode Error
BookmarkItem.bookmarkUpdated=Il sito ${name} ? stato aggiornato all'edizione
${edition}.
BookmarkItem.bookmarkUpdatedTitle=${name}: link aggiornato
BookmarkItem.bookmarkUpdatedWithLink=Il Sito ${link}${name}${/link} ? stato
aggiornato all'edizione ${edition}.
@@ -58,6 +60,7 @@
ConfigToadlet.appliedTitle=Configurazione Applicata
ConfigToadlet.apply=Conferma
ConfigToadlet.configNavTitle=Esplora Configurazione
+ConfigToadlet.contributeTranslation=Contribuisci alla traduzione
ConfigToadlet.defaultIs=Il valore predefinito per l'opzione di configurazione
?: '${default}'.
ConfigToadlet.fullTitle=Configurazione del Nodo Freenet di ${name}
ConfigToadlet.homepage=Homepage del Nodo
@@ -105,11 +108,16 @@
DarknetConnectionsToadlet.cantFetchNoderefURL=Non ? stato possibile richiamare
la referenza di un nodo da ${url}. Riprovare.
DarknetConnectionsToadlet.cantParseTryAgain=L'analisi del testo non ha
prodotto la referenza di un nodo: Riprovare.
DarknetConnectionsToadlet.cantParseWrongEnding=Non ? stato possibile
analizzare le referenza: L'ultimo rigo dovrebbe contenere solo la parola End,
esso contiene invece: ${end}
+DarknetConnectionsToadlet.clockProblem=Il tuo orologio e l'orologio del nodo
differiscono di oltre 24 ore. La connessione ? stata diabilitata perch? questo
pu? causare problami con l'aggiornamento ed i client.
+DarknetConnectionsToadlet.clockProblemShort=Problema relativo all' orologio
DarknetConnectionsToadlet.confirmRemoveNode=Si ? certi di voler rimuovere
"+peerNodes[i].getName()+" ? Rimuovere un nodo che ? stato disconnesso per meno
di una settimana non consigliabile; meglio sarebbe attendere ancora un po',
considerando che potrebbe trattarsi di un problema temporaneo, e che ci sono
utenti che non hanno la possibilit? lasciar girare il proprio nodo giorno e
notte.
DarknetConnectionsToadlet.confirmRemoveNodeTitle=Conferma
DarknetConnectionsToadlet.confirmRemoveNodeWarningTitle=Rimozione Nodo
+DarknetConnectionsToadlet.connError=Connessione fallita (il nodo ha un 'bug'?)
+DarknetConnectionsToadlet.connErrorShort=Errore di Connessione
DarknetConnectionsToadlet.connected=Connesso: Il nodo ? connesso a questi peer:
DarknetConnectionsToadlet.connectedShort=Connessi
+DarknetConnectionsToadlet.darknetFnpPort=Darknet FNP: ${port}/UDP (da nodo a
nodo; questa ? la porta che potrebbe essere necessario forwardare su router)
DarknetConnectionsToadlet.disabled=Non connesso e disabilitato: L'utente ha
configurato il nodo in maniera da non connettersi a questo peer.
DarknetConnectionsToadlet.disabledShort=Disabilitato
DarknetConnectionsToadlet.enterDescription=Descrizione:
@@ -149,6 +157,7 @@
DarknetConnectionsToadlet.nodePortsTitle=Porte utilizzate dal nodo
DarknetConnectionsToadlet.notConnected=Non connesso: Finora non ci sono state
connessioni ma il nodo cerca continuamente di connettersi
DarknetConnectionsToadlet.notConnectedShort=Disconnessi
+DarknetConnectionsToadlet.opennetFnpPort=Opennet FNP: ${port}/UDP (da nodo a
nodo; potrebbe essere necessario forwardare questa porta su router)
DarknetConnectionsToadlet.pasteReference=Incolla la referenza qui:
DarknetConnectionsToadlet.privateNote=Nota privata relativa a questo nodo:
DarknetConnectionsToadlet.privateNoteTitle=Nota Privata
@@ -189,6 +198,7 @@
FProxyToadlet.errorIsFatal=Questo ? un errore grave (fatal error). Riprovare
probabilmente non risolver? il problema.
FProxyToadlet.errorWithReason=Errore: ${error}
FProxyToadlet.expectedKeyButGot=Invece di una chiave Freenet, ? stato ricevuto:
+FProxyToadlet.expectedMimeType=MIME type che ci si aspettava: ${mime}
FProxyToadlet.explanationTitle=Spiegazione
FProxyToadlet.fetchLargeFileAnywayAndDisplay=Apri comunque e mostra il file
nel browser
FProxyToadlet.fileInformationTitle=Informazioni sul file
@@ -214,8 +224,11 @@
FProxyToadlet.openForceDisk=${link}Clicka qui${/link} per forzare il browser a
scaricare il file su disco.
FProxyToadlet.openPossRSSAsForceDisk=${link}Clicka qui${/link} per scaricare
il file su disco (${bold}possibile pericolo${/bold} se si sta usando Firefox
2.0.0.0; il problema dovrebbe essere stato risolto in 2.0.0.1
FProxyToadlet.openPossRSSAsPlainText=${link}Clicka qui${/link} per aprire il
file come testo 'liscio (plain text) (ci? ${bold}pu? rappresentare un
pericolo${/bold} se si sta usando IE7 o FF2).
+FProxyToadlet.openPossRSSForceDisk=${link}Clicka qui${/link} per cercare di
costringere il browser a scaricare il file su disco (${bold}Pu? essere
pericoloso se si sta usando Firefox 2.0.0${/bold} ; il problema dovrebbe essere
risolto in 2.0.1).
FProxyToadlet.openRSSAsRSS=${link}Clicka qui${/link} per aprire il file come
RSS (ci? ${bold}rappresenta un pericolo${/bold} se l'autore del sito ? mal
intenzionato, perch? il filtraggio di RSS in Freenet non ? ancora stato
implementato).
FProxyToadlet.openRSSForce=${link}Clicka qui${/link} per aprire il file come
${mime} (ci? ${bold}pu? costituire un pericolo${/bold} se si usa IE7 o FF2).
+FProxyToadlet.opennet=gestisci connessioni non fidate
+FProxyToadlet.opennetTitle=Sconosciuti
FProxyToadlet.options=Opzioni disponibili:
FProxyToadlet.pathNotFound=Il percorso specificato non esiste.
FProxyToadlet.pathNotFoundTitle=Percorso non trovato
@@ -283,7 +296,9 @@
FetchException.longError.26=Archivio riavviato
FetchException.longError.27=Redirezione permanente: usare la nuova URI
FetchException.longError.28=Non sono stati trovati dati sufficienti; alcuni
dati sono stati richiamati ma il redirect potrebbe puntare su localit? non
valide
+FetchException.longError.29=MIME Type sbagliato: la chiave non era nella lista
dei MIME type permessi fornita dal client.
FetchException.longError.3=Il nodo non sa cosa fare dei metadati
+FetchException.longError.30=La richiesta ? stata terminata da un nodo perch?
esso aveva da poco ricevuto un'altra richiesta per la stessa chiave e quella
richiesta non era andata a buon fine.
FetchException.longError.4=Fallimento nell'analisi dei metadati
FetchException.longError.5=Fallimento durante l'estrazione di file da un
archivio
FetchException.longError.6=Non ? stato possibile decodificare un blocco
@@ -311,23 +326,55 @@
FetchException.shortError.26=Archivio riavviato
FetchException.shortError.27=Nuova URI
FetchException.shortError.28=Non sono stati trovati tutti i dati
+FetchException.shortError.29=Errore: MIME type sbagliato
FetchException.shortError.3=Metadati sconosciuti
+FetchException.shortError.30=Non ? stato possibile trovare i dati richiesti
(fallimento recente)
FetchException.shortError.4=Metadati non validi
FetchException.shortError.5=Fallimento archivio
FetchException.shortError.6=Errore decodifica block
FetchException.shortError.7=Troppi livelli di metadati
FetchException.shortError.8=Troppi riavvii di archivio
FetchException.shortError.9=Troppa recursione
+FileOffer.acceptTransferButton=Accetta Trasferimento
+FileOffer.askUserTitle=Trasferimento file diretto.
+FileOffer.commentLabel=Commenti:
+FileOffer.failedReceiveHeader=Non ? stato possibile completare il
trasferimento del file ${filename} da ${node}.
+FileOffer.failedReceiveTitle=Trasferimento fallito
+FileOffer.fileLabel=File:
+FileOffer.mimeLabel=MIME Type:
+FileOffer.offeredFileHeader=Il nodo ${name} offre il file:
+FileOffer.rejectTransferButton=Rifiuta trasferimento
+FileOffer.senderLabel=Mittente:
+FileOffer.sizeLabel=Dimensioni:
+FileOffer.succeededReceiveHeader=Il trasferimento del file ${filename} da
${node} ? stato completato.
+FileOffer.succeededReceiveTitle=Trasferimento file completato
FirstTimeWizardToadlet.bandwidthLimit=Limitazioni dell'ampiezza di banda
FirstTimeWizardToadlet.bandwidthLimitLong=Scegliere il tipo di connessione
+FirstTimeWizardToadlet.chooseNodeName=Il nome del nodo ? obbligatorio!
+FirstTimeWizardToadlet.chooseNodeNameLong=Inserire un nome per il nodo nello
spazio sottostante. Tale nome sara visibile soltanto ai peer ai quali il nodo ?
connesso e a nessun altro. Si consiglia di usare il proprio nickname IRC
possibilmente con qualche contatto in modo da essere reperibili in caso di
problemi ("Mario Rossi nessuno at niente.com").
+FirstTimeWizardToadlet.congratz=Benvenuto a bordo!
+FirstTimeWizardToadlet.congratzLong=Congratulazioni, la configurazione di base
del nodo Freenet ? completa. E' possibile cambiare e modificare ognuno dei
parametri appena impostati usando la pagina "configurazione" che ?
raggiungibile attraverso il menu sulla sinistra dell'interfaccia. Vi auguriamo
una piacevole esperienza con Freenet.
+FirstTimeWizardToadlet.connectToStrangers=Connetti con sconosciuti?
+FirstTimeWizardToadlet.connectToStrangersLong=Permettendo connessioni con
sconosciuti, questo nodo Freenet sar? meno sicuro; chiunque port? determinare
che un nodo sta girando sul tuo computer e qualsiasi malintenzionato portebbe
connettersi ad esso. per non permettere che Freenet si connetta a chiunque,
bisogner? contattare almeno altre tre persone conosciute e fidate che gi?
stiano usando Freenet e conettersi a loro manualmente.
+FirstTimeWizardToadlet.continue=Continua
FirstTimeWizardToadlet.datastoreSize=Dimensioni magazzino dati
FirstTimeWizardToadlet.datastoreSizeLong=Selezionare le dimensione desiderata
per il file di immagazzinaggio dati
+FirstTimeWizardToadlet.enableOpennet=Connettersi automaticamente a nodi
gestiti da sconosciuti?
FirstTimeWizardToadlet.homepageTitle=Utilit? di configurazione automatica
+FirstTimeWizardToadlet.iDoTrust=Possiamo fidarci degli utenti connessi a
${interface} (${ip}) ?
+FirstTimeWizardToadlet.isNetworkTrusted=La rete locale ? affidabile?
+FirstTimeWizardToadlet.isNetworkTrustedLong=Possiamo fidarci della rete
locale? Rispondendo di si a questa domanda, tutti i servizii forniti dal nodo
Freenet saranno pienamente accessibili da chiunque sul network suddetto. E'
possibile configurare un accesso pi? selettivo attraverso la pagina
"configurazione" dopo aver completato questo wizard.
+FirstTimeWizardToadlet.noNetworkIF=Non ? stata trovata nessuna interfaccia di
rete addizionale
+FirstTimeWizardToadlet.noNetworkIFLong=Freenet non ha trovato altre interfacce
di rete, quindi dar? per scontato che l'utente si connetter? dal computer
locale e solo da quello.
FirstTimeWizardToadlet.selectLanguage=Lingua
FirstTimeWizardToadlet.selectLanguageLong=Selezionare una lingua dalla lista
qui sotto:
+FirstTimeWizardToadlet.skipWizard=Non sono un novellino, lascia perdere il
wizard.
FirstTimeWizardToadlet.step1Title=Configurazione automatica Freenet -
Scegliere la lingua da utilizzare
FirstTimeWizardToadlet.step2Title=Configurazione automatica Freenet - Limite
banda
FirstTimeWizardToadlet.step3Title=Configurazione automatica di Freenet -
Dimensioni magazzino dati
+FirstTimeWizardToadlet.step4Title=Freenet first time wizard! - Configurazione
di rete
+FirstTimeWizardToadlet.step5Title=Freenet first time wizard! -
Congratulazioni, il nodo ? ora configurato.
+FirstTimeWizardToadlet.step6Title=Configurazione automatica di Freenet -
Congratulazioni, il tuo nodo ? ora configurato.
FirstTimeWizardToadlet.welcomeInfoboxContent1=Benvenuti all'utilit? di
configurazione automatica che vi permetter? di configurare Freenet e cominciare
ad usarlo, velocemente e facilmente
FirstTimeWizardToadlet.welcomeInfoboxTitle=Benvenuti all'utilit? di
configurazione automatica
FproxyToadlet.dangerousRSSTitle=Contenuto potenzialmente pericoloso (RSS)
@@ -373,6 +420,7 @@
InsertException.longError.1=Caller ha fornito una URI che non ? possibile
utilizzare"
InsertException.longError.10=Annullato dall'utente
InsertException.longError.11=Meta string (probabilmente '/') usata nella URI
+InsertException.longError.12=Binary blob format error
InsertException.longError.2=Errore bucket interno: potrebbe trattarsi di
mancanza di spazio sufficiente su disco rigido o di mancanza di autorizzazione.
InsertException.longError.3=Errore interno
InsertException.longError.4=Un nodo 'a valle' (downstream) ? andato in time
out o ? stato gravemente sovraccaricato
@@ -384,6 +432,7 @@
InsertException.shortError.1=URI non valida
InsertException.shortError.10=Annullato
InsertException.shortError.11=Meta string usata nella chiave
+InsertException.shortError.12=Binary blob format error
InsertException.shortError.2=Errore nei temp files
InsertException.shortError.3=Errore Interno
InsertException.shortError.4=Timeout o sovraccarico
@@ -444,6 +493,7 @@
N2NTMToadlet.failedTitle=Fallito
N2NTMToadlet.friends=Amici
N2NTMToadlet.homepage=Homepage
+N2NTMToadlet.noSuchFileOrCannotRead=Trasferimento fallito:File inesistente o
illegibile.
N2NTMToadlet.peerName=Nome del Peer
N2NTMToadlet.peerNotFoundTitle=Peer non trovato
N2NTMToadlet.peerNotFoundWithHash=Non ? stato possibile trovare il peer con
hash code \u201c${hash}\u201d
@@ -464,6 +514,8 @@
N2NTMUserAlert.header=Da: ${from} (scritto ${composed} | inviato ${sent} |
ricevuto ${received})
N2NTMUserAlert.reply=Rispondi
N2NTMUserAlert.title=Messaggio di testo da nodo a nodo (N2NTM) ${number} da:
${peername} (${peer})
+Node.alwaysAllowLocalAddresses=Permettere sempre la connessione a nodi via
indirizzi locali?
+Node.alwaysAllowLocalAddressesLong=Se impostato su "true" (vero) il nodo
cercher? di connettersi ad altri nodi usando il loro indirizzo locale
(localhost, LAN) oltre al loro indirizzo IP pubblico. Se questa opzione non e'
impostata, si pu? comunque abilitarla separatamente per singoli peer darknet
(ma non per i peer opennet). Impostare questa opzione se ci si vuole connettere
ad altri nodi sulla stessa rete locale (LAN) o che girano sullo stesso
computer, e non far caso alle referenze "bogus" ("scr?use") che possono far
mandare al nodo pacchetti UDP alle macchine sulla rete locale.
Node.bandwidthLimitMustBePositiveOrMinusOne=Il valore dell'ampiezza di banda
deve essere positivo o -1
Node.bindTo=Indirizzo IP collegato
Node.bindToLong=Indirizzo IP collegato
@@ -498,8 +550,14 @@
Node.nodeDirLong=Directory contenente relativi al nodo, per esempio la lista
dei peer
Node.nodeName=Nickname di questo nodo Freenet
Node.nodeNameLong=Nickname del nodo. Visibile solo dagli Amici
+Node.oneConnectionPerIP=Limita ad una connessione per indirizzo?
+Node.oneConnectionPerIPLong=Non permettere pi? di una connessione per
indirizzo? Questo render? leggermente pi? difficile eseguire un attacco
connettendosi al tuo nodo pi? volte con diverse identit? in modo da dominare il
tuo routing (instradamento) e rendere pi? facile raccogliere dati con lo
"harvesting" (lett: "il raccolto", in agricoltura). Abilitare questa opzione
rende anche impossibile che un peer sia connesso al tuo nodo sia su darknet che
su opennet.
+Node.opennetEnabled=Abilita supporto per Opennet?
+Node.opennetEnabledLong=Abilita Opennet? Se Opennet ("rete aperta") ?
abilitato, il nodo scambier? automaticamente referenze on altri nodi. Ma questo
significa anche che il fatto che sul tuo computer gira un nodo Freenet non sar?
pi? un segreto, e molti attacchi saranno pi? facili da eseguire. Se conosci
abbastanza gente che usa Freenet, la miglior cosa da fare ? di continuare ad
usare darknet.
Node.outBWLimit=Limite dell'ampiezza di banda in uscita (bytes per secondo)
Node.outBWLimitLong=Limite "duro" dell' ampiezza di banda in uscita
(bytes/sec); di solito il nodo non eccede questo limite
+Node.passOpennetPeersThroughDarknet=Trasmettere referenze opennet attraverso
peer darknet?
+Node.passOpennetPeersThroughDarknetLong=Se impostata su "true" (vero)
referenze opennet verranno trasmesse attraverso peer darknet (ma MAI la
referenza del nodo locale). In questo modo un nodo (nodo locale, o i suoi peer)
pu? ottenere peer opennet dai suoi peer darknet. Questo ? utile perch? permette
di riconnettersi in caso di perdita dei peer, per esempio dopo una lunga
disconnessione, ma rende l'analisi del traffico leggermente pi? facile, quindi
chi ? paranoico dovrebbe disabilitare questa opzione.
Node.port=Numero della porta FNP (UDP)
Node.portLong=Porta UDP per le comunicazioni da nodo a nodo (Freenet Node
Protocol)
Node.storeDirectory=Directory dello store
@@ -574,8 +632,16 @@
NodeUpdateManager.updateFailedTitle=Aggiornamento Fallito!
NodeUpdateManager.updateURI=Dove cercare aggiornamenti?
NodeUpdateManager.updateURILong=Dove cercare aggiornamenti?
+OpennetConnectionsToadlet.fullTitle=${counts} Sconosciuti (Peers non Fid?ti)
di ${name}
+OpennetConnectionsToadlet.peersListTitle=I Miei Opennet Peer (nodi gestiti da
sconosciuti, aggiunti dal nodo)
+OpennetUserAlert.warning=Il modo promiscuo ? attualmente attivato. Ci?
significa che esso si connetter? con Sconosiuti, e quindi che chiunque potr?
facilmente determinare che l'utente titolare del tale abbonamento sta usando
Freenet. Molti attacchi vengono facilitati da questa modalit?, bloccare il nodo
(per esempio a un firewall nazionale) diventa molto pi? facile, ed intoltre
l'utente non ha controllo su chi si connette al suo nodo. Si raccomanda
vivamente di procurarsi qualce connessione ad Amici (nodi fidati, gestiti da
persone conosciute); il modo promiscuo va considerato una misura temporanea da
utilizzarsi finch? non ci si potr? connettere ad Amici. Connettendosi
esclusivamente a nodi gestiti da persone conosciute, pur non essendo impossibli
degli attacchi da parte loro, risulter? comunque meno probabile l'esposizione
ad agenzie governative (tipo servizi segreti o che so io) o altri "cattivi".
Noa che aggiungendo un peer alla sezione Amici non cambia molto la situazione a
meno che tale nodo non sia gestito da qualcuno di consciuto e di cui ci si fida
(per ragioni sia di routing [instradamento] che di sicurezza)!
+OpennetUserAlert.warningTitle=Avvertenza: Modo Promiscuo Attivato: Il nodo si
connetter? a degli sconosciuti
PNGFilter.invalidHeader=Il file che si sta cercando di richiamare non e' un
PNG: esso non include un header PNG valido. Potrebbe trattarsi di un file in
altro formato e il browser potrebbe fare qualcosa di pericoloso a causa della
confusione creata dalla mancata corrispondenza; il file ? stato pertanto
bloccato.
PNGFilter.invalidHeaderTitle=Header PNG non valido
+PeerManagerUserAlert.clockProblem=${count} dei tuoi peer non riescono a
connettersi perch? il loro orologio di sistema differisce dal tuo di oltre 24
ore. Verifica che l'orologio del computer sia regolato sull'ora esatta.
Regolazioni inaccurate dell'orologio causano molti problemi nel funzionamento
dei meccanismi tra nodo e client.
+PeerManagerUserAlert.clockProblemTitle=Problema relativo all'orologio.
+PeerManagerUserAlert.connError=${count} dei tupi peer non riescono a
connettersi per motivi sconosciuti, forse per causa di 'bug' nel nodo o di una
referenza di un nodo che e' corrotta.
+PeerManagerUserAlert.connErrorTitle=Alcuni peer non riescono a connettersi
PeerManagerUserAlert.noConns=Non ? stato finora possibile connettersi ad alcun
nodo. Forse qualcuno dei peer si connettera entro breve. in caso contrario sar?
necessario aggiungere altri peer; c'e' bisogno di almeno tre peer connessi in
ogni momento, meglio 5-10.
PeerManagerUserAlert.noConnsTitle=Non ci sono connessioni aperte
PeerManagerUserAlert.noPeersDarknet=Questo nodo non ha alcun peer al quale
connettersi e non pu? quindi funzionare normalmente. In teoria ci si dovrebbe
connettere esclusivamente a persone che si conosce (per i paranoici: persone di
cui ci si fida, per i non paranoici: persone con le quali si ha parlato). Per
un corretto funzionamento c'e' bisogno di almeno tre peer connessi in ogni
momento, idealmente 5-10. Ci si pu? connettere a irc.freenode.net canale
#freenet-refs e chiedere chi vuole connettersi, ma ? bene tenere presente che
si ? vulnerabili per i proprii peer.. (Speciamente in queste prime versioni
alfa di Freenet 0.7...) VERIFICARE CHE L'ATRA PARE AGGIUNGA LA REFERENZA ALLA
SUA LISTA: LE CONNESSIONI "A SENSO UNICO" NON FUNZIONANO!
@@ -599,6 +665,13 @@
PeerManagerUserAlert.tooOldNeverConnectedPeers=Uno o pi? peer non si sono mai
connessi nelle due settimane trascorse da quando sono stati aggiunti. E' da
prendere in considerazione l'idea di rimuoverli in quanto essi stanno
marginalmente compromettendo il rendimento (pacchetti sprecati cencando di
comunicare con nodi che non ci sono).
PeerManagerUserAlert.tooOldNeverConnectedPeersTitle=Peer mai connesso/i troopo
vecchio/i
PeerManagerUserAlert.twoConns=Il nodo ha solo due connessioni. Rendimento e
sicurezza risulteranno di qualit? inferiore, e non sara possibile provvedere
instradamento (routing) per altri nodi. Il nodo ? collegato al network come un
"anello di catena" e non contribuisce (molto) alla salute generale del network
stesso. Per un corretto funzionamento del nodo, ? necessario che almeno tre
peers (e idealmente 5-10) siano connessi in ogni momento.
+PeersSayKeyBlownAlert.connectedSayBlownLabel=I seguenti nodi hanno rilevato un
problema con la chiave (si cerca attualmente di ottenere il certificato di
revoca da loro):
+PeersSayKeyBlownAlert.disconnectedSayBlownLabel=I seguenti nodi si sono
disconnessi dopo aver comunicato che la chiave ? saltata, quindi non ? stato
possibile richiamare il certificato di revoca:
+PeersSayKeyBlownAlert.failedFetch=Non ? stato possibile scaricare il
certificato di revoca. Le possibili cause di tale evento includono la
possibilit? di un attacco sul nodo locale volto a fargli scaricare ed
installare un aggiornamento nonostante la chiave sia saltata, o la possibilit?
che dei nodi stiano "mentendo" circa la chiave di revoca. Si prega di
contattare gli sviluppatori di Freenet per cercare di mettere ordine in questo
casino.
+PeersSayKeyBlownAlert.failedTransferSayBlownLabel=Questi nodi hanno comunicato
che la chiave di revoca ? saltata ma poi non hanno completato il trasferimento
del certificato di revoca:
+PeersSayKeyBlownAlert.fetching=Il nodo sta scaricando il certificato di revoca
contentnte spiegazioni pi? dettagliate.
+PeersSayKeyBlownAlert.intro=Uno o pi? peers ci comunicano che la chiave di
revoca per l'aggiornamento automatico ? saltata. Questo significa che qualcuno
potrebbe essere venuto a conoscenza della chiave privata del sistema di
autoaggiornamento, cosa che potrebbe far eseguire al nodo il codice che
l'attaccante volesse fargli eseguire (se l'aggiornamento venisse eseguito): per
prevenire tale eventualit?, il sistema di autoaggiornamento ? stato
disabilitato. E' anche possibile che dei peers stiano deliberatamente mentendo
a proposito della chiave di revoca.
+PeersSayKeyBlownAlert.titleWithCount=chiave di Auto-aggiornamento saltata,
evento confermato da ${count} peer!
PluginManager.cannotSetOnceLoaded=Una volta caricata, non ? pi? possibile
impostare la lista dei plugin
PluginManager.loadedOnStartup=Plugin da caricare all'avvio
PluginManager.loadedOnStartupLong=Classpath, nome e locazione dei plugin da
caricare all'avvio
@@ -698,7 +771,7 @@
QueueToadlet.persistence=Persistenza
QueueToadlet.persistenceForever=illimitata
QueueToadlet.persistenceNone=nessuna
-QueueToadlet.persistenceRebootr=reboot
+QueueToadlet.persistenceReboot=reboot
QueueToadlet.pleaseEnableFCP=Per accedere a questa pagina ? necessario
abilitare il server FCP
QueueToadlet.priority=Priorit?
QueueToadlet.priority0=urgenza estrema
@@ -712,6 +785,7 @@
QueueToadlet.progressbarAccurate=Questo valore e' accurato
QueueToadlet.progressbarNotAccurate=I valori possono essere imprecisi perch?
il processo di download del file non e' stato finalizzato
QueueToadlet.reason=Motivo
+QueueToadlet.remove=Elimina
QueueToadlet.requestNavigation=Esplora Richieste
QueueToadlet.restart=Riavvia
QueueToadlet.size=Dimensioni
@@ -748,6 +822,8 @@
SimpleToadletServer.cssOverrideCantRead=Non ? stato possibile leggere il file
di sovrascrittura CSS fornito: ${filename}
SimpleToadletServer.cssOverrideLong=Questa impostazione permette di utilizzare
un CSS personalizzato invece di quello normalmente usato. AVVERTENZA: i CSS
possono essere pericolosi, e *non* vengono filtrati: utilizzare a proprio
rischio. Per includerli nella distribuzione principale e-mail devl at
freenetroject.org
SimpleToadletServer.cssOverrideNotInUploads=Non ? possibile usare questa
impostazione: "${filename} non ? una directory dalla quale sono permessi gli
upload.
+SimpleToadletServer.doRobots=Escludere robots via robots.txt?
+SimpleToadletServer.doRobotsLong=Pubblica /robots.txt che dice a persone,
Google, spiders, wget, ecc. di lasciarci in pace.
SimpleToadletServer.enableJS=Permetti a FProxy di usare Javascript
SimpleToadletServer.enableJSLong=Determina se FProxy pu? o meno fare uso di
Javascript. Questa impostazione di solito va tenuta su 'false'. Nota che i
freesite non fanno uso di javascript nemmeno se qui abilitata.
SimpleToadletServer.enabled=Abilita FProxy
@@ -803,20 +879,25 @@
TextModeClientInterfaceServer.enabledLong=Abilita TMCI
TextModeClientInterfaceServer.telnetPortNumber=Porta telnet
TextModeClientInterfaceServer.telnetPortNumberLong=Numero della porta telnet
+TimeSkewDetectedUserAlert.text=Una discepanza temporale ? stata rilevata dal
nodo. Questo ? un inconveniente grave, il nodo non potr? funzionare
correttamente finch? non vi si sar? ovviato. Tra le cause pi? comuni, la
modalit? powersafe mal configurata, cattiva sincronizzazione tra i clients del
network, hardware bugs.
+TimeSkewDetectedUserAlert.title=Discrepanza temporale!
Toadlet.cancel=Cancella
Toadlet.clickHere=Clicka qui
Toadlet.homepage=Homepage
Toadlet.internalErrorPleaseReport=Errore interno: se possibile, riportarlo
Toadlet.internalErrorTitle=Errore Interno
+Toadlet.no=No
Toadlet.nodeHomepage=Homepage del Nodo
Toadlet.notSupportedTitle=Non Supportato
Toadlet.notSupportedWithClass=Il browser ha mandato una richiesta che Freenet
(${class}) non capisce.
+Toadlet.ok=Ok
Toadlet.permRedirectWithReason=Redirect permanente: ${reason}
Toadlet.returnToHomepage=Torna alla homepage del nodo
Toadlet.returnToNodeHomepage=Torna alla homepage del nodo
Toadlet.returnToPrevPage=Torna alla pagina precedente
Toadlet.tempRedirectWithReason=Redirect temporaneo: ${reason}
Toadlet.unauthorized=L'accesso a questa pagina ? interdetto.
+Toadlet.yes=S?
ToadletContextImpl.cannotParseContentLength=errore di analisi content-length:
${error}
ToadletContextImpl.headersLineTooLong=Un rigo troppo lungo sta analizzando gli
headers
ToadletContextImpl.methodNotAllowed=Metodo HTTP Non Permesso
Modified: branches/freenet-jfk/src/freenet/l10n/freenet.l10n.no.properties
===================================================================
--- branches/freenet-jfk/src/freenet/l10n/freenet.l10n.no.properties
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/l10n/freenet.l10n.no.properties
2007-08-21 20:26:59 UTC (rev 14828)
@@ -43,6 +43,7 @@
BookmarkManager.malformedBookmark=Missformet Bokmerke
BooleanOption.parseError=Ukjent boolean: ${val} - pr?v true eller false
BuildOldAgeUserAlert.tooOld=Denne nodens programvare er eldre enn den eldste
versjonen (Build #${lastgood}) tillatt av de nyeste 'peers' vi pr?ver ? koble
til. Vennligst oppdater noden so fort som mulig ettersom du ikke kan koble til
'peers' markert "For ny" f?r du gj?r dette. (Hvis du ikke oppdaterer kan du
etterhvert miste tilkoblingen til Freenet.)
+BuildOldAgeUserAlert.tooOldTitle=For gammel versjon
CSSTokenizerFilter.deletedDisallowedString=Slett ulovlig streng
CSSTokenizerFilter.supplementalCharsNotSupported=UCS-4 TEGN OVER 0xFFFF ER
IKKE ST?TTET!
ConfigToadlet.appliedFailureExceptions=Endringene du gjorde i konfigurasjonen
blir brukt med f?lgende unntak:
@@ -51,8 +52,10 @@
ConfigToadlet.appliedTitle=Konfigurasjon I Bruk
ConfigToadlet.apply=Bruk
ConfigToadlet.configNavTitle=Navigasjon
+ConfigToadlet.contributeTranslation=Bidra til oversettelsen
ConfigToadlet.fullTitle=Freenet Node Konfigurasjon for ${name}
ConfigToadlet.possibilitiesTitle=Dine Muligheter
+ConfigToadlet.reset=Tilbakestill
ConfigToadlet.returnToNodeConfig=Returner til nodens konfigurasjon
ConfigToadlet.shortTitle=Konfigurasjon
ConfigToadlet.title=Freenet Node Konfigurasjon
@@ -88,11 +91,15 @@
DarknetConnectionsToadlet.cantFetchNoderefURL=Kunne ikke hente node referansen
fra ${url}. Vennligst pr?v p? nytt.
DarknetConnectionsToadlet.cantParseTryAgain=Kunne ikke tolke den gitte teksten
som en referanse: (${error}). Vennligst pr?v p? nytt.
DarknetConnectionsToadlet.cantParseWrongEnding=Kunne ikke tolke nodens
referanse: Den skal slutte med End p? en linje for seg selv, men den slutter
med: ${end}
+DarknetConnectionsToadlet.clockProblem=Forskjellen mellom klokken din og denne
nodens klokke er mer enn 24 timer. Vi har deaktivert tilkoblingen ettersom
dette kan f?re til problemer med oppdatering og klienter.
+DarknetConnectionsToadlet.clockProblemShort=Klokkeproblem
DarknetConnectionsToadlet.confirmRemoveNode=Er du sikker p? at du vil fjerne
"${sname}"? F?r den har minst en uke nedetid, er det ikke anbefalt ? gj?re det,
ettersom det kan v?re midlertidig, og mange brukere ikke kan kj?re noden 24x7.
DarknetConnectionsToadlet.confirmRemoveNodeTitle=Vennlist bekreft
DarknetConnectionsToadlet.confirmRemoveNodeWarningTitle=Node Fjerning
+DarknetConnectionsToadlet.connErrorShort=Tilkoblingsfeil
DarknetConnectionsToadlet.connected=Tilkoblet: Vi er vellykket tilkoblet disse
nodene
DarknetConnectionsToadlet.connectedShort=Tilkoblet
+DarknetConnectionsToadlet.darknetFnpPort=Darknet FNP: ${port}/UDP (mellom
noder; du vil kanskje videresende denne porten)
DarknetConnectionsToadlet.disabled=Ikke tilkoblet og deaktivert: fordi
brukeren har instruert noden til ? ikke koble til disse naboene.
DarknetConnectionsToadlet.disabledShort=Deaktivert
DarknetConnectionsToadlet.enterDescription=Legg til beskrivelse:
@@ -127,6 +134,7 @@
DarknetConnectionsToadlet.nodePortsTitle=Porter som brukes av noden
DarknetConnectionsToadlet.notConnected=Ikke tilkoblet: Ingen tilkobling s?
langt, men noden pr?ver kontinuerlig ? koble til.
DarknetConnectionsToadlet.notConnectedShort=Frakoblet
+DarknetConnectionsToadlet.opennetFnpPort=Opennet FNP: ${port}/UDP (mellom
noder; du vil kanskje videresende denne porten)
DarknetConnectionsToadlet.pasteReference=Lim inn referansen her:
DarknetConnectionsToadlet.privateNote=Et privat notat om denne naboen
DarknetConnectionsToadlet.privateNoteTitle=Privat Notat
@@ -135,6 +143,7 @@
DarknetConnectionsToadlet.removePeers=Fjern valgte naboer
DarknetConnectionsToadlet.selectAction=-- Velg handling --
DarknetConnectionsToadlet.sendMessageTitle=Send Node to Node Text Message
+DarknetConnectionsToadlet.sendMessageToPeers=Send N2NTM til valgte peers
DarknetConnectionsToadlet.separator=-- -- --
DarknetConnectionsToadlet.statusTitle=Status
DarknetConnectionsToadlet.tmciDisabled=TMCI er deaktivert (enkel telnet-basert
kommandolinje-grensesnitt)
@@ -148,12 +157,18 @@
DarknetConnectionsToadlet.updateChangedPrivnotes=Oppdater endrede private
notater
DarknetConnectionsToadlet.urlReference=Skriv inn URLen til referansen her:
DarknetConnectionsToadlet.versionTitle=Versjon
+ExtOldAgeUserAlert.extTooOld=Det ser ut som freenet-ext.jar filen din er
utdatert: vi anbefaler sterkt at du oppgraderer den til
http://downloads.freenetproject.org/alpha/freenet-ext.jar.
+ExtOldAgeUserAlert.extTooOldTitle=Freenet-ext er for gammel
FProxyToadlet.backToFProxy=${link}Klikk her${/link} for ? g? til FProxy
hjemmesiden.
+FProxyToadlet.config=konfigruer noden din
FProxyToadlet.configTitle=Konfigurasjon
+FProxyToadlet.dangerousContentTitle=Potensiellt Farlig Innhold
+FProxyToadlet.dangerousRSSTitle=Potensielt Farlig Innhold (RSS)
FProxyToadlet.downloadInBackgroundToDisk=Last ned i bakgrunnen og lagre i
nedlastingsmappen
FProxyToadlet.errorIsFatal=Dette er en fatal feil. Det er usannsynlig at
problemet vil l?ses ved ? pr?ve p? nytt.
FProxyToadlet.errorWithReason=Feil: ${error}
FProxyToadlet.expectedKeyButGot=Forventet en Freenet n?kkel, men fikk:
+FProxyToadlet.expectedMimeType=Forventet MIME-type: ${mime}
FProxyToadlet.explanationTitle=Forklaring
FProxyToadlet.fetchLargeFileAnywayAndDisplay=Hent uansett og vis filen i
nettleseren
FProxyToadlet.fileInformationTitle=Fil Informasjon
@@ -164,22 +179,32 @@
FProxyToadlet.invalidKeyTitle=Ugyldig N?kkel
FProxyToadlet.largeFile=Stor fil
FProxyToadlet.largeFileExplanationAndOptions=Freenet n?kkelen du ba om peker
til en stor fil. Filer p? denne st?rrelsen kan generelt sett ikke sendes
direkte til nettleseren siden de tar for lang til for Freenet noden ? hente. De
f?lgende mulighetene er tilgjengelige:
+FProxyToadlet.mayChange=(kan bli endret)
FProxyToadlet.mimeType=MIME type: ${mime}
FProxyToadlet.notFoundTitle=Ikke Funnet
+FProxyToadlet.openAsText=${link}Klikk her${/link} for ? ?pne filen som tekst
(dette b?r ikke v?re farlig, men det kan se ?delagt ut).
+FProxyToadlet.openForce=${link}Klikk her${/link} for ? ?pne filen som ${mime}
(les advarselen over!).
FProxyToadlet.openRSSAsRSS=${link}Klikk her${/link} for ? ?pne filen som RSS
(dette er ${bold}farlig${/bold} hvis forfatteren av siden er ondskapsfull
ettersom Freenet ikke kan filtrere RSS enda).
+FProxyToadlet.opennetTitle=Fremmede
FProxyToadlet.options=Dine valg er:
FProxyToadlet.pluginsTitle=Tillegg
+FProxyToadlet.queue=h?ndter foresp?rsler satt i k?
+FProxyToadlet.queueTitle=K?
FProxyToadlet.sizeLabel=Str?rrelse:
FProxyToadlet.sizeUnknown=St?rrelse: ukjent
FProxyToadlet.stats=vis statistikk
FProxyToadlet.statsTitle=Statistikk
FProxyToadlet.translationTitle=Oversettelse
+FProxyToadlet.unableToRetrieve=Freenet kunne ikke hente denne filen.
FProxyToadlet.unknownMIMEType=MIME type: ukjent
FProxyToadlet.welcome=hjemmeside
FProxyToadlet.welcomeTitle=Hjem
FcpServer.downloadsFileCanCreateCannotReadOrWrite=Opprettet fil, men kan ikke
lese og skrive den
FcpServer.downloadsFileDoesNotExistCannotCreate=Filen finnes ikke og kan ikke
lages
+FcpServer.downloadsFileExistsCannotReadOrWrite=Filen eksisterer, men kan ikke
skrives eller leses
FcpServer.downloadsFileUnreadable=Filen finnes, men kan ikke leses
+FcpServer.isEnabled=Er FCP serveren aktivert?
+FcpServer.isEnabledLong=Er FCP serveren aktivert?
FcpServer.portNumber=FCP port nummer
FcpServer.portNumberLong=FCP port nummer.
FetchException.longError.1=For mange lag med gjentakelse inn i arkivet
@@ -200,6 +225,7 @@
FetchException.longError.26=Arkivet ble startet p? nytt
FetchException.longError.27=Permanent omdirigering: bruk den nye URIen
FetchException.longError.28=Ikke nok data ble funnet; noe data ble hentet, men
omdirigeringer kan peke til ingenting
+FetchException.longError.29=Feil MIME-type: N?kkelen var ikke i listen over
tillatte MIME-typer fra klienten
FetchException.longError.3=Vet ikke hva som skal gj?res med metadata
FetchException.longError.4=Tolkning av metadata mislyktes
FetchException.longError.5=Mislyktes i ? trekke ut filer fra et arkiv
@@ -224,23 +250,43 @@
FetchException.shortError.26=Arkiv startet p? nytt
FetchException.shortError.27=Ny URI
FetchException.shortError.28=Alle data ikke funnet
+FetchException.shortError.29=Feil MIME-type
FetchException.shortError.3=Ukjent metadata
+FetchException.shortError.30=Data ikke funnet (mislyktes nylig)
FetchException.shortError.4=Ugyldig metadata
FetchException.shortError.5=Arkiv feil
FetchException.shortError.6=Blokkdekodingsfeil
FetchException.shortError.7=For mange metadata-lag
FetchException.shortError.8=For mange arkiv omstarter
FetchException.shortError.9=For mye gjentakelse
+FileOffer.acceptTransferButton=Aksepter overf?ring
+FileOffer.askUserTitle=Direkte filoverf?ring
+FileOffer.commentLabel=Kommentar:
+FileOffer.failedReceiveHeader=Overf?ringen av ${filename} fra ${node}
mislyktes.
+FileOffer.failedReceiveTitle=Mottak av fil mislyktes
+FileOffer.fileLabel=Fil:
+FileOffer.mimeLabel=MIME Type:
+FileOffer.offeredFileHeader=Noden ${name} har tilbydt en fil:
+FileOffer.rejectTransferButton=Avsl? Overf?ring
+FileOffer.senderLabel=Sender:
+FileOffer.sizeLabel=St?rrelse:
+FileOffer.succeededReceiveHeader=Overf?ringen av filen ${filename} fra ${node}
var vellykket.
+FileOffer.succeededReceiveTitle=Vellykket mottak av fil
FirstTimeWizardToadlet.bandwidthLimit=B?ndbreddebegrensninger
FirstTimeWizardToadlet.bandwidthLimitLong=Vennligst velg din tilkoblingstype
fra nedtrekksmenyen under.
+FirstTimeWizardToadlet.congratz=Velkommen ombord!
FirstTimeWizardToadlet.datastoreSize=Datalagerst?rrelse
FirstTimeWizardToadlet.datastoreSizeLong=Vennligst velg en st?rrelse for
datalageret ditt.
FirstTimeWizardToadlet.homepageTitle=Freenet f?rstegangsveiviser!
+FirstTimeWizardToadlet.iDoTrust=Stoler du p? folk koblet til ${interface}
(${ip})?
+FirstTimeWizardToadlet.isNetworkTrusted=Stoler du p? ditt lokale nettverk?
+FirstTimeWizardToadlet.noNetworkIF=Fant ingen ekstra nettverkstilkobling
FirstTimeWizardToadlet.selectLanguage=Spr?k
FirstTimeWizardToadlet.selectLanguageLong=Vennligst velg et spr?k fra listen
under:
FirstTimeWizardToadlet.step1Title=Freenet f?rstegangsveiviser! - Velg ditt
spr?k
FirstTimeWizardToadlet.step2Title=Freenet f?rstegangsveiviser!
B?ndbreddebegrensninger
FirstTimeWizardToadlet.step3Title=Freenet f?rstegangsveiviser! -
Datalagerst?rrelse
+FirstTimeWizardToadlet.step5Title=Freenet f?rstegangsveiviser! - Gratulerer,
noden din er n? konfigurert
FirstTimeWizardToadlet.welcomeInfoboxContent1=Velkommen til freenet
f?rstegangsveiviser. Dette verkt?yet vil gi deg mulighet til ? konfigurere
noden din fort og enkelt for ? f? deg i gang. Vennligst
FirstTimeWizardToadlet.welcomeInfoboxTitle=Velkommen til Freenet
f?rstegangsveiviser!
GIFFilter.invalidHeader=Filen inneholder ikke et gyldig GIF hode.
@@ -274,12 +320,15 @@
InsertException.longError.10=Avbrutt av bruker
InsertException.longError.12=Bin?r blob formateringsfeil
InsertException.longError.3=Intern feil
+InsertException.longError.5=Kunne ikke sende innsettingen til nok noder
(normalt i sm? nettverk, pr?v ? hente den uansett)
InsertException.longError.9=Innsettingen kolliderte med forskjellig,
eksisterende data p? samme n?kkel
InsertException.shortError.1=Ugyldig URI
InsertException.shortError.10=Avbrutt
InsertException.shortError.12=Bin?r blob formateringsfeil
InsertException.shortError.3=Intern feil
InsertException.shortError.5=Rute ikke funnet
+InsertException.shortError.6=Noen blokker mislyktes fatalt
+InsertException.shortError.8=Foresp?rselen kunne ikke forlate noden
InsertException.shortError.9=Kolliderte med eksisterende data
IntOption.parseError=Den spesifiserte verdien kan ikke tolkes som en 32-bits
integer: ${val}
JPEGFilter.notJpeg=Filen du pr?vde ? hente er ikke JPEG. Den kan v?re et annet
filformat, og nettleseren din kan gj?re noe farlig med den. Derfor har filen
blitt blokkert.
@@ -295,7 +344,10 @@
KnownUnsafeContentTypeException.knownUnsafe=Dette er en potensielt farlig
MIME-type. Hvis noden slipper den gjennom kan nettleseren din gj?re mange
d?rlige ting som kan lede til kompromittering av din anonymitet, og at IP
adressen din blir avsl?rt i forbindelse med denne siden. Spesielt:
KnownUnsafeContentTypeException.noFilter=Siden det ikke finnes noe innebygd
filter for denne filen b?r du utvise den h?yeste forsiktighet!
KnownUnsafeContentTypeException.title=Kjent farlig type: ${type}
+LocalFileInsertToadlet.checkPathReadable=Sjekk at den spesifiserte stien er
lesbar for brukeren som kj?rer noden.
+LocalFileInsertToadlet.dirCannotBeRead=Stien "${path}" kan ikke leses.
LocalFileInsertToadlet.fileHeader=Fil
+LocalFileInsertToadlet.insert=Sett inn
LocalFileInsertToadlet.sizeHeader=St?rrelse
LogConfigHandler.detaildPriorityThreshold=Detaljert prioritetsgrense
LogConfigHandler.detaildPriorityThresholdLong=Detaljert prioritetsbegrensning,
eksempel freenet:normal,freenet.node:minor
@@ -316,14 +368,23 @@
LongOption.parseError=Den spesifiserte verdien kan ikke tolkes som en 64-bits
integer: ${val}
MeaningfulNodeNameUserAlert.noNodeNick=Det ser ut som noden din ikke har et
kallenavn. ? legge inn e-mail adressen eller IRC kallenavnet ditt her er
generelt en god ide og det hjelper vennene dine ? kjenne igjen noden din (merk
at bare darknet naboer dine listet p? vennesiden kan se nodens navn, det vil
ikke bli vist til opennet naboer).
MeaningfulNodeNameUserAlert.noNodeNickTitle=Noden din har ikke et navn.
+N2NTMToadlet.composingMessageLabel=Skriver N2NTM til de f?lgende mottakerne:
+N2NTMToadlet.delayed=Opptatt: Sending av meldingen til mottaker ble kanskje
forsinket
N2NTMToadlet.delayedTitle=Forsinket
+N2NTMToadlet.failed=Meldingen kunne ikke sendes til mottakeren: mottakeren er
ikke tilkoblet
N2NTMToadlet.failedTitle=Mislyktes
N2NTMToadlet.friends=Venner
+N2NTMToadlet.noSuchFileOrCannotRead=Kunne ikke sende filen: Den finnes ikke
eller kan ikke leses.
+N2NTMToadlet.peerName=Peer Navn
+N2NTMToadlet.peerNotFoundTitle=Peer ble ikke funnet
N2NTMToadlet.processingSend=Sending av Node to Node Text Message Behandles
+N2NTMToadlet.queued=Satt i k?: Mottakeren var ikke tilkoblet, s? meldingen er
satt i k? til denne kobler til
+N2NTMToadlet.queuedTitle=Satt i k?
N2NTMToadlet.returnToFriends=Returner til venneliste
N2NTMToadlet.sendMessage=Send Node til Node Tekst Melding
N2NTMToadlet.sendMessageShort=Send melding
N2NTMToadlet.sendStatus=N2NTM Sendt Status
+N2NTMToadlet.sent=Meldingen ble sendt til mottakeren
N2NTMToadlet.sentTitle=Sendt
N2NTMToadlet.tooLong=N2NTMer er begrenset til 1024 tegn
N2NTMToadlet.tooLongTitle=For lang
@@ -348,6 +409,8 @@
Node.mustBePositive=Konfigurasjonsverdien m? v?re positiv
Node.nodeName=Kallenavn for denne Freenet noden
Node.nodeNameLong=Nodens kallenavn. Dette vil bare v?re synlig for venner.
+Node.oneConnectionPerIP=Begrens til en tilkobling per adresse?
+Node.opennetEnabled=Aktiver Opennet-st?tte?
Node.outBWLimit=Utg?ende b?ndbreddebegrensning (byte per sekund)
Node.outBWLimitLong=Hard utg?ende b?ndbreddebegrensning (byte/sek); noden b?r
nesten aldri g? over dette
Node.port=FNP port nummer (UDP)
@@ -363,6 +426,8 @@
NodeClientCore.couldNotFindOrCreateDir=Kunne ikke finne eller opprette mappe
NodeClientCore.maxUSKFetchersMustBeGreaterThanZero=M? v?re st?rre enn null
NodeIPDectector.inclLocalAddress=Inkluder lokal adresse i noderef
+NodeIPDectector.inclLocalAddressLong=Skal din lokale adresse (LAN og
localhost) inkluderes i nodens referanse? Dette vil ikke v?re nyttig med mindre
begge sider setter allowLocalAddress=true for den respektive referansen (bruk
vennesiden i avansert modus for ? sette denne verdien).
+NodeIPDectector.ipOverride=Overstyring av IPadresse
NodeIPDectector.ipOverrideLong=IP adresseoverstyring (vanligvis ikke
n?dvendig) - sett denne hvis du har *statisk* IP adresse eller et domenenavn
(f.eks via dyndns), og du er bak en brannmur.
NodeIPDectector.tempAddressHint=Midlertidig hint om IP adresse
NodeIPDectector.tempAddressHintLong=Midlertidig hint om hva IP adressen v?r
kan v?re; slettes etter bruk
@@ -371,6 +436,7 @@
NodeStat.threadLimit=Tr?d-grense
NodeStats.mustBePercentValueNotFull=Denne verdien m? v?re en prosent mellom 0
og 99.
NodeStats.valueTooLow=Denne verdien er for lav for den innstillingen, ?k den!
+NodeUpdateManager.enabled=Let etter og last ned nye versjoner
NodeUpdateManager.enabledLong=Skal noden automatisk sjekke etter nye versjoner
av Freenet. Hvis ja, nye versjoner vil automatisk oppdages og lastes ned, men
ikke n?dvendigvis installert. Denne innstillingen settes automatisk til 'false'
(nei) hvis noden kj?rer uten innpakningen.
NodeUpdateManager.extURI=Hvor skal noden se etter oppdateringer til
freenet-ext.jar?
NodeUpdateManager.extURILong=Hvor skal noden se etter oppdateringer til
freenet-ext.jar?
@@ -389,8 +455,20 @@
NodeUpdateManager.updateURILong=Hvor skal noden se etter oppdateringer?
PNGFilter.invalidHeader=Filen du pr?vde ? hente er ikke et PNG. Det inkluderer
ikke et gyldig PNG hode. Det kan v?re et annet format, og nettleseren din kan
gj?re noe farlig med det. Det har derfor blitt blokkert.
PNGFilter.invalidHeaderTitle=Ikke et PNG - ugyldig hode
+PeerManagerUserAlert.clockProblemTitle=Klokkeproblem
PeerManagerUserAlert.noConns=Denne noden har ikke kunnet koble til noen andre
noder s? langt; den vil ikke kunne fungere normalt. Forh?pentligvis vil noen av
naboene koble til snart; hvis ikke, pr?v ? skaffe noen flere naboer. Du trenger
minst 3 naboer, og b?r ha 5-10.
+PeerManagerUserAlert.noPeersTitle=Ingen peers funnet
+PeerManagerUserAlert.onlyFewConnsTitle=Bare ${count} fungerende tilkobling(er)
+PeerManagerUserAlert.tooManyConnsTitle=For mange ?pne tilkoblinger
PeerManagerUserAlert.tooManyDisconnectedTitle=For mange frakoblede naboer
+PeerManagerUserAlert.tooManyPeersTitle=For mange peers
+PeersSayKeyBlownAlert.connectedSayBlownLabel=Disse tilkoblede nodene sier at
oppdateringssystemet er kompromitert (vi pr?ver ? laste ned
revokasjonssertifikatet fra dem):
+PeersSayKeyBlownAlert.disconnectedSayBlownLabel=Disse nodene fortalte oss at
n?kkelen har blitt kompromitert, men koblet deretter fra. Derfor kunne vi ikke
hente revokasjonssertifikatet fra disse:
+PeersSayKeyBlownAlert.failedFetch=Noden din kunne ikke laste ned
revokasjonsertifikatet. Mulige ?rsaker inkluderer ett angrep p? noden din for ?
f? den til ? oppdatere selv om n?kkelen er kompromitert. Vennligst kontakt
utviklerne eller andre Freenet-brukere for ? rydde opp i dette.
+PeersSayKeyBlownAlert.failedTransferSayBlownLabel=Disse nodene sa at n?kkelen
har blitt kompromitert, men overf?rte ikke revokasjonssertifikatet:
+PeersSayKeyBlownAlert.fetching=Noden din pr?ver ? laste ned
revokasjonssertifikatet for ? finne ut flere detaljer.
+PeersSayKeyBlownAlert.intro=En eller flere av dine peers sier at det
automatiske oppdaterinssystemet er kompromitert! Dette betyr at en angriper kan
vite den private n?kkelen for oppdateringssystemet og kan derfor f?r noden din
til ? kj?re kode han velger (hvis du oppdaterer)! Det automatiske
oppdateringssystemet har blitt deaktivert. Det er ogs? mulig at dine peers med
overlegg lyver om dette.
+PeersSayKeyBlownAlert.titleWithCount=Auto-oppdateringssystemet er kompromitert
i f?lge ${count} peer(s)!
PluginManager.cannotSetOnceLoaded=Kan ikke endre tilleggslisten n?r den er
lastet
PluginManager.loadedOnStartup=Tillegg som skal lastes ved oppstart
PluginManager.loadedPlugins=Tillegg som skal lastes ved oppstart
@@ -399,6 +477,7 @@
PluginManager.pluginReqNewerJVMTitle=Nyere JVM kreves av ${name}.
PluginToadlet.addPluginTitle=Legg til et tillegg
PluginToadlet.failedToLoadPlugin=Mislyktes i ? laste tillegg.
+PluginToadlet.failedToLoadPluginCheckClass=Tillegget du bad om kunne ikke
lastes. Vennligst sjekk navnet p? tileggets klasse og URL, hvis du angav en.
PluginToadlet.failedToLoadPluginTitle=Lasting av tillegg mislyktes
PluginToadlet.internalNameTitle=Internt Navn
PluginToadlet.loadPluginCommand=Last tillegg
@@ -408,27 +487,48 @@
PluginToadlet.pluginListTitle=Liste over Tillegg
PluginToadlet.pluginNameTitle=Navn p? Tillegg
PluginToadlet.pluginNotFound=Det forespurte tillegget ble ikke funnet.
+PluginToadlet.pluginNotFoundTitle=Tillegg ble ikke funnet
PluginToadlet.returnToPluginsWithLinks=Vennligst ${link}returner${/link} til
listen over tillegg.
PluginToadlet.visit=Vis
+PproxyToadlet.classNameTitle=Klassenavn
PproxyToadlet.internalIDTitle=Intern ID
+PproxyToadlet.noPlugins=Ingen tillegg lastet
+PproxyToadlet.plugins=Tillegg
+PproxyToadlet.reload=Last p? nytt
PproxyToadlet.startedAtTitle=Startet
+QueueToadlet.DinProgress=P?begynte nedlastinger
+QueueToadlet.UinProgress=P?begynte opplastinger
+QueueToadlet.change=Endre
QueueToadlet.completedDinDownloadDirectory=Fullf?rt: Nedlastinger til
nedlastingsmappen (${size})
+QueueToadlet.completedU=Fullf?rt: Opplastinger (${size})
QueueToadlet.delete=Slett
+QueueToadlet.download=Last ned
QueueToadlet.errorDToDisk=Kan ikke laste ned til disk
QueueToadlet.errorNoFileOrCannotRead=Filen finnes ikke eller kan ikke leses
+QueueToadlet.errorNoFileSelected=Ingen fil valgt
+QueueToadlet.errorNoFileSelectedU=Du valgte ingen fil for opplasting.
QueueToadlet.errorNoKey=Ingen n?kkel ble spesifisert for nedlasting
QueueToadlet.errorNoKeyToD=Du spesifiserte ingen n?kkel ? laste ned.
QueueToadlet.failedD=Mislykkede nedlastinger
+QueueToadlet.failedToRemove=Kunne ikke fjerne ${id}: ${message}
+QueueToadlet.failedToRemoveId=Kunne ikke fjerne: ${id}
+QueueToadlet.failedToRemoveRequest=Kunne ikke fjerne foresp?rselen
QueueToadlet.failedU=Mislykkede opplastinger
QueueToadlet.fileName=Filnavn
QueueToadlet.files=Filer
+QueueToadlet.follow=F?lg Omdirigeringer
+QueueToadlet.insertAs=Sett inn som:
+QueueToadlet.insertFile=Sett inn fil
QueueToadlet.key=N?kkel
QueueToadlet.legend=Forklaring
QueueToadlet.mimeType=MIME Type
QueueToadlet.none=ingen
QueueToadlet.panicButton=Panikk knapp
QueueToadlet.panicButtonConfirmation=Slett alt uten bekreftelse!
+QueueToadlet.persistence=Varighet
+QueueToadlet.persistenceForever=for evig
QueueToadlet.persistenceNone=ingen
+QueueToadlet.pleaseEnableFCP=Du m? aktivere FCP serveren for ? f? tilgang til
denne siden
QueueToadlet.priority=Prioritet
QueueToadlet.priority0=krise
QueueToadlet.priority1=veldig h?y
@@ -436,12 +536,21 @@
QueueToadlet.priority3=medium
QueueToadlet.priority4=lav
QueueToadlet.priority5=veldig lav
+QueueToadlet.priority6=blir aldri ferdig
+QueueToadlet.progress=Fremgang
+QueueToadlet.progressbarAccurate=Denne fremgangsverdien er n?yaktig
+QueueToadlet.reason=Grunn
+QueueToadlet.remove=Fjern
QueueToadlet.restart=Start p? nytt
QueueToadlet.size=St?rrelse
+QueueToadlet.starting=STARTER
+QueueToadlet.title=Global k? for ${nodeName}
QueueToadlet.totalSize=Total St?rrelse
QueueToadlet.unknown=Ukjent
QueueToadlet.warningUnsafeContent=Potensielt Farlig Innhold
QueueToadlet.warningUnsafeContentExplanation=Filen du vil laste ned kan ikke
filtrert av Freenets innholdsfilter! Det betyr at anonymiteten din kan bli
kompromittert ved ? ?pne filen!
+QueueToadlet.wipD=P?g?ende: Nedlastinger (${size})
+QueueToadlet.wipU=P?g?ende: Opplastinger (${size})
RevocationKeyFoundUserAlert.text=Noden din har funnet auto-oppdateringens
revokasjons n?kkel p? nettverket. Det betyr at auto-oppdateringssystemet
sannsynligvis har blitt KOMPROMITTERT! Derfor har det blitt deaktivert p? noden
din for ? forhindre at "onde ting" blir installert. Vi anbefaler sterkt at du
bes?ker prosjektets webside for oppdateringer. Vennligst verifiser at websiden
ikke har blitt erstattet. Revokasjonsmeldingen er den f?lgende: ${message}.
RevocationKeyFoundUserAlert.title=Prosjektets private n?kkel har blitt
kompromittert!
ShortOption.parseError=Kan ikke tolke verdien som en streng-tabell: ${error}
@@ -451,6 +560,7 @@
SimpleToadletServer.cssName=CSS Navn
SimpleToadletServer.cssNameLong=Navn p? CSSen FProxy skal bruke
SimpleToadletServer.cssOverrideCantRead=Vi kan ikke lese den gitte CSS-filen:
${filename}
+SimpleToadletServer.enabled=Aktiver FProxy?
SimpleToadletServer.illegalCSSName=CSS navnet kan ikke inneholde skr?streker
eller kolon!
SimpleToadletServer.panicButton=Vis panikknappen?
SimpleToadletServer.panicButtonLong=Skal panikknappen vises p? /queue/ siden.
@@ -463,9 +573,11 @@
StatisticsToadlet.allocMemory=Allokert Java minne: ${memory}
StatisticsToadlet.bandwidthTitle=B?ndbredde
StatisticsToadlet.cpus=Tilgjengelige CPUer: ${count}
+StatisticsToadlet.getLogs=Vis nodens siste loggfil
StatisticsToadlet.inputRate=Inndata fart: ${rate}/sekund (av ${max}/sekund)
StatisticsToadlet.jeDumpButton=Generer en JE Dump
StatisticsToadlet.jvmInfoTitle=JVM Info
+StatisticsToadlet.jvmVendor=JVM produsent: ${vendor}
StatisticsToadlet.jvmVersion=JVM Versjon: ${version}
StatisticsToadlet.maxMemory=Maksimum Java minne: ${memory}
StatisticsToadlet.noRequests=Noden din behandler ingen foresp?rsler akkurat n?.
@@ -473,12 +585,19 @@
StatisticsToadlet.osName=OS Navn: ${name}
StatisticsToadlet.osVersion=OS Versjon: ${version}
StatisticsToadlet.outputRate=Utdata fart: ${rate}/sekund (av ${max}/sekund)
+StatisticsToadlet.peerStatsTitle=Tilkoblingsstatistikk
+StatisticsToadlet.threadDumpButton=Generer en Tr?d Dump
StatisticsToadlet.threads=Kj?rende tr?der: ${running}/${max}
StatisticsToadlet.totalInput=Inndate totalt: ${total} (${rate}/sekund)
StatisticsToadlet.totalOutput=Utdata totalt: ${total} (${rate}/sekund)
StatisticsToadlet.usedMemory=Brukt Java minne: ${memory}
StatisticsToadlet.versionTitle=Node Versjonsinformasjon
SymlinkerToadlet.symlinksLong=En liste over "alias#target" som danner en
gruppe lenker
+TestnetHandler.cannotEnableDisableOnTheFly=Det er ikke mulig ?
aktivere/deaktivere testnet-modus mens noden er p?; restart noden og skaff nye
tilkoblinger
+TestnetHandler.enable=Aktiver testnet-modus? (FARLIG)
+TestnetHandler.enableLong=Skal testnet-modus aktiveres (FARLIG!)?
Testnet-modus eliminerer annonymiteten i bytte mot ? hjelpe utviklerne i ?
feils?ke noden.
+TestnetHandler.port=Testnet port
+TestnetHandler.portLong=Testnet port nummer (-1 = lyttePort+1000)
TextModeClientInterfaceServer.enabled=Aktiver TMCI
TextModeClientInterfaceServer.enabledLong=Skal TMCI aktiveres
TextModeClientInterfaceServer.telnetPortNumber=Telnet port
@@ -488,6 +607,7 @@
Toadlet.homepage=Hjemmeside
Toadlet.internalErrorPleaseReport=Intern feil: vennligst rapporter
Toadlet.internalErrorTitle=Intern Feil
+Toadlet.no=Nei
Toadlet.nodeHomepage=Nodens Hjemmeside
Toadlet.notSupportedTitle=Ikke St?ttet
Toadlet.notSupportedWithClass=Nettleseren din sendte en foresp?rsel Freenet
(${class}) ikke forst?r.
@@ -496,6 +616,7 @@
Toadlet.returnToPrevPage=Returner til den forrige siden
Toadlet.tempRedirectWithReason=Midlertidig omdirigering: ${reason}
Toadlet.unauthorized=Du er ikke lov til ? vise denne siden.
+Toadlet.yes=Ja
ToadletContextImpl.cannotParseContentLength=Tolkningsfeil i innholdslengde:
${error}
ToadletContextImpl.methodNotAllowed=HTTP Method er ikke Lovlig
ToadletContextImpl.noContentLengthInPOST=Ingen innholdslengde i POST
@@ -523,9 +644,12 @@
TranslationToadlet.updateTranslationCommand=Oppdater oversettelsen!
UnknownContentTypeException.explanation=Freenet noden din vet ingen ting om
denne MIME typen. Det betyr at nettleseren din kan gj?re noe farlig som respons
til nedlasting av denne filen. For eksempel inneholder mange formater innlagte
bilder eller videoer, som lastes ned fra internett; dette er p? ingen m?te
ufarlig, ettersom det kan ?delegge anonymiteten din og vise IP adressen (hvis
en angriper har kontroll over websiden eller har tilgang til loggene). Linker
til internett kan ogs? v?re en trussel, av samme grunn, og det samme gjelder
makroer, av disse og andre grunner.
UnknownContentTypeException.title=Ukjent og potensielt farlig filtype: ${type}
+UpdateDeployContext.cannotUpdateNoExtJar=Fant ikke freenet-ext.jar i
wrapper.conf (fant freenet.jar: ${mainFilename})
+UpdateDeployContext.cannotUpdateNoJars=Fant ingen av Freenet sine jar-filer i
wrapper.conf
UpdateDeployContext.cannotUpdateNoMainJar=Kunne ikke finne freenet.jar i
wrapper.conf (fant freenet-ext.jar: ${extFilename})
UpdateDeployContext.updateCatastrophe=KATASTROFAL FEIL: Slettet ${old}, men
kan ikke bytte navn fra ${new} til ${old}, derfor VIL IKKE NODEN STARTE!
Vennligst l?s problemet ved ? endre navnet p? ${new} til ${old} manuelt.
UpdateDeployContext.updateFailedCannotDeleteOldConfig=Kan ikke slette ${old}
s? kan ikke bytte navn til den. Oppdatering mislyktes.
+UpdateDeployContext.updateFailedNonStandardConfig=Kunne ikke oppdatere p?
grunn av ikke-standard konfigurasjon: skrev main=${main} ext=${ext} - dette b?r
ikke skje! Rapporter dette til utviklerne og inkluder din wrapper.conf.
UpdatedVersionAvailableUserAlert.alsoDownloadedNewExtJar=Noden din har ogs?
lastet ned en ny versjon av Freenet extra jar, versjon ${version}
UpdatedVersionAvailableUserAlert.armed=Noden din vil automatisk starte p? nytt
etter den har fullf?rt nedlastingen og verifikasjonen av den nye versjonen av
Freenet.
UpdatedVersionAvailableUserAlert.clickToUpdateASAP=Klikk under for ? oppdatere
noden s? fort oppdateringen har blitt verifisert.
@@ -541,7 +665,9 @@
UpdatedVersionAvailableUserAlert.updateASAPButton=Oppdater ASAP
UpdatedVersionAvailableUserAlert.updateASAPQuestion=Vil du at noden automatisk
skal starte p? nytt s? fort den har lastet ned oppdateringen?
UpdatedVersionAvailableUserAlert.updateNowButton=Oppdater N?!
+UserAlert.apply=Bruk
UserAlert.hide=Skjul
+UserAlert.reset=Tilbakestill
UserAlertManager.alertsOnHomepage=| Se dem p? ${link}Freenet
hjemmesiden${/link}.
UserAlertManager.alertsTitle=Gjenst?ende advarsler
UserAlertManager.criticalErrorCountLabel=Kritiske feil:
Modified: branches/freenet-jfk/src/freenet/l10n/freenet.l10n.se.properties
===================================================================
--- branches/freenet-jfk/src/freenet/l10n/freenet.l10n.se.properties
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/l10n/freenet.l10n.se.properties
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,9 +1,9 @@
BookmarkEditorToadlet.addBookmark=L?gg till bokm?rke
BookmarkEditorToadlet.addCategory=L?gg till kategori
+BookmarkEditorToadlet.addNewBookmark=L?gg till bokm?rke
+BookmarkEditorToadlet.addNewCategory=L?gg till en kategori
BookmarkEditorToadlet.addedNewBookmark=Bokm?rket sparades.
BookmarkEditorToadlet.addedNewBookmarkTitle=Bokm?rke sparat
-BookmarkEditorToadlet.addNewBookmark=L?gg till bokm?rke
-BookmarkEditorToadlet.addNewCategory=L?gg till en kategori
BookmarkEditorToadlet.bookmarkDoesNotExist="${bookmark}" finns inte.
BookmarkEditorToadlet.cancelCut=Avbryt klipp ut
BookmarkEditorToadlet.cancelDelete=Avbryt
@@ -11,11 +11,11 @@
BookmarkEditorToadlet.changesSavedTitle=?ndringar sparade
BookmarkEditorToadlet.confirmDelete=Radera
BookmarkEditorToadlet.cut=Klipp ut
+BookmarkEditorToadlet.delete=Radera
+BookmarkEditorToadlet.deleteBookmark=Radera bokm?rke
BookmarkEditorToadlet.deleteBookmarkConfirm=Vill du verkligen radera
${bookmark}?
-BookmarkEditorToadlet.deleteBookmark=Radera bokm?rke
+BookmarkEditorToadlet.deleteCategory=Radera kategori
BookmarkEditorToadlet.deleteCategoryConfirm=?r det s?kert att du vill radera
${bookmark} och l?nkarna inuti?
-BookmarkEditorToadlet.deleteCategory=Radera kategori
-BookmarkEditorToadlet.delete=Radera
BookmarkEditorToadlet.deleteSucceeded=Bokm?rket har raderats.
BookmarkEditorToadlet.deleteSucceededTitle=Raderat
BookmarkEditorToadlet.edit=?ndra
@@ -40,6 +40,8 @@
BookmarkManager.list=Bokm?rken
BookmarkManager.listLong=En lista med dina bokm?rken.
BuildOldAgeUserAlert.tooOldTitle=F?r gammal version
+CSSTokenizerFilter.deletedUnofficialIdentWithURL=Raderade inofficiell
identitet med url
+CSSTokenizerFilter.unknownAtIdentifierLabel=Ok?nd @identifierare:
ConfigToadlet.appliedFailureExceptions=Inst?llningarna ?ndrades med f?ljande
undantag:
ConfigToadlet.appliedFailureTitle=Inst?llningarna kan inte till?mpas
ConfigToadlet.appliedSuccess=?ndringarna sparades.
@@ -66,6 +68,7 @@
ContentFilter.imageGifReadAdvice=GIF bild - antagligen inte farligt
ContentFilter.imageGifWriteAdvice=GIF bild - antagligen inte farligt men du
b?r radera eventuella kommentarer i filen
ContentFilter.imageIcoReadAdvice=Ikon fil - antagligen inte farligt
+ContentFilter.imageIcoWriteAdvice=Ikon fil - antagligen inte farlig (kanske
kan ineh?lla annan data?)
ContentFilter.imageJpegReadAdvice=JPEG bild - antagligen inte farligt
ContentFilter.imageJpegWriteAdvice=JPEG bild - antagligen inte farligt men kan
ineh?lla EXIF data
ContentFilter.imagePngReadAdvice=PNG bild - antagligen inte farligt
@@ -74,19 +77,18 @@
ContentFilter.textHtmlWriteAdvice=HTML - kan ineh?lla farlig metadata o.s.v.;
kontrollera filen i en textl?sare f?r s?kerhets skull.
ContentFilter.textPlainReadAdvice=Vanlig text - inte farligt s?vida du inte
anv?nder en farlig browser (Internet Explorer)
ContentFilter.textPlainWriteAdvice=Ren text - inte farligt s?vida filen inte
ineh?ller personlig information
-CSSTokenizerFilter.deletedUnofficialIdentWithURL=Raderade inofficiell
identitet med url
DarknetConnectionsToadlet.activityTitle=Nuvarande aktivitet
DarknetConnectionsToadlet.add=L?gg till
DarknetConnectionsToadlet.addPeerTitle=L?gg till en nod
DarknetConnectionsToadlet.alreadyInReferences=Referensen finns redan.
DarknetConnectionsToadlet.backedOff=Ansluten men upptagen: Vi skickar inga
f?rfr?gningar till en upptagen nod.
DarknetConnectionsToadlet.backedOffShort=Upptagen
+DarknetConnectionsToadlet.busy=Upptagna: Dessa noder ?r anslutna men upptagna
s? d?rf?r skckar vi inga f?rfr?gningar till dem.
DarknetConnectionsToadlet.busyShort=Upptagen
-DarknetConnectionsToadlet.busy=Upptagna: Dessa noder ?r anslutna men upptagna
s? d?rf?r skckar vi inga f?rfr?gningar till dem.
DarknetConnectionsToadlet.cancel=Avbryt
DarknetConnectionsToadlet.cantFetchNoderefURL=Kunde inte h?mta referens fr?n
${url}. F?rs?k igen.
DarknetConnectionsToadlet.cantParseTryAgain=Kunde inte anv?nda texten som nod
referens: (${error}). F?rs?k igen.
-DarknetConnectionsToadlet.confirmRemoveNode=?r du s?ker p? att du vill ta bort
"+peerNodes[i].getName()+" ? Innan den har minst en veckas netid, ?r det inte
rekommenderat att g?ra s? d? anv?ndaren kan komma tillbaka.
+DarknetConnectionsToadlet.confirmRemoveNode=?r du s?ker p? att du vill ta bort
"${name}"? Innan noden har haft minst en veckas nedtid s? ?r det inte
rekommenderat att ta bort den d? anv?ndaren kanska bara ?r tillf?lligt inaktiv,
v?nta g?rna n?gra dagar till innan du tar bort den.
DarknetConnectionsToadlet.confirmRemoveNodeTitle=Godk?nn
DarknetConnectionsToadlet.confirmRemoveNodeWarningTitle=Nod borttagning
DarknetConnectionsToadlet.connected=Anslutna: Noder som tar emot f?rfr?gningar.
@@ -111,31 +113,31 @@
DarknetConnectionsToadlet.invalidSignature=Kan inte verifiera signaturen p?
referensen (${error}).
DarknetConnectionsToadlet.ipAddress=Nodens IP:Port
DarknetConnectionsToadlet.ipAddressTitle=Adress
-DarknetConnectionsToadlet.listeningShort=Lyssnar
DarknetConnectionsToadlet.listenOnly=Inte ansluten och lyssnar endast: Vi
kommer inte f?rs?ka kontakta den h?r noden d? inst?llningarna endast medger att
vi lyssnar.
DarknetConnectionsToadlet.listenOnlyShort=Lyssna endast
+DarknetConnectionsToadlet.listeningShort=Lyssnar
DarknetConnectionsToadlet.myFriends=V?nner
DarknetConnectionsToadlet.myReferenceHeader=${linkref}Denna nods
referens${/linkref} (${linktext}som text${/linktext})
DarknetConnectionsToadlet.nameClickToMessage=Nodens namn. Klicka p? namnet f?r
att skicka N2NTM (Nod till nod text meddelanden)
DarknetConnectionsToadlet.nameTitle=Namn
DarknetConnectionsToadlet.neverConnected=Aldrig ansluten: Den h?r noden har
aldrig varit ansluten.
DarknetConnectionsToadlet.neverConnectedShort=Aldrig ansluten
-DarknetConnectionsToadlet.nodeHomepage=nod hemsida
-DarknetConnectionsToadlet.nodePortsTitle=Portar som noden anv?nder
DarknetConnectionsToadlet.noPeersFirstHalf=Freenet kan inte fungera ?nnu d? du
inte lagt till n?gra noder ?nnu. V?nligen g? till
DarknetConnectionsToadlet.noPeersSecondHalf=och l?s informationen.
DarknetConnectionsToadlet.noRefOrURL=Kunde inte hitta en nod referens eller
URL. F?rs?k igen.
DarknetConnectionsToadlet.noRequests=Noden hanterar inga f?rfr?gningar just nu.
+DarknetConnectionsToadlet.nodeHomepage=nod hemsida
+DarknetConnectionsToadlet.nodePortsTitle=Portar som noden anv?nder
DarknetConnectionsToadlet.notConnected=Inte ansluten: Ingen anslutning ?nnu,
forts?tter att f?rs?ka.
DarknetConnectionsToadlet.notConnectedShort=Icke ansluten
DarknetConnectionsToadlet.pasteReference=Klistra in referens h?r:
DarknetConnectionsToadlet.privateNoteTitle=Beskrivning
-DarknetConnectionsToadlet.referenceCopyWarning=Nod referens, M?ste kopieras
${bold}som den ?r${/bold}. ?ndringar kommer att g?ra den
${bold}oanv?ndbar${/bold}.
-DarknetConnectionsToadlet.removePeers=Ta bort markerad nod
+DarknetConnectionsToadlet.referenceCopyWarning=Nod referensen m?ste kopieras
${bold}som den ?r${/bold}. ?ndringar kommer att g?ra den
${bold}oanv?ndbar${/bold}.
DarknetConnectionsToadlet.remove=Ta bort
+DarknetConnectionsToadlet.removePeers=Ta bort markerad(e) nod(er)
DarknetConnectionsToadlet.selectAction=-- V?lj ?tg?rd --
DarknetConnectionsToadlet.sendMessageTitle=Skicka nod till nod text meddelande
-DarknetConnectionsToadlet.sendMessageToPeers=Skicka N2NTM till markerade noder
+DarknetConnectionsToadlet.sendMessageToPeers=Skicka N2NTM till markerad(e)
nod(er)
DarknetConnectionsToadlet.separator=-- -- --
DarknetConnectionsToadlet.statusTitle=Status
DarknetConnectionsToadlet.tmciDisabled=TMCI ?r avst?ngd! (simple telnet-based
command-line interface)
@@ -147,44 +149,10 @@
DarknetConnectionsToadlet.triedToAddSelf=Du kan inte l?gga till din egen nod.
DarknetConnectionsToadlet.unauthorized=Du har inte r?ttigheter att bes?ka den
h?r sidan.
DarknetConnectionsToadlet.unknownAddress=(ok?nd adress)
-DarknetConnectionsToadlet.updateChangedPrivnotes=Updatera ?ndrade nod
beskrivningar
+DarknetConnectionsToadlet.updateChangedPrivnotes=Uppdatera beskrivning(ar) p?
markerad(e) nod(er)
DarknetConnectionsToadlet.urlReference=URL till referens:
DarknetConnectionsToadlet.versionTitle=Version
ExtOldAgeUserAlert.extTooOldTitle=Freenet-ext ?r f?r gammal
-FcpServer.allowedHostsFullAccessLong=IP adresser med full FCP tillg?ng till
noden. Klienter med dessa IP nummer kan starta om noden, ?ndra inst?llningar,
m.m. Notera att ALLA klienter har tillg?ng till direct disk I/O!
-FcpServer.allowedHostsFullAccess=V?rdar med full tillg?ng till FCP
-FcpServer.allowedHostsLong=IP addresser som f?r ansluta till FCP. Kan vara en
komma separerad lista med IP nummer och ?ven CIDR maskerade IP;n som
192.168.0.0/24. Varning! Alla med tillg?ng till FCP kan ladda upp och ner filer
(noden f?rs?ker dock att inte skriva ?ver existerande filer).
-FcpServer.allowedHosts=Till?tna v?rddatorer (l?s varningen!)
-FcpServer.bindTo=IP adress att knyta till
-FcpServer.bindToLong=IP adress att knyta FCP till
-FcpServer.cannotStartOrStopOnTheFly=FCP kan inte startas eller stoppas n?r
Freenet k?rs
-FcpServer.downloadsFileCanCreateCannotReadOrWrite=Filen skapades men kan inte
l?sas eller skrivas
-FcpServer.downloadsFileDoesNotExistCannotCreate=Filen existerar redan och kan
d?rf?r inte skapas
-FcpServer.downloadsFileExistsCannotReadOrWrite=Filen existerar men kan inte
l?sas eller skrivas
-FcpServer.downloadsFileUnreadable=Filen finns men kan inte l?sas
-FcpServer.enablePersistentDownload=Aktivera ?terupptagningsbara nedladdningar?
-FcpServer.enablePersistentDownloadLong=Denna inst?llning g?r s? att du kan
?teruppta en nedladdning efter omstart av Freenet. F?r att detta ska vara
m?jligt kr?vs att nedladdningarna skrivs till disk vilket kan inneb?ra en fara
f?r vissa.
-FcpServer.filenameToStorePData=Fil d?r ?terupptagningsbara nedladdningar sparas
-FcpServer.filenameToStorePDataLong=Fil d?r information om ?terupptagningsbara
nedladdningar sparas
-FcpServer.intervalBetweenWrites=Intervall mellan skrivning av information om
?terupptagningsbara nedladdningar
-FcpServer.intervalBetweenWritesLong=Intervall mellan skrivning av information
om ?terupptagningsbara nedladdningar (M?ts i milliseknder)
-FcpServer.isEnabled=Aktivera FCP?
-FcpServer.isEnabledLong=FCP (Freenet Client Protocol) anv?nds av externa
program s?som Frost, Thaw och FreeMulET.
-FcpServer.portNumber=FCP port
-FcpServer.portNumberLong=FCP port nummer.
-FetchException.longError.10=Filen kunde inte hittas i arkivet
-FetchException.longError.13=Datan kunde inte hittas
-FetchException.longError.20=Felaktig URI
-FetchException.longError.21=F?r stor
-FetchException.longError.22=Metadatan ?r f?r stor
-FetchException.longError.23=F?r m?nga block per segment
-FetchException.longError.25=Avbruten
-FetchException.shortError.17=Internt fel
-FetchException.shortError.18=?verf?ringen misslyckades
-FetchException.shortError.20=Felaktig URI
-FetchException.shortError.23=F?r m?nga block per segment
-FetchException.shortError.28=All data kunde inte hittas
-FetchException.shortError.4=Felaktig metadata
FProxyToadlet.abortToHomepage=Avbryt och ?terv?nd till FProxys hemsida
FProxyToadlet.backToFProxy=${link}Klicka h?r${/link} f?r att g? till FProxys
hemsida.
FProxyToadlet.backToReferrer=${link}Klicka h?r${/link} f?r att g? tillbaka.
@@ -194,8 +162,8 @@
FProxyToadlet.dangerousContentTitle=Potentiellt farligt ineh?ll
FProxyToadlet.dangerousRSSSubtitle=RSS fl?de kan vara farligt
FProxyToadlet.dangerousRSSTitle=Potentiellt farligt ineh?ll (RSS)
-FproxyToadlet.dangerousRSSTitle=Potentionellt farligt ineh?ll (RSS)
FProxyToadlet.downloadInBackgroundToDisk=Ladda ner i bakgrunden och spara i
downloads mappen
+FProxyToadlet.errorIsFatal=Det h?r ?r ett fatalt fel. Det ?r osannolikt att
ett nytt f?rs?k kommer l?sa problemet.
FProxyToadlet.errorWithReason=Fel: ${error}
FProxyToadlet.expectedKeyButGot=Noden f?rv?ntade sig en Freenet nyckel, men
fick :
FProxyToadlet.explanationTitle=F?rklaring
@@ -212,14 +180,14 @@
FProxyToadlet.internalErrorTitle=Internt fel
FProxyToadlet.invalidKeyTitle=Ogiltig nyckel
FProxyToadlet.invalidKeyWithReason=Ogiltig nyckel: ${reason}
+FProxyToadlet.largeFile=Stor fil
FProxyToadlet.largeFileExplanationAndOptions=Freenet nyckeln du efterfr?gar ?r
en stor fil. Filer i den h?r storleken kan oftast inte skickas direkt till din
webbl?sare d? det tar f?r l?nge f?r Freenet att h?mta dem. F?ljande val finns:
-FProxyToadlet.largeFile=Stor fil
FProxyToadlet.mimeType=MIME typ: ${mime}
FProxyToadlet.notEnoughMetaStrings=Inte tillr?ckligt med meta-str?ngar
FProxyToadlet.notFoundTitle=Ej hittad
FProxyToadlet.openAsText=${link}Klicka h?r${/link} f?r att ?ppna filen som
text (Ska inte vara farligt men ineh?llet kan visas felaktigt).
+FProxyToadlet.openForce=${link}Klicka h?r${/link} f?r att ?ppna filen som
${mime} (L?s varningen ovan!).
FProxyToadlet.openForceDisk=${link}Klicka h?r${/link} f?r att ladda ner filen
med webbl?saren.
-FProxyToadlet.openForce=${link}Klicka h?r${/link} f?r att ?ppna filen som
${mime} (L?s varningen ovan!).
FProxyToadlet.openPossRSSAsForceDisk=${link}Klicka h?r${/link} f?r att tvinga
webbl?saren att ladda ner filen (detta kan vara ${bold}farligt${/bold} om du
anv?nder Firefox 2.0.0, i 2.0.1 ska problmet vara l?st)
FProxyToadlet.openPossRSSAsPlainText=${link}Klicka h?r${/link} f?r att ?ppna
filen som ren text (Detta kan vara ${bold}farligt${/bold} om du anv?nder IE7
eller FF2).
FProxyToadlet.openRSSAsRSS=${link}Klicka h?r${/link} f?r att ?ppna filen som
RSS (detta ?r ${bold}farligt${/bold} ifall upphovsmannen ?r ondsint d? Freenet
inte filtrerar RSS ?nnu).
@@ -229,30 +197,88 @@
FProxyToadlet.pathNotFoundTitle=S?kv?g ej funnen
FProxyToadlet.plugins=Konfigurera och hantera plugins
FProxyToadlet.pluginsTitle=Plugins
+FProxyToadlet.queue=Upp / nedladdningar
FProxyToadlet.queueTitle=K?
-FProxyToadlet.queue=Upp / nedladdningar
FProxyToadlet.retryNow=F?rs?k igen
FProxyToadlet.sizeLabel=Storlek:
FProxyToadlet.sizeUnknown=Storlek: ok?nd
FProxyToadlet.stats=Se statistik
FProxyToadlet.statsTitle=Statistik
+FProxyToadlet.translation=Verktyg f?r att ?vers?tta nodens gr?nssnitt till
ditt eget spr?k
FProxyToadlet.translationTitle=?vers?ttning
-FProxyToadlet.translation=Verktyg f?r att ?vers?tta nodens gr?nssnitt till
ditt eget spr?k
FProxyToadlet.unableToRetrieve=Freenet kunde inte h?mta filen.
FProxyToadlet.unknownMIMEType=MIME typ: ok?nd
FProxyToadlet.welcome=Hemsida
FProxyToadlet.welcomeTitle=Hem
+FcpServer.allowedHosts=Till?tna v?rddatorer (l?s varningen!)
+FcpServer.allowedHostsFullAccess=V?rdar med full tillg?ng till FCP
+FcpServer.allowedHostsFullAccessLong=IP adresser med full FCP tillg?ng till
noden. Klienter med dessa IP nummer kan starta om noden, ?ndra inst?llningar,
m.m. Notera att ALLA klienter har tillg?ng till direct disk I/O!
+FcpServer.allowedHostsLong=IP addresser som f?r ansluta till FCP. Kan vara en
komma separerad lista med IP nummer och ?ven CIDR maskerade IP;n som
192.168.0.0/24. Varning! Alla med tillg?ng till FCP kan ladda upp och ner filer
(noden f?rs?ker dock att inte skriva ?ver existerande filer).
+FcpServer.bindTo=IP adress att knyta till
+FcpServer.bindToLong=IP adress att knyta FCP till
+FcpServer.cannotStartOrStopOnTheFly=FCP kan inte startas eller stoppas n?r
Freenet k?rs
+FcpServer.downloadsFileCanCreateCannotReadOrWrite=Filen skapades men kan inte
l?sas eller skrivas
+FcpServer.downloadsFileDoesNotExistCannotCreate=Filen existerar redan och kan
d?rf?r inte skapas
+FcpServer.downloadsFileExistsCannotReadOrWrite=Filen existerar men kan inte
l?sas eller skrivas
+FcpServer.downloadsFileUnreadable=Filen finns men kan inte l?sas
+FcpServer.enablePersistentDownload=Aktivera ?terupptagningsbara nedladdningar?
+FcpServer.enablePersistentDownloadLong=Denna inst?llning g?r s? att du kan
?teruppta en nedladdning efter omstart av Freenet. F?r att detta ska vara
m?jligt kr?vs att nedladdningarna skrivs till disk vilket kan inneb?ra en fara
f?r vissa.
+FcpServer.filenameToStorePData=Fil d?r ?terupptagningsbara nedladdningar sparas
+FcpServer.filenameToStorePDataLong=Fil d?r information om ?terupptagningsbara
nedladdningar sparas
+FcpServer.intervalBetweenWrites=Intervall mellan skrivning av information om
?terupptagningsbara nedladdningar
+FcpServer.intervalBetweenWritesLong=Intervall mellan skrivning av information
om ?terupptagningsbara nedladdningar (M?ts i milliseknder)
+FcpServer.isEnabled=Aktivera FCP?
+FcpServer.isEnabledLong=FCP (Freenet Client Protocol) anv?nds av externa
program s?som Frost, Thaw och FreeMulET.
+FcpServer.portNumber=FCP port
+FcpServer.portNumberLong=FCP port nummer.
+FetchException.longError.10=Filen kunde inte hittas i arkivet
+FetchException.longError.13=Datan kunde inte hittas
+FetchException.longError.15=En nod var ?verbelastad eller tog f?r l?ng tid p?
sig
+FetchException.longError.17=Internt fel, antagligen en bugg
+FetchException.longError.20=Felaktig URI
+FetchException.longError.21=F?r stor
+FetchException.longError.22=Metadatan ?r f?r stor
+FetchException.longError.23=F?r m?nga block per segment
+FetchException.longError.25=Avbruten
+FetchException.shortError.13=Datan kunde inte hittas
+FetchException.shortError.17=Internt fel
+FetchException.shortError.18=?verf?ringen misslyckades
+FetchException.shortError.20=Felaktig URI
+FetchException.shortError.23=F?r m?nga block per segment
+FetchException.shortError.27=Ny URI
+FetchException.shortError.28=All data kunde inte hittas
+FetchException.shortError.4=Felaktig metadata
+FileOffer.acceptTransferButton=Acceptera ?verf?ring
+FileOffer.askUserTitle=Direkt fil?verf?ring
+FileOffer.commentLabel=Kommentar:
+FileOffer.failedReceiveHeader=?verf?ringen av ${filename} fr?n ${node}
misslyckades.
+FileOffer.failedReceiveTitle=Fil?verf?ringen misslyckades
+FileOffer.fileLabel=Fil:
+FileOffer.mimeLabel=MIME Typ:
+FileOffer.offeredFileHeader=${name} f?rs?ker skicka en fil till dig:
+FileOffer.senderLabel=Avs?ndare:
+FileOffer.sizeLabel=Storlek:
+FileOffer.succeededReceiveHeader=?verf?ringen av ${filename} fr?n ${node}
lyckades.
+FirstTimeWizardToadlet.congratz=V?lkommen till Freenet!
+FirstTimeWizardToadlet.noNetworkIF=Inget extra n?tverkskort kunde hittas
+FproxyToadlet.dangerousRSSTitle=Potentionellt farligt ineh?ll (RSS)
+GIFFilter.notGif=Filen du f?rs?ker h?mta ?r inte en GIF. Det kan vara n?got
annat filformat som din webbl?sare kanske hanterar p? ett farligt s?tt s?
d?rf?r har vi blockerat den.
+GIFFilter.tooShort=Filen ?r f?r kort f?r att vara en GIF.
+GIFFilter.tooShortTitle=F?r kort
HTMLFilter.deletedUnknownStyle=Raderade ok?nd stil
+IPUndetectedUserAlert.detecting=Freenet f?rs?ker f?r tillf?llet detektera din
externa IP adress. Om detta tar mer ?n n?gra minuter s? ?r n?got fel.
+IPUndetectedUserAlert.unknownAddressTitle=Ok?nd extern adress
InsertException.longError.10=Avbruten av anv?ndaren
InsertException.longError.3=Internt fel
+InsertException.shortError.1=Felaktig URI
InsertException.shortError.10=Avbruten
-InsertException.shortError.1=Felaktig URI
InsertException.shortError.3=Internt fel
-IPUndetectedUserAlert.detecting=Freenet f?rs?ker f?r tillf?llet detektera din
externa IP adress. Om detta tar mer ?n n?gra minuter s? ?r n?got fel.
-IPUndetectedUserAlert.unknownAddressTitle=Ok?nd extern adress
+JPEGFilter.notJpeg=Filen du f?rs?ker h?mta ?r inte en JPEG. Det kan vara n?got
annat filformat som din webbl?sare kanske hanterar p? ett farligt s?tt s?
d?rf?r har vi blockerat den.
JPEGFilter.tooShort=Filen ?r f?r liten f?r att vara en JPEG bild.
KnownUnsafeContentTypeException.dangerousLinksLabel=Farliga l?nkar:
KnownUnsafeContentTypeException.dangerousMetadataLabel=Farlig metadata:
+KnownUnsafeContentTypeException.dangerousScriptsLabel=Farligt skript:
+KnownUnsafeContentTypeException.noFilter=Eftersom det inte finns n?got inbyggt
filter f?r den h?r typen av data s? b?r du iakta stor f?rsiktighet!
KnownUnsafeContentTypeException.title=Datatypen ?r k?nd f?r att vara farlig:
${type}
LocalFileInsertToadlet.checkPathExist=Kontroller att den angivna s?kv?gen
finns.
LocalFileInsertToadlet.checkPathIsDir=Kontrollera att den angivna s?kv?gen
leder till en mapp.
@@ -264,25 +290,25 @@
LocalFileInsertToadlet.sizeHeader=Storlek
LogConfigHandler.detaildPriorityThreshold=Detaljerad loggningsniv?
LogConfigHandler.detaildPriorityThresholdLong=Detaljerad loggningsniv?,
exempelvis freenet:normal,freenet.node:minor
+LogConfigHandler.dirName=Mapp f?r loggfiler
LogConfigHandler.dirNameLong=Mapp d?r loggfiler sparas
-LogConfigHandler.dirName=Mapp f?r loggfiler
LogConfigHandler.enabled=Aktvera loggning?
LogConfigHandler.enabledLong=Ja aktiverar loggning (Loggnings niv? st?lls in
separat) Nej inaktiverar all loggning.
+LogConfigHandler.maxCachedBytes=Maximal storlek p? loggar i RAM minnet.
LogConfigHandler.maxCachedBytesLong=Maximal storlek p? loggar i Ram minnet
-LogConfigHandler.maxCachedBytes=Maximal storlek p? loggar i RAM minnet.
+LogConfigHandler.maxCachedLines=Maximalt antal loggade linjer i RAM minnet
LogConfigHandler.maxCachedLinesLong=Maximalt antal loggade linjer i RAM minnet
-LogConfigHandler.maxCachedLines=Maximalt antal loggade linjer i RAM minnet
+LogConfigHandler.maxZippedLogsSize=Maximalt utrymme f?r gamla logg filer
LogConfigHandler.maxZippedLogsSizeLong=Maximalt utrymme f?r gamla logg filer
-LogConfigHandler.maxZippedLogsSize=Maximalt utrymme f?r gamla logg filer
LogConfigHandler.minLoggingPriority=Loggningsniv?
LogConfigHandler.minLoggingPriorityLong=Loggningsniv?
+LogConfigHandler.rotationInterval=Tidsintervall f?r logg rotation
LogConfigHandler.rotationIntervalLong=Logg rotations intervall - Tidsintervall
f?r logg rotation. Vi sparar de senaste 2 logg filerna (Nuvarande och
f?reg?ende) ?ldre logg filer komprimeras och sparas. Max disk utrymme f?r
sparade logg filer st?lls in separat.
-LogConfigHandler.rotationInterval=Tidsintervall f?r logg rotation
LoggerHook.unrecognizedPriority=Ok?nd prioritet: ${name}.
MeaningfulNodeNameUserAlert.noNodeNickTitle=Du har inte angett ett namn till
din nod.
N2NTMToadlet.composingMessageLabel=Skriv meddelande som ska skickas till
f?ljande:
+N2NTMToadlet.delayed=Upptagen: S?ndning av meddelande kan vara f?rsenad
N2NTMToadlet.delayedTitle=F?rsenad
-N2NTMToadlet.delayed=Upptagen: S?ndning av meddelande kan vara f?rsenad
N2NTMToadlet.failed=Meddelandet kunde inte skickas: Noden ?r inte ansluten.
N2NTMToadlet.failedTitle=Misslyckades
N2NTMToadlet.friends=V?nner
@@ -295,8 +321,8 @@
N2NTMToadlet.queuedTitle=K?ad
N2NTMToadlet.returnToFriends=?terg? till V?nner
N2NTMToadlet.returnToNodeHomepage=?terv?nd till hemsidan
+N2NTMToadlet.sendMessage=Skicka nod till nod text meddelande
N2NTMToadlet.sendMessageShort=Skicka meddelande
-N2NTMToadlet.sendMessage=Skicka nod till nod text meddelande
N2NTMToadlet.sendStatus=N2NTM s?nd status
N2NTMToadlet.sent=Meddelande skickat till noden
N2NTMToadlet.sentTitle=Skickat
@@ -312,82 +338,90 @@
Node.buggyJVM=JVM;en du anv?nder (${version}) ?r k?nd f?r att vara buggig. Du
kan f? felmeddelanden som s?ger att du har slut p? minne n?r det egentligen
finns rikligt med minne kvar. V?nligen uppgradera till minst Sun Java 1.4.2_13,
1.5.0_10 or 1.6 (rekommenderas). Se
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4855795 .
Node.buggyJVMTitle=Varning f?r buggig JVM
Node.bwlimitMustBePositive=Bandbreddsbegr?nsningen m?ste vara h?gre ?n 0
-NodeClientCore.allowInsecureCHKLong=F?re version 1010 var alla CHKs os?kra
(endast halv kryptering anv?ndes). Vill du till?ta gamla CHKs?
-NodeClientCore.allowInsecureCHK=Till?t os?kra CHKs?
-NodeClientCore.allowInsecureSSKLong=F?re version 1010 var alla SSKs os?kra
(endast halv kryptering anv?ndes). Vill du till?ta gamla SSKs?
-NodeClientCore.allowInsecureSSK=Till?t os?kra SSKs?
-NodeClientCore.couldNotFindOrCreateDir=Kunde inte hitta eller skapa mappen
-NodeClientCore.downloadAllowedDirs=Mapp/ar dit nedladdning ?r till?ten
-NodeClientCore.downloadDirLong=f?rvald nedladdningsmapp
-NodeClientCore.downloadDir=Nedladdningsmapp
-NodeClientCore.fileForClientStats=Fil d?r klient statistik lagras
-NodeClientCore.maxUSKFetchersMustBeGreaterThanZero=V?rdet m?ste vara st?rre ?n
noll
-NodeClientCore.tempDirLong=Mapp f?r tempor?ra filer.
-NodeClientCore.tempDir=Mapp f?r tempor?ra filer
-NodeClientCore.uploadAllowedDirs=Mappar som uppladdning till?ts fr?n
Node.databaseMemory=Max utrymme f?r freenets databas
Node.disableHangCheckers=Avativera alla h?ngningskontroller
Node.errorApplyingConfig=Ett fel uppstod n?r de nya inst?llningarna skulle
anv?ndas : ${error}
+Node.extraPeerDir=mapp till extra peer data
Node.extraPeerDirLong=Mapp f?r extra peer data
-Node.extraPeerDir=mapp till extra peer data
+Node.inBWLimit=Maximal nedladdningshastighet (bytes per sekund)
Node.inBWLimitLong=Maximal nedladningshastighet (bytes per sekund), noden ska
n?stan aldrig ?verskrida detta v?rde, -1 = 4 * inst?lld uppladdningshastighet.
-Node.inBWLimitLong=Maximal nedladningshastighet (bytes per sekund), noden ska
n?stan aldrig ?verskrida detta v?rde, -1 = 4x inst?lld uppladdningshastighet.
-Node.inBWLimit=Maximal nedladdningshastighet (bytes per sekund)
Node.invalidStoreSize=Lagringsutrymmet m?ste vara minst 32MB
-NodeIPDectector.inclLocalAddress=Inkludera lokala adresser i nod-referens?
-NodeIPDectector.tempAddressHintLong=Tempor?r fingervisning om v?r IP adress,
raderas efter anv?ndning.
-NodeIPDectector.tempAddressHint=Tempor?r fingervisning om v?r IP adress
-NodeIPDetector.maybeSymmetricTitle=Anslutnings problem
-NodeIPDetector.unknownHostErrorInIPOverride=Ok?nd v?rd: ${error}
+Node.l10nLanguage=Spr?k
Node.l10nLanguageLong=Den h?r inst?llningen ?ndrar spr?ket i din nods
web-gr?nssnitt. Vissa ?vers?ttningar kan beh?va en omstart f?r att fungera.
-Node.l10nLanguage=Spr?k
Node.maxHTL=Max HTL
Node.mustBePositive=V?rdet m?ste vara positivt
+Node.nodeDir=Nod mapp
Node.nodeDirLong=Mapp d?r nodrelaterade filer sparas.
-Node.nodeDir=Nod mapp
+Node.nodeName=Nodnamn
Node.nodeNameLong=Nodnamn. Synligt endast f?r de noder du ?r ansluten till.
-Node.nodeName=Nodnamn
+Node.outBWLimit=Maximal uppladningshastighet (bytes per sekund)
Node.outBWLimitLong=Maximal uppladningshastighet (bytes per sekund), noden ska
n?stan aldrig ?verskrida detta v?rde.
-Node.outBWLimit=Maximal uppladningshastighet (bytes per sekund)
Node.port=FNP port (UDP)
Node.portLong=UDP port f?r nod-till-nod kommunikation (Freenet Node Protocol)
+Node.storeDirectory=Mapp f?r datalagring
+Node.storeDirectoryLong=Mapp f?r datalagring
+Node.storeMaxMemTooHigh=Att ge mer ?n 80% av ram minnet till BDB (Berkeley
DataBase) ?r antagligen inte vad du vill g?ra!
+Node.storeSize=Max storlek p? Freenets datalagring
+Node.storeSizeLong=Max storlek p? Freenets datalagring, det utrymme i din nod
som anv?nds till freenets datalagring. St?rre data utrymme ?n standard ?r att
f?redra.
+NodeClientCore.allowInsecureCHK=Till?t os?kra CHKs?
+NodeClientCore.allowInsecureCHKLong=F?re version 1010 var alla CHKs os?kra
(endast halv kryptering anv?ndes). Vill du till?ta gamla CHKs?
+NodeClientCore.allowInsecureSSK=Till?t os?kra SSKs?
+NodeClientCore.allowInsecureSSKLong=F?re version 1010 var alla SSKs os?kra
(endast halv kryptering anv?ndes). Vill du till?ta gamla SSKs?
+NodeClientCore.couldNotFindOrCreateDir=Kunde inte hitta eller skapa mappen
+NodeClientCore.downloadAllowedDirs=Mapp/ar dit nedladdning ?r till?ten
+NodeClientCore.downloadDir=Nedladdningsmapp
+NodeClientCore.downloadDirLong=f?rvald nedladdningsmapp
+NodeClientCore.fileForClientStats=Fil d?r klient statistik lagras
+NodeClientCore.maxUSKFetchers=Maximalt antal USK h?mtare
+NodeClientCore.maxUSKFetchersLong=Maximalt antal USK h?mtare
+NodeClientCore.maxUSKFetchersMustBeGreaterThanZero=V?rdet m?ste vara st?rre ?n
noll
+NodeClientCore.movingTempDirOnTheFlyNotSupported=Flytt av temp mappen kan inte
g?ras n?r noden ?r ig?ng
+NodeClientCore.tempDir=Mapp f?r tempor?ra filer
+NodeClientCore.tempDirLong=Mapp f?r tempor?ra filer.
+NodeClientCore.uploadAllowedDirs=Mappar som uppladdning till?ts fr?n
+NodeIPDectector.inclLocalAddress=Inkludera lokala adresser i nod-referens?
+NodeIPDectector.ipOverride=?verskrid IP adress
+NodeIPDectector.ipOverrideLong=?verskridning av IP adress (beh?vs oftast inte)
- Ifall du har en fast IP adress eller ett dom?n namn (t.e.x. via dyndns) kan
du ange den/det h?r ifall du ?r bakom en brandv?gg.
+NodeIPDectector.tempAddressHint=Tempor?r fingervisning om v?r IP adress
+NodeIPDectector.tempAddressHintLong=Tempor?r fingervisning om v?r IP adress,
raderas efter anv?ndning.
+NodeIPDetector.maybeSymmetricTitle=Anslutnings problem
+NodeIPDetector.unknownHostErrorInIPOverride=Ok?nd v?rd: ${error}
NodeStat.aggressiveGC=Aggressiv GC modifikator
NodeStat.aggressiveGCLong=L?ter anv?ndaren ?ndra tiden mellan GC och tvingat
avslut. SKA INTE ?NDRAS om du inte vet vad du g?r! -1 betyder : st?ng av
tvingat anrop till System.gc() och System.runFinalization()
NodeStat.memCheck=Aktivera minneskontrollen
NodeStat.memCheckLong=Aktivera minneskontrollen (Skriver ett meddelande i
logg, N?dv?ndig f?r aggressiv GC modifikator)
-NodeStats.mustBePercentValueNotFull=V?rdet m?ste vara mellan 0-99 (uttrycks i
procent).
NodeStat.statsPersister=Fil d?r nodstatistik lagras
NodeStat.statsPersisterLong=Fil att lagra nod statistik i (klient statistik
lagras inte) Statistiken anv?nds f?r att avg?ra om f?rfr?gningar ska
accepteras, radera INTE denna fil!
+NodeStat.threadLimit=Max antal tr?dar
+NodeStat.threadLimitLong=Noden f?rs?ker att inte ?verskrida max antal tr?dar
genom att v?gra nya anrop.
+NodeStats.mustBePercentValueNotFull=V?rdet m?ste vara mellan 0-99 (uttrycks i
procent).
NodeStats.valueTooLow=V?rdet f?r den h?r inst?llningen ?r f?r l?gt, du m?ste
?ka det!
-NodeStat.threadLimitLong=Noden f?rs?ker att inte ?verskrida max antal tr?dar
genom att v?gra nya anrop.
-NodeStat.threadLimit=Max antal tr?dar
-Node.storeDirectoryLong=Mapp f?r datalagring
-Node.storeDirectory=Mapp f?r datalagring
-Node.storeMaxMemTooHigh=Att ge mer ?n 80% av ram minnet till BDB (Berkeley
DataBase) ?r antagligen inte vad du vill g?ra!
-Node.storeSizeLong=Max storlek p? Freenets datalagring, det utrymme i din nod
som anv?nds till freenets datalagring. St?rre data utrymme ?n standard ?r att
f?redra.
-Node.storeSize=Max storlek p? Freenets datalagring
NodeUpdateManager.enabled=Ladda ner nya versioner automatiskt?
NodeUpdateManager.enabledLong=Ska noden s?ka efter och ladda ner upgraderingar
automatiskt? Den h?r inst?llningen st?ller sig p? false om noden inte k?rs inom
wrappern.
NodeUpdateManager.extURI=Adress d?r noden letar efter uppdateringar till
freenet-ext.jar
NodeUpdateManager.extURILong=Adress d?r noden letar efter uppdateringar till
freenet-ext.jar
NodeUpdateManager.installNewVersions=Installera nya versioner automatiskt?
NodeUpdateManager.installNewVersionsLong=Ska nya Freenet versioner installeras
automatiskt utan att f?rst fr?ga?
+NodeUpdateManager.invalidExtURI=Felaktig ext URI: ${error}
+NodeUpdateManager.invalidUpdateURI=Felaktig uppdaterings URI: ${error}
NodeUpdateManager.noUpdateWithoutWrapper=Kan inte uppdatera eftersom Freenet
inte k?rs med wrappern
+NodeUpdateManager.updateFailed=Uppdateringen misslyckades: ${reason}
NodeUpdateManager.updateFailedTitle=Uppdateringen misslyckades!
-NodeUpdateManager.updateFailed=Uppdateringen misslyckades: ${reason}
NodeUpdateManager.updateURI=Adress d?r noden letar efter uppdateringar
NodeUpdateManager.updateURILong=Adress d?r noden letar efter uppdateringar
+PNGFilter.invalidHeader=Filen du f?rs?ker h?mta ?r inte en PNG. Det kan vara
n?got annat filformat som din webbl?sare kanske hanterar p? ett farligt s?tt s?
d?rf?r har vi blockerat den.
PeerManagerUserAlert.noConnsTitle=Inga ?ppna anslutningar
PeerManagerUserAlert.noPeersTitle=Inga peers hittades
+PeerManagerUserAlert.onlyFewConnsTitle=Endast ${count} ?ppen/?ppna
anslutning(ar)
PeerManagerUserAlert.tooHighPingTimeTitle=Nodens medel ping tid ?r f?r h?g
PeerManagerUserAlert.tooManyConnsTitle=F?r m?nga ?ppna anslutningar
PeerManagerUserAlert.tooManyDisconnectedTitle=F?r m?nga icke anslutna peers
PeerManagerUserAlert.tooManyNeverConnectedTitle=M?nga peers har aldrig anslutit
PeerManagerUserAlert.tooManyPeersTitle=F?r m?nga peers
+PluginManager.loadedOnStartup=Plugins som ska laddas vid uppstart
PluginManager.loadedOnStartupLong=Classpath, namn och s?kv?g till plugins som
ska startas samtidigt som noden.
-PluginManager.loadedOnStartup=Plugins som ska laddas vid uppstart
+PluginManager.loadedPlugins=Plugins som ska laddas vid uppstart
PluginManager.loadedPluginsLong=En lista med plugins som ska startas samtidigt
som noden.
-PluginManager.loadedPlugins=Plugins som ska laddas vid uppstart
PluginManager.pluginReqNewerJVM=Pluginen ${name} verkar kr?va en nyare JVM.
V?nligen installera minst Sun java 1.5, eller ta bort pluginen.
PluginManager.pluginReqNewerJVMTitle=Nyare JVM kr?vs av pluginen ${name}.
PluginToadlet.addPluginTitle=L?gg till plugin
@@ -412,36 +446,37 @@
PproxyToadlet.loadPluginLabel=Plugin att ladda:
PproxyToadlet.noPlugins=Inga plugins laddade
PproxyToadlet.pluginNotFoundReloadTitle=Pluginen kunde inte hittas (laddar om)
+PproxyToadlet.pluginUnloaded=Plugin stoppad
+PproxyToadlet.pluginUnloadedWithName=Pluginen ${name} har stoppats.
PproxyToadlet.plugins=Plugins
PproxyToadlet.pluginsWithNodeName=Plugins f?r ${name}
-PproxyToadlet.pluginUnloaded=Plugin stoppad
-PproxyToadlet.pluginUnloadedWithName=Pluginen ${name} har stoppats.
PproxyToadlet.reload=Starta om
PproxyToadlet.returnToPluginPage=?terg? till plugins sidan
PproxyToadlet.startedAtTitle=Startad vid
+PproxyToadlet.unload=Stoppa
PproxyToadlet.unloadPluginTitle=Stoppa plugin?
PproxyToadlet.unloadPluginWithName=Vill du verkligen stoppa ${name}?
-PproxyToadlet.unload=Stoppa
+QueueToadlet.DUinProgress=P?g?ende mapp uppladdningar
+QueueToadlet.DinProgress=P?g?ende nedladdningar (${size})
+QueueToadlet.UinProgress=P?g?ende uppladdningar (${size})
QueueToadlet.change=?ndra
+QueueToadlet.completedDU=Slutf?rda mapp uppladdningar
QueueToadlet.completedDinDownloadDirectory=Slutf?rda nedladdningar till
download mappen (${size})
QueueToadlet.completedDinTempDirectory=Slutf?rda nedladdningar till tempor?r
mapp (${size})
QueueToadlet.completedDtoDisk=Slutf?rda nedladdningar
QueueToadlet.completedDtoTemp=Slutf?rda nedladdningar till temp
-QueueToadlet.completedDU=Slutf?rda mapp uppladdningar
+QueueToadlet.completedU=Slutf?rda uppladdningar (${size})
QueueToadlet.completedUDirectory=Slutf?rda mapp uppladdningar (${size})
-QueueToadlet.completedU=Slutf?rda uppladdningar (${size})
QueueToadlet.delete=Ta bort
-QueueToadlet.DinProgress=P?g?ende nedladdningar (${size})
QueueToadlet.download=Ladda ner
-QueueToadlet.DUinProgress=P?g?ende mapp uppladdningar
QueueToadlet.emergency=N?dfall
QueueToadlet.errorAccessDenied=Fel: ?tkomst nekad!
QueueToadlet.errorAccessDeniedFile=De nuvarande inst?llningarna medger inte
uppladdning av "${file}".
+QueueToadlet.errorDToDisk=Kan inte ladda ner till h?rddisk
+QueueToadlet.errorDToDiskConfig=Nodens nuvarande inst?llningar till?ter inte
nedladdningar till downloads mappen.
QueueToadlet.errorDownloadNotCompleted=Nedladdning inte slutf?rd
+QueueToadlet.errorDownloadNotFound=Nedladdning inte hittad
QueueToadlet.errorDownloadNotFoundExplanation=Nedladdningen kunde inte hittas.
?r den redan raderad?
-QueueToadlet.errorDownloadNotFound=Nedladdning inte hittad
-QueueToadlet.errorDToDiskConfig=Nodens nuvarande inst?llningar till?ter inte
nedladdningar till downloads mappen.
-QueueToadlet.errorDToDisk=Kan inte ladda ner till h?rddisk
QueueToadlet.errorInvalidURI=Felaktig URI
QueueToadlet.errorInvalidURIToD=URI;n ?r felaktig och kan inte laddas ner.
QueueToadlet.errorInvalidURIToU=Du angav inte en giltig URI att ladda upp
filen med.
@@ -452,8 +487,8 @@
QueueToadlet.errorNoKeyToD=Du angav ingen nyckel.
QueueToadlet.failedD=Misslyckade nedladdningar
QueueToadlet.failedDU=Misslyckad mapp uppladdning
+QueueToadlet.failedToRemove=Misslyckades med att ta bort ${id}: ${message}
QueueToadlet.failedToRemoveId=Kunde inte ta bort: ${id}
-QueueToadlet.failedToRemove=Misslyckades med att ta bort ${id}: ${message}
QueueToadlet.failedToRemoveRequest=Misslyckades med att ta bort f?rfr?gan
QueueToadlet.failedToRestart=Kunde inte starta om: ${id}
QueueToadlet.failedToRestartRequest=Omstart misslyckades
@@ -469,18 +504,18 @@
QueueToadlet.insertFile=Ladda upp fil
QueueToadlet.key=Nyckel
QueueToadlet.legend=Historia
-QueueToadlet.legend=Prioritet
QueueToadlet.low=L?g
QueueToadlet.medium=Medium
QueueToadlet.mimeType=MIME Typ
+QueueToadlet.noTaskOnGlobalQueue=Den globala k?n ?r tom.
QueueToadlet.none=ingen
-QueueToadlet.noTaskOnGlobalQueue=Den globala k?n ?r tom.
+QueueToadlet.panicButton=Panik knapp
QueueToadlet.panicButtonConfirmation=Radera allt utan att fr?ga!\u00a0
-QueueToadlet.panicButton=Panik knapp
QueueToadlet.persistenceForever=F?revigt
QueueToadlet.persistenceNone=ingen
-QueueToadlet.persistenceRebootr=starta om
+QueueToadlet.persistenceReboot=starta om
QueueToadlet.pleaseEnableFCP=Du m?ste aktivera FCP f?r att f? ?tkomst till den
h?r sidan.
+QueueToadlet.priority=Prioritet
QueueToadlet.priority0=n?dfall
QueueToadlet.priority1=v?ldigt h?g
QueueToadlet.priority2=h?g
@@ -488,45 +523,46 @@
QueueToadlet.priority4=l?g
QueueToadlet.priority5=v?ldigt l?g
QueueToadlet.priority6=pause
-QueueToadlet.priority=Prioritet
+QueueToadlet.progress=Nedladdat
QueueToadlet.progressbarAccurate=V?rdet st?mmer
QueueToadlet.progressbarNotAccurate=V?rdet kommer troligen att ?ndras eftersom
nedladdningen inte kommit nog l?ngt
-QueueToadlet.progress=Nedladdat
QueueToadlet.reason=Orsak
+QueueToadlet.remove=Ta bort
QueueToadlet.requestNavigation=Navigation
QueueToadlet.restart=Omstart
QueueToadlet.size=Storlek
QueueToadlet.starting=STARTAR
QueueToadlet.title=Global k? f?r ${nodeName}
QueueToadlet.totalSize=Total storlek
-QueueToadlet.UinProgress=P?g?ende uppladdningar (${size})
QueueToadlet.unknown=Ok?nd
QueueToadlet.veryhigh=V?ldigt h?g
QueueToadlet.verylow=V?ldigt l?g
+QueueToadlet.warningUnsafeContent=Potentionellt farligt ineh?ll
QueueToadlet.warningUnsafeContentExplanation=Filen du vill ladda ner filtreras
inte av Freenet! Din anonymitet kan hotas om du ?ppnar denna fil!
-QueueToadlet.warningUnsafeContent=Potentionellt farligt ineh?ll
QueueToadlet.willneverfinish=Pause
QueueToadlet.wipD=P?g?ende nedladdningar (${size})
QueueToadlet.wipDU=P?g?ende mapp uppladdningar (${size})
QueueToadlet.wipU=P?g?ende uppladdningar (${size})
SimpleToadletServer.advancedMode=Aktivera avancerat l?ge?
SimpleToadletServer.advancedModeLong=Ska information och inst?llningar avsedda
f?r avancerade anv?ndare/utvecklare visas? Denna inst?llning ska normalt vara
avst?ngd.
+SimpleToadletServer.allowedFullAccess=V?rdar med full tillg?ng til Fproxy
(L?s Varning)
SimpleToadletServer.allowedFullAccessLong=V?rdar med full FProxy tillg?ng till
noden, dessa kan starta om noden, ?ndra inst?llningar, m.m.. VARNING: Var
f?rsiktig med vilka du ger full tillg?ng till noden!
-SimpleToadletServer.allowedFullAccess=V?rdar med full tillg?ng til Fproxy
(L?s Varning)
+SimpleToadletServer.allowedHosts=V?rdnamn eller IP addresser som f?r ansluta
till FProxy.
SimpleToadletServer.allowedHostsLong=Kan vara en komma separerad lista med IP
nummer och ?ven CIDR maskerade IP;n som 192.168.0.0/24. Notera att dessa har
tillg?ng till h?rddisken inom ramarna f?r en annan inst?llning.
-SimpleToadletServer.allowedHosts=V?rdnamn eller IP addresser som f?r ansluta
till FProxy.
SimpleToadletServer.bindTo=IP adress att knyta till
SimpleToadletServer.bindToLong=IP adress att knyta FProxy till
+SimpleToadletServer.cannotChangePortOnTheFly=Kan inte ?ndra FProxy;s port
nummer n?r noden ?r ig?ng
+SimpleToadletServer.couldNotChangeBindTo=Kunde inte ?ndra adressen som FProxy
knyts till: ${error}.
+SimpleToadletServer.cssName=Stilmall
SimpleToadletServer.cssNameLong=Namnet p? den stilmall du vill anv?nda.
-SimpleToadletServer.cssName=Stilmall
SimpleToadletServer.cssOverride=Ladda egen stilmall (VARNING!)
SimpleToadletServer.cssOverrideLong=Du kan ladda in en egen stilmall. VARNING:
Stilmallar kan vara farliga och filtreras inte! Anv?nd p? egen risk. (F?rdiga
stilmallar kan skickas till devl at freenetproject.org f?r att inkluderas i
Freenet ;) )
+SimpleToadletServer.enableJS=Ska FProxy f? anv?nda Javascript?
+SimpleToadletServer.enableJSLong=Ska FProxy f? anv?nda Javascript "Hj?lpare"?
Den h?r inst?llningen ska normalt vara avst?ngd. Den h?r inst?llningen g?r inte
s? att Freesiter kan anv?nda Javascript.
SimpleToadletServer.enabled=Aktivera FProxy?
SimpleToadletServer.enabledLong=Aktivera FProxy och tillh?rande HTTP tj?nster.
-SimpleToadletServer.enableJSLong=Ska FProxy f? anv?nda Javascript "Hj?lpare"?
Den h?r inst?llningen ska normalt vara avst?ngd. Den h?r inst?llningen g?r inte
s? att Freesiter kan anv?nda Javascript.
-SimpleToadletServer.enableJS=Ska FProxy f? anv?nda Javascript?
+SimpleToadletServer.panicButton=Visa panik knappen?
SimpleToadletServer.panicButtonLong=Ska panik knappen synas p? /queue/ sidan.
-SimpleToadletServer.panicButton=Visa panik knappen?
SimpleToadletServer.port=FProxy port
SimpleToadletServer.portLong=FProxy port nummer
StaticToadlet.pathInvalidChars=URI;n ineh?ller ogiltiga tecken.
@@ -557,21 +593,23 @@
SymlinkerToadlet.symlinks=Syml?nkar i ToadletServer
TestnetHandler.enable=Aktivera testnet L?ge? (FARLIGT)
TestnetHandler.enableLong=Ska testnet aktiveras (FARLIGT!). Testnet eliminerar
din anonymitet i utbyte mot att du hj?lper utvecklarna att debugga din nod.
+TestnetHandler.port=Testnet port
TestnetHandler.portLong=Testnet port nummer (-1 = lystningsPort+1000)
-TestnetHandler.port=Testnet port
+TextModeClientInterfaceServer.allowedHosts=Till?tna v?rdar
TextModeClientInterfaceServer.allowedHostsLong=V?rdnamn eller IP addresser som
f?r ansluta till TMCI. Kan vara en komma separerad lista med v?rdnamn, IP
nummer och ?ven CIDR maskerade IP;n som 192.168.0.0/24
-TextModeClientInterfaceServer.allowedHosts=Till?tna v?rdar
TextModeClientInterfaceServer.bindTo=IP adress att knyta till
TextModeClientInterfaceServer.bindToLong=IP adress att knyta TMCI till
+TextModeClientInterfaceServer.enableInputOutput=Aktivera vid stdout/stdin?
TextModeClientInterfaceServer.enabled=Aktivera TMCI
TextModeClientInterfaceServer.enabledLong=Ska TMCI (Text Mode Client
Interface) aktiveras
-TextModeClientInterfaceServer.enableInputOutput=Aktivera vid stdout/stdin?
+TextModeClientInterfaceServer.telnetPortNumber=Telnet port
TextModeClientInterfaceServer.telnetPortNumberLong=Telnet port nummer
-TextModeClientInterfaceServer.telnetPortNumber=Telnet port
Toadlet.cancel=Avbryt
Toadlet.clickHere=Klicka h?r
+Toadlet.homepage=Hemsida
Toadlet.internalErrorPleaseReport=Internt fel : v?nligen rapportera
Toadlet.internalErrorTitle=Internt fel
+Toadlet.no=Nej
Toadlet.nodeHomepage=Nod hemsida
Toadlet.notSupportedTitle=St?ds ej
Toadlet.notSupportedWithClass=Din webb l?sare skickade en f?rfr?gan som
Freenet (${class}) inte f?rstod.
@@ -581,6 +619,8 @@
Toadlet.returnToPrevPage=?terg? till f?rra sidan
Toadlet.tempRedirectWithReason=Tempor?r omdirigering: ${reason}
Toadlet.unauthorized=Du har inte r?ttigheter att bes?ka den h?r sidan.
+Toadlet.yes=Ja
+ToadletContextImpl.methodNotAllowed=HTTP Metoden ?r inte till?ten
TranslationToadlet.bracketRemoveOverride=(Radera ?vers?ttningen!)
TranslationToadlet.bracketTranslateIt=(?vers?tt till ditt spr?k!)
TranslationToadlet.bracketUpdateTranslation=(Uppdatera ?vers?ttningen)
@@ -591,36 +631,46 @@
TranslationToadlet.hideAlreadyTranslated=G?m str?ngar som redan ?versatts
TranslationToadlet.originalVersionLabel=Original (engelsk version)
TranslationToadlet.reEdit=?ndra ?vers?ttningen
+TranslationToadlet.remove=Ta bort
TranslationToadlet.removeOverrideTitle=Radera ?vers?ttning
TranslationToadlet.removeOverrideWarningTitle=Du ?r p? v?g att radera en
?vers?ttning!
-TranslationToadlet.remove=Ta bort
TranslationToadlet.returnToTranslations=?terv?nd till ?vers?ttnings sidan
TranslationToadlet.showEverything=Visa allt, inkluderar redan ?versatta
str?ngar
TranslationToadlet.translationKeyLabel=?vers?ttnings nyckel
+TranslationToadlet.translationUpdateTitle=Uppdatera ?vers?ttning
TranslationToadlet.translationUpdatedTitle=Uppdatera ?vers?ttning!
-TranslationToadlet.translationUpdateTitle=Uppdatera ?vers?ttning
TranslationToadlet.updateTranslationCommand=Uppdatera ?vers?ttningen!
UnknownContentTypeException.title=Ok?nt och potentiellt farligt ineh?ll:
${type}
UpdateDeployContext.cannotUpdateNoExtJar=Hittade inte freenet-ext.jar i
wrapper.conf (freenet.jar hittades: ${mainFilename})
UpdateDeployContext.cannotUpdateNoJars=Kunde inte hitta Freenet jars i
wrapper.conf
UpdateDeployContext.cannotUpdateNoMainJar=Hittade inte freenet.jar i
wrapper.conf (freenet-ext.jar hitades: ${extFilename})
+UpdateDeployContext.updateCatastrophe=KATASTROFALT FEL: Raderade ${old} men
kunde inte byta namn p? ${new} till ${old} d?rf?r kommer noden INTE ATT STARTAS
OM! V?nligen byt namn p? ${new} till ${old} manuellt.
+UpdateDeployContext.updateFailedCannotDeleteOldConfig=Kan inte radera ${old}
s? d?rf?r kan inte en ny skrivas. Uppdatering misslyckades.
UpdatedVersionAvailableUserAlert.armed=Noden kommer att startas om d? den nya
versionen har laddats ner och verifierats.
UpdatedVersionAvailableUserAlert.clickToUpdateASAP=Klicka nedan f?r att
uppdatera din nod s? fort som uppdateringen har verifierats.
UpdatedVersionAvailableUserAlert.clickToUpdateNow=Klicka nedan f?r att
uppdatera din nod direkt.
UpdatedVersionAvailableUserAlert.downloadedNewExtJar=Din nod har laddat ner en
ny version av Freenet extra jar, version ${version}.
UpdatedVersionAvailableUserAlert.downloadedNewJar=Noden har laddat ner en ny
version av Freenet, version ${version}.
+UpdatedVersionAvailableUserAlert.fetchingNewBoth=Din nod laddar nu ner en ny
version av Freenet (nod version ${nodeVersion} och extra jar version
${extVersion}).
+UpdatedVersionAvailableUserAlert.fetchingNewExt=Din nod laddar f?r tillf?llet
ner en ny version av Freenet (extra jar version ${extVersion}).
+UpdatedVersionAvailableUserAlert.notLatest=Det verkar som att din nod inte k?r
den senaste versionen av mjukvaran.
UpdatedVersionAvailableUserAlert.title=A ny stabil version av Freenet finns
tillg?nglig
UpdatedVersionAvailableUserAlert.updateASAPButton=Uppdatera
UpdatedVersionAvailableUserAlert.updateNowButton=Uppdatera Nu!
UserAlert.apply=Anv?nd
UserAlert.hide=G?m
+UserAlert.reset=?terst?ll
+UserAlertManager.alertsOnHomepage=| Mer information finns p?
${link}hemsidan${/link}.
+UserAlertManager.alertsTitle=Kritiska fel
UserAlertManager.criticalErrorCountLabel=Kritiska fel:
UserAlertManager.errorCountLabel=Fel:
+UserAlertManager.totalLabel=Totalt:
UserAlertManager.warningCountLabel=Varningar:
-UserAlert.reset=?terst?ll
WelcomeToadlet.activityTitle=Nuvarande aktivitet
WelcomeToadlet.arkFetchCount=ARK H?mtare: ${total}
+WelcomeToadlet.confirmAddBookmarkSubTitle=Godk?nn att bokm?rket l?ggs till
WelcomeToadlet.confirmAddBookmarkTitle=L?gg till bokm?rke
+WelcomeToadlet.confirmAddBookmarkWithKey=Godk?nn att du vill addera ${key}
till dina bokm?rken och ange en beskrivning:
WelcomeToadlet.confirmExternalLinkSubTitle=Godk?nn extern l?nk
WelcomeToadlet.confirmExternalLinkTitle=VARNING: Extern l?nk
WelcomeToadlet.confirmExternalLinkWithURL=Vill du verkligen bes?ka ${url}.
VARNING: Du l?mnar FREENET! Att bes?ka den h?r l?nken kommer allvarligt att
?ventyra din anonymitet! Du rekommenderas att inte forts?tta!
@@ -631,50 +681,11 @@
WelcomeToadlet.extVersionWithRecommended=Freenet-ext Build #${build}
(${recbuild} ?r rekommenderad) r${rev}
WelcomeToadlet.fetch=H?mta
WelcomeToadlet.fetchKeyLabel=H?mta en Freenet nyckel
+WelcomeToadlet.finInsertSuccessWithKey=Meddelandet har laddats upp till ${key}.
WelcomeToadlet.finInsertedTitle=Uppladdning
-WelcomeToadlet.finInsertSuccessWithKey=Meddelandet har laddats upp till ${key}.
WelcomeToadlet.fromHeader=Fr?n
WelcomeToadlet.goToExternalLink=G? till den angivna l?nken
WelcomeToadlet.homepageFullTitleWithName=Freenet FProxy Hemsida f?r ${name}
WelcomeToadlet.ieWarning=Du verkar anv?nda Microsoft Internet Explorer.
Ondsint skrivna Freenet sidor kan vara en fara f?r din anonymitet!
WelcomeToadlet.ieWarningTitle=S?kerhetsrisk!
-WelcomeToadlet.insertCount=Uppladdningar: ${total}
-WelcomeToadlet.insertedTitle=Uppladdning
-WelcomeToadlet.insertFailedTitle=Uppladdningen misslyckades
-WelcomeToadlet.insertFailedWithMessage=Uppladdningen misslyckades med f?ljande
meddelande: ${message}
-WelcomeToadlet.insertSucceededTitle=Uppladdning slutf?rd
-WelcomeToadlet.messageHeader=Meddelande
-WelcomeToadlet.nodeUpdateConfirmTitle=Godk?nn uppgradering av noden
-WelcomeToadlet.nodeUpdateConfirm=Vill du uppdatera din Freenet nod?
-WelcomeToadlet.privateKeyHeader=Privat nyckel
-WelcomeToadlet.publicKeyHeader=Publik nyckel
-WelcomeToadlet.requestCount=F?rfr?gningar: ${total}
-WelcomeToadlet.restartConfirmTitle=Nod omstart
-WelcomeToadlet.restartConfirm=Vill du verkligen starta om noden?
-WelcomeToadlet.restartingTitle=Freenet startas om.
-WelcomeToadlet.restarting=V?nligen v?nta medans noden starts om, detta kan ta
flera minuter. Tack f?r att du anv?nder Freenet.
-WelcomeToadlet.restartNode=Starta om noden
-WelcomeToadlet.restart=Starta om
-WelcomeToadlet.shutdownConfirmTitle=St?ng av noden
-WelcomeToadlet.shutdownDone=Freenet noden har st?ngts av korrekt.
-WelcomeToadlet.shutdownNode=St?ng av noden
-WelcomeToadlet.shutdown=St?ng av
-WelcomeToadlet.splitfileErrorLabel=Splitfile-specifikt fel:
-WelcomeToadlet.startIndexHeader=Index att starta vid
-WelcomeToadlet.subjectHeader=?mne
-WelcomeToadlet.targetBoardHeader=M?l forum
-WelcomeToadlet.testnetWarning=K?r i testnet l?ge. Detta ?r en stor fara f?r
din anonymitet!
-WelcomeToadlet.testnetWarningTitle=Testnet l?ge
-WelcomeToadlet.thanks=Tack f?r att du anv?nder Freenet.
-WelcomeToadlet.threadDumpSubTitle=Generera en tr?d dump
-WelcomeToadlet.threadDumpTitle=Generera en tr?d dump
-WelcomeToadlet.threadDumpWithFilename=En tr?d dump har gernererats och sparats
i ${filename}.
-WelcomeToadlet.transferringRequestCount=Vidarebefodringar: ${total}
-WelcomeToadlet.update=Uppdatera
-WelcomeToadlet.updatingThanks=Tack f?r att du anv?nder Freenet.
-WelcomeToadlet.updatingTitle=Nod Uppdatering
-WelcomeToadlet.uriWouldHaveBeen=URI;n skulle ha varit: ${uri}
-WelcomeToadlet.version=Freenet ${fullVersion} Build ${build} r${rev}
-WelcomeToadlet.versionHeader=Information om Freenet & nod kontroll
-WelcomeToadlet.writtenDatabaseStats=Runtime databas statistik har skrivits
till wrapper loggen
-End
+WelcomeToadlet.insertCount
Modified:
branches/freenet-jfk/src/freenet/pluginmanager/AccessDeniedPluginHTTPException.java
===================================================================
---
branches/freenet-jfk/src/freenet/pluginmanager/AccessDeniedPluginHTTPException.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/pluginmanager/AccessDeniedPluginHTTPException.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -11,7 +11,7 @@
public class AccessDeniedPluginHTTPException extends PluginHTTPException {
private static final long serialVersionUID = -1;
- public final short code = 403; // Access Denied
+ public static final short code = 403; // Access Denied
public AccessDeniedPluginHTTPException(String errorMessage, String
location) {
super(errorMessage, location);
Modified:
branches/freenet-jfk/src/freenet/pluginmanager/DownloadPluginHTTPException.java
===================================================================
---
branches/freenet-jfk/src/freenet/pluginmanager/DownloadPluginHTTPException.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/pluginmanager/DownloadPluginHTTPException.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -11,7 +11,7 @@
public class DownloadPluginHTTPException extends PluginHTTPException {
private static final long serialVersionUID = -1;
- public final short code = 200; // Found
+ public static final short CODE = 200; // Found
public final String filename;
public final String mimeType;
public final byte[] data;
Modified: branches/freenet-jfk/src/freenet/pluginmanager/FredPlugin.java
===================================================================
--- branches/freenet-jfk/src/freenet/pluginmanager/FredPlugin.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/pluginmanager/FredPlugin.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -8,5 +8,6 @@
public void terminate();
+ /** Run the plugin. Called after node startup. Should be able to access
queue etc at this point. */
public void runPlugin(PluginRespirator pr);
}
Copied:
branches/freenet-jfk/src/freenet/pluginmanager/FredPluginHTTPAdvanced.java
(from rev 14796,
trunk/freenet/src/freenet/pluginmanager/FredPluginHTTPAdvanced.java)
===================================================================
--- branches/freenet-jfk/src/freenet/pluginmanager/FredPluginHTTPAdvanced.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/pluginmanager/FredPluginHTTPAdvanced.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,4 @@
+package freenet.pluginmanager;
+public interface FredPluginHTTPAdvanced{
+
+}
\ No newline at end of file
Modified:
branches/freenet-jfk/src/freenet/pluginmanager/NotFoundPluginHTTPException.java
===================================================================
---
branches/freenet-jfk/src/freenet/pluginmanager/NotFoundPluginHTTPException.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/pluginmanager/NotFoundPluginHTTPException.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -11,7 +11,7 @@
public class NotFoundPluginHTTPException extends PluginHTTPException {
private static final long serialVersionUID = -1;
- public final short code = 404; // Not Found
+ public static final short code = 404; // Not Found
public NotFoundPluginHTTPException(String errorMessage, String
location) {
super(errorMessage, location);
Modified:
branches/freenet-jfk/src/freenet/pluginmanager/PluginHTTPException.java
===================================================================
--- branches/freenet-jfk/src/freenet/pluginmanager/PluginHTTPException.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/pluginmanager/PluginHTTPException.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -11,7 +11,7 @@
public class PluginHTTPException extends Exception {
private static final long serialVersionUID = -1;
- public final short code = 400; // Bad Request
+ public static final short code = 400; // Bad Request
public final String message;
public final String location;
Modified: branches/freenet-jfk/src/freenet/pluginmanager/PluginHandler.java
===================================================================
--- branches/freenet-jfk/src/freenet/pluginmanager/PluginHandler.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/pluginmanager/PluginHandler.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -20,17 +20,24 @@
* @param plug
*/
public static PluginInfoWrapper startPlugin(PluginManager pm, String
filename, FredPlugin plug, PluginRespirator pr) {
- PluginStarter ps = new PluginStarter(pr);
- PluginInfoWrapper pi = new PluginInfoWrapper(plug, ps,
filename);
+ final PluginStarter ps = new PluginStarter(pr);
+ final PluginInfoWrapper pi = new PluginInfoWrapper(plug, ps,
filename);
// This is an ugly trick... sorry ;o)
// The thread still exists as an identifier, but is never
started if the
// plugin doesn't require it
ps.setPlugin(pm, plug);
- if (!pi.isThreadlessPlugin())
- ps.start();
- else
- ps.run();
+ // Run after startup
+ // FIXME this is horrible, wastes a thread, need to make
PluginStarter a Runnable
+ // not a Thread, and then deal with the consequences of that
(removePlugin(Thread)) ...
+ pm.getTicker().queueTimedJob(new Runnable() {
+ public void run() {
+ if (!pi.isThreadlessPlugin())
+ ps.start();
+ else
+ ps.run();
+ }
+ }, 0);
return pi;
}
@@ -71,11 +78,13 @@
System.err.println("Caught Throwable
while running plugin: "+t);
t.printStackTrace();
}
+ if(!(plugin instanceof FredPluginThreadless))
+ pm.removePlugin(this);
+ } else {
+ // If not FredPlugin, then the whole thing is
aborted,
+ // and then this method will return, killing
the thread
+ return;
}
- // If not FredPlugin, then the whole thing is aborted,
- // and then this method will return, killing the thread
-
- pm.removePlugin(this);
}
}
Modified: branches/freenet-jfk/src/freenet/pluginmanager/PluginManager.java
===================================================================
--- branches/freenet-jfk/src/freenet/pluginmanager/PluginManager.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/pluginmanager/PluginManager.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,15 +1,11 @@
/* This code is part of Freenet. It is distributed under the GNU General
-* Public License, version 2 (or at your option any later version). See
-* http://www.gnu.org/ for further details of the GPL. */
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
package freenet.pluginmanager;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.BufferedReader;
-import java.io.DataInputStream;
import java.io.File;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -31,6 +27,7 @@
import freenet.l10n.L10n;
import freenet.node.Node;
import freenet.node.NodeClientCore;
+import freenet.node.Ticker;
import freenet.node.useralerts.SimpleUserAlert;
import freenet.node.useralerts.UserAlert;
import freenet.support.Logger;
@@ -42,15 +39,15 @@
public class PluginManager {
/*
- *
- * TODO: Synchronize
- * TODO: Synchronize
- * TODO: Synchronize
- * TODO: Synchronize
- * TODO: Synchronize
- *
- */
-
+ *
+ * TODO: Synchronize
+ * TODO: Synchronize
+ * TODO: Synchronize
+ * TODO: Synchronize
+ * TODO: Synchronize
+ *
+ */
+
private HashMap toadletList;
private HashMap pluginInfo;
private PluginRespirator pluginRespirator = null;
@@ -58,7 +55,7 @@
private final NodeClientCore core;
SubConfig pmconfig;
private boolean logMINOR;
-
+
public PluginManager(Node node) {
pluginInfo = new HashMap();
toadletList = new HashMap();
@@ -66,7 +63,7 @@
this.core = node.clientCore;
logMINOR = Logger.shouldLog(Logger.MINOR, this);
pluginRespirator = new PluginRespirator(node, this);
-
+
pmconfig = new SubConfig("pluginmanager", node.config);
// Start plugins in the config
pmconfig.register("loadplugin", null, 9, true, false,
"PluginManager.loadedOnStartup", "PluginManager.loadedOnStartupLong",
@@ -79,8 +76,8 @@
// FIXME
throw new
InvalidConfigValueException(L10n.getString("PluginManager.cannotSetOnceLoaded"));
}
- });
-
+ });
+
String fns[] = pmconfig.getStringArr("loadplugin");
if (fns != null) {
for (int i = 0 ; i < fns.length ; i++) {
@@ -88,33 +85,33 @@
startPlugin(fns[i], false);
}
}
-
+
pmconfig.finishedInitialization();
/*System.err.println("=================================");
- pmconfig.finishedInitialization();
- fns = pmconfig.getStringArr("loadplugin");
- for (int i = 0 ; i < fns.length ; i++)
- System.err.println("Load: " +
StringArrOption.decode(fns[i]));
- System.err.println("=================================");
- */
+ pmconfig.finishedInitialization();
+ fns = pmconfig.getStringArr("loadplugin");
+ for (int i = 0 ; i < fns.length ; i++)
+ System.err.println("Load: " + StringArrOption.decode(fns[i]));
+ System.err.println("=================================");
+ */
}
-
+
private String[] getConfigLoadString() {
try{
Iterator it = getPlugins().iterator();
Vector v = new Vector();
-
+
while(it.hasNext())
v.add(((PluginInfoWrapper)it.next()).getFilename());
-
+
return (String[]) v.toArray(new String[v.size()]);
}catch (NullPointerException e){
Logger.error(this, "error while loading plugins:
disabling them:"+e);
return new String[0];
}
}
-
+
public void startPlugin(String filename, boolean store) {
if (filename.trim().length() == 0)
return;
@@ -124,14 +121,14 @@
plug = LoadPlugin(filename);
PluginInfoWrapper pi = PluginHandler.startPlugin(this,
filename, plug, pluginRespirator);
// handles FProxy? If so, register
-
+
if (pi.isPproxyPlugin())
registerToadlet(plug);
if(pi.isIPDetectorPlugin()) {
node.ipDetector.registerIPDetectorPlugin((FredPluginIPDetector) plug);
}
-
+
synchronized (pluginInfo) {
pluginInfo.put(pi.getThreadName(), pi);
}
@@ -147,14 +144,14 @@
System.err.println("Plugin "+filename+" appears
to require a later JVM");
Logger.error(this, "Plugin "+filename+" appears
to require a later JVM");
core.alerts.register(new SimpleUserAlert(true,
- l10n("pluginReqNewerJVMTitle",
"name", filename),
- l10n("pluginReqNewerJVM",
"name", filename),
- UserAlert.ERROR));
+
l10n("pluginReqNewerJVMTitle", "name", filename),
+
l10n("pluginReqNewerJVM", "name", filename),
+ UserAlert.ERROR));
}
}
if(store) core.storeConfig();
}
-
+
private String l10n(String key, String pattern, String value) {
return L10n.getString("PluginManager."+key, pattern, value);
}
@@ -166,7 +163,7 @@
}
Logger.normal(this, "Added HTTP handler for
/plugins/"+pl.getClass().getName()+ '/');
}
-
+
public void removePlugin(Thread t) {
Object removeKey = null;
synchronized (pluginInfo) {
@@ -180,28 +177,28 @@
try {
toadletList.remove(pi.getPluginClassName());
Logger.normal(this,
"Removed HTTP handler for /plugins/"+
-
pi.getPluginClassName()+ '/');
+
pi.getPluginClassName()+ '/', new Exception("debug"));
} catch (Throwable ex) {
Logger.error(this,
"removing Plugin", ex);
}
}
}
}
-
+
if (removeKey != null)
pluginInfo.remove(removeKey);
}
if(removeKey != null)
core.storeConfig();
}
-
+
public void addToadletSymlinks(PluginInfoWrapper pi) {
synchronized (toadletList) {
try {
String targets[] =
pi.getPluginToadletSymlinks();
if (targets == null)
return;
-
+
for (int i = 0 ; i < targets.length ; i++) {
toadletList.remove(targets[i]);
Logger.normal(this, "Removed HTTP
symlink: " + targets[i] +
@@ -212,7 +209,7 @@
}
}
}
-
+
public void removeToadletSymlinks(PluginInfoWrapper pi) {
synchronized (toadletList) {
String rm = null;
@@ -220,7 +217,7 @@
String targets[] =
pi.getPluginToadletSymlinks();
if (targets == null)
return;
-
+
for (int i = 0 ; i < targets.length ; i++) {
rm = targets[i];
toadletList.remove(targets[i]);
@@ -246,7 +243,7 @@
}
return out.toString();
}
-
+
public Set getPlugins() {
HashSet out = new HashSet();
synchronized (pluginInfo) {
@@ -258,37 +255,37 @@
}
return out;
}
-
+
public String handleHTTPGet(String plugin, HTTPRequest request) throws
PluginHTTPException {
FredPlugin handler = null;
synchronized (toadletList) {
handler = (FredPlugin)toadletList.get(plugin);
}
/*if (handler == null)
- return null;
- */
-
+ return null;
+ */
+
if (handler instanceof FredPluginHTTP)
return ((FredPluginHTTP)handler).handleHTTPGet(request);
-
+
throw new NotFoundPluginHTTPException("Plugin not found!",
"/plugins");
}
-
+
public String handleHTTPPost(String plugin, HTTPRequest request) throws
PluginHTTPException {
FredPlugin handler = null;
synchronized (toadletList) {
handler = (FredPlugin)toadletList.get(plugin);
}
/*if (handler == null)
- return null;
- */
-
+ return null;
+ */
+
if (handler instanceof FredPluginHTTP)
return
((FredPluginHTTP)handler).handleHTTPPost(request);
-
+
throw new NotFoundPluginHTTPException("Plugin not found!",
"/plugins");
}
-
+
public void killPlugin(String name) {
PluginInfoWrapper pi = null;
boolean found = false;
@@ -306,18 +303,18 @@
else
pi.stopPlugin();
}
-
-
+
+
/**
- * Method to load a plugin from the given path and return is as an
object.
- * Will accept filename to be of one of the following forms:
- * "classname" to load a class from the current classpath
- * "classame at file:/path/to/jarfile.jar" to load class from an other
jarfile.
- *
- * @param filename The filename to load from
- * @return An instanciated object of the plugin
- * @throws PluginNotFoundException If anything goes wrong.
- */
+ * Method to load a plugin from the given path and return is as an
object.
+ * Will accept filename to be of one of the following forms:
+ * "classname" to load a class from the current classpath
+ * "classame at file:/path/to/jarfile.jar" to load class from an other
jarfile.
+ *
+ * @param filename The filename to load from
+ * @return An instanciated object of the plugin
+ * @throws PluginNotFoundException If anything goes wrong.
+ */
private FredPlugin LoadPlugin(String filename) throws
PluginNotFoundException {
logMINOR = Logger.shouldLog(Logger.MINOR, this);
Class cls = null;
@@ -334,41 +331,29 @@
}
String pluginname = filename.substring(0,
filename.length()-1);
filename = null;
-
+
URL url;
- DataInputStream dis;
- InputStream is = null;
- BufferedInputStream bis = null;
- FileOutputStream fos = null;
- BufferedOutputStream bos = null;
-
+ InputStream is = null;
+
try {
url = new
URL("http://downloads.freenetproject.org/alpha/plugins/" + pluginname +
".jar.url");
if(logMINOR) Logger.minor(this, "Downloading
"+url);
is = url.openStream();
- bis = new BufferedInputStream(is);
- dis = new DataInputStream(bis);
-
- File pluginsDirectory = new File("plugins");
- if(!pluginsDirectory.exists()) {
- Logger.normal(this, "The plugin directory hasn't been
found, let's create it");
- if(!pluginsDirectory.mkdir())
- return null;
- }
-
- File finalFile = new File("plugins/" + pluginname + ".jar");
- File f = File.createTempFile(pluginname, ".tmp",
pluginsDirectory);
- fos = new FileOutputStream(f);
- bos = new BufferedOutputStream(fos);
- int len = 0, writenBytes = 0;
- byte[] buffer = new byte[4096];
- while ((len = dis.read(buffer)) != -1) {
- bos.write(buffer, writenBytes, len);
- writenBytes +=len;
- }
- f.renameTo(finalFile);
- filename = "*@file://" + FileUtil.getCanonicalFile(f);
- if(logMINOR) Logger.minor(this, "Rewritten to
"+filename);
+
+ File pluginsDirectory = new File("plugins");
+ if(!pluginsDirectory.exists()) {
+ Logger.normal(this, "The plugin
directory hasn't been found, let's create it");
+ if(!pluginsDirectory.mkdir())
+ return null;
+ }
+
+ File finalFile = new File("plugins/" +
pluginname + ".jar");
+ if(!FileUtil.writeTo(is, finalFile))
+ Logger.error(this, "Failed to rename
the temporary file into "+finalFile);
+
+ filename = "*@file://" +
FileUtil.getCanonicalFile(finalFile);
+ if(logMINOR) Logger.minor(this, "Rewritten to
"+filename);
+
} catch (MalformedURLException mue) {
Logger.error(this, "MAlformedURLException has
occured : "+ mue, mue);
return null;
@@ -381,16 +366,13 @@
return null;
} finally {
try {
- if(bis != null) bis.close();
if(is != null) is.close();
- if(bos != null) bos.close();
- if(fos != null) fos.close();
} catch (IOException ioe) {}
}
if(filename == null)
return null;
}
-
+
BufferedReader in = null;
InputStream is = null;
if ((filename.indexOf("@") >= 0)) {
@@ -400,7 +382,7 @@
try {
String realURL = null;
String realClass = null;
-
+
// Load the jar-file
String[] parts = filename.split("@");
if (parts.length != 2) {
@@ -409,7 +391,7 @@
realClass = parts[0];
realURL = parts[1];
if(logMINOR) Logger.minor(this, "Class:
"+realClass+" URL: "+realURL);
-
+
if (filename.endsWith(".url")) {
if(!assumeURLRedirect) {
// Load the txt-file
@@ -417,7 +399,7 @@
URLConnection uc =
url.openConnection();
in = new BufferedReader(
new
InputStreamReader(uc.getInputStream()));
-
+
realURL = in.readLine();
if(realURL == null)
throw new
PluginNotFoundException("Initialization error: " + url +
@@ -428,21 +410,21 @@
}
assumeURLRedirect =
!assumeURLRedirect;
}
-
+
// Load the class inside file
URL[] serverURLs = new URL[]{new
URL(realURL)};
ClassLoader cl = new
URLClassLoader(serverURLs);
-
-
+
+
// Handle automatic fetching of
pluginclassname
if (realClass.equals("*")) {
-
+
// Clean URL
URI liburi =
URIPreEncoder.encodeURI(realURL);
if(logMINOR)
Logger.minor(this,
"cleaned url: "+realURL+" -> "+liburi.toString());
realURL = liburi.toString();
-
+
URL url = new
URL("jar:"+realURL+"!/");
JarURLConnection jarConnection
= (JarURLConnection)url.openConnection();
// Java seems to cache even
file: urls...
@@ -450,12 +432,12 @@
JarFile jf =
jarConnection.getJarFile();
//URLJarFile jf = new
URLJarFile(new File(liburi));
//is =
jf.getInputStream(jf.getJarEntry("META-INF/MANIFEST.MF"));
-
+
//BufferedReader manifest = new
BufferedReader(new
InputStreamReader(cl.getResourceAsStream("/META-INF/MANIFEST.MF")));
-
+
//URL url = new URL(parts[1]);
//URLConnection uc =
cl.getResource("/META-INF/MANIFEST.MF").openConnection();
-
+
is =
jf.getInputStream(jf.getJarEntry("META-INF/MANIFEST.MF"));
in = new BufferedReader(new
InputStreamReader(is));
String line;
@@ -468,14 +450,14 @@
}
//System.err.println("Real
classname: " + realClass);
}
-
+
cls = cl.loadClass(realClass);
-
+
} catch (Exception e) {
if (tries >= 5)
throw new
PluginNotFoundException("Initialization error:"
+ filename, e);
-
+
try {
Thread.sleep(100);
} catch (Exception ee) {}
@@ -495,10 +477,10 @@
throw new PluginNotFoundException(filename);
}
}
-
+
if(cls == null)
throw new PluginNotFoundException("Unknown error");
-
+
// Class loaded... Objectize it!
Object o = null;
try {
@@ -507,12 +489,16 @@
throw new PluginNotFoundException("Could not re-create
plugin:" +
filename, e);
}
-
+
// See if we have the right type
if (!(o instanceof FredPlugin)) {
throw new PluginNotFoundException("Not a plugin: " +
filename);
}
-
+
return (FredPlugin)o;
}
+
+ Ticker getTicker() {
+ return node.getTicker();
+ }
}
Modified:
branches/freenet-jfk/src/freenet/pluginmanager/RedirectPluginHTTPException.java
===================================================================
---
branches/freenet-jfk/src/freenet/pluginmanager/RedirectPluginHTTPException.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/pluginmanager/RedirectPluginHTTPException.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -11,7 +11,7 @@
public class RedirectPluginHTTPException extends PluginHTTPException {
private static final long serialVersionUID = -1;
- public final short code = 302; // Found
+ public static final short code = 302; // Found
public final String newLocation;
public RedirectPluginHTTPException(String message, String location,
String newLocation) {
Modified: branches/freenet-jfk/src/freenet/store/BerkeleyDBFreenetStore.java
===================================================================
--- branches/freenet-jfk/src/freenet/store/BerkeleyDBFreenetStore.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/store/BerkeleyDBFreenetStore.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -32,6 +32,7 @@
import com.sleepycat.je.SecondaryKeyCreator;
import com.sleepycat.je.Transaction;
import com.sleepycat.je.log.DbChecksumException;
+import com.sleepycat.je.log.LogFileNotFoundException;
import com.sleepycat.je.util.DbLoad;
import freenet.crypt.CryptFormatException;
@@ -182,23 +183,32 @@
System.err.println("Failed to reload database
"+dbName+": "+e);
e.printStackTrace();
}
+
+ // Should just open now, although it will need to
reconstruct the secondary indexes.
}
try {
+ // First try just opening it.
return new BerkeleyDBFreenetStore(storeEnvironment,
newDBPrefix, newStoreFile, newFixSecondaryFile,
maxStoreKeys, blockSize, headerSize,
throwOnTooFewKeys, noCheck, wipe, storeShutdownHook,
reconstructFile);
} catch (DatabaseException e) {
+ // Try a reconstruct
+
System.err.println("Could not open store: "+e);
e.printStackTrace();
if(type == TYPE_SSK) {
- System.err.println("Cannot reconstruct SSK
store/cache. Move the old store/cache out of the way, and report to
developers.");
- throw e;
+ System.err.println("Cannot reconstruct SSK
store/cache! Sorry, your SSK store will now be deleted...");
+
BerkeleyDBFreenetStore.wipeOldDatabases(storeEnvironment, newDBPrefix);
+ newStoreFile.delete();
+ return new
BerkeleyDBFreenetStore(storeEnvironment, newDBPrefix, newStoreFile,
newFixSecondaryFile,
+ maxStoreKeys, blockSize,
headerSize, throwOnTooFewKeys, noCheck, wipe, storeShutdownHook,
+ reconstructFile);
}
- System.err.println("Attempting to reconstruct...");
+ System.err.println("Attempting to reconstruct
index...");
WrapperManager.signalStarting(5*60*60*1000);
// Reconstruct
@@ -246,7 +256,7 @@
dbConfig.setTransactional(true);
if(wipe) {
System.err.println("Wiping old database for "+prefix);
- wipeOldDatabases(prefix);
+ wipeOldDatabases(environment, prefix);
}
chkDB = environment.openDatabase(null,prefix+"CHK",dbConfig);
@@ -410,7 +420,7 @@
boolean dontCheckForHolesShrinking = false;
- long chkBlocksInDatabase = chkDB.count();
+ long chkBlocksInDatabase =
highestBlockNumberInDatabase();
chkBlocksInStore = chkBlocksInDatabase;
long chkBlocksFromFile = countCHKBlocksFromFile();
lastRecentlyUsed = getMaxRecentlyUsed();
@@ -955,7 +965,7 @@
this.reconstructFile = reconstructFile;
name = prefix;
- wipeOldDatabases(prefix);
+ wipeOldDatabases(environment, prefix);
// Delete old database(s).
@@ -1022,22 +1032,22 @@
storeShutdownHook.addEarlyJob(new ShutdownHook());
}
- private void wipeOldDatabases(String prefix) {
- wipeDatabase(prefix+"CHK");
- wipeDatabase(prefix+"CHK_accessTime");
- wipeDatabase(prefix+"CHK_blockNum");
+ private static void wipeOldDatabases(Environment env, String prefix) {
+ wipeDatabase(env, prefix+"CHK");
+ wipeDatabase(env, prefix+"CHK_accessTime");
+ wipeDatabase(env, prefix+"CHK_blockNum");
System.err.println("Removed old database "+prefix);
}
- private void wipeDatabase(String name) {
+ private static void wipeDatabase(Environment env, String name) {
WrapperManager.signalStarting(5*60*60*1000);
- Logger.normal(this, "Wiping database "+name);
+ Logger.normal(BerkeleyDBFreenetStore.class, "Wiping database
"+name);
try {
- environment.removeDatabase(null, name);
+ env.removeDatabase(null, name);
} catch (DatabaseNotFoundException e) {
System.err.println("Database "+name+" does not exist
deleting it");
} catch (DatabaseException e) {
- Logger.error(this, "Could not remove old database:
"+name+": "+e, e);
+ Logger.error(BerkeleyDBFreenetStore.class, "Could not
remove old database: "+name+": "+e, e);
System.err.println("Could not remove old database:
"+name+": "+e);
e.printStackTrace();
}
@@ -1320,7 +1330,7 @@
}
- block = new SSKBlock(data,header,chk, true);
+ block = new SSKBlock(data,header,chk, false);
if(!dontPromote) {
storeBlock.updateRecentlyUsed();
@@ -1751,8 +1761,9 @@
chkDB_blockNum.get(t, blockNumEntry, found,
LockMode.DEFAULT);
if(success == OperationStatus.KEYEXIST || success ==
OperationStatus.SUCCESS) {
- System.err.println("Trying to overwrite block
"+blockNum+" but already used: "+getName());
- Logger.error(this, "Trying to overwrite block
"+blockNum+" but already used: "+getName());
+ System.err.println("Trying to overwrite block
"+blockNum+" but already used: "+getName()+" for "+e);
+ e.printStackTrace();
+ Logger.error(this, "Trying to overwrite block
"+blockNum+" but already used: "+getName()+" for "+e);
return false;
} else {
Logger.minor(this, "Key doesn't exist for block
num "+blockNum+" but caught "+e, e);
@@ -1794,8 +1805,13 @@
}
Logger.error(this, "Corrupt secondary database
("+getName()+"). Should be cleaned up on restart.");
System.err.println("Corrupt secondary database
("+getName()+"). Should be cleaned up on restart.");
-
System.exit(freenet.node.Node.EXIT_DATABASE_REQUIRES_RESTART);
- } else if(ex instanceof DbChecksumException || ex
instanceof RunRecoveryException) {
+ WrapperManager.restart();
+
System.exit(freenet.node.NodeInitException.EXIT_DATABASE_REQUIRES_RESTART);
+ } else if(ex instanceof DbChecksumException || ex
instanceof RunRecoveryException || ex instanceof LogFileNotFoundException ||
+ // UGH! We really shouldn't have to do
this ... :(
+ (msg != null &&
+
(msg.indexOf("LogFileNotFoundException") >= 0 ||
msg.indexOf("DbChecksumException") >= 0)
+ ||
msg.indexOf("RunRecoveryException") >= 0)) {
System.err.println("Corrupt database! Will be
reconstructed on restart");
try {
reconstructFile.createNewFile();
@@ -1804,6 +1820,9 @@
System.err.println("Corrupt database
("+getName()+") but could not create flag file "+reconstructFile);
return; // Not sure what else we can do
}
+ } else {
+ if(ex.getCause() != null)
+
checkSecondaryDatabaseError(ex.getCause());
}
}
}
@@ -2063,29 +2082,37 @@
if(chkStore != null)
chkStore.close();
} catch (Throwable t) {
- System.err.println("Caught closing
database: "+t);
- t.printStackTrace();
+ if(!(t instanceof RunRecoveryException
|| t instanceof OutOfMemoryError)) {
+ System.err.println("Caught
closing database: "+t);
+ t.printStackTrace();
+ }
}
try {
if(chkDB_accessTime != null)
chkDB_accessTime.close();
} catch (Throwable t) {
- System.err.println("Caught closing
database: "+t);
- t.printStackTrace();
+ if(!(t instanceof RunRecoveryException
|| t instanceof OutOfMemoryError)) {
+ System.err.println("Caught
closing database: "+t);
+ t.printStackTrace();
+ }
}
try {
if(chkDB_blockNum != null)
chkDB_blockNum.close();
} catch (Throwable t) {
- System.err.println("Caught closing
database: "+t);
- t.printStackTrace();
+ if(!(t instanceof RunRecoveryException
|| t instanceof OutOfMemoryError)) {
+ System.err.println("Caught
closing database: "+t);
+ t.printStackTrace();
+ }
}
try {
if(chkDB != null)
chkDB.close();
} catch (Throwable t) {
- System.err.println("Caught closing
database: "+t);
- t.printStackTrace();
+ if(!(t instanceof RunRecoveryException
|| t instanceof OutOfMemoryError)) {
+ System.err.println("Caught
closing database: "+t);
+ t.printStackTrace();
+ }
}
if(logMINOR) Logger.minor(this, "Closing
database finished.");
System.err.println("Closed database");
Modified: branches/freenet-jfk/src/freenet/support/BitArray.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/BitArray.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/BitArray.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -43,8 +43,8 @@
public BitArray(BitArray src) {
this._size = src._size;
- this._bits = new byte[src._size];
- System.arraycopy(_bits, 0, src._bits, 0, _bits.length);
+ this._bits = new byte[src._bits.length];
+ System.arraycopy(src._bits, 0, _bits, 0, src._bits.length);
}
public void setBit(int pos, boolean f) {
@@ -123,8 +123,11 @@
if(b == 0) continue;
for(int j=0;j<8;j++) {
int mask = (1 << j);
- if((b & mask) != 0)
- return i*8+j;
+ if((b & mask) != 0) {
+ int x = i*8+j;
+ if(x >= _size) return -1;
+ return x;
+ }
}
}
return -1;
Copied: branches/freenet-jfk/src/freenet/support/Executor.java (from rev 14796,
trunk/freenet/src/freenet/support/Executor.java)
===================================================================
--- branches/freenet-jfk/src/freenet/support/Executor.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/support/Executor.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,16 @@
+/**
+ * @author toad
+ * To the extent that this is copyrightable, it's part of Freenet and licensed
+ * under GPL2 or later. However, it's a trivial interface taken from Sun JDK
1.5,
+ * and we will use that when we migrate to 1.5.
+ */
+package freenet.support;
+
+public interface Executor {
+
+ /** Execute a job. */
+ public void execute(Runnable job, String jobName);
+
+ /** Count the number of threads waiting for work */
+ public int waitingThreads();
+}
Modified: branches/freenet-jfk/src/freenet/support/Fields.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/Fields.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/Fields.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -1,6 +1,5 @@
package freenet.support;
-import java.io.DataInputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -146,6 +145,18 @@
}
/**
+ * Find the boolean value of the field. Throw if the string is neither
"yes"/"true" nor "no"/"false".
+ * @param s
+ * @return
+ */
+ public static boolean stringToBool(String s) throws
NumberFormatException {
+ if(s == null) throw new NumberFormatException("Null");
+ if(s.equalsIgnoreCase("false") || s.equalsIgnoreCase("no"))
return false;
+ if(s.equalsIgnoreCase("true") || s.equalsIgnoreCase("yes"))
return true;
+ throw new NumberFormatException("Invalid boolean: "+s);
+ }
+
+ /**
* Converts a boolean to a String of either "true" or "false".
*
* @param b
Modified: branches/freenet-jfk/src/freenet/support/FileLoggerHook.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/FileLoggerHook.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/FileLoggerHook.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -693,7 +693,7 @@
if (rotate) {
this.baseFilename = baseFilename;
} else {
- logStream = new FileOutputStream(baseFilename,
!logOverwrite);
+ logStream = new BufferedOutputStream(new
FileOutputStream(baseFilename, !logOverwrite), 65536);
}
}
@@ -822,18 +822,20 @@
if (e != null) {
- // Convert the stack trace to a string.
- ByteArrayOutputStream bos = new
ByteArrayOutputStream(350);
- PrintWriter bpw = new PrintWriter(bos);
- try {
- e.printStackTrace(bpw);
- } catch (NullPointerException ex) {
- log(this, getClass(), "Got evil
NPE-in-stack-trace bug", null, ERROR);
- bpw.println("[ evil NPE-in-stack-trace
triggered ]");
+ sb.append(e.toString());
+
+ StackTraceElement[] trace = e.getStackTrace();
+
+ if(trace == null)
+ sb.append("(null)");
+ else {
+ sb.append('\n');
+ for(int i=0;i<trace.length;i++) {
+ sb.append("\tat ");
+ sb.append(trace[i].toString());
+ sb.append('\n');
+ }
}
- bpw.flush();
-
- sb.append(bos.toString());
}
logString(sb.toString().getBytes());
Modified: branches/freenet-jfk/src/freenet/support/HTMLDecoder.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/HTMLDecoder.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/HTMLDecoder.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -3,7 +3,8 @@
* http://www.gnu.org/ for further details of the GPL. */
package freenet.support;
-import java.util.HashMap;
+//import java.util.HashMap;
+import java.util.Map;
/**
* Description: Utility for converting character references e.g.: < >
@@ -13,8 +14,8 @@
*/
public class HTMLDecoder {
- public static final HashMap charTable;
-
+ static Map charTable = HTMLEntities.decodeMap;
+
public static String decode(String s) {
String t;
Character ch;
@@ -147,267 +148,19 @@
// HTML is very particular about what constitutes white space.
public static boolean isWhitespace(char ch) {
- return (ch == '\u0020')
- || (ch == '\r')
- || (ch == '\n')
+ return
+ //space
+ (ch == '\u0020')
+ //Mac newline
+ || (ch == '\r')
+ //Unix newline
+ || (ch == '\n')
+ //tab
|| (ch == '\u0009')
+ //Control
|| (ch == '\u000c')
+ //zero width space
|| (ch == '\u200b');
}
- static {
- charTable = new HashMap();
- charTable.put("quot", new Character((char)34));
- charTable.put("amp", new Character((char)38));
- charTable.put("apos", new Character((char)39));
- charTable.put("lt", new Character((char)60));
- charTable.put("gt", new Character((char)62));
- charTable.put("nbsp", new Character((char)160));
- charTable.put("iexcl", new Character((char)161));
- charTable.put("cent", new Character((char)162));
- charTable.put("pound", new Character((char)163));
- charTable.put("curren", new Character((char)164));
- charTable.put("yen", new Character((char)165));
- charTable.put("brvbar", new Character((char)166));
- charTable.put("sect", new Character((char)167));
- charTable.put("uml", new Character((char)168));
- charTable.put("copy", new Character((char)169));
- charTable.put("ordf", new Character((char)170));
- charTable.put("laquo", new Character((char)171));
- charTable.put("not", new Character((char)172));
- charTable.put("shy", new Character((char)173));
- charTable.put("reg", new Character((char)174));
- charTable.put("macr", new Character((char)175));
- charTable.put("deg", new Character((char)176));
- charTable.put("plusmn", new Character((char)177));
- charTable.put("sup2", new Character((char)178));
- charTable.put("sup3", new Character((char)179));
- charTable.put("acute", new Character((char)180));
- charTable.put("micro", new Character((char)181));
- charTable.put("para", new Character((char)182));
- charTable.put("middot", new Character((char)183));
- charTable.put("cedil", new Character((char)184));
- charTable.put("sup1", new Character((char)185));
- charTable.put("ordm", new Character((char)186));
- charTable.put("raquo", new Character((char)187));
- charTable.put("frac14", new Character((char)188));
- charTable.put("frac12", new Character((char)189));
- charTable.put("frac34", new Character((char)190));
- charTable.put("iquest", new Character((char)191));
- charTable.put("Agrave", new Character((char)192));
- charTable.put("Aacute", new Character((char)193));
- charTable.put("Acirc", new Character((char)194));
- charTable.put("Atilde", new Character((char)195));
- charTable.put("Auml", new Character((char)196));
- charTable.put("Aring", new Character((char)197));
- charTable.put("AElig", new Character((char)198));
- charTable.put("Ccedil", new Character((char)199));
- charTable.put("Egrave", new Character((char)200));
- charTable.put("Eacute", new Character((char)201));
- charTable.put("Ecirc", new Character((char)202));
- charTable.put("Euml", new Character((char)203));
- charTable.put("Igrave", new Character((char)204));
- charTable.put("Iacute", new Character((char)205));
- charTable.put("Icirc", new Character((char)206));
- charTable.put("Iuml", new Character((char)207));
- charTable.put("ETH", new Character((char)208));
- charTable.put("Ntilde", new Character((char)209));
- charTable.put("Ograve", new Character((char)210));
- charTable.put("Oacute", new Character((char)211));
- charTable.put("Ocirc", new Character((char)212));
- charTable.put("Otilde", new Character((char)213));
- charTable.put("Ouml", new Character((char)214));
- charTable.put("times", new Character((char)215));
- charTable.put("Oslash", new Character((char)216));
- charTable.put("Ugrave", new Character((char)217));
- charTable.put("Uacute", new Character((char)218));
- charTable.put("Ucirc", new Character((char)219));
- charTable.put("Uuml", new Character((char)220));
- charTable.put("Yacute", new Character((char)221));
- charTable.put("THORN", new Character((char)222));
- charTable.put("szlig", new Character((char)223));
- charTable.put("agrave", new Character((char)224));
- charTable.put("aacute", new Character((char)225));
- charTable.put("acirc", new Character((char)226));
- charTable.put("atilde", new Character((char)227));
- charTable.put("auml", new Character((char)228));
- charTable.put("aring", new Character((char)229));
- charTable.put("aelig", new Character((char)230));
- charTable.put("ccedil", new Character((char)231));
- charTable.put("egrave", new Character((char)232));
- charTable.put("eacute", new Character((char)233));
- charTable.put("ecirc", new Character((char)234));
- charTable.put("euml", new Character((char)235));
- charTable.put("igrave", new Character((char)236));
- charTable.put("iacute", new Character((char)237));
- charTable.put("icirc", new Character((char)238));
- charTable.put("iuml", new Character((char)239));
- charTable.put("eth", new Character((char)240));
- charTable.put("ntilde", new Character((char)241));
- charTable.put("ograve", new Character((char)242));
- charTable.put("oacute", new Character((char)243));
- charTable.put("ocirc", new Character((char)244));
- charTable.put("otilde", new Character((char)245));
- charTable.put("ouml", new Character((char)246));
- charTable.put("divide", new Character((char)247));
- charTable.put("oslash", new Character((char)248));
- charTable.put("ugrave", new Character((char)249));
- charTable.put("uacute", new Character((char)250));
- charTable.put("ucirc", new Character((char)251));
- charTable.put("uuml", new Character((char)252));
- charTable.put("yacute", new Character((char)253));
- charTable.put("thorn", new Character((char)254));
- charTable.put("yuml", new Character((char)255));
- charTable.put("OElig", new Character((char)338));
- charTable.put("oelig", new Character((char)339));
- charTable.put("Scaron", new Character((char)352));
- charTable.put("scaron", new Character((char)353));
- charTable.put("fnof", new Character((char)402));
- charTable.put("circ", new Character((char)710));
- charTable.put("tilde", new Character((char)732));
- charTable.put("Alpha", new Character((char)913));
- charTable.put("Beta", new Character((char)914));
- charTable.put("Gamma", new Character((char)915));
- charTable.put("Delta", new Character((char)916));
- charTable.put("Epsilon", new Character((char)917));
- charTable.put("Zeta", new Character((char)918));
- charTable.put("Eta", new Character((char)919));
- charTable.put("Theta", new Character((char)920));
- charTable.put("Iota", new Character((char)921));
- charTable.put("Kappa", new Character((char)922));
- charTable.put("Lambda", new Character((char)923));
- charTable.put("Mu", new Character((char)924));
- charTable.put("Nu", new Character((char)925));
- charTable.put("Xi", new Character((char)926));
- charTable.put("Omicron", new Character((char)927));
- charTable.put("Pi", new Character((char)928));
- charTable.put("Rho", new Character((char)929));
- charTable.put("Sigma", new Character((char)931));
- charTable.put("Tau", new Character((char)932));
- charTable.put("Upsilon", new Character((char)933));
- charTable.put("Phi", new Character((char)934));
- charTable.put("Chi", new Character((char)935));
- charTable.put("Psi", new Character((char)936));
- charTable.put("Omega", new Character((char)937));
- charTable.put("alpha", new Character((char)945));
- charTable.put("beta", new Character((char)946));
- charTable.put("gamma", new Character((char)947));
- charTable.put("delta", new Character((char)948));
- charTable.put("epsilon", new Character((char)949));
- charTable.put("zeta", new Character((char)950));
- charTable.put("eta", new Character((char)951));
- charTable.put("theta", new Character((char)952));
- charTable.put("iota", new Character((char)953));
- charTable.put("kappa", new Character((char)954));
- charTable.put("lambda", new Character((char)955));
- charTable.put("mu", new Character((char)956));
- charTable.put("nu", new Character((char)957));
- charTable.put("xi", new Character((char)958));
- charTable.put("omicron", new Character((char)959));
- charTable.put("pi", new Character((char)960));
- charTable.put("rho", new Character((char)961));
- charTable.put("sigmaf", new Character((char)962));
- charTable.put("sigma", new Character((char)963));
- charTable.put("tau", new Character((char)964));
- charTable.put("upsilon", new Character((char)965));
- charTable.put("phi", new Character((char)966));
- charTable.put("chi", new Character((char)967));
- charTable.put("psi", new Character((char)968));
- charTable.put("omega", new Character((char)969));
- charTable.put("thetasym", new Character((char)977));
- charTable.put("upsih", new Character((char)978));
- charTable.put("piv", new Character((char)982));
- charTable.put("ensp", new Character((char)8194));
- charTable.put("emsp", new Character((char)8195));
- charTable.put("thinsp", new Character((char)8201));
- charTable.put("zwnj", new Character((char)8204));
- charTable.put("zwj", new Character((char)8205));
- charTable.put("lrm", new Character((char)8206));
- charTable.put("rlm", new Character((char)8207));
- charTable.put("ndash", new Character((char)8211));
- charTable.put("mdash", new Character((char)8212));
- charTable.put("lsquo", new Character((char)8216));
- charTable.put("rsquo", new Character((char)8217));
- charTable.put("sbquo", new Character((char)8218));
- charTable.put("ldquo", new Character((char)8220));
- charTable.put("rdquo", new Character((char)8221));
- charTable.put("bdquo", new Character((char)8222));
- charTable.put("dagger", new Character((char)8224));
- charTable.put("Dagger", new Character((char)8225));
- charTable.put("bull", new Character((char)8226));
- charTable.put("hellip", new Character((char)8230));
- charTable.put("permil", new Character((char)8240));
- charTable.put("prime", new Character((char)8242));
- charTable.put("Prime", new Character((char)8243));
- charTable.put("lsaquo", new Character((char)8249));
- charTable.put("rsaquo", new Character((char)8250));
- charTable.put("oline", new Character((char)8254));
- charTable.put("frasl", new Character((char)8260));
- charTable.put("euro", new Character((char)8364));
- charTable.put("image", new Character((char)8465));
- charTable.put("weierp", new Character((char)8472));
- charTable.put("real", new Character((char)8476));
- charTable.put("trade", new Character((char)8482));
- charTable.put("alefsym", new Character((char)8501));
- charTable.put("larr", new Character((char)8592));
- charTable.put("uarr", new Character((char)8593));
- charTable.put("rarr", new Character((char)8594));
- charTable.put("darr", new Character((char)8595));
- charTable.put("harr", new Character((char)8596));
- charTable.put("crarr", new Character((char)8629));
- charTable.put("lArr", new Character((char)8656));
- charTable.put("uArr", new Character((char)8657));
- charTable.put("rArr", new Character((char)8658));
- charTable.put("dArr", new Character((char)8659));
- charTable.put("hArr", new Character((char)8660));
- charTable.put("forall", new Character((char)8704));
- charTable.put("part", new Character((char)8706));
- charTable.put("exist", new Character((char)8707));
- charTable.put("empty", new Character((char)8709));
- charTable.put("nabla", new Character((char)8711));
- charTable.put("isin", new Character((char)8712));
- charTable.put("notin", new Character((char)8713));
- charTable.put("ni", new Character((char)8715));
- charTable.put("prod", new Character((char)8719));
- charTable.put("sum", new Character((char)8721));
- charTable.put("minus", new Character((char)8722));
- charTable.put("lowast", new Character((char)8727));
- charTable.put("radic", new Character((char)8730));
- charTable.put("prop", new Character((char)8733));
- charTable.put("infin", new Character((char)8734));
- charTable.put("ang", new Character((char)8736));
- charTable.put("and", new Character((char)8743));
- charTable.put("or", new Character((char)8744));
- charTable.put("cap", new Character((char)8745));
- charTable.put("cup", new Character((char)8746));
- charTable.put("int", new Character((char)8747));
- charTable.put("there4", new Character((char)8756));
- charTable.put("sim", new Character((char)8764));
- charTable.put("cong", new Character((char)8773));
- charTable.put("asymp", new Character((char)8776));
- charTable.put("ne", new Character((char)8800));
- charTable.put("equiv", new Character((char)8801));
- charTable.put("le", new Character((char)8804));
- charTable.put("ge", new Character((char)8805));
- charTable.put("sub", new Character((char)8834));
- charTable.put("sup", new Character((char)8835));
- charTable.put("nsub", new Character((char)8836));
- charTable.put("sube", new Character((char)8838));
- charTable.put("supe", new Character((char)8839));
- charTable.put("oplus", new Character((char)8853));
- charTable.put("otimes", new Character((char)8855));
- charTable.put("perp", new Character((char)8869));
- charTable.put("sdot", new Character((char)8901));
- charTable.put("lceil", new Character((char)8968));
- charTable.put("rceil", new Character((char)8969));
- charTable.put("lfloor", new Character((char)8970));
- charTable.put("rfloor", new Character((char)8971));
- charTable.put("lang", new Character((char)9001));
- charTable.put("rang", new Character((char)9002));
- charTable.put("loz", new Character((char)9674));
- charTable.put("spades", new Character((char)9824));
- charTable.put("clubs", new Character((char)9827));
- charTable.put("hearts", new Character((char)9829));
- charTable.put("diams", new Character((char)9830));
- }
}
Modified: branches/freenet-jfk/src/freenet/support/HTMLEncoder.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/HTMLEncoder.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/HTMLEncoder.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -13,7 +13,8 @@
* @author Unique Person at w3nO30p4p9L81xKTXbCaQBOvUww (via Frost)
*/
public class HTMLEncoder {
- public final static CharTable charTable;
+ public final static CharTable charTable =
+ new CharTable(HTMLEntities.encodeMap);
public static String encode(String s) {
int n = s.length();
@@ -41,282 +42,7 @@
}
}
-
- static {
- HashMap temp = new HashMap();
- temp.put(new Character((char)0), "#0");
- temp.put(new Character((char)34), "quot");
- temp.put(new Character((char)38), "amp");
- temp.put(new Character((char)39), "#39");
- temp.put(new Character((char)60), "lt");
- temp.put(new Character((char)62), "gt");
- temp.put(new Character((char)160), "nbsp");
- temp.put(new Character((char)161), "iexcl");
- temp.put(new Character((char)162), "cent");
- temp.put(new Character((char)163), "pound");
- temp.put(new Character((char)164), "curren");
- temp.put(new Character((char)165), "yen");
- temp.put(new Character((char)166), "brvbar");
- temp.put(new Character((char)167), "sect");
- temp.put(new Character((char)168), "uml");
- temp.put(new Character((char)169), "copy");
- temp.put(new Character((char)170), "ordf");
- temp.put(new Character((char)171), "laquo");
- temp.put(new Character((char)172), "not");
- temp.put(new Character((char)173), "shy");
- temp.put(new Character((char)174), "reg");
- temp.put(new Character((char)175), "macr");
- temp.put(new Character((char)176), "deg");
- temp.put(new Character((char)177), "plusmn");
- temp.put(new Character((char)178), "sup2");
- temp.put(new Character((char)179), "sup3");
- temp.put(new Character((char)180), "acute");
- temp.put(new Character((char)181), "micro");
- temp.put(new Character((char)182), "para");
- temp.put(new Character((char)183), "middot");
- temp.put(new Character((char)184), "cedil");
- temp.put(new Character((char)185), "sup1");
- temp.put(new Character((char)186), "ordm");
- temp.put(new Character((char)187), "raquo");
- temp.put(new Character((char)188), "frac14");
- temp.put(new Character((char)189), "frac12");
- temp.put(new Character((char)190), "frac34");
- temp.put(new Character((char)191), "iquest");
- temp.put(new Character((char)192), "Agrave");
- temp.put(new Character((char)193), "Aacute");
- temp.put(new Character((char)194), "Acirc");
- temp.put(new Character((char)195), "Atilde");
- temp.put(new Character((char)196), "Auml");
- temp.put(new Character((char)197), "Aring");
- temp.put(new Character((char)198), "AElig");
- temp.put(new Character((char)199), "Ccedil");
- temp.put(new Character((char)200), "Egrave");
- temp.put(new Character((char)201), "Eacute");
- temp.put(new Character((char)202), "Ecirc");
- temp.put(new Character((char)203), "Euml");
- temp.put(new Character((char)204), "Igrave");
- temp.put(new Character((char)205), "Iacute");
- temp.put(new Character((char)206), "Icirc");
- temp.put(new Character((char)207), "Iuml");
- temp.put(new Character((char)208), "ETH");
- temp.put(new Character((char)209), "Ntilde");
- temp.put(new Character((char)210), "Ograve");
- temp.put(new Character((char)211), "Oacute");
- temp.put(new Character((char)212), "Ocirc");
- temp.put(new Character((char)213), "Otilde");
- temp.put(new Character((char)214), "Ouml");
- temp.put(new Character((char)215), "times");
- temp.put(new Character((char)216), "Oslash");
- temp.put(new Character((char)217), "Ugrave");
- temp.put(new Character((char)218), "Uacute");
- temp.put(new Character((char)219), "Ucirc");
- temp.put(new Character((char)220), "Uuml");
- temp.put(new Character((char)221), "Yacute");
- temp.put(new Character((char)222), "THORN");
- temp.put(new Character((char)223), "szlig");
- temp.put(new Character((char)224), "agrave");
- temp.put(new Character((char)225), "aacute");
- temp.put(new Character((char)226), "acirc");
- temp.put(new Character((char)227), "atilde");
- temp.put(new Character((char)228), "auml");
- temp.put(new Character((char)229), "aring");
- temp.put(new Character((char)230), "aelig");
- temp.put(new Character((char)231), "ccedil");
- temp.put(new Character((char)232), "egrave");
- temp.put(new Character((char)233), "eacute");
- temp.put(new Character((char)234), "ecirc");
- temp.put(new Character((char)235), "euml");
- temp.put(new Character((char)236), "igrave");
- temp.put(new Character((char)237), "iacute");
- temp.put(new Character((char)238), "icirc");
- temp.put(new Character((char)239), "iuml");
- temp.put(new Character((char)240), "eth");
- temp.put(new Character((char)241), "ntilde");
- temp.put(new Character((char)242), "ograve");
- temp.put(new Character((char)243), "oacute");
- temp.put(new Character((char)244), "ocirc");
- temp.put(new Character((char)245), "otilde");
- temp.put(new Character((char)246), "ouml");
- temp.put(new Character((char)247), "divide");
- temp.put(new Character((char)248), "oslash");
- temp.put(new Character((char)249), "ugrave");
- temp.put(new Character((char)250), "uacute");
- temp.put(new Character((char)251), "ucirc");
- temp.put(new Character((char)252), "uuml");
- temp.put(new Character((char)253), "yacute");
- temp.put(new Character((char)254), "thorn");
- temp.put(new Character((char)255), "yuml");
- temp.put(new Character((char)260), "#260");
- temp.put(new Character((char)261), "#261");
- temp.put(new Character((char)262), "#262");
- temp.put(new Character((char)263), "#263");
- temp.put(new Character((char)280), "#280");
- temp.put(new Character((char)281), "#281");
- temp.put(new Character((char)321), "#321");
- temp.put(new Character((char)322), "#322");
- temp.put(new Character((char)323), "#323");
- temp.put(new Character((char)324), "#324");
- temp.put(new Character((char)338), "OElig");
- temp.put(new Character((char)339), "oelig");
- temp.put(new Character((char)346), "#346");
- temp.put(new Character((char)347), "#347");
- temp.put(new Character((char)352), "Scaron");
- temp.put(new Character((char)353), "scaron");
- temp.put(new Character((char)376), "Yuml");
- temp.put(new Character((char)377), "#377");
- temp.put(new Character((char)378), "#378");
- temp.put(new Character((char)379), "#379");
- temp.put(new Character((char)380), "#380");
- temp.put(new Character((char)402), "fnof");
- temp.put(new Character((char)710), "circ");
- temp.put(new Character((char)732), "tilde");
- temp.put(new Character((char)913), "Alpha");
- temp.put(new Character((char)914), "Beta");
- temp.put(new Character((char)915), "Gamma");
- temp.put(new Character((char)916), "Delta");
- temp.put(new Character((char)917), "Epsilon");
- temp.put(new Character((char)918), "Zeta");
- temp.put(new Character((char)919), "Eta");
- temp.put(new Character((char)920), "Theta");
- temp.put(new Character((char)921), "Iota");
- temp.put(new Character((char)922), "Kappa");
- temp.put(new Character((char)923), "Lambda");
- temp.put(new Character((char)924), "Mu");
- temp.put(new Character((char)925), "Nu");
- temp.put(new Character((char)926), "Xi");
- temp.put(new Character((char)927), "Omicron");
- temp.put(new Character((char)928), "Pi");
- temp.put(new Character((char)929), "Rho");
- temp.put(new Character((char)931), "Sigma");
- temp.put(new Character((char)932), "Tau");
- temp.put(new Character((char)933), "Upsilon");
- temp.put(new Character((char)934), "Phi");
- temp.put(new Character((char)935), "Chi");
- temp.put(new Character((char)936), "Psi");
- temp.put(new Character((char)937), "Omega");
- temp.put(new Character((char)945), "alpha");
- temp.put(new Character((char)946), "beta");
- temp.put(new Character((char)947), "gamma");
- temp.put(new Character((char)948), "delta");
- temp.put(new Character((char)949), "epsilon");
- temp.put(new Character((char)950), "zeta");
- temp.put(new Character((char)951), "eta");
- temp.put(new Character((char)952), "theta");
- temp.put(new Character((char)953), "iota");
- temp.put(new Character((char)954), "kappa");
- temp.put(new Character((char)955), "lambda");
- temp.put(new Character((char)956), "mu");
- temp.put(new Character((char)957), "nu");
- temp.put(new Character((char)958), "xi");
- temp.put(new Character((char)959), "omicron");
- temp.put(new Character((char)960), "pi");
- temp.put(new Character((char)961), "rho");
- temp.put(new Character((char)962), "sigmaf");
- temp.put(new Character((char)963), "sigma");
- temp.put(new Character((char)964), "tau");
- temp.put(new Character((char)965), "upsilon");
- temp.put(new Character((char)966), "phi");
- temp.put(new Character((char)967), "chi");
- temp.put(new Character((char)968), "psi");
- temp.put(new Character((char)969), "omega");
- temp.put(new Character((char)977), "thetasym");
- temp.put(new Character((char)978), "upsih");
- temp.put(new Character((char)982), "piv");
- temp.put(new Character((char)8194), "ensp");
- temp.put(new Character((char)8195), "emsp");
- temp.put(new Character((char)8201), "thinsp");
- temp.put(new Character((char)8204), "zwnj");
- temp.put(new Character((char)8205), "zwj");
- temp.put(new Character((char)8206), "lrm");
- temp.put(new Character((char)8207), "rlm");
- temp.put(new Character((char)8211), "ndash");
- temp.put(new Character((char)8212), "mdash");
- temp.put(new Character((char)8216), "lsquo");
- temp.put(new Character((char)8217), "rsquo");
- temp.put(new Character((char)8218), "sbquo");
- temp.put(new Character((char)8220), "ldquo");
- temp.put(new Character((char)8221), "rdquo");
- temp.put(new Character((char)8222), "bdquo");
- temp.put(new Character((char)8224), "dagger");
- temp.put(new Character((char)8225), "Dagger");
- temp.put(new Character((char)8226), "bull");
- temp.put(new Character((char)8230), "hellip");
- temp.put(new Character((char)8240), "permil");
- temp.put(new Character((char)8242), "prime");
- temp.put(new Character((char)8243), "Prime");
- temp.put(new Character((char)8249), "lsaquo");
- temp.put(new Character((char)8250), "rsaquo");
- temp.put(new Character((char)8254), "oline");
- temp.put(new Character((char)8260), "frasl");
- temp.put(new Character((char)8364), "euro");
- temp.put(new Character((char)8465), "image");
- temp.put(new Character((char)8472), "weierp");
- temp.put(new Character((char)8476), "real");
- temp.put(new Character((char)8482), "trade");
- temp.put(new Character((char)8501), "alefsym");
- temp.put(new Character((char)8592), "larr");
- temp.put(new Character((char)8593), "uarr");
- temp.put(new Character((char)8594), "rarr");
- temp.put(new Character((char)8595), "darr");
- temp.put(new Character((char)8596), "harr");
- temp.put(new Character((char)8629), "crarr");
- temp.put(new Character((char)8656), "lArr");
- temp.put(new Character((char)8657), "uArr");
- temp.put(new Character((char)8658), "rArr");
- temp.put(new Character((char)8659), "dArr");
- temp.put(new Character((char)8660), "hArr");
- temp.put(new Character((char)8704), "forall");
- temp.put(new Character((char)8706), "part");
- temp.put(new Character((char)8707), "exist");
- temp.put(new Character((char)8709), "empty");
- temp.put(new Character((char)8711), "nabla");
- temp.put(new Character((char)8712), "isin");
- temp.put(new Character((char)8713), "notin");
- temp.put(new Character((char)8715), "ni");
- temp.put(new Character((char)8719), "prod");
- temp.put(new Character((char)8721), "sum");
- temp.put(new Character((char)8722), "minus");
- temp.put(new Character((char)8727), "lowast");
- temp.put(new Character((char)8730), "radic");
- temp.put(new Character((char)8733), "prop");
- temp.put(new Character((char)8734), "infin");
- temp.put(new Character((char)8736), "ang");
- temp.put(new Character((char)8743), "and");
- temp.put(new Character((char)8744), "or");
- temp.put(new Character((char)8745), "cap");
- temp.put(new Character((char)8746), "cup");
- temp.put(new Character((char)8747), "int");
- temp.put(new Character((char)8756), "there4");
- temp.put(new Character((char)8764), "sim");
- temp.put(new Character((char)8773), "cong");
- temp.put(new Character((char)8776), "asymp");
- temp.put(new Character((char)8800), "ne");
- temp.put(new Character((char)8801), "equiv");
- temp.put(new Character((char)8804), "le");
- temp.put(new Character((char)8805), "ge");
- temp.put(new Character((char)8834), "sub");
- temp.put(new Character((char)8835), "sup");
- temp.put(new Character((char)8836), "nsub");
- temp.put(new Character((char)8838), "sube");
- temp.put(new Character((char)8839), "supe");
- temp.put(new Character((char)8853), "oplus");
- temp.put(new Character((char)8855), "otimes");
- temp.put(new Character((char)8869), "perp");
- temp.put(new Character((char)8901), "sdot");
- temp.put(new Character((char)8968), "lceil");
- temp.put(new Character((char)8969), "rceil");
- temp.put(new Character((char)8970), "lfloor");
- temp.put(new Character((char)8971), "rfloor");
- temp.put(new Character((char)9001), "lang");
- temp.put(new Character((char)9002), "rang");
- temp.put(new Character((char)9674), "loz");
- temp.put(new Character((char)9824), "spades");
- temp.put(new Character((char)9827), "clubs");
- temp.put(new Character((char)9829), "hearts");
- temp.put(new Character((char)9830), "diams");
- charTable = new CharTable(temp);
- }
-
+
private final static class CharTable{
private char[] chars;
private String[] strings;
Copied: branches/freenet-jfk/src/freenet/support/HTMLEntities.java (from rev
14796, trunk/freenet/src/freenet/support/HTMLEntities.java)
===================================================================
--- branches/freenet-jfk/src/freenet/support/HTMLEntities.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/support/HTMLEntities.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,328 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+
+import java.util.HashMap;
+
+
+/**
+ * Class that provides data structures filled with
+ * HTML Entities and correspondant char value
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public final class HTMLEntities {
+
+ /**
+ * a Map where the HTML Entity is the
+ * value and the correspondant char is
+ * the key
+ */
+ public static final HashMap encodeMap;
+
+ /**
+ * a Map where the HTML Entity is the
+ * key and the correspondant char is
+ * the value
+ */
+ public static final HashMap decodeMap;
+
+ private static final Object[][] charArray = {
+ {new Character((char)0), "#0"},
+ {new Character((char)34), "quot"},
+ {new Character((char)38), "amp"},
+ {new Character((char)39), "#39"},
+ {new Character((char)60), "lt"},
+ {new Character((char)62), "gt"},
+ {new Character((char)160), "nbsp"},
+ {new Character((char)161), "iexcl"},
+ {new Character((char)162), "cent"},
+ {new Character((char)163), "pound"},
+ {new Character((char)164), "curren"},
+ {new Character((char)165), "yen"},
+ {new Character((char)166), "brvbar"},
+ {new Character((char)167), "sect"},
+ {new Character((char)168), "uml"},
+ {new Character((char)169), "copy"},
+ {new Character((char)170), "ordf"},
+ {new Character((char)171), "laquo"},
+ {new Character((char)172), "not"},
+ {new Character((char)173), "shy"},
+ {new Character((char)174), "reg"},
+ {new Character((char)175), "macr"},
+ {new Character((char)176), "deg"},
+ {new Character((char)177), "plusmn"},
+ {new Character((char)178), "sup2"},
+ {new Character((char)179), "sup3"},
+ {new Character((char)180), "acute"},
+ {new Character((char)181), "micro"},
+ {new Character((char)182), "para"},
+ {new Character((char)183), "middot"},
+ {new Character((char)184), "cedil"},
+ {new Character((char)185), "sup1"},
+ {new Character((char)186), "ordm"},
+ {new Character((char)187), "raquo"},
+ {new Character((char)188), "frac14"},
+ {new Character((char)189), "frac12"},
+ {new Character((char)190), "frac34"},
+ {new Character((char)191), "iquest"},
+ {new Character((char)192), "Agrave"},
+ {new Character((char)193), "Aacute"},
+ {new Character((char)194), "Acirc"},
+ {new Character((char)195), "Atilde"},
+ {new Character((char)196), "Auml"},
+ {new Character((char)197), "Aring"},
+ {new Character((char)198), "AElig"},
+ {new Character((char)199), "Ccedil"},
+ {new Character((char)200), "Egrave"},
+ {new Character((char)201), "Eacute"},
+ {new Character((char)202), "Ecirc"},
+ {new Character((char)203), "Euml"},
+ {new Character((char)204), "Igrave"},
+ {new Character((char)205), "Iacute"},
+ {new Character((char)206), "Icirc"},
+ {new Character((char)207), "Iuml"},
+ {new Character((char)208), "ETH"},
+ {new Character((char)209), "Ntilde"},
+ {new Character((char)210), "Ograve"},
+ {new Character((char)211), "Oacute"},
+ {new Character((char)212), "Ocirc"},
+ {new Character((char)213), "Otilde"},
+ {new Character((char)214), "Ouml"},
+ {new Character((char)215), "times"},
+ {new Character((char)216), "Oslash"},
+ {new Character((char)217), "Ugrave"},
+ {new Character((char)218), "Uacute"},
+ {new Character((char)219), "Ucirc"},
+ {new Character((char)220), "Uuml"},
+ {new Character((char)221), "Yacute"},
+ {new Character((char)222), "THORN"},
+ {new Character((char)223), "szlig"},
+ {new Character((char)224), "agrave"},
+ {new Character((char)225), "aacute"},
+ {new Character((char)226), "acirc"},
+ {new Character((char)227), "atilde"},
+ {new Character((char)228), "auml"},
+ {new Character((char)229), "aring"},
+ {new Character((char)230), "aelig"},
+ {new Character((char)231), "ccedil"},
+ {new Character((char)232), "egrave"},
+ {new Character((char)233), "eacute"},
+ {new Character((char)234), "ecirc"},
+ {new Character((char)235), "euml"},
+ {new Character((char)236), "igrave"},
+ {new Character((char)237), "iacute"},
+ {new Character((char)238), "icirc"},
+ {new Character((char)239), "iuml"},
+ {new Character((char)240), "eth"},
+ {new Character((char)241), "ntilde"},
+ {new Character((char)242), "ograve"},
+ {new Character((char)243), "oacute"},
+ {new Character((char)244), "ocirc"},
+ {new Character((char)245), "otilde"},
+ {new Character((char)246), "ouml"},
+ {new Character((char)247), "divide"},
+ {new Character((char)248), "oslash"},
+ {new Character((char)249), "ugrave"},
+ {new Character((char)250), "uacute"},
+ {new Character((char)251), "ucirc"},
+ {new Character((char)252), "uuml"},
+ {new Character((char)253), "yacute"},
+ {new Character((char)254), "thorn"},
+ {new Character((char)255), "yuml"},
+ {new Character((char)260), "#260"},
+ {new Character((char)261), "#261"},
+ {new Character((char)262), "#262"},
+ {new Character((char)263), "#263"},
+ {new Character((char)280), "#280"},
+ {new Character((char)281), "#281"},
+ {new Character((char)321), "#321"},
+ {new Character((char)322), "#322"},
+ {new Character((char)323), "#323"},
+ {new Character((char)324), "#324"},
+ {new Character((char)338), "OElig"},
+ {new Character((char)339), "oelig"},
+ {new Character((char)346), "#346"},
+ {new Character((char)347), "#347"},
+ {new Character((char)352), "Scaron"},
+ {new Character((char)353), "scaron"},
+ {new Character((char)376), "Yuml"},
+ {new Character((char)377), "#377"},
+ {new Character((char)378), "#378"},
+ {new Character((char)379), "#379"},
+ {new Character((char)380), "#380"},
+ {new Character((char)402), "fnof"},
+ {new Character((char)710), "circ"},
+ {new Character((char)732), "tilde"},
+ {new Character((char)913), "Alpha"},
+ {new Character((char)914), "Beta"},
+ {new Character((char)915), "Gamma"},
+ {new Character((char)916), "Delta"},
+ {new Character((char)917), "Epsilon"},
+ {new Character((char)918), "Zeta"},
+ {new Character((char)919), "Eta"},
+ {new Character((char)920), "Theta"},
+ {new Character((char)921), "Iota"},
+ {new Character((char)922), "Kappa"},
+ {new Character((char)923), "Lambda"},
+ {new Character((char)924), "Mu"},
+ {new Character((char)925), "Nu"},
+ {new Character((char)926), "Xi"},
+ {new Character((char)927), "Omicron"},
+ {new Character((char)928), "Pi"},
+ {new Character((char)929), "Rho"},
+ {new Character((char)931), "Sigma"},
+ {new Character((char)932), "Tau"},
+ {new Character((char)933), "Upsilon"},
+ {new Character((char)934), "Phi"},
+ {new Character((char)935), "Chi"},
+ {new Character((char)936), "Psi"},
+ {new Character((char)937), "Omega"},
+ {new Character((char)945), "alpha"},
+ {new Character((char)946), "beta"},
+ {new Character((char)947), "gamma"},
+ {new Character((char)948), "delta"},
+ {new Character((char)949), "epsilon"},
+ {new Character((char)950), "zeta"},
+ {new Character((char)951), "eta"},
+ {new Character((char)952), "theta"},
+ {new Character((char)953), "iota"},
+ {new Character((char)954), "kappa"},
+ {new Character((char)955), "lambda"},
+ {new Character((char)956), "mu"},
+ {new Character((char)957), "nu"},
+ {new Character((char)958), "xi"},
+ {new Character((char)959), "omicron"},
+ {new Character((char)960), "pi"},
+ {new Character((char)961), "rho"},
+ {new Character((char)962), "sigmaf"},
+ {new Character((char)963), "sigma"},
+ {new Character((char)964), "tau"},
+ {new Character((char)965), "upsilon"},
+ {new Character((char)966), "phi"},
+ {new Character((char)967), "chi"},
+ {new Character((char)968), "psi"},
+ {new Character((char)969), "omega"},
+ {new Character((char)977), "thetasym"},
+ {new Character((char)978), "upsih"},
+ {new Character((char)982), "piv"},
+ {new Character((char)8194), "ensp"},
+ {new Character((char)8195), "emsp"},
+ {new Character((char)8201), "thinsp"},
+ {new Character((char)8204), "zwnj"},
+ {new Character((char)8205), "zwj"},
+ {new Character((char)8206), "lrm"},
+ {new Character((char)8207), "rlm"},
+ {new Character((char)8211), "ndash"},
+ {new Character((char)8212), "mdash"},
+ {new Character((char)8216), "lsquo"},
+ {new Character((char)8217), "rsquo"},
+ {new Character((char)8218), "sbquo"},
+ {new Character((char)8220), "ldquo"},
+ {new Character((char)8221), "rdquo"},
+ {new Character((char)8222), "bdquo"},
+ {new Character((char)8224), "dagger"},
+ {new Character((char)8225), "Dagger"},
+ {new Character((char)8226), "bull"},
+ {new Character((char)8230), "hellip"},
+ {new Character((char)8240), "permil"},
+ {new Character((char)8242), "prime"},
+ {new Character((char)8243), "Prime"},
+ {new Character((char)8249), "lsaquo"},
+ {new Character((char)8250), "rsaquo"},
+ {new Character((char)8254), "oline"},
+ {new Character((char)8260), "frasl"},
+ {new Character((char)8364), "euro"},
+ {new Character((char)8465), "image"},
+ {new Character((char)8472), "weierp"},
+ {new Character((char)8476), "real"},
+ {new Character((char)8482), "trade"},
+ {new Character((char)8501), "alefsym"},
+ {new Character((char)8592), "larr"},
+ {new Character((char)8593), "uarr"},
+ {new Character((char)8594), "rarr"},
+ {new Character((char)8595), "darr"},
+ {new Character((char)8596), "harr"},
+ {new Character((char)8629), "crarr"},
+ {new Character((char)8656), "lArr"},
+ {new Character((char)8657), "uArr"},
+ {new Character((char)8658), "rArr"},
+ {new Character((char)8659), "dArr"},
+ {new Character((char)8660), "hArr"},
+ {new Character((char)8704), "forall"},
+ {new Character((char)8706), "part"},
+ {new Character((char)8707), "exist"},
+ {new Character((char)8709), "empty"},
+ {new Character((char)8711), "nabla"},
+ {new Character((char)8712), "isin"},
+ {new Character((char)8713), "notin"},
+ {new Character((char)8715), "ni"},
+ {new Character((char)8719), "prod"},
+ {new Character((char)8721), "sum"},
+ {new Character((char)8722), "minus"},
+ {new Character((char)8727), "lowast"},
+ {new Character((char)8730), "radic"},
+ {new Character((char)8733), "prop"},
+ {new Character((char)8734), "infin"},
+ {new Character((char)8736), "ang"},
+ {new Character((char)8743), "and"},
+ {new Character((char)8744), "or"},
+ {new Character((char)8745), "cap"},
+ {new Character((char)8746), "cup"},
+ {new Character((char)8747), "int"},
+ {new Character((char)8756), "there4"},
+ {new Character((char)8764), "sim"},
+ {new Character((char)8773), "cong"},
+ {new Character((char)8776), "asymp"},
+ {new Character((char)8800), "ne"},
+ {new Character((char)8801), "equiv"},
+ {new Character((char)8804), "le"},
+ {new Character((char)8805), "ge"},
+ {new Character((char)8834), "sub"},
+ {new Character((char)8835), "sup"},
+ {new Character((char)8836), "nsub"},
+ {new Character((char)8838), "sube"},
+ {new Character((char)8839), "supe"},
+ {new Character((char)8853), "oplus"},
+ {new Character((char)8855), "otimes"},
+ {new Character((char)8869), "perp"},
+ {new Character((char)8901), "sdot"},
+ {new Character((char)8968), "lceil"},
+ {new Character((char)8969), "rceil"},
+ {new Character((char)8970), "lfloor"},
+ {new Character((char)8971), "rfloor"},
+ {new Character((char)9001), "lang"},
+ {new Character((char)9002), "rang"},
+ {new Character((char)9674), "loz"},
+ {new Character((char)9824), "spades"},
+ {new Character((char)9827), "clubs"},
+ {new Character((char)9829), "hearts"},
+ {new Character((char)9830), "diams"}
+ };
+
+
+ static {
+ encodeMap = new HashMap();
+ decodeMap = new HashMap();
+
+ for(int i=0; i<charArray.length; i++) {
+ encodeMap.put(charArray[i][0],charArray[i][1]);
+ decodeMap.put(charArray[i][1],charArray[i][0]);
+ }
+
+ }
+
+}
Modified: branches/freenet-jfk/src/freenet/support/HTMLNode.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/HTMLNode.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/HTMLNode.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -9,15 +9,13 @@
import java.util.Map;
import java.util.Set;
-import freenet.l10n.L10n;
-
public class HTMLNode {
protected final String name;
private final String content;
- protected final Map attributes = new HashMap();
+ private final Map attributes = new HashMap();
protected final List children = new ArrayList();
@@ -37,10 +35,6 @@
this(name, new String[] { attributeName }, new String[] {
attributeValue }, content);
}
- public HTMLNode(String name, String[] attributeNames, String[]
attributeValues) {
- this(name, attributeNames, attributeValues, null);
- }
-
public HTMLNode(String name, String[] attributeNames, String[]
attributeValues, String content) {
this.name = name.toLowerCase(Locale.ENGLISH);
if ((attributeNames != null) && (attributeValues != null)) {
@@ -51,36 +45,20 @@
attributes.put(attributeNames[attributeIndex],
attributeValues[attributeIndex]);
}
}
- if (content != null) {
- if (!name.equals("#") && !name.equals("%")) {
- addChild(new HTMLNode("#", content));
- this.content = null;
- } else {
- this.content = content;
- }
- } else {
+ if (content != null && !name.equals("#") && !name.equals("%")) {
+ addChild(new HTMLNode("#", content));
this.content = null;
- }
+ } else
+ this.content = content;
}
/**
- * @return the name
- */
- public String getName() {
- return name;
- }
-
- /**
* @return the content
*/
public String getContent() {
return content;
}
- public void addAttribute(String attributeName) {
- addAttribute(attributeName, attributeName);
- }
-
public void addAttribute(String attributeName, String attributeValue) {
attributes.put(attributeName, attributeValue);
}
@@ -95,6 +73,13 @@
public HTMLNode addChild(HTMLNode childNode) {
if (childNode == null) throw new NullPointerException();
+ //since an efficient algorithm to check the loop presence
+ //is not present, at least it checks if we are trying to
+ //addChild the node itself as a child
+ if (childNode.equals(this))
+ throw new IllegalArgumentException("A HTMLNode cannot
be child of himself");
+ if (children.contains(childNode))
+ throw new IllegalArgumentException("Cannot add twice
the same HTMLNode as child");
children.add(childNode);
return childNode;
}
@@ -190,7 +175,7 @@
*/
public static class HTMLDoctype extends HTMLNode {
- protected final String systemUri;
+ private final String systemUri;
/**
*
@@ -205,6 +190,9 @@
*/
public StringBuffer generate(StringBuffer tagBuffer) {
tagBuffer.append("<!DOCTYPE ").append(name).append("
PUBLIC \"").append(systemUri).append("\">\n");
+ //TODO A meaningful exception should be raised
+ // when trying to call the method for a HTMLDoctype
+ // with number of child != 1
return ((HTMLNode) children.get(0)).generate(tagBuffer);
}
Modified: branches/freenet-jfk/src/freenet/support/HexUtil.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/HexUtil.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/HexUtil.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -21,7 +21,7 @@
/**
- * Converts a byte array into a string of upper case hex chars.
+ * Converts a byte array into a string of lower case hex chars.
*
* @param bs
* A byte array
@@ -32,6 +32,8 @@
* @return the string of hex chars.
*/
public static final String bytesToHex(byte[] bs, int off, int length) {
+ if (bs.length <= off || bs.length < off+length)
+ throw new IllegalArgumentException();
StringBuffer sb = new StringBuffer(length * 2);
bytesToHexAppend(bs, off, length, sb);
return sb.toString();
@@ -42,8 +44,10 @@
int off,
int length,
StringBuffer sb) {
+ if (bs.length <= off || bs.length < off+length)
+ throw new IllegalArgumentException();
sb.ensureCapacity(sb.length() + length * 2);
- for (int i = off; (i < (off + length)) && (i < bs.length); i++)
{
+ for (int i = off; i < (off + length); i++) {
sb.append(Character.forDigit((bs[i] >>> 4) & 0xf, 16));
sb.append(Character.forDigit(bs[i] & 0xf, 16));
}
@@ -76,6 +80,7 @@
*/
public static final void hexToBytes(String s, byte[] out, int off)
throws NumberFormatException, IndexOutOfBoundsException {
+
int slen = s.length();
if ((slen % 2) != 0) {
s = '0' + s;
@@ -105,6 +110,9 @@
/**
* Pack the bits in ba into a byte[].
+ *
+ * @param ba : the BitSet
+ * @param size : How many bits shall be taken into account starting
from the LSB?
*/
public final static byte[] bitsToBytes(BitSet ba, int size) {
int bytesAlloc = countBytesForBits(size);
@@ -116,10 +124,10 @@
for(int j=0;j<8;j++) {
int idx = i*8+j;
boolean val =
- idx > size ? false :
+ idx > size - 1 ? false :
ba.get(idx);
s |= val ? (1<<j) : 0;
- if(sb != null) sb.append(val ? '1' : '0');
+ if(logDEBUG) sb.append(val ? '1' : '0');
}
if(s > 255) throw new IllegalStateException("WTF? s =
"+s);
b[i] = (byte)s;
Modified: branches/freenet-jfk/src/freenet/support/LRUHashtable.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/LRUHashtable.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/LRUHashtable.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -58,6 +58,14 @@
}
}
+ public final synchronized Object peekValue() {
+ if ( list.size() > 0 ) {
+ return ((QItem)hash.get(((QItem)list.tail()).obj)).value;
+ } else {
+ return null;
+ }
+ }
+
public final int size() {
return list.size();
}
@@ -121,4 +129,8 @@
}
}
+ public boolean isEmpty() {
+ return list.isEmpty();
+ }
+
}
Modified: branches/freenet-jfk/src/freenet/support/LRUQueue.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/LRUQueue.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/LRUQueue.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -34,6 +34,21 @@
}
/**
+ * push to bottom (least recently used position)
+ */
+ public synchronized void pushLeast(Object obj) {
+ QItem insert = (QItem)hash.get(obj);
+ if (insert == null) {
+ insert = new QItem(obj);
+ hash.put(obj,insert);
+ } else {
+ list.remove(insert);
+ }
+
+ list.push(insert);
+ }
+
+ /**
* @return Least recently pushed Object.
*/
public final synchronized Object pop() {
@@ -95,6 +110,34 @@
return hash.keySet().toArray();
}
+ public synchronized Object[] toArray(Object[] array) {
+ return hash.keySet().toArray(array);
+ }
+
+ public synchronized Object[] toArrayOrdered() {
+ Object[] array = new Object[list.size()];
+ int x = 0;
+ for(Enumeration e =
list.reverseElements();e.hasMoreElements();) {
+ array[x++] = ((QItem)e.nextElement()).obj;
+ }
+ return array;
+ }
+
+ /**
+ * @param array The array to fill in. If it is too small a new array of
the same type will be allocated.
+ */
+ public synchronized Object[] toArrayOrdered(Object[] array) {
+ array = toArray(array);
+ int listSize = list.size();
+ if(array.length != listSize)
+ throw new
IllegalStateException("array.length="+array.length+" but list.size="+listSize);
+ int x = 0;
+ for(Enumeration e =
list.reverseElements();e.hasMoreElements();) {
+ array[x++] = ((QItem)e.nextElement()).obj;
+ }
+ return array;
+ }
+
public synchronized boolean isEmpty() {
return hash.isEmpty();
}
Copied: branches/freenet-jfk/src/freenet/support/MutableBoolean.java (from rev
14796, trunk/freenet/src/freenet/support/MutableBoolean.java)
===================================================================
--- branches/freenet-jfk/src/freenet/support/MutableBoolean.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/support/MutableBoolean.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,15 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.support;
+
+/**
+ * Freely modifiable boolean wrapper.
+ * @author toad
+ *
+ */
+public class MutableBoolean {
+
+ public boolean value;
+
+}
Copied: branches/freenet-jfk/src/freenet/support/PooledExecutor.java (from rev
14796, trunk/freenet/src/freenet/support/PooledExecutor.java)
===================================================================
--- branches/freenet-jfk/src/freenet/support/PooledExecutor.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/support/PooledExecutor.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,139 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.support;
+
+import java.util.ArrayList;
+
+/**
+ * Pooled Executor implementation. Create a thread when we need one, let them
die
+ * after 5 minutes of inactivity.
+ * @author toad
+ */
+public class PooledExecutor implements Executor {
+
+ private final ArrayList runningThreads /* <MyThread> */ = new
ArrayList();
+ private final ArrayList waitingThreads /* <MyThread> */ = new
ArrayList();
+ long threadCounter = 0;
+ private long jobCount;
+ private long jobMisses;
+ private static boolean logMINOR;
+
+ /** Maximum time a thread will wait for a job */
+ static final int TIMEOUT = 5*60*1000;
+
+ public void start() {
+ logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ }
+
+ public void execute(Runnable job, String jobName) {
+ while(true) {
+ MyThread t;
+ boolean mustStart = false;
+ boolean miss = false;
+ synchronized(this) {
+ jobCount++;
+ if(!waitingThreads.isEmpty()) {
+ t = (MyThread)
waitingThreads.remove(waitingThreads.size()-1);
+ } else {
+ // Will be coalesced by thread count
listings if we use "@" or "for"
+ t = new MyThread("Pooled thread
awaiting work @"+(threadCounter++));
+ t.setDaemon(true);
+ mustStart = true;
+ miss = true;
+ }
+ }
+ synchronized(t) {
+ if(!t.alive) continue;
+ if(t.nextJob != null) continue;
+ t.nextJob = job;
+ if(!mustStart)
+ // It is possible that we could get a
wierd race condition with
+ // notify()/wait() signalling on a
thread being used by higher
+ // level code. So we'd best use
notifyAll().
+ t.notifyAll();
+ }
+ t.setName(jobName);
+ if(mustStart) {
+ t.start();
+ synchronized(this) {
+ runningThreads.add(t);
+ if(miss)
+ jobMisses++;
+ if(logMINOR)
+ Logger.minor(this, "Jobs:
"+jobMisses+" misses of "+jobCount);
+ }
+ }
+ return;
+ }
+ }
+
+ public synchronized int waitingThreads() {
+ return waitingThreads.size();
+ }
+
+ class MyThread extends Thread {
+
+ final String defaultName;
+ boolean alive = true;
+ Runnable nextJob;
+
+ public MyThread(String defaultName) {
+ super(defaultName);
+ this.defaultName = defaultName;
+ }
+
+ public void run() {
+ long ranJobs = 0;
+ while(true) {
+ Runnable job;
+
+ synchronized(this) {
+ job = nextJob;
+ nextJob = null;
+ }
+
+ if(job == null) {
+ synchronized(PooledExecutor.this) {
+ waitingThreads.add(this);
+ }
+ synchronized(this) {
+ if(nextJob == null) {
+
this.setName(defaultName);
+ try {
+ wait(TIMEOUT);
+ } catch
(InterruptedException e) {
+ // Ignore
+ }
+ }
+ job = nextJob;
+ nextJob = null;
+ if(job == null) {
+ alive = false;
+ // execute() won't give
us another job if alive = false
+ }
+ }
+ synchronized(PooledExecutor.this) {
+ waitingThreads.remove(this);
+ if(!alive) {
+
runningThreads.remove(this);
+ if(logMINOR)
+
Logger.minor(this, "Exiting having executed "+ranJobs+" jobs : "+this);
+ return;
+ }
+ }
+ }
+
+ // Run the job
+ try {
+ job.run();
+ } catch (Throwable t) {
+ Logger.error(this, "Caught "+t+"
running job "+job, t);
+ }
+ ranJobs++;
+ }
+ }
+
+ }
+
+}
Modified: branches/freenet-jfk/src/freenet/support/RandomGrabArray.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/RandomGrabArray.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/RandomGrabArray.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -66,7 +66,6 @@
oret = ret;
if(ret.isCancelled()) ret = null;
if(ret != null && !ret.canRemove()) {
- ret.setParentGrabArray(null);
return ret;
}
do {
Modified: branches/freenet-jfk/src/freenet/support/ShortBuffer.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/ShortBuffer.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/ShortBuffer.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -56,7 +56,7 @@
public ShortBuffer(byte[] data) {
_start = 0;
if(data.length > Short.MAX_VALUE)
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("Too big: "+data.length);
_length = (short)data.length;
_data = data;
}
Modified: branches/freenet-jfk/src/freenet/support/SimpleFieldSet.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/SimpleFieldSet.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/SimpleFieldSet.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -33,8 +33,23 @@
private String endMarker;
private final boolean shortLived;
static public final char MULTI_LEVEL_CHAR = '.';
+ static public final char MULTI_VALUE_CHAR = ';';
+ static public final char KEYVALUE_SEPARATOR_CHAR = '=';
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
/**
+ * Create a SimpleFieldSet.
+ * @param shortLived If false, strings will be interned to ensure that
they use as
+ * little memory as possible. Only set to true if the SFS will be
short-lived or
+ * small.
+ */
+ public SimpleFieldSet(boolean shortLived) {
+ values = new HashMap();
+ subsets = null;
+ this.shortLived = shortLived;
+ }
+
+ /**
* Construct a SimpleFieldSet from reading a BufferedReader.
* @param br
* @param allowMultiple If true, multiple lines with the same field name
will be
@@ -46,9 +61,7 @@
* problem.
*/
public SimpleFieldSet(BufferedReader br, boolean allowMultiple, boolean
shortLived) throws IOException {
- values = new HashMap();
- subsets = null;
- this.shortLived = shortLived;
+ this(shortLived);
read(br, allowMultiple);
}
@@ -61,35 +74,23 @@
}
public SimpleFieldSet(LineReader lis, int maxLineLength, int
lineBufferSize, boolean tolerant, boolean utf8OrIso88591, boolean
allowMultiple, boolean shortLived) throws IOException {
- values = new HashMap();
- subsets = null;
- this.shortLived = shortLived;
+ this(shortLived);
read(lis, maxLineLength, lineBufferSize, tolerant, utf8OrIso88591,
allowMultiple);
}
-
- /**
- * Create a SimpleFieldSet.
- * @param shortLived If false, strings will be interned to ensure that
they use as
- * little memory as possible. Only set to true if the SFS will be
short-lived or
- * small.
- */
- public SimpleFieldSet(boolean shortLived) {
- values = new HashMap();
- subsets = null;
- this.shortLived = shortLived;
- }
/**
* Construct from a string.
+ * String format:
+ * blah=blah
+ * blah=blah
+ * End
* @param shortLived If false, strings will be interned to ensure that
they use as
* little memory as possible. Only set to true if the SFS will be
short-lived or
* small.
* @throws IOException if the string is too short or invalid.
*/
public SimpleFieldSet(String content, boolean allowMultiple, boolean
shortLived) throws IOException {
- values = new HashMap();
- subsets = null;
- this.shortLived = shortLived;
+ this(shortLived);
StringReader sr = new StringReader(content);
BufferedReader br = new BufferedReader(sr);
read(br, allowMultiple);
@@ -112,7 +113,7 @@
throw new IOException(); // No end marker!
}
firstLine = false;
- int index = line.indexOf('=');
+ int index = line.indexOf(KEYVALUE_SEPARATOR_CHAR);
if(index >= 0) {
// Mapping
String before = line.substring(0, index);
@@ -149,7 +150,7 @@
}
if((line.length() == 0) && tolerant) continue; // ignore
firstLine = false;
- int index = line.indexOf('=');
+ int index = line.indexOf(KEYVALUE_SEPARATOR_CHAR);
if(index >= 0) {
// Mapping
String before = line.substring(0, index);
@@ -169,8 +170,8 @@
if(idx == -1)
return (String) values.get(key);
else if(idx == 0)
- return null;
- else {
+ return (subset("") == null) ? null :
subset("").get(key.substring(1));
+ else {
if(subsets == null) return null;
String before = key.substring(0, idx);
String after = key.substring(idx+1);
@@ -181,12 +182,14 @@
}
public String[] getAll(String key) {
- return split(get(key));
+ String k = get(key);
+ if(k == null) return null;
+ return split(k);
}
private static final String[] split(String string) {
if(string == null) return new String[0];
- return string.split(";"); // slower???
+ return string.split(String.valueOf(MULTI_VALUE_CHAR)); // slower???
// int index = string.indexOf(';');
// if(index == -1) return null;
// Vector v=new Vector();
@@ -203,7 +206,40 @@
// return (String[]) v.toArray();
}
+ private static final String unsplit(String[] strings) {
+ StringBuffer sb = new StringBuffer();
+ for(int i=0;i<strings.length;i++) {
+ if(i != 0) sb.append(MULTI_VALUE_CHAR);
+ sb.append(strings[i]);
+ }
+ return sb.toString();
+ }
+
/**
+ * Put contents of a fieldset, overwrite old values.
+ */
+ public void putAllOverwrite(SimpleFieldSet fs) {
+ Iterator i = fs.values.keySet().iterator();
+ while(i.hasNext()) {
+ String key = (String) i.next();
+ String hisVal = (String) fs.values.get(key);
+ values.put(key, hisVal); // overwrite old
+ }
+ if(fs.subsets == null) return;
+ i = fs.subsets.keySet().iterator();
+ while(i.hasNext()) {
+ String key = (String) i.next();
+ SimpleFieldSet hisFS = (SimpleFieldSet) fs.subsets.get(key);
+ SimpleFieldSet myFS = (SimpleFieldSet) subsets.get(key);
+ if(myFS != null) {
+ myFS.putAllOverwrite(hisFS);
+ } else {
+ subsets.put(key, hisFS);
+ }
+ }
+ }
+
+ /**
* Set a key to a value. If the value already exists, throw
IllegalStateException.
* @param key The key.
* @param value The value.
@@ -250,7 +286,7 @@
private synchronized final boolean put(String key, String value,
boolean allowMultiple, boolean overwrite) {
int idx;
if(value == null) return true; // valid no-op
- if(value.indexOf('\n') != -1) throw new
IllegalArgumentException("A simplefieldSet can't accept \n !");
+ if(value.indexOf('\n') != -1) throw new
IllegalArgumentException("A simplefieldSet can't accept newlines !");
if((idx = key.indexOf(MULTI_LEVEL_CHAR)) == -1) {
String x = (String) values.get(key);
@@ -259,7 +295,7 @@
values.put(key, value);
} else {
if(!allowMultiple) return false;
- values.put(key, ((String)values.get(key))+ ';'
+value);
+ values.put(key, ((String)values.get(key))+
MULTI_VALUE_CHAR +value);
}
} else {
String before = key.substring(0, idx);
@@ -325,7 +361,7 @@
String value = (String) entry.getValue();
w.write(prefix);
w.write(key);
- w.write('=');
+ w.write(KEYVALUE_SEPARATOR_CHAR);
w.write(value);
w.write('\n');
}
@@ -361,7 +397,7 @@
// Output
for(i=0; i < keys.length; i++)
- w.write(prefix+keys[i]+'='+get(keys[i])+'\n');
+
w.write(prefix+keys[i]+KEYVALUE_SEPARATOR_CHAR+get(keys[i])+'\n');
if(subsets != null) {
String[] orderedPrefixes = (String[])
subsets.keySet().toArray(new String[subsets.size()]);
@@ -438,6 +474,15 @@
KeyIterator subIterator;
String prefix;
+ /**
+ * It provides an iterator for the SimpleSetField
+ * which passes through every key.
+ * (e.g. for key1=value1 key2.sub2=value2 key1.sub=value3
+ * it will provide key1,key2.sub2,key1.sub)
+ * @param a prefix to put BEFORE every key
+ * (e.g. for key1=value, if the iterator is created with prefix
"aPrefix",
+ * it will provide aPrefixkey1
+ */
public KeyIterator(String prefix) {
synchronized(SimpleFieldSet.this) {
valuesIterator = values.keySet().iterator();
@@ -463,10 +508,18 @@
public boolean hasNext() {
synchronized(SimpleFieldSet.this) {
- if(valuesIterator.hasNext()) return true;
- if((subIterator != null) &&
subIterator.hasNext()) return true;
- if(subIterator != null) subIterator = null;
- return false;
+ while(true) {
+ if(valuesIterator.hasNext()) return
true;
+ if((subIterator != null) &&
subIterator.hasNext()) return true;
+ if(subIterator != null) subIterator =
null;
+ if(subsetIterator != null &&
subsetIterator.hasNext()) {
+ String key = (String)
subsetIterator.next();
+ SimpleFieldSet fs =
(SimpleFieldSet) subsets.get(key);
+ String newPrefix = prefix + key
+ MULTI_LEVEL_CHAR;
+ subIterator =
fs.keyIterator(newPrefix);
+ } else
+ return false;
+ }
}
}
@@ -551,6 +604,16 @@
}
}
+ /**
+ * It removes the specified subset.
+ * For example, in a SimpleFieldSet like this:
+ * foo=bar
+ * foo.bar=foobar
+ * foo.bar.boo=foobarboo
+ * calling it with the parameter "foo"
+ * means to drop the second and the third line.
+ * @param is the subset to remove
+ */
public synchronized void removeSubset(String key) {
if(subsets == null) return;
int idx;
@@ -578,11 +641,11 @@
}
public Iterator directSubsetNameIterator() {
- return subsets.keySet().iterator();
+ return (subsets == null) ? null : subsets.keySet().iterator();
}
public String[] namesOfDirectSubsets() {
- return (String[]) subsets.keySet().toArray(new
String[subsets.size()]);
+ return (subsets == null) ? EMPTY_STRING_ARRAY : (String[])
subsets.keySet().toArray(new String[subsets.size()]);
}
public static SimpleFieldSet readFrom(InputStream is, boolean
allowMultiple, boolean shortLived) throws IOException {
@@ -645,6 +708,16 @@
}
}
+ public double getDouble(String key) throws FSParseException {
+ String s = get(key);
+ if(s == null) throw new FSParseException("No key "+key);
+ try {
+ return Double.parseDouble(s);
+ } catch (NumberFormatException e) {
+ throw new FSParseException("Cannot parse "+s+" for
integer "+key);
+ }
+ }
+
public long getLong(String key, long def) {
String s = get(key);
if(s == null) return def;
@@ -664,6 +737,44 @@
throw new FSParseException("Cannot parse "+s+" for long
"+key);
}
}
+
+ public short getShort(String key) throws FSParseException {
+ String s = get(key);
+ if(s == null) throw new FSParseException("No key "+key);
+ try {
+ return Short.parseShort(s);
+ } catch (NumberFormatException e) {
+ throw new FSParseException("Cannot parse "+s+" for
short "+key);
+ }
+ }
+
+ public short getShort(String key, short def) {
+ String s = get(key);
+ if(s == null) return def;
+ try {
+ return Short.parseShort(s);
+ } catch (NumberFormatException e) {
+ return def;
+ }
+ }
+
+ public char getChar(String key) throws FSParseException {
+ String s = get(key);
+ if(s == null) throw new FSParseException("No key "+key);
+ if (s.length() == 1)
+ return s.charAt(0);
+ else
+ throw new FSParseException("Cannot parse "+s+"
for char "+key);
+ }
+
+ public char getChar(String key, char def) {
+ String s = get(key);
+ if(s == null) return def;
+ if (s.length() == 1)
+ return s.charAt(0);
+ else
+ return def;
+ }
public boolean getBoolean(String key, boolean def) {
return Fields.stringToBool(get(key), def);
@@ -678,6 +789,7 @@
public int[] getIntArray(String key) {
String[] strings = getAll(key);
+ if(strings == null) return null;
int[] ret = new int[strings.length];
for(int i=0;i<strings.length;i++) {
try {
@@ -690,4 +802,8 @@
return ret;
}
+ public void putOverwrite(String key, String[] strings) {
+ putOverwrite(key, unsplit(strings));
+ }
+
}
Modified: branches/freenet-jfk/src/freenet/support/StringArray.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/StringArray.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/StringArray.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -20,7 +20,7 @@
if((array != null) && (array.length > 0)){
StringBuffer sb = new StringBuffer();
for(int i=0; i<array.length; i++)
- sb.append(array.toString()+'|');
+ sb.append(array[i].toString()+'|');
return '[' + sb.substring(0, sb.length() -
1).toString() + ']';
}else
return "";
@@ -83,5 +83,19 @@
public static String toString(long[] array) {
return toString(toArray(array));
}
+
+ public static String[] toArray(int[] array) {
+ if((array != null) && (array.length > 0)){
+ String[] result = new String[array.length];
+ for(int i=0; i<array.length; i++)
+ result[i] = Long.toString(array[i]);
+ return result;
+ }else
+ return null;
+ }
+ public static String toString(int[] array) {
+ return toString(toArray(array));
+ }
+
}
Modified: branches/freenet-jfk/src/freenet/support/TimeUtil.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/TimeUtil.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/TimeUtil.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -25,72 +25,102 @@
* Formats milliseconds into a week/day/hour/second/milliseconds string.
*/
public class TimeUtil {
- public static String formatTime(long timeInterval, int maxTerms,
boolean withSecondFractions) {
- StringBuffer sb = new StringBuffer(64);
- long l = timeInterval;
- int termCount = 0;
- //
- int weeks = (int)(l / ((long)7*24*60*60*1000));
- if (weeks > 0) {
+
+ /**
+ * It converts a given time interval into a
+ * week/day/hour/second.milliseconds string.
+ * @param timeInterval interval to convert
+ * @param maxTerms the terms number to display
+ * (e.g. 2 means "h" and "m" if the time could be expressed in hour,
+ * 3 means "h","m","s" in the same example).
+ * The maximum terms number available is 6
+ * @param withSecondFractions if true it displays seconds.milliseconds
+ * @return the formatted String
+ */
+ public static String formatTime(long timeInterval, int maxTerms, boolean
withSecondFractions) {
+
+ if (maxTerms > 6 )
+ throw new IllegalArgumentException();
+
+ StringBuffer sb = new StringBuffer(64);
+ long l = timeInterval;
+ int termCount = 0;
+ //
+ if(l < 0) {
+ sb.append('-');
+ l = l * -1;
+ }
+ if( !withSecondFractions && l < 1000 ) {
+ return "";
+ }
+ if(termCount >= maxTerms) {
+ return sb.toString();
+ }
+ //
+ long weeks = (long)(l / ((long)7*24*60*60*1000));
+ if (weeks > 0) {
sb.append(weeks).append('w');
- termCount++;
- l = l - ((long)weeks * ((long)7*24*60*60*1000));
- }
- //
- int days = (int)(l / ((long)24*60*60*1000));
- if (days > 0) {
+ termCount++;
+ l = l - ((long)weeks * ((long)7*24*60*60*1000));
+ }
+ if(termCount >= maxTerms) {
+ return sb.toString();
+ }
+ //
+ long days = (long)(l / ((long)24*60*60*1000));
+ if (days > 0) {
sb.append(days).append('d');
- termCount++;
- l = l - ((long)days * ((long)24*60*60*1000));
- }
- if(termCount >= maxTerms) {
- return sb.toString();
- }
- //
- int hours = (int)(l / ((long)60*60*1000));
- if (hours > 0) {
+ termCount++;
+ l = l - ((long)days * ((long)24*60*60*1000));
+ }
+ if(termCount >= maxTerms) {
+ return sb.toString();
+ }
+ //
+ long hours = (long)(l / ((long)60*60*1000));
+ if (hours > 0) {
sb.append(hours).append('h');
- termCount++;
- l = l - ((long)hours * ((long)60*60*1000));
- }
- if(termCount >= maxTerms) {
- return sb.toString();
- }
- //
- int minutes = (int)(l / ((long)60*1000));
- if (minutes > 0) {
+ termCount++;
+ l = l - ((long)hours * ((long)60*60*1000));
+ }
+ if(termCount >= maxTerms) {
+ return sb.toString();
+ }
+ //
+ long minutes = (long)(l / ((long)60*1000));
+ if (minutes > 0) {
sb.append(minutes).append('m');
- termCount++;
- l = l - ((long)minutes * ((long)60*1000));
- }
- if(termCount >= maxTerms) {
- return sb.toString();
- }
- if(withSecondFractions && ((maxTerms - termCount) >= 2)) {
- if (l > 0) {
- double fractionalSeconds = ((double) l) /
((double) 1000.0);
- DecimalFormat fix3 = new DecimalFormat("0.000");
+ termCount++;
+ l = l - ((long)minutes * ((long)60*1000));
+ }
+ if(termCount >= maxTerms) {
+ return sb.toString();
+ }
+ if(withSecondFractions && ((maxTerms - termCount) >= 2)) {
+ if (l > 0) {
+ double fractionalSeconds = ((double) l) / ((double) 1000.0);
+ DecimalFormat fix3 = new DecimalFormat("0.000");
sb.append(fix3.format(fractionalSeconds)).append('s');
- termCount++;
- //l = l - ((long)fractionalSeconds *
(long)1000);
- }
- } else {
- int seconds = (int)(l / (long)1000);
- if (seconds > 0) {
+ termCount++;
+ //l = l - ((long)fractionalSeconds * (long)1000);
+ }
+ } else {
+ long seconds = (long)(l / (long)1000);
+ if (seconds > 0) {
sb.append(seconds).append('s');
- termCount++;
- //l = l - ((long)seconds * (long)1000);
- }
- }
- //
- return sb.toString();
- }
-
- public static String formatTime(long timeInterval) {
- return formatTime(timeInterval, 2, false);
- }
-
- public static String formatTime(long timeInterval, int maxTerms) {
- return formatTime(timeInterval, maxTerms, false);
- }
+ termCount++;
+ //l = l - ((long)seconds * (long)1000);
+ }
+ }
+ //
+ return sb.toString();
+ }
+
+ public static String formatTime(long timeInterval) {
+ return formatTime(timeInterval, 2, false);
+ }
+
+ public static String formatTime(long timeInterval, int maxTerms) {
+ return formatTime(timeInterval, maxTerms, false);
+ }
}
Modified: branches/freenet-jfk/src/freenet/support/TokenBucket.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/TokenBucket.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/TokenBucket.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -34,7 +34,11 @@
* @return True if we could acquire the tokens.
*/
public synchronized boolean instantGrab(long tokens) {
+ if(logMINOR)
+ Logger.minor(this, "instant grab: "+tokens+"
current="+current+" max="+max);
addTokens();
+ if(logMINOR)
+ Logger.minor(this, "instant grab: "+tokens+"
current="+current+" max="+max);
if(current > tokens) {
current -= tokens;
if(current > max) current = max;
@@ -173,6 +177,8 @@
public synchronized void addTokens() {
addTokensNoClip();
if(current > max) current = max;
+ if(logMINOR)
+ Logger.minor(this, "addTokens: Clipped,
current="+current);
}
/**
@@ -182,6 +188,8 @@
long add = tokensToAdd();
current += add;
timeLastTick += add * nanosPerTick;
+ if(logMINOR)
+ Logger.minor(this, "addTokensNoClip: Added "+add+"
tokens, current="+current);
// Deliberately do not clip to size at this point; caller must
do this, but it is usually beneficial for the caller to do so.
}
Modified: branches/freenet-jfk/src/freenet/support/URLDecoder.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/URLDecoder.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/URLDecoder.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -3,9 +3,8 @@
* http://www.gnu.org/ for further details of the GPL. */
package freenet.support;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
+import java.io.StringWriter;
/**
* Decode encoded URLs (or parts of URLs). @see URLEncoder.
@@ -41,13 +40,13 @@
if (s.length() == 0)
return "";
int len = s.length();
- ByteArrayOutputStream decodedBytes = new
ByteArrayOutputStream();
+ StringWriter decoded = new StringWriter();
boolean hasDecodedSomething = false;
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
if (Character.isLetterOrDigit(c))
- decodedBytes.write(c);
+ decoded.write(c);
else if (c == '%') {
if (i >= len - 2) {
throw new URLEncodedFormatException(s);
@@ -62,34 +61,25 @@
long read = Fields.hexToLong(hexval);
if (read == 0)
throw new
URLEncodedFormatException("Can't encode" + " 00");
- decodedBytes.write((int) read);
+ decoded.write((int) read);
hasDecodedSomething = true;
} catch (NumberFormatException nfe) {
// Not encoded?
if(tolerant && !hasDecodedSomething) {
- try {
- byte[] buf =
('%'+hexval).getBytes("UTF-8");
- decodedBytes.write(buf,
0, buf.length);
- continue;
- } catch
(UnsupportedEncodingException e) {
- throw new Error(e);
- }
+ decoded.write('%');
+ decoded.write(hexval);
+ continue;
}
throw new
URLEncodedFormatException("Not a two character hex % escape: "+hexval+" in "+s);
}
} else {
- try {
- byte[] encoded =
(""+c).getBytes("UTF-8");
- decodedBytes.write(encoded, 0,
encoded.length);
- } catch (UnsupportedEncodingException e) {
- throw new Error(e);
- }
+ decoded.write(c);
}
}
try {
- decodedBytes.close();
- return new String(decodedBytes.toByteArray(), "utf-8");
+ decoded.close();
+ return decoded.toString();
} catch (IOException ioe1) {
/* if this throws something's wrong */
}
Copied: branches/freenet-jfk/src/freenet/support/WeakHashSet.java (from rev
14796, trunk/freenet/src/freenet/support/WeakHashSet.java)
===================================================================
--- branches/freenet-jfk/src/freenet/support/WeakHashSet.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/support/WeakHashSet.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,80 @@
+package freenet.support;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+public class WeakHashSet implements Set {
+
+ private final WeakHashMap map;
+
+ public WeakHashSet() {
+ map = new WeakHashMap();
+ }
+
+ public boolean add(Object key) {
+ return map.put(key, null) == null;
+ }
+
+ public boolean addAll(Collection arg0) {
+ boolean changed = false;
+ for(Iterator i=arg0.iterator();i.hasNext();) {
+ changed |= add(i.next());
+ }
+ return changed;
+ }
+
+ public void clear() {
+ map.clear();
+ }
+
+ public boolean contains(Object key) {
+ return map.containsKey(key);
+ }
+
+ public boolean containsAll(Collection arg0) {
+ for(Iterator i=arg0.iterator();i.hasNext();) {
+ if(!map.containsKey(i.next())) return false;
+ }
+ return true;
+ }
+
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ public Iterator iterator() {
+ return map.keySet().iterator();
+ }
+
+ public boolean remove(Object key) {
+ return map.remove(key) != null;
+ }
+
+ public boolean removeAll(Collection arg0) {
+ boolean changed = false;
+ for(Iterator i=arg0.iterator();i.hasNext();) {
+ changed |= remove(i.next());
+ }
+ return changed;
+ }
+
+ public boolean retainAll(Collection arg0) {
+ // FIXME
+ throw new UnsupportedOperationException();
+ }
+
+ public int size() {
+ return map.size();
+ }
+
+ public Object[] toArray() {
+ return map.keySet().toArray();
+ }
+
+ public Object[] toArray(Object[] arg0) {
+ return map.keySet().toArray(arg0);
+ }
+
+}
Modified: branches/freenet-jfk/src/freenet/support/compress/GzipCompressor.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/compress/GzipCompressor.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/compress/GzipCompressor.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -24,7 +24,9 @@
os = output.getOutputStream();
gos = new GZIPOutputStream(os);
long written = 0;
- byte[] buffer = new byte[4096];
+ // Bigger input buffer, so can compress all at once.
+ // Won't hurt on I/O either, although most OSs will
only return a page at a time.
+ byte[] buffer = new byte[32768];
while(true) {
int l = (int) Math.min(buffer.length, maxLength
- written);
int x = is.read(buffer, 0, buffer.length);
@@ -65,14 +67,17 @@
byte[] buffer = new byte[4096];
while(true) {
int l = (int) Math.min(buffer.length, maxLength -
written);
- int x = gis.read(buffer, 0, 4096);
+ // We can over-read to determine whether we have
over-read.
+ // We enforce maximum size this way.
+ // FIXME there is probably a better way to do this!
+ int x = gis.read(buffer, 0, buffer.length);
if(l < x) {
Logger.normal(this, "l="+l+", x="+x+",
written="+written+", maxLength="+maxLength+" throwing a
CompressionOutputSizeException");
if(maxCheckSizeBytes > 0) {
written += x;
while(true) {
l = (int)
Math.min(buffer.length, maxLength + maxCheckSizeBytes - written);
- x = gis.read(buffer, 0, 4096);
+ x = gis.read(buffer, 0, l);
if(x <= -1) throw new
CompressionOutputSizeException(written);
if(x == 0) throw new
IOException("Returned zero from read()");
written += x;
Modified: branches/freenet-jfk/src/freenet/support/io/ArrayBucket.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/ArrayBucket.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/ArrayBucket.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -32,7 +32,7 @@
data.add(initdata);
}
- public ArrayBucket(String name) {
+ ArrayBucket(String name) {
data = new ArrayList();
this.name = name;
}
Copied: branches/freenet-jfk/src/freenet/support/io/BaseFileBucket.java (from
rev 14796, trunk/freenet/src/freenet/support/io/BaseFileBucket.java)
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/BaseFileBucket.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/support/io/BaseFileBucket.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,464 @@
+package freenet.support.io;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import org.tanukisoftware.wrapper.WrapperManager;
+
+import freenet.support.Logger;
+import freenet.support.SimpleFieldSet;
+import freenet.support.StringArray;
+import freenet.support.api.Bucket;
+
+public abstract class BaseFileBucket implements Bucket,
SerializableToFieldSetBucket {
+
+ // JVM caches File.size() and there is no way to flush the cache, so we
+ // need to track it ourselves
+ protected long length;
+ protected long fileRestartCounter;
+ /** Has the bucket been freed? If so, no further operations may be done
*/
+ private boolean freed;
+ /** Vector of streams (FileBucketInputStream or FileBucketOutputStream)
which
+ * are open to this file. So we can be sure they are all closed when we
free it.
+ * Can be null. */
+ private Vector streams;
+
+ protected static String tempDir = null;
+
+ public BaseFileBucket(File file) {
+ if(file == null) throw new NullPointerException();
+ this.length = file.length();
+ if(deleteOnExit()) {
+ try {
+ file.deleteOnExit();
+ } catch (NullPointerException e) {
+
if(WrapperManager.hasShutdownHookBeenTriggered()) {
+ Logger.normal(this,
"NullPointerException setting deleteOnExit while shutting down - buggy JVM
code: "+e, e);
+ } else {
+ Logger.error(this, "Caught "+e+" doing
deleteOnExit() for "+file+" - JVM bug ????");
+ }
+ }
+ }
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ synchronized (this) {
+ File file = getFile();
+ if(freed)
+ throw new IOException("File already freed");
+ if(isReadOnly())
+ throw new IOException("Bucket is read-only:
"+this);
+
+ if(createFileOnly() && file.exists())
+ throw new FileExistsException(file);
+
+ if(streams != null && !streams.isEmpty())
+ Logger.error(this, "Streams open on "+this+"
while opening an output stream!: "+streams);
+
+ File tempfile = createFileOnly() ? getTempfile() : file;
+ long streamNumber = ++fileRestartCounter;
+
+ FileBucketOutputStream os =
+ new FileBucketOutputStream(tempfile,
streamNumber);
+
+ if(Logger.shouldLog(Logger.DEBUG, this))
+ Logger.debug(this, "Creating "+os, new
Exception("debug"));
+
+ addStream(os);
+ return os;
+ }
+ }
+
+ private synchronized void addStream(Object stream) {
+ // BaseFileBucket is a very common object, and often very long
lived,
+ // so we need to minimize memory usage even at the cost of
frequent allocations.
+ if(streams == null)
+ streams = new Vector(1,1);
+ streams.add(stream);
+ }
+
+ private synchronized void removeStream(Object stream) {
+ // Race condition is possible
+ if(streams == null) return;
+ streams.remove(stream);
+ if(streams.isEmpty()) streams = null;
+ }
+
+ protected abstract boolean createFileOnly();
+
+ protected abstract boolean deleteOnExit();
+
+ protected abstract boolean deleteOnFinalize();
+
+ protected abstract boolean deleteOnFree();
+
+ /**
+ * Create a temporary file in the same directory as this file.
+ */
+ protected File getTempfile() throws IOException {
+ File file = getFile();
+ File f = File.createTempFile(file.getName(), ".freenet-tmp",
file.getParentFile());
+ if(deleteOnExit()) f.deleteOnExit();
+ return f;
+ }
+
+ protected synchronized void resetLength() {
+ length = 0;
+ }
+
+ /**
+ * Internal OutputStream impl.
+ * If createFileOnly is set, we won't overwrite an existing file, and
we write to a temp file
+ * then rename over the target. Note that we can't use createNewFile
then new FOS() because while
+ * createNewFile is atomic, the combination is not, so if we do it we
are vulnerable to symlink
+ * attacks.
+ * @author toad
+ */
+ class FileBucketOutputStream extends FileOutputStream {
+
+ private long restartCount;
+ private File tempfile;
+ private boolean closed;
+
+ protected FileBucketOutputStream(
+ File tempfile, long restartCount)
+ throws FileNotFoundException {
+ super(tempfile, false);
+ if(Logger.shouldLog(Logger.MINOR, this))
+ Logger.minor(this, "Writing to "+tempfile+" for
"+getFile());
+ this.tempfile = tempfile;
+ resetLength();
+ this.restartCount = restartCount;
+ closed = false;
+ }
+
+ protected void confirmWriteSynchronized() throws IOException {
+ synchronized(BaseFileBucket.this) {
+ if (fileRestartCounter > restartCount)
+ throw new
IllegalStateException("writing to file after restart");
+ if(freed)
+ throw new IOException("writing to file
after it has been freed");
+ }
+ if(isReadOnly())
+ throw new IOException("File is read-only");
+
+ }
+
+ public void write(byte[] b) throws IOException {
+ synchronized (BaseFileBucket.this) {
+ confirmWriteSynchronized();
+ super.write(b);
+ length += b.length;
+ }
+ }
+
+ public void write(byte[] b, int off, int len) throws
IOException {
+ synchronized (BaseFileBucket.this) {
+ confirmWriteSynchronized();
+ super.write(b, off, len);
+ length += len;
+ }
+ }
+
+ public void write(int b) throws IOException {
+ synchronized (BaseFileBucket.this) {
+ confirmWriteSynchronized();
+ super.write(b);
+ length++;
+ }
+ }
+
+ public void close() throws IOException {
+ File file;
+ synchronized(this) {
+ if(closed) return;
+ closed = true;
+ file = getFile();
+ }
+ removeStream(this);
+ boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ if(logMINOR)
+ Logger.minor(this, "Closing
"+BaseFileBucket.this);
+ try {
+ super.close();
+ } catch (IOException e) {
+ if(logMINOR)
+ Logger.minor(this, "Failed closing
"+BaseFileBucket.this+" : "+e, e);
+ if(createFileOnly()) tempfile.delete();
+ throw e;
+ }
+ if(createFileOnly()) {
+ if(file.exists()) {
+ if(logMINOR)
+ Logger.minor(this, "File exists
creating file for "+this);
+ tempfile.delete();
+ throw new FileExistsException(file);
+ }
+ if(!tempfile.renameTo(file)) {
+ if(logMINOR)
+ Logger.minor(this, "Cannot
rename file for "+this);
+ if(file.exists()) throw new
FileExistsException(file);
+ tempfile.delete();
+ if(logMINOR)
+ Logger.minor(this, "Deleted,
cannot rename file for "+this);
+ throw new IOException("Cannot rename
file");
+ }
+ }
+ }
+
+ public String toString() {
+ return
super.toString()+":"+BaseFileBucket.this.toString();
+ }
+ }
+
+ class FileBucketInputStream extends FileInputStream {
+ Exception e;
+ boolean closed;
+
+ public FileBucketInputStream(File f) throws IOException {
+ super(f);
+ if (Logger.shouldLog(Logger.DEBUG, this))
+ e = new Exception("debug");
+ }
+
+ public void close() throws IOException {
+ synchronized(this) {
+ if(closed) return;
+ closed = true;
+ }
+ removeStream(this);
+ super.close();
+ }
+
+ public String toString() {
+ return
super.toString()+":"+BaseFileBucket.this.toString();
+ }
+ }
+
+ public synchronized InputStream getInputStream() throws IOException {
+ if(freed)
+ throw new IOException("File already freed");
+ File file = getFile();
+ if(!file.exists()) {
+ Logger.normal(this, "File does not exist: "+file+" for
"+this);
+ return new NullInputStream();
+ } else {
+ FileBucketInputStream is =
+ new FileBucketInputStream(file);
+ addStream(is);
+ if(Logger.shouldLog(Logger.DEBUG, this))
+ Logger.debug(this, "Creating "+is, new
Exception("debug"));
+ return is;
+ }
+ }
+
+ /**
+ * @return the name of the file.
+ */
+ public synchronized String getName() {
+ return getFile().getName();
+ }
+
+ public synchronized long size() {
+ return length;
+ }
+
+ /**
+ * Actually delete the underlying file. Called by finalizer, will not be
+ * called twice. But length must still be valid when calling it.
+ */
+ protected synchronized void deleteFile() {
+ if(Logger.shouldLog(Logger.MINOR, this))
+ Logger.minor(this, "Deleting "+getFile()+" for "+this,
new Exception("debug"));
+ getFile().delete();
+ }
+
+ public void finalize() {
+ if(deleteOnFinalize())
+ free(true);
+ }
+
+ /**
+ * Return directory used for temp files.
+ */
+ public final synchronized static String getTempDir() {
+ return tempDir; // **FIXME**/TODO: locking on tempDir needs to
be checked by a Java guru for consistency
+ }
+
+ /**
+ * Set temp file directory.
+ * <p>
+ * The directory must exist.
+ */
+ public final synchronized static void setTempDir(String dirName) {
+ File dir = new File(dirName);
+ if (!(dir.exists() && dir.isDirectory() && dir.canWrite())) {
+ throw new IllegalArgumentException(
+ "Bad Temp Directory: " + dir.getAbsolutePath());
+ }
+ tempDir = dirName; // **FIXME**/TODO: locking on tempDir needs
to be checked by a Java guru for consistency
+ }
+
+ // determine the temp directory in one of several ways
+
+ static {
+ // Try the Java property (1.2 and above)
+ tempDir = System.getProperty("java.io.tmpdir");
+
+ // Deprecated calls removed.
+
+ // Try TEMP and TMP
+ // if (tempDir == null) {
+ // tempDir = System.getenv("TEMP");
+ // }
+
+ // if (tempDir == null) {
+ // tempDir = System.getenv("TMP");
+ // }
+
+ // make some semi-educated guesses based on OS.
+
+ if (tempDir == null) {
+ String os = System.getProperty("os.name");
+ if (os != null) {
+
+ String[] candidates = null;
+
+ // XXX: Add more possible OSes here.
+ if (os.equalsIgnoreCase("Linux")
+ || os.equalsIgnoreCase("FreeBSD")) {
+ String[] linuxCandidates = { "/tmp",
"/var/tmp" };
+ candidates = linuxCandidates;
+ } else if (os.equalsIgnoreCase("Windows")) {
+ String[] windowsCandidates =
+ { "C:\\TEMP",
"C:\\WINDOWS\\TEMP" };
+ candidates = windowsCandidates;
+ }
+
+ if (candidates != null) {
+ for (int i = 0; i < candidates.length;
i++) {
+ File path = new
File(candidates[i]);
+ if (path.exists()
+ && path.isDirectory()
+ && path.canWrite()) {
+ tempDir = candidates[i];
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // last resort -- use current working directory
+
+ if (tempDir == null) {
+ // This can be null -- but that's OK, null => cwd for
File
+ // constructor, anyways.
+ tempDir = System.getProperty("user.dir");
+ }
+ }
+
+ public synchronized Bucket[] split(int splitSize) {
+ 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];
+ File file = getFile();
+ for(int i=0;i<buckets.length;i++) {
+ long startAt = i * splitSize * 1L;
+ long endAt = Math.min(startAt + splitSize * 1L, length);
+ long len = endAt - startAt;
+ buckets[i] = new ReadOnlyFileSliceBucket(file, startAt,
len);
+ }
+ return buckets;
+ }
+
+ public void free() {
+ free(false);
+ }
+
+ public void free(boolean forceFree) {
+ Object[] toClose;
+ synchronized(this) {
+ if(freed) return;
+ freed = true;
+ toClose = streams == null ? null : streams.toArray();
+ streams = null;
+ }
+
+ if(toClose != null) {
+ Logger.error(this, "Streams open free()ing "+this+" :
"+StringArray.toString(toClose), new Exception("debug"));
+ for(int i=0;i<toClose.length;i++) {
+ try {
+ if(toClose[i] instanceof
FileBucketOutputStream) {
+ ((FileBucketOutputStream)
toClose[i]).close();
+ } else {
+ ((FileBucketInputStream)
toClose[i]).close();
+ }
+ } catch (IOException e) {
+ Logger.error(this, "Caught closing
stream in free(): "+e, e);
+ } catch (Throwable t) {
+ Logger.error(this, "Caught closing
stream in free(): "+t, t);
+ }
+ }
+ }
+
+ File file = getFile();
+ if ((deleteOnFree() || forceFree) && file.exists()) {
+ Logger.debug(this,
+ "Deleting bucket " + file.getName());
+ deleteFile();
+ if (file.exists())
+ Logger.error(this,
+ "Delete failed on bucket " +
file.getName());
+ }
+ }
+
+ public synchronized String toString() {
+ return super.toString()+ ':'
+getFile().getPath()+":streams="+(streams == null ? 0 : streams.size());
+ }
+
+ /**
+ * Returns the file object this buckets data is kept in.
+ */
+ public abstract File getFile();
+
+ public synchronized SimpleFieldSet toFieldSet() {
+ if(deleteOnFinalize()) return null;
+ SimpleFieldSet fs = new SimpleFieldSet(false);
+ fs.putSingle("Type", "FileBucket");
+ fs.putSingle("Filename", getFile().toString());
+ fs.put("Length", size());
+ return fs;
+ }
+
+ public static Bucket create(SimpleFieldSet fs, PersistentFileTracker f)
throws CannotCreateFromFieldSetException {
+ String tmp = fs.get("Filename");
+ if(tmp == null) throw new CannotCreateFromFieldSetException("No
filename");
+ File file = FileUtil.getCanonicalFile(new File(tmp));
+ if(f.matches(file)) {
+ return PersistentTempFileBucket.create(fs, f);
+ }
+ tmp = fs.get("Length");
+ if(tmp == null) throw new CannotCreateFromFieldSetException("No
length");
+ try {
+ long length = Long.parseLong(tmp);
+ if(length != file.length())
+ throw new
CannotCreateFromFieldSetException("Invalid length: should be "+length+"
actually "+file.length()+" on "+file);
+ } catch (NumberFormatException e) {
+ throw new CannotCreateFromFieldSetException("Corrupt
length "+tmp, e);
+ }
+ FileBucket bucket = new FileBucket(file, false, true, false,
false, false);
+ if(file.exists()) // no point otherwise!
+ f.register(file);
+ return bucket;
+ }
+
+}
Modified: branches/freenet-jfk/src/freenet/support/io/FileBucket.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/FileBucket.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/FileBucket.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -4,16 +4,7 @@
package freenet.support.io;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import freenet.crypt.RandomSource;
-import freenet.support.Logger;
-import freenet.support.SimpleFieldSet;
import freenet.support.api.Bucket;
/**
@@ -21,7 +12,7 @@
*
* @author oskar
*/
-public class FileBucket implements Bucket, SerializableToFieldSetBucket {
+public class FileBucket extends BaseFileBucket implements Bucket,
SerializableToFieldSetBucket {
protected final File file;
protected boolean readOnly;
@@ -29,7 +20,6 @@
protected boolean deleteOnFree;
protected final boolean deleteOnExit;
protected final boolean createFileOnly;
- protected long length;
// JVM caches File.size() and there is no way to flush the cache, so we
// need to track it ourselves
protected long fileRestartCounter;
@@ -52,6 +42,7 @@
* @param deleteOnExit If true, delete the file on a clean exit of the
JVM. Irreversible - use with care!
*/
public FileBucket(File file, boolean readOnly, boolean createFileOnly,
boolean deleteOnFinalize, boolean deleteOnExit, boolean deleteOnFree) {
+ super(file);
if(file == null) throw new NullPointerException();
file = file.getAbsoluteFile();
this.readOnly = readOnly;
@@ -60,323 +51,20 @@
this.deleteOnFinalize = deleteOnFinalize;
this.deleteOnFree = deleteOnFree;
this.deleteOnExit = deleteOnExit;
- if(deleteOnExit) {
- try {
- file.deleteOnExit();
- } catch (NullPointerException e) {
- Logger.error(this, "Impossible: "+e, e);
- System.err.println("Impossible: "+e);
- e.printStackTrace();
- }
- }
// Useful for finding temp file leaks.
// System.err.println("-- FileBucket.ctr(0) -- " +
// file.getAbsolutePath());
// (new Exception("get stack")).printStackTrace();
fileRestartCounter = 0;
- if(file.exists()) {
- length = file.length();
- if(!file.canWrite())
- readOnly = true;
- }
- else length = 0;
}
/**
- * Creates a new FileBucket in a random temporary file in the temporary
- * directory.
- * @throws IOException
- */
- public FileBucket(RandomSource random) throws IOException {
- // **FIXME**/TODO: locking on tempDir needs to be checked by a
Java guru for consistency
- file = File.createTempFile(tempDir, ".freenet.tmp");
- createFileOnly = true;
- // Useful for finding temp file leaks.
- //System.err.println("-- FileBucket.ctr(1) -- " +
- // file.getAbsolutePath());
- //(new Exception("get stack")).printStackTrace();
- deleteOnFinalize = true;
- deleteOnExit = true;
- length = 0;
- file.deleteOnExit();
- }
-
- public FileBucket(SimpleFieldSet fs, PersistentFileTracker f) throws
CannotCreateFromFieldSetException {
- createFileOnly = true;
- deleteOnExit = false;
- String tmp = fs.get("Filename");
- if(tmp == null) throw new CannotCreateFromFieldSetException("No
filename");
- this.file = FileUtil.getCanonicalFile(new File(tmp));
- tmp = fs.get("Length");
- if(tmp == null) throw new CannotCreateFromFieldSetException("No
length");
- try {
- length = Long.parseLong(tmp);
- if(length != file.length())
- throw new
CannotCreateFromFieldSetException("Invalid length: should be "+length+"
actually "+file.length()+" on "+file);
- } catch (NumberFormatException e) {
- throw new CannotCreateFromFieldSetException("Corrupt
length "+tmp, e);
- }
- if(file.exists()) // no point otherwise!
- f.register(file);
- }
-
- public OutputStream getOutputStream() throws IOException {
- synchronized (this) {
- if(readOnly)
- throw new IOException("Bucket is read-only");
-
- if(createFileOnly && file.exists())
- throw new FileExistsException(file);
-
- // FIXME: behaviour depends on UNIX semantics, to
totally abstract
- // it out we would have to kill the old write streams
here
- // FIXME: what about existing streams? Will ones on
append append
- // to the new truncated file? Do we want them to? What
about
- // truncated ones? We should kill old streams here,
right?
- return newFileBucketOutputStream(createFileOnly ?
getTempfile() : file, file.getPath(), ++fileRestartCounter);
- }
- }
-
- /**
- * Create a temporary file in the same directory as this file.
- */
- protected File getTempfile() throws IOException {
- File f = File.createTempFile(file.getName(), ".freenet-tmp",
file.getParentFile());
- if(deleteOnExit) f.deleteOnExit();
- return f;
- }
-
- protected FileBucketOutputStream newFileBucketOutputStream(
- File tempfile, String s, long streamNumber) throws IOException {
- return new FileBucketOutputStream(tempfile, s, streamNumber);
- }
-
- protected synchronized void resetLength() {
- length = 0;
- }
-
- /**
- * Internal OutputStream impl.
- * If createFileOnly is set, we won't overwrite an existing file, and
we write to a temp file
- * then rename over the target. Note that we can't use createNewFile
then new FOS() because while
- * createNewFile is atomic, the combination is not, so if we do it we
are vulnerable to symlink
- * attacks.
- * @author toad
- */
- class FileBucketOutputStream extends FileOutputStream {
-
- private long restartCount;
- private File tempfile;
- private boolean closed;
-
- protected FileBucketOutputStream(
- File tempfile, String s, long restartCount)
- throws FileNotFoundException {
- super(tempfile, false);
- if(Logger.shouldLog(Logger.MINOR, this))
- Logger.minor(this, "Writing to "+tempfile+" for
"+file);
- this.tempfile = tempfile;
- resetLength();
- this.restartCount = restartCount;
- closed = false;
- }
-
- protected void confirmWriteSynchronized() throws IOException {
- if (fileRestartCounter > restartCount)
- throw new IllegalStateException("writing to
file after restart");
- if(readOnly)
- throw new IOException("File is read-only");
- }
-
- public void write(byte[] b) throws IOException {
- synchronized (FileBucket.this) {
- confirmWriteSynchronized();
- super.write(b);
- length += b.length;
- }
- }
-
- public void write(byte[] b, int off, int len) throws
IOException {
- synchronized (FileBucket.this) {
- confirmWriteSynchronized();
- super.write(b, off, len);
- length += len;
- }
- }
-
- public void write(int b) throws IOException {
- synchronized (FileBucket.this) {
- confirmWriteSynchronized();
- super.write(b);
- length++;
- }
- }
-
- public void close() throws IOException {
- synchronized(this) {
- if(closed) return;
- closed = true;
- }
- boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
- if(logMINOR)
- Logger.minor(this, "Closing "+FileBucket.this);
- try {
- super.close();
- } catch (IOException e) {
- if(logMINOR)
- Logger.minor(this, "Failed closing
"+FileBucket.this+" : "+e, e);
- if(createFileOnly) tempfile.delete();
- throw e;
- }
- if(createFileOnly) {
- if(file.exists()) {
- if(logMINOR)
- Logger.minor(this, "File exists
creating file for "+this);
- tempfile.delete();
- throw new FileExistsException(file);
- }
- if(!tempfile.renameTo(file)) {
- if(logMINOR)
- Logger.minor(this, "Cannot
rename file for "+this);
- if(file.exists()) throw new
FileExistsException(file);
- tempfile.delete();
- if(logMINOR)
- Logger.minor(this, "Deleted,
cannot rename file for "+this);
- throw new IOException("Cannot rename
file");
- }
- }
- }
- }
-
- class FileBucketInputStream extends FileInputStream {
- Exception e;
-
- public FileBucketInputStream(File f) throws IOException {
- super(f);
- if (Logger.shouldLog(Logger.DEBUG, this))
- e = new Exception("debug");
- }
- }
-
- public synchronized InputStream getInputStream() throws IOException {
- if(!file.exists()) {
- Logger.normal(this, "File does not exist: "+file+" for
"+this);
- return new NullInputStream();
- } else
- return new FileBucketInputStream(file);
- }
-
- /**
- * @return the name of the file.
- */
- public synchronized String getName() {
- return file.getName();
- }
-
- public synchronized long size() {
- return length;
- }
-
- /**
* Returns the file object this buckets data is kept in.
*/
public synchronized File getFile() {
return file;
}
- /**
- * Actually delete the underlying file. Called by finalizer, will not be
- * called twice. But length must still be valid when calling it.
- */
- protected synchronized void deleteFile() {
- file.delete();
- }
-
- public void finalize() {
- if(deleteOnFinalize)
- free(deleteOnFinalize);
- }
-
- /**
- * Return directory used for temp files.
- */
- public final synchronized static String getTempDir() {
- return tempDir; // **FIXME**/TODO: locking on tempDir needs to
be checked by a Java guru for consistency
- }
-
- /**
- * Set temp file directory.
- * <p>
- * The directory must exist.
- */
- public final synchronized static void setTempDir(String dirName) {
- File dir = new File(dirName);
- if (!(dir.exists() && dir.isDirectory() && dir.canWrite())) {
- throw new IllegalArgumentException(
- "Bad Temp Directory: " + dir.getAbsolutePath());
- }
- tempDir = dirName; // **FIXME**/TODO: locking on tempDir needs
to be checked by a Java guru for consistency
- }
-
- // determine the temp directory in one of several ways
-
- static {
- // Try the Java property (1.2 and above)
- tempDir = System.getProperty("java.io.tmpdir");
-
- // Deprecated calls removed.
-
- // Try TEMP and TMP
- // if (tempDir == null) {
- // tempDir = System.getenv("TEMP");
- // }
-
- // if (tempDir == null) {
- // tempDir = System.getenv("TMP");
- // }
-
- // make some semi-educated guesses based on OS.
-
- if (tempDir == null) {
- String os = System.getProperty("os.name");
- if (os != null) {
-
- String[] candidates = null;
-
- // XXX: Add more possible OSes here.
- if (os.equalsIgnoreCase("Linux")
- || os.equalsIgnoreCase("FreeBSD")) {
- String[] linuxCandidates = { "/tmp",
"/var/tmp" };
- candidates = linuxCandidates;
- } else if (os.equalsIgnoreCase("Windows")) {
- String[] windowsCandidates =
- { "C:\\TEMP",
"C:\\WINDOWS\\TEMP" };
- candidates = windowsCandidates;
- }
-
- if (candidates != null) {
- for (int i = 0; i < candidates.length;
i++) {
- File path = new
File(candidates[i]);
- if (path.exists()
- && path.isDirectory()
- && path.canWrite()) {
- tempDir = candidates[i];
- break;
- }
- }
- }
- }
- }
-
- // last resort -- use current working directory
-
- if (tempDir == null) {
- // This can be null -- but that's OK, null => cwd for
File
- // constructor, anyways.
- tempDir = System.getProperty("user.dir");
- }
- }
-
public synchronized boolean isReadOnly() {
return readOnly;
}
@@ -394,46 +82,19 @@
deleteOnFinalize = false;
}
- public synchronized Bucket[] split(int splitSize) {
- 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];
- for(int i=0;i<buckets.length;i++) {
- long startAt = i * splitSize * 1L;
- long endAt = Math.min(startAt + splitSize * 1L, length);
- long len = endAt - startAt;
- buckets[i] = new ReadOnlyFileSliceBucket(file, startAt,
len);
- }
- return buckets;
+ protected boolean createFileOnly() {
+ return createFileOnly;
}
- public void free() {
- free(false);
+ protected boolean deleteOnExit() {
+ return deleteOnExit;
}
-
- public synchronized void free(boolean forceFree) {
- if ((deleteOnFree || forceFree) && file.exists()) {
- Logger.debug(this,
- "Deleting bucket " + file.getName());
- deleteFile();
- if (file.exists())
- Logger.error(this,
- "Delete failed on bucket " +
file.getName());
- }
+
+ protected boolean deleteOnFinalize() {
+ return deleteOnFinalize;
}
-
- public synchronized String toString() {
- return super.toString()+ ':' +file.getPath();
- }
- public synchronized SimpleFieldSet toFieldSet() {
- if(deleteOnFinalize) return null;
- SimpleFieldSet fs = new SimpleFieldSet(false);
- fs.putSingle("Type", "FileBucket");
- fs.putSingle("Filename", file.toString());
- fs.put("Length", length);
- return fs;
+ protected boolean deleteOnFree() {
+ return deleteOnFree;
}
}
Deleted: branches/freenet-jfk/src/freenet/support/io/FileBucketFactory.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/FileBucketFactory.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/FileBucketFactory.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,39 +0,0 @@
-package freenet.support.io;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Vector;
-
-import freenet.support.Logger;
-import freenet.support.api.Bucket;
-import freenet.support.api.BucketFactory;
-
-public class FileBucketFactory implements BucketFactory {
-
- private Vector files = new Vector();
-
- // Must have trailing "/"
- public final File rootDir;
-
- public FileBucketFactory(File rootDir) {
- this.rootDir = rootDir;
- }
-
- public Bucket makeBucket(long size) throws IOException {
- File f = File.createTempFile("bf_", ".freenet-tmp", rootDir);
- Bucket b = new FileBucket(f, false, true, true, false, true);
- files.addElement(f);
- return b;
- }
-
- public void freeBucket(Bucket b) throws IOException {
- if (!(b instanceof FileBucket)) throw new IOException("not a
FileBucket!");
- File f = ((FileBucket) b).getFile();
- //System.err.println("FREEING: " + f.getName());
- if (files.removeElement(f)) {
- if (!f.delete())
- Logger.error(this, "Delete failed on bucket "+f.getName(), new
Exception());
- files.trimToSize();
- }
- }
-}
Modified: branches/freenet-jfk/src/freenet/support/io/FileUtil.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/FileUtil.java 2007-08-21
19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/FileUtil.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -4,10 +4,14 @@
package freenet.support.io;
import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import freenet.client.DefaultMIMETypes;
@@ -72,6 +76,7 @@
return result;
}
+ // FIXME: this is called readUTF but it reads in the default charset
... eh??
public static String readUTF(File file) throws FileNotFoundException,
IOException {
StringBuffer result = new StringBuffer();
FileInputStream fis = null;
@@ -85,9 +90,8 @@
char[] buf = new char[4096];
int length = 0;
-
- while(length != -1) {
- length = isr.read(buf);
+
+ while((length = isr.read(buf)) > 0) {
result.append(buf, 0, length);
}
@@ -100,7 +104,37 @@
}
return result.toString();
}
+
+ public static boolean writeTo(InputStream input, File target) throws
FileNotFoundException, IOException {
+ BufferedInputStream bis = null;
+ DataInputStream dis = null;
+ FileOutputStream fos = null;
+ BufferedOutputStream bos = null;
+ File file = File.createTempFile("temp", ".tmp");
+
+ try {
+ bis = new BufferedInputStream(input);
+ dis = new DataInputStream(bis);
+ fos = new FileOutputStream(file);
+ bos= new BufferedOutputStream(fos);
+ int len = 0;
+ byte[] buffer = new byte[4096];
+ while ((len = dis.read(buffer)) > 0) {
+ bos.write(buffer, 0, len);
+ }
+ } catch (IOException e) {
+ throw e;
+ } finally {
+ if(dis != null) dis.close();
+ if(bis != null) bis.close();
+ if(fos != null) fos.close();
+ if(bos != null) bos.close();
+ }
+
+ return file.renameTo(target);
+ }
+
public static String sanitize(String s) {
StringBuffer sb = new StringBuffer(s.length());
for(int i=0;i<s.length();i++) {
@@ -125,8 +159,10 @@
if(filename.indexOf('.') >= 0) {
String oldExt =
filename.substring(filename.lastIndexOf('.'));
if(DefaultMIMETypes.isValidExt(mimeType, oldExt))
return filename;
- }
- return filename + '.' + DefaultMIMETypes.getExtension(filename);
+ }
+ String defaultExt = DefaultMIMETypes.getExtension(filename);
+ if(defaultExt == null) return filename;
+ else return filename + '.' + defaultExt;
}
}
Modified: branches/freenet-jfk/src/freenet/support/io/FilenameGenerator.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/FilenameGenerator.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/FilenameGenerator.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -6,7 +6,7 @@
import org.tanukisoftware.wrapper.WrapperManager;
import freenet.crypt.RandomSource;
-import freenet.support.HexUtil;
+import freenet.support.Fields;
import freenet.support.Logger;
import freenet.support.TimeUtil;
@@ -27,15 +27,14 @@
this.random = random;
this.prefix = prefix;
if (dir == null)
- tmpDir = new File(System.getProperty("java.io.tmpdir"));
+ tmpDir = FileUtil.getCanonicalFile(new
File(System.getProperty("java.io.tmpdir")));
else
- tmpDir = dir;
+ tmpDir = FileUtil.getCanonicalFile(dir);
if(!tmpDir.exists()) {
tmpDir.mkdir();
}
if(!(tmpDir.isDirectory() && tmpDir.canRead() &&
tmpDir.canWrite()))
throw new IOException("Not a directory or cannot
read/write: "+tmpDir);
-
if(wipeFiles) {
long wipedFiles = 0;
long wipeableFiles = 0;
@@ -64,18 +63,45 @@
}
}
- public File makeRandomFilename() {
- byte[] randomFilename = new byte[8]; // should be plenty
+ public long makeRandomFilename() {
+ long randomFilename; // should be plenty
while(true) {
- random.nextBytes(randomFilename);
- String filename = prefix +
HexUtil.bytesToHex(randomFilename);
+ randomFilename = random.nextLong();
+ if(randomFilename == -1) continue; // Disallowed as
used for error reporting
+ String filename = prefix +
Long.toHexString(randomFilename);
File ret = new File(tmpDir, filename);
if(!ret.exists()) {
if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Made random
filename: "+ret, new Exception("debug"));
- return ret;
+ return randomFilename;
}
}
}
+ public File getFilename(long id) {
+ return new File(tmpDir, prefix + Long.toHexString(id));
+ }
+
+ public boolean matches(File file) {
+ return getID(file) != -1;
+ }
+
+ public long getID(File file) {
+
if(!(FileUtil.getCanonicalFile(file.getParentFile()).equals(tmpDir))) {
+ Logger.error(this, "Not the same dir:
parent="+FileUtil.getCanonicalFile(file.getParentFile())+" but tmpDir="+tmpDir);
+ return -1;
+ }
+ String name = file.getName();
+ if(!name.startsWith(prefix)) {
+ Logger.error(this, "Does not start with prefix:
"+name+" prefix "+prefix);
+ return -1;
+ }
+ try {
+ return
Fields.hexToLong(name.substring(prefix.length()));
+ } catch (NumberFormatException e) {
+ Logger.error(this, "Cannot getID: "+e+" from
"+(name.substring(prefix.length())), e);
+ return -1;
+ }
+ }
+
}
Copied: branches/freenet-jfk/src/freenet/support/io/MultiReaderBucket.java
(from rev 14796, trunk/freenet/src/freenet/support/io/MultiReaderBucket.java)
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/MultiReaderBucket.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/support/io/MultiReaderBucket.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,129 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.support.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+
+import freenet.support.api.Bucket;
+
+/**
+ * A wrapper for a read-only bucket providing for multiple readers. The data
is
+ * only freed when all of the readers have freed it.
+ * @author toad
+ */
+public class MultiReaderBucket {
+
+ private final Bucket bucket;
+
+ // Assume there will be relatively few readers
+ private ArrayList readers;
+
+ private boolean closed;
+
+ public MultiReaderBucket(Bucket underlying) {
+ bucket = underlying;
+ }
+
+ /** Get a reader bucket */
+ public Bucket getReaderBucket() {
+ synchronized(this) {
+ if(closed) return null;
+ Bucket d = new ReaderBucket();
+ if(readers == null) readers = new ArrayList();
+ readers.add(d);
+ return d;
+ }
+ }
+
+ class ReaderBucket implements Bucket {
+
+ private boolean freed;
+
+ public void free() {
+ synchronized(MultiReaderBucket.this) {
+ if(freed) return;
+ freed = true;
+ readers.remove(this);
+ if(!readers.isEmpty()) return;
+ readers = null;
+ if(closed) return;
+ closed = true;
+ }
+ bucket.free();
+ }
+
+ public InputStream getInputStream() throws IOException {
+ synchronized(MultiReaderBucket.this) {
+ if(freed || closed) {
+ throw new IOException("Already freed");
+ }
+ }
+ return new ReaderBucketInputStream();
+ }
+
+ private class ReaderBucketInputStream extends InputStream {
+
+ InputStream is;
+
+ ReaderBucketInputStream() throws IOException {
+ is = bucket.getInputStream();
+ }
+
+ public final int read() throws IOException {
+ synchronized(MultiReaderBucket.this) {
+ if(freed || closed) throw new
IOException("Already closed");
+ }
+ return is.read();
+ }
+
+ public final int read(byte[] data, int offset, int
length) throws IOException {
+ synchronized(MultiReaderBucket.this) {
+ if(freed || closed) throw new
IOException("Already closed");
+ }
+ return is.read(data, offset, length);
+ }
+
+ public final int read(byte[] data) throws IOException {
+ synchronized(MultiReaderBucket.this) {
+ if(freed || closed) throw new
IOException("Already closed");
+ }
+ return is.read(data);
+ }
+
+ public final void close() throws IOException {
+ is.close();
+ }
+
+ }
+
+ public String getName() {
+ return bucket.getName();
+ }
+
+ public OutputStream getOutputStream() throws IOException {
+ throw new IOException("Read only");
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ public void setReadOnly() {
+ // Already read only
+ }
+
+ public long size() {
+ return bucket.size();
+ }
+
+ public void finalize() {
+ free();
+ }
+
+ }
+
+}
Modified:
branches/freenet-jfk/src/freenet/support/io/NullPersistentFileTracker.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/NullPersistentFileTracker.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/NullPersistentFileTracker.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -22,4 +22,16 @@
return new File(".");
}
+ public boolean matches(File file) {
+ return false;
+ }
+
+ public FilenameGenerator getGenerator() {
+ return null;
+ }
+
+ public long getID(File file) {
+ return 0;
+ }
+
}
Modified:
branches/freenet-jfk/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java
===================================================================
---
branches/freenet-jfk/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -6,6 +6,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.lang.ref.SoftReference;
import org.spaceroots.mantissa.random.MersenneTwister;
@@ -28,8 +29,8 @@
private final Bucket bucket;
private final int minPaddedSize;
private final RandomSource origRandom;
- private final Rijndael aes;
- /** The decryption key. May be null. */
+ private SoftReference /* <Rijndael> */ aesRef;
+ /** The decryption key. */
private final byte[] key;
/** Broken (old) encryption? */
private final boolean brokenEncryption;
@@ -45,26 +46,14 @@
* @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) {
+ public PaddedEphemerallyEncryptedBucket(Bucket bucket, int minSize,
RandomSource origRandom) {
this.origRandom = origRandom;
this.bucket = bucket;
if(bucket.size() != 0) throw new
IllegalArgumentException("Bucket must be empty");
- try {
- aes = new Rijndael(256, 256, false);
- } catch (UnsupportedCipherException e) {
- throw new Error(e);
- }
brokenEncryption = false;
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.key = tempKey;
this.minPaddedSize = minSize;
readOnly = false;
lastOutputStream = 0;
@@ -88,12 +77,7 @@
this.origRandom = origRandom;
this.bucket = bucket;
brokenEncryption = oldCrypto;
- try {
- aes = new Rijndael(256, 256, oldCrypto);
- } catch (UnsupportedCipherException e) {
- throw new Error(e);
- }
- aes.initialize(key);
+ if(key.length != 32) throw new IllegalArgumentException("Key
wrong length: "+key.length);
this.key = key;
this.minPaddedSize = minSize;
readOnly = false;
@@ -119,12 +103,7 @@
throw new CannotCreateFromFieldSetException("No key");
brokenEncryption = fs.get("CryptoType") == null;
key = HexUtil.hexToBytes(tmp);
- try {
- aes = new Rijndael(256, 256, brokenEncryption);
- } catch (UnsupportedCipherException e) {
- throw new Error(e);
- }
- aes.initialize(key);
+ if(key.length != 32) throw new IllegalArgumentException("Key
wrong length: "+key.length);
tmp = fs.get("MinPaddedSize");
if(tmp == null)
minPaddedSize = 1024; // FIXME throw! back
compatibility hack
@@ -136,7 +115,7 @@
}
}
if(dataLength > bucket.size())
- throw new CannotCreateFromFieldSetException("Underlying
bucket is too small: should be "+dataLength+" actually "+bucket.size());
+ throw new CannotCreateFromFieldSetException("Underlying
bucket "+bucket+" is too small: should be "+dataLength+" actually
"+bucket.size());
}
public OutputStream getOutputStream() throws IOException {
@@ -159,6 +138,7 @@
this.out = out;
dataLength = 0;
this.streamNumber = streamNumber;
+ Rijndael aes = getRijndael();
pcfb = PCFBMode.create(aes);
}
@@ -235,6 +215,7 @@
public PaddedEphemerallyEncryptedInputStream(InputStream in) {
this.in = in;
+ Rijndael aes = getRijndael();
pcfb = PCFBMode.create(aes);
ptr = 0;
}
@@ -310,6 +291,22 @@
}
}
+ private synchronized Rijndael getRijndael() {
+ Rijndael aes;
+ if(aesRef != null) {
+ aes = (Rijndael) aesRef.get();
+ if(aes != null) return aes;
+ }
+ try {
+ aes = new Rijndael(256, 256, false);
+ } catch (UnsupportedCipherException e) {
+ throw new Error(e);
+ }
+ aes.initialize(key);
+ aesRef = new SoftReference(aes);
+ return aes;
+ }
+
public String getName() {
return "Encrypted:"+bucket.getName();
}
@@ -342,7 +339,7 @@
}
/**
- * Get the decryption key. May have been blanked out.
+ * Get the decryption key.
*/
public byte[] getKey() {
return key;
Modified:
branches/freenet-jfk/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java
===================================================================
---
branches/freenet-jfk/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -23,6 +23,6 @@
}
public Bucket makeBucket(long size) throws IOException {
- return new
PaddedEphemerallyEncryptedBucket(baseFactory.makeBucket(size), minSize, random,
true);
+ return new
PaddedEphemerallyEncryptedBucket(baseFactory.makeBucket(size), minSize, random);
}
}
Modified: branches/freenet-jfk/src/freenet/support/io/PersistentFileTracker.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/PersistentFileTracker.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/PersistentFileTracker.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -21,5 +21,14 @@
* Get the persistent temp files directory.
*/
public File getDir();
+
+ /**
+ * Is the file in question one of our persistent temp files?
+ */
+ public boolean matches(File file);
+
+ public FilenameGenerator getGenerator();
+
+ public long getID(File file);
}
Modified:
branches/freenet-jfk/src/freenet/support/io/PersistentTempBucketFactory.java
===================================================================
---
branches/freenet-jfk/src/freenet/support/io/PersistentTempBucketFactory.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/support/io/PersistentTempBucketFactory.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -91,22 +91,24 @@
Iterator i = originalFiles.iterator();
while(i.hasNext()) {
File f = (File) (i.next());
+ if(Logger.shouldLog(Logger.MINOR, this))
+ Logger.minor(this, "Deleting old tempfile "+f);
f.delete();
}
}
private Bucket makeRawBucket(long size) throws IOException {
- return new FileBucket(fg.makeRandomFilename(), false, true,
false, false, true);
+ return new PersistentTempFileBucket(fg.makeRandomFilename(),
fg);
}
public Bucket makeBucket(long size) throws IOException {
Bucket b = makeRawBucket(size);
- return new DelayedFreeBucket(this, new
PaddedEphemerallyEncryptedBucket(b, 1024, rand, false));
+ return new DelayedFreeBucket(this, new
PaddedEphemerallyEncryptedBucket(b, 1024, rand));
}
public Bucket makeEncryptedBucket() throws IOException {
Bucket b = makeRawBucket(-1);
- return new DelayedFreeBucket(this, new
PaddedEphemerallyEncryptedBucket(b, 1024, rand, false));
+ return new DelayedFreeBucket(this, new
PaddedEphemerallyEncryptedBucket(b, 1024, rand));
}
/**
@@ -130,4 +132,16 @@
return dir;
}
+ public FilenameGenerator getGenerator() {
+ return fg;
+ }
+
+ public boolean matches(File file) {
+ return fg.matches(file);
+ }
+
+ public long getID(File file) {
+ return fg.getID(file);
+ }
+
}
Copied:
branches/freenet-jfk/src/freenet/support/io/PersistentTempFileBucket.java (from
rev 14796, trunk/freenet/src/freenet/support/io/PersistentTempFileBucket.java)
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/PersistentTempFileBucket.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/support/io/PersistentTempFileBucket.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,55 @@
+package freenet.support.io;
+
+import java.io.File;
+
+import freenet.support.SimpleFieldSet;
+import freenet.support.api.Bucket;
+
+public class PersistentTempFileBucket extends TempFileBucket {
+
+ protected PersistentTempFileBucket(long id, FilenameGenerator
generator) {
+ super(id, generator);
+ }
+
+ protected boolean deleteOnFinalize() {
+ // Do not delete on finalize
+ return false;
+ }
+
+ protected boolean deleteOnExit() {
+ // DO NOT DELETE ON EXIT !!!!
+ return false;
+ }
+
+ public static Bucket create(SimpleFieldSet fs, PersistentFileTracker f)
throws CannotCreateFromFieldSetException {
+ String tmp = fs.get("Filename");
+ if(tmp == null) throw new CannotCreateFromFieldSetException("No
filename");
+ File file = FileUtil.getCanonicalFile(new File(tmp));
+ long id = f.getID(file);
+ if(id == -1)
+ throw new CannotCreateFromFieldSetException("Cannot
derive persistent temp file id from filename "+file);
+ tmp = fs.get("Length");
+ if(tmp == null) throw new CannotCreateFromFieldSetException("No
length");
+ long length;
+ try {
+ length = Long.parseLong(tmp);
+ if(length != file.length())
+ throw new
CannotCreateFromFieldSetException("Invalid length: should be "+length+"
actually "+file.length()+" on "+file);
+ } catch (NumberFormatException e) {
+ throw new CannotCreateFromFieldSetException("Corrupt
length "+tmp, e);
+ }
+ Bucket bucket = new PersistentTempFileBucket(id,
f.getGenerator());
+ if(file.exists()) // no point otherwise!
+ f.register(file);
+ return bucket;
+ }
+
+ public SimpleFieldSet toFieldSet() {
+ if(deleteOnFinalize()) return null;
+ SimpleFieldSet fs = super.toFieldSet();
+ fs.putOverwrite("Type", "PersistentTempFileBucket");
+ fs.put("FilenameID", filenameID);
+ return fs;
+ }
+
+}
Deleted: branches/freenet-jfk/src/freenet/support/io/RandomAccessFileBucket.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/RandomAccessFileBucket.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/RandomAccessFileBucket.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,453 +0,0 @@
-// 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;
-import freenet.support.api.Bucket;
-
-/**
- * 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 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 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();
-
- if(Logger.shouldLog(Logger.DEBUG, this))
- Logger.debug(this, "closed open InputStream !: " +
- file.getAbsolutePath());
- }
- else if (streams.elementAt(i) instanceof OutputStream) {
- ((OutputStream)streams.elementAt(i)).close();
- if(Logger.shouldLog(Logger.DEBUG, this))
- 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 * 1L + offset;
- int blockLen = blockSize;
- if (i == nBlocks - 1) {
- blockLen = (int) (length - (nBlocks - 1) * blockSize * 1L);
- }
- 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) {
- if(Logger.shouldLog(Logger.DEBUG, this))
- 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);
- 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();
- raf.close();
- }
- }
-
- ////////////////////////////////////////////////////////////
- private void println(String text) {
- if (vociferous) {
- if(Logger.shouldLog(Logger.DEBUG, this))
- 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(false);
- fs.putSingle("Type", "RandomAccessFileBucket");
- fs.putSingle("Filename", file.toString());
- fs.put("Offset", offset);
- fs.put("Length", len);
- return fs;
- }
-}
Modified:
branches/freenet-jfk/src/freenet/support/io/RandomAccessFileWrapper.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/RandomAccessFileWrapper.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/RandomAccessFileWrapper.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -5,6 +5,8 @@
import java.io.IOException;
import java.io.RandomAccessFile;
+import freenet.support.Logger;
+
public class RandomAccessFileWrapper implements RandomAccessThing {
// FIXME maybe we should avoid opening these until we are ready to use
them
@@ -38,4 +40,12 @@
return raf.length();
}
+ public void close() {
+ try {
+ raf.close();
+ } catch (IOException e) {
+ Logger.error(this, "Could not close "+raf+" : "+e+" for
"+this, e);
+ }
+ }
+
}
Modified: branches/freenet-jfk/src/freenet/support/io/RandomAccessThing.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/RandomAccessThing.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/RandomAccessThing.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -16,5 +16,7 @@
public void pread(long fileOffset, byte[] buf, int bufOffset, int
length) throws IOException;
public void pwrite(long fileOffset, byte[] buf, int bufOffset, int
length) throws IOException;
+
+ public void close();
}
Modified:
branches/freenet-jfk/src/freenet/support/io/SerializableToFieldSetBucketUtil.java
===================================================================
---
branches/freenet-jfk/src/freenet/support/io/SerializableToFieldSetBucketUtil.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/support/io/SerializableToFieldSetBucketUtil.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -19,7 +19,7 @@
public static Bucket create(SimpleFieldSet fs, RandomSource random,
PersistentFileTracker f) throws CannotCreateFromFieldSetException {
if(fs == null) {
if(Logger.shouldLog(Logger.MINOR,
SerializableToFieldSetBucketUtil.class))
-
Logger.minor(SerializableToFieldSetBucketUtil.class, "fs = null");
+
Logger.minor(SerializableToFieldSetBucketUtil.class, "fs = null", new
Exception("debug"));
return null;
}
String type = fs.get("Type");
@@ -56,17 +56,17 @@
throw new CannotCreateFromFieldSetException("No type");
} else if(type.equals("FileBucket")) {
- return new FileBucket(fs, f);
+ return BaseFileBucket.create(fs, f);
} else if(type.equals("PaddedEphemerallyEncryptedBucket")) {
return new PaddedEphemerallyEncryptedBucket(fs, random,
f);
} else if(type.equals("NullBucket")) {
return new NullBucket();
- } else if(type.equals("RandomAccessFileBucket")) {
- return new RandomAccessFileBucket(fs, f);
} else if(type.equals("ReadOnlyFileSliceBucket")) {
return new ReadOnlyFileSliceBucket(fs);
} else if(type.equals("DelayedFreeBucket")) {
return new DelayedFreeBucket(fs, random, f);
+ } else if(type.equals("PersistentTempFileBucket")) {
+ return PersistentTempFileBucket.create(fs, f);
} else
throw new
CannotCreateFromFieldSetException("Unrecognized type "+type);
}
Deleted: branches/freenet-jfk/src/freenet/support/io/SpyInputStream.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/SpyInputStream.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/SpyInputStream.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,148 +0,0 @@
-package freenet.support.io;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/*
- * This code is part of FProxy, an HTTP proxy server for Freenet. It is
- * distributed under the GNU Public Licence (GPL) version 2. See
- * http://www.gnu.org/ for further details of the GPL.
- */
-
-/**
- * The purpose of all of this gobbledeygook is to keep rude FCPClient
- * implementations from writing to temp files after the requests that own them
- * have been canceled.
- *
- * <p>
- * These could be removed once FCPClient implementation deficiencies have been
- * corrected but sanity checks are always useful.
- * </p>
- *
- * @author ian
- * @see freenet.support.SpyOutputStream
- */
-class SpyInputStream extends java.io.FilterInputStream {
-
- private String prefix = "";
- private TempFileBucket tfb = null;
-
- private final void println(String text) {
- }
-
- private final void checkValid() throws IOException {
- synchronized (tfb) {
- if (tfb.isReleased()) {
- throw new IOException(
- "Attempt to use a released
TempFileBucket: " + prefix);
- }
- }
- }
-
- /**
- * Constructor for the SpyInputStream object
- *
- * @param tfb
- * @param prefix
- * @exception IOException
- */
- public SpyInputStream(TempFileBucket tfb, String prefix)
- throws IOException {
- super(null);
- InputStream tmpIn = null;
- try {
- this.prefix = prefix;
- this.tfb = tfb;
- checkValid();
- tmpIn = tfb.getRealInputStream();
- in = tmpIn;
- } catch (IOException ioe) {
- try {
- if (tmpIn != null) {
- tmpIn.close();
- }
- } catch (Exception e) {
- // NOP
- }
- throw ioe;
- }
- println("Created new InputStream");
- }
-
- public int read() throws java.io.IOException {
- synchronized (tfb) {
- println(".read()");
- checkValid();
- return in.read();
- }
- }
-
- public int read(byte[] bytes) throws java.io.IOException {
- synchronized (tfb) {
- println(".read(byte[])");
- checkValid();
- return in.read(bytes);
- }
- }
-
- public int read(byte[] bytes, int a, int b) throws java.io.IOException {
- synchronized (tfb) {
- println(".read(byte[], int, int)");
- checkValid();
- // FIXME remove debugging
- if((a+b > bytes.length) || (a < 0) || (b < 0))
- throw new
ArrayIndexOutOfBoundsException("a="+a+", b="+b+", length "+bytes.length);
- return in.read(bytes, a, b);
- }
- }
-
- public long skip(long a) throws java.io.IOException {
- synchronized (tfb) {
- println(".skip(long)");
- checkValid();
- return in.skip(a);
- }
- }
-
- public int available() throws java.io.IOException {
- synchronized (tfb) {
- println(".available()");
- checkValid();
- return in.available();
- }
- }
-
- public void close() throws java.io.IOException {
- synchronized (tfb) {
- println(".close()");
- checkValid();
- in.close();
- if (tfb.streams.contains(in)) {
- tfb.streams.removeElement(in);
- }
- }
- }
-
-
- public void mark(int a) {
- synchronized (tfb) {
- println(".mark(int)");
- in.mark(a);
- }
- }
-
- public void reset() throws java.io.IOException {
- synchronized (tfb) {
- println(".reset()");
- checkValid();
- in.reset();
- }
- }
-
- public boolean markSupported() {
- synchronized (tfb) {
- println(".markSupported()");
- return in.markSupported();
- }
- }
-}
Deleted: branches/freenet-jfk/src/freenet/support/io/SpyOutputStream.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/SpyOutputStream.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/SpyOutputStream.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,116 +0,0 @@
-package freenet.support.io;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import freenet.support.Logger;
-
-/*
- * This code is part of FProxy, an HTTP proxy server for Freenet. It is
- * distributed under the GNU Public Licence (GPL) version 2. See
- * http://www.gnu.org/ for further details of the GPL.
- */
-
-/**
- * @author ian
- * @see freenet.support.SpyInputStream
- */
-public class SpyOutputStream extends FilterOutputStream {
-
- private String prefix = "";
- private TempFileBucket tfb = null;
-
- private void debugPrintLn(String text) {
- if (Logger.shouldLog(Logger.DEBUG,this))
- Logger.debug(this, text);
- }
-
- private final void checkValid() throws IOException {
- synchronized (tfb) {
- if (tfb.isReleased()) {
- throw new IOException(
- "Attempt to use a released
TempFileBucket: " + prefix);
- }
- }
- }
-
- /**
- * Constructor for the SpyOutputStream object
- *
- * @param tfb
- * @param pref
- * @exception IOException
- */
- public SpyOutputStream(TempFileBucket tfb, String pref)
- throws IOException {
- super(null);
- OutputStream tmpOut = null;
- try {
- this.prefix = pref;
- this.tfb = tfb;
- checkValid();
- tmpOut = tfb.getRealOutputStream();
- out = tmpOut;
- } catch (IOException ioe) {
- //ioe.printStackTrace();
- debugPrintLn("SpyOutputStream ctr failed!: " +
ioe.toString());
- try {
- if (tmpOut != null) {
- tmpOut.close();
- }
- } catch (Exception e0) {
- // NOP
- }
- debugPrintLn("SpyOutputStream ctr failed!: " +
ioe.toString());
- throw ioe;
- }
- debugPrintLn("Created new OutputStream");
- }
-
- ////////////////////////////////////////////////////////////
- // FilterOutputStream implementation
-
- public void write(int b) throws IOException {
- synchronized (tfb) {
- // println(".write(b)");
- checkValid();
- out.write(b);
- }
- }
-
- public void write(byte[] buf) throws IOException {
- synchronized (tfb) {
- // println(".write(buf)");
- checkValid();
- out.write(buf);
- }
- }
-
- public void write(byte[] buf, int off, int len) throws IOException {
- synchronized (tfb) {
- // println(".write(buf,off,len)");
- checkValid();
- out.write(buf, off, len);
- }
- }
-
- public void flush() throws IOException {
- synchronized (tfb) {
- debugPrintLn(".flush()");
- checkValid();
- out.flush();
- }
- }
-
- public void close() throws IOException {
- synchronized (tfb) {
- debugPrintLn(".close()");
- checkValid();
- out.close();
- if (tfb.streams.contains(out)) {
- tfb.streams.removeElement(out);
- }
- }
- }
-}
Modified: branches/freenet-jfk/src/freenet/support/io/TempBucketFactory.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/TempBucketFactory.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/TempBucketFactory.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,9 +1,7 @@
package freenet.support.io;
-import java.io.File;
import java.io.IOException;
-import freenet.support.Logger;
import freenet.support.api.Bucket;
import freenet.support.api.BucketFactory;
@@ -20,33 +18,19 @@
*/
public class TempBucketFactory implements BucketFactory {
- private static class NOPHook implements TempBucketHook {
- public void enlargeFile(long curLength, long finalLength) {
- }
- public void shrinkFile(long curLength, long finalLength) {
- }
- public void deleteFile(long curLength) {
- }
- public void createFile(long curLength) {
- }
- }
-
- private final static TempBucketHook DONT_HOOK = new NOPHook();
- private static TempBucketHook hook = DONT_HOOK;
- private static boolean logDebug=true;
-
private final FilenameGenerator filenameGenerator;
public static long defaultIncrement = 4096;
+
+ public static float DEFAULT_FACTOR = 1.25F;
// Storage accounting disabled by default.
public TempBucketFactory(FilenameGenerator filenameGenerator) {
- logDebug = Logger.shouldLog(Logger.DEBUG,this);
this.filenameGenerator = filenameGenerator;
}
public Bucket makeBucket(long size) throws IOException {
- return makeBucket(size, 1.25F, defaultIncrement);
+ return makeBucket(size, DEFAULT_FACTOR, defaultIncrement);
}
public Bucket makeBucket(long size, float factor) throws IOException {
@@ -67,61 +51,9 @@
*/
public TempFileBucket makeBucket(long size, float factor, long
increment)
throws IOException {
- logDebug = Logger.shouldLog(Logger.DEBUG,this);
- File f = filenameGenerator.makeRandomFilename();
- if(f == null) throw new NullPointerException();
+ long id = filenameGenerator.makeRandomFilename();
- return new TempFileBucket(f, hook, size, increment, factor);
+ return new TempFileBucket(id, filenameGenerator);
}
- /**
- * Free bucket
- *
- * @param b
- * Description of the Parameter
- */
- public void freeBucket(Bucket b) {
- if (b instanceof TempFileBucket) {
- if (logDebug)
- Logger.debug(
- this,
- "Temp bucket released: "
- + ((TempFileBucket)
b).getFile().getAbsolutePath(),
- new Exception("debug"));
- if (!((TempFileBucket) b).release()) {
- System.err.println("Could not release temp
bucket" + b);
- Logger.error(
- this,
- "Could not release temp bucket " + b,
- new Exception("Failed to release
tempbucket"));
- }
- }
- }
-
- /**
- * Sets the storage accounting hook.
- *
- * @param t
- * The hook object to use to keep track of the amount of
storage
- * used. It is legal for t to be null. In this case storage
- * accounting is disabled.
- */
- public static void setHook(TempBucketHook t) {
- if (logDebug)
- Logger.debug(
- TempBucketFactory.class,
- "Set TempBucketHook to " + t);
- hook = t;
- if (hook == null) {
- // Allow hooks to be disabled w/o sprinkling
- // if (hook != null) {/*blah blah */} calls
- // throughout the code.
- hook = DONT_HOOK;
- if (logDebug) {
- Logger.debug(
- TempBucketHook.class,
- "TempBucketHook file usage management
was disabled.");
- }
- }
- }
}
Deleted: branches/freenet-jfk/src/freenet/support/io/TempBucketHook.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/TempBucketHook.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/TempBucketHook.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,34 +0,0 @@
-/* This code is part of Freenet. It is distributed under the GNU General
- * Public License, version 2 (or at your option any later version). See
- * http://www.gnu.org/ for further details of the GPL. */
-package freenet.support.io;
-
-import java.io.IOException;
-
-public interface TempBucketHook {
-
- /** Allocate space for a write making the file larger
- * Call this before writing a file, make sure you call shrinkFile if the
write fails
- * @param curLength the length of the file before the write
- * @param finalLength the length of the file after the write
- * @throws IOException if insufficient space
- */
- void enlargeFile(long curLength, long finalLength) throws IOException;
-
- /** Deallocate space after a write enlarging the file fails
- * Call this if enlargeFile was called but the write failed.
- * Also call it if you want to truncate a file
- * @param curLength original length before write
- * @param finalLength length the file would have been if the write had
succeeded
- */
- void shrinkFile(long curLength, long finalLength);
-
- /** Deallocate space for a temp file, AFTER successful delete completed
- */
- void deleteFile(long curLength);
-
- /** Allocate space for a temp file, before actually creating it
- */
- void createFile(long curLength) throws IOException;
-
-}
Modified: branches/freenet-jfk/src/freenet/support/io/TempFileBucket.java
===================================================================
--- branches/freenet-jfk/src/freenet/support/io/TempFileBucket.java
2007-08-21 19:57:05 UTC (rev 14827)
+++ branches/freenet-jfk/src/freenet/support/io/TempFileBucket.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,13 +1,10 @@
package freenet.support.io;
import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Vector;
import freenet.support.Logger;
import freenet.support.SimpleFieldSet;
+import freenet.support.api.Bucket;
/*
* This code is part of FProxy, an HTTP proxy server for Freenet.
@@ -19,423 +16,70 @@
*
* @author giannij
*/
-public class TempFileBucket extends FileBucket {
- TempBucketHook hook = null;
- // How much we have asked the Hook to allocate for us
- long fakeLength = 0;
- long minAlloc;
- float factor;
+public class TempFileBucket extends BaseFileBucket implements Bucket,
SerializableToFieldSetBucket {
+ long filenameID;
+ final FilenameGenerator generator;
private static boolean logDebug = true;
+ private boolean readOnly;
/**
* Constructor for the TempFileBucket object
*
* @param f File
*/
- protected TempFileBucket(
- File f,
- TempBucketHook hook,
- long startLength,
- long minAlloc,
- float factor)
- throws IOException {
- super(f, false, false, true, true, true);
+ public TempFileBucket(
+ long id,
+ FilenameGenerator generator) {
+ super(generator.getFilename(id));
+ this.filenameID = id;
+ this.generator = generator;
synchronized(this) {
logDebug = Logger.shouldLog(Logger.DEBUG, this);
}
- if (minAlloc > 0)
- this.minAlloc = minAlloc;
- else
- this.minAlloc = 1024;
- this.factor = factor;
- if (factor < 1.0)
- throw new IllegalArgumentException("factor must be >=
1.0");
- // Make sure finalize wacks temp file
- // if it is not explictly freed.
- deleteOnFinalize = true;
-
//System.err.println("FProxyServlet.TempFileBucket -- created:
" +
// f.getAbsolutePath());
- this.hook = hook;
- long x = startLength <= 0 ? minAlloc : startLength;
- hook.createFile(x);
- this.fakeLength = x;
synchronized(this) {
if (logDebug)
Logger.debug(
this,
- "Initializing TempFileBucket(" + f +
',' + hook + ')');
+ "Initializing TempFileBucket(" +
getFile());
}
}
- /**
- * Gets the realInputStream attribute of the TempFileBucket object
- *
- * @return The realInputStream value
- * @exception IOException Description of the Exception
- */
- synchronized InputStream getRealInputStream() throws IOException {
- if (released)
- throw new IllegalStateException(
- "Trying to getInputStream on " + "released
TempFileBucket!");
- if (logDebug)
- Logger.debug(
- this,
- "getRealInputStream() for " + file,
- new Exception("debug"));
- if (!file.exists())
- return new NullInputStream();
- else
- return new HookedFileBucketInputStream(file);
+ protected boolean deleteOnFinalize() {
+ // Make sure finalize wacks temp file
+ // if it is not explictly freed.
+ return true;
}
-
- /**
- * Gets the realOutputStream attribute of the TempFileBucket object
- *
- * @return The realOutputStream value
- * @exception IOException Description of the Exception
- */
- OutputStream getRealOutputStream() throws IOException {
- synchronized(this) {
- if (logDebug)
- Logger.debug(
- this,
- "getRealOutputStream() for " + file,
- new Exception("debug"));
- }
- return super.getOutputStream();
+
+ public SimpleFieldSet toFieldSet() {
+ if(deleteOnFinalize())
+ return null; // Not persistent
+ // For subclasses i.e. PersistentTempFileBucket
+ return super.toFieldSet();
}
- // Wrap non-const members so we can tell
- // when code touches the Bucket after it
- // has been released.
- /**
- * Gets the inputStream attribute of the TempFileBucket object
- *
- * @return The inputStream value
- * @exception IOException Description of the Exception
- */
- public synchronized InputStream getInputStream() throws IOException {
- logDebug = Logger.shouldLog(Logger.DEBUG, this);
- if (logDebug)
- Logger.debug(this, "getInputStream for " + file);
- InputStream newIn = new SpyInputStream(this,
file.getAbsolutePath());
- return newIn;
+ protected boolean createFileOnly() {
+ return false;
}
- /**
- * Gets the outputStream attribute of the TempFileBucket object
- *
- * @return The outputStream value
- * @exception IOException Description of the Exception
- */
- public synchronized OutputStream getOutputStream() throws IOException {
- logDebug = Logger.shouldLog(Logger.DEBUG, this);
- if (logDebug)
- Logger.debug(this, "getOutputStream for " + file);
- return new SpyOutputStream(this, file.getAbsolutePath());
- }
-
- /**
- * Release
- *
- * @return Success
- */
- public synchronized boolean release() {
- if(Logger.shouldLog(Logger.MINOR, this))
- Logger.minor(this, "Releasing bucket: "+file, new
Exception("debug"));
- //System.err.println("FProxyServlet.TempFileBucket -- release:
" + // file.getAbsolutePath());
-
- //System.err.println("CALL STACK: ");
- //(new Exception()).printStackTrace();
-
- // Force all open streams closed.
- // Windows won't let us delete the file unless we
- // do this.
- logDebug = Logger.shouldLog(Logger.DEBUG, this);
- if (logDebug)
- Logger.debug(this, "Releasing TempFileBucket " + file);
- for (int i = 0; i < streams.size(); i++) {
- try {
- if (streams.elementAt(i) instanceof
InputStream) {
- InputStream is = (InputStream)
streams.elementAt(i);
- is.close();
-
- if (logDebug) {
- Logger.debug(
- this,
- "closed open
InputStream !: "
- +
file.getAbsolutePath(),
- new Exception("debug"));
- if (is instanceof
FileBucketInputStream) {
- Logger.debug(
- this,
- "Open
InputStream created: ",
-
((FileBucketInputStream) is).e);
- }
- }
- } else if (streams.elementAt(i) instanceof
OutputStream) {
- OutputStream os = (OutputStream)
(streams.elementAt(i));
- os.close();
- if (logDebug) {
- Logger.debug(
- this,
- "closed open
OutputStream !: "
- +
file.getAbsolutePath(),
- new Exception("debug"));
-// if (os instanceof
FileBucketOutputStream) {
-// Logger.debug(
-// this,
-// "Open
OutputStream created: ",
-//
((FileBucketOutputStream) os).e);
-// }
-
- }
- }
- } catch (IOException ioe) {
- }
- }
- if (logDebug)
- Logger.debug(this, "Closed streams for " + file);
- if (released) {
- if(Logger.shouldLog(Logger.MINOR, this))
- Logger.minor(this,
- "Already released file: " +
file.getName());
- if (file.exists())
- throw new IllegalStateException(
- "already released file "
- + file.getName()
- + " BUT IT STILL EXISTS!");
- return true;
- }
- if (logDebug)
- Logger.debug(
- this,
- "Checked for released for " + file);
- released = true;
- if (file.exists()) {
- if (logDebug)
- Logger.debug(
- this,
- "Deleting bucket " + file.getName());
- if (!file.delete()) {
- Logger.error(
- this,
- "Delete failed on bucket " +
file.getName(),
- new Exception());
- // Nonrecoverable; even though the user can't
fix it it's still very serious
- return false;
- } else {
- if (hook != null)
- hook.deleteFile(fakeLength);
- }
- } else {
- if (hook != null)
- hook.deleteFile(fakeLength);
- }
- if (logDebug)
- Logger.debug(
- this,
- "release() returning true for " + file);
+ protected boolean deleteOnFree() {
return true;
}
- /**
- * Gets the released attribute of the TempFileBucket object
- *
- * @return The released value
- */
- public final synchronized boolean isReleased() {
- return released;
+ public File getFile() {
+ return generator.getFilename(filenameID);
}
-// /**
-// * Finalize
-// *
-// * @exception Throwable Description of the Exception
-// */
-// public void finalize() throws Throwable {
-// if (logDebug)
-// Logger.debug(this, "Finalizing TempFileBucket for " +
file);
-// super.finalize();
-// }
-
- protected Vector streams = new Vector();
- private boolean released;
-
- protected synchronized FileBucketOutputStream newFileBucketOutputStream(
- String s,
- boolean append,
- long restartCount)
- throws IOException {
- if (logDebug)
- Logger.debug(this,
- "Creating new HookedFileBucketOutputStream for
" + file);
- if (hook != null)
- return new HookedFileBucketOutputStream(s,
restartCount);
- else
- return super.newFileBucketOutputStream(new File(s), s,
restartCount);
+ public boolean isReadOnly() {
+ return readOnly;
}
- protected synchronized void deleteFile() {
- if (logDebug)
- Logger.debug(this, "Deleting " + file);
- file.delete();
- if (hook != null)
- hook.deleteFile(fakeLength);
+ public void setReadOnly() {
+ readOnly = true;
}
- protected synchronized void resetLength() {
- if (logDebug)
- Logger.debug(this, "Resetting length for " + file);
- if (length != 0) {
- if (hook != null) {
- hook.shrinkFile(0, fakeLength);
- fakeLength = 0;
- }
- super.resetLength();
- }
+ protected boolean deleteOnExit() {
+ return true;
}
-
- protected final synchronized void getLengthSynchronized(long len)
throws IOException {
- // Core.logger.log(this, "getLengthSynchronized("+len+
- // "); fakeLength = "+fakeLength,
Logger.DEBUG);
- long l = fakeLength;
- long ol = l;
- while (len > l) {
- l = (long) (l * factor);
- if (minAlloc > 0)
- l = l + minAlloc - (l % minAlloc);
- if (l <= fakeLength)
- throw new IllegalStateException("Bucket
extension error!");
- // Core.logger.log(this, "l now "+l,
Logger.DEBUG);
- if (ol == l)
- throw new IllegalStateException("infinite
loop");
- ol = l;
- }
- if (fakeLength != l) {
- if (Logger.shouldLog(Logger.DEBUG, this))
- Logger.debug(
- this,
- "getLengthSynchronized("
- + len
- + "): increasing "
- + fakeLength
- + " to: "
- + l
- + " (real length: "
- + length
- + ')');
- hook.enlargeFile(fakeLength, l);
- }
- fakeLength = l;
- }
-
- public synchronized String toString(){
- return "TempFileBucket (File:
'"+getFile().getAbsolutePath()+"', streams: "+streams.size()+", hook: "+hook+
')';
- }
-
- class HookedFileBucketInputStream extends FileBucketInputStream {
- HookedFileBucketInputStream(File f) throws IOException {
- super(f);
- streams.addElement(this);
- }
-
- public void close() throws IOException {
- super.close();
- while (streams.remove(this));
- }
- }
-
- class HookedFileBucketOutputStream extends FileBucketOutputStream {
-
- protected HookedFileBucketOutputStream(
- String s,
- long restartCount)
- throws IOException {
- super(new File(s), s, restartCount);
- streams.addElement(this);
- if (Logger.shouldLog(Logger.DEBUG, this))
- Logger.debug(
- this,
- "Created HookedFileBucketOutputStream("
- + s
- + ','
- + restartCount
- + ')');
- }
-
- public void close() throws IOException {
- super.close();
- while (streams.remove(this));
- }
-
- public void write(byte[] b) throws IOException {
- // Core.logger.log(this,
"HookedFileBucketOutputStream.write(byte[] len "+
- // b.length+") for "+file,
Logger.DEBUG);
- synchronized (TempFileBucket.this) {
- // Core.logger.log(this,
"Synchronized on TempFileBucket",
- // Logger.DEBUG);
- super.confirmWriteSynchronized();
- // Core.logger.log(this,
"confirmWriteSynchronized()", Logger.DEBUG);
- long finalLength = length + b.length;
- // Core.logger.log(this,
"length="+length+", finalLength="+finalLength,
- // Logger.DEBUG);
- long realStartLen = fakeLength;
- getLengthSynchronized(finalLength);
- // Core.logger.log(this, "Called
hook.enlargeFile()", Logger.DEBUG);
- try {
- super.write(b);
- // Core.logger.log(this,
"Written", Logger.DEBUG);
- } catch (IOException e) {
- // Core.logger.log(this,
"Write failed", Logger.DEBUG);
- hook.shrinkFile(realStartLen,
fakeLength);
- fakeLength = realStartLen;
- // Core.logger.log(this,
"Shrank file", Logger.DEBUG);
- throw e;
- }
- }
- }
-
- public void write(byte[] b, int off, int len) throws
IOException {
- // Core.logger.log(this,
"HookedFileBucketOutputStream.write(byte[], "+off+
- // ","+len+") for "+file,
Logger.DEBUG);
- synchronized (TempFileBucket.this) {
- long finalLength = length + len;
- long realStartLen = fakeLength;
- getLengthSynchronized(finalLength);
- try {
- super.write(b, off, len);
- } catch (IOException e) {
- hook.shrinkFile(realStartLen,
fakeLength);
- fakeLength = realStartLen;
- throw e;
- }
- }
- }
-
- public void write(int b) throws IOException {
- // Core.logger.log(this,
"HookedFileBucketOutputStream.write(int) for "+file,
- // Logger.DEBUG);
- synchronized (TempFileBucket.this) {
- long finalLength = length + 1;
- long realStartLen = fakeLength;
- getLengthSynchronized(finalLength);
- try {
- super.write(b);
- } catch (IOException e) {
- hook.shrinkFile(realStartLen,
fakeLength);
- fakeLength = realStartLen;
- throw e;
- }
- }
- }
-
- }
-
- public SimpleFieldSet toFieldSet() {
- SimpleFieldSet fs = super.toFieldSet();
- fs.putSingle("Type", "TempFileBucket");
- return fs;
- }
}
Modified:
branches/freenet-jfk/src/freenet/support/math/TimeDecayingRunningAverage.java
===================================================================
---
branches/freenet-jfk/src/freenet/support/math/TimeDecayingRunningAverage.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/freenet/support/math/TimeDecayingRunningAverage.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -7,6 +7,7 @@
import java.io.DataOutputStream;
import java.io.IOException;
+import freenet.node.TimeSkewDetectorCallback;
import freenet.support.Logger;
import freenet.support.SimpleFieldSet;
@@ -40,6 +41,7 @@
double minReport;
double maxReport;
boolean logDEBUG;
+ private final TimeSkewDetectorCallback timeSkewCallback;
public String toString() {
long now = System.currentTimeMillis();
@@ -53,7 +55,7 @@
}
public TimeDecayingRunningAverage(double defaultValue, long halfLife,
- double min, double max) {
+ double min, double max, TimeSkewDetectorCallback callback) {
curValue = defaultValue;
this.defaultValue = defaultValue;
started = false;
@@ -66,10 +68,11 @@
if(logDEBUG)
Logger.debug(this, "Created "+this,
new Exception("debug"));
+ this.timeSkewCallback = callback;
}
public TimeDecayingRunningAverage(double defaultValue, long halfLife,
- double min, double max, SimpleFieldSet fs) {
+ double min, double max, SimpleFieldSet fs,
TimeSkewDetectorCallback callback) {
curValue = defaultValue;
this.defaultValue = defaultValue;
started = false;
@@ -87,7 +90,7 @@
started = fs.getBoolean("Started", false);
if(started) {
curValue = fs.getDouble("CurrentValue", curValue);
- if(curValue > maxReport || curValue < minReport) {
+ if(curValue > maxReport || curValue < minReport ||
Double.isNaN(curValue)) {
curValue = defaultValue;
totalReports = 0;
createdTime = System.currentTimeMillis();
@@ -98,9 +101,10 @@
}
}
}
+ this.timeSkewCallback = callback;
}
- public TimeDecayingRunningAverage(double defaultValue, double halfLife,
double min, double max, DataInputStream dis) throws IOException {
+ public TimeDecayingRunningAverage(double defaultValue, double halfLife,
double min, double max, DataInputStream dis, TimeSkewDetectorCallback callback)
throws IOException {
int m = dis.readInt();
if(m != MAGIC) throw new IOException("Invalid magic "+m);
int v = dis.readInt();
@@ -120,6 +124,7 @@
lastReportTime = -1;
createdTime = System.currentTimeMillis() - priorExperienceTime;
totalReports = dis.readLong();
+ this.timeSkewCallback = callback;
}
public TimeDecayingRunningAverage(TimeDecayingRunningAverage a) {
@@ -132,6 +137,7 @@
this.started = a.started;
this.totalReports = a.totalReports;
this.curValue = a.curValue;
+ this.timeSkewCallback = a.timeSkewCallback;
}
public synchronized double currentValue() {
@@ -165,13 +171,17 @@
now - lastReportTime;
long uptime = now - createdTime;
if(thisInterval < 0) {
- Logger.error(this, "Clock (reporting)
went back in time, ignoring report: "+now+" was "+lastReportTime+" (back
"+(-thisInterval)+"ms");
+ Logger.error(this, "Clock (reporting)
went back in time, ignoring report: "+now+" was "+lastReportTime+" (back
"+(-thisInterval)+"ms)");
lastReportTime = now;
+ if(timeSkewCallback != null)
+
timeSkewCallback.setTimeSkewDetectedUserAlert();
return;
}
double thisHalfLife = halfLife;
if(uptime < 0) {
- Logger.error(this, "Clock (uptime) went
back in time, ignoring report: "+now+" was "+createdTime+" (back
"+(-uptime)+"ms");
+ Logger.error(this, "Clock (uptime) went
back in time, ignoring report: "+now+" was "+createdTime+" (back
"+(-uptime)+"ms)");
+ if(timeSkewCallback != null)
+
timeSkewCallback.setTimeSkewDetectedUserAlert();
return;
} else {
if((uptime / 4) < thisHalfLife)
thisHalfLife = (uptime / 4);
Copied: branches/freenet-jfk/src/freenet/tools/MergeSFS.java (from rev 14796,
trunk/freenet/src/freenet/tools/MergeSFS.java)
===================================================================
--- branches/freenet-jfk/src/freenet/tools/MergeSFS.java
(rev 0)
+++ branches/freenet-jfk/src/freenet/tools/MergeSFS.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,26 @@
+package freenet.tools;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import freenet.support.SimpleFieldSet;
+
+public class MergeSFS {
+
+ /**
+ * @param args
+ * @throws IOException
+ */
+ public static void main(String[] args) throws IOException {
+ File f1 = new File(args[0]);
+ File f2 = new File(args[1]);
+ SimpleFieldSet fs1 = SimpleFieldSet.readFrom(f1, false, true);
+ SimpleFieldSet fs2 = SimpleFieldSet.readFrom(f2, false, true);
+ fs1.putAllOverwrite(fs2);
+ PrintWriter pw = new PrintWriter(System.out);
+ fs1.writeToOrdered(pw);
+ pw.flush();
+ }
+
+}
Modified:
branches/freenet-jfk/src/org/spaceroots/mantissa/random/MersenneTwister.java
===================================================================
---
branches/freenet-jfk/src/org/spaceroots/mantissa/random/MersenneTwister.java
2007-08-21 19:57:05 UTC (rev 14827)
+++
branches/freenet-jfk/src/org/spaceroots/mantissa/random/MersenneTwister.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -68,193 +68,187 @@
* @version $Id: MersenneTwister.java,v 1.1 2005/02/07 23:03:14 amphibian Exp $
*/
-public class MersenneTwister
- extends Random {
-
+public class MersenneTwister extends Random {
private static final long serialVersionUID = -1;
-
- /** Creates a new random number generator.
- * <p>The instance is initialized using the current time as the
- * seed.</p>
- */
- public MersenneTwister() {
- mt = new int[N];
- setSeed(System.currentTimeMillis());
- }
- /** Creates a new random number generator using a single int seed.
- * @param seed the initial seed (32 bits integer)
- */
- public MersenneTwister(int seed) {
- mt = new int[N];
- setSeed(seed);
- }
+ private static final int N = 624;
+ private static final int M = 397;
+ private static final int[] MAG01 = { 0x0, 0x9908b0df };
- /** Creates a new random number generator using an int array seed.
- * @param seed the initial seed (32 bits integers array), if null
- * the seed of the generator will be related to the current time
- */
- public MersenneTwister(int[] seed) {
- mt = new int[N];
- setSeed(seed);
- }
+ private final int[] mt;
+ private int mti;
- /** Seed from byte[] */
- public MersenneTwister(byte[] seed) {
- mt = new int[N];
- setSeed(seed);
- }
-
- /** Creates a new random number generator using a single long seed.
- * @param seed the initial seed (64 bits integer)
- */
- public MersenneTwister(long seed) {
- mt = new int[N];
- setSeed(seed);
- }
+ /** Creates a new random number generator.
+ * <p>The instance is initialized using the current time as the
+ * seed.</p>
+ */
+ public MersenneTwister() {
+ mt = new int[N];
+ setSeed(System.currentTimeMillis());
+ }
- /** Reinitialize the generator as if just built with the given int seed.
- * <p>The state of the generator is exactly the same as a new
- * generator built with the same seed.</p>
- * @param seed the initial seed (32 bits integer)
- */
- public void setSeed(int seed) {
- // we use a long masked by 0xffffffffL as a poor man unsigned int
- long longMT = seed;
- mt[0]= (int) longMT;
- for (mti = 1; mti < N; ++mti) {
- // See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
- // initializer from the 2002-01-09 C version by Makoto Matsumoto
- longMT = (1812433253l * (longMT ^ (longMT >> 30)) + mti) & 0xffffffffL;
- mt[mti]= (int) longMT;
- }
- }
+ /** Creates a new random number generator using a single int seed.
+ * @param seed the initial seed (32 bits integer)
+ */
+ public MersenneTwister(int seed) {
+ mt = new int[N];
+ setSeed(seed);
+ }
- /**
- * Seed from byte[].
- */
- public void setSeed(byte[] seed) {
- int[] seeds = new int[seed.length/4];
- for(int i=0;i<seeds.length;i+=4) {
- seeds[i] = Fields.bytesToInt(seed, i);
- }
- setSeed(seeds);
- }
-
- /** Reinitialize the generator as if just built with the given int array
seed.
- * <p>The state of the generator is exactly the same as a new
- * generator built with the same seed.</p>
- * @param seed the initial seed (32 bits integers array), if null
- * the seed of the generator will be related to the current time
- */
- public void setSeed(int[] seed) {
+ /** Creates a new random number generator using an int array seed.
+ * @param seed the initial seed (32 bits integers array), if null
+ * the seed of the generator will be related to the current time
+ */
+ public MersenneTwister(int[] seed) {
+ mt = new int[N];
+ setSeed(seed);
+ }
- if (seed == null) {
- setSeed(System.currentTimeMillis());
- return;
- }
+ /** Seed from byte[] */
+ public MersenneTwister(byte[] seed) {
+ mt = new int[N];
+ setSeed(seed);
+ }
- setSeed(19650218);
- int i = 1;
- int j = 0;
+ /** Creates a new random number generator using a single long seed.
+ * @param seed the initial seed (64 bits integer)
+ */
+ public MersenneTwister(long seed) {
+ mt = new int[N];
+ setSeed(seed);
+ }
- for (int k = Math.max(N, seed.length); k != 0; k--) {
- long l0 = (mt[i] & 0x7fffffffl) | ((mt[i] < 0) ? 0x80000000l : 0x0l);
- long l1 = (mt[i-1] & 0x7fffffffl) | ((mt[i-1] < 0) ? 0x80000000l : 0x0l);
- long l = (l0 ^ ((l1 ^ (l1 >> 30)) * 1664525l)) + seed[j] + j; // non
linear
- mt[i] = (int) (l & 0xffffffffl);
- i++; j++;
- if (i >= N) {
- mt[0] = mt[N - 1];
- i = 1;
- }
- if (j >= seed.length) {
- j = 0;
- }
- }
+ /** Reinitialize the generator as if just built with the given int seed.
+ * <p>The state of the generator is exactly the same as a new
+ * generator built with the same seed.</p>
+ * @param seed the initial seed (32 bits integer)
+ */
+ public synchronized void setSeed(int seed) {
+ // we use a long masked by 0xffffffffL as a poor man unsigned
int
+ long longMT = seed;
+ mt[0]= (int) longMT;
+ for (mti = 1; mti < N; ++mti) {
+ // See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
+ // initializer from the 2002-01-09 C version by Makoto
Matsumoto
+ longMT = (1812433253l * (longMT ^ (longMT >> 30)) +
mti) & 0xffffffffL;
+ mt[mti]= (int) longMT;
+ }
+ }
- for (int k = N - 1; k != 0; k--) {
- long l0 = (mt[i] & 0x7fffffffl) | ((mt[i] < 0) ? 0x80000000l : 0x0l);
- long l1 = (mt[i-1] & 0x7fffffffl) | ((mt[i-1] < 0) ? 0x80000000l : 0x0l);
- long l = (l0 ^ ((l1 ^ (l1 >> 30)) * 1566083941l)) - i; // non linear
- mt[i] = (int) (l & 0xffffffffL);
- i++;
- if (i >= N) {
- mt[0] = mt[N - 1];
- i = 1;
- }
- }
+ /**
+ * Seed from byte[].
+ */
+ public synchronized void setSeed(byte[] seed) {
+ int[] seeds = new int[seed.length/4];
+ for(int i=0;i<seeds.length;i+=4) {
+ seeds[i] = Fields.bytesToInt(seed, i);
+ }
+ setSeed(seeds);
+ }
- mt[0] = 0x80000000; // MSB is 1; assuring non-zero initial array
+ /** Reinitialize the generator as if just built with the given int
array seed.
+ * <p>The state of the generator is exactly the same as a new
+ * generator built with the same seed.</p>
+ * @param seed the initial seed (32 bits integers array), if null
+ * the seed of the generator will be related to the current time
+ */
+ public synchronized void setSeed(int[] seed) {
+ if (seed == null) {
+ setSeed(System.currentTimeMillis());
+ return;
+ }
- }
+ setSeed(19650218);
+ int i = 1;
+ int j = 0;
- /** Reinitialize the generator as if just built with the given long seed.
- * <p>The state of the generator is exactly the same as a new
- * generator built with the same seed.</p>
- * @param seed the initial seed (64 bits integer)
- */
- public void setSeed(long seed) {
- if (mt == null) {
- // this is probably a spurious call from base class constructor,
- // we do nothing and wait for the setSeed in our own
- // constructors after array allocation
- return;
- }
- setSeed(new int[] { (int) (seed >>> 32), (int) (seed & 0xffffffffl) });
- }
+ for (int k = Math.max(N, seed.length); k != 0; k--) {
+ long l0 = (mt[i] & 0x7fffffffl) | ((mt[i] < 0) ?
0x80000000l : 0x0l);
+ long l1 = (mt[i-1] & 0x7fffffffl) | ((mt[i-1] < 0) ?
0x80000000l : 0x0l);
+ long l = (l0 ^ ((l1 ^ (l1 >> 30)) * 1664525l)) +
seed[j] + j; // non linear
+ mt[i] = (int) (l & 0xffffffffl);
+ i++; j++;
+ if (i >= N) {
+ mt[0] = mt[N - 1];
+ i = 1;
+ }
+ if (j >= seed.length) {
+ j = 0;
+ }
+ }
- /** Generate next pseudorandom number.
- * <p>This method is the core generation algorithm. As per
- * <code>java.util.Random</code> contract, it is used by all the
- * public generation methods for the various primitive types {@link
- * #nextBoolean nextBoolean}, {@link #nextBytes nextBytes}, {@link
- * #nextDouble nextDouble}, {@link #nextFloat nextFloat}, {@link
- * #nextGaussian nextGaussian}, {@link #nextInt nextInt} and {@link
- * #nextLong nextLong}.</p>
- * @param bits number of random bits to produce
- */
- protected int next(int bits) {
+ for (int k = N - 1; k != 0; k--) {
+ long l0 = (mt[i] & 0x7fffffffl) | ((mt[i] < 0) ?
0x80000000l : 0x0l);
+ long l1 = (mt[i-1] & 0x7fffffffl) | ((mt[i-1] < 0) ?
0x80000000l : 0x0l);
+ long l = (l0 ^ ((l1 ^ (l1 >> 30)) * 1566083941l)) - i;
// non linear
+ mt[i] = (int) (l & 0xffffffffL);
+ i++;
+ if (i >= N) {
+ mt[0] = mt[N - 1];
+ i = 1;
+ }
+ }
- int y;
+ mt[0] = 0x80000000; // MSB is 1; assuring non-zero initial array
- if (mti >= N) { // generate N words at one time
- int mtNext = mt[0];
- for (int k = 0; k < N - M; ++k) {
- int mtCurr = mtNext;
- mtNext = mt[k + 1];
- y = (mtCurr & 0x80000000) | (mtNext & 0x7fffffff);
- mt[k] = mt[k + M] ^ (y >>> 1) ^ MAG01[y & 0x1];
- }
- for (int k = N - M; k < N - 1; ++k) {
- int mtCurr = mtNext;
- mtNext = mt[k + 1];
- y = (mtCurr & 0x80000000) | (mtNext & 0x7fffffff);
- mt[k] = mt[k + (M - N)] ^ (y >>> 1) ^ MAG01[y & 0x1];
- }
- y = (mtNext & 0x80000000) | (mt[0] & 0x7fffffff);
- mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ MAG01[y & 0x1];
+ }
- mti = 0;
- }
-
- y = mt[mti++];
+ /** Reinitialize the generator as if just built with the given long
seed.
+ * <p>The state of the generator is exactly the same as a new
+ * generator built with the same seed.</p>
+ * @param seed the initial seed (64 bits integer)
+ */
+ public synchronized void setSeed(long seed) {
+ if (mt == null) {
+ // this is probably a spurious call from base class
constructor,
+ // we do nothing and wait for the setSeed in our own
+ // constructors after array allocation
+ return;
+ }
+ setSeed(new int[] { (int) (seed >>> 32), (int) (seed &
0xffffffffl) });
+ }
- // tempering
- y ^= (y >>> 11);
- y ^= (y << 7) & 0x9d2c5680;
- y ^= (y << 15) & 0xefc60000;
- y ^= (y >>> 18);
+ /** Generate next pseudorandom number.
+ * <p>This method is the core generation algorithm. As per
+ * <code>java.util.Random</code> contract, it is used by all the
+ * public generation methods for the various primitive types {@link
+ * #nextBoolean nextBoolean}, {@link #nextBytes nextBytes}, {@link
+ * #nextDouble nextDouble}, {@link #nextFloat nextFloat}, {@link
+ * #nextGaussian nextGaussian}, {@link #nextInt nextInt} and {@link
+ * #nextLong nextLong}.</p>
+ * @param bits number of random bits to produce
+ */
+ protected synchronized int next(int bits) {
+ int y;
- return y >>> (32 - bits);
+ if (mti >= N) { // generate N words at one time
+ int mtNext = mt[0];
+ for (int k = 0; k < N - M; ++k) {
+ int mtCurr = mtNext;
+ mtNext = mt[k + 1];
+ y = (mtCurr & 0x80000000) | (mtNext &
0x7fffffff);
+ mt[k] = mt[k + M] ^ (y >>> 1) ^ MAG01[y & 0x1];
+ }
+ for (int k = N - M; k < N - 1; ++k) {
+ int mtCurr = mtNext;
+ mtNext = mt[k + 1];
+ y = (mtCurr & 0x80000000) | (mtNext &
0x7fffffff);
+ mt[k] = mt[k + (M - N)] ^ (y >>> 1) ^ MAG01[y &
0x1];
+ }
+ y = (mtNext & 0x80000000) | (mt[0] & 0x7fffffff);
+ mt[N - 1] = mt[M - 1] ^ (y >>> 1) ^ MAG01[y & 0x1];
- }
+ mti = 0;
+ }
- private static final int N = 624;
- private static final int M = 397;
- private static final int[] MAG01 = { 0x0, 0x9908b0df };
+ y = mt[mti++];
- private int[] mt;
- private int mti;
+ // tempering
+ y ^= (y >>> 11);
+ y ^= (y << 7) & 0x9d2c5680;
+ y ^= (y << 15) & 0xefc60000;
+ y ^= (y >>> 18);
+ return y >>> (32 - bits);
+ }
}
Copied: branches/freenet-jfk/test/freenet/support (from rev 14796,
trunk/freenet/test/freenet/support)
Deleted: branches/freenet-jfk/test/freenet/support/Base64Test.java
===================================================================
--- trunk/freenet/test/freenet/support/Base64Test.java 2007-08-18 19:36:17 UTC
(rev 14796)
+++ branches/freenet-jfk/test/freenet/support/Base64Test.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -1,159 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-package freenet.support;
-
-import junit.framework.TestCase;
-import java.util.Arrays;
-
-/**
- * Test case for {@link freenet.support.Base64} class.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class Base64Test extends TestCase {
-
- /**
- * Test the encode(byte[]) method
- * against a well-known example
- * (see http://en.wikipedia.org/wiki/Base_64 as reference)
- * to verify if it encode works correctly.
- */
- public void testEncode() {
- String toEncode = "Man is distinguished, not only by his
reason, but by this singular " +
- "passion from other animals, which is a lust of
the mind, that by a perseverance " +
- "of delight in the continued and indefatigable
generation of knowledge, exceeds " +
- "the short vehemence of any carnal pleasure.";
- String expectedResult =
"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ" +
-
"1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG"
+
-
"x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY"
+
-
"29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRz"
+
-
"IHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4";
- byte[] aByteArrayToEncode = toEncode.getBytes();
- assertEquals(Base64.encode(aByteArrayToEncode),expectedResult);
- }
-
- /**
- * Test the decode(String) method
- * against a well-known example
- * (see http://en.wikipedia.org/wiki/Base_64 as reference)
- * to verify if it decode an already encoded string correctly.
- */
- public void testDecode() {
- String toDecode =
"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ" +
-
"1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG"
+
-
"x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY"
+
-
"29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRz"
+
-
"IHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=";
- String expectedResult = "Man is distinguished, not only by his
reason, but by this singular " +
- "passion from other animals, which is a lust of
the mind, that by a perseverance " +
- "of delight in the continued and indefatigable
generation of knowledge, exceeds " +
- "the short vehemence of any carnal pleasure.";
- try {
- String decodedString = new
String(Base64.decode(toDecode));
- assertEquals(decodedString,expectedResult);
- } catch (IllegalBase64Exception aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
-
- /**
- * Test encode(byte[] in)
- * and decode(String inStr) methods,
- * to verify if they work correctly together.
- * It compares the string before encoding
- * and with the one after decoding.
- */
- public void testEncodeDecode() {
- byte[] bytesDecoded;
- byte[] bytesToEncode = new byte[5];
-
- //byte upper bound
- bytesToEncode[0] = 127;
- bytesToEncode[1] = 64;
- bytesToEncode[2] = 0;
- bytesToEncode[3] = -64;
- //byte lower bound
- bytesToEncode[4] = -128;
-
- String aBase64EncodedString = Base64.encode(bytesToEncode);
-
- try {
- bytesDecoded = Base64.decode(aBase64EncodedString);
- assertTrue(Arrays.equals(bytesToEncode,bytesDecoded));
}
- catch (IllegalBase64Exception aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
-
- /**
- * Test the encode(String,boolean)
- * method to verify if the padding
- * character '=' is correctly placed.
- */
- public void testEncodePadding() {
- byte[][] methodBytesArray = {
- //three byte Array -> no padding char expected
- {4,4,4},
- //two byte Array -> one padding char expected
- {4,4},
- //one byte Array -> two padding-chars expected
- {4}};
- String encoded;
-
- for (int i = 0; i<methodBytesArray.length; i++) {
- encoded = Base64.encode(methodBytesArray[i],true);
- if (i == 0)
- //no occurrences expected
- assertEquals(encoded.indexOf('='),-1);
- else
-
assertEquals(encoded.indexOf('='),encoded.length()-i);
- }
- }
-
- /**
- * Test if the decode(String) method
- * raise correctly an exception when
- * providing a string with non-Base64
- * characters.
- */
- public void testIllegalBaseCharacter() {
-// TODO: check many other possibile cases!
- String illegalCharString = "abcd=fghilmn";
- try {
- Base64.decode(illegalCharString);
- fail("Expected IllegalBase64Exception not thrown"); }
- catch (IllegalBase64Exception exception) {
- assertSame("illegal Base64
character",exception.getMessage()); }
- }
-
- /**
- * Test if the decode(String) method
- * raise correctly an exception when
- * providing a string with a
- * wrong Base64 length.
- * (as we can consider not-padded strings too,
- * the only wrong lengths are the ones
- * where -> number MOD 4 = 1).
- */
- public void testIllegalBaseLength() {
- //most interesting case
- String illegalLengthString = "a";
- try {
- Base64.decode(illegalLengthString);
- fail("Expected IllegalBase64Exception not thrown"); }
- catch (IllegalBase64Exception exception) {
- assertSame("illegal Base64
length",exception.getMessage()); }
- }
-}
\ No newline at end of file
Copied: branches/freenet-jfk/test/freenet/support/Base64Test.java (from rev
14796, trunk/freenet/test/freenet/support/Base64Test.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/Base64Test.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/Base64Test.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,159 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package freenet.support;
+
+import junit.framework.TestCase;
+import java.util.Arrays;
+
+/**
+ * Test case for {@link freenet.support.Base64} class.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class Base64Test extends TestCase {
+
+ /**
+ * Test the encode(byte[]) method
+ * against a well-known example
+ * (see http://en.wikipedia.org/wiki/Base_64 as reference)
+ * to verify if it encode works correctly.
+ */
+ public void testEncode() {
+ String toEncode = "Man is distinguished, not only by his
reason, but by this singular " +
+ "passion from other animals, which is a lust of
the mind, that by a perseverance " +
+ "of delight in the continued and indefatigable
generation of knowledge, exceeds " +
+ "the short vehemence of any carnal pleasure.";
+ String expectedResult =
"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ" +
+
"1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG"
+
+
"x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY"
+
+
"29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRz"
+
+
"IHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4";
+ byte[] aByteArrayToEncode = toEncode.getBytes();
+ assertEquals(Base64.encode(aByteArrayToEncode),expectedResult);
+ }
+
+ /**
+ * Test the decode(String) method
+ * against a well-known example
+ * (see http://en.wikipedia.org/wiki/Base_64 as reference)
+ * to verify if it decode an already encoded string correctly.
+ */
+ public void testDecode() {
+ String toDecode =
"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ" +
+
"1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG"
+
+
"x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY"
+
+
"29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRz"
+
+
"IHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=";
+ String expectedResult = "Man is distinguished, not only by his
reason, but by this singular " +
+ "passion from other animals, which is a lust of
the mind, that by a perseverance " +
+ "of delight in the continued and indefatigable
generation of knowledge, exceeds " +
+ "the short vehemence of any carnal pleasure.";
+ try {
+ String decodedString = new
String(Base64.decode(toDecode));
+ assertEquals(decodedString,expectedResult);
+ } catch (IllegalBase64Exception aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+
+ /**
+ * Test encode(byte[] in)
+ * and decode(String inStr) methods,
+ * to verify if they work correctly together.
+ * It compares the string before encoding
+ * and with the one after decoding.
+ */
+ public void testEncodeDecode() {
+ byte[] bytesDecoded;
+ byte[] bytesToEncode = new byte[5];
+
+ //byte upper bound
+ bytesToEncode[0] = 127;
+ bytesToEncode[1] = 64;
+ bytesToEncode[2] = 0;
+ bytesToEncode[3] = -64;
+ //byte lower bound
+ bytesToEncode[4] = -128;
+
+ String aBase64EncodedString = Base64.encode(bytesToEncode);
+
+ try {
+ bytesDecoded = Base64.decode(aBase64EncodedString);
+ assertTrue(Arrays.equals(bytesToEncode,bytesDecoded));
}
+ catch (IllegalBase64Exception aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+
+ /**
+ * Test the encode(String,boolean)
+ * method to verify if the padding
+ * character '=' is correctly placed.
+ */
+ public void testEncodePadding() {
+ byte[][] methodBytesArray = {
+ //three byte Array -> no padding char expected
+ {4,4,4},
+ //two byte Array -> one padding char expected
+ {4,4},
+ //one byte Array -> two padding-chars expected
+ {4}};
+ String encoded;
+
+ for (int i = 0; i<methodBytesArray.length; i++) {
+ encoded = Base64.encode(methodBytesArray[i],true);
+ if (i == 0)
+ //no occurrences expected
+ assertEquals(encoded.indexOf('='),-1);
+ else
+
assertEquals(encoded.indexOf('='),encoded.length()-i);
+ }
+ }
+
+ /**
+ * Test if the decode(String) method
+ * raise correctly an exception when
+ * providing a string with non-Base64
+ * characters.
+ */
+ public void testIllegalBaseCharacter() {
+// TODO: check many other possibile cases!
+ String illegalCharString = "abcd=fghilmn";
+ try {
+ Base64.decode(illegalCharString);
+ fail("Expected IllegalBase64Exception not thrown"); }
+ catch (IllegalBase64Exception exception) {
+ assertSame("illegal Base64
character",exception.getMessage()); }
+ }
+
+ /**
+ * Test if the decode(String) method
+ * raise correctly an exception when
+ * providing a string with a
+ * wrong Base64 length.
+ * (as we can consider not-padded strings too,
+ * the only wrong lengths are the ones
+ * where -> number MOD 4 = 1).
+ */
+ public void testIllegalBaseLength() {
+ //most interesting case
+ String illegalLengthString = "a";
+ try {
+ Base64.decode(illegalLengthString);
+ fail("Expected IllegalBase64Exception not thrown"); }
+ catch (IllegalBase64Exception exception) {
+ assertSame("illegal Base64
length",exception.getMessage()); }
+ }
+}
\ No newline at end of file
Deleted: branches/freenet-jfk/test/freenet/support/BitArrayTest.java
===================================================================
--- trunk/freenet/test/freenet/support/BitArrayTest.java 2007-08-18
19:36:17 UTC (rev 14796)
+++ branches/freenet-jfk/test/freenet/support/BitArrayTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -1,184 +0,0 @@
-/* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package freenet.support;
-
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.BitArray} class.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class BitArrayTest extends TestCase {
-
- private final int sampleBitsNumber = 10;
- private final int oneByteBits = 8;
-
- /**
- * Creates a BitArray with all values set to the
- * boolean argument
- * @param arraySize the size of the BitArray
- * @param value the value for each bit
- * @return the set BitArray
- */
- private BitArray createAllEqualsBitArray(int arraySize, boolean value) {
- BitArray methodBitArray = new BitArray(arraySize);
- //setting all bits true
- for (int i=0; i<methodBitArray.getSize();i++)
- methodBitArray.setBit(i,value);
- return methodBitArray;
- }
-
- /**
- * Creates a String of toRepeat String as long as needed
- * @param stringSize length requested
- * @param toRepeat String to repeat stringSize times
- * @return the String of toRepeat
- */
- private String createAllOneString(int stringSize, String toRepeat) {
- StringBuffer methodStringBuffer = new StringBuffer();
- for (int i=0;i<stringSize;i++)
- methodStringBuffer.append(toRepeat);
- return methodStringBuffer.toString();
- }
-
- /**
- * Tests BitArray(int) constructor
- * and verifies if the instance is
- * well created (all values must be
- * readables and false, and the length
- * has to be correct)
- */
- public void testBitArray_int() {
- BitArray methodBitArray = new BitArray(sampleBitsNumber);
- for(int i=0;i<sampleBitsNumber;i++)
- assertFalse(methodBitArray.bitAt(i));
- assertEquals(methodBitArray.getSize(),sampleBitsNumber);
- }
-
- /**
- * Tests toString() method
- * creating BitArrays with same value bits.
- */
- public void testToStringAllEquals() {
- BitArray methodBitArray =
createAllEqualsBitArray(sampleBitsNumber,true);
- String expectedString =
createAllOneString(sampleBitsNumber,"1");
- assertEquals(methodBitArray.toString(),expectedString);
- methodBitArray =
createAllEqualsBitArray(sampleBitsNumber,false);
- expectedString = createAllOneString(sampleBitsNumber,"0");
- assertEquals(methodBitArray.toString(),expectedString);
- }
-
- /**
- * Tests toString() method
- * with a BitArray with size zero.
- */
- public void testToStringEmpty() {
- BitArray methodBitArray = new BitArray(0);
- assertEquals(methodBitArray.toString().length(),0);
- }
-
- /**
- * Tests setBit(int,boolean) method
- * trying to set a bit out of bounds
- */
- public void testSetBit_OutOfBounds() {
- BitArray methodBitArray = new BitArray(sampleBitsNumber);
- try {
- methodBitArray.setBit(sampleBitsNumber,true);
- //fail("Expected Exception Error Not Thrown!");
- }
- catch (ArrayIndexOutOfBoundsException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Tests setBit(int,boolean) method
- * using getAt(int) to verify if they are
- * consistent.
- */
- public void testSetAndGetBit() {
- BitArray methodBitArray = new BitArray(sampleBitsNumber);
- //setting true even bits
- for (int i=0; i<methodBitArray.getSize();i=i+2)
- methodBitArray.setBit(i,true);
- //checking even bits
- for (int i=0; i<methodBitArray.getSize();i=i+2)
- assertTrue(methodBitArray.bitAt(i));
- //checking odd bits
- for (int i=1; i<methodBitArray.getSize();i=i+2)
- assertFalse(methodBitArray.bitAt(i));
- }
-
- /**
- * Tests unsignedByteToInt(byte) method
- * trying it correctness for every possible (i.e. 256)
- * byte value
- */
- public void testUnsignedByteToInt() {
- byte sampleByte;
- for (int i =0; i<256; i++) {
- sampleByte = (byte)i;
- assertEquals(i,BitArray.unsignedByteToInt(sampleByte));
}
- }
-
- /**
- * Tests getSize() method
- */
- public void testGetSize() {
- BitArray methodBitArray = new BitArray(0);
- assertEquals(methodBitArray.getSize(),0);
- methodBitArray = createAllEqualsBitArray(sampleBitsNumber,true);
- assertEquals(methodBitArray.getSize(),sampleBitsNumber);
- }
-
- /**
- * Tests setAllOnes() method
- * comparing the result to
- * a BitArray with already all ones
- * set.
- */
- public void testSetAllOnes() {
- BitArray methodBitArray =
createAllEqualsBitArray(sampleBitsNumber,true);
- BitArray methodBitArrayToVerify = new
BitArray(sampleBitsNumber);
- methodBitArrayToVerify.setAllOnes();
- assertEquals(methodBitArray,methodBitArrayToVerify);
- }
-
- /**
- * Tests firstOne() method
- * far all possible first-one-position
- * in a BitArray with as many bits as in
- * a single byte
- */
- public void testFirstOne() {
- BitArray methodBitArray = new BitArray(oneByteBits);
- //only one "1"
- for(int i=0; i<oneByteBits; i++) {
- methodBitArray = new BitArray(oneByteBits);
- methodBitArray.setBit(i,true);
- assertEquals(methodBitArray.firstOne(),i);}
-
- methodBitArray.setAllOnes();
- //augmenting zeros
- for(int i=0; i<oneByteBits-1; i++) {
- methodBitArray.setBit(i,false);
- assertEquals(methodBitArray.firstOne(),i+1);}
- //all zeros
- methodBitArray.setBit(oneByteBits-1,false);
- assertEquals(methodBitArray.firstOne(),-1);
- }
-
-}
Copied: branches/freenet-jfk/test/freenet/support/BitArrayTest.java (from rev
14796, trunk/freenet/test/freenet/support/BitArrayTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/BitArrayTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/BitArrayTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,184 @@
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.BitArray} class.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class BitArrayTest extends TestCase {
+
+ private final int sampleBitsNumber = 10;
+ private final int oneByteBits = 8;
+
+ /**
+ * Creates a BitArray with all values set to the
+ * boolean argument
+ * @param arraySize the size of the BitArray
+ * @param value the value for each bit
+ * @return the set BitArray
+ */
+ private BitArray createAllEqualsBitArray(int arraySize, boolean value) {
+ BitArray methodBitArray = new BitArray(arraySize);
+ //setting all bits true
+ for (int i=0; i<methodBitArray.getSize();i++)
+ methodBitArray.setBit(i,value);
+ return methodBitArray;
+ }
+
+ /**
+ * Creates a String of toRepeat String as long as needed
+ * @param stringSize length requested
+ * @param toRepeat String to repeat stringSize times
+ * @return the String of toRepeat
+ */
+ private String createAllOneString(int stringSize, String toRepeat) {
+ StringBuffer methodStringBuffer = new StringBuffer();
+ for (int i=0;i<stringSize;i++)
+ methodStringBuffer.append(toRepeat);
+ return methodStringBuffer.toString();
+ }
+
+ /**
+ * Tests BitArray(int) constructor
+ * and verifies if the instance is
+ * well created (all values must be
+ * readables and false, and the length
+ * has to be correct)
+ */
+ public void testBitArray_int() {
+ BitArray methodBitArray = new BitArray(sampleBitsNumber);
+ for(int i=0;i<sampleBitsNumber;i++)
+ assertFalse(methodBitArray.bitAt(i));
+ assertEquals(methodBitArray.getSize(),sampleBitsNumber);
+ }
+
+ /**
+ * Tests toString() method
+ * creating BitArrays with same value bits.
+ */
+ public void testToStringAllEquals() {
+ BitArray methodBitArray =
createAllEqualsBitArray(sampleBitsNumber,true);
+ String expectedString =
createAllOneString(sampleBitsNumber,"1");
+ assertEquals(methodBitArray.toString(),expectedString);
+ methodBitArray =
createAllEqualsBitArray(sampleBitsNumber,false);
+ expectedString = createAllOneString(sampleBitsNumber,"0");
+ assertEquals(methodBitArray.toString(),expectedString);
+ }
+
+ /**
+ * Tests toString() method
+ * with a BitArray with size zero.
+ */
+ public void testToStringEmpty() {
+ BitArray methodBitArray = new BitArray(0);
+ assertEquals(methodBitArray.toString().length(),0);
+ }
+
+ /**
+ * Tests setBit(int,boolean) method
+ * trying to set a bit out of bounds
+ */
+ public void testSetBit_OutOfBounds() {
+ BitArray methodBitArray = new BitArray(sampleBitsNumber);
+ try {
+ methodBitArray.setBit(sampleBitsNumber,true);
+ //fail("Expected Exception Error Not Thrown!");
+ }
+ catch (ArrayIndexOutOfBoundsException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Tests setBit(int,boolean) method
+ * using getAt(int) to verify if they are
+ * consistent.
+ */
+ public void testSetAndGetBit() {
+ BitArray methodBitArray = new BitArray(sampleBitsNumber);
+ //setting true even bits
+ for (int i=0; i<methodBitArray.getSize();i=i+2)
+ methodBitArray.setBit(i,true);
+ //checking even bits
+ for (int i=0; i<methodBitArray.getSize();i=i+2)
+ assertTrue(methodBitArray.bitAt(i));
+ //checking odd bits
+ for (int i=1; i<methodBitArray.getSize();i=i+2)
+ assertFalse(methodBitArray.bitAt(i));
+ }
+
+ /**
+ * Tests unsignedByteToInt(byte) method
+ * trying it correctness for every possible (i.e. 256)
+ * byte value
+ */
+ public void testUnsignedByteToInt() {
+ byte sampleByte;
+ for (int i =0; i<256; i++) {
+ sampleByte = (byte)i;
+ assertEquals(i,BitArray.unsignedByteToInt(sampleByte));
}
+ }
+
+ /**
+ * Tests getSize() method
+ */
+ public void testGetSize() {
+ BitArray methodBitArray = new BitArray(0);
+ assertEquals(methodBitArray.getSize(),0);
+ methodBitArray = createAllEqualsBitArray(sampleBitsNumber,true);
+ assertEquals(methodBitArray.getSize(),sampleBitsNumber);
+ }
+
+ /**
+ * Tests setAllOnes() method
+ * comparing the result to
+ * a BitArray with already all ones
+ * set.
+ */
+ public void testSetAllOnes() {
+ BitArray methodBitArray =
createAllEqualsBitArray(sampleBitsNumber,true);
+ BitArray methodBitArrayToVerify = new
BitArray(sampleBitsNumber);
+ methodBitArrayToVerify.setAllOnes();
+ assertEquals(methodBitArray,methodBitArrayToVerify);
+ }
+
+ /**
+ * Tests firstOne() method
+ * far all possible first-one-position
+ * in a BitArray with as many bits as in
+ * a single byte
+ */
+ public void testFirstOne() {
+ BitArray methodBitArray = new BitArray(oneByteBits);
+ //only one "1"
+ for(int i=0; i<oneByteBits; i++) {
+ methodBitArray = new BitArray(oneByteBits);
+ methodBitArray.setBit(i,true);
+ assertEquals(methodBitArray.firstOne(),i);}
+
+ methodBitArray.setAllOnes();
+ //augmenting zeros
+ for(int i=0; i<oneByteBits-1; i++) {
+ methodBitArray.setBit(i,false);
+ assertEquals(methodBitArray.firstOne(),i+1);}
+ //all zeros
+ methodBitArray.setBit(oneByteBits-1,false);
+ assertEquals(methodBitArray.firstOne(),-1);
+ }
+
+}
Deleted: branches/freenet-jfk/test/freenet/support/HTMLEncoderDecoderTest.java
===================================================================
--- trunk/freenet/test/freenet/support/HTMLEncoderDecoderTest.java
2007-08-18 19:36:17 UTC (rev 14796)
+++ branches/freenet-jfk/test/freenet/support/HTMLEncoderDecoderTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,129 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package freenet.support;
-import freenet.utils.UTFUtil;
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.HTMLEncoder} and
- * {@link freenet.support.HTMLDecoder} classes.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class HTMLEncoderDecoderTest extends TestCase {
-
- private static final char WHITESPACE = '\u0020';
- private static final char TAB = '\t';
- private static final char UNIX_NEWLINE = '\n';
- private static final char MAC_NEWLINE = '\r';
- private static final char CONTROL = '\u000c';
- private static final char ZEROWIDTHSPACE = '\u200b';
-
- /**
- * Tests decode(String) method
- * trying to decode entity by entity
- */
- public void testDecodeSingleEntities() {
- for (int i =0; i<UTFUtil.HTML_ENTITIES_UTF.length; i++)
-
assertEquals(HTMLDecoder.decode(UTFUtil.HTML_ENTITIES_UTF[i][1]),UTFUtil.HTML_ENTITIES_UTF[i][0]);
- }
-
- /**
- * Tests decode(String) method
- * trying to decode a long String
- * with all possible entity appended
- */
- public void testDecodeAppendedEntities() {
- StringBuffer toDecode = new StringBuffer();
- StringBuffer expected = new StringBuffer();
- for (int i =0; i<UTFUtil.HTML_ENTITIES_UTF.length; i++) {
- toDecode.append(UTFUtil.HTML_ENTITIES_UTF[i][1]);
- expected.append(UTFUtil.HTML_ENTITIES_UTF[i][0]);
- }
-
assertEquals(HTMLDecoder.decode(toDecode.toString()),expected.toString());
- }
-
- /**
- * Tests decode(String) method
- * trying to decode incomplete entities.
- * The incomplete entity must remain
- * the same as before encoding
- */
- public void testDecodeIncomplete() {
- //without ending semicolon
- assertEquals(HTMLDecoder.decode("&Phi"),"&Phi");
- //an Entity without a char,
- //which means a not existing Entity
- assertEquals(HTMLDecoder.decode("&Ph;"),"&Ph;");
- //without ash
- assertEquals(HTMLDecoder.decode("&1234;"),"&1234;");
- //without ampersand
- assertEquals(HTMLDecoder.decode("Phi;"),"Phi;");
- //emtpy String
- assertEquals(HTMLDecoder.decode(""),"");
- }
-
- /**
- * Tests compact(String) method
- * trying to compact String with
- * repeated whitespaces of every kind
- * (e.g. tabs,newline,space).
- */
- public void testCompactRepeated(){
- StringBuffer strBuffer[] = new StringBuffer[6];
- for (int i = 0; i < strBuffer.length; i++)
- strBuffer[i] = new StringBuffer();
-
- for (int i=0;i<100;i++) {
- //adding different "whitespaces"
- strBuffer[0].append(WHITESPACE);
- strBuffer[1].append(TAB);
- strBuffer[2].append(UNIX_NEWLINE);
- strBuffer[3].append(MAC_NEWLINE);
- strBuffer[4].append(CONTROL);
- strBuffer[5].append(ZEROWIDTHSPACE);
-
- for (int j = 0; j < strBuffer.length; j++)
- assertEquals(" ",
-
HTMLDecoder.compact(strBuffer[j].toString()));
- }
- }
-
- /**
- * Tests compact(String) method
- * with each kind of "whitespace"
- */
- public void testCompactMixed(){
- String toCompact = "\u0020"+"\t"+"\n"+"\r"+"\u200b"+"\u000c";
- assertEquals(HTMLDecoder.compact(toCompact)," ");
- }
-
- /**
- * Tests isWhiteSpace() method
- * against all possible HTML white space
- * type
- */
- public void testIsWhiteSpace() {
- assertTrue(HTMLDecoder.isWhitespace(WHITESPACE));
- assertTrue(HTMLDecoder.isWhitespace(TAB));
- assertTrue(HTMLDecoder.isWhitespace(UNIX_NEWLINE));
- assertTrue(HTMLDecoder.isWhitespace(MAC_NEWLINE));
- assertTrue(HTMLDecoder.isWhitespace(CONTROL));
- assertTrue(HTMLDecoder.isWhitespace(ZEROWIDTHSPACE));
- }
-
-
-}
Copied: branches/freenet-jfk/test/freenet/support/HTMLEncoderDecoderTest.java
(from rev 14796, trunk/freenet/test/freenet/support/HTMLEncoderDecoderTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/HTMLEncoderDecoderTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/HTMLEncoderDecoderTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,129 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+import freenet.utils.UTFUtil;
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.HTMLEncoder} and
+ * {@link freenet.support.HTMLDecoder} classes.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class HTMLEncoderDecoderTest extends TestCase {
+
+ private static final char WHITESPACE = '\u0020';
+ private static final char TAB = '\t';
+ private static final char UNIX_NEWLINE = '\n';
+ private static final char MAC_NEWLINE = '\r';
+ private static final char CONTROL = '\u000c';
+ private static final char ZEROWIDTHSPACE = '\u200b';
+
+ /**
+ * Tests decode(String) method
+ * trying to decode entity by entity
+ */
+ public void testDecodeSingleEntities() {
+ for (int i =0; i<UTFUtil.HTML_ENTITIES_UTF.length; i++)
+
assertEquals(HTMLDecoder.decode(UTFUtil.HTML_ENTITIES_UTF[i][1]),UTFUtil.HTML_ENTITIES_UTF[i][0]);
+ }
+
+ /**
+ * Tests decode(String) method
+ * trying to decode a long String
+ * with all possible entity appended
+ */
+ public void testDecodeAppendedEntities() {
+ StringBuffer toDecode = new StringBuffer();
+ StringBuffer expected = new StringBuffer();
+ for (int i =0; i<UTFUtil.HTML_ENTITIES_UTF.length; i++) {
+ toDecode.append(UTFUtil.HTML_ENTITIES_UTF[i][1]);
+ expected.append(UTFUtil.HTML_ENTITIES_UTF[i][0]);
+ }
+
assertEquals(HTMLDecoder.decode(toDecode.toString()),expected.toString());
+ }
+
+ /**
+ * Tests decode(String) method
+ * trying to decode incomplete entities.
+ * The incomplete entity must remain
+ * the same as before encoding
+ */
+ public void testDecodeIncomplete() {
+ //without ending semicolon
+ assertEquals(HTMLDecoder.decode("&Phi"),"&Phi");
+ //an Entity without a char,
+ //which means a not existing Entity
+ assertEquals(HTMLDecoder.decode("&Ph;"),"&Ph;");
+ //without ash
+ assertEquals(HTMLDecoder.decode("&1234;"),"&1234;");
+ //without ampersand
+ assertEquals(HTMLDecoder.decode("Phi;"),"Phi;");
+ //emtpy String
+ assertEquals(HTMLDecoder.decode(""),"");
+ }
+
+ /**
+ * Tests compact(String) method
+ * trying to compact String with
+ * repeated whitespaces of every kind
+ * (e.g. tabs,newline,space).
+ */
+ public void testCompactRepeated(){
+ StringBuffer strBuffer[] = new StringBuffer[6];
+ for (int i = 0; i < strBuffer.length; i++)
+ strBuffer[i] = new StringBuffer();
+
+ for (int i=0;i<100;i++) {
+ //adding different "whitespaces"
+ strBuffer[0].append(WHITESPACE);
+ strBuffer[1].append(TAB);
+ strBuffer[2].append(UNIX_NEWLINE);
+ strBuffer[3].append(MAC_NEWLINE);
+ strBuffer[4].append(CONTROL);
+ strBuffer[5].append(ZEROWIDTHSPACE);
+
+ for (int j = 0; j < strBuffer.length; j++)
+ assertEquals(" ",
+
HTMLDecoder.compact(strBuffer[j].toString()));
+ }
+ }
+
+ /**
+ * Tests compact(String) method
+ * with each kind of "whitespace"
+ */
+ public void testCompactMixed(){
+ String toCompact = "\u0020"+"\t"+"\n"+"\r"+"\u200b"+"\u000c";
+ assertEquals(HTMLDecoder.compact(toCompact)," ");
+ }
+
+ /**
+ * Tests isWhiteSpace() method
+ * against all possible HTML white space
+ * type
+ */
+ public void testIsWhiteSpace() {
+ assertTrue(HTMLDecoder.isWhitespace(WHITESPACE));
+ assertTrue(HTMLDecoder.isWhitespace(TAB));
+ assertTrue(HTMLDecoder.isWhitespace(UNIX_NEWLINE));
+ assertTrue(HTMLDecoder.isWhitespace(MAC_NEWLINE));
+ assertTrue(HTMLDecoder.isWhitespace(CONTROL));
+ assertTrue(HTMLDecoder.isWhitespace(ZEROWIDTHSPACE));
+ }
+
+
+}
Deleted: branches/freenet-jfk/test/freenet/support/HTMLNodeTest.java
===================================================================
--- trunk/freenet/test/freenet/support/HTMLNodeTest.java 2007-08-18
19:36:17 UTC (rev 14796)
+++ branches/freenet-jfk/test/freenet/support/HTMLNodeTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -1,309 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package freenet.support;
-
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.HTMLNode} class.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class HTMLNodeTest extends TestCase {
-
- private HTMLNode exampleNode;
-
- //example node name that includes a not ASCII char [greek alpha]
- private static final String SAMPLE_NODE_NAME = "s\u03b1mpleNode";
-
- //example node attribute that includes a not ASCII char [greek beta]
- private static final String SAMPLE_ATTRIBUTE_NAME =
"sampleAttri\u03b2uteName";
-
- //example node attribute value that includes a not ASCII char [greek
epsilon]
- private static final String SAMPLE_ATTRIBUTE_VALUE =
"sampleAttribut\u03b5Value";
-
- //example node content that includes a not ASCII char [greek omicron]
- private static final String SAMPLE_NODE_CONTENT =
"sampleNodeC\u03bfntent";
-
- protected void setUp() throws Exception {
- super.setUp();
- exampleNode = new HTMLNode(SAMPLE_NODE_NAME);
- }
-
- /**
- * Test HTMLNode(String,String,String,String) constructor
- * using non-ASCII chars
- */
- public void testNotAsciiHTMLNode_StringStringStringString() {
- HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME,
- SAMPLE_ATTRIBUTE_NAME,SAMPLE_ATTRIBUTE_VALUE,
- SAMPLE_NODE_CONTENT);
- assertFalse(exampleNode.children.contains(methodHTMLNode));
- exampleNode.addChild(methodHTMLNode);
- assertTrue(exampleNode.children.contains(methodHTMLNode));
- }
-
- /**
- * Tests addAttribute(String,String) method
- * adding the same attribute many times
- * and verifying it keeps only one
- * reference to it.
- */
- public void testSameAttributeManyTimes() {
- int times = 100;
- String methodAttributeName = "exampleAttributeName";
- String methodAttributeValue = "exampleAttributeValue";
- for (int i = 0; i < times; i++) {
-
exampleNode.addAttribute(methodAttributeName,methodAttributeValue);
- assertEquals(exampleNode.getAttributes().size(),1);
- }
- }
-
- /**
- * Tests addChild(HTMLNode) method
- * adding the Node itself as its
- * child. The method should rise an exception
- */
- public void testAddChildUsingTheNodeItselfAsChild() {
- try {
- exampleNode.addChild(exampleNode);
- fail("Expected Exception Error Not Thrown!"); }
- catch (IllegalArgumentException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Tests addChildren(HTMLNode[]) method
- * adding the Node itself as its
- * child. The method should rise an exception
- */
- public void testAddChildrenUsingTheNodeItselfAsChild() {
- HTMLNode[] methodHTMLNodesArray = {new
HTMLNode(SAMPLE_NODE_NAME),
-
exampleNode,
-
new HTMLNode(SAMPLE_NODE_NAME+"1")};
- try {
- exampleNode.addChildren(methodHTMLNodesArray);
- fail("Expected Exception Error Not Thrown!"); }
- catch (IllegalArgumentException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Tests addChild(String) method
- * using the same name every time
- * and verifying that a real new
- * HTML is always added.
- */
- public void testAddChildSameName() {
- int times = 100;
- for (int i = 1; i<=times; i++) {
- exampleNode.addChild(SAMPLE_NODE_NAME);
- assertEquals(exampleNode.children.size(),i);
- }
- }
-
- /**
- * Tests addChild(HTMLNode) method
- * verifying the behavior when adding
- * the same HTMLNode instance two times.
- * It should raise an IllegalArgument exception.
- */
- public void testAddChildSameObject() {
- HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME);
- exampleNode.addChild(methodHTMLNode);
- try {
- exampleNode.addChild(methodHTMLNode);
- fail("Expected Exception Error Not Thrown!"); }
- catch (IllegalArgumentException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Tests addChildren(HTMLNode[]) method
- * verifying the behavior when adding
- * the same HTMLNode instance two times.
- */
- public void testAddChildrenSameObject() {
- HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME);
- HTMLNode[] methodHTMLNodesArray = {methodHTMLNode,
-
methodHTMLNode};
- try {
- exampleNode.addChildren(methodHTMLNodesArray);
- fail("Expected Exception Error Not Thrown!"); }
- catch (IllegalArgumentException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Tests getContent() method using
- * common sample HTMLNode, and "#"
- * "%" named nodes
- */
- public void testGetContent() {
- HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME);
- assertNull(methodHTMLNode.getContent());
-
- methodHTMLNode = new
HTMLNode(SAMPLE_NODE_NAME,SAMPLE_NODE_CONTENT);
- //since the HTMLNode name is not "#", or "%",
- //the content will be a new child with the "#" name
- assertEquals(SAMPLE_NODE_CONTENT,
-
((HTMLNode)(methodHTMLNode.children.get(0))).getContent());
- assertNull(methodHTMLNode.getContent());
-
- methodHTMLNode = new HTMLNode("#",SAMPLE_NODE_CONTENT);
- assertEquals(SAMPLE_NODE_CONTENT,
- methodHTMLNode.getContent());
- methodHTMLNode = new HTMLNode("%",SAMPLE_NODE_CONTENT);
- assertEquals(SAMPLE_NODE_CONTENT,
- methodHTMLNode.getContent());
- }
-
- /**
- * Fetches the first line of a String
- * @param aString the String to consider
- * @return the first line of the String
- */
- private String readFirstLine(String aString) {
- int newLineIndex = aString.indexOf("\n");
- if ( newLineIndex == -1)
- return aString;
- return aString.substring(0,newLineIndex);
- }
-
- /**
- * Tests generate() method with a
- * HTMLNode with only the name.
- * The resulting string should be in the form:
- * <node_name />
- */
- public void testGenerate_fromHTMLNode_String() {
- HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME);
- assertEquals(("<"+SAMPLE_NODE_NAME+" />").toLowerCase(),
- methodHTMLNode.generate());
- }
-
- /**
- * Tests generate() method with a
- * HTMLNode with the name and content.
- * The resulting string should be in the form:
- * <node_name>Node_Content</node_name>
- */
- public void testGenerate_fromHTMLNode_StringString() {
- HTMLNode methodHTMLNode = new
HTMLNode(SAMPLE_NODE_NAME,SAMPLE_NODE_CONTENT);
- assertEquals(("<"+SAMPLE_NODE_NAME+">").toLowerCase() +
- SAMPLE_NODE_CONTENT +
-
("</"+SAMPLE_NODE_NAME+">").toLowerCase(),
- methodHTMLNode.generate());
- }
-
- /**
- * Tests generate() method with a
- * HTMLNode with the name, an attribute and its value.
- * The resulting string should be in the form:
- * <node_name Attribute_Name="Attribute_Value" />
- */
- public void testGenerate_fromHTMLNode_StringStringString() {
- HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME,
- SAMPLE_ATTRIBUTE_NAME,SAMPLE_ATTRIBUTE_VALUE);
- assertEquals(("<"+SAMPLE_NODE_NAME+" ").toLowerCase() +
- SAMPLE_ATTRIBUTE_NAME + "=" +
- "\""+SAMPLE_ATTRIBUTE_VALUE+"\""+
- " />",
- methodHTMLNode.generate());
- }
-
- /**
- * Tests generate() method with a
- * HTMLNode with the name, an attribute and its value.
- * The resulting string should be in the form:
- * <node_name Attribute_Name="Attribute_Value">Node_Content</node_name>
- */
- public void testGenerate_fromHTMLNode_StringStringStringString() {
- HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME,
- SAMPLE_ATTRIBUTE_NAME,SAMPLE_ATTRIBUTE_VALUE,
- SAMPLE_NODE_CONTENT);
- assertEquals(generateFullNodeOutput(SAMPLE_NODE_NAME,
- SAMPLE_ATTRIBUTE_NAME, SAMPLE_ATTRIBUTE_VALUE,
- SAMPLE_NODE_CONTENT),
- methodHTMLNode.generate());
- }
-
- /**
- * Generates the correct output for the HTMLNode.generate() method
- * when called from a single node having the specified parameters
- * @param aName the HTMLNode name
- * @param aAttributeName the HTMLNode attribute name
- * @param aAttributeValue the HTMLNode attribute value
- * @param aContent the HTMLNode content
- * @return the correct output expected by HTMLNode.generate() method
- */
- private String generateFullNodeOutput(String aName, String
aAttributeName, String aAttributeValue, String aContent) {
- return ("<"+aName+" ").toLowerCase() +
- aAttributeName + "=" +
- "\""+aAttributeValue+"\">" +
- aContent +
- ("</"+aName+">").toLowerCase();
- }
-
- /**
- * Tests generate() method with a
- * HTMLNode that has a child.
- * <node_name Attribute_Name="Attribute_Value">Node_Content
- * <child_node_name
child_Attribute_Name="child_Attribute_Value">child_Node_Content</child_node_name>
- * </node_name>
- */
- public void testGenerate_HTMLNode_withChild() {
- HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME,
- SAMPLE_ATTRIBUTE_NAME,SAMPLE_ATTRIBUTE_VALUE,
- SAMPLE_NODE_CONTENT);
- HTMLNode methodHTMLNodeChild = new HTMLNode(SAMPLE_NODE_NAME,
- SAMPLE_ATTRIBUTE_NAME,SAMPLE_ATTRIBUTE_VALUE,
- SAMPLE_NODE_CONTENT);
-
- methodHTMLNode.addChild(methodHTMLNodeChild);
-
- assertEquals(("<"+SAMPLE_NODE_NAME+" ").toLowerCase() +
- SAMPLE_ATTRIBUTE_NAME + "=" +
- "\""+SAMPLE_ATTRIBUTE_VALUE+"\">" +
- SAMPLE_NODE_CONTENT +
-
- //child
- generateFullNodeOutput(SAMPLE_NODE_NAME,
- SAMPLE_ATTRIBUTE_NAME,
SAMPLE_ATTRIBUTE_VALUE,
- SAMPLE_NODE_CONTENT) +
-
- ("</"+SAMPLE_NODE_NAME+">").toLowerCase(),
- methodHTMLNode.generate());
- }
-
- /**
- * Tests HTMLDoctype.generate() method
- * comparing the result with the expected
- * String. It is useful for regression tests.
- */
- public void testHTMLDoctype_generate() {
- String sampleDocType = "html";
- String sampleSystemUri = "-//W3C//DTD XHTML 1.1//EN";
- HTMLNode methodHTMLNodeDoc = new
HTMLNode.HTMLDoctype(sampleDocType,sampleSystemUri);
- methodHTMLNodeDoc.addChild(SAMPLE_NODE_NAME);
- String generatedString = methodHTMLNodeDoc.generate();
- //consider only the HTMLDocType generated text
- assertEquals("<!DOCTYPE "+sampleDocType+" PUBLIC
\""+sampleSystemUri+"\">",
- readFirstLine(generatedString));
-
- }
-
-}
Copied: branches/freenet-jfk/test/freenet/support/HTMLNodeTest.java (from rev
14796, trunk/freenet/test/freenet/support/HTMLNodeTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/HTMLNodeTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/HTMLNodeTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,309 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.HTMLNode} class.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class HTMLNodeTest extends TestCase {
+
+ private HTMLNode exampleNode;
+
+ //example node name that includes a not ASCII char [greek alpha]
+ private static final String SAMPLE_NODE_NAME = "s\u03b1mpleNode";
+
+ //example node attribute that includes a not ASCII char [greek beta]
+ private static final String SAMPLE_ATTRIBUTE_NAME =
"sampleAttri\u03b2uteName";
+
+ //example node attribute value that includes a not ASCII char [greek
epsilon]
+ private static final String SAMPLE_ATTRIBUTE_VALUE =
"sampleAttribut\u03b5Value";
+
+ //example node content that includes a not ASCII char [greek omicron]
+ private static final String SAMPLE_NODE_CONTENT =
"sampleNodeC\u03bfntent";
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ exampleNode = new HTMLNode(SAMPLE_NODE_NAME);
+ }
+
+ /**
+ * Test HTMLNode(String,String,String,String) constructor
+ * using non-ASCII chars
+ */
+ public void testNotAsciiHTMLNode_StringStringStringString() {
+ HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME,
+ SAMPLE_ATTRIBUTE_NAME,SAMPLE_ATTRIBUTE_VALUE,
+ SAMPLE_NODE_CONTENT);
+ assertFalse(exampleNode.children.contains(methodHTMLNode));
+ exampleNode.addChild(methodHTMLNode);
+ assertTrue(exampleNode.children.contains(methodHTMLNode));
+ }
+
+ /**
+ * Tests addAttribute(String,String) method
+ * adding the same attribute many times
+ * and verifying it keeps only one
+ * reference to it.
+ */
+ public void testSameAttributeManyTimes() {
+ int times = 100;
+ String methodAttributeName = "exampleAttributeName";
+ String methodAttributeValue = "exampleAttributeValue";
+ for (int i = 0; i < times; i++) {
+
exampleNode.addAttribute(methodAttributeName,methodAttributeValue);
+ assertEquals(exampleNode.getAttributes().size(),1);
+ }
+ }
+
+ /**
+ * Tests addChild(HTMLNode) method
+ * adding the Node itself as its
+ * child. The method should rise an exception
+ */
+ public void testAddChildUsingTheNodeItselfAsChild() {
+ try {
+ exampleNode.addChild(exampleNode);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (IllegalArgumentException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Tests addChildren(HTMLNode[]) method
+ * adding the Node itself as its
+ * child. The method should rise an exception
+ */
+ public void testAddChildrenUsingTheNodeItselfAsChild() {
+ HTMLNode[] methodHTMLNodesArray = {new
HTMLNode(SAMPLE_NODE_NAME),
+
exampleNode,
+
new HTMLNode(SAMPLE_NODE_NAME+"1")};
+ try {
+ exampleNode.addChildren(methodHTMLNodesArray);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (IllegalArgumentException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Tests addChild(String) method
+ * using the same name every time
+ * and verifying that a real new
+ * HTML is always added.
+ */
+ public void testAddChildSameName() {
+ int times = 100;
+ for (int i = 1; i<=times; i++) {
+ exampleNode.addChild(SAMPLE_NODE_NAME);
+ assertEquals(exampleNode.children.size(),i);
+ }
+ }
+
+ /**
+ * Tests addChild(HTMLNode) method
+ * verifying the behavior when adding
+ * the same HTMLNode instance two times.
+ * It should raise an IllegalArgument exception.
+ */
+ public void testAddChildSameObject() {
+ HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME);
+ exampleNode.addChild(methodHTMLNode);
+ try {
+ exampleNode.addChild(methodHTMLNode);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (IllegalArgumentException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Tests addChildren(HTMLNode[]) method
+ * verifying the behavior when adding
+ * the same HTMLNode instance two times.
+ */
+ public void testAddChildrenSameObject() {
+ HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME);
+ HTMLNode[] methodHTMLNodesArray = {methodHTMLNode,
+
methodHTMLNode};
+ try {
+ exampleNode.addChildren(methodHTMLNodesArray);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (IllegalArgumentException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Tests getContent() method using
+ * common sample HTMLNode, and "#"
+ * "%" named nodes
+ */
+ public void testGetContent() {
+ HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME);
+ assertNull(methodHTMLNode.getContent());
+
+ methodHTMLNode = new
HTMLNode(SAMPLE_NODE_NAME,SAMPLE_NODE_CONTENT);
+ //since the HTMLNode name is not "#", or "%",
+ //the content will be a new child with the "#" name
+ assertEquals(SAMPLE_NODE_CONTENT,
+
((HTMLNode)(methodHTMLNode.children.get(0))).getContent());
+ assertNull(methodHTMLNode.getContent());
+
+ methodHTMLNode = new HTMLNode("#",SAMPLE_NODE_CONTENT);
+ assertEquals(SAMPLE_NODE_CONTENT,
+ methodHTMLNode.getContent());
+ methodHTMLNode = new HTMLNode("%",SAMPLE_NODE_CONTENT);
+ assertEquals(SAMPLE_NODE_CONTENT,
+ methodHTMLNode.getContent());
+ }
+
+ /**
+ * Fetches the first line of a String
+ * @param aString the String to consider
+ * @return the first line of the String
+ */
+ private String readFirstLine(String aString) {
+ int newLineIndex = aString.indexOf("\n");
+ if ( newLineIndex == -1)
+ return aString;
+ return aString.substring(0,newLineIndex);
+ }
+
+ /**
+ * Tests generate() method with a
+ * HTMLNode with only the name.
+ * The resulting string should be in the form:
+ * <node_name />
+ */
+ public void testGenerate_fromHTMLNode_String() {
+ HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME);
+ assertEquals(("<"+SAMPLE_NODE_NAME+" />").toLowerCase(),
+ methodHTMLNode.generate());
+ }
+
+ /**
+ * Tests generate() method with a
+ * HTMLNode with the name and content.
+ * The resulting string should be in the form:
+ * <node_name>Node_Content</node_name>
+ */
+ public void testGenerate_fromHTMLNode_StringString() {
+ HTMLNode methodHTMLNode = new
HTMLNode(SAMPLE_NODE_NAME,SAMPLE_NODE_CONTENT);
+ assertEquals(("<"+SAMPLE_NODE_NAME+">").toLowerCase() +
+ SAMPLE_NODE_CONTENT +
+
("</"+SAMPLE_NODE_NAME+">").toLowerCase(),
+ methodHTMLNode.generate());
+ }
+
+ /**
+ * Tests generate() method with a
+ * HTMLNode with the name, an attribute and its value.
+ * The resulting string should be in the form:
+ * <node_name Attribute_Name="Attribute_Value" />
+ */
+ public void testGenerate_fromHTMLNode_StringStringString() {
+ HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME,
+ SAMPLE_ATTRIBUTE_NAME,SAMPLE_ATTRIBUTE_VALUE);
+ assertEquals(("<"+SAMPLE_NODE_NAME+" ").toLowerCase() +
+ SAMPLE_ATTRIBUTE_NAME + "=" +
+ "\""+SAMPLE_ATTRIBUTE_VALUE+"\""+
+ " />",
+ methodHTMLNode.generate());
+ }
+
+ /**
+ * Tests generate() method with a
+ * HTMLNode with the name, an attribute and its value.
+ * The resulting string should be in the form:
+ * <node_name Attribute_Name="Attribute_Value">Node_Content</node_name>
+ */
+ public void testGenerate_fromHTMLNode_StringStringStringString() {
+ HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME,
+ SAMPLE_ATTRIBUTE_NAME,SAMPLE_ATTRIBUTE_VALUE,
+ SAMPLE_NODE_CONTENT);
+ assertEquals(generateFullNodeOutput(SAMPLE_NODE_NAME,
+ SAMPLE_ATTRIBUTE_NAME, SAMPLE_ATTRIBUTE_VALUE,
+ SAMPLE_NODE_CONTENT),
+ methodHTMLNode.generate());
+ }
+
+ /**
+ * Generates the correct output for the HTMLNode.generate() method
+ * when called from a single node having the specified parameters
+ * @param aName the HTMLNode name
+ * @param aAttributeName the HTMLNode attribute name
+ * @param aAttributeValue the HTMLNode attribute value
+ * @param aContent the HTMLNode content
+ * @return the correct output expected by HTMLNode.generate() method
+ */
+ private String generateFullNodeOutput(String aName, String
aAttributeName, String aAttributeValue, String aContent) {
+ return ("<"+aName+" ").toLowerCase() +
+ aAttributeName + "=" +
+ "\""+aAttributeValue+"\">" +
+ aContent +
+ ("</"+aName+">").toLowerCase();
+ }
+
+ /**
+ * Tests generate() method with a
+ * HTMLNode that has a child.
+ * <node_name Attribute_Name="Attribute_Value">Node_Content
+ * <child_node_name
child_Attribute_Name="child_Attribute_Value">child_Node_Content</child_node_name>
+ * </node_name>
+ */
+ public void testGenerate_HTMLNode_withChild() {
+ HTMLNode methodHTMLNode = new HTMLNode(SAMPLE_NODE_NAME,
+ SAMPLE_ATTRIBUTE_NAME,SAMPLE_ATTRIBUTE_VALUE,
+ SAMPLE_NODE_CONTENT);
+ HTMLNode methodHTMLNodeChild = new HTMLNode(SAMPLE_NODE_NAME,
+ SAMPLE_ATTRIBUTE_NAME,SAMPLE_ATTRIBUTE_VALUE,
+ SAMPLE_NODE_CONTENT);
+
+ methodHTMLNode.addChild(methodHTMLNodeChild);
+
+ assertEquals(("<"+SAMPLE_NODE_NAME+" ").toLowerCase() +
+ SAMPLE_ATTRIBUTE_NAME + "=" +
+ "\""+SAMPLE_ATTRIBUTE_VALUE+"\">" +
+ SAMPLE_NODE_CONTENT +
+
+ //child
+ generateFullNodeOutput(SAMPLE_NODE_NAME,
+ SAMPLE_ATTRIBUTE_NAME,
SAMPLE_ATTRIBUTE_VALUE,
+ SAMPLE_NODE_CONTENT) +
+
+ ("</"+SAMPLE_NODE_NAME+">").toLowerCase(),
+ methodHTMLNode.generate());
+ }
+
+ /**
+ * Tests HTMLDoctype.generate() method
+ * comparing the result with the expected
+ * String. It is useful for regression tests.
+ */
+ public void testHTMLDoctype_generate() {
+ String sampleDocType = "html";
+ String sampleSystemUri = "-//W3C//DTD XHTML 1.1//EN";
+ HTMLNode methodHTMLNodeDoc = new
HTMLNode.HTMLDoctype(sampleDocType,sampleSystemUri);
+ methodHTMLNodeDoc.addChild(SAMPLE_NODE_NAME);
+ String generatedString = methodHTMLNodeDoc.generate();
+ //consider only the HTMLDocType generated text
+ assertEquals("<!DOCTYPE "+sampleDocType+" PUBLIC
\""+sampleSystemUri+"\">",
+ readFirstLine(generatedString));
+
+ }
+
+}
Deleted: branches/freenet-jfk/test/freenet/support/HexUtilTest.java
===================================================================
--- trunk/freenet/test/freenet/support/HexUtilTest.java 2007-08-18 19:36:17 UTC
(rev 14796)
+++ branches/freenet-jfk/test/freenet/support/HexUtilTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -1,371 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-package freenet.support;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.BitSet;
-
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.HexUtil} class.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class HexUtilTest extends TestCase {
-
- /**
- * Test the bytesToHex(byte[]) method
- * against every possible single byte value.
- */
- public void testBytesToHex_byte() {
- byte[] methodByteArray = new byte[1];
- String expectedResult;
- for (int i = 255; i >= 0; i--) {
- methodByteArray[0] = (byte)i;
- /* Integer.toHexString works with int so it doesn't
return always a two digit hex.
- For this reason we need the next "switch case". */
- expectedResult = (i <= 15?
- "0" + (Integer.toHexString(i)):
- (Integer.toHexString(i)));
-
assertEquals(expectedResult,HexUtil.bytesToHex(methodByteArray));}
- }
-
- /**
- * Test the hexToBytes(String) method
- * against the hex representation of
- * every possible single byte.
- * The starting offset is always 0.
- */
- public void testHexToBytes_String() {
- byte[] expectedByteArray = new byte[1];
- String methodHexString;
- for (int i = 255; i >= 0; i--) {
- expectedByteArray[0] = (byte)i;
- /* Integer.toHexString works with int so it doesn't
return always a two digit hex.
- For this reason we need the next "switch case". */
- methodHexString = (i <= 15?
- "0" + (Integer.toHexString(i)):
- (Integer.toHexString(i)));
-
assertTrue(Arrays.equals(expectedByteArray,HexUtil.hexToBytes(methodHexString)));}
- }
-
- /**
- * Test the hexToBytes(String,int) method
- * against the hex representation of
- * every possible single byte.
- * The starting offset is always 0.
- */
- public void testHexToBytes_StringInt() {
- byte[] expectedByteArray = new byte[1];
- String methodHexString;
- for (int i = 255; i >= 0; i--) {
- expectedByteArray[0] = (byte)i;
- /* Integer.toHexString works with int so it doesn't
return always a two digit hex.
- For this reason we need the next "switch case". */
- methodHexString = (i <= 15?
- "0" + (Integer.toHexString(i)):
- (Integer.toHexString(i)));
-
assertTrue(Arrays.equals(expectedByteArray,HexUtil.hexToBytes(methodHexString,0)));}
- }
-
- /**
- * Test the hexToBytes(String,byte[],int) method
- * against the hex representation of
- * every possible single byte.
- */
- public void testHexToBytes_StringByteInt() {
- byte[] expectedByteArray = new byte[1];
- byte[] outputArray = new byte[1];
- String methodHexString;
- for (int i = 255; i >= 0; i--) {
- expectedByteArray[0] = (byte)i;
- /* Integer.toHexString works with int so it doesn't
return always a two digit hex.
- For this reason we need the next "switch case". */
- methodHexString = (i <= 15?
- "0" + (Integer.toHexString(i)):
- (Integer.toHexString(i)));
- HexUtil.hexToBytes(methodHexString,outputArray,0);
-
assertTrue(Arrays.equals(expectedByteArray,outputArray));}
- }
-
- /**
- * Test the bitsToByte(BitSet,int) method
- * against the bit representation of
- * every possible single byte.
- */
- public void testBitsToBytes_BitSetInt() {
- byte[] expectedByteArray = new byte[1];
- byte[] outputArray = new byte[1];
- BitSet methodBitSet = new BitSet(8);
- for (int i = 0; i < 256; i++) {
- outputArray = HexUtil.bitsToBytes(methodBitSet, 8);
- expectedByteArray[0] = (byte)i;
-
assertTrue(Arrays.equals(expectedByteArray,outputArray));
- addOne(methodBitSet);
- }
- }
-
- /**
- * It adds 1 to a given BitSet
- * @param aBitSet
- */
- private void addOne(BitSet aBitSet) {
- int bitSetIndex = 0;
- while (aBitSet.get(bitSetIndex)==true) {
- aBitSet.flip(bitSetIndex);
- bitSetIndex++;
- }
- aBitSet.flip(bitSetIndex);
- }
-
- /**
- * Test countBytesForBits(int) method
- * against all possible values until 256 bytes
- */
- public void testCountBytesForBits_int() {
- //border case
- assertEquals(HexUtil.countBytesForBits(0),0);
- for (int expectedBytesCount = 1; expectedBytesCount < 256;
expectedBytesCount++)
- for (int bits = (expectedBytesCount-1)*8+1; bits <=
(expectedBytesCount)*8; bits++)
-
assertEquals(HexUtil.countBytesForBits(bits),expectedBytesCount);
- }
-
- /**
- * Test bytesToBits(byte[],BitSet,int) method
- * against all possible single byte value.
- * It uses HexUtil.bitsToBytes() method for the check,
- * so be sure that method works correctly!
- */
- public void testBytesToBits_byteBitSetInt() {
- byte[] methodByteArray = new byte[1];
- BitSet methodBitSet = new BitSet(8);
- for (int i = 0; i < 255; i++) {
- methodByteArray[0] = (byte)i;
- HexUtil.bytesToBits(methodByteArray,methodBitSet,7);
-
assertTrue(Arrays.equals(methodByteArray,HexUtil.bitsToBytes(methodBitSet,8)));}
- }
-
- /**
- * Test biToHex(BigInteger) method
- * comparing its results to results provided
- * by different scientific valid calculators.
- */
- public void testBiToHex_BigInteger() {
- BigInteger methodBigInteger = new BigInteger("999999999999999");
- String expectedHexValue = "038d7ea4c67fff";
-
assertEquals(HexUtil.biToHex(methodBigInteger),expectedHexValue);
- methodBigInteger = new BigInteger("0");
- expectedHexValue = "00";
-
assertEquals(HexUtil.biToHex(methodBigInteger),expectedHexValue);
- methodBigInteger = new BigInteger("72057594037927935");
- expectedHexValue = "00ffffffffffffff";
-
assertEquals(HexUtil.biToHex(methodBigInteger),expectedHexValue);
- }
-
- /**
- * Test bitsToHexString(BitSet,int) method
- * comparing its results to results provided
- * by different scientific valid calculators.
- */
- public void testBitsToHexString() {
- BitSet methodBitSet = new BitSet(8);
- String expectedString = "00";
-
assertEquals(HexUtil.bitsToHexString(methodBitSet,8),expectedString);
- methodBitSet.set(0,7,true); /*0x7f*/
- expectedString = "7f";
-
assertEquals(HexUtil.bitsToHexString(methodBitSet,8),expectedString);
- methodBitSet.set(0,9,true); /*0xff*/
- expectedString = "ff";
-
assertEquals(HexUtil.bitsToHexString(methodBitSet,8),expectedString);
- }
-
- /**
- * Tests hexToBits(String,BitSet,int) method
- */
- public void testHexToBits() {
- String methodStringToStore = "00";
- BitSet methodBitSet = new BitSet(8);
-
HexUtil.hexToBits(methodStringToStore,methodBitSet,methodBitSet.size());
- assertTrue(methodBitSet.cardinality()==0);
- BitSet expectedBitSet = new BitSet(8);
- expectedBitSet.set(0,7,true); /*0x7f*/
- methodStringToStore = "7f";
- methodBitSet = new BitSet(8);
-
HexUtil.hexToBits(methodStringToStore,methodBitSet,methodBitSet.size());
- assertTrue(methodBitSet.intersects(expectedBitSet));
- expectedBitSet.set(0,9,true); /*0xff*/
- methodStringToStore = "ff";
- methodBitSet = new BitSet(8);
-
HexUtil.hexToBits(methodStringToStore,methodBitSet,methodBitSet.size());
- assertTrue(methodBitSet.intersects(expectedBitSet));
- }
-
- /**
- * Tests writeBigInteger(BigInteger,DataOutputStream)
- * and readBigInteger(DataInputStream) comparing a
- * BigInteger after writing it to a Stream and
- * reading it from the writing result.
- */
- public void testWriteAndReadBigInteger() {
- BigInteger methodBigInteger = new BigInteger("999999999999999");
- ByteArrayOutputStream methodByteArrayOutStream = new
ByteArrayOutputStream();
- DataOutputStream methodDataOutStream = new
DataOutputStream(methodByteArrayOutStream);
- try {
-
HexUtil.writeBigInteger(methodBigInteger,methodDataOutStream);
- ByteArrayInputStream methodByteArrayInStream =
- new
ByteArrayInputStream(methodByteArrayOutStream.toByteArray());
- DataInputStream methodDataInStream = new
DataInputStream(methodByteArrayInStream);
-
assertTrue(methodBigInteger.compareTo(HexUtil.readBigInteger(methodDataInStream))==0);
- } catch (IOException aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
-
- /**
- * Test bytesToHex(byte[],int,int) method
- * with a too long starting offset. The tested
- * method should raise an exception.
- */
- public void testBytesToHex_byteIntInt_WithLongOffset() {
- try {
- int arrayLength = 3;
- byte[] methodBytesArray = new byte[arrayLength];
- HexUtil.bytesToHex(methodBytesArray,arrayLength+1,1);
- fail("Expected Exception Error Not Thrown!"); }
- catch (IllegalArgumentException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Test bytesToHex(byte[],int,int) method
- * with asking to read too many bytes. The tested
- * method should raise an exception.
- */
- public void testBytesToHex_byteIntInt_WithLongReading() {
- try {
- int arrayLength = 3;
- byte[] methodBytesArray = new byte[arrayLength];
- HexUtil.bytesToHex(methodBytesArray,0,arrayLength+1);
- fail("Expected Exception Error Not Thrown!"); }
- catch (IllegalArgumentException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Test bytesToHex(byte[],int,int) method
- * with a 0 length.
- */
- public void testBytesToHex_byteIntInt_WithZeroLength() {
- int length = 0;
- byte[] methodBytesArray = {1,2,3}; //a non-zero
bytes array
- assertEquals("",HexUtil.bytesToHex(methodBytesArray,0,length));
- }
-
- /**
- * Test hexToBytes(String,byte[],int) method
- * with a too long offset.
- * The method should raise an exception.
- */
- public void testHexToBytes_StringByteInt_WithLongOffset() {
- try {
- String methodString = "0";
- byte[] methodByteArray = new byte[1];
-
HexUtil.hexToBytes(methodString,methodByteArray,methodByteArray.length);
- fail("Expected Exception Error Not Thrown!"); }
- catch (ArrayIndexOutOfBoundsException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Test hexToBytes(String,byte[],int) method
- * with a too short byte[] to put the result.
- * The method should raise an exception.
- */
- public void testHexToBytes_StringByteInt_WithShortArray() {
- try {
- String methodString = "0000";
- byte[] methodByteArray = new byte[1];
- HexUtil.hexToBytes(methodString,methodByteArray,0);
- fail("Expected Exception Error Not Thrown!"); }
- catch (IndexOutOfBoundsException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Test all hexToBytes() methods
- * with a not valid character.
- * The method should raise an exception.
- */
- public void testHexToBytes_WithBadDigit() {
- String methodString = "00%0";
- try {
- byte[] methodByteArray = new byte[methodString.length()];
- HexUtil.hexToBytes(methodString,methodByteArray,0);
- fail("Expected Exception Error Not Thrown!"); }
- catch (NumberFormatException anException) {
- assertNotNull(anException); }
- try {
- HexUtil.hexToBytes(methodString,0);
- fail("Expected Exception Error Not Thrown!"); }
- catch (NumberFormatException anException) {
- assertNotNull(anException); }
- try {
- HexUtil.hexToBytes(methodString);
- fail("Expected Exception Error Not Thrown!"); }
- catch (NumberFormatException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Test the bitsToByte(BitSet,int) method
- * using a size smaller than the actual number
- * of bits in the BitSet.
- */
- public void testBitsToBytes_WithShortSize() {
- byte[] expectedByteArray = new byte[1];
- byte[] outputArray = new byte[1];
- BitSet methodBitSet = new BitSet(8);
-
- /* 0x01 */
- methodBitSet.flip(0);
- expectedByteArray[0] = (byte)1;
- /* 0x01 & 0x00 == 0x01 */
- outputArray = HexUtil.bitsToBytes(methodBitSet,0);
- assertFalse(Arrays.equals(expectedByteArray,outputArray));
- /* 0x01 & 0x01 == 0x01 */
- outputArray = HexUtil.bitsToBytes(methodBitSet,1);
- assertTrue(Arrays.equals(expectedByteArray,outputArray));
-
- /* 0x80 */
- methodBitSet.flip(7);
- /* 0x08 */
- methodBitSet.flip(3);
- expectedByteArray[0] = (byte)128+8+1;
- /* 0x89 & 0x08 == 0x89 */
- outputArray = HexUtil.bitsToBytes(methodBitSet,3);
- assertFalse(Arrays.equals(expectedByteArray,outputArray));
- /* 0x89 & 0xff == 0x89 */
- outputArray = HexUtil.bitsToBytes(methodBitSet,8);
- assertTrue(Arrays.equals(expectedByteArray,outputArray));
- }
-}
Copied: branches/freenet-jfk/test/freenet/support/HexUtilTest.java (from rev
14796, trunk/freenet/test/freenet/support/HexUtilTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/HexUtilTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/HexUtilTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,371 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package freenet.support;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.BitSet;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.HexUtil} class.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class HexUtilTest extends TestCase {
+
+ /**
+ * Test the bytesToHex(byte[]) method
+ * against every possible single byte value.
+ */
+ public void testBytesToHex_byte() {
+ byte[] methodByteArray = new byte[1];
+ String expectedResult;
+ for (int i = 255; i >= 0; i--) {
+ methodByteArray[0] = (byte)i;
+ /* Integer.toHexString works with int so it doesn't
return always a two digit hex.
+ For this reason we need the next "switch case". */
+ expectedResult = (i <= 15?
+ "0" + (Integer.toHexString(i)):
+ (Integer.toHexString(i)));
+
assertEquals(expectedResult,HexUtil.bytesToHex(methodByteArray));}
+ }
+
+ /**
+ * Test the hexToBytes(String) method
+ * against the hex representation of
+ * every possible single byte.
+ * The starting offset is always 0.
+ */
+ public void testHexToBytes_String() {
+ byte[] expectedByteArray = new byte[1];
+ String methodHexString;
+ for (int i = 255; i >= 0; i--) {
+ expectedByteArray[0] = (byte)i;
+ /* Integer.toHexString works with int so it doesn't
return always a two digit hex.
+ For this reason we need the next "switch case". */
+ methodHexString = (i <= 15?
+ "0" + (Integer.toHexString(i)):
+ (Integer.toHexString(i)));
+
assertTrue(Arrays.equals(expectedByteArray,HexUtil.hexToBytes(methodHexString)));}
+ }
+
+ /**
+ * Test the hexToBytes(String,int) method
+ * against the hex representation of
+ * every possible single byte.
+ * The starting offset is always 0.
+ */
+ public void testHexToBytes_StringInt() {
+ byte[] expectedByteArray = new byte[1];
+ String methodHexString;
+ for (int i = 255; i >= 0; i--) {
+ expectedByteArray[0] = (byte)i;
+ /* Integer.toHexString works with int so it doesn't
return always a two digit hex.
+ For this reason we need the next "switch case". */
+ methodHexString = (i <= 15?
+ "0" + (Integer.toHexString(i)):
+ (Integer.toHexString(i)));
+
assertTrue(Arrays.equals(expectedByteArray,HexUtil.hexToBytes(methodHexString,0)));}
+ }
+
+ /**
+ * Test the hexToBytes(String,byte[],int) method
+ * against the hex representation of
+ * every possible single byte.
+ */
+ public void testHexToBytes_StringByteInt() {
+ byte[] expectedByteArray = new byte[1];
+ byte[] outputArray = new byte[1];
+ String methodHexString;
+ for (int i = 255; i >= 0; i--) {
+ expectedByteArray[0] = (byte)i;
+ /* Integer.toHexString works with int so it doesn't
return always a two digit hex.
+ For this reason we need the next "switch case". */
+ methodHexString = (i <= 15?
+ "0" + (Integer.toHexString(i)):
+ (Integer.toHexString(i)));
+ HexUtil.hexToBytes(methodHexString,outputArray,0);
+
assertTrue(Arrays.equals(expectedByteArray,outputArray));}
+ }
+
+ /**
+ * Test the bitsToByte(BitSet,int) method
+ * against the bit representation of
+ * every possible single byte.
+ */
+ public void testBitsToBytes_BitSetInt() {
+ byte[] expectedByteArray = new byte[1];
+ byte[] outputArray = new byte[1];
+ BitSet methodBitSet = new BitSet(8);
+ for (int i = 0; i < 256; i++) {
+ outputArray = HexUtil.bitsToBytes(methodBitSet, 8);
+ expectedByteArray[0] = (byte)i;
+
assertTrue(Arrays.equals(expectedByteArray,outputArray));
+ addOne(methodBitSet);
+ }
+ }
+
+ /**
+ * It adds 1 to a given BitSet
+ * @param aBitSet
+ */
+ private void addOne(BitSet aBitSet) {
+ int bitSetIndex = 0;
+ while (aBitSet.get(bitSetIndex)==true) {
+ aBitSet.flip(bitSetIndex);
+ bitSetIndex++;
+ }
+ aBitSet.flip(bitSetIndex);
+ }
+
+ /**
+ * Test countBytesForBits(int) method
+ * against all possible values until 256 bytes
+ */
+ public void testCountBytesForBits_int() {
+ //border case
+ assertEquals(HexUtil.countBytesForBits(0),0);
+ for (int expectedBytesCount = 1; expectedBytesCount < 256;
expectedBytesCount++)
+ for (int bits = (expectedBytesCount-1)*8+1; bits <=
(expectedBytesCount)*8; bits++)
+
assertEquals(HexUtil.countBytesForBits(bits),expectedBytesCount);
+ }
+
+ /**
+ * Test bytesToBits(byte[],BitSet,int) method
+ * against all possible single byte value.
+ * It uses HexUtil.bitsToBytes() method for the check,
+ * so be sure that method works correctly!
+ */
+ public void testBytesToBits_byteBitSetInt() {
+ byte[] methodByteArray = new byte[1];
+ BitSet methodBitSet = new BitSet(8);
+ for (int i = 0; i < 255; i++) {
+ methodByteArray[0] = (byte)i;
+ HexUtil.bytesToBits(methodByteArray,methodBitSet,7);
+
assertTrue(Arrays.equals(methodByteArray,HexUtil.bitsToBytes(methodBitSet,8)));}
+ }
+
+ /**
+ * Test biToHex(BigInteger) method
+ * comparing its results to results provided
+ * by different scientific valid calculators.
+ */
+ public void testBiToHex_BigInteger() {
+ BigInteger methodBigInteger = new BigInteger("999999999999999");
+ String expectedHexValue = "038d7ea4c67fff";
+
assertEquals(HexUtil.biToHex(methodBigInteger),expectedHexValue);
+ methodBigInteger = new BigInteger("0");
+ expectedHexValue = "00";
+
assertEquals(HexUtil.biToHex(methodBigInteger),expectedHexValue);
+ methodBigInteger = new BigInteger("72057594037927935");
+ expectedHexValue = "00ffffffffffffff";
+
assertEquals(HexUtil.biToHex(methodBigInteger),expectedHexValue);
+ }
+
+ /**
+ * Test bitsToHexString(BitSet,int) method
+ * comparing its results to results provided
+ * by different scientific valid calculators.
+ */
+ public void testBitsToHexString() {
+ BitSet methodBitSet = new BitSet(8);
+ String expectedString = "00";
+
assertEquals(HexUtil.bitsToHexString(methodBitSet,8),expectedString);
+ methodBitSet.set(0,7,true); /*0x7f*/
+ expectedString = "7f";
+
assertEquals(HexUtil.bitsToHexString(methodBitSet,8),expectedString);
+ methodBitSet.set(0,9,true); /*0xff*/
+ expectedString = "ff";
+
assertEquals(HexUtil.bitsToHexString(methodBitSet,8),expectedString);
+ }
+
+ /**
+ * Tests hexToBits(String,BitSet,int) method
+ */
+ public void testHexToBits() {
+ String methodStringToStore = "00";
+ BitSet methodBitSet = new BitSet(8);
+
HexUtil.hexToBits(methodStringToStore,methodBitSet,methodBitSet.size());
+ assertTrue(methodBitSet.cardinality()==0);
+ BitSet expectedBitSet = new BitSet(8);
+ expectedBitSet.set(0,7,true); /*0x7f*/
+ methodStringToStore = "7f";
+ methodBitSet = new BitSet(8);
+
HexUtil.hexToBits(methodStringToStore,methodBitSet,methodBitSet.size());
+ assertTrue(methodBitSet.intersects(expectedBitSet));
+ expectedBitSet.set(0,9,true); /*0xff*/
+ methodStringToStore = "ff";
+ methodBitSet = new BitSet(8);
+
HexUtil.hexToBits(methodStringToStore,methodBitSet,methodBitSet.size());
+ assertTrue(methodBitSet.intersects(expectedBitSet));
+ }
+
+ /**
+ * Tests writeBigInteger(BigInteger,DataOutputStream)
+ * and readBigInteger(DataInputStream) comparing a
+ * BigInteger after writing it to a Stream and
+ * reading it from the writing result.
+ */
+ public void testWriteAndReadBigInteger() {
+ BigInteger methodBigInteger = new BigInteger("999999999999999");
+ ByteArrayOutputStream methodByteArrayOutStream = new
ByteArrayOutputStream();
+ DataOutputStream methodDataOutStream = new
DataOutputStream(methodByteArrayOutStream);
+ try {
+
HexUtil.writeBigInteger(methodBigInteger,methodDataOutStream);
+ ByteArrayInputStream methodByteArrayInStream =
+ new
ByteArrayInputStream(methodByteArrayOutStream.toByteArray());
+ DataInputStream methodDataInStream = new
DataInputStream(methodByteArrayInStream);
+
assertTrue(methodBigInteger.compareTo(HexUtil.readBigInteger(methodDataInStream))==0);
+ } catch (IOException aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+
+ /**
+ * Test bytesToHex(byte[],int,int) method
+ * with a too long starting offset. The tested
+ * method should raise an exception.
+ */
+ public void testBytesToHex_byteIntInt_WithLongOffset() {
+ try {
+ int arrayLength = 3;
+ byte[] methodBytesArray = new byte[arrayLength];
+ HexUtil.bytesToHex(methodBytesArray,arrayLength+1,1);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (IllegalArgumentException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Test bytesToHex(byte[],int,int) method
+ * with asking to read too many bytes. The tested
+ * method should raise an exception.
+ */
+ public void testBytesToHex_byteIntInt_WithLongReading() {
+ try {
+ int arrayLength = 3;
+ byte[] methodBytesArray = new byte[arrayLength];
+ HexUtil.bytesToHex(methodBytesArray,0,arrayLength+1);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (IllegalArgumentException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Test bytesToHex(byte[],int,int) method
+ * with a 0 length.
+ */
+ public void testBytesToHex_byteIntInt_WithZeroLength() {
+ int length = 0;
+ byte[] methodBytesArray = {1,2,3}; //a non-zero
bytes array
+ assertEquals("",HexUtil.bytesToHex(methodBytesArray,0,length));
+ }
+
+ /**
+ * Test hexToBytes(String,byte[],int) method
+ * with a too long offset.
+ * The method should raise an exception.
+ */
+ public void testHexToBytes_StringByteInt_WithLongOffset() {
+ try {
+ String methodString = "0";
+ byte[] methodByteArray = new byte[1];
+
HexUtil.hexToBytes(methodString,methodByteArray,methodByteArray.length);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (ArrayIndexOutOfBoundsException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Test hexToBytes(String,byte[],int) method
+ * with a too short byte[] to put the result.
+ * The method should raise an exception.
+ */
+ public void testHexToBytes_StringByteInt_WithShortArray() {
+ try {
+ String methodString = "0000";
+ byte[] methodByteArray = new byte[1];
+ HexUtil.hexToBytes(methodString,methodByteArray,0);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (IndexOutOfBoundsException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Test all hexToBytes() methods
+ * with a not valid character.
+ * The method should raise an exception.
+ */
+ public void testHexToBytes_WithBadDigit() {
+ String methodString = "00%0";
+ try {
+ byte[] methodByteArray = new byte[methodString.length()];
+ HexUtil.hexToBytes(methodString,methodByteArray,0);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (NumberFormatException anException) {
+ assertNotNull(anException); }
+ try {
+ HexUtil.hexToBytes(methodString,0);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (NumberFormatException anException) {
+ assertNotNull(anException); }
+ try {
+ HexUtil.hexToBytes(methodString);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (NumberFormatException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Test the bitsToByte(BitSet,int) method
+ * using a size smaller than the actual number
+ * of bits in the BitSet.
+ */
+ public void testBitsToBytes_WithShortSize() {
+ byte[] expectedByteArray = new byte[1];
+ byte[] outputArray = new byte[1];
+ BitSet methodBitSet = new BitSet(8);
+
+ /* 0x01 */
+ methodBitSet.flip(0);
+ expectedByteArray[0] = (byte)1;
+ /* 0x01 & 0x00 == 0x01 */
+ outputArray = HexUtil.bitsToBytes(methodBitSet,0);
+ assertFalse(Arrays.equals(expectedByteArray,outputArray));
+ /* 0x01 & 0x01 == 0x01 */
+ outputArray = HexUtil.bitsToBytes(methodBitSet,1);
+ assertTrue(Arrays.equals(expectedByteArray,outputArray));
+
+ /* 0x80 */
+ methodBitSet.flip(7);
+ /* 0x08 */
+ methodBitSet.flip(3);
+ expectedByteArray[0] = (byte)128+8+1;
+ /* 0x89 & 0x08 == 0x89 */
+ outputArray = HexUtil.bitsToBytes(methodBitSet,3);
+ assertFalse(Arrays.equals(expectedByteArray,outputArray));
+ /* 0x89 & 0xff == 0x89 */
+ outputArray = HexUtil.bitsToBytes(methodBitSet,8);
+ assertTrue(Arrays.equals(expectedByteArray,outputArray));
+ }
+}
Deleted: branches/freenet-jfk/test/freenet/support/LRUHashtableTest.java
===================================================================
--- trunk/freenet/test/freenet/support/LRUHashtableTest.java 2007-08-18
19:36:17 UTC (rev 14796)
+++ branches/freenet-jfk/test/freenet/support/LRUHashtableTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,358 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package freenet.support;
-
-import java.util.Enumeration;
-
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.LRUHashtable} class.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class LRUHashtableTest extends TestCase {
-
- private final int sampleElemsNumber = 100;
-
- /**
- * Creates a double array of objects with a specified size
- * where Object[i][0] is the key, and is an Integer,
- * and Object[i][1] is the value
- * @param size the array size
- * @return the objects double array
- */
- private Object[][] createSampleKeyVal(int size) {
- Object[][] sampleObjects = new Object[size][2];
- for (int i=0; i<sampleObjects.length;i++) {
- //key
- sampleObjects[i][0] = new Integer(i);
- //value
- sampleObjects[i][1] = new Object(); }
- return sampleObjects;
- }
-
- /**
- * Creates a LRUHashtable filled with the specified objects number
- * @param size HashTable size
- * @return the created LRUHashtable
- */
- private LRUHashtable createSampleHashTable(int size) {
- LRUHashtable methodLRUht = new LRUHashtable();
- Object[][] sampleObjects = createSampleKeyVal(size);
- for (int i=0;i<sampleObjects.length;i++)
-
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
- return methodLRUht;
- }
-
- /**
- * It verifies if a key-value pair is present in
- * a LRUHashtable
- * @param aLRUht a LRUHashtable to check in
- * @param aKey a key to find
- * @param aValue the correspondent value
- * @return true if the key is present and returned value is the same as
in the argument
- */
- private boolean verifyKeyValPresence(LRUHashtable aLRUht, Object aKey,
Object aValue) {
- if (aLRUht.containsKey(aKey))
- return aLRUht.get(aKey).equals(aValue);
- return false;
- }
-
- /**
- * Tests push(Object,Object) method
- * providing null object as arguments
- * (after setting up a sample HashTable)
- * and verifying if the correct exception
- * is raised
- */
- public void testPushNull() {
- LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
- try {
- //a null value is admitted
- methodLRUht.push(new Object(),null);}
- catch (NullPointerException anException) {
- fail("Not expected exception thrown : " +
anException.getMessage()); }
- try {
- methodLRUht.push(null,null);
- fail("Expected Exception Error Not Thrown!"); }
- catch (NullPointerException anException) {
assertNotNull(anException); }
- try {
- methodLRUht.push(null,new Object());
- fail("Expected Exception Error Not Thrown!"); }
- catch (NullPointerException anException) {
assertNotNull(anException); }
-
- }
-
- /**
- * Tests push(Object,Object) method
- * and verifies the behaviour when
- * pushing the same object more than one
- * time.
- */
- public void testPushSameObjTwice() {
- LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
- Object[][] sampleObj = {
- { new Integer(sampleElemsNumber), new Object()
},
- { new Integer(sampleElemsNumber+1), new
Object() } };
-
- methodLRUht.push(sampleObj[0][0],sampleObj[0][1]);
- methodLRUht.push(sampleObj[1][0],sampleObj[1][1]);
-
- //check presence
-
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[0][0],sampleObj[0][1]));
-
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[1][0],sampleObj[1][1]));
- //check size
- assertTrue(methodLRUht.size()==sampleElemsNumber+2);
-
- //push the same object another time
- methodLRUht.push(sampleObj[0][0],sampleObj[0][1]);
-
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[0][0],sampleObj[0][1]));
-
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[1][0],sampleObj[1][1]));
- assertTrue(methodLRUht.size()==sampleElemsNumber+2);
- }
-
- /**
- * Tests push(Object,Object) method
- * and verifies the behaviour when
- * pushing the same key with two different
- * values.
- */
- public void testPushSameKey() {
- LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
- Object[][] sampleObj = {
- { new Integer(sampleElemsNumber), new Object()
},
- { new Integer(sampleElemsNumber+1), new
Object() } };
-
- methodLRUht.push(sampleObj[0][0],sampleObj[0][1]);
- methodLRUht.push(sampleObj[1][0],sampleObj[1][1]);
-
- //check presence
-
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[0][0],sampleObj[0][1]));
-
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[1][0],sampleObj[1][1]));
- //check size
- assertTrue(methodLRUht.size()==sampleElemsNumber+2);
-
- //creating and pushing a different value
- sampleObj[0][1] = new Object();
- methodLRUht.push(sampleObj[0][0],sampleObj[0][1]);
-
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[0][0],sampleObj[0][1]));
-
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[1][0],sampleObj[1][1]));
- assertTrue(methodLRUht.size()==sampleElemsNumber+2);
- }
-
- /**
- * Tests popKey() method pushing
- * and popping objects and
- * verifying if their keys are correctly
- * (in a FIFO manner) fetched and the
- * HashTable entry deleted
- */
- public void testPopKey() {
- LRUHashtable methodLRUht = new LRUHashtable();
- Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
- //pushing objects
- for (int i=0; i<sampleObjects.length; i++)
-
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
- //getting keys
- for (int i=0; i<sampleObjects.length; i++)
- assertEquals(sampleObjects[i][0],methodLRUht.popKey());
- //the HashTable must be empty
- assertNull(methodLRUht.popKey());
- }
-
- /**
- * Tests popKey() method pushing
- * and popping objects and
- * verifying if their values are correctly
- * (in a FIFO manner) fetched and the
- * HashTable entry deleted
- */
- public void testPopValue() {
- LRUHashtable methodLRUht = new LRUHashtable();
- Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
- //pushing objects
- for (int i=0; i<sampleObjects.length; i++)
-
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
- //getting values
- for (int i=0; i<sampleObjects.length; i++)
-
assertEquals(sampleObjects[i][1],methodLRUht.popValue());
- //the HashTable must be empty
- assertNull(methodLRUht.popKey());
- }
-
- /**
- * Tests peekValue() method pushing
- * and popping objects and
- * verifying if their peekValue is correct
- */
- public void testPeekValue() {
- LRUHashtable methodLRUht = new LRUHashtable();
- Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
- //pushing objects
- for (int i=0; i<sampleObjects.length; i++)
-
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
- //getting values
- for (int i=0; i<sampleObjects.length; i++) {
-
assertEquals(sampleObjects[i][1],methodLRUht.peekValue());
- methodLRUht.popKey(); }
- //the HashTable must be empty
- assertNull(methodLRUht.peekValue());
- //insert and fetch a null value
- methodLRUht.push(new Object(),null);
- assertNull(methodLRUht.peekValue());
- }
-
- /**
- * Tests size() method
- * pushing and popping elements into
- * the LRUHashTable
- */
- public void testSize() {
- LRUHashtable methodLRUht = new LRUHashtable();
- Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
- assertTrue(methodLRUht.size()==0);
- //pushing objects
- for (int i=0; i<sampleObjects.length; i++) {
-
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
- assertTrue(methodLRUht.size()==i+1); }
- //popping keys
- for (int i=sampleObjects.length-1; i>=0; i--) {
- methodLRUht.popKey();
- assertTrue(methodLRUht.size()==i); }
- }
-
- /**
- * Tests removeKey(Object) method
- * verifies if all elements are correctly
- * removed checking the method return value,
- * if the element is still contained and
- * the HashTable size.
- */
- public void testRemoveKey() {
- LRUHashtable methodLRUht = new LRUHashtable();
- Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
- //pushing objects
- for (int i=0; i<sampleObjects.length; i++)
-
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
- //popping keys
- for (int i=sampleObjects.length-1; i>=0; i--) {
- assertTrue(methodLRUht.removeKey(sampleObjects[i][0]));
-
assertFalse(methodLRUht.containsKey(sampleObjects[i][0]));
- assertTrue(methodLRUht.size()==i); }
- }
-
- /**
- * Tests removeKey(Object) providing a null
- * key and trying to remove it after
- * setting up a sample queue.
- */
- public void testRemoveNullKey() {
- LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
- try {
- methodLRUht.removeKey(null);
- fail("Expected Exception Error Not Thrown!"); }
- catch (NullPointerException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Tests removeKey(Object) method
- * trying to remove a not present key after
- * setting up a sample LRUHashtable.
- */
- public void testRemoveNotPresent() {
- LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
- assertFalse(methodLRUht.removeKey(new Object()));
- }
-
- /**
- * Tests containsKey(Object) method
- * trying to find a not present key after
- * setting up a sample queue.
- * Then it search for a present one.
- */
- public void testContainsKey() {
- LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
- assertFalse(methodLRUht.containsKey(new Object()));
- Object methodSampleObj = new Object();
- methodLRUht.push(methodSampleObj,null);
- assertTrue(methodLRUht.containsKey(methodSampleObj));
- }
-
- /**
- * Tests get(Object) method
- * trying to find a not present key after
- * setting up a sample HashTable,
- * then it search a present key.
- */
- public void testGet() {
- LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
- assertNull(methodLRUht.get(new Object()));
- Object methodSampleKey = new Object();
- Object methodSampleValue = new Object();
- methodLRUht.push(methodSampleKey,methodSampleValue);
-
assertEquals(methodLRUht.get(methodSampleKey),methodSampleValue);
- }
-
- /**
- * Tests get(Object) trying to fetch
- * a null key.
- */
- public void testGetNullKey() {
- LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
- try {
- methodLRUht.get(null);
- fail("Expected Exception Error Not Thrown!"); }
- catch (NullPointerException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Tests keys() method
- * verifying if the Enumeration provided
- * is correct
- */
- public void testKeys() {
- LRUHashtable methodLRUht = new LRUHashtable();
- Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
- //pushing objects
- for (int i=0; i<sampleObjects.length; i++)
-
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
- Enumeration methodEnumeration = methodLRUht.keys();
- int j=0;
- while(methodEnumeration.hasMoreElements()) {
-
assertEquals(methodEnumeration.nextElement(),sampleObjects[j][0]);
- j++; }
- }
-
- /**
- * Tests isEmpty() method
- * trying it with a new generated
- * HashTable and after popping
- * out all keys in a sample LRUHashTable
- */
- public void testIsEmpty() {
- LRUHashtable methodLRUht = new LRUHashtable();
- assertTrue(methodLRUht.isEmpty());
- methodLRUht = createSampleHashTable(sampleElemsNumber);
- //popping keys
- for (int i=0; i<sampleElemsNumber;i++)
- methodLRUht.popKey();
- assertTrue(methodLRUht.isEmpty());
- }
-
-}
Copied: branches/freenet-jfk/test/freenet/support/LRUHashtableTest.java (from
rev 14796, trunk/freenet/test/freenet/support/LRUHashtableTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/LRUHashtableTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/LRUHashtableTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,358 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+
+import java.util.Enumeration;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.LRUHashtable} class.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class LRUHashtableTest extends TestCase {
+
+ private final int sampleElemsNumber = 100;
+
+ /**
+ * Creates a double array of objects with a specified size
+ * where Object[i][0] is the key, and is an Integer,
+ * and Object[i][1] is the value
+ * @param size the array size
+ * @return the objects double array
+ */
+ private Object[][] createSampleKeyVal(int size) {
+ Object[][] sampleObjects = new Object[size][2];
+ for (int i=0; i<sampleObjects.length;i++) {
+ //key
+ sampleObjects[i][0] = new Integer(i);
+ //value
+ sampleObjects[i][1] = new Object(); }
+ return sampleObjects;
+ }
+
+ /**
+ * Creates a LRUHashtable filled with the specified objects number
+ * @param size HashTable size
+ * @return the created LRUHashtable
+ */
+ private LRUHashtable createSampleHashTable(int size) {
+ LRUHashtable methodLRUht = new LRUHashtable();
+ Object[][] sampleObjects = createSampleKeyVal(size);
+ for (int i=0;i<sampleObjects.length;i++)
+
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
+ return methodLRUht;
+ }
+
+ /**
+ * It verifies if a key-value pair is present in
+ * a LRUHashtable
+ * @param aLRUht a LRUHashtable to check in
+ * @param aKey a key to find
+ * @param aValue the correspondent value
+ * @return true if the key is present and returned value is the same as
in the argument
+ */
+ private boolean verifyKeyValPresence(LRUHashtable aLRUht, Object aKey,
Object aValue) {
+ if (aLRUht.containsKey(aKey))
+ return aLRUht.get(aKey).equals(aValue);
+ return false;
+ }
+
+ /**
+ * Tests push(Object,Object) method
+ * providing null object as arguments
+ * (after setting up a sample HashTable)
+ * and verifying if the correct exception
+ * is raised
+ */
+ public void testPushNull() {
+ LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
+ try {
+ //a null value is admitted
+ methodLRUht.push(new Object(),null);}
+ catch (NullPointerException anException) {
+ fail("Not expected exception thrown : " +
anException.getMessage()); }
+ try {
+ methodLRUht.push(null,null);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (NullPointerException anException) {
assertNotNull(anException); }
+ try {
+ methodLRUht.push(null,new Object());
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (NullPointerException anException) {
assertNotNull(anException); }
+
+ }
+
+ /**
+ * Tests push(Object,Object) method
+ * and verifies the behaviour when
+ * pushing the same object more than one
+ * time.
+ */
+ public void testPushSameObjTwice() {
+ LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
+ Object[][] sampleObj = {
+ { new Integer(sampleElemsNumber), new Object()
},
+ { new Integer(sampleElemsNumber+1), new
Object() } };
+
+ methodLRUht.push(sampleObj[0][0],sampleObj[0][1]);
+ methodLRUht.push(sampleObj[1][0],sampleObj[1][1]);
+
+ //check presence
+
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[0][0],sampleObj[0][1]));
+
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[1][0],sampleObj[1][1]));
+ //check size
+ assertTrue(methodLRUht.size()==sampleElemsNumber+2);
+
+ //push the same object another time
+ methodLRUht.push(sampleObj[0][0],sampleObj[0][1]);
+
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[0][0],sampleObj[0][1]));
+
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[1][0],sampleObj[1][1]));
+ assertTrue(methodLRUht.size()==sampleElemsNumber+2);
+ }
+
+ /**
+ * Tests push(Object,Object) method
+ * and verifies the behaviour when
+ * pushing the same key with two different
+ * values.
+ */
+ public void testPushSameKey() {
+ LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
+ Object[][] sampleObj = {
+ { new Integer(sampleElemsNumber), new Object()
},
+ { new Integer(sampleElemsNumber+1), new
Object() } };
+
+ methodLRUht.push(sampleObj[0][0],sampleObj[0][1]);
+ methodLRUht.push(sampleObj[1][0],sampleObj[1][1]);
+
+ //check presence
+
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[0][0],sampleObj[0][1]));
+
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[1][0],sampleObj[1][1]));
+ //check size
+ assertTrue(methodLRUht.size()==sampleElemsNumber+2);
+
+ //creating and pushing a different value
+ sampleObj[0][1] = new Object();
+ methodLRUht.push(sampleObj[0][0],sampleObj[0][1]);
+
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[0][0],sampleObj[0][1]));
+
assertTrue(verifyKeyValPresence(methodLRUht,sampleObj[1][0],sampleObj[1][1]));
+ assertTrue(methodLRUht.size()==sampleElemsNumber+2);
+ }
+
+ /**
+ * Tests popKey() method pushing
+ * and popping objects and
+ * verifying if their keys are correctly
+ * (in a FIFO manner) fetched and the
+ * HashTable entry deleted
+ */
+ public void testPopKey() {
+ LRUHashtable methodLRUht = new LRUHashtable();
+ Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
+ //pushing objects
+ for (int i=0; i<sampleObjects.length; i++)
+
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
+ //getting keys
+ for (int i=0; i<sampleObjects.length; i++)
+ assertEquals(sampleObjects[i][0],methodLRUht.popKey());
+ //the HashTable must be empty
+ assertNull(methodLRUht.popKey());
+ }
+
+ /**
+ * Tests popKey() method pushing
+ * and popping objects and
+ * verifying if their values are correctly
+ * (in a FIFO manner) fetched and the
+ * HashTable entry deleted
+ */
+ public void testPopValue() {
+ LRUHashtable methodLRUht = new LRUHashtable();
+ Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
+ //pushing objects
+ for (int i=0; i<sampleObjects.length; i++)
+
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
+ //getting values
+ for (int i=0; i<sampleObjects.length; i++)
+
assertEquals(sampleObjects[i][1],methodLRUht.popValue());
+ //the HashTable must be empty
+ assertNull(methodLRUht.popKey());
+ }
+
+ /**
+ * Tests peekValue() method pushing
+ * and popping objects and
+ * verifying if their peekValue is correct
+ */
+ public void testPeekValue() {
+ LRUHashtable methodLRUht = new LRUHashtable();
+ Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
+ //pushing objects
+ for (int i=0; i<sampleObjects.length; i++)
+
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
+ //getting values
+ for (int i=0; i<sampleObjects.length; i++) {
+
assertEquals(sampleObjects[i][1],methodLRUht.peekValue());
+ methodLRUht.popKey(); }
+ //the HashTable must be empty
+ assertNull(methodLRUht.peekValue());
+ //insert and fetch a null value
+ methodLRUht.push(new Object(),null);
+ assertNull(methodLRUht.peekValue());
+ }
+
+ /**
+ * Tests size() method
+ * pushing and popping elements into
+ * the LRUHashTable
+ */
+ public void testSize() {
+ LRUHashtable methodLRUht = new LRUHashtable();
+ Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
+ assertTrue(methodLRUht.size()==0);
+ //pushing objects
+ for (int i=0; i<sampleObjects.length; i++) {
+
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
+ assertTrue(methodLRUht.size()==i+1); }
+ //popping keys
+ for (int i=sampleObjects.length-1; i>=0; i--) {
+ methodLRUht.popKey();
+ assertTrue(methodLRUht.size()==i); }
+ }
+
+ /**
+ * Tests removeKey(Object) method
+ * verifies if all elements are correctly
+ * removed checking the method return value,
+ * if the element is still contained and
+ * the HashTable size.
+ */
+ public void testRemoveKey() {
+ LRUHashtable methodLRUht = new LRUHashtable();
+ Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
+ //pushing objects
+ for (int i=0; i<sampleObjects.length; i++)
+
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
+ //popping keys
+ for (int i=sampleObjects.length-1; i>=0; i--) {
+ assertTrue(methodLRUht.removeKey(sampleObjects[i][0]));
+
assertFalse(methodLRUht.containsKey(sampleObjects[i][0]));
+ assertTrue(methodLRUht.size()==i); }
+ }
+
+ /**
+ * Tests removeKey(Object) providing a null
+ * key and trying to remove it after
+ * setting up a sample queue.
+ */
+ public void testRemoveNullKey() {
+ LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
+ try {
+ methodLRUht.removeKey(null);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (NullPointerException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Tests removeKey(Object) method
+ * trying to remove a not present key after
+ * setting up a sample LRUHashtable.
+ */
+ public void testRemoveNotPresent() {
+ LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
+ assertFalse(methodLRUht.removeKey(new Object()));
+ }
+
+ /**
+ * Tests containsKey(Object) method
+ * trying to find a not present key after
+ * setting up a sample queue.
+ * Then it search for a present one.
+ */
+ public void testContainsKey() {
+ LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
+ assertFalse(methodLRUht.containsKey(new Object()));
+ Object methodSampleObj = new Object();
+ methodLRUht.push(methodSampleObj,null);
+ assertTrue(methodLRUht.containsKey(methodSampleObj));
+ }
+
+ /**
+ * Tests get(Object) method
+ * trying to find a not present key after
+ * setting up a sample HashTable,
+ * then it search a present key.
+ */
+ public void testGet() {
+ LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
+ assertNull(methodLRUht.get(new Object()));
+ Object methodSampleKey = new Object();
+ Object methodSampleValue = new Object();
+ methodLRUht.push(methodSampleKey,methodSampleValue);
+
assertEquals(methodLRUht.get(methodSampleKey),methodSampleValue);
+ }
+
+ /**
+ * Tests get(Object) trying to fetch
+ * a null key.
+ */
+ public void testGetNullKey() {
+ LRUHashtable methodLRUht =
createSampleHashTable(sampleElemsNumber);
+ try {
+ methodLRUht.get(null);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (NullPointerException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Tests keys() method
+ * verifying if the Enumeration provided
+ * is correct
+ */
+ public void testKeys() {
+ LRUHashtable methodLRUht = new LRUHashtable();
+ Object[][] sampleObjects =
createSampleKeyVal(sampleElemsNumber);
+ //pushing objects
+ for (int i=0; i<sampleObjects.length; i++)
+
methodLRUht.push(sampleObjects[i][0],sampleObjects[i][1]);
+ Enumeration methodEnumeration = methodLRUht.keys();
+ int j=0;
+ while(methodEnumeration.hasMoreElements()) {
+
assertEquals(methodEnumeration.nextElement(),sampleObjects[j][0]);
+ j++; }
+ }
+
+ /**
+ * Tests isEmpty() method
+ * trying it with a new generated
+ * HashTable and after popping
+ * out all keys in a sample LRUHashTable
+ */
+ public void testIsEmpty() {
+ LRUHashtable methodLRUht = new LRUHashtable();
+ assertTrue(methodLRUht.isEmpty());
+ methodLRUht = createSampleHashTable(sampleElemsNumber);
+ //popping keys
+ for (int i=0; i<sampleElemsNumber;i++)
+ methodLRUht.popKey();
+ assertTrue(methodLRUht.isEmpty());
+ }
+
+}
Deleted: branches/freenet-jfk/test/freenet/support/LRUQueueTest.java
===================================================================
--- trunk/freenet/test/freenet/support/LRUQueueTest.java 2007-08-18
19:36:17 UTC (rev 14796)
+++ branches/freenet-jfk/test/freenet/support/LRUQueueTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -1,291 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package freenet.support;
-
-import java.util.Enumeration;
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.LRUQueue} class.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class LRUQueueTest extends TestCase {
-
- private final int sampleElemsNumber = 100;
-
- /**
- * Creates an array of objects with a specified size
- * @param size the array size
- * @return the objects array
- */
- private Object[] createSampleObjects(int size) {
- Object[] sampleObjects = new Object[size];
- for (int i=0; i<sampleObjects.length;i++)
- sampleObjects[i] = new Object();
- return sampleObjects;
- }
-
- /**
- * Creates a LRUQueue filled with the specified objects number
- * @param size queue size
- * @return the created LRUQueue
- */
- private LRUQueue createSampleQueue(int size) {
- LRUQueue methodLRUQueue = new LRUQueue();
- Object[] sampleObjects = createSampleObjects(size);
- for (int i=0;i<sampleObjects.length;i++)
- methodLRUQueue.push(sampleObjects[i]);
- return methodLRUQueue;
- }
-
- /**
- * Verifies if an element is present in an array
- * @param anArray the array to search into
- * @param aElementToSearch the object that must be found
- * @return true if there is at least one reference to the object
- */
- private boolean isPresent(Object[] anArray, Object aElementToSearch) {
- for(int i=0; i<anArray.length; i++)
- if (anArray[i].equals(aElementToSearch))
- return true;
- return false;
- }
-
- /**
- * Verifies if the order of the last two elements in the
- * queue is correct
- * @param aLRUQueue the LRUQueue to check
- * @param nextToLast the next-to-last element expected
- * @param last the last element expected
- * @return true if the order is correct
- */
- private boolean verifyLastElemsOrder(LRUQueue aLRUQueue, Object
nextToLast, Object last ) {
- boolean retVal = true;
- int size = aLRUQueue.size();
- Enumeration methodEnum = aLRUQueue.elements();
- int counter = 0;
- while (methodEnum.hasMoreElements()) {
- //next-to-last object
- if (counter == size-2)
- retVal &=
(methodEnum.nextElement()).equals(nextToLast);
- //last object
- else if (counter == size-1)
- retVal &=
(methodEnum.nextElement()).equals(last);
- else
- methodEnum.nextElement();
- counter++; }
- return retVal;
- }
-
- /**
- * Tests push(Object) method
- * providing a null object as argument
- * (after setting up a sample queue)
- * and verifying if the correct exception
- * is raised
- */
- public void testPushNull() {
- LRUQueue methodLRUQueue =
this.createSampleQueue(sampleElemsNumber);
- try {
- methodLRUQueue.push(null);
- fail("Expected Exception Error Not Thrown!"); }
- catch (NullPointerException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Tests push(Object) method
- * and verifies the behaviour when
- * pushing the same object more than one
- * time.
- */
- public void testPushSameObjTwice() {
- LRUQueue methodLRUQueue =
this.createSampleQueue(sampleElemsNumber);
- Object[] sampleObj = {new Object(), new Object()};
-
- methodLRUQueue.push(sampleObj[0]);
- methodLRUQueue.push(sampleObj[1]);
-
- //check size
- assertTrue(methodLRUQueue.size()==sampleElemsNumber+2);
- //check order
- assertTrue(verifyLastElemsOrder(methodLRUQueue, sampleObj[0],
sampleObj[1]));
-
- methodLRUQueue.push(sampleObj[0]);
- //check size
- assertTrue(methodLRUQueue.size()==sampleElemsNumber+2);
- //check order
- assertTrue(verifyLastElemsOrder(methodLRUQueue, sampleObj[1],
sampleObj[0]));
- }
-
- /**
- * Tests pop() method pushing
- * and popping objects and
- * verifying if they are correctly (in a FIFO manner)
- * fetched and deleted
- */
- public void testPop() {
- LRUQueue methodLRUQueue = new LRUQueue();
- Object[] sampleObjects = createSampleObjects(sampleElemsNumber);
- //pushing objects
- for (int i=0; i<sampleObjects.length; i++)
- methodLRUQueue.push(sampleObjects[i]);
- //getting objects
- for (int i=0; i<sampleObjects.length; i++)
- assertEquals(sampleObjects[i],methodLRUQueue.pop());
- //the queue must be empty
- assertNull(methodLRUQueue.pop());
- }
-
- /**
- * Tests size() method checking size
- * when empty, when putting each object
- * and when popping each object.
- */
- public void testSize() {
- Object[] sampleObjects = createSampleObjects(sampleElemsNumber);
- LRUQueue methodLRUQueue = new LRUQueue();
- assertTrue(methodLRUQueue.size()==0);
- //pushing objects
- for (int i=0; i<sampleObjects.length; i++) {
- methodLRUQueue.push(sampleObjects[i]);
- assertTrue(methodLRUQueue.size()==i+1); }
- //getting all objects
- for (int i=sampleObjects.length-1; i>=0; i--) {
- methodLRUQueue.pop();
- assertTrue(methodLRUQueue.size()==i); }
- assertTrue(methodLRUQueue.size()==0);
- }
-
- /**
- * Tests remove(Object) method
- * verifies if all objects are correctly
- * removed checking the method return value,
- * if the object is still contained and
- * the queue size.
- */
- public void testRemove() {
- LRUQueue methodLRUQueue = new LRUQueue();
- Object[] sampleObjects = createSampleObjects(sampleElemsNumber);
- for (int i=0;i<sampleObjects.length;i++)
- methodLRUQueue.push(sampleObjects[i]);
- //removing all objects in the opposite way used by pop() method
- for(int i=sampleObjects.length-1;i>=0;i--) {
- assertTrue(methodLRUQueue.remove(sampleObjects[i]));
- assertFalse(methodLRUQueue.contains(sampleObjects[i]));
- assertTrue(methodLRUQueue.size()==i); }
- }
-
- /**
- * Tests remove(Object) providing a null
- * argument and trying to remove it after
- * setting up a sample queue.
- */
- public void testRemoveNull() {
- LRUQueue methodLRUQueue = createSampleQueue(sampleElemsNumber);
- try {
- methodLRUQueue.remove(null);
- fail("Expected Exception Error Not Thrown!"); }
- catch (NullPointerException anException) {
- assertNotNull(anException); }
- }
-
- /**
- * Tests remove(Object) method
- * trying to remove a not present object after
- * setting up a sample queue.
- */
- public void testRemoveNotPresent() {
- LRUQueue methodLRUQueue = createSampleQueue(sampleElemsNumber);
- assertFalse(methodLRUQueue.remove(new Object()));
- }
-
- /**
- * Tests contains(Object) method
- * trying to find a not present object after
- * setting up a sample queue.
- * Then it search a present object.
- */
- public void testContains() {
- LRUQueue methodLRUQueue = createSampleQueue(sampleElemsNumber);
- assertFalse(methodLRUQueue.contains(new Object()));
- Object methodSampleObj = new Object();
- methodLRUQueue.push(methodSampleObj);
- assertTrue(methodLRUQueue.contains(methodSampleObj));
- }
-
-
- /**
- * Tests elements() method
- * verifying if the Enumeration provided
- * is correct
- */
- public void testElements() {
- Object[] sampleObjects = createSampleObjects(sampleElemsNumber);
- LRUQueue methodLRUQueue = new LRUQueue();
- //pushing objects
- for (int i=0; i<sampleObjects.length; i++)
- methodLRUQueue.push(sampleObjects[i]);
- Enumeration methodEnumeration = methodLRUQueue.elements();
- int j=0;
- while(methodEnumeration.hasMoreElements()) {
-
assertEquals(methodEnumeration.nextElement(),sampleObjects[j]);
- j++; }
- }
-
- /**
- * Tests toArray() method
- * verifying if the array generated has the same object
- * that are put into the created LRUQueue
- */
- public void testToArray() {
- LRUQueue methodLRUQueue = new LRUQueue();
- Object[] sampleObjects = createSampleObjects(sampleElemsNumber);
- //pushing objects
- for (int i=0; i<sampleObjects.length; i++)
- methodLRUQueue.push(sampleObjects[i]);
- Object[] resultingArray = methodLRUQueue.toArray();
- assertTrue(resultingArray.length==sampleObjects.length);
- for(int i=0;i<sampleObjects.length;i++)
- assertTrue(isPresent(resultingArray,sampleObjects[i]));
- }
-
- /**
- * Tests toArray() method
- * when the queue is empty
- */
- public void testToArrayEmptyQueue() {
- LRUQueue methodLRUQueue = new LRUQueue();
- assertTrue(methodLRUQueue.toArray().length==0);
- }
-
- /**
- * Tests isEmpty() method
- * trying it with an empty queue
- * and then with a sample queue.
- */
- public void testIsEmpty() {
- LRUQueue methodLRUQueue = new LRUQueue();
- assertTrue(methodLRUQueue.isEmpty());
- methodLRUQueue = createSampleQueue(sampleElemsNumber);
- assertFalse(methodLRUQueue.isEmpty());
- //emptying the queue...
- for(int i=0;i<sampleElemsNumber;i++)
- methodLRUQueue.pop();
- assertTrue(methodLRUQueue.isEmpty());
- }
-}
\ No newline at end of file
Copied: branches/freenet-jfk/test/freenet/support/LRUQueueTest.java (from rev
14796, trunk/freenet/test/freenet/support/LRUQueueTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/LRUQueueTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/LRUQueueTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,291 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+
+import java.util.Enumeration;
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.LRUQueue} class.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class LRUQueueTest extends TestCase {
+
+ private final int sampleElemsNumber = 100;
+
+ /**
+ * Creates an array of objects with a specified size
+ * @param size the array size
+ * @return the objects array
+ */
+ private Object[] createSampleObjects(int size) {
+ Object[] sampleObjects = new Object[size];
+ for (int i=0; i<sampleObjects.length;i++)
+ sampleObjects[i] = new Object();
+ return sampleObjects;
+ }
+
+ /**
+ * Creates a LRUQueue filled with the specified objects number
+ * @param size queue size
+ * @return the created LRUQueue
+ */
+ private LRUQueue createSampleQueue(int size) {
+ LRUQueue methodLRUQueue = new LRUQueue();
+ Object[] sampleObjects = createSampleObjects(size);
+ for (int i=0;i<sampleObjects.length;i++)
+ methodLRUQueue.push(sampleObjects[i]);
+ return methodLRUQueue;
+ }
+
+ /**
+ * Verifies if an element is present in an array
+ * @param anArray the array to search into
+ * @param aElementToSearch the object that must be found
+ * @return true if there is at least one reference to the object
+ */
+ private boolean isPresent(Object[] anArray, Object aElementToSearch) {
+ for(int i=0; i<anArray.length; i++)
+ if (anArray[i].equals(aElementToSearch))
+ return true;
+ return false;
+ }
+
+ /**
+ * Verifies if the order of the last two elements in the
+ * queue is correct
+ * @param aLRUQueue the LRUQueue to check
+ * @param nextToLast the next-to-last element expected
+ * @param last the last element expected
+ * @return true if the order is correct
+ */
+ private boolean verifyLastElemsOrder(LRUQueue aLRUQueue, Object
nextToLast, Object last ) {
+ boolean retVal = true;
+ int size = aLRUQueue.size();
+ Enumeration methodEnum = aLRUQueue.elements();
+ int counter = 0;
+ while (methodEnum.hasMoreElements()) {
+ //next-to-last object
+ if (counter == size-2)
+ retVal &=
(methodEnum.nextElement()).equals(nextToLast);
+ //last object
+ else if (counter == size-1)
+ retVal &=
(methodEnum.nextElement()).equals(last);
+ else
+ methodEnum.nextElement();
+ counter++; }
+ return retVal;
+ }
+
+ /**
+ * Tests push(Object) method
+ * providing a null object as argument
+ * (after setting up a sample queue)
+ * and verifying if the correct exception
+ * is raised
+ */
+ public void testPushNull() {
+ LRUQueue methodLRUQueue =
this.createSampleQueue(sampleElemsNumber);
+ try {
+ methodLRUQueue.push(null);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (NullPointerException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Tests push(Object) method
+ * and verifies the behaviour when
+ * pushing the same object more than one
+ * time.
+ */
+ public void testPushSameObjTwice() {
+ LRUQueue methodLRUQueue =
this.createSampleQueue(sampleElemsNumber);
+ Object[] sampleObj = {new Object(), new Object()};
+
+ methodLRUQueue.push(sampleObj[0]);
+ methodLRUQueue.push(sampleObj[1]);
+
+ //check size
+ assertTrue(methodLRUQueue.size()==sampleElemsNumber+2);
+ //check order
+ assertTrue(verifyLastElemsOrder(methodLRUQueue, sampleObj[0],
sampleObj[1]));
+
+ methodLRUQueue.push(sampleObj[0]);
+ //check size
+ assertTrue(methodLRUQueue.size()==sampleElemsNumber+2);
+ //check order
+ assertTrue(verifyLastElemsOrder(methodLRUQueue, sampleObj[1],
sampleObj[0]));
+ }
+
+ /**
+ * Tests pop() method pushing
+ * and popping objects and
+ * verifying if they are correctly (in a FIFO manner)
+ * fetched and deleted
+ */
+ public void testPop() {
+ LRUQueue methodLRUQueue = new LRUQueue();
+ Object[] sampleObjects = createSampleObjects(sampleElemsNumber);
+ //pushing objects
+ for (int i=0; i<sampleObjects.length; i++)
+ methodLRUQueue.push(sampleObjects[i]);
+ //getting objects
+ for (int i=0; i<sampleObjects.length; i++)
+ assertEquals(sampleObjects[i],methodLRUQueue.pop());
+ //the queue must be empty
+ assertNull(methodLRUQueue.pop());
+ }
+
+ /**
+ * Tests size() method checking size
+ * when empty, when putting each object
+ * and when popping each object.
+ */
+ public void testSize() {
+ Object[] sampleObjects = createSampleObjects(sampleElemsNumber);
+ LRUQueue methodLRUQueue = new LRUQueue();
+ assertTrue(methodLRUQueue.size()==0);
+ //pushing objects
+ for (int i=0; i<sampleObjects.length; i++) {
+ methodLRUQueue.push(sampleObjects[i]);
+ assertTrue(methodLRUQueue.size()==i+1); }
+ //getting all objects
+ for (int i=sampleObjects.length-1; i>=0; i--) {
+ methodLRUQueue.pop();
+ assertTrue(methodLRUQueue.size()==i); }
+ assertTrue(methodLRUQueue.size()==0);
+ }
+
+ /**
+ * Tests remove(Object) method
+ * verifies if all objects are correctly
+ * removed checking the method return value,
+ * if the object is still contained and
+ * the queue size.
+ */
+ public void testRemove() {
+ LRUQueue methodLRUQueue = new LRUQueue();
+ Object[] sampleObjects = createSampleObjects(sampleElemsNumber);
+ for (int i=0;i<sampleObjects.length;i++)
+ methodLRUQueue.push(sampleObjects[i]);
+ //removing all objects in the opposite way used by pop() method
+ for(int i=sampleObjects.length-1;i>=0;i--) {
+ assertTrue(methodLRUQueue.remove(sampleObjects[i]));
+ assertFalse(methodLRUQueue.contains(sampleObjects[i]));
+ assertTrue(methodLRUQueue.size()==i); }
+ }
+
+ /**
+ * Tests remove(Object) providing a null
+ * argument and trying to remove it after
+ * setting up a sample queue.
+ */
+ public void testRemoveNull() {
+ LRUQueue methodLRUQueue = createSampleQueue(sampleElemsNumber);
+ try {
+ methodLRUQueue.remove(null);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (NullPointerException anException) {
+ assertNotNull(anException); }
+ }
+
+ /**
+ * Tests remove(Object) method
+ * trying to remove a not present object after
+ * setting up a sample queue.
+ */
+ public void testRemoveNotPresent() {
+ LRUQueue methodLRUQueue = createSampleQueue(sampleElemsNumber);
+ assertFalse(methodLRUQueue.remove(new Object()));
+ }
+
+ /**
+ * Tests contains(Object) method
+ * trying to find a not present object after
+ * setting up a sample queue.
+ * Then it search a present object.
+ */
+ public void testContains() {
+ LRUQueue methodLRUQueue = createSampleQueue(sampleElemsNumber);
+ assertFalse(methodLRUQueue.contains(new Object()));
+ Object methodSampleObj = new Object();
+ methodLRUQueue.push(methodSampleObj);
+ assertTrue(methodLRUQueue.contains(methodSampleObj));
+ }
+
+
+ /**
+ * Tests elements() method
+ * verifying if the Enumeration provided
+ * is correct
+ */
+ public void testElements() {
+ Object[] sampleObjects = createSampleObjects(sampleElemsNumber);
+ LRUQueue methodLRUQueue = new LRUQueue();
+ //pushing objects
+ for (int i=0; i<sampleObjects.length; i++)
+ methodLRUQueue.push(sampleObjects[i]);
+ Enumeration methodEnumeration = methodLRUQueue.elements();
+ int j=0;
+ while(methodEnumeration.hasMoreElements()) {
+
assertEquals(methodEnumeration.nextElement(),sampleObjects[j]);
+ j++; }
+ }
+
+ /**
+ * Tests toArray() method
+ * verifying if the array generated has the same object
+ * that are put into the created LRUQueue
+ */
+ public void testToArray() {
+ LRUQueue methodLRUQueue = new LRUQueue();
+ Object[] sampleObjects = createSampleObjects(sampleElemsNumber);
+ //pushing objects
+ for (int i=0; i<sampleObjects.length; i++)
+ methodLRUQueue.push(sampleObjects[i]);
+ Object[] resultingArray = methodLRUQueue.toArray();
+ assertTrue(resultingArray.length==sampleObjects.length);
+ for(int i=0;i<sampleObjects.length;i++)
+ assertTrue(isPresent(resultingArray,sampleObjects[i]));
+ }
+
+ /**
+ * Tests toArray() method
+ * when the queue is empty
+ */
+ public void testToArrayEmptyQueue() {
+ LRUQueue methodLRUQueue = new LRUQueue();
+ assertTrue(methodLRUQueue.toArray().length==0);
+ }
+
+ /**
+ * Tests isEmpty() method
+ * trying it with an empty queue
+ * and then with a sample queue.
+ */
+ public void testIsEmpty() {
+ LRUQueue methodLRUQueue = new LRUQueue();
+ assertTrue(methodLRUQueue.isEmpty());
+ methodLRUQueue = createSampleQueue(sampleElemsNumber);
+ assertFalse(methodLRUQueue.isEmpty());
+ //emptying the queue...
+ for(int i=0;i<sampleElemsNumber;i++)
+ methodLRUQueue.pop();
+ assertTrue(methodLRUQueue.isEmpty());
+ }
+}
\ No newline at end of file
Deleted: branches/freenet-jfk/test/freenet/support/MultiValueTableTest.java
===================================================================
--- trunk/freenet/test/freenet/support/MultiValueTableTest.java 2007-08-18
19:36:17 UTC (rev 14796)
+++ branches/freenet-jfk/test/freenet/support/MultiValueTableTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,345 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package freenet.support;
-
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
-import java.util.Arrays;
-
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.MultiValueTable} class.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class MultiValueTableTest extends TestCase {
-
- private final int sampleKeyNumber = 100;
- private final int sampleMaxValueNumber = 3;
- private final boolean sampleIsRandom = true;
-
- /**
- * Create a Object[][] filled with increasing Integers as keys
- * and a List of generic Objects as values.
- * @param keysNumber the number of keys to create
- * @param valueNumber the maximum value number per key
- * @param isRandom if true each key could have [1,valuesNumber] values
- * chosen randomly, if false each key will have valuesNumber values
- * @return the Object[][] created
- */
- private Object[][] createSampleKeyMultiVal(int keysNumber, int
valuesNumber, boolean isRandom) {
- Object[][] sampleObjects = new Object[keysNumber][valuesNumber];
- int methodValuesNumber = valuesNumber;
- Random rnd = new Random();
- for (int i=0; i<sampleObjects.length;i++) {
- if (isRandom)
- methodValuesNumber =
1+rnd.nextInt(valuesNumber);
- sampleObjects[i][0] = new Integer(i);
- sampleObjects[i][1] =
fillSampleValuesList(methodValuesNumber); }
- return sampleObjects;
- }
-
- /**
- * Create a sample List filled
- * with the specified number of
- * generic objects
- * @param valuesNumber number of objects to create
- * @return the sample List
- */
- private List fillSampleValuesList(int valuesNumber) {
- List sampleValues = new LinkedList();
- for(int i=0; i<valuesNumber;i++)
- sampleValues.add(new Object());
- return sampleValues;
- }
-
- /**
- * Create a sample MultiValueTable
- * @param keyNumber the number of key to insert in the MultiValueTable
- * @param maxValueNumber the maximum number of value for each key
- * @param isRandom true if the maxValueNumber is an upper bound, false
if it is the actual value
- * @return the sample MultiValueTable created
- */
- private MultiValueTable createSampleMultiValueTable(int keyNumber, int
maxValueNumber, boolean isRandom) {
- Object[][] sampleObjects =
createSampleKeyMultiVal(keyNumber,maxValueNumber,isRandom);
- return fillMultiValueTable(sampleObjects);
- }
-
- /**
- * Given an Enumeration it returns the number of present objects
- * @param anEnumeration
- * @return the number of present objects
- */
- private int enumerationSize(Enumeration anEnumeration) {
- int counter = 0;
- while(anEnumeration.hasMoreElements()) {
- anEnumeration.nextElement();
- counter++;}
- return counter;
- }
-
- /**
- * Fill a new MultiValueTable from a Object[][] provided.
- * The Object[][] must be in the same form generated by
- * createSampleKeyMultiVal method.
- * @param sampleObjects Object[][] array, with [i][0] as key and [i][1]
as list of values
- * @return the created MultiValueTable
- */
- private MultiValueTable fillMultiValueTable(Object[][] sampleObjects) {
- MultiValueTable methodMVTable = new MultiValueTable();
- Iterator itr;
- for(int i=0;i<sampleKeyNumber;i++) {
- itr = ((List)(sampleObjects[i][1])).iterator();
- while( itr.hasNext())
- methodMVTable.put(sampleObjects[i][0],
itr.next());
- }
- return methodMVTable;
- }
-
- /**
- * Tests if there are problems when
- * putting values in a sample
- * MultiValueTable
- */
- public void testPut() {
- assertNotNull(
-
createSampleMultiValueTable(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom));
- }
-
- /**
- * Tests get(Object) method with both
- * present keys and not present
- */
- public void testGet() {
- MultiValueTable methodMVTable = new MultiValueTable();
- assertNull(methodMVTable.get(new Object()));
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- methodMVTable = fillMultiValueTable(sampleObjects);
- for(int i=0;i<sampleObjects.length;i++)
-
assertEquals(methodMVTable.get(sampleObjects[i][0]),((List)sampleObjects[i][1]).get(0));
- }
-
- /**
- * Tests containsKey(Object) method verifying
- * if all keys inserted are correctly found.
- * It verifies the correct behavior with empty
- * MultiValueTable and not present keys, too.
- */
- public void testContainsKey() {
- MultiValueTable methodMVTable = new MultiValueTable();
- assertFalse(methodMVTable.containsKey(new Object()));
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- methodMVTable = fillMultiValueTable(sampleObjects);
- for(int i=0;i<sampleObjects.length;i++)
-
assertTrue(methodMVTable.containsKey(sampleObjects[i][0]));
- assertFalse(methodMVTable.containsKey(new Object()));
- }
-
- /**
- * Tests containsElement(Object,Object) method
- * verifying if all values inserted are correctly
- * found.
- * It verifies the correct behavior with empty
- * MultiValueTable and not present Elements, too.
- */
- public void testContainsElement() {
- MultiValueTable methodMVTable = new MultiValueTable();
- assertFalse(methodMVTable.containsElement(new Object(),new
Object()));
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- methodMVTable = fillMultiValueTable(sampleObjects);
- Iterator iter;
- for(int i=0;i<sampleObjects.length;i++) {
- iter = ((List)(sampleObjects[i][1])).iterator();
-
assertFalse(methodMVTable.containsElement(sampleObjects[i][0],new Object()));
- while(iter.hasNext())
-
assertTrue(methodMVTable.containsElement(sampleObjects[i][0],iter.next()));
- }
- }
-
- /**
- * Tests getAll() method
- */
- public void testGetAll() {
- MultiValueTable methodMVTable = new MultiValueTable();
- //TODO: verifies if an Exception is necessary
- methodMVTable.getAll(new Object());
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- methodMVTable = fillMultiValueTable(sampleObjects);
- Iterator iter;
- Enumeration methodEnumeration;
- for(int i=0;i<sampleObjects.length;i++) {
- iter = ((List)(sampleObjects[i][1])).iterator();
- methodEnumeration =
methodMVTable.getAll(sampleObjects[i][0]);
- while(iter.hasNext())
-
assertEquals(methodEnumeration.nextElement(),iter.next());
- }
- }
-
- /**
- * Tests countAll() method
- */
- public void testCountAll() {
- MultiValueTable methodMVTable = new MultiValueTable();
- assertEquals(methodMVTable.countAll(new Object()),0);
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- methodMVTable = fillMultiValueTable(sampleObjects);
- for(int i=0;i<sampleObjects.length;i++)
-
assertEquals(((List)(sampleObjects[i][1])).size(),methodMVTable.countAll(sampleObjects[i][0]));
- }
-
- /**
- * Tests getSync(Object) method fetching
- * both present and not present keys
- */
- public void testGetSync() {
- MultiValueTable methodMVTable = new MultiValueTable();
- assertNull(methodMVTable.getSync(new Object()));
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- methodMVTable = fillMultiValueTable(sampleObjects);
- for(int i=0;i<sampleObjects.length;i++)
-
assertEquals(methodMVTable.getSync(sampleObjects[i][0]),((List)sampleObjects[i][1]));
- }
-
- /**
- * Tests getArray(Object) method both
- * with a present key and a not present key
- */
- public void testGetArray() {
- MultiValueTable methodMVTable = new MultiValueTable();
- assertNull(methodMVTable.getArray(new Object()));
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- methodMVTable = fillMultiValueTable(sampleObjects);
- for(int i=0;i<sampleObjects.length;i++)
-
assertTrue(Arrays.equals(((List)(sampleObjects[i][1])).toArray(),methodMVTable.getArray(sampleObjects[i][0])));
- }
-
- /**
- * Tests remove(Object) method trying
- * to remove all keys inserted in a MultiValueTable.
- * It verifies the behavior when removing a not present
- * key, too.
- */
- public void testRemove() {
- MultiValueTable methodMVTable = new MultiValueTable();
- //TODO: shouldn't it raise an exception?
- methodMVTable.remove(new Object());
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- methodMVTable = fillMultiValueTable(sampleObjects);
- for(int i=0;i<sampleObjects.length;i++)
- methodMVTable.remove(sampleObjects[i][0]);
- assertTrue(methodMVTable.isEmpty());
- }
-
- /**
- * Tests isEmpty() method with an empty MultiValueTable,
- * after putting objects and after removing all of them.
- */
- public void testIsEmpty() {
- MultiValueTable methodMVTable = new MultiValueTable();
- assertTrue(methodMVTable.isEmpty());
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- methodMVTable = fillMultiValueTable(sampleObjects);
- assertFalse(methodMVTable.isEmpty());
- for(int i=0;i<sampleObjects.length;i++)
- methodMVTable.remove(sampleObjects[i][0]);
- assertTrue(methodMVTable.isEmpty());
- }
-
- /**
- * Tests clear() method filling a MultiValueTable
- * and verifying if all keys are correctly removed.
- * Finally it verifies the result of isEmpty() method.
- */
- public void testClear() {
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- MultiValueTable methodMVTable =
fillMultiValueTable(sampleObjects);
- methodMVTable.clear();
- for(int i=0;i<sampleObjects.length;i++)
-
assertFalse(methodMVTable.containsKey(sampleObjects[i][0]));
- assertTrue(methodMVTable.isEmpty());
- }
-
- /**
- * Tests removeElement(Object,Object) removing all elements from
- * a sample MultiValueTable, and verifying if they are correctly
- * removed and if the result of isEmpty() method is correct.
- */
- public void testRemoveElement() {
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- MultiValueTable methodMVTable =
fillMultiValueTable(sampleObjects);
- Object methodValue;
- Iterator iter;
- for(int i=0;i<sampleObjects.length;i++) {
- iter = ((List)(sampleObjects[i][1])).iterator();
-
assertFalse(methodMVTable.removeElement(sampleObjects[i][0],new Object()));
- while(iter.hasNext()) {
- methodValue = iter.next();
-
assertTrue(methodMVTable.removeElement(sampleObjects[i][0],methodValue));
-
assertFalse(methodMVTable.containsElement(sampleObjects[i][0],methodValue));
- }
- }
- assertTrue(methodMVTable.isEmpty());
- }
-
- /**
- * Tests keys() method verifying if all keys inserted are
- * correctly present in the resulting Enumeration
- */
- public void testKeys() {
- Object[][] sampleObjects =
-
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
- MultiValueTable methodMVTable =
fillMultiValueTable(sampleObjects);
- //TODO: shouldn't it respect keys order?
- int j = sampleObjects.length-1;
- Enumeration methodEnumeration = methodMVTable.keys();
- while(methodEnumeration.hasMoreElements()) {
-
assertEquals(sampleObjects[j][0],methodEnumeration.nextElement());
- j--;}
- }
-
- /**
- * Tests elements() and keys() method
- * verifying their behavior when putting the same
- * value for different keys.
- */
- public void testDifferentKeysSameElement() {
- int keysNumber = 2;
- MultiValueTable methodMVTable = new MultiValueTable();
- String sampleValue = "sampleValue";
- //putting the same value for different keys
- for(int i=0;i<keysNumber;i++)
- methodMVTable.put(new Object(),sampleValue);
-
- assertEquals(enumerationSize(methodMVTable.elements()),1);
- assertEquals(enumerationSize(methodMVTable.keys()),keysNumber);
- }
-
-}
Copied: branches/freenet-jfk/test/freenet/support/MultiValueTableTest.java
(from rev 14796, trunk/freenet/test/freenet/support/MultiValueTableTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/MultiValueTableTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/MultiValueTableTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,345 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.MultiValueTable} class.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class MultiValueTableTest extends TestCase {
+
+ private final int sampleKeyNumber = 100;
+ private final int sampleMaxValueNumber = 3;
+ private final boolean sampleIsRandom = true;
+
+ /**
+ * Create a Object[][] filled with increasing Integers as keys
+ * and a List of generic Objects as values.
+ * @param keysNumber the number of keys to create
+ * @param valueNumber the maximum value number per key
+ * @param isRandom if true each key could have [1,valuesNumber] values
+ * chosen randomly, if false each key will have valuesNumber values
+ * @return the Object[][] created
+ */
+ private Object[][] createSampleKeyMultiVal(int keysNumber, int
valuesNumber, boolean isRandom) {
+ Object[][] sampleObjects = new Object[keysNumber][valuesNumber];
+ int methodValuesNumber = valuesNumber;
+ Random rnd = new Random();
+ for (int i=0; i<sampleObjects.length;i++) {
+ if (isRandom)
+ methodValuesNumber =
1+rnd.nextInt(valuesNumber);
+ sampleObjects[i][0] = new Integer(i);
+ sampleObjects[i][1] =
fillSampleValuesList(methodValuesNumber); }
+ return sampleObjects;
+ }
+
+ /**
+ * Create a sample List filled
+ * with the specified number of
+ * generic objects
+ * @param valuesNumber number of objects to create
+ * @return the sample List
+ */
+ private List fillSampleValuesList(int valuesNumber) {
+ List sampleValues = new LinkedList();
+ for(int i=0; i<valuesNumber;i++)
+ sampleValues.add(new Object());
+ return sampleValues;
+ }
+
+ /**
+ * Create a sample MultiValueTable
+ * @param keyNumber the number of key to insert in the MultiValueTable
+ * @param maxValueNumber the maximum number of value for each key
+ * @param isRandom true if the maxValueNumber is an upper bound, false
if it is the actual value
+ * @return the sample MultiValueTable created
+ */
+ private MultiValueTable createSampleMultiValueTable(int keyNumber, int
maxValueNumber, boolean isRandom) {
+ Object[][] sampleObjects =
createSampleKeyMultiVal(keyNumber,maxValueNumber,isRandom);
+ return fillMultiValueTable(sampleObjects);
+ }
+
+ /**
+ * Given an Enumeration it returns the number of present objects
+ * @param anEnumeration
+ * @return the number of present objects
+ */
+ private int enumerationSize(Enumeration anEnumeration) {
+ int counter = 0;
+ while(anEnumeration.hasMoreElements()) {
+ anEnumeration.nextElement();
+ counter++;}
+ return counter;
+ }
+
+ /**
+ * Fill a new MultiValueTable from a Object[][] provided.
+ * The Object[][] must be in the same form generated by
+ * createSampleKeyMultiVal method.
+ * @param sampleObjects Object[][] array, with [i][0] as key and [i][1]
as list of values
+ * @return the created MultiValueTable
+ */
+ private MultiValueTable fillMultiValueTable(Object[][] sampleObjects) {
+ MultiValueTable methodMVTable = new MultiValueTable();
+ Iterator itr;
+ for(int i=0;i<sampleKeyNumber;i++) {
+ itr = ((List)(sampleObjects[i][1])).iterator();
+ while( itr.hasNext())
+ methodMVTable.put(sampleObjects[i][0],
itr.next());
+ }
+ return methodMVTable;
+ }
+
+ /**
+ * Tests if there are problems when
+ * putting values in a sample
+ * MultiValueTable
+ */
+ public void testPut() {
+ assertNotNull(
+
createSampleMultiValueTable(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom));
+ }
+
+ /**
+ * Tests get(Object) method with both
+ * present keys and not present
+ */
+ public void testGet() {
+ MultiValueTable methodMVTable = new MultiValueTable();
+ assertNull(methodMVTable.get(new Object()));
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ methodMVTable = fillMultiValueTable(sampleObjects);
+ for(int i=0;i<sampleObjects.length;i++)
+
assertEquals(methodMVTable.get(sampleObjects[i][0]),((List)sampleObjects[i][1]).get(0));
+ }
+
+ /**
+ * Tests containsKey(Object) method verifying
+ * if all keys inserted are correctly found.
+ * It verifies the correct behavior with empty
+ * MultiValueTable and not present keys, too.
+ */
+ public void testContainsKey() {
+ MultiValueTable methodMVTable = new MultiValueTable();
+ assertFalse(methodMVTable.containsKey(new Object()));
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ methodMVTable = fillMultiValueTable(sampleObjects);
+ for(int i=0;i<sampleObjects.length;i++)
+
assertTrue(methodMVTable.containsKey(sampleObjects[i][0]));
+ assertFalse(methodMVTable.containsKey(new Object()));
+ }
+
+ /**
+ * Tests containsElement(Object,Object) method
+ * verifying if all values inserted are correctly
+ * found.
+ * It verifies the correct behavior with empty
+ * MultiValueTable and not present Elements, too.
+ */
+ public void testContainsElement() {
+ MultiValueTable methodMVTable = new MultiValueTable();
+ assertFalse(methodMVTable.containsElement(new Object(),new
Object()));
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ methodMVTable = fillMultiValueTable(sampleObjects);
+ Iterator iter;
+ for(int i=0;i<sampleObjects.length;i++) {
+ iter = ((List)(sampleObjects[i][1])).iterator();
+
assertFalse(methodMVTable.containsElement(sampleObjects[i][0],new Object()));
+ while(iter.hasNext())
+
assertTrue(methodMVTable.containsElement(sampleObjects[i][0],iter.next()));
+ }
+ }
+
+ /**
+ * Tests getAll() method
+ */
+ public void testGetAll() {
+ MultiValueTable methodMVTable = new MultiValueTable();
+ //TODO: verifies if an Exception is necessary
+ methodMVTable.getAll(new Object());
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ methodMVTable = fillMultiValueTable(sampleObjects);
+ Iterator iter;
+ Enumeration methodEnumeration;
+ for(int i=0;i<sampleObjects.length;i++) {
+ iter = ((List)(sampleObjects[i][1])).iterator();
+ methodEnumeration =
methodMVTable.getAll(sampleObjects[i][0]);
+ while(iter.hasNext())
+
assertEquals(methodEnumeration.nextElement(),iter.next());
+ }
+ }
+
+ /**
+ * Tests countAll() method
+ */
+ public void testCountAll() {
+ MultiValueTable methodMVTable = new MultiValueTable();
+ assertEquals(methodMVTable.countAll(new Object()),0);
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ methodMVTable = fillMultiValueTable(sampleObjects);
+ for(int i=0;i<sampleObjects.length;i++)
+
assertEquals(((List)(sampleObjects[i][1])).size(),methodMVTable.countAll(sampleObjects[i][0]));
+ }
+
+ /**
+ * Tests getSync(Object) method fetching
+ * both present and not present keys
+ */
+ public void testGetSync() {
+ MultiValueTable methodMVTable = new MultiValueTable();
+ assertNull(methodMVTable.getSync(new Object()));
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ methodMVTable = fillMultiValueTable(sampleObjects);
+ for(int i=0;i<sampleObjects.length;i++)
+
assertEquals(methodMVTable.getSync(sampleObjects[i][0]),((List)sampleObjects[i][1]));
+ }
+
+ /**
+ * Tests getArray(Object) method both
+ * with a present key and a not present key
+ */
+ public void testGetArray() {
+ MultiValueTable methodMVTable = new MultiValueTable();
+ assertNull(methodMVTable.getArray(new Object()));
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ methodMVTable = fillMultiValueTable(sampleObjects);
+ for(int i=0;i<sampleObjects.length;i++)
+
assertTrue(Arrays.equals(((List)(sampleObjects[i][1])).toArray(),methodMVTable.getArray(sampleObjects[i][0])));
+ }
+
+ /**
+ * Tests remove(Object) method trying
+ * to remove all keys inserted in a MultiValueTable.
+ * It verifies the behavior when removing a not present
+ * key, too.
+ */
+ public void testRemove() {
+ MultiValueTable methodMVTable = new MultiValueTable();
+ //TODO: shouldn't it raise an exception?
+ methodMVTable.remove(new Object());
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ methodMVTable = fillMultiValueTable(sampleObjects);
+ for(int i=0;i<sampleObjects.length;i++)
+ methodMVTable.remove(sampleObjects[i][0]);
+ assertTrue(methodMVTable.isEmpty());
+ }
+
+ /**
+ * Tests isEmpty() method with an empty MultiValueTable,
+ * after putting objects and after removing all of them.
+ */
+ public void testIsEmpty() {
+ MultiValueTable methodMVTable = new MultiValueTable();
+ assertTrue(methodMVTable.isEmpty());
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ methodMVTable = fillMultiValueTable(sampleObjects);
+ assertFalse(methodMVTable.isEmpty());
+ for(int i=0;i<sampleObjects.length;i++)
+ methodMVTable.remove(sampleObjects[i][0]);
+ assertTrue(methodMVTable.isEmpty());
+ }
+
+ /**
+ * Tests clear() method filling a MultiValueTable
+ * and verifying if all keys are correctly removed.
+ * Finally it verifies the result of isEmpty() method.
+ */
+ public void testClear() {
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ MultiValueTable methodMVTable =
fillMultiValueTable(sampleObjects);
+ methodMVTable.clear();
+ for(int i=0;i<sampleObjects.length;i++)
+
assertFalse(methodMVTable.containsKey(sampleObjects[i][0]));
+ assertTrue(methodMVTable.isEmpty());
+ }
+
+ /**
+ * Tests removeElement(Object,Object) removing all elements from
+ * a sample MultiValueTable, and verifying if they are correctly
+ * removed and if the result of isEmpty() method is correct.
+ */
+ public void testRemoveElement() {
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ MultiValueTable methodMVTable =
fillMultiValueTable(sampleObjects);
+ Object methodValue;
+ Iterator iter;
+ for(int i=0;i<sampleObjects.length;i++) {
+ iter = ((List)(sampleObjects[i][1])).iterator();
+
assertFalse(methodMVTable.removeElement(sampleObjects[i][0],new Object()));
+ while(iter.hasNext()) {
+ methodValue = iter.next();
+
assertTrue(methodMVTable.removeElement(sampleObjects[i][0],methodValue));
+
assertFalse(methodMVTable.containsElement(sampleObjects[i][0],methodValue));
+ }
+ }
+ assertTrue(methodMVTable.isEmpty());
+ }
+
+ /**
+ * Tests keys() method verifying if all keys inserted are
+ * correctly present in the resulting Enumeration
+ */
+ public void testKeys() {
+ Object[][] sampleObjects =
+
createSampleKeyMultiVal(sampleKeyNumber,sampleMaxValueNumber,sampleIsRandom);
+ MultiValueTable methodMVTable =
fillMultiValueTable(sampleObjects);
+ //TODO: shouldn't it respect keys order?
+ int j = sampleObjects.length-1;
+ Enumeration methodEnumeration = methodMVTable.keys();
+ while(methodEnumeration.hasMoreElements()) {
+
assertEquals(sampleObjects[j][0],methodEnumeration.nextElement());
+ j--;}
+ }
+
+ /**
+ * Tests elements() and keys() method
+ * verifying their behavior when putting the same
+ * value for different keys.
+ */
+ public void testDifferentKeysSameElement() {
+ int keysNumber = 2;
+ MultiValueTable methodMVTable = new MultiValueTable();
+ String sampleValue = "sampleValue";
+ //putting the same value for different keys
+ for(int i=0;i<keysNumber;i++)
+ methodMVTable.put(new Object(),sampleValue);
+
+ assertEquals(enumerationSize(methodMVTable.elements()),1);
+ assertEquals(enumerationSize(methodMVTable.keys()),keysNumber);
+ }
+
+}
Deleted: branches/freenet-jfk/test/freenet/support/SimpleFieldSetTest.java
===================================================================
--- trunk/freenet/test/freenet/support/SimpleFieldSetTest.java 2007-08-18
19:36:17 UTC (rev 14796)
+++ branches/freenet-jfk/test/freenet/support/SimpleFieldSetTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,701 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-package freenet.support;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.Arrays;
-import java.util.Iterator;
-
-import freenet.node.FSParseException;
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.SimpleFieldSet} class.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class SimpleFieldSetTest extends TestCase {
-
- private static final char KEY_VALUE_SEPARATOR = '=';
-
- /* A double string array used across all tests
- * it must not be changed in order to perform tests
- * correctly */
- private static final String[][] SAMPLE_STRING_PAIRS = {
- //directSubset
- {"foo","bar"},
- {"foo.bar","foobar"},
- {"foo.bar.boo.far","foobar"},
- {"foo2","foobar.fooboo.foofar.foofoo"},
- {"foo3",KEY_VALUE_SEPARATOR+"bar"} };
-
- private static final String SAMPLE_END_MARKER = "END";
-
- /**
- * Tests putSingle(String,String) method
- * trying to store a key with two paired
- * multi_level_chars (i.e. "..").
- */
- public void
testSimpleFieldSetPutSingle_StringString_WithTwoPairedMultiLevelChars() {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- String methodKey = "foo..bar.";
- String methodValue = "foobar";
- methodSFS.putSingle(methodKey,methodValue);
-
assertEquals(methodSFS.subset("foo").subset("").subset("bar").get(""),methodValue);
- assertEquals(methodSFS.get(methodKey),methodValue);
- }
-
- /**
- * Tests putAppend(String,String) method
- * trying to store a key with two paired
- * multi_level_chars (i.e. "..").
- */
- public void
testSimpleFieldSetPutAppend_StringString_WithTwoPairedMultiLevelChars() {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- String methodKey = "foo..bar";
- String methodValue = "foobar";
- methodSFS.putAppend(methodKey,methodValue);
- assertEquals(methodSFS.get(methodKey),methodValue);
- }
-
- /**
- * Tests put() and get() methods
- * using a normal Map behaviour
- * and without MULTI_LEVEL_CHARs
- */
- public void testSimpleFieldSetPutAndGet_NoMultiLevel(){
- String[][] methodPairsArray = {
-
{"A","a"},{"B","b"},{"C","c"},{"D","d"},{"E","e"},{"F","f"} };
- assertTrue(checkPutAndGetPairs(methodPairsArray));
- }
-
- /**
- * Tests put() and get() methods
- * using a normal Map behaviour
- * and with MULTI_LEVEL_CHARs
- */
- public void testSimpleFieldSetPutAndGet_MultiLevel(){
- String[][] methodPairsArray_DoubleLevel = {
- {"A.A","aa"},
- {"A.B","ab"},
- {"A.C","ac"},
- {"A.D","ad"},
- {"A.E","ae"},
- {"A.F","af"} };
- String[][] methodPairsArray_MultiLevel = {
- {"A.A.A.A","aa"},
- {"A.B.A","ab"},
- {"A.C.Cc","ac"},
- {"A.D.F","ad"},
- {"A.E.G","ae"},
- {"A.F.J.II.UI.BOO","af"} };
- assertTrue(checkPutAndGetPairs(methodPairsArray_DoubleLevel));
- assertTrue(checkPutAndGetPairs(methodPairsArray_MultiLevel));
- }
-
-
- /**
- * It puts key-value pairs in a SimpleFieldSet
- * and verify if it can do the correspondant
- * get correctly.
- * @param aPairsArray
- * @return true if it is correct
- */
- private boolean checkPutAndGetPairs(String[][] aPairsArray) {
- boolean retValue = true;
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- //putting values
- for (int i = 0; i < aPairsArray.length; i++)
- methodSFS.putSingle(aPairsArray[i][0],
aPairsArray[i][1]);
- for (int i = 0; i < aPairsArray.length; i++)
//getting values
- retValue &=
methodSFS.get(aPairsArray[i][0]).equals(aPairsArray[i][1]);
- retValue &= checkSimpleFieldSetSize(methodSFS,
aPairsArray.length);
- return retValue;
- }
-
- /**
- * Tests subset(String) method
- * putting two levels keys and
- * fetching it through subset() method
- * on the first level and then get()
- * on the second
- */
- public void testSimpleFieldSetSubset_String() {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- String[][] methodPairsArray_MultiLevel = {
- {"A","A","aa"},
- {"A","B","ab"},
- {"A","C","ac"},
- {"A","D","ad"},
- {"A","E","ae"},
- {"A","F","af"} };
- //putting values
- for (int i = 0; i < methodPairsArray_MultiLevel.length; i++)
- methodSFS.putSingle(methodPairsArray_MultiLevel[i][0]
- + SimpleFieldSet.MULTI_LEVEL_CHAR
- +
methodPairsArray_MultiLevel[i][1],
- methodPairsArray_MultiLevel[i][2]);
- //getting subsets and then values
- for (int i = 0; i < methodPairsArray_MultiLevel.length; i++)
- assertEquals(
- methodSFS.subset(
-
methodPairsArray_MultiLevel[i][0]).get(methodPairsArray_MultiLevel[i][1]),
- methodPairsArray_MultiLevel[i][2]);
-
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray_MultiLevel.length));
- }
-
- /**
- * Tests putAllOverwrite(SimpleFieldSet) method
- * trying to overwrite a whole SimpleFieldSet
- * with another with same keys but different
- * values
- */
- public void testPutAllOverwrite() {
- String methodAppendedString = "buu";
- SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
- SimpleFieldSet methodNewSFS =
this.sfsFromStringPairs(methodAppendedString);
- methodSFS.putAllOverwrite(methodNewSFS);
- for (int i=0; i < SAMPLE_STRING_PAIRS.length; i++)
- assertEquals(methodSFS.get(SAMPLE_STRING_PAIRS[i][0]),
-
SAMPLE_STRING_PAIRS[i][1]+methodAppendedString);
- }
-
- /**
- * Tests put(String,SimpleFieldSet) method
- */
- public void testPut_StringSimpleFieldSet() {
- String methodKey = "prefix";
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- methodSFS.put(methodKey,sfsFromSampleStringPairs());
- for (int i=0; i < SAMPLE_STRING_PAIRS.length; i++)
- assertEquals(
-
methodSFS.get(methodKey+SimpleFieldSet.MULTI_LEVEL_CHAR+SAMPLE_STRING_PAIRS[i][0]),
- SAMPLE_STRING_PAIRS[i][1]);
- }
-
- /**
- * Tests put(String,SimpleFieldSet) method
- */
- public void testTPut_StringSimpleFieldSet() {
- String methodKey = "prefix";
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- methodSFS.tput(methodKey,sfsFromSampleStringPairs());
- for (int i=0; i < SAMPLE_STRING_PAIRS.length; i++)
-
assertEquals(methodSFS.get(methodKey+SimpleFieldSet.MULTI_LEVEL_CHAR+SAMPLE_STRING_PAIRS[i][0]),
- SAMPLE_STRING_PAIRS[i][1]);
- }
-
- /**
- * Tests put(String,SimpleFieldSet) and
- * tput(String,SimpleFieldSet) trying to
- * add empty data structures
- */
- public void testPutAndTPut_WithEmpty() {
- SimpleFieldSet methodEmptySFS = new SimpleFieldSet(true);
- SimpleFieldSet methodSampleSFS = sfsFromSampleStringPairs();
- try {
- methodSampleSFS.put("sample",methodEmptySFS);
- fail("Expected Exception Error Not Thrown!"); }
- catch (IllegalArgumentException anException) {
- assertNotNull(anException); }
- try {
- methodSampleSFS.tput("sample",methodSampleSFS); }
- catch (IllegalArgumentException aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
-
- /**
- * It creates a SFS from the SAMPLE_STRING_PAIRS
- * and putting a suffix after every value
- * @param aSuffix to put after every value
- * @return the SimpleFieldSet created
- */
- private SimpleFieldSet sfsFromStringPairs(String aSuffix) {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- //creating new
- for (int i = 0; i < SAMPLE_STRING_PAIRS.length; i++)
- methodSFS.putSingle(SAMPLE_STRING_PAIRS[i][0],
- SAMPLE_STRING_PAIRS[i][1]+aSuffix);
- return methodSFS;
- }
-
- /**
- * Tests put(String,boolean) and getBoolean(String,boolean)
- * methods consistency.
- * The default value (returned if the key is not found) is set to
"false"
- * and the real value is always set to "true", so
- * we are sure if it finds the right value or not
- * (and does not use the default).
- */
- public void testPut_StringBoolean() {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- int length = 15;
- for(int i = 0; i < length; i++)
- methodSFS.put(Integer.toString(i),true);
- for (int i = 0; i < length; i++)
-
assertEquals(methodSFS.getBoolean(Integer.toString(i),false),true);
- assertTrue(checkSimpleFieldSetSize(methodSFS,length));
- }
-
-
- /**
- * Checks if the provided SimpleFieldSet
- * has the right size
- * @param aSimpleFieldSet
- * @param expectedSize
- * @return true if the size is the expected
- */
- private boolean checkSimpleFieldSetSize(SimpleFieldSet aSimpleFieldSet,
int expectedSize) {
- int actualSize = 0;
- Iterator methodKeyIterator = aSimpleFieldSet.keyIterator();
- while (methodKeyIterator.hasNext()) {
- methodKeyIterator.next();
- actualSize++; }
- return expectedSize == actualSize;
- }
-
- /**
- * Tests put(String,int) and
- * [getInt(String),getInt(String,int)]
- * methods consistency.
- * The default value (returned if the key is not found)
- * is set to a not present int value, so we are sure
- * if it finds the right value or not
- * (and does not use the default).
- */
- public void testPut_StringInt() {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- int[][] methodPairsArray =
- { {1,1},{2,2},{3,3},{4,4} };
- for (int i = 0; i < methodPairsArray.length; i++)
- methodSFS.put(Integer.toString(methodPairsArray[i][0]),
methodPairsArray[i][1]);
-
-
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray.length));
-
- for (int i = 0; i < methodPairsArray.length; i++) {
- try {
-
assertEquals(methodSFS.getInt(Integer.toString(methodPairsArray[i][0])),
- methodPairsArray[i][1]);
-
assertEquals(methodSFS.getInt(Integer.toString(methodPairsArray[i][0]),5),
- methodPairsArray[i][1]);
- } catch (FSParseException aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
- }
-
- /**
- * Tests put(String,long) and
- * [getLong(String),getLong(String,long)]
- * methods consistency.
- * The default value (returned if the key is not found)
- * is set to a not present long value, so we are sure
- * if it finds the right value or not
- * (and does not use the default).
- */
- public void testPut_StringLong() {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- long[][] methodPairsArray =
- { {1,1},{2,2},{3,3},{4,4} };
- for (int i = 0; i < methodPairsArray.length; i++)
- methodSFS.put(Long.toString(methodPairsArray[i][0]),
methodPairsArray[i][1]);
-
-
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray.length));
-
- for (int i = 0; i < methodPairsArray.length; i++) {
- try {
-
assertEquals(methodSFS.getLong(Long.toString(methodPairsArray[i][0])),
- methodPairsArray[i][1]);
-
assertEquals(methodSFS.getLong(Long.toString(methodPairsArray[i][0]),5),
- methodPairsArray[i][1]);
- } catch (FSParseException aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
- }
-
- /**
- * Tests put(String,char) and
- * [getChar(String),getChar(String,char)]
- * methods consistency.
- * The default value (returned if the key is not found)
- * is set to a not present char value, so we are sure
- * if it finds the right value or not
- * (and does not use the default).
- */
- public void testPut_StringChar() {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- char[][] methodPairsArray =
- { {'1','1'},{'2','2'},{'3','3'},{'4','4'} };
- for (int i = 0; i < methodPairsArray.length; i++)
- methodSFS.put(String.valueOf(methodPairsArray[i][0]),
methodPairsArray[i][1]);
-
-
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray.length));
-
- for (int i = 0; i < methodPairsArray.length; i++) {
- try {
-
assertEquals(methodSFS.getChar(String.valueOf(methodPairsArray[i][0])),
- methodPairsArray[i][1]);
-
assertEquals(methodSFS.getChar(String.valueOf(methodPairsArray[i][0]),'5'),
- methodPairsArray[i][1]);
- } catch (FSParseException aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
- }
-
- /**
- * Tests put(String,short) and
- * [getShort(String)|getShort(String,short)]
- * methods consistency.
- * The default value (returned if the key is not found)
- * is set to a not present short value, so we are sure
- * if it finds the right value or not
- * (and does not use the default).
- */
- public void testPut_StringShort() {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- short[][] methodPairsArray =
- { {1,1},{2,2},{3,3},{4,4} };
- for (int i = 0; i < methodPairsArray.length; i++)
- methodSFS.put(Short.toString(methodPairsArray[i][0]),
methodPairsArray[i][1]);
-
-
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray.length));
-
- for (int i = 0; i < methodPairsArray.length; i++) {
- try {
-
assertEquals(methodSFS.getShort(Short.toString(methodPairsArray[i][0])),
- methodPairsArray[i][1]);
-
assertEquals(methodSFS.getShort(Short.toString(methodPairsArray[i][0]),(short)5),
- methodPairsArray[i][1]);
- } catch (FSParseException aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
- }
-
- /**
- * Tests put(String,double) and
- * [getDouble(String)|getDouble(String,double)]
- * methods consistency.
- * The default value (returned if the key is not found)
- * is set to a not present double value, so we are sure
- * if it finds the right value or not
- * (and does not use the default).
- */
- public void testPut_StringDouble() {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- double[][] methodPairsArray =
- { {1,1},{2,2},{3,3},{4,4} };
- for (int i = 0; i < methodPairsArray.length; i++)
- methodSFS.put(Double.toString(methodPairsArray[i][0]),
methodPairsArray[i][1]);
-
-
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray.length));
-
- for (int i = 0; i < methodPairsArray.length; i++) {
- try {
- //there is no assertEquals(Double,Double) so we
are obliged to do this way -_-
- assertEquals(
-
Double.compare((methodSFS.getDouble(Double.toString(methodPairsArray[i][0]))),
-
methodPairsArray[i][1]),0);
- assertEquals(
-
Double.compare(methodSFS.getDouble(Double.toString(methodPairsArray[i][0]),(double)5),
-
methodPairsArray[i][1]),0);
- } catch (FSParseException aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
- }
-
- /**
- * Generates a string for the SFS parser in the canonical form:
- * key=value
- * END
- * @param aStringPairsArray
- * @return a String ready to be read by a SFS parser
- */
- private String sfsReadyString(String[][] aStringPairsArray) {
-
- String methodStringToReturn = "";
- for(int i = 0; i < aStringPairsArray.length; i++)
- methodStringToReturn +=
aStringPairsArray[i][0]+KEY_VALUE_SEPARATOR+aStringPairsArray[i][1]+'\n';
- methodStringToReturn += SAMPLE_END_MARKER;
- return methodStringToReturn;
- }
-
- /**
- * Tests SimpleFieldSet(String,boolean,boolean) constructor,
- * with simple and border cases of the canonical form.
- */
- public void testSimpleFieldSet_StringBooleanBoolean() {
- String[][] methodStringPairs = SAMPLE_STRING_PAIRS;
- String methodStringToParse = sfsReadyString(methodStringPairs);
- try {
- SimpleFieldSet methodSFS = new
SimpleFieldSet(methodStringToParse,false,false);
- for (int i=0; i < methodStringPairs.length; i++)
-
assertEquals(methodSFS.get(methodStringPairs[i][0]),
- methodStringPairs[i][1]);
- } catch (IOException aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
-
- /**
- * Tests SimpleFieldSet(BufferedReader,boolean,boolean) constructor,
- * with simple and border cases of the canonical form.
- */
- public void testSimpleFieldSet_BufferedReaderBooleanBoolean() {
- String[][] methodStringPairs = SAMPLE_STRING_PAIRS;
- BufferedReader methodBufferedReader =
- new BufferedReader(new
StringReader(sfsReadyString(methodStringPairs)));
- try {
- SimpleFieldSet methodSFS = new
SimpleFieldSet(methodBufferedReader,false,false);
- for (int i=0; i < methodStringPairs.length; i++)
-
assertEquals(methodSFS.get(methodStringPairs[i][0]),
- methodStringPairs[i][1]);
- } catch (IOException aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
-
- /**
- * Generates a SimpleFieldSet using the
- * SAMPLE_STRING_PAIRS and sfs put method
- * @return a SimpleFieldSet
- */
- private SimpleFieldSet sfsFromSampleStringPairs() {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- for (int i = 0; i < SAMPLE_STRING_PAIRS.length; i++)
- methodSFS.putSingle(SAMPLE_STRING_PAIRS[i][0],
- SAMPLE_STRING_PAIRS[i][1]);
- assertTrue(checkSimpleFieldSetSize(methodSFS,
- SAMPLE_STRING_PAIRS.length));
- return methodSFS;
- }
-
- /**
- * Tests SimpleFieldSet(SimpleFieldSet) constructor,
- * with simple and border cases of the canonical form.
- */
- public void testSimpleFieldSet_SimpleFieldSet() {
- SimpleFieldSet methodSFS = new
SimpleFieldSet(sfsFromSampleStringPairs());
- String[][] methodStringPairs = SAMPLE_STRING_PAIRS;
- for (int i=0; i < methodStringPairs.length; i++)
- assertEquals(methodSFS.get(methodStringPairs[i][0]),
- methodStringPairs[i][1]);
- }
-
- /**
- * Tests {get,set}EndMarker(String) methods
- * using them after a String parsing
- */
- public void testEndMarker() {
- String methodEndMarker = "ANOTHER-ENDING";
- String methodStringToParse =
sfsReadyString(SAMPLE_STRING_PAIRS);
- try {
- SimpleFieldSet methodSFS = new
SimpleFieldSet(methodStringToParse,false,false);
-
assertEquals(methodSFS.getEndMarker(),SAMPLE_END_MARKER);
- methodSFS.setEndMarker(methodEndMarker);
- assertEquals(methodSFS.getEndMarker(),methodEndMarker);
- } catch (IOException aException) {
- fail("Not expected exception thrown : " +
aException.getMessage()); }
- }
-
- /**
- * Tests isEmpty() method.
- */
- public void testIsEmpty() {
- SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
- assertFalse(methodSFS.isEmpty());
- methodSFS = new SimpleFieldSet(true);
- assertTrue(methodSFS.isEmpty());
- }
-
- /**
- * Tests directSubsetNameIterator() method.
- * It uses SAMPLE_STRING_PAIRS and for this reason
- * the expected subset is "foo".
- */
- public void testDirectSubsetNameIterator() {
- SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
- String expectedSubset = SAMPLE_STRING_PAIRS[0][0]; //"foo"
- Iterator methodIter = methodSFS.directSubsetNameIterator();
- while (methodIter.hasNext())
- ((String)methodIter.next()).equals(expectedSubset);
- methodSFS = new SimpleFieldSet(true);
- methodIter = methodSFS.directSubsetNameIterator();
- assertNull(methodIter);
- }
-
- /**
- * Tests nameOfDirectSubsets() method.
- */
- public void testNamesOfDirectSubsets() {
- String[] expectedResult = {SAMPLE_STRING_PAIRS[0][0]};
- SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
-
assertTrue(Arrays.equals(methodSFS.namesOfDirectSubsets(),expectedResult));
-
- methodSFS = new SimpleFieldSet(true);
- assertTrue(Arrays.equals(methodSFS.namesOfDirectSubsets(), new
String[0]));
- }
-
- /**
- * Test the putOverwrite(String,String) method.
- */
- public void testPutOverwrite_String() {
- String methodKey = "foo.bar";
- String[] methodValues = {"boo","bar","zoo"};
- String expectedResult = "zoo";
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- for (int i = 0 ; i < methodValues.length; i++)
- methodSFS.putOverwrite(methodKey,methodValues[i]);
- assertEquals(methodSFS.get(methodKey),expectedResult);
- }
-
- /**
- * Test the putOverwrite(String,String[]) method.
- */
- public void testPutOverwrite_StringArray() {
- String methodKey = "foo.bar";
- String[] methodValues = {"boo","bar","zoo"};
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- methodSFS.putOverwrite(methodKey,methodValues);
-
assertTrue(Arrays.equals(methodSFS.getAll(methodKey),methodValues));
- }
-
- /**
- * Test the putAppend(String,String) method.
- */
- public void testPutAppend() {
- String methodKey = "foo.bar";
- String[] methodValues = {"boo","bar","zoo"};
- String expectedResult = "boo"+SimpleFieldSet.MULTI_VALUE_CHAR
-
+"bar"+SimpleFieldSet.MULTI_VALUE_CHAR
- +"zoo";
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- for (int i = 0 ; i < methodValues.length; i++)
- methodSFS.putAppend(methodKey,methodValues[i]);
- assertEquals(methodSFS.get(methodKey),expectedResult);
- }
-
- /**
- * Tests the getAll(String) method.
- */
- public void testGetAll() {
- String methodKey = "foo.bar";
- String[] methodValues = {"boo","bar","zoo"};
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- for (int i = 0 ; i < methodValues.length; i++)
- methodSFS.putAppend(methodKey,methodValues[i]);
-
assertTrue(Arrays.equals(methodSFS.getAll(methodKey),methodValues));
- }
-
- /**
- * Tests the getIntArray(String) method
- */
- public void testGetIntArray() {
- SimpleFieldSet methodSFS = new SimpleFieldSet(true);
- String keyPrefix = "foo";
- for (int i = 0; i<15; i++)
- methodSFS.putAppend(keyPrefix,String.valueOf(i));
- int[] result = methodSFS.getIntArray(keyPrefix);
- for (int i = 0; i<15; i++)
- assertTrue(result[i]==i);
-
- }
-
- /**
- * Tests removeValue(String) method
- */
- public void testRemoveValue() {
- SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
- methodSFS.removeValue("foo");
- assertNull(methodSFS.get(SAMPLE_STRING_PAIRS[0][0]));
- for(int i=1;i<SAMPLE_STRING_PAIRS.length;i++)
- assertEquals(methodSFS.get(SAMPLE_STRING_PAIRS[i][0]),
- SAMPLE_STRING_PAIRS[i][1]);
- }
-
- /**
- * Tests removeSubset(String) method
- */
- public void testRemoveSubset() {
- SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
- methodSFS.removeSubset("foo");
- for(int i = 1; i< 3; i++)
- assertNull(methodSFS.get(SAMPLE_STRING_PAIRS[i][0]));
- assertEquals(methodSFS.get(SAMPLE_STRING_PAIRS[0][0]),
- SAMPLE_STRING_PAIRS[0][1]);
- for(int i = 3; i< 5; i++)
- assertEquals(methodSFS.get(SAMPLE_STRING_PAIRS[i][0]),
- SAMPLE_STRING_PAIRS[i][1]);
- }
-
- /**
- * Searches for a key in a given String[][] array.
- * We consider that keys are stored in String[x][0]
- * @param aStringPairsArray
- * @param aPrefix that could be put before found key
- * @param aKey to be searched
- * @return true if there is the key
- */
- private boolean isAKey(String[][] aStringPairsArray, String aPrefix,
String aKey) {
- for (int i=0; i<aStringPairsArray.length; i++)
- if (aKey.equals(aPrefix+aStringPairsArray[i][0]))
- return true;
- return false;
- }
-
- /**
- * Verifies if all keys in a String[][]
- * (We consider that keys are stored in String[x][0])
- * are the same that the Iterator provides.
- * In this way both hasNext() and next() methods
- * are tested.
- * @param aStringPairsArray
- * @param aPrefix that could be put before found key
- * @param aIterator
- * @return true if they have the same key set
- */
- private boolean areAllContainedKeys(String[][] aStringPairsArray,
String aPrefix, Iterator aIterator) {
- boolean retValue = true;
- int actualLength = 0;
- while (aIterator.hasNext()) {
- actualLength++;
- retValue &=
isAKey(aStringPairsArray,aPrefix,(String)aIterator.next());
- }
- retValue &= (actualLength==aStringPairsArray.length);
- return retValue;
- }
-
- /**
- * Tests the Iterator given for the
- * SimpleFieldSet class.
- * It tests hasNext() and next() methods.
- */
- public void testKeyIterator() {
- SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
- Iterator itr = methodSFS.keyIterator();
- assertTrue(areAllContainedKeys(SAMPLE_STRING_PAIRS,"",itr));
- }
-
- /**
- * Tests the Iterator created using prefix
- * given for the SimpleFieldSet class
- */
- public void testKeyIterator_String() {
- String methodPrefix = "bob";
- SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
- Iterator itr = methodSFS.keyIterator(methodPrefix);
-
assertTrue(areAllContainedKeys(SAMPLE_STRING_PAIRS,methodPrefix,itr));
- }
-}
Copied: branches/freenet-jfk/test/freenet/support/SimpleFieldSetTest.java (from
rev 14796, trunk/freenet/test/freenet/support/SimpleFieldSetTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/SimpleFieldSetTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/SimpleFieldSetTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,701 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package freenet.support;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import freenet.node.FSParseException;
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.SimpleFieldSet} class.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class SimpleFieldSetTest extends TestCase {
+
+ private static final char KEY_VALUE_SEPARATOR = '=';
+
+ /* A double string array used across all tests
+ * it must not be changed in order to perform tests
+ * correctly */
+ private static final String[][] SAMPLE_STRING_PAIRS = {
+ //directSubset
+ {"foo","bar"},
+ {"foo.bar","foobar"},
+ {"foo.bar.boo.far","foobar"},
+ {"foo2","foobar.fooboo.foofar.foofoo"},
+ {"foo3",KEY_VALUE_SEPARATOR+"bar"} };
+
+ private static final String SAMPLE_END_MARKER = "END";
+
+ /**
+ * Tests putSingle(String,String) method
+ * trying to store a key with two paired
+ * multi_level_chars (i.e. "..").
+ */
+ public void
testSimpleFieldSetPutSingle_StringString_WithTwoPairedMultiLevelChars() {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ String methodKey = "foo..bar.";
+ String methodValue = "foobar";
+ methodSFS.putSingle(methodKey,methodValue);
+
assertEquals(methodSFS.subset("foo").subset("").subset("bar").get(""),methodValue);
+ assertEquals(methodSFS.get(methodKey),methodValue);
+ }
+
+ /**
+ * Tests putAppend(String,String) method
+ * trying to store a key with two paired
+ * multi_level_chars (i.e. "..").
+ */
+ public void
testSimpleFieldSetPutAppend_StringString_WithTwoPairedMultiLevelChars() {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ String methodKey = "foo..bar";
+ String methodValue = "foobar";
+ methodSFS.putAppend(methodKey,methodValue);
+ assertEquals(methodSFS.get(methodKey),methodValue);
+ }
+
+ /**
+ * Tests put() and get() methods
+ * using a normal Map behaviour
+ * and without MULTI_LEVEL_CHARs
+ */
+ public void testSimpleFieldSetPutAndGet_NoMultiLevel(){
+ String[][] methodPairsArray = {
+
{"A","a"},{"B","b"},{"C","c"},{"D","d"},{"E","e"},{"F","f"} };
+ assertTrue(checkPutAndGetPairs(methodPairsArray));
+ }
+
+ /**
+ * Tests put() and get() methods
+ * using a normal Map behaviour
+ * and with MULTI_LEVEL_CHARs
+ */
+ public void testSimpleFieldSetPutAndGet_MultiLevel(){
+ String[][] methodPairsArray_DoubleLevel = {
+ {"A.A","aa"},
+ {"A.B","ab"},
+ {"A.C","ac"},
+ {"A.D","ad"},
+ {"A.E","ae"},
+ {"A.F","af"} };
+ String[][] methodPairsArray_MultiLevel = {
+ {"A.A.A.A","aa"},
+ {"A.B.A","ab"},
+ {"A.C.Cc","ac"},
+ {"A.D.F","ad"},
+ {"A.E.G","ae"},
+ {"A.F.J.II.UI.BOO","af"} };
+ assertTrue(checkPutAndGetPairs(methodPairsArray_DoubleLevel));
+ assertTrue(checkPutAndGetPairs(methodPairsArray_MultiLevel));
+ }
+
+
+ /**
+ * It puts key-value pairs in a SimpleFieldSet
+ * and verify if it can do the correspondant
+ * get correctly.
+ * @param aPairsArray
+ * @return true if it is correct
+ */
+ private boolean checkPutAndGetPairs(String[][] aPairsArray) {
+ boolean retValue = true;
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ //putting values
+ for (int i = 0; i < aPairsArray.length; i++)
+ methodSFS.putSingle(aPairsArray[i][0],
aPairsArray[i][1]);
+ for (int i = 0; i < aPairsArray.length; i++)
//getting values
+ retValue &=
methodSFS.get(aPairsArray[i][0]).equals(aPairsArray[i][1]);
+ retValue &= checkSimpleFieldSetSize(methodSFS,
aPairsArray.length);
+ return retValue;
+ }
+
+ /**
+ * Tests subset(String) method
+ * putting two levels keys and
+ * fetching it through subset() method
+ * on the first level and then get()
+ * on the second
+ */
+ public void testSimpleFieldSetSubset_String() {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ String[][] methodPairsArray_MultiLevel = {
+ {"A","A","aa"},
+ {"A","B","ab"},
+ {"A","C","ac"},
+ {"A","D","ad"},
+ {"A","E","ae"},
+ {"A","F","af"} };
+ //putting values
+ for (int i = 0; i < methodPairsArray_MultiLevel.length; i++)
+ methodSFS.putSingle(methodPairsArray_MultiLevel[i][0]
+ + SimpleFieldSet.MULTI_LEVEL_CHAR
+ +
methodPairsArray_MultiLevel[i][1],
+ methodPairsArray_MultiLevel[i][2]);
+ //getting subsets and then values
+ for (int i = 0; i < methodPairsArray_MultiLevel.length; i++)
+ assertEquals(
+ methodSFS.subset(
+
methodPairsArray_MultiLevel[i][0]).get(methodPairsArray_MultiLevel[i][1]),
+ methodPairsArray_MultiLevel[i][2]);
+
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray_MultiLevel.length));
+ }
+
+ /**
+ * Tests putAllOverwrite(SimpleFieldSet) method
+ * trying to overwrite a whole SimpleFieldSet
+ * with another with same keys but different
+ * values
+ */
+ public void testPutAllOverwrite() {
+ String methodAppendedString = "buu";
+ SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
+ SimpleFieldSet methodNewSFS =
this.sfsFromStringPairs(methodAppendedString);
+ methodSFS.putAllOverwrite(methodNewSFS);
+ for (int i=0; i < SAMPLE_STRING_PAIRS.length; i++)
+ assertEquals(methodSFS.get(SAMPLE_STRING_PAIRS[i][0]),
+
SAMPLE_STRING_PAIRS[i][1]+methodAppendedString);
+ }
+
+ /**
+ * Tests put(String,SimpleFieldSet) method
+ */
+ public void testPut_StringSimpleFieldSet() {
+ String methodKey = "prefix";
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ methodSFS.put(methodKey,sfsFromSampleStringPairs());
+ for (int i=0; i < SAMPLE_STRING_PAIRS.length; i++)
+ assertEquals(
+
methodSFS.get(methodKey+SimpleFieldSet.MULTI_LEVEL_CHAR+SAMPLE_STRING_PAIRS[i][0]),
+ SAMPLE_STRING_PAIRS[i][1]);
+ }
+
+ /**
+ * Tests put(String,SimpleFieldSet) method
+ */
+ public void testTPut_StringSimpleFieldSet() {
+ String methodKey = "prefix";
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ methodSFS.tput(methodKey,sfsFromSampleStringPairs());
+ for (int i=0; i < SAMPLE_STRING_PAIRS.length; i++)
+
assertEquals(methodSFS.get(methodKey+SimpleFieldSet.MULTI_LEVEL_CHAR+SAMPLE_STRING_PAIRS[i][0]),
+ SAMPLE_STRING_PAIRS[i][1]);
+ }
+
+ /**
+ * Tests put(String,SimpleFieldSet) and
+ * tput(String,SimpleFieldSet) trying to
+ * add empty data structures
+ */
+ public void testPutAndTPut_WithEmpty() {
+ SimpleFieldSet methodEmptySFS = new SimpleFieldSet(true);
+ SimpleFieldSet methodSampleSFS = sfsFromSampleStringPairs();
+ try {
+ methodSampleSFS.put("sample",methodEmptySFS);
+ fail("Expected Exception Error Not Thrown!"); }
+ catch (IllegalArgumentException anException) {
+ assertNotNull(anException); }
+ try {
+ methodSampleSFS.tput("sample",methodSampleSFS); }
+ catch (IllegalArgumentException aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+
+ /**
+ * It creates a SFS from the SAMPLE_STRING_PAIRS
+ * and putting a suffix after every value
+ * @param aSuffix to put after every value
+ * @return the SimpleFieldSet created
+ */
+ private SimpleFieldSet sfsFromStringPairs(String aSuffix) {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ //creating new
+ for (int i = 0; i < SAMPLE_STRING_PAIRS.length; i++)
+ methodSFS.putSingle(SAMPLE_STRING_PAIRS[i][0],
+ SAMPLE_STRING_PAIRS[i][1]+aSuffix);
+ return methodSFS;
+ }
+
+ /**
+ * Tests put(String,boolean) and getBoolean(String,boolean)
+ * methods consistency.
+ * The default value (returned if the key is not found) is set to
"false"
+ * and the real value is always set to "true", so
+ * we are sure if it finds the right value or not
+ * (and does not use the default).
+ */
+ public void testPut_StringBoolean() {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ int length = 15;
+ for(int i = 0; i < length; i++)
+ methodSFS.put(Integer.toString(i),true);
+ for (int i = 0; i < length; i++)
+
assertEquals(methodSFS.getBoolean(Integer.toString(i),false),true);
+ assertTrue(checkSimpleFieldSetSize(methodSFS,length));
+ }
+
+
+ /**
+ * Checks if the provided SimpleFieldSet
+ * has the right size
+ * @param aSimpleFieldSet
+ * @param expectedSize
+ * @return true if the size is the expected
+ */
+ private boolean checkSimpleFieldSetSize(SimpleFieldSet aSimpleFieldSet,
int expectedSize) {
+ int actualSize = 0;
+ Iterator methodKeyIterator = aSimpleFieldSet.keyIterator();
+ while (methodKeyIterator.hasNext()) {
+ methodKeyIterator.next();
+ actualSize++; }
+ return expectedSize == actualSize;
+ }
+
+ /**
+ * Tests put(String,int) and
+ * [getInt(String),getInt(String,int)]
+ * methods consistency.
+ * The default value (returned if the key is not found)
+ * is set to a not present int value, so we are sure
+ * if it finds the right value or not
+ * (and does not use the default).
+ */
+ public void testPut_StringInt() {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ int[][] methodPairsArray =
+ { {1,1},{2,2},{3,3},{4,4} };
+ for (int i = 0; i < methodPairsArray.length; i++)
+ methodSFS.put(Integer.toString(methodPairsArray[i][0]),
methodPairsArray[i][1]);
+
+
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray.length));
+
+ for (int i = 0; i < methodPairsArray.length; i++) {
+ try {
+
assertEquals(methodSFS.getInt(Integer.toString(methodPairsArray[i][0])),
+ methodPairsArray[i][1]);
+
assertEquals(methodSFS.getInt(Integer.toString(methodPairsArray[i][0]),5),
+ methodPairsArray[i][1]);
+ } catch (FSParseException aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+ }
+
+ /**
+ * Tests put(String,long) and
+ * [getLong(String),getLong(String,long)]
+ * methods consistency.
+ * The default value (returned if the key is not found)
+ * is set to a not present long value, so we are sure
+ * if it finds the right value or not
+ * (and does not use the default).
+ */
+ public void testPut_StringLong() {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ long[][] methodPairsArray =
+ { {1,1},{2,2},{3,3},{4,4} };
+ for (int i = 0; i < methodPairsArray.length; i++)
+ methodSFS.put(Long.toString(methodPairsArray[i][0]),
methodPairsArray[i][1]);
+
+
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray.length));
+
+ for (int i = 0; i < methodPairsArray.length; i++) {
+ try {
+
assertEquals(methodSFS.getLong(Long.toString(methodPairsArray[i][0])),
+ methodPairsArray[i][1]);
+
assertEquals(methodSFS.getLong(Long.toString(methodPairsArray[i][0]),5),
+ methodPairsArray[i][1]);
+ } catch (FSParseException aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+ }
+
+ /**
+ * Tests put(String,char) and
+ * [getChar(String),getChar(String,char)]
+ * methods consistency.
+ * The default value (returned if the key is not found)
+ * is set to a not present char value, so we are sure
+ * if it finds the right value or not
+ * (and does not use the default).
+ */
+ public void testPut_StringChar() {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ char[][] methodPairsArray =
+ { {'1','1'},{'2','2'},{'3','3'},{'4','4'} };
+ for (int i = 0; i < methodPairsArray.length; i++)
+ methodSFS.put(String.valueOf(methodPairsArray[i][0]),
methodPairsArray[i][1]);
+
+
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray.length));
+
+ for (int i = 0; i < methodPairsArray.length; i++) {
+ try {
+
assertEquals(methodSFS.getChar(String.valueOf(methodPairsArray[i][0])),
+ methodPairsArray[i][1]);
+
assertEquals(methodSFS.getChar(String.valueOf(methodPairsArray[i][0]),'5'),
+ methodPairsArray[i][1]);
+ } catch (FSParseException aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+ }
+
+ /**
+ * Tests put(String,short) and
+ * [getShort(String)|getShort(String,short)]
+ * methods consistency.
+ * The default value (returned if the key is not found)
+ * is set to a not present short value, so we are sure
+ * if it finds the right value or not
+ * (and does not use the default).
+ */
+ public void testPut_StringShort() {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ short[][] methodPairsArray =
+ { {1,1},{2,2},{3,3},{4,4} };
+ for (int i = 0; i < methodPairsArray.length; i++)
+ methodSFS.put(Short.toString(methodPairsArray[i][0]),
methodPairsArray[i][1]);
+
+
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray.length));
+
+ for (int i = 0; i < methodPairsArray.length; i++) {
+ try {
+
assertEquals(methodSFS.getShort(Short.toString(methodPairsArray[i][0])),
+ methodPairsArray[i][1]);
+
assertEquals(methodSFS.getShort(Short.toString(methodPairsArray[i][0]),(short)5),
+ methodPairsArray[i][1]);
+ } catch (FSParseException aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+ }
+
+ /**
+ * Tests put(String,double) and
+ * [getDouble(String)|getDouble(String,double)]
+ * methods consistency.
+ * The default value (returned if the key is not found)
+ * is set to a not present double value, so we are sure
+ * if it finds the right value or not
+ * (and does not use the default).
+ */
+ public void testPut_StringDouble() {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ double[][] methodPairsArray =
+ { {1,1},{2,2},{3,3},{4,4} };
+ for (int i = 0; i < methodPairsArray.length; i++)
+ methodSFS.put(Double.toString(methodPairsArray[i][0]),
methodPairsArray[i][1]);
+
+
assertTrue(checkSimpleFieldSetSize(methodSFS,methodPairsArray.length));
+
+ for (int i = 0; i < methodPairsArray.length; i++) {
+ try {
+ //there is no assertEquals(Double,Double) so we
are obliged to do this way -_-
+ assertEquals(
+
Double.compare((methodSFS.getDouble(Double.toString(methodPairsArray[i][0]))),
+
methodPairsArray[i][1]),0);
+ assertEquals(
+
Double.compare(methodSFS.getDouble(Double.toString(methodPairsArray[i][0]),(double)5),
+
methodPairsArray[i][1]),0);
+ } catch (FSParseException aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+ }
+
+ /**
+ * Generates a string for the SFS parser in the canonical form:
+ * key=value
+ * END
+ * @param aStringPairsArray
+ * @return a String ready to be read by a SFS parser
+ */
+ private String sfsReadyString(String[][] aStringPairsArray) {
+
+ String methodStringToReturn = "";
+ for(int i = 0; i < aStringPairsArray.length; i++)
+ methodStringToReturn +=
aStringPairsArray[i][0]+KEY_VALUE_SEPARATOR+aStringPairsArray[i][1]+'\n';
+ methodStringToReturn += SAMPLE_END_MARKER;
+ return methodStringToReturn;
+ }
+
+ /**
+ * Tests SimpleFieldSet(String,boolean,boolean) constructor,
+ * with simple and border cases of the canonical form.
+ */
+ public void testSimpleFieldSet_StringBooleanBoolean() {
+ String[][] methodStringPairs = SAMPLE_STRING_PAIRS;
+ String methodStringToParse = sfsReadyString(methodStringPairs);
+ try {
+ SimpleFieldSet methodSFS = new
SimpleFieldSet(methodStringToParse,false,false);
+ for (int i=0; i < methodStringPairs.length; i++)
+
assertEquals(methodSFS.get(methodStringPairs[i][0]),
+ methodStringPairs[i][1]);
+ } catch (IOException aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+
+ /**
+ * Tests SimpleFieldSet(BufferedReader,boolean,boolean) constructor,
+ * with simple and border cases of the canonical form.
+ */
+ public void testSimpleFieldSet_BufferedReaderBooleanBoolean() {
+ String[][] methodStringPairs = SAMPLE_STRING_PAIRS;
+ BufferedReader methodBufferedReader =
+ new BufferedReader(new
StringReader(sfsReadyString(methodStringPairs)));
+ try {
+ SimpleFieldSet methodSFS = new
SimpleFieldSet(methodBufferedReader,false,false);
+ for (int i=0; i < methodStringPairs.length; i++)
+
assertEquals(methodSFS.get(methodStringPairs[i][0]),
+ methodStringPairs[i][1]);
+ } catch (IOException aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+
+ /**
+ * Generates a SimpleFieldSet using the
+ * SAMPLE_STRING_PAIRS and sfs put method
+ * @return a SimpleFieldSet
+ */
+ private SimpleFieldSet sfsFromSampleStringPairs() {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ for (int i = 0; i < SAMPLE_STRING_PAIRS.length; i++)
+ methodSFS.putSingle(SAMPLE_STRING_PAIRS[i][0],
+ SAMPLE_STRING_PAIRS[i][1]);
+ assertTrue(checkSimpleFieldSetSize(methodSFS,
+ SAMPLE_STRING_PAIRS.length));
+ return methodSFS;
+ }
+
+ /**
+ * Tests SimpleFieldSet(SimpleFieldSet) constructor,
+ * with simple and border cases of the canonical form.
+ */
+ public void testSimpleFieldSet_SimpleFieldSet() {
+ SimpleFieldSet methodSFS = new
SimpleFieldSet(sfsFromSampleStringPairs());
+ String[][] methodStringPairs = SAMPLE_STRING_PAIRS;
+ for (int i=0; i < methodStringPairs.length; i++)
+ assertEquals(methodSFS.get(methodStringPairs[i][0]),
+ methodStringPairs[i][1]);
+ }
+
+ /**
+ * Tests {get,set}EndMarker(String) methods
+ * using them after a String parsing
+ */
+ public void testEndMarker() {
+ String methodEndMarker = "ANOTHER-ENDING";
+ String methodStringToParse =
sfsReadyString(SAMPLE_STRING_PAIRS);
+ try {
+ SimpleFieldSet methodSFS = new
SimpleFieldSet(methodStringToParse,false,false);
+
assertEquals(methodSFS.getEndMarker(),SAMPLE_END_MARKER);
+ methodSFS.setEndMarker(methodEndMarker);
+ assertEquals(methodSFS.getEndMarker(),methodEndMarker);
+ } catch (IOException aException) {
+ fail("Not expected exception thrown : " +
aException.getMessage()); }
+ }
+
+ /**
+ * Tests isEmpty() method.
+ */
+ public void testIsEmpty() {
+ SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
+ assertFalse(methodSFS.isEmpty());
+ methodSFS = new SimpleFieldSet(true);
+ assertTrue(methodSFS.isEmpty());
+ }
+
+ /**
+ * Tests directSubsetNameIterator() method.
+ * It uses SAMPLE_STRING_PAIRS and for this reason
+ * the expected subset is "foo".
+ */
+ public void testDirectSubsetNameIterator() {
+ SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
+ String expectedSubset = SAMPLE_STRING_PAIRS[0][0]; //"foo"
+ Iterator methodIter = methodSFS.directSubsetNameIterator();
+ while (methodIter.hasNext())
+ ((String)methodIter.next()).equals(expectedSubset);
+ methodSFS = new SimpleFieldSet(true);
+ methodIter = methodSFS.directSubsetNameIterator();
+ assertNull(methodIter);
+ }
+
+ /**
+ * Tests nameOfDirectSubsets() method.
+ */
+ public void testNamesOfDirectSubsets() {
+ String[] expectedResult = {SAMPLE_STRING_PAIRS[0][0]};
+ SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
+
assertTrue(Arrays.equals(methodSFS.namesOfDirectSubsets(),expectedResult));
+
+ methodSFS = new SimpleFieldSet(true);
+ assertTrue(Arrays.equals(methodSFS.namesOfDirectSubsets(), new
String[0]));
+ }
+
+ /**
+ * Test the putOverwrite(String,String) method.
+ */
+ public void testPutOverwrite_String() {
+ String methodKey = "foo.bar";
+ String[] methodValues = {"boo","bar","zoo"};
+ String expectedResult = "zoo";
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ for (int i = 0 ; i < methodValues.length; i++)
+ methodSFS.putOverwrite(methodKey,methodValues[i]);
+ assertEquals(methodSFS.get(methodKey),expectedResult);
+ }
+
+ /**
+ * Test the putOverwrite(String,String[]) method.
+ */
+ public void testPutOverwrite_StringArray() {
+ String methodKey = "foo.bar";
+ String[] methodValues = {"boo","bar","zoo"};
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ methodSFS.putOverwrite(methodKey,methodValues);
+
assertTrue(Arrays.equals(methodSFS.getAll(methodKey),methodValues));
+ }
+
+ /**
+ * Test the putAppend(String,String) method.
+ */
+ public void testPutAppend() {
+ String methodKey = "foo.bar";
+ String[] methodValues = {"boo","bar","zoo"};
+ String expectedResult = "boo"+SimpleFieldSet.MULTI_VALUE_CHAR
+
+"bar"+SimpleFieldSet.MULTI_VALUE_CHAR
+ +"zoo";
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ for (int i = 0 ; i < methodValues.length; i++)
+ methodSFS.putAppend(methodKey,methodValues[i]);
+ assertEquals(methodSFS.get(methodKey),expectedResult);
+ }
+
+ /**
+ * Tests the getAll(String) method.
+ */
+ public void testGetAll() {
+ String methodKey = "foo.bar";
+ String[] methodValues = {"boo","bar","zoo"};
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ for (int i = 0 ; i < methodValues.length; i++)
+ methodSFS.putAppend(methodKey,methodValues[i]);
+
assertTrue(Arrays.equals(methodSFS.getAll(methodKey),methodValues));
+ }
+
+ /**
+ * Tests the getIntArray(String) method
+ */
+ public void testGetIntArray() {
+ SimpleFieldSet methodSFS = new SimpleFieldSet(true);
+ String keyPrefix = "foo";
+ for (int i = 0; i<15; i++)
+ methodSFS.putAppend(keyPrefix,String.valueOf(i));
+ int[] result = methodSFS.getIntArray(keyPrefix);
+ for (int i = 0; i<15; i++)
+ assertTrue(result[i]==i);
+
+ }
+
+ /**
+ * Tests removeValue(String) method
+ */
+ public void testRemoveValue() {
+ SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
+ methodSFS.removeValue("foo");
+ assertNull(methodSFS.get(SAMPLE_STRING_PAIRS[0][0]));
+ for(int i=1;i<SAMPLE_STRING_PAIRS.length;i++)
+ assertEquals(methodSFS.get(SAMPLE_STRING_PAIRS[i][0]),
+ SAMPLE_STRING_PAIRS[i][1]);
+ }
+
+ /**
+ * Tests removeSubset(String) method
+ */
+ public void testRemoveSubset() {
+ SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
+ methodSFS.removeSubset("foo");
+ for(int i = 1; i< 3; i++)
+ assertNull(methodSFS.get(SAMPLE_STRING_PAIRS[i][0]));
+ assertEquals(methodSFS.get(SAMPLE_STRING_PAIRS[0][0]),
+ SAMPLE_STRING_PAIRS[0][1]);
+ for(int i = 3; i< 5; i++)
+ assertEquals(methodSFS.get(SAMPLE_STRING_PAIRS[i][0]),
+ SAMPLE_STRING_PAIRS[i][1]);
+ }
+
+ /**
+ * Searches for a key in a given String[][] array.
+ * We consider that keys are stored in String[x][0]
+ * @param aStringPairsArray
+ * @param aPrefix that could be put before found key
+ * @param aKey to be searched
+ * @return true if there is the key
+ */
+ private boolean isAKey(String[][] aStringPairsArray, String aPrefix,
String aKey) {
+ for (int i=0; i<aStringPairsArray.length; i++)
+ if (aKey.equals(aPrefix+aStringPairsArray[i][0]))
+ return true;
+ return false;
+ }
+
+ /**
+ * Verifies if all keys in a String[][]
+ * (We consider that keys are stored in String[x][0])
+ * are the same that the Iterator provides.
+ * In this way both hasNext() and next() methods
+ * are tested.
+ * @param aStringPairsArray
+ * @param aPrefix that could be put before found key
+ * @param aIterator
+ * @return true if they have the same key set
+ */
+ private boolean areAllContainedKeys(String[][] aStringPairsArray,
String aPrefix, Iterator aIterator) {
+ boolean retValue = true;
+ int actualLength = 0;
+ while (aIterator.hasNext()) {
+ actualLength++;
+ retValue &=
isAKey(aStringPairsArray,aPrefix,(String)aIterator.next());
+ }
+ retValue &= (actualLength==aStringPairsArray.length);
+ return retValue;
+ }
+
+ /**
+ * Tests the Iterator given for the
+ * SimpleFieldSet class.
+ * It tests hasNext() and next() methods.
+ */
+ public void testKeyIterator() {
+ SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
+ Iterator itr = methodSFS.keyIterator();
+ assertTrue(areAllContainedKeys(SAMPLE_STRING_PAIRS,"",itr));
+ }
+
+ /**
+ * Tests the Iterator created using prefix
+ * given for the SimpleFieldSet class
+ */
+ public void testKeyIterator_String() {
+ String methodPrefix = "bob";
+ SimpleFieldSet methodSFS = sfsFromSampleStringPairs();
+ Iterator itr = methodSFS.keyIterator(methodPrefix);
+
assertTrue(areAllContainedKeys(SAMPLE_STRING_PAIRS,methodPrefix,itr));
+ }
+}
Deleted: branches/freenet-jfk/test/freenet/support/SizeUtilTest.java
===================================================================
--- trunk/freenet/test/freenet/support/SizeUtilTest.java 2007-08-18
19:36:17 UTC (rev 14796)
+++ branches/freenet-jfk/test/freenet/support/SizeUtilTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -1,77 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package freenet.support;
-
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.SizeUtil} class.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class SizeUtilTest extends TestCase {
-
- String[][] valAndExpected = {
- //one byte
- {"1","B"},
- //one kilobyte
- {"1024","KiB"},
- //one megabyte
- {"1048576","MiB"},
- //one gigabyte
- {"1073741824","GiB"},
- //one terabyte
- {"1099511627776","TiB"},
- //one petabyte
- //{"1125899906842624","1.0 PiB"},
- //one exabyte
- //{"1152921504606846976", "1.0 EiB"},
- //one zettabyte
- //{"1180591620717411303424", "1.0 ZiB"},
- //one yottabyte
- //{"1208925819614629174706176","1.0 YiB"},
- };
-
- public void testFormatSizeLong() {
- Long methodLong;
- methodLong = Long.valueOf(valAndExpected[0][0]);
- assertEquals(SizeUtil.formatSize(methodLong.longValue()),
- "1 "+valAndExpected[0][1]);
-
- for(int i = 1; i < valAndExpected.length; i++) {
- methodLong = Long.valueOf(valAndExpected[i][0]);
-
assertEquals(SizeUtil.formatSize(methodLong.longValue()),
- "1.0 "+valAndExpected[i][1]); }
- }
-
- /**
- * Tests if formatSize(long) method
- * works correctly with intermediate values
- * (i.e. 1/4,1/2,3/4)
- */
- public void testFormatSizeLong_WithIntermediateValues() {
- Long methodLong;
- String[] actualValue = {"1.0","1.25","1.5","1.75"};
-
- for(int i = 1; i < valAndExpected.length; i++) {
- methodLong = Long.valueOf(valAndExpected[i][0]);
- for(int j = 0; j < 4; j++)
-
assertEquals(SizeUtil.formatSize(methodLong.longValue()+(methodLong.longValue()*j/4)),
- actualValue[j]+"
"+valAndExpected[i][1]);
- }
- }
-
-}
Copied: branches/freenet-jfk/test/freenet/support/SizeUtilTest.java (from rev
14796, trunk/freenet/test/freenet/support/SizeUtilTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/SizeUtilTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/SizeUtilTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,77 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.SizeUtil} class.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class SizeUtilTest extends TestCase {
+
+ String[][] valAndExpected = {
+ //one byte
+ {"1","B"},
+ //one kilobyte
+ {"1024","KiB"},
+ //one megabyte
+ {"1048576","MiB"},
+ //one gigabyte
+ {"1073741824","GiB"},
+ //one terabyte
+ {"1099511627776","TiB"},
+ //one petabyte
+ //{"1125899906842624","1.0 PiB"},
+ //one exabyte
+ //{"1152921504606846976", "1.0 EiB"},
+ //one zettabyte
+ //{"1180591620717411303424", "1.0 ZiB"},
+ //one yottabyte
+ //{"1208925819614629174706176","1.0 YiB"},
+ };
+
+ public void testFormatSizeLong() {
+ Long methodLong;
+ methodLong = Long.valueOf(valAndExpected[0][0]);
+ assertEquals(SizeUtil.formatSize(methodLong.longValue()),
+ "1 "+valAndExpected[0][1]);
+
+ for(int i = 1; i < valAndExpected.length; i++) {
+ methodLong = Long.valueOf(valAndExpected[i][0]);
+
assertEquals(SizeUtil.formatSize(methodLong.longValue()),
+ "1.0 "+valAndExpected[i][1]); }
+ }
+
+ /**
+ * Tests if formatSize(long) method
+ * works correctly with intermediate values
+ * (i.e. 1/4,1/2,3/4)
+ */
+ public void testFormatSizeLong_WithIntermediateValues() {
+ Long methodLong;
+ String[] actualValue = {"1.0","1.25","1.5","1.75"};
+
+ for(int i = 1; i < valAndExpected.length; i++) {
+ methodLong = Long.valueOf(valAndExpected[i][0]);
+ for(int j = 0; j < 4; j++)
+
assertEquals(SizeUtil.formatSize(methodLong.longValue()+(methodLong.longValue()*j/4)),
+ actualValue[j]+"
"+valAndExpected[i][1]);
+ }
+ }
+
+}
Deleted: branches/freenet-jfk/test/freenet/support/TimeUtilTest.java
===================================================================
--- trunk/freenet/test/freenet/support/TimeUtilTest.java 2007-08-18
19:36:17 UTC (rev 14796)
+++ branches/freenet-jfk/test/freenet/support/TimeUtilTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -1,147 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package freenet.support;
-
-import java.util.Locale;
-
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.TimeUtil} class.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class TimeUtilTest extends TestCase {
-
- //1w+1d+1h+1m+1s+1ms
- private long oneForTermLong = 694861001;
-
- protected void setUp() throws Exception {
- Locale.setDefault(Locale.US);
- }
-
- /**
- * Tests formatTime(long,int,boolean) method
- * trying the biggest long value
- */
- public void testFormatTime_LongIntBoolean_MaxValue() {
- String expectedForMaxLongValue = "15250284452w3d7h12m55.807s";
- assertEquals(TimeUtil.formatTime(Long.MAX_VALUE,6,true),
- expectedForMaxLongValue);
- }
-
- /**
- * Tests formatTime(long,int) method
- * trying the biggest long value
- */
- public void testFormatTime_LongInt() {
- String expectedForMaxLongValue = "15250284452w3d7h12m55s";
- assertEquals(TimeUtil.formatTime(Long.MAX_VALUE,6),
- expectedForMaxLongValue);
- }
-
- /**
- * Tests formatTime(long) method
- * trying the biggest long value
- */
- public void testFormatTime_Long() {
- //it uses two terms by default
- String expectedForMaxLongValue = "15250284452w3d";
- assertEquals(TimeUtil.formatTime(Long.MAX_VALUE),
- expectedForMaxLongValue);
- }
-
- /**
- * Tests formatTime(long) method
- * using known values.
- * They could be checked using Google Calculator
- * http://www.google.com/intl/en/help/features.html#calculator
- */
- public void testFormatTime_KnownValues() {
- Long methodLong;
- String[][] valAndExpected = {
- //one week
- {"604800000","1w"},
- //one day
- {"86400000","1d"},
- //one hour
- {"3600000","1h"},
- //one minute
- {"60000","1m"},
- //one second
- {"1000","1s"}
- };
- for(int i = 0; i < valAndExpected.length; i++) {
- methodLong = Long.valueOf(valAndExpected[i][0]);
-
assertEquals(TimeUtil.formatTime(methodLong.longValue()),
- valAndExpected[i][1]); }
- }
-
- /**
- * Tests formatTime(long,int) method
- * using a long value that generate every possible
- * term kind. It tests if the maxTerms arguments
- * works correctly
- */
- public void testFormatTime_LongIntBoolean_maxTerms() {
- String[] valAndExpected = {
- //0 terms
- "",
- //1 term
- "1w",
- //2 terms
- "1w1d",
- //3 terms
- "1w1d1h",
- //4 terms
- "1w1d1h1m",
- //5 terms
- "1w1d1h1m1s",
- //6 terms
- "1w1d1h1m1.001s"
- };
- for(int i = 0; i < valAndExpected.length; i++)
- assertEquals(TimeUtil.formatTime(oneForTermLong,i,true),
- valAndExpected[i]);
- }
-
- /**
- * Tests formatTime(long,int) method
- * using one millisecond time interval.
- * It tests if the withSecondFractions argument
- * works correctly
- */
- public void testFormatTime_LongIntBoolean_milliseconds() {
- long methodValue = 1; //1ms
- assertEquals(TimeUtil.formatTime(methodValue,6,false),"");
- assertEquals(TimeUtil.formatTime(methodValue,6,true),"0.001s");
- }
-
- /**
- * Tests formatTime(long,int) method
- * using a long value that generate every possible
- * term kind. It tests if the maxTerms arguments
- * works correctly
- */
- public void testFormatTime_LongIntBoolean_tooManyTerms() {
- try {
- TimeUtil.formatTime(oneForTermLong,7);
- fail("Expected IllegalArgumentException not thrown"); }
- catch (IllegalArgumentException anException) {
- assertNotNull(anException); }
- }
-
-}
Copied: branches/freenet-jfk/test/freenet/support/TimeUtilTest.java (from rev
14796, trunk/freenet/test/freenet/support/TimeUtilTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/TimeUtilTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/TimeUtilTest.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,147 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.TimeUtil} class.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class TimeUtilTest extends TestCase {
+
+ //1w+1d+1h+1m+1s+1ms
+ private long oneForTermLong = 694861001;
+
+ protected void setUp() throws Exception {
+ Locale.setDefault(Locale.US);
+ }
+
+ /**
+ * Tests formatTime(long,int,boolean) method
+ * trying the biggest long value
+ */
+ public void testFormatTime_LongIntBoolean_MaxValue() {
+ String expectedForMaxLongValue = "15250284452w3d7h12m55.807s";
+ assertEquals(TimeUtil.formatTime(Long.MAX_VALUE,6,true),
+ expectedForMaxLongValue);
+ }
+
+ /**
+ * Tests formatTime(long,int) method
+ * trying the biggest long value
+ */
+ public void testFormatTime_LongInt() {
+ String expectedForMaxLongValue = "15250284452w3d7h12m55s";
+ assertEquals(TimeUtil.formatTime(Long.MAX_VALUE,6),
+ expectedForMaxLongValue);
+ }
+
+ /**
+ * Tests formatTime(long) method
+ * trying the biggest long value
+ */
+ public void testFormatTime_Long() {
+ //it uses two terms by default
+ String expectedForMaxLongValue = "15250284452w3d";
+ assertEquals(TimeUtil.formatTime(Long.MAX_VALUE),
+ expectedForMaxLongValue);
+ }
+
+ /**
+ * Tests formatTime(long) method
+ * using known values.
+ * They could be checked using Google Calculator
+ * http://www.google.com/intl/en/help/features.html#calculator
+ */
+ public void testFormatTime_KnownValues() {
+ Long methodLong;
+ String[][] valAndExpected = {
+ //one week
+ {"604800000","1w"},
+ //one day
+ {"86400000","1d"},
+ //one hour
+ {"3600000","1h"},
+ //one minute
+ {"60000","1m"},
+ //one second
+ {"1000","1s"}
+ };
+ for(int i = 0; i < valAndExpected.length; i++) {
+ methodLong = Long.valueOf(valAndExpected[i][0]);
+
assertEquals(TimeUtil.formatTime(methodLong.longValue()),
+ valAndExpected[i][1]); }
+ }
+
+ /**
+ * Tests formatTime(long,int) method
+ * using a long value that generate every possible
+ * term kind. It tests if the maxTerms arguments
+ * works correctly
+ */
+ public void testFormatTime_LongIntBoolean_maxTerms() {
+ String[] valAndExpected = {
+ //0 terms
+ "",
+ //1 term
+ "1w",
+ //2 terms
+ "1w1d",
+ //3 terms
+ "1w1d1h",
+ //4 terms
+ "1w1d1h1m",
+ //5 terms
+ "1w1d1h1m1s",
+ //6 terms
+ "1w1d1h1m1.001s"
+ };
+ for(int i = 0; i < valAndExpected.length; i++)
+ assertEquals(TimeUtil.formatTime(oneForTermLong,i,true),
+ valAndExpected[i]);
+ }
+
+ /**
+ * Tests formatTime(long,int) method
+ * using one millisecond time interval.
+ * It tests if the withSecondFractions argument
+ * works correctly
+ */
+ public void testFormatTime_LongIntBoolean_milliseconds() {
+ long methodValue = 1; //1ms
+ assertEquals(TimeUtil.formatTime(methodValue,6,false),"");
+ assertEquals(TimeUtil.formatTime(methodValue,6,true),"0.001s");
+ }
+
+ /**
+ * Tests formatTime(long,int) method
+ * using a long value that generate every possible
+ * term kind. It tests if the maxTerms arguments
+ * works correctly
+ */
+ public void testFormatTime_LongIntBoolean_tooManyTerms() {
+ try {
+ TimeUtil.formatTime(oneForTermLong,7);
+ fail("Expected IllegalArgumentException not thrown"); }
+ catch (IllegalArgumentException anException) {
+ assertNotNull(anException); }
+ }
+
+}
Deleted: branches/freenet-jfk/test/freenet/support/URIPreEncoderTest.java
===================================================================
--- trunk/freenet/test/freenet/support/URIPreEncoderTest.java 2007-08-18
19:36:17 UTC (rev 14796)
+++ branches/freenet-jfk/test/freenet/support/URIPreEncoderTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,69 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package freenet.support;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import freenet.utils.UTFUtil;
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.URIPreEncoder} class
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class URIPreEncoderTest extends TestCase {
-
- private String prtblAscii = new String(UTFUtil.PRINTABLE_ASCII);
- private String stressedUTF_8Chars = new String(UTFUtil.STRESSED_UTF);
-
- private boolean containsOnlyValidChars(String aString) {
- char eachChar;
- for (int i = 0; i < aString.length(); i++) {
- eachChar = aString.charAt(i);
- if (URIPreEncoder.allowedChars.indexOf(eachChar) < 0)
- return false;
- };
- return true;
- }
-
- /**
- * Tests encode(String) method
- * to verify if it converts all
- * not safe chars into safe chars.
- */
- public void testEncode() {
- String toEncode = prtblAscii+stressedUTF_8Chars;
- String encoded = URIPreEncoder.encode(toEncode);
- assertTrue(containsOnlyValidChars(encoded));
- }
-
- /**
- * Tests encodeURI(String) method
- * to verify if it converts all
- * not safe chars into safe chars.
- */
- public void testEncodeURI() {
- String toEncode = prtblAscii+stressedUTF_8Chars;
- URI encoded;
- //try {
- // encoded = URIPreEncoder.encodeURI(toEncode);
this method will throw a not expected exception because '%' is included as a
valid char
- // assertTrue(containsOnlyValidChars(encoded.toString()));
- //} catch (URISyntaxException anException) {
- // fail("Not expected exception thrown : " +
anException.getMessage()); }
- }
-
-}
Copied: branches/freenet-jfk/test/freenet/support/URIPreEncoderTest.java (from
rev 14796, trunk/freenet/test/freenet/support/URIPreEncoderTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/URIPreEncoderTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/URIPreEncoderTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,69 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import freenet.utils.UTFUtil;
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.URIPreEncoder} class
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class URIPreEncoderTest extends TestCase {
+
+ private String prtblAscii = new String(UTFUtil.PRINTABLE_ASCII);
+ private String stressedUTF_8Chars = new String(UTFUtil.STRESSED_UTF);
+
+ private boolean containsOnlyValidChars(String aString) {
+ char eachChar;
+ for (int i = 0; i < aString.length(); i++) {
+ eachChar = aString.charAt(i);
+ if (URIPreEncoder.allowedChars.indexOf(eachChar) < 0)
+ return false;
+ };
+ return true;
+ }
+
+ /**
+ * Tests encode(String) method
+ * to verify if it converts all
+ * not safe chars into safe chars.
+ */
+ public void testEncode() {
+ String toEncode = prtblAscii+stressedUTF_8Chars;
+ String encoded = URIPreEncoder.encode(toEncode);
+ assertTrue(containsOnlyValidChars(encoded));
+ }
+
+ /**
+ * Tests encodeURI(String) method
+ * to verify if it converts all
+ * not safe chars into safe chars.
+ */
+ public void testEncodeURI() {
+ String toEncode = prtblAscii+stressedUTF_8Chars;
+ URI encoded;
+ //try {
+ // encoded = URIPreEncoder.encodeURI(toEncode);
this method will throw a not expected exception because '%' is included as a
valid char
+ // assertTrue(containsOnlyValidChars(encoded.toString()));
+ //} catch (URISyntaxException anException) {
+ // fail("Not expected exception thrown : " +
anException.getMessage()); }
+ }
+
+}
Deleted: branches/freenet-jfk/test/freenet/support/URLEncoderDecoderTest.java
===================================================================
--- trunk/freenet/test/freenet/support/URLEncoderDecoderTest.java
2007-08-18 19:36:17 UTC (rev 14796)
+++ branches/freenet-jfk/test/freenet/support/URLEncoderDecoderTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -1,167 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package freenet.support;
-
-import java.io.UnsupportedEncodingException;
-import freenet.utils.*;
-import junit.framework.TestCase;
-
-/**
- * Test case for {@link freenet.support.URLEncoder} and
- * {@link freenet.support.URLDecoder} classes.
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public class URLEncoderDecoderTest extends TestCase {
-
- private String prtblAscii = new String(UTFUtil.PRINTABLE_ASCII);
- private String stressedUTF_8Chars = new String(UTFUtil.STRESSED_UTF);
-
- /**
- * Tests if URLEncode.encode(String) and
- * URLDecode.decode(String,boolean) methods
- * work correctly together, both with safe
- * characters and not safe "base" (i.e. ASCII) chars .
- */
- public void testEncodeDecodeString_notSafeBaseChars() {
- String[] toEncode = {
- //safe chars
- URLEncoder.safeURLCharacters,
- prtblAscii,
- //triple % char, if badly encoded it will
generate an exception
- "%%%",
- //no chars
- ""};
- try {
- assertTrue(areCorrectlyEncodedDecoded(toEncode));
- } catch (URLEncodedFormatException anException) {
- fail("Not expected exception thrown : " +
anException.getMessage()); }
- }
-
- /**
- * Tests if URLEncode.encode(String) and
- * URLDecode.decode(String,boolean) methods
- * work correctly together, both with safe
- * characters and not safe "advanced" (i.e. not ASCII) chars .
- */
- public void testEncodeDecodeString_notSafeAdvChars() {
- String[] toEncode = {stressedUTF_8Chars};
- try {
- assertTrue(areCorrectlyEncodedDecoded(toEncode));
- } catch (URLEncodedFormatException anException) {
- fail("Not expected exception thrown : " +
anException.getMessage()); }
- }
-
- /**
- * Verifies if a string is the same after
- * being processed by encoding and
- * decoding methods
- * @param toEncode String to Encode
- * @return true means to be tolerant of bogus escapes
- * @throws URLEncodedFormatException
- */
- private boolean areCorrectlyEncodedDecoded(String[] toEncode) throws
URLEncodedFormatException {
- boolean retValue = true;
- String[] encoded = new String[toEncode.length];
- //encoding
- for (int i = 0; i < encoded.length; i++)
- encoded[i] = URLEncoder.encode(toEncode[i]);
- //decoding
- for (int i = 0; i < encoded.length; i++)
- retValue &=
(URLDecoder.decode(encoded[i],false)).equals(toEncode[i]);
- return retValue;
- }
-
- /**
- * Tests encode(String,String,boolean) method
- * to verify if the force parameter is
- * well-managed for each safeURLCharacter,
- * with both true and false ascii-flag.
- */
- public void testEncodeForced() {
- String toEncode,expectedResult;
- char eachChar;
- for(int i=0; i<URLEncoder.safeURLCharacters.length(); i++) {
- eachChar = URLEncoder.safeURLCharacters.charAt(i);
- toEncode = String.valueOf(eachChar);
- try {
- expectedResult = "%"+ HexUtil.bytesToHex(
- //since safe chars are only
US-ASCII
- toEncode.getBytes("US-ASCII"));
-
assertEquals(URLEncoder.encode(toEncode,toEncode,false),
- expectedResult);
-
assertEquals(URLEncoder.encode(toEncode,toEncode,true),
- expectedResult);
- } catch (UnsupportedEncodingException anException) {
- fail("Not expected exception thrown : " +
anException.getMessage()); }
- }
- }
-
-
- /**
- * Verifies if a URLEncodedFormatException is raised
- * when decoding the provided String
- * @param toDecode the String to decode
- * @param tolerant whether the decoding should be tolerant with
- * @return
- */
- private boolean isDecodeRaisingEncodedException(String toDecode,
boolean tolerant) {
- boolean retValue = false;
- try {
- System.out.println(URLDecoder.decode(toDecode,false));
- } catch (URLEncodedFormatException anException) {
- retValue = true; }
- return retValue;
- }
-
- /**
- * Tests decode(String,boolean) method
- * using not valid encoded String to
- * verifies if it raises an exception
- */
- public void testDecodeWrongString() {
- String toDecode = "%00";
- assertTrue(isDecodeRaisingEncodedException(toDecode,false));
- }
-
- /**
- * Tests decode(String,boolean) method
- * using not valid hex values String to
- * verifies if it raises an exception
- */
- public void testDecodeWrongHex() {
- String toDecode =
"123456789abcde"+prtblAscii+stressedUTF_8Chars;
-
- for (int i = 0; i<toDecode.length(); i++)
- assertTrue(
-
isDecodeRaisingEncodedException("%"+toDecode.substring(i,i+1),false));
- }
-
- /**
- * Tests decode(String,boolean) method
- * trying the boolean argument, to verify
- * if it work correctly as a hack to allow users
- * to paste in URLs containing %'s.
- */
- public void testTolerantDecoding() {
- String toDecode = "%%%";
-
- try {
- assertEquals(URLDecoder.decode(toDecode,true),toDecode);
- } catch (URLEncodedFormatException anException) {
- fail("Not expected exception thrown : " +
anException.getMessage()); }
- }
-}
\ No newline at end of file
Copied: branches/freenet-jfk/test/freenet/support/URLEncoderDecoderTest.java
(from rev 14796, trunk/freenet/test/freenet/support/URLEncoderDecoderTest.java)
===================================================================
--- branches/freenet-jfk/test/freenet/support/URLEncoderDecoderTest.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/support/URLEncoderDecoderTest.java
2007-08-21 20:26:59 UTC (rev 14828)
@@ -0,0 +1,167 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+
+import java.io.UnsupportedEncodingException;
+import freenet.utils.*;
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.URLEncoder} and
+ * {@link freenet.support.URLDecoder} classes.
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public class URLEncoderDecoderTest extends TestCase {
+
+ private String prtblAscii = new String(UTFUtil.PRINTABLE_ASCII);
+ private String stressedUTF_8Chars = new String(UTFUtil.STRESSED_UTF);
+
+ /**
+ * Tests if URLEncode.encode(String) and
+ * URLDecode.decode(String,boolean) methods
+ * work correctly together, both with safe
+ * characters and not safe "base" (i.e. ASCII) chars .
+ */
+ public void testEncodeDecodeString_notSafeBaseChars() {
+ String[] toEncode = {
+ //safe chars
+ URLEncoder.safeURLCharacters,
+ prtblAscii,
+ //triple % char, if badly encoded it will
generate an exception
+ "%%%",
+ //no chars
+ ""};
+ try {
+ assertTrue(areCorrectlyEncodedDecoded(toEncode));
+ } catch (URLEncodedFormatException anException) {
+ fail("Not expected exception thrown : " +
anException.getMessage()); }
+ }
+
+ /**
+ * Tests if URLEncode.encode(String) and
+ * URLDecode.decode(String,boolean) methods
+ * work correctly together, both with safe
+ * characters and not safe "advanced" (i.e. not ASCII) chars .
+ */
+ public void testEncodeDecodeString_notSafeAdvChars() {
+ String[] toEncode = {stressedUTF_8Chars};
+ try {
+ assertTrue(areCorrectlyEncodedDecoded(toEncode));
+ } catch (URLEncodedFormatException anException) {
+ fail("Not expected exception thrown : " +
anException.getMessage()); }
+ }
+
+ /**
+ * Verifies if a string is the same after
+ * being processed by encoding and
+ * decoding methods
+ * @param toEncode String to Encode
+ * @return true means to be tolerant of bogus escapes
+ * @throws URLEncodedFormatException
+ */
+ private boolean areCorrectlyEncodedDecoded(String[] toEncode) throws
URLEncodedFormatException {
+ boolean retValue = true;
+ String[] encoded = new String[toEncode.length];
+ //encoding
+ for (int i = 0; i < encoded.length; i++)
+ encoded[i] = URLEncoder.encode(toEncode[i]);
+ //decoding
+ for (int i = 0; i < encoded.length; i++)
+ retValue &=
(URLDecoder.decode(encoded[i],false)).equals(toEncode[i]);
+ return retValue;
+ }
+
+ /**
+ * Tests encode(String,String,boolean) method
+ * to verify if the force parameter is
+ * well-managed for each safeURLCharacter,
+ * with both true and false ascii-flag.
+ */
+ public void testEncodeForced() {
+ String toEncode,expectedResult;
+ char eachChar;
+ for(int i=0; i<URLEncoder.safeURLCharacters.length(); i++) {
+ eachChar = URLEncoder.safeURLCharacters.charAt(i);
+ toEncode = String.valueOf(eachChar);
+ try {
+ expectedResult = "%"+ HexUtil.bytesToHex(
+ //since safe chars are only
US-ASCII
+ toEncode.getBytes("US-ASCII"));
+
assertEquals(URLEncoder.encode(toEncode,toEncode,false),
+ expectedResult);
+
assertEquals(URLEncoder.encode(toEncode,toEncode,true),
+ expectedResult);
+ } catch (UnsupportedEncodingException anException) {
+ fail("Not expected exception thrown : " +
anException.getMessage()); }
+ }
+ }
+
+
+ /**
+ * Verifies if a URLEncodedFormatException is raised
+ * when decoding the provided String
+ * @param toDecode the String to decode
+ * @param tolerant whether the decoding should be tolerant with
+ * @return
+ */
+ private boolean isDecodeRaisingEncodedException(String toDecode,
boolean tolerant) {
+ boolean retValue = false;
+ try {
+ System.out.println(URLDecoder.decode(toDecode,false));
+ } catch (URLEncodedFormatException anException) {
+ retValue = true; }
+ return retValue;
+ }
+
+ /**
+ * Tests decode(String,boolean) method
+ * using not valid encoded String to
+ * verifies if it raises an exception
+ */
+ public void testDecodeWrongString() {
+ String toDecode = "%00";
+ assertTrue(isDecodeRaisingEncodedException(toDecode,false));
+ }
+
+ /**
+ * Tests decode(String,boolean) method
+ * using not valid hex values String to
+ * verifies if it raises an exception
+ */
+ public void testDecodeWrongHex() {
+ String toDecode =
"123456789abcde"+prtblAscii+stressedUTF_8Chars;
+
+ for (int i = 0; i<toDecode.length(); i++)
+ assertTrue(
+
isDecodeRaisingEncodedException("%"+toDecode.substring(i,i+1),false));
+ }
+
+ /**
+ * Tests decode(String,boolean) method
+ * trying the boolean argument, to verify
+ * if it work correctly as a hack to allow users
+ * to paste in URLs containing %'s.
+ */
+ public void testTolerantDecoding() {
+ String toDecode = "%%%";
+
+ try {
+ assertEquals(URLDecoder.decode(toDecode,true),toDecode);
+ } catch (URLEncodedFormatException anException) {
+ fail("Not expected exception thrown : " +
anException.getMessage()); }
+ }
+}
\ No newline at end of file
Copied: branches/freenet-jfk/test/freenet/utils (from rev 14796,
trunk/freenet/test/freenet/utils)
Deleted: branches/freenet-jfk/test/freenet/utils/UTFUtil.java
===================================================================
--- trunk/freenet/test/freenet/utils/UTFUtil.java 2007-08-18 19:36:17 UTC
(rev 14796)
+++ branches/freenet-jfk/test/freenet/utils/UTFUtil.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -1,147 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package freenet.utils;
-
-import junit.framework.TestCase;
-
-/**
- * Utility class used throught test cases classes
- *
- * @author Alberto Bacchelli <sback at freenetproject.org>
- */
-public final class UTFUtil extends TestCase {
-
- public void testFake() {
-
- }
-
- //printable ascii symbols
- public static final char PRINTABLE_ASCII[] = {
- '
','!','@','#','$','%','^','&','(',')','+','=','{','}','[',']',':',';','\\','\"','\'',
- ',','<','>','.','?','~','`'};
-
- //stressed UTF chars values
- public static final char STRESSED_UTF[] = {
-
//???????????????????????????????????????????????????????????????
-
'\u00c9','\u00e2','\u00fb','\u0114','\u012d','\u0146','\u015f','\u00ca','\u00e3','\u00fc',
-
'\u0115','\u012e','\u0147','\u0160','\u00cb','\u00e4','\u00fd','\u0116','\u012f','\u0148',
-
'\u0161','\u00cc','\u00e5','\u00fe','\u0117','\u0130','\u0149','\u0162','\u00cd','\u00e6',
-
'\u00ff','\u0118','\u0131','\u014a','\u0163','\u00ce','\u00e7','\u0100','\u0119','\u0132',
-
'\u014b','\u0164','\u00cf','\u00e8','\u0101','\u011a','\u0133','\u014c','\u0165','\u00d0',
-
'\u00e9','\u0102','\u011b','\u0134','\u014d','\u0166','\u00d1','\u00ea','\u0103','\u011c',
- '\u0135','\u014e','\u0167',
-
//???????????????????????????????????????????????????????????????
-
'\u00d2','\u00eb','\u0104','\u011d','\u0136','\u014f','\u0168','\u00d3','\u00ec','\u0105',
-
'\u011e','\u0137','\u0150','\u0169','\u00d4','\u00ed','\u0106','\u011f','\u0138','\u0151',
-
'\u016a','\u00d5','\u00ee','\u0107','\u0120','\u0139','\u0152','\u016b','\u00d6','\u00ef',
-
'\u0108','\u0121','\u013a','\u0153','\u016c','\u00d7','\u00f0','\u0109','\u0122','\u013b',
-
'\u0154','\u016d','\u00d8','\u00f1','\u010a','\u0123','\u013c','\u0155','\u016e','\u00d9',
-
'\u00f2','\u010b','\u0124','\u013d','\u0156','\u016f','\u00da','\u00f3','\u010c','\u0125',
- '\u013e','\u0157','\u0170',
- //?????????????????????????????????????????????????
-
'\u00db','\u00f4','\u010d','\u0126','\u013f','\u0158','\u0171','\u00dc','\u00f5','\u010e',
-
'\u0127','\u0140','\u0159','\u0172','\u00dd','\u00f6','\u010f','\u0128','\u0141','\u015a',
-
'\u0173','\u00de','\u00f7','\u0110','\u0129','\u0142','\u015b','\u0174','\u00df','\u00f8',
-
'\u0111','\u012a','\u0143','\u015c','\u0175','\u00e0','\u00f9','\u0112','\u012b','\u0144',
-
'\u015d','\u0176','\u00e1','\u00fa','\u0113','\u012c','\u0145','\u015e','\u0177'};
-
- /*
- * HTML entities ISO-88591
- * see for reference
http://www.w3.org/TR/html4/sgml/entities.html#iso-88591
- */
- public static final String HTML_ENTITIES_UTF[][] = {
- //ISO 8859-1 Symbol Entities
-
{"\u00a1","¡"},{"\u00a2","¢"},{"\u00a3","£"},{"\u00a4","¤"},
-
{"\u00a5","¥"},{"\u00a6","¦"},{"\u00a7","§"},{"\u00a8","¨"},
-
{"\u00a9","©"},{"\u00aa","ª"},{"\u00ab","«"},{"\u00ac","¬"},
- {"\u00ad","­"},{"\u00ae","®"},{"\u00af","¯"},
-
{"\u00b0","°"},{"\u00b1","±"},{"\u00b2","²"},{"\u00b3","³"},
-
{"\u00b4","´"},{"\u00b5","µ"},{"\u00b6","¶"},{"\u00b7","·"},
-
{"\u00b8","¸"},{"\u00b9","¹"},{"\u00ba","º"},{"\u00bb","»"},
-
{"\u00bc","¼"},{"\u00bd","½"},{"\u00be","¾"},{"\u00bf","¿"},
- //ISO 8859-1 Character Entities
-
{"\u00c0","À"},{"\u00c1","Á"},{"\u00c2","Â"},{"\u00c3","Ã"},
-
{"\u00c4","Ä"},{"\u00c5","Å"},{"\u00c6","Æ"},{"\u00c7","Ç"},
-
{"\u00c8","È"},{"\u00c9","É"},{"\u00ca","Ê"},{"\u00cb","Ë"},
-
{"\u00cc","Ì"},{"\u00cd","Í"},{"\u00ce","Î"},{"\u00cf","Ï"},
-
{"\u00d0","Ð"},{"\u00d1","Ñ"},{"\u00d2","Ò"},{"\u00d3","Ó"},
-
{"\u00d4","Ô"},{"\u00d5","Õ"},{"\u00d6","Ö"},{"\u00d7","×"},
-
{"\u00d8","Ø"},{"\u00d9","Ù"},{"\u00da","Ú"},{"\u00db","Û"},
-
{"\u00dc","Ü"},{"\u00dd","Ý"},{"\u00de","Þ"},{"\u00df","ß"},
-
{"\u00e0","à"},{"\u00e1","á"},{"\u00e2","â"},{"\u00e3","ã"},
-
{"\u00e4","ä"},{"\u00e5","å"},{"\u00e6","æ"},{"\u00e7","ç"},
-
{"\u00e8","è"},{"\u00e9","é"},{"\u00ea","ê"},{"\u00eb","ë"},
-
{"\u00ec","ì"},{"\u00ed","í"},{"\u00ee","î"},{"\u00ef","ï"},
- {"\u00f0","ð"},{"\u00f1","ñ"},
-
{"\u00f2","ò"},{"\u00f3","ó"},{"\u00f4","ô"},{"\u00f5","õ"},
- {"\u00f6","ö"},{"\u00f7","÷"},{"\u00f8","ø"},
-
{"\u00f9","ù"},{"\u00fa","ú"},{"\u00fb","û"},{"\u00fc","ü"},
- {"\u00fd","ý"},{"\u00fe","þ"},{"\u00ff","ÿ"},
- //Greek
-
{"\u0391","Α"},{"\u0392","Β"},{"\u0393","Γ"},{"\u0394","Δ"},
-
{"\u0395","Ε"},{"\u0396","Ζ"},{"\u0397","Η"},{"\u0398","Θ"},
-
{"\u0399","Ι"},{"\u039a","Κ"},{"\u039b","Λ"},{"\u039c","Μ"},
-
{"\u039d","Ν"},{"\u039e","Ξ"},{"\u039f","Ο"},{"\u03a0","Π"},
-
{"\u03a1","Ρ"},{"\u03a3","Σ"},{"\u03a4","Τ"},{"\u03a5","Υ"},
-
{"\u03a6","Φ"},{"\u03a7","Χ"},{"\u03a8","Ψ"},{"\u03a9","Ω"},
-
{"\u03b1","α"},{"\u03b2","β"},{"\u03b3","γ"},{"\u03b4","δ"},
-
{"\u03b5","ε"},{"\u03b6","ζ"},{"\u03b7","η"},{"\u03b8","θ"},
-
{"\u03b9","ι"},{"\u03ba","κ"},{"\u03bb","λ"},{"\u03bc","μ"},
-
{"\u03bd","ν"},{"\u03be","ξ"},{"\u03bf","ο"},{"\u03c0","π"},
-
{"\u03c1","ρ"},{"\u03c2","ς"},{"\u03c3","σ"},{"\u03c4","τ"},
-
{"\u03c5","υ"},{"\u03c6","φ"},{"\u03c7","χ"},{"\u03c8","ψ"},
-
{"\u03c9","ω"},{"\u03d1","ϑ"},{"\u03d2","ϒ"},{"\u03d6","ϖ"},
- //General Punctuation
-
{"\u2022","•"},{"\u2026","…"},{"\u2032","′"},{"\u2033","″"},
- {"\u203e","‾"},{"\u2044","⁄"},
- //Letterlike Symbols
-
{"\u2118","℘"},{"\u2111","ℑ"},{"\u211c","ℜ"},{"\u2122","™"},
- {"\u2135","ℵ"},
- //Arrows
-
{"\u2190","←"},{"\u2191","↑"},{"\u2192","→"},{"\u2193","↓"},
-
{"\u2194","↔"},{"\u21b5","↵"},{"\u21d0","⇐"},{"\u21d1","⇑"},
- {"\u21d2","⇒"},{"\u21d3","⇓"},{"\u21d4","⇔"},
- //Mathematical Operators
-
{"\u2200","∀"},{"\u2202","∂"},{"\u2203","∃"},{"\u2205","∅"},
-
{"\u2207","∇"},{"\u2208","∈"},{"\u2209","∉"},{"\u220b","∋"},
-
{"\u220f","∏"},{"\u2211","∑"},{"\u2212","−"},{"\u2217","∗"},
-
{"\u221a","√"},{"\u221d","∝"},{"\u221e","∞"},{"\u2220","∠"},
-
{"\u2227","∧"},{"\u2228","∨"},{"\u2229","∩"},{"\u222a","∪"},
-
{"\u222b","∫"},{"\u2234","∴"},{"\u223c","∼"},{"\u2245","≅"},
-
{"\u2248","≈"},{"\u2260","≠"},{"\u2261","≡"},{"\u2264","≤"},
-
{"\u2265","≥"},{"\u2282","⊂"},{"\u2283","⊃"},{"\u2284","⊄"},
-
{"\u2286","⊆"},{"\u2287","⊇"},{"\u2295","⊕"},{"\u2297","⊗"},
- {"\u22a5","⊥"},{"\u22c5","⋅"},
- //Miscellaneous Technical
-
{"\u2308","⌈"},{"\u2309","⌉"},{"\u230a","⌊"},{"\u230b","⌋"},
- {"\u2329","⟨"},{"\u232a","⟩"},
- //Geometric Shapes
-
{"\u25ca","◊"},{"\u2660","♠"},{"\u2663","♣"},{"\u2665","♥"},
- {"\u2666","♦"},
- //Latin Extended-A
-
{"\u0152","Œ"},{"\u0153","œ"},{"\u0160","Š"},{"\u0161","š"},
- {"\u0178","Ÿ"},
- //Spacing Modifier Letters
- {"\u02c6","ˆ"},{"\u02dc","˜"},
- //General Punctuation
-
{"\u2002"," "},{"\u2003"," "},{"\u2009"," "},{"\u200c","‌"},
-
{"\u200d","‍"},{"\u200e","‎"},{"\u200f","‏"},{"\u2013","–"},
-
{"\u2014","—"},{"\u2018","‘"},{"\u2019","’"},{"\u201a","‚"},
-
{"\u201c","“"},{"\u201d","”"},{"\u201e","„"},{"\u2020","†"},
-
{"\u2021","‡"},{"\u2030","‰"},{"\u2039","‹"},{"\u203a","›"},
- {"\u20ac","€"}
- };
-}
Copied: branches/freenet-jfk/test/freenet/utils/UTFUtil.java (from rev 14796,
trunk/freenet/test/freenet/utils/UTFUtil.java)
===================================================================
--- branches/freenet-jfk/test/freenet/utils/UTFUtil.java
(rev 0)
+++ branches/freenet-jfk/test/freenet/utils/UTFUtil.java 2007-08-21
20:26:59 UTC (rev 14828)
@@ -0,0 +1,147 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.utils;
+
+import junit.framework.TestCase;
+
+/**
+ * Utility class used throught test cases classes
+ *
+ * @author Alberto Bacchelli <sback at freenetproject.org>
+ */
+public final class UTFUtil extends TestCase {
+
+ public void testFake() {
+
+ }
+
+ //printable ascii symbols
+ public static final char PRINTABLE_ASCII[] = {
+ '
','!','@','#','$','%','^','&','(',')','+','=','{','}','[',']',':',';','\\','\"','\'',
+ ',','<','>','.','?','~','`'};
+
+ //stressed UTF chars values
+ public static final char STRESSED_UTF[] = {
+
//???????????????????????????????????????????????????????????????
+
'\u00c9','\u00e2','\u00fb','\u0114','\u012d','\u0146','\u015f','\u00ca','\u00e3','\u00fc',
+
'\u0115','\u012e','\u0147','\u0160','\u00cb','\u00e4','\u00fd','\u0116','\u012f','\u0148',
+
'\u0161','\u00cc','\u00e5','\u00fe','\u0117','\u0130','\u0149','\u0162','\u00cd','\u00e6',
+
'\u00ff','\u0118','\u0131','\u014a','\u0163','\u00ce','\u00e7','\u0100','\u0119','\u0132',
+
'\u014b','\u0164','\u00cf','\u00e8','\u0101','\u011a','\u0133','\u014c','\u0165','\u00d0',
+
'\u00e9','\u0102','\u011b','\u0134','\u014d','\u0166','\u00d1','\u00ea','\u0103','\u011c',
+ '\u0135','\u014e','\u0167',
+
//???????????????????????????????????????????????????????????????
+
'\u00d2','\u00eb','\u0104','\u011d','\u0136','\u014f','\u0168','\u00d3','\u00ec','\u0105',
+
'\u011e','\u0137','\u0150','\u0169','\u00d4','\u00ed','\u0106','\u011f','\u0138','\u0151',
+
'\u016a','\u00d5','\u00ee','\u0107','\u0120','\u0139','\u0152','\u016b','\u00d6','\u00ef',
+
'\u0108','\u0121','\u013a','\u0153','\u016c','\u00d7','\u00f0','\u0109','\u0122','\u013b',
+
'\u0154','\u016d','\u00d8','\u00f1','\u010a','\u0123','\u013c','\u0155','\u016e','\u00d9',
+
'\u00f2','\u010b','\u0124','\u013d','\u0156','\u016f','\u00da','\u00f3','\u010c','\u0125',
+ '\u013e','\u0157','\u0170',
+ //?????????????????????????????????????????????????
+
'\u00db','\u00f4','\u010d','\u0126','\u013f','\u0158','\u0171','\u00dc','\u00f5','\u010e',
+
'\u0127','\u0140','\u0159','\u0172','\u00dd','\u00f6','\u010f','\u0128','\u0141','\u015a',
+
'\u0173','\u00de','\u00f7','\u0110','\u0129','\u0142','\u015b','\u0174','\u00df','\u00f8',
+
'\u0111','\u012a','\u0143','\u015c','\u0175','\u00e0','\u00f9','\u0112','\u012b','\u0144',
+
'\u015d','\u0176','\u00e1','\u00fa','\u0113','\u012c','\u0145','\u015e','\u0177'};
+
+ /*
+ * HTML entities ISO-88591
+ * see for reference
http://www.w3.org/TR/html4/sgml/entities.html#iso-88591
+ */
+ public static final String HTML_ENTITIES_UTF[][] = {
+ //ISO 8859-1 Symbol Entities
+
{"\u00a1","¡"},{"\u00a2","¢"},{"\u00a3","£"},{"\u00a4","¤"},
+
{"\u00a5","¥"},{"\u00a6","¦"},{"\u00a7","§"},{"\u00a8","¨"},
+
{"\u00a9","©"},{"\u00aa","ª"},{"\u00ab","«"},{"\u00ac","¬"},
+ {"\u00ad","­"},{"\u00ae","®"},{"\u00af","¯"},
+
{"\u00b0","°"},{"\u00b1","±"},{"\u00b2","²"},{"\u00b3","³"},
+
{"\u00b4","´"},{"\u00b5","µ"},{"\u00b6","¶"},{"\u00b7","·"},
+
{"\u00b8","¸"},{"\u00b9","¹"},{"\u00ba","º"},{"\u00bb","»"},
+
{"\u00bc","¼"},{"\u00bd","½"},{"\u00be","¾"},{"\u00bf","¿"},
+ //ISO 8859-1 Character Entities
+
{"\u00c0","À"},{"\u00c1","Á"},{"\u00c2","Â"},{"\u00c3","Ã"},
+
{"\u00c4","Ä"},{"\u00c5","Å"},{"\u00c6","Æ"},{"\u00c7","Ç"},
+
{"\u00c8","È"},{"\u00c9","É"},{"\u00ca","Ê"},{"\u00cb","Ë"},
+
{"\u00cc","Ì"},{"\u00cd","Í"},{"\u00ce","Î"},{"\u00cf","Ï"},
+
{"\u00d0","Ð"},{"\u00d1","Ñ"},{"\u00d2","Ò"},{"\u00d3","Ó"},
+
{"\u00d4","Ô"},{"\u00d5","Õ"},{"\u00d6","Ö"},{"\u00d7","×"},
+
{"\u00d8","Ø"},{"\u00d9","Ù"},{"\u00da","Ú"},{"\u00db","Û"},
+
{"\u00dc","Ü"},{"\u00dd","Ý"},{"\u00de","Þ"},{"\u00df","ß"},
+
{"\u00e0","à"},{"\u00e1","á"},{"\u00e2","â"},{"\u00e3","ã"},
+
{"\u00e4","ä"},{"\u00e5","å"},{"\u00e6","æ"},{"\u00e7","ç"},
+
{"\u00e8","è"},{"\u00e9","é"},{"\u00ea","ê"},{"\u00eb","ë"},
+
{"\u00ec","ì"},{"\u00ed","í"},{"\u00ee","î"},{"\u00ef","ï"},
+ {"\u00f0","ð"},{"\u00f1","ñ"},
+
{"\u00f2","ò"},{"\u00f3","ó"},{"\u00f4","ô"},{"\u00f5","õ"},
+ {"\u00f6","ö"},{"\u00f7","÷"},{"\u00f8","ø"},
+
{"\u00f9","ù"},{"\u00fa","ú"},{"\u00fb","û"},{"\u00fc","ü"},
+ {"\u00fd","ý"},{"\u00fe","þ"},{"\u00ff","ÿ"},
+ //Greek
+
{"\u0391","Α"},{"\u0392","Β"},{"\u0393","Γ"},{"\u0394","Δ"},
+
{"\u0395","Ε"},{"\u0396","Ζ"},{"\u0397","Η"},{"\u0398","Θ"},
+
{"\u0399","Ι"},{"\u039a","Κ"},{"\u039b","Λ"},{"\u039c","Μ"},
+
{"\u039d","Ν"},{"\u039e","Ξ"},{"\u039f","Ο"},{"\u03a0","Π"},
+
{"\u03a1","Ρ"},{"\u03a3","Σ"},{"\u03a4","Τ"},{"\u03a5","Υ"},
+
{"\u03a6","Φ"},{"\u03a7","Χ"},{"\u03a8","Ψ"},{"\u03a9","Ω"},
+
{"\u03b1","α"},{"\u03b2","β"},{"\u03b3","γ"},{"\u03b4","δ"},
+
{"\u03b5","ε"},{"\u03b6","ζ"},{"\u03b7","η"},{"\u03b8","θ"},
+
{"\u03b9","ι"},{"\u03ba","κ"},{"\u03bb","λ"},{"\u03bc","μ"},
+
{"\u03bd","ν"},{"\u03be","ξ"},{"\u03bf","ο"},{"\u03c0","π"},
+
{"\u03c1","ρ"},{"\u03c2","ς"},{"\u03c3","σ"},{"\u03c4","τ"},
+
{"\u03c5","υ"},{"\u03c6","φ"},{"\u03c7","χ"},{"\u03c8","ψ"},
+
{"\u03c9","ω"},{"\u03d1","ϑ"},{"\u03d2","ϒ"},{"\u03d6","ϖ"},
+ //General Punctuation
+
{"\u2022","•"},{"\u2026","…"},{"\u2032","′"},{"\u2033","″"},
+ {"\u203e","‾"},{"\u2044","⁄"},
+ //Letterlike Symbols
+
{"\u2118","℘"},{"\u2111","ℑ"},{"\u211c","ℜ"},{"\u2122","™"},
+ {"\u2135","ℵ"},
+ //Arrows
+
{"\u2190","←"},{"\u2191","↑"},{"\u2192","→"},{"\u2193","↓"},
+
{"\u2194","↔"},{"\u21b5","↵"},{"\u21d0","⇐"},{"\u21d1","⇑"},
+ {"\u21d2","⇒"},{"\u21d3","⇓"},{"\u21d4","⇔"},
+ //Mathematical Operators
+
{"\u2200","∀"},{"\u2202","∂"},{"\u2203","∃"},{"\u2205","∅"},
+
{"\u2207","∇"},{"\u2208","∈"},{"\u2209","∉"},{"\u220b","∋"},
+
{"\u220f","∏"},{"\u2211","∑"},{"\u2212","−"},{"\u2217","∗"},
+
{"\u221a","√"},{"\u221d","∝"},{"\u221e","∞"},{"\u2220","∠"},
+
{"\u2227","∧"},{"\u2228","∨"},{"\u2229","∩"},{"\u222a","∪"},
+
{"\u222b","∫"},{"\u2234","∴"},{"\u223c","∼"},{"\u2245","≅"},
+
{"\u2248","≈"},{"\u2260","≠"},{"\u2261","≡"},{"\u2264","≤"},
+
{"\u2265","≥"},{"\u2282","⊂"},{"\u2283","⊃"},{"\u2284","⊄"},
+
{"\u2286","⊆"},{"\u2287","⊇"},{"\u2295","⊕"},{"\u2297","⊗"},
+ {"\u22a5","⊥"},{"\u22c5","⋅"},
+ //Miscellaneous Technical
+
{"\u2308","⌈"},{"\u2309","⌉"},{"\u230a","⌊"},{"\u230b","⌋"},
+ {"\u2329","⟨"},{"\u232a","⟩"},
+ //Geometric Shapes
+
{"\u25ca","◊"},{"\u2660","♠"},{"\u2663","♣"},{"\u2665","♥"},
+ {"\u2666","♦"},
+ //Latin Extended-A
+
{"\u0152","Œ"},{"\u0153","œ"},{"\u0160","Š"},{"\u0161","š"},
+ {"\u0178","Ÿ"},
+ //Spacing Modifier Letters
+ {"\u02c6","ˆ"},{"\u02dc","˜"},
+ //General Punctuation
+
{"\u2002"," "},{"\u2003"," "},{"\u2009"," "},{"\u200c","‌"},
+
{"\u200d","‍"},{"\u200e","‎"},{"\u200f","‏"},{"\u2013","–"},
+
{"\u2014","—"},{"\u2018","‘"},{"\u2019","’"},{"\u201a","‚"},
+
{"\u201c","“"},{"\u201d","”"},{"\u201e","„"},{"\u2020","†"},
+
{"\u2021","‡"},{"\u2030","‰"},{"\u2039","‹"},{"\u203a","›"},
+ {"\u20ac","€"}
+ };
+}