X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fnet%2Fpterodactylus%2Ffcp%2FFcpUtils.java;h=095708366bec6b54823f8daa6ce0ec105355d771;hb=a655177a4605236e866ac7e0ce32f7cb5289cbc4;hp=6f4ef45066ba662515e02db0d5a81f59d2c9ebb6;hpb=0df9aebe7aa2bb808c95a27b88cb6febb03c0b68;p=jFCPlib.git
diff --git a/src/net/pterodactylus/fcp/FcpUtils.java b/src/net/pterodactylus/fcp/FcpUtils.java
index 6f4ef45..0957083 100644
--- a/src/net/pterodactylus/fcp/FcpUtils.java
+++ b/src/net/pterodactylus/fcp/FcpUtils.java
@@ -1,6 +1,5 @@
/*
- * jSite2 - FcpUtils.java -
- * Copyright © 2008 David Roden
+ * jFCPlib - FcpUtils.java - Copyright © 2008 David Roden
*
* 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
@@ -19,8 +18,13 @@
package net.pterodactylus.fcp;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -30,7 +34,7 @@ import java.util.concurrent.atomic.AtomicLong;
/**
* Helper class with utility methods for the FCP protocol.
- *
+ *
* @author David âBombeâ Roden <bombe@freenetproject.org>
*/
public class FcpUtils {
@@ -40,7 +44,7 @@ public class FcpUtils {
/**
* Returns a unique identifier.
- *
+ *
* @return A unique identifier
*/
public static String getUniqueIdentifier() {
@@ -49,7 +53,7 @@ public class FcpUtils {
/**
* Parses an integer field, separated by â;â and returns the parsed values.
- *
+ *
* @param field
* The field to parse
* @return An array with the parsed values
@@ -70,14 +74,14 @@ public class FcpUtils {
/**
* Encodes the given integer array into a string, separating the values by
* â;â.
- *
+ *
* @param values
* The values to encode
* @return The encoded values
*/
public static String encodeMultiIntegerField(int[] values) {
StringBuilder encodedField = new StringBuilder();
- for (int value: values) {
+ for (int value : values) {
if (encodedField.length() > 0) {
encodedField.append(';');
}
@@ -89,14 +93,14 @@ public class FcpUtils {
/**
* Encodes the given string array into a string, separating the values by
* â;â.
- *
+ *
* @param values
* The values to encode
* @return The encoded values
*/
public static String encodeMultiStringField(String[] values) {
StringBuilder encodedField = new StringBuilder();
- for (String value: values) {
+ for (String value : values) {
if (encodedField.length() > 0) {
encodedField.append(';');
}
@@ -106,9 +110,9 @@ public class FcpUtils {
}
/**
- * Tries to parse the given string into an int, returning -1
- * if the string can not be parsed.
- *
+ * Tries to parse the given string into an int, returning -1
if
+ * the string can not be parsed.
+ *
* @param value
* The string to parse
* @return The parsed int, or -1
@@ -120,7 +124,7 @@ public class FcpUtils {
/**
* Tries to parse the given string into an int, returning
* defaultValue
if the string can not be parsed.
- *
+ *
* @param value
* The string to parse
* @param defaultValue
@@ -138,7 +142,7 @@ public class FcpUtils {
/**
* Tries to parse the given string into an long, returning -1
* if the string can not be parsed.
- *
+ *
* @param value
* The string to parse
* @return The parsed long, or -1
@@ -150,7 +154,7 @@ public class FcpUtils {
/**
* Tries to parse the given string into an long, returning
* defaultValue
if the string can not be parsed.
- *
+ *
* @param value
* The string to parse
* @param defaultValue
@@ -167,7 +171,7 @@ public class FcpUtils {
/**
* Closes the given socket.
- *
+ *
* @param socket
* The socket to close
*/
@@ -183,7 +187,7 @@ public class FcpUtils {
/**
* Closes the given Closeable.
- *
+ *
* @param closeable
* The Closeable to close
*/
@@ -199,9 +203,9 @@ public class FcpUtils {
/**
* Copies as many bytes as possible (i.e. until {@link InputStream#read()}
- * returns -1
) from the source input stream to the
- * destination output stream.
- *
+ * returns -1
) from the source input stream to the destination
+ * output stream.
+ *
* @param source
* The input stream to read from
* @param destination
@@ -215,11 +219,11 @@ public class FcpUtils {
/**
* Copies length
bytes from the source input stream to the
- * destination output stream. If length
is -1
- * as much bytes as possible will be copied (i.e. until
+ * destination output stream. If length
is -1
as
+ * much bytes as possible will be copied (i.e. until
* {@link InputStream#read()} returns -1
to signal the end of
* the stream).
- *
+ *
* @param source
* The input stream to read from
* @param destination
@@ -235,11 +239,11 @@ public class FcpUtils {
/**
* Copies length
bytes from the source input stream to the
- * destination output stream. If length
is -1
- * as much bytes as possible will be copied (i.e. until
+ * destination output stream. If length
is -1
as
+ * much bytes as possible will be copied (i.e. until
* {@link InputStream#read()} returns -1
to signal the end of
* the stream).
- *
+ *
* @param source
* The input stream to read from
* @param destination
@@ -268,4 +272,198 @@ public class FcpUtils {
}
}
+ /**
+ * This input stream stores the content of another input stream either in a
+ * file or in memory, depending on the length of the input stream.
+ *
+ * @author David âBombeâ Roden <bombe@freenetproject.org>
+ */
+ public static class TempInputStream extends InputStream {
+
+ /** The default maximum lenght for in-memory storage. */
+ public static final long MAX_LENGTH_MEMORY = 65536;
+
+ /** The temporary file to read from. */
+ private final File tempFile;
+
+ /** The input stream that reads from the file. */
+ private final InputStream fileInputStream;
+
+ /** The input stream that reads from memory. */
+ private final InputStream memoryInputStream;
+
+ /**
+ * Creates a new temporary input stream that stores the given input
+ * stream in a temporary file.
+ *
+ * @param originalInputStream
+ * The original input stream
+ * @throws IOException
+ * if an I/O error occurs
+ */
+ public TempInputStream(InputStream originalInputStream) throws IOException {
+ this(originalInputStream, -1);
+ }
+
+ /**
+ * Creates a new temporary input stream that stores the given input
+ * stream in memory if it is shorter than {@link #MAX_LENGTH_MEMORY},
+ * otherwise it is stored in a file.
+ *
+ * @param originalInputStream
+ * The original input stream
+ * @param length
+ * The length of the input stream
+ * @throws IOException
+ * if an I/O error occurs
+ */
+ public TempInputStream(InputStream originalInputStream, long length) throws IOException {
+ this(originalInputStream, length, MAX_LENGTH_MEMORY);
+ }
+
+ /**
+ * Creates a new temporary input stream that stores the given input
+ * stream in memory if it is shorter than maxMemoryLength
,
+ * otherwise it is stored in a file.
+ *
+ * @param originalInputStream
+ * The original input stream
+ * @param length
+ * The length of the input stream
+ * @param maxMemoryLength
+ * The maximum length to store in memory
+ * @throws IOException
+ * if an I/O error occurs
+ */
+ public TempInputStream(InputStream originalInputStream, long length, long maxMemoryLength) throws IOException {
+ if ((length > -1) && (length <= maxMemoryLength)) {
+ ByteArrayOutputStream memoryOutputStream = new ByteArrayOutputStream((int) length);
+ try {
+ FcpUtils.copy(originalInputStream, memoryOutputStream, length, (int) length);
+ } finally {
+ memoryOutputStream.close();
+ }
+ tempFile = null;
+ fileInputStream = null;
+ memoryInputStream = new ByteArrayInputStream(memoryOutputStream.toByteArray());
+ } else {
+ tempFile = File.createTempFile("temp-", ".bin");
+ tempFile.deleteOnExit();
+ FileOutputStream fileOutputStream = null;
+ try {
+ fileOutputStream = new FileOutputStream(tempFile);
+ FcpUtils.copy(originalInputStream, fileOutputStream);
+ fileInputStream = new FileInputStream(tempFile);
+ } finally {
+ FcpUtils.close(fileOutputStream);
+ }
+ memoryInputStream = null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int available() throws IOException {
+ if (memoryInputStream != null) {
+ return memoryInputStream.available();
+ }
+ return fileInputStream.available();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void close() throws IOException {
+ if (memoryInputStream != null) {
+ memoryInputStream.close();
+ return;
+ }
+ tempFile.delete();
+ fileInputStream.close();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void mark(int readlimit) {
+ if (memoryInputStream != null) {
+ memoryInputStream.mark(readlimit);
+ return;
+ }
+ fileInputStream.mark(readlimit);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean markSupported() {
+ if (memoryInputStream != null) {
+ return memoryInputStream.markSupported();
+ }
+ return fileInputStream.markSupported();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read() throws IOException {
+ if (memoryInputStream != null) {
+ return memoryInputStream.read();
+ }
+ return fileInputStream.read();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read(byte[] b) throws IOException {
+ if (memoryInputStream != null) {
+ return memoryInputStream.read(b);
+ }
+ return fileInputStream.read(b);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (memoryInputStream != null) {
+ return memoryInputStream.read(b, off, len);
+ }
+ return fileInputStream.read(b, off, len);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void reset() throws IOException {
+ if (memoryInputStream != null) {
+ memoryInputStream.reset();
+ return;
+ }
+ fileInputStream.reset();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long skip(long n) throws IOException {
+ if (memoryInputStream != null) {
+ return memoryInputStream.skip(n);
+ }
+ return fileInputStream.skip(n);
+ }
+
+ }
+
}