package com.ikokoon.toolkit; import java.beans.XMLDecoder; import java.beans.XMLEncoder; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; 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.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import com.ikokoon.serenity.model.Unique; /** * This class contains methods for changing a string to the byte code representation and visa versa. Also some other nifty functions like stripping a * string of white space etc. * * @author Michael Couck * @since 12.07.09 * @version 01.00 */ public class Toolkit { /** The logger. */ private static Logger logger = Logger.getLogger(Toolkit.class); /** * Simple, fast hash function to generate quite unique hashes from strings(i.e. toCharArray()). * * @param string * the string to generate the hash from * @return the integer representation of the hash of the string characters, typically quite unique for strings less than 10 characters */ public static final Long hash(String string) { // Must be prime of course long seed = 131; // 31 131 1313 13131 131313 etc.. long hash = 0; char[] chars = string.toCharArray(); for (int i = 0; i < chars.length; i++) { hash = (hash * seed) + chars[i]; } return Long.valueOf(Math.abs(hash)); } /** * Builds a hash from an array of objects. * * @param objects * the objects to build the hash from * @return the hash of the objects */ public static final Long hash(Object... objects) { StringBuilder builder = new StringBuilder(); for (Object object : objects) { builder.append(object); } Long hash = Toolkit.hash(builder.toString()); return hash; } /** * This method replaces the / in the byte code name with . which is XML friendly. * * @param name * the byte code name of a class * @return the Java name of the class */ public static String slashToDot(String name) { if (name == null) { return name; } name = name.replace('/', '.'); name = name.replace('\\', '.'); return name; } /** * This method replaces the . in the byte code name with / which is what we expect from byte code. * * @param name * the name of the class or package * @return the byte code name of the class or package */ public static String dotToSlash(String name) { if (name == null) { return name; } name = name.replace('.', '/'); return name; } /** * Takes the name of a class and returns the package name for the class. * * @param className * the name of the class fully qualified * @return the package name of the class */ public static String classNameToPackageName(String className) { // Type type = Type.getType(className); className = Toolkit.slashToDot(className); // type.getClassName(); int index = className.lastIndexOf('.'); if (index > -1) { return className.substring(0, index); } // Default and exception package return ""; } /** * Removes any whitespace from the string. * * @param string * the string to remove whitespace from * @return the string without any whitespace that includes carriage returns etc. */ public static String stripWhitespace(String string) { if (string == null) { return string; } StringBuffer buffer = new StringBuffer(); char[] chars = string.toCharArray(); int state = 0; for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (Character.isWhitespace(c)) { if (state == 1) { continue; } state = 1; buffer.append(' '); } else { state = 0; buffer.append(c); } } return buffer.toString(); } /** * Gets a field in the class or in the heirachy of the class. * * @param klass * the original class * @param name * the name of the field * @return the field in the object or super classes of the object */ public static Field getField(Class<?> klass, String name) { if (klass == null || name == null) { return null; } Field field = null; try { field = klass.getDeclaredField(name); } catch (Throwable t) { t.getCause(); } if (field == null) { Class<?> superClass = klass.getSuperclass(); if (superClass != null) { field = getField(superClass, name); } } return field; } /** * Returns the value of the field specified from the object specified. * * @param object * the object to get the field value from * @param name * the name of the field in the object * @return the value of the field if there is such a field or null if there isn't ir if anything goes wrong */ @SuppressWarnings("unchecked") public static <E> E getValue(Class<E> klass, Object object, String name) { if (object == null) { return null; } Field field = getField(object.getClass(), name); if (field != null) { try { field.setAccessible(true); return (E) field.get(object); } catch (Exception e) { logger.error("Exception accessing the field's value", e); } } return null; } @SuppressWarnings("unchecked") public static <E> E executeMethod(Object object, String methodName, Object[] parameters) { Class<?>[] parameterTypes = new Class[parameters.length]; int index = 0; for (Object parameter : parameters) { parameterTypes[index++] = parameter.getClass(); } try { Method method = object.getClass().getDeclaredMethod(methodName, parameterTypes); method.setAccessible(true); return (E) method.invoke(object, parameters); } catch (SecurityException e) { logger.error("Security exception", e); } catch (NoSuchMethodException e) { logger.error("No such method exception", e); } catch (IllegalArgumentException e) { logger.error("Illegal argument exception", e); } catch (IllegalAccessException e) { logger.error("Illegal access exception", e); } catch (InvocationTargetException e) { logger.error("Target invocation exception", e); } return null; } /** * Deletes all the files recursively and then the directories recursively. * * @param file * the directory or file to delete * @param the * number of times to retry to delete the file */ public static void deleteFile(File file, int maxRetryCount) { deleteFile(file, maxRetryCount, 0); } private static void deleteFile(File file, int maxRetryCount, int retryCount) { if (file == null || !file.exists()) { return; } if (file.isDirectory()) { File children[] = file.listFiles(); for (int j = 0; j < children.length; j++) { File child = children[j]; deleteFile(child, maxRetryCount, 0); } } logger.info("File : " + file); if (file.delete()) { logger.info("Deleted file : " + file); } else { if (retryCount >= maxRetryCount) { if (file.exists()) { logger.info("Couldn't delete file : " + file); } } else { logger.info("Retrying count : " + retryCount + ", file : " + file); deleteFile(file, maxRetryCount, ++retryCount); } } } /** * Deletes all the files in a directory with one of the specified extensions. * * @param file * the file to delete or the directory to delete files in * @param extensions * the extensions of files to delete */ public static void deleteFiles(File file, String... extensions) { if (file == null || !file.exists() || !file.canWrite()) { return; } if (file.isDirectory()) { File files[] = file.listFiles(); for (int j = 0; j < files.length; j++) { file = files[j]; deleteFiles(file, extensions); } } if (file.isFile()) { String fileName = file.getName(); for (String extension : extensions) { if (fileName.endsWith(extension)) { if (file.delete()) { logger.debug("Deleted file : " + file); } else { logger.warn("Couldn't delete file : " + file); } } } } } /** * This is the interface to select files with below. * * @author Michael Couck * @since 10.01.10 * @version 01.00 */ public interface IFileFilter { public boolean matches(File file); } /** * Finds files on the file system below the directory specified recursively using the selection criteria supplied in the IFileFilter parameter. * * @param file * the file to start looking from * @param filter * the filter to select files with * @param list * the list of files to add the selected files to */ public static void findFiles(File file, IFileFilter filter, List<File> list) { if (file == null || !file.exists()) { return; } if (filter.matches(file)) { list.add(file); } if (file.isDirectory()) { File files[] = file.listFiles(); for (int j = 0; files != null && j < files.length; j++) { findFiles(files[j], filter, list); } } } /** * Reads the contents of the file and returns the contents in a byte array form. * * @param file * the file to read the contents from * @return the file contents in a byte array output stream * @throws Exception */ public static ByteArrayOutputStream getContents(File file) { InputStream inputStream = null; try { inputStream = new FileInputStream(file); } catch (FileNotFoundException e) { logger.error("No file by that name.", e); } catch (Exception e) { logger.error("General error accessing the file " + file, e); } return getContents(inputStream); } /** * Reads the contents of the file and returns the contents in a byte array form. * * @param inputStream * the file to read the contents from * @return the file contents in a byte array output stream * @throws Exception */ public static ByteArrayOutputStream getContents(InputStream inputStream) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); if (inputStream == null) { return bos; } try { byte[] bytes = new byte[1024]; int read; while ((read = inputStream.read(bytes)) > -1) { bos.write(bytes, 0, read); } logger.debug("Read bytes : " + bos.toString()); } catch (Exception e) { logger.error("Exception accessing the file contents.", e); } finally { try { inputStream.close(); } catch (Exception e) { logger.error("Exception closing input stream " + inputStream, e); } } return bos; } /** * Writes the contents of a byte array to a file. * * @param file * the file to write to * @param bytes * the byte data to write */ public static void setContents(File file, byte[] bytes) { FileOutputStream fileOutputStream = null; try { if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } if (!file.exists()) { file.createNewFile(); } fileOutputStream = new FileOutputStream(file); fileOutputStream.write(bytes, 0, bytes.length); } catch (FileNotFoundException e) { logger.error("File " + file + " not found", e); } catch (IOException e) { logger.error("IO exception writing file contents", e); } catch (Exception e) { logger.error("General exception setting the file contents", e); } finally { if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { logger.error("Exception closing the output stream", e); } } } } /** * Formats a double to the required precision. * * @param d * the double to format * @param precision * the precision for the result * @return the double formatted to the required precision */ public static double format(double d, int precision) { String doubleString = Double.toString(d); doubleString = format(doubleString, precision); try { d = Double.parseDouble(doubleString); } catch (Exception e) { logger.error("Exception formatting : " + d + ", " + precision, e); } return d; } /** * Formats a string to the desired precision. * * @param string * the string to format to a precision * @param precision * the precision of the result * @return the string formatted to the required precision */ public static String format(String string, int precision) { if (string == null) { return string; } char[] chars = string.trim().toCharArray(); StringBuilder builder = new StringBuilder(); int decimal = 1; int state = 0; int decimals = 0; for (char c : chars) { switch (c) { case '.': case ',': state = decimal; builder.append(c); break; default: if (state == decimal) { if (decimals++ >= precision) { break; } } builder.append(c); break; } } return builder.toString(); } /** * Serializes an object to a byte array then to a base 64 string of the byte array. * * @param object * the object to serialise to base 64 * @return the string representation of the object in serialised base 64 */ public static String serializeToBase64(Object object) { String base64 = null; try { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(object); byte[] bytes = byteArrayOutputStream.toByteArray(); base64 = Base64.encode(bytes); base64 = base64.replaceAll("\n", ""); base64 = base64.replaceAll("\r", ""); base64 = base64.replaceAll("\t", ""); } catch (Exception e) { logger.error("Exception serializing the object : " + object, e); } return base64; } /** * De-serializes an object from a base 64 string to an object. * * @param base64 * the base 64 string representation of the object * @return the object de-serialised from the string or null if an exception is thrown */ public static Object deserializeFromBase64(String base64) { byte[] bytes = Base64.decode(base64); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); try { ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream); return objectInputStream.readObject(); } catch (Exception e) { logger.error("Exception deserializing the object from the base 64 string : " + base64, e); } return null; } /** * Returns an array of values that are defined as being a unique combination for the entity by using the Unique annotation for the class. * * @param <T> * the type of object to be inspected for unique fields * @param t * the object t inspect for unique field combinations * @return the array of unique field values for the entity */ @SuppressWarnings("unchecked") public static <T> T[] getUniqueValues(T t) { Unique unique = t.getClass().getAnnotation(Unique.class); if (unique == null) { return (T[]) new Object[] { t }; } String[] fields = unique.fields(); List<T> values = new ArrayList<T>(); for (String field : fields) { Object value = Toolkit.getValue(Object.class, t, field); T[] uniqueValues = (T[]) getUniqueValues(value); for (T uniqueValue : uniqueValues) { values.add(uniqueValue); } } return (T[]) values.toArray(new Object[values.size()]); } public static void copyFile(File in, File out) { if (!out.getParentFile().exists()) { if (!out.getParentFile().mkdirs()) { logger.info("Didn't create parent directories : " + out.getParentFile().getAbsolutePath()); } } if (!out.exists()) { try { out.createNewFile(); } catch (IOException e) { logger.error("Exception creating new file : " + out.getAbsolutePath(), e); } } FileChannel inChannel = null; FileChannel outChannel = null; try { inChannel = new FileInputStream(in).getChannel(); outChannel = new FileOutputStream(out).getChannel(); inChannel.transferTo(0, inChannel.size(), outChannel); } catch (Exception e) { logger.error("Exception copying file : " + in + ", to : " + out, e); } finally { if (inChannel != null) { try { inChannel.close(); } catch (Exception e) { logger.error("", e); } } if (outChannel != null) { try { outChannel.close(); } catch (Exception e) { logger.error("", e); } } } } /** * This function will copy files or directories from one location to another. note that the source and the destination must be mutually exclusive. * This function can not be used to copy a directory to a sub directory of itself. The function will also have problems if the destination files * already exist. * * @param src * A File object that represents the source for the copy * @param dest * A File object that represents the destination for the copy. */ public static void copyFiles(File src, File dest) { // Check to ensure that the source is valid... if (!src.exists()) { logger.warn("Source file/directory does not exist : " + src); return; } else if (!src.canRead()) { // check to ensure we have rights to the source... logger.warn("Source file/directory not readable : " + src); return; } // is this a directory copy? if (src.isDirectory()) { if (!dest.exists()) { // does the destination already exist? // if not we need to make it exist if possible (note this is mkdirs not mkdir) if (!dest.mkdirs()) { logger.warn("Could not create the new destination directory : " + dest); } } // get a listing of files... String children[] = src.list(); // copy all the files in the list. for (int i = 0; i < children.length; i++) { File childSrc = new File(src, children[i]); File childDest = new File(dest, children[i]); copyFiles(childSrc, childDest); } } else { // This was not a directory, so lets just copy the file copyFile(src, dest); } } /** * If Java 1.4 is unavailable, the following technique may be used. * * @param aInput * is the original String which may contain substring aOldPattern * @param aOldPattern * is the non-empty substring which is to be replaced * @param aNewPattern * is the replacement for aOldPattern */ public static String replaceAll(final String aInput, final String aOldPattern, final String aNewPattern) { if (aOldPattern.equals("")) { throw new IllegalArgumentException("Old pattern must have content."); } final StringBuffer result = new StringBuffer(); // startIdx and idxOld delimit various chunks of aInput; these // chunks always end where aOldPattern begins int startIdx = 0; int idxOld = 0; while ((idxOld = aInput.indexOf(aOldPattern, startIdx)) >= 0) { // grab a part of aInput which does not include aOldPattern result.append(aInput.substring(startIdx, idxOld)); // add aNewPattern to take place of aOldPattern result.append(aNewPattern); // reset the startIdx to just after the current match, to see // if there are any further matches startIdx = idxOld + aOldPattern.length(); } // the final chunk will go to the end of aInput result.append(aInput.substring(startIdx)); return result.toString(); } public static boolean createFile(File file) { boolean allCreated = file == null; if (file != null && file.getParentFile() != null && !file.getParentFile().exists()) { if (!file.getParentFile().mkdirs()) { logger.warn("Directory : " + file.getParent() + ", not created."); allCreated = false; } } if (file != null && !file.exists()) { try { if (!file.createNewFile()) { logger.warn("Didn't create file : " + file.getAbsolutePath()); allCreated = false; } } catch (Exception e) { logger.error("Exception creating file : " + file, e); } } if (file.exists()) { allCreated = true; } return allCreated; } public static String serialize(Object object) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); XMLEncoder xmlEncoder = new XMLEncoder(byteArrayOutputStream); xmlEncoder.writeObject(object); xmlEncoder.flush(); xmlEncoder.close(); return byteArrayOutputStream.toString(); } public static Object deserialize(String xml) { InputStream inputStream = new ByteArrayInputStream(xml.getBytes()); XMLDecoder decoder = new XMLDecoder(inputStream); Object object = decoder.readObject(); decoder.close(); return object; } /** * Verifies that all the characters in a string are digits, ie. the string is a number. * * @param string * the string to verify for digit data * @return whether every character in a string is a digit */ public static boolean isDigits(String string) { if (string == null || string.trim().equals("")) { return false; } char[] chars = string.toCharArray(); for (char c : chars) { if (!Character.isDigit(c)) { return false; } } return true; } public static void main(String[] args) { File file = new File("D:/Servers/Tomcat/apache-tomcat-6.0.26/bin/serenity/charts"); Toolkit.deleteFile(file, 3); } }