Java tutorial
/* $Id$ Copyright (C) 2003-2012 Virginia Tech. All rights reserved. SEE LICENSE FOR MORE INFORMATION Author: Middleware Services Email: middleware@vt.edu Version: $Revision$ Updated: $Date$ */ package org.ldaptive; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Queue; import java.util.regex.Pattern; import org.apache.commons.codec.binary.Base64; /** * Provides utility methods for this package. * * @author Middleware Services * @version $Revision$ $Date$ */ public final class LdapUtils { /** UTF-8 character set. */ private static final Charset UTF8_CHARSET = Charset.forName("UTF-8"); /** Size of buffer in bytes to use when reading files. */ private static final int READ_BUFFER_SIZE = 128; /** Prime number to assist in calculating hash codes. */ private static final int HASH_CODE_PRIME = 113; /** Pattern to match ipv4 addresses. */ private static final Pattern IPV4_PATTERN = Pattern .compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)" + "(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$"); /** Pattern to match ipv6 addresses. */ private static final Pattern IPV6_STD_PATTERN = Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"); /** Pattern to match ipv6 hex compressed addresses. */ private static final Pattern IPV6_HEX_COMPRESSED_PATTERN = Pattern.compile( "^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::" + "((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$"); /** Prefix used to indicate a classpath resource. */ private static final String CLASSPATH_PREFIX = "classpath:"; /** Prefix used to indicate a file resource. */ private static final String FILE_PREFIX = "file:"; /** Default constructor. */ private LdapUtils() { } /** * This will convert the supplied value to a base64 encoded string. Returns * null if the bytes cannot be encoded. * * @param value to base64 encode * * @return base64 encoded value */ public static String base64Encode(final byte[] value) { return value != null ? new String(Base64.encodeBase64(value), UTF8_CHARSET) : null; } /** * This will convert the supplied value to a base64 encoded string. Returns * null if the string cannot be encoded. * * @param value to base64 encode * * @return base64 encoded value */ public static String base64Encode(final String value) { return value != null ? base64Encode(value.getBytes(UTF8_CHARSET)) : null; } /** * This will convert the supplied value to a UTF-8 encoded string. Returns * null if the bytes cannot be encoded. * * @param value to UTF-8 encode * * @return UTF-8 encoded value */ public static String utf8Encode(final byte[] value) { return value != null ? new String(value, UTF8_CHARSET) : null; } /** * This will convert the supplied value to a UTF-8 encoded byte array. Returns * null if the string cannot be encoded. * * @param value to UTF-8 encode * * @return UTF-8 encoded value */ public static byte[] utf8Encode(final String value) { return value != null ? value.getBytes(UTF8_CHARSET) : null; } /** * This will decode the supplied value as a base64 encoded string to a byte[]. * * @param value to base64 decode * * @return base64 decoded value */ public static byte[] base64Decode(final String value) { return value != null ? Base64.decodeBase64(value.getBytes()) : null; } /** * Reads the data at the supplied URL and returns it as a byte array. * * @param url to read * * @return bytes read from the URL * * @throws IOException if an error occurs reading data */ public static byte[] readURL(final URL url) throws IOException { return readInputStream(url.openStream()); } /** * Reads the data in the supplied stream and returns it as a byte array. * * @param is stream to read * * @return bytes read from the stream * * @throws IOException if an error occurs reading data */ public static byte[] readInputStream(final InputStream is) throws IOException { final ByteArrayOutputStream data = new ByteArrayOutputStream(); try { final byte[] buffer = new byte[READ_BUFFER_SIZE]; int length; while ((length = is.read(buffer)) != -1) { data.write(buffer, 0, length); } } finally { is.close(); data.close(); } return data.toByteArray(); } /** * Concatenates multiple arrays together. * * @param <T> type of array * @param first array to concatenate. Cannot be null. * @param rest of the arrays to concatenate. May be null. * * @return array containing the concatenation of all parameters */ public static <T> T[] concatArrays(final T[] first, final T[]... rest) { int totalLength = first.length; for (T[] array : rest) { if (array != null) { totalLength += array.length; } } final T[] result = Arrays.copyOf(first, totalLength); int offset = first.length; for (T[] array : rest) { if (array != null) { System.arraycopy(array, 0, result, offset, array.length); offset += array.length; } } return result; } /** * Determines equality of the supplied objects by delegating to their hashCode * methods. * * @param o1 to test equality of * @param o2 to test equality of * * @return whether o1 equals o2 */ public static boolean areEqual(final Object o1, final Object o2) { if (o1 == null) { return o2 == null; } return o2 != null && (o1 == o2 || o1.getClass() == o2.getClass() && o1.hashCode() == o2.hashCode()); } /** * Computes a hash code for the supplied objects using the supplied seed. If a * Collection type is found it is iterated over. * * @param seed odd/prime number * @param objects to calculate hashCode for * * @return hash code for the supplied objects */ public static int computeHashCode(final int seed, final Object... objects) { if (objects == null || objects.length == 0) { return seed * HASH_CODE_PRIME; } int hc = seed; for (Object object : objects) { hc = HASH_CODE_PRIME * hc; if (object != null) { if (object instanceof List<?> || object instanceof Queue<?>) { int index = 1; for (Object o : (Collection<?>) object) { hc += computeHashCode(o) * index++; } } else if (object instanceof Collection<?>) { for (Object o : (Collection<?>) object) { hc += computeHashCode(o); } } else { hc += computeHashCode(object); } } } return hc; } /** * Computes a hash code for the supplied object. Checks for arrays of type * byte[] and Object[] and delegates to the {@link Arrays} class. Otherwise * {@link Object#hashCode()} is invoked. * * @param object to calculate hash code for * * @return hash code */ private static int computeHashCode(final Object object) { int hc = 0; if (object instanceof byte[]) { hc += Arrays.hashCode((byte[]) object); } else if (object instanceof Object[]) { hc += Arrays.hashCode((Object[]) object); } else { hc += object.hashCode(); } return hc; } /** * Returns whether the supplied string represents an IP address. Matches both * IPv4 and IPv6 addresses. * * @param s to match * * @return whether the supplied string represents an IP address */ public static boolean isIPAddress(final String s) { return s != null && (IPV4_PATTERN.matcher(s).matches() || IPV6_STD_PATTERN.matcher(s).matches() || IPV6_HEX_COMPRESSED_PATTERN.matcher(s).matches()); } /** * Parses the supplied path and returns an input stream based on the prefix in * the path. If a path is prefixed with the string "classpath:" it is * interpreted as a classpath specification. If a path is prefixed with the * string "file:" it is interpreted as a file path. * * @param path that designates a resource * * @return input stream to read the resource * * @throws IOException if the resource cannot be read * @throws IllegalArgumentException if path is not prefixed with either * 'classpath:' or 'file:' */ public static InputStream getResource(final String path) throws IOException { InputStream is; if (path.startsWith(CLASSPATH_PREFIX)) { is = LdapUtils.class.getResourceAsStream(path.substring(CLASSPATH_PREFIX.length())); } else if (path.startsWith(FILE_PREFIX)) { is = new FileInputStream(new File(path.substring(FILE_PREFIX.length()))); } else { throw new IllegalArgumentException( "path must start with either " + CLASSPATH_PREFIX + " or " + FILE_PREFIX); } return is; } }