2 * jSite2 - FcpUtils.java -
3 * Copyright © 2008 David Roden
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 package net.pterodactylus.fcp;
22 import java.io.Closeable;
23 import java.io.EOFException;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.net.Socket;
28 import java.util.StringTokenizer;
29 import java.util.concurrent.atomic.AtomicLong;
32 * Helper class with utility methods for the FCP protocol.
34 * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
36 public class FcpUtils {
38 /** Counter for unique identifiers. */
39 private static AtomicLong counter = new AtomicLong();
42 * Returns a unique identifier.
44 * @return A unique identifier
46 public static String getUniqueIdentifier() {
47 return new StringBuilder().append(System.currentTimeMillis()).append('-').append(counter.getAndIncrement()).toString();
51 * Parses an integer field, separated by ‘;’ and returns the parsed values.
55 * @return An array with the parsed values
56 * @throws NumberFormatException
57 * if a value can not be converted to a number
59 public static int[] decodeMultiIntegerField(String field) throws NumberFormatException {
60 StringTokenizer fieldTokens = new StringTokenizer(field, ";");
61 int[] result = new int[fieldTokens.countTokens()];
63 while (fieldTokens.hasMoreTokens()) {
64 String fieldToken = fieldTokens.nextToken();
65 result[counter++] = Integer.valueOf(fieldToken);
71 * Encodes the given integer array into a string, separating the values by
75 * The values to encode
76 * @return The encoded values
78 public static String encodeMultiIntegerField(int[] values) {
79 StringBuilder encodedField = new StringBuilder();
80 for (int value: values) {
81 if (encodedField.length() > 0) {
82 encodedField.append(';');
84 encodedField.append(value);
86 return encodedField.toString();
90 * Encodes the given string array into a string, separating the values by
94 * The values to encode
95 * @return The encoded values
97 public static String encodeMultiStringField(String[] values) {
98 StringBuilder encodedField = new StringBuilder();
99 for (String value: values) {
100 if (encodedField.length() > 0) {
101 encodedField.append(';');
103 encodedField.append(value);
105 return encodedField.toString();
109 * Tries to parse the given string into an int, returning <code>-1</code>
110 * if the string can not be parsed.
113 * The string to parse
114 * @return The parsed int, or <code>-1</code>
116 public static int safeParseInt(String value) {
117 return safeParseInt(value, -1);
121 * Tries to parse the given string into an int, returning
122 * <code>defaultValue</code> if the string can not be parsed.
125 * The string to parse
126 * @param defaultValue
127 * The value to return if the string can not be parsed.
128 * @return The parsed int, or <code>defaultValue</code>
130 public static int safeParseInt(String value, int defaultValue) {
132 return Integer.valueOf(value);
133 } catch (NumberFormatException nfe1) {
139 * Tries to parse the given string into an long, returning <code>-1</code>
140 * if the string can not be parsed.
143 * The string to parse
144 * @return The parsed long, or <code>-1</code>
146 public static long safeParseLong(String value) {
147 return safeParseLong(value, -1);
151 * Tries to parse the given string into an long, returning
152 * <code>defaultValue</code> if the string can not be parsed.
155 * The string to parse
156 * @param defaultValue
157 * The value to return if the string can not be parsed.
158 * @return The parsed long, or <code>defaultValue</code>
160 public static long safeParseLong(String value, long defaultValue) {
162 return Integer.valueOf(value);
163 } catch (NumberFormatException nfe1) {
169 * Closes the given socket.
172 * The socket to close
174 public static void close(Socket socket) {
175 if (socket != null) {
178 } catch (IOException ioe1) {
185 * Closes the given Closeable.
188 * The Closeable to close
190 public static void close(Closeable closeable) {
191 if (closeable != null) {
194 } catch (IOException ioe1) {
201 * Copies as many bytes as possible (i.e. until {@link InputStream#read()}
202 * returns <code>-1</code>) from the source input stream to the
203 * destination output stream.
206 * The input stream to read from
208 * The output stream to write to
209 * @throws IOException
210 * if an I/O error occurs
212 public static void copy(InputStream source, OutputStream destination) throws IOException {
213 copy(source, destination, -1);
217 * Copies <code>length</code> bytes from the source input stream to the
218 * destination output stream. If <code>length</code> is <code>-1</code>
219 * as much bytes as possible will be copied (i.e. until
220 * {@link InputStream#read()} returns <code>-1</code> to signal the end of
224 * The input stream to read from
226 * The output stream to write to
228 * The number of bytes to copy
229 * @throws IOException
230 * if an I/O error occurs
232 public static void copy(InputStream source, OutputStream destination, long length) throws IOException {
233 copy(source, destination, length, 1 << 16);
237 * Copies <code>length</code> bytes from the source input stream to the
238 * destination output stream. If <code>length</code> is <code>-1</code>
239 * as much bytes as possible will be copied (i.e. until
240 * {@link InputStream#read()} returns <code>-1</code> to signal the end of
244 * The input stream to read from
246 * The output stream to write to
248 * The number of bytes to copy
251 * @throws IOException
252 * if an I/O error occurs
254 public static void copy(InputStream source, OutputStream destination, long length, int bufferSize) throws IOException {
255 long remaining = length;
256 byte[] buffer = new byte[bufferSize];
258 while ((remaining == -1) || (remaining > 0)) {
259 read = source.read(buffer, 0, ((remaining > bufferSize) || (remaining == -1)) ? bufferSize : (int) remaining);
264 throw new EOFException("stream reached eof");
266 destination.write(buffer, 0, read);