package org.korsakow.ide.util; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class Util { public static interface Predicate<T> { boolean execute(T t); } public static String join(Object[] arr) { return join(arr, ","); } public static String join(Object[] arr, String glue) { StringBuilder builder = new StringBuilder(); for (Object o : arr) { builder.append(o.toString()).append(glue); } if (builder.length() > glue.length()) builder.delete(builder.length() - glue.length(), builder.length()); return builder.toString(); } public static String join(Collection<?> coll) { return join(coll, ","); } public static String join(Collection<?> coll, String glue) { StringBuilder builder = new StringBuilder(); for (Object o : coll) { builder.append(o.toString()).append(glue); } if (builder.length() > 0) builder.delete(builder.length() - glue.length(), builder.length()); return builder.toString(); } public static <O extends Object> O[] array(Class<O> clazz, O ...args) { O[] array = (O[])java.lang.reflect.Array.newInstance(clazz, args.length); System.arraycopy(args, 0, array, 0, args.length); return array; } public static <O extends Object> O[] arrayAdd(O[] src, O ...args) { O[] array = (O[])java.lang.reflect.Array.newInstance(src.getClass().getComponentType(), args.length + src.length); System.arraycopy(src, 0, array, 0, src.length); System.arraycopy(args, 0, array, src.length, args.length); return array; } public static <M> List<M> list(Class<M> clazz, M... args) { return asList(array(clazz, args)); } public static <M> List<M> asList(M[] array) { List<M> list = new ArrayList<M>(); for (M m : array) list.add(m); return list; } public static <T> List<T> filterList(Collection<T> src, Predicate<T> p) { List<T> list = new ArrayList<T>(); for (T t : src) { if (p.execute(t)) list.add(t); } return list; } /** * Converts a collection of weak reference to a collection of "strong" references. * * References that are empty/null are omitted. * * @param <T> * @param weakCollection * @return */ public static <T> Collection<T> extractReferences(Collection<WeakReference<T>> weakCollection) { // we basically wrap the reflection related exceptions in a runtimeexception since we don't // realistically expect them to occur since collections typically have default constructors try { // instantiating and casting like this is possible becaus of type-erasure in generics // otherwise i guess there would have to be some related functionality in the Class api Collection<T> references = weakCollection.getClass().newInstance(); for (WeakReference<T> ref : weakCollection) { T strongRef = ref.get(); if (strongRef != null) references.add(strongRef); } return references; // IllegalArgumentException; let this through since we'd otherwise just wrap it in one } catch (SecurityException e) { throw new IllegalArgumentException(e); } catch (InstantiationException e) { throw new IllegalArgumentException(e); } catch (IllegalAccessException e) { throw new IllegalArgumentException(e); } } /** * Clears the collection of any weak references that are null/empty. * @param collection TODO: this SHOULD be typed Collection<WeakReference<?>> but i was not able to pass in collections such as Set<WeakReference<Object>> for some reason?! */ public static void cleanEmptyReferences(Collection<?> collection) { Collection<WeakReference<?>> toRemove = new ArrayList<WeakReference<?>>(); for (Object obj : collection) { if (obj instanceof WeakReference) // due to either generics sucking or my lame skillz, see doc comment for the parameter { WeakReference<?> ref = (WeakReference<?>)obj; Object t = ref.get(); if (t == null) toRemove.add(ref); } } collection.removeAll(toRemove); } public static String getStackTraceString(Throwable t) { if (t == null) return "null"; StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); t.printStackTrace(pw); String trace = sw.toString(); if (t.getCause() != null) trace += "\nCause:\n" + getStackTraceString(t.getCause()); return trace; } /** * Returns a unique representation of the exception's stack trace. * The intent is to be able to identify exceptions based on where they occurred, while not being limited * by the message or parameters having changed. * * Note that the returned String might be somewhat large since the entire stack is walked and recursed for all causes. * * @param t * @return */ public static String getStackTraceUUID(Throwable t) { StringBuilder sb = new StringBuilder(); StackTraceElement[] trace = t.getStackTrace(); for (StackTraceElement elm : trace) { // filename+line should be unique but sometimes we don't get them at all sb.append(elm.getFileName() + elm.getLineNumber() + elm.getClassName() + elm.getMethodName()); // sb.append("\n"); } if (t.getCause() != null) sb.append(getStackTraceUUID(t.getCause())); return sb.toString(); } public static Throwable getRootCause(Throwable t) { Throwable c = t.getCause(); while (c != null && c.getCause() != null) c = c.getCause(); return c; } }