+++ /dev/null
-/*
- * 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
- * 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 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;
-import java.net.Socket;
-import java.util.StringTokenizer;
-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 {
-
- /** Counter for unique identifiers. */
- private static AtomicLong counter = new AtomicLong();
-
- /**
- * Returns a unique identifier.
- *
- * @return A unique identifier
- */
- public static String getUniqueIdentifier() {
- return new StringBuilder().append(System.currentTimeMillis()).append('-').append(counter.getAndIncrement()).toString();
- }
-
- /**
- * Parses an integer field, separated by ‘;’ and returns the parsed values.
- *
- * @param field
- * The field to parse
- * @return An array with the parsed values
- * @throws NumberFormatException
- * if a value can not be converted to a number
- */
- public static int[] decodeMultiIntegerField(String field) throws NumberFormatException {
- StringTokenizer fieldTokens = new StringTokenizer(field, ";");
- int[] result = new int[fieldTokens.countTokens()];
- int counter = 0;
- while (fieldTokens.hasMoreTokens()) {
- String fieldToken = fieldTokens.nextToken();
- result[counter++] = Integer.valueOf(fieldToken);
- }
- return result;
- }
-
- /**
- * 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) {
- if (encodedField.length() > 0) {
- encodedField.append(';');
- }
- encodedField.append(value);
- }
- return encodedField.toString();
- }
-
- /**
- * 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) {
- if (encodedField.length() > 0) {
- encodedField.append(';');
- }
- encodedField.append(value);
- }
- return encodedField.toString();
- }
-
- /**
- * Tries to parse the given string into an int, returning <code>-1</code> if
- * the string can not be parsed.
- *
- * @param value
- * The string to parse
- * @return The parsed int, or <code>-1</code>
- */
- public static int safeParseInt(String value) {
- return safeParseInt(value, -1);
- }
-
- /**
- * Tries to parse the given string into an int, returning
- * <code>defaultValue</code> if the string can not be parsed.
- *
- * @param value
- * The string to parse
- * @param defaultValue
- * The value to return if the string can not be parsed.
- * @return The parsed int, or <code>defaultValue</code>
- */
- public static int safeParseInt(String value, int defaultValue) {
- try {
- return Integer.valueOf(value);
- } catch (NumberFormatException nfe1) {
- return defaultValue;
- }
- }
-
- /**
- * Tries to parse the given string into an long, returning <code>-1</code>
- * if the string can not be parsed.
- *
- * @param value
- * The string to parse
- * @return The parsed long, or <code>-1</code>
- */
- public static long safeParseLong(String value) {
- return safeParseLong(value, -1);
- }
-
- /**
- * Tries to parse the given string into an long, returning
- * <code>defaultValue</code> if the string can not be parsed.
- *
- * @param value
- * The string to parse
- * @param defaultValue
- * The value to return if the string can not be parsed.
- * @return The parsed long, or <code>defaultValue</code>
- */
- public static long safeParseLong(String value, long defaultValue) {
- try {
- return Integer.valueOf(value);
- } catch (NumberFormatException nfe1) {
- return defaultValue;
- }
- }
-
- /**
- * Closes the given socket.
- *
- * @param socket
- * The socket to close
- */
- public static void close(Socket socket) {
- if (socket != null) {
- try {
- socket.close();
- } catch (IOException ioe1) {
- /* ignore. */
- }
- }
- }
-
- /**
- * Closes the given Closeable.
- *
- * @param closeable
- * The Closeable to close
- */
- public static void close(Closeable closeable) {
- if (closeable != null) {
- try {
- closeable.close();
- } catch (IOException ioe1) {
- /* ignore. */
- }
- }
- }
-
- /**
- * Copies as many bytes as possible (i.e. until {@link InputStream#read()}
- * returns <code>-1</code>) from the source input stream to the destination
- * output stream.
- *
- * @param source
- * The input stream to read from
- * @param destination
- * The output stream to write to
- * @throws IOException
- * if an I/O error occurs
- */
- public static void copy(InputStream source, OutputStream destination) throws IOException {
- copy(source, destination, -1);
- }
-
- /**
- * Copies <code>length</code> bytes from the source input stream to the
- * destination output stream. If <code>length</code> is <code>-1</code> as
- * much bytes as possible will be copied (i.e. until
- * {@link InputStream#read()} returns <code>-1</code> to signal the end of
- * the stream).
- *
- * @param source
- * The input stream to read from
- * @param destination
- * The output stream to write to
- * @param length
- * The number of bytes to copy
- * @throws IOException
- * if an I/O error occurs
- */
- public static void copy(InputStream source, OutputStream destination, long length) throws IOException {
- copy(source, destination, length, 1 << 16);
- }
-
- /**
- * Copies <code>length</code> bytes from the source input stream to the
- * destination output stream. If <code>length</code> is <code>-1</code> as
- * much bytes as possible will be copied (i.e. until
- * {@link InputStream#read()} returns <code>-1</code> to signal the end of
- * the stream).
- *
- * @param source
- * The input stream to read from
- * @param destination
- * The output stream to write to
- * @param length
- * The number of bytes to copy
- * @param bufferSize
- * The buffer size
- * @throws IOException
- * if an I/O error occurs
- */
- public static void copy(InputStream source, OutputStream destination, long length, int bufferSize) throws IOException {
- long remaining = length;
- byte[] buffer = new byte[bufferSize];
- int read = 0;
- while ((remaining == -1) || (remaining > 0)) {
- read = source.read(buffer, 0, ((remaining > bufferSize) || (remaining == -1)) ? bufferSize : (int) remaining);
- if (read == -1) {
- if (length == -1) {
- return;
- }
- throw new EOFException("stream reached eof");
- }
- destination.write(buffer, 0, read);
- remaining -= read;
- }
- }
-
- /**
- * 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 <code>maxMemoryLength</code>,
- * 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);
- }
-
- }
-
-}