/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.openejb.util; import org.apache.openejb.loader.IO; import javax.naming.Binding; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.OutputStream; import java.io.PrintStream; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; /** * @version $Rev$ $Date$ */ public class Debug { public static String printStackTrace(final Throwable t) { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); t.printStackTrace(new PrintStream(baos)); return new String(baos.toByteArray()); } public static Map<String, Object> contextToMap(final Context context) throws NamingException { final Map<String, Object> map = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER); contextToMap(context, "", map); return map; } public static void contextToMap(final Context context, final String baseName, final Map<String, Object> results) throws NamingException { final NamingEnumeration<Binding> namingEnumeration = context.listBindings(""); while (namingEnumeration.hasMoreElements()) { final Binding binding = namingEnumeration.nextElement(); final String name = binding.getName(); final String fullName = baseName + name; final Object object = binding.getObject(); results.put(fullName, object); if (object instanceof Context) { contextToMap((Context) object, fullName + "/", results); } } } public static Map<String, Object> printContext(final Context context) throws NamingException { return printContext(context, System.out); } public static Map<String, Object> printContext(final Context context, final PrintStream out) throws NamingException { final Map<String, Object> map = contextToMap(context); for (final Entry<String, Object> entry : map.entrySet()) { out.println(entry.getKey() + "=" + entry.getValue().getClass().getName()); } return map; } public static Map<String, Object> printContextValues(final Context context) throws NamingException { return printContextValues(context, System.out); } public static Map<String, Object> printContextValues(final Context context, final PrintStream out) throws NamingException { final Map<String, Object> map = contextToMap(context); for (final Entry<String, Object> entry : map.entrySet()) { out.println(entry.getKey() + "=" + entry.getValue()); } return map; } public static List<Field> getFields(final Class clazz) { if (clazz == null) { return Collections.EMPTY_LIST; } final List<Field> fields = new ArrayList<Field>(); fields.addAll(Arrays.asList(clazz.getDeclaredFields())); fields.addAll(getFields(clazz.getSuperclass())); return fields; } public static class Trace { private static final Trace trace = new Trace(); private final Map<String, Node> elements = new LinkedHashMap<String, Node>(); private final List<Event> events = new ArrayList<Event>(); private static final class Event { private final long time = System.currentTimeMillis(); private final List<StackTraceElement> elements; private Event(final List<StackTraceElement> elements) { this.elements = Collections.unmodifiableList(elements); } @Override public String toString() { return "<li>" + "time=" + time + ", elements=" + elements + "</li>"; } } public static void record() { try { final File file = new File("/tmp/trace.html"); final OutputStream write = IO.write(file); report(write); } catch (final FileNotFoundException e) { e.printStackTrace(); } } public static void report(final OutputStream write) { final PrintStream stream = new PrintStream(write); report(stream); stream.close(); } public static void report(final PrintStream stream) { trace.print(stream); stream.print("<br/><ul>"); for (final Trace.Event event : trace.events) { stream.println(event); } stream.print("</ul>"); } public static void mark() { final Throwable throwable = new Exception().fillInStackTrace(); final List<StackTraceElement> stackTraceElements = new ArrayList<StackTraceElement>(Arrays.asList(throwable.getStackTrace())); Collections.reverse(stackTraceElements); final Iterator<StackTraceElement> iterator = stackTraceElements.iterator(); while (iterator.hasNext()) { final StackTraceElement element = iterator.next(); if (!element.getClassName().startsWith("org.apache")) { iterator.remove(); } if (element.getClassName().endsWith("Debug") && element.getMethodName().equals("mark")) { iterator.remove(); } } trace.link(stackTraceElements); } public void print(final PrintStream out) { final Set<Node> seen = new HashSet<Node>(); for (final Node node : elements.values()) { if (node.parent == null) { out.println("<ul>"); print(seen, out, node, "- "); out.println("</ul>"); } } } private void print(final Set<Node> seen, final PrintStream out, final Node node, final String s) { if (!seen.add(node)) { return; } out.print("<li>\n"); final StackTraceElement e = node.getElement(); out.printf("<b>%s</b> <i>%s <font color='gray'>(%s)</font></i>\n", escape(e.getMethodName()), reverse(e.getClassName()), e.getLineNumber()); if (node.children.size() > 0) { out.println("<ul>"); for (final Node child : node.children) { print(seen, out, child, s); } out.println("</ul>"); } out.print("</li>\n"); } private String escape(final String methodName) { return methodName.replace("<", "<").replace(">", ">"); } private void printTxt(final Set<Node> seen, final PrintStream out, final Node node, String s) { if (!seen.add(node)) { return; } out.print(s); final StackTraceElement e = node.getElement(); out.printf("**%s** *%s* (%s)\n", e.getMethodName(), reverse(e.getClassName()), e.getLineNumber()); s = " " + s; for (final Node child : node.children) { print(seen, out, child, s); } } private String reverse2(final String className) { final List<String> list = Arrays.asList(className.split("\\.")); Collections.reverse(list); String string = Join.join(".", list); string = string.replaceAll("(.*?)(\\..*)", "$1<font color=\"gray\">$2</font>"); return string; } private String reverse(String string) { string = string.replaceAll("(.*)\\.([^.]+)", "$2 <font color=\"gray\">$1</font>"); return string; } public static class Node { private Node parent; private final String trace; private final StackTraceElement element; private final List<Node> children = new ArrayList<Node>(); public Node(final StackTraceElement element) { this.element = element; this.trace = element.toString(); } public String getTrace() { return trace; } public StackTraceElement getElement() { return element; } public Node addChild(final Node node) { node.parent = this; children.add(node); return node; } } public static void reset() { trace.events.clear(); trace.elements.clear(); } public void link(final List<StackTraceElement> elements) { events.add(new Event(elements)); final Iterator<StackTraceElement> iterator = elements.iterator(); if (!iterator.hasNext()) { return; } Node parent = get(iterator.next()); while (iterator.hasNext()) { parent = parent.addChild(get(iterator.next())); } } private Node get(final StackTraceElement element) { final String key = element.toString(); Node node = elements.get(key); if (node == null) { node = new Node(element); elements.put(key, node); } return node; } } }