faster checks in the logging. Also better description

This commit is contained in:
Alex Huang 2011-06-21 09:56:01 -07:00
parent 8459ae0beb
commit 9d1523e6d6
1 changed files with 40 additions and 23 deletions

View File

@ -28,7 +28,23 @@ import java.util.Map;
import org.apache.log4j.spi.ThrowableRenderer;
public final class CglibThrowableRenderer implements ThrowableRenderer {
/**
* This renderer removes all the Cglib generated methods from the call
* stack. It is generally not useful and makes the log confusing to look
* at.
*
* Unfortunately, I had to copy out the EnhancedThrowableRenderer from
* the apach libraries because EnhancedThrowableRenderer is a final class.
* I would have much more preferred to extend EnhancedThrowableRenderer and
* simply override doRender. Not sure what the developers are thinking there
* making it final.
*
* In order to use this you must add
* <throwableRenderer class="com.cloud.utils.log.CglibThrowableRenderer"/>
* into log4j.xml.
*
*/
public class CglibThrowableRenderer implements ThrowableRenderer {
/**
* Throwable.getStackTrace() method.
*/
@ -38,7 +54,6 @@ public final class CglibThrowableRenderer implements ThrowableRenderer {
*/
private Method getClassNameMethod;
/**
* Construct new instance.
*/
@ -48,7 +63,7 @@ public final class CglibThrowableRenderer implements ThrowableRenderer {
getStackTraceMethod = Throwable.class.getMethod("getStackTrace", noArgs);
Class ste = Class.forName("java.lang.StackTraceElement");
getClassNameMethod = ste.getMethod("getClassName", noArgs);
} catch(Exception ex) {
} catch (Exception ex) {
}
}
@ -59,23 +74,24 @@ public final class CglibThrowableRenderer implements ThrowableRenderer {
public String[] doRender(final Throwable throwable) {
try {
Object[] noArgs = null;
Object[] elements = (Object[]) getStackTraceMethod.invoke(throwable, noArgs);
Object[] elements = (Object[])getStackTraceMethod.invoke(throwable, noArgs);
ArrayList<String> lines = new ArrayList<String>(elements.length + 1);
lines.add(throwable.toString());
Map classMap = new HashMap();
for(int i = 0; i < elements.length; i++) {
if (!elements[i].toString().endsWith("(<generated>)")) {
for (int i = 0; i < elements.length; i++) {
if (!(elements[i] instanceof StackTraceElement) || !((StackTraceElement)elements[i]).getFileName().equals("<generated>")) {
lines.add(formatElement(elements[i], classMap));
}
}
return lines.toArray(new String[lines.size()]);
} catch(Exception ex) {
} catch (Exception ex) {
return null;
}
}
/**
* Format one element from stack trace.
*
* @param element element, may not be null.
* @param classMap map of class name to location.
* @return string representation of element.
@ -84,7 +100,7 @@ public final class CglibThrowableRenderer implements ThrowableRenderer {
StringBuffer buf = new StringBuffer("\tat ");
buf.append(element);
try {
String className = getClassNameMethod.invoke(element, (Object[]) null).toString();
String className = getClassNameMethod.invoke(element, (Object[])null).toString();
Object classDetails = classMap.get(className);
if (classDetails != null) {
buf.append(classDetails);
@ -98,13 +114,13 @@ public final class CglibThrowableRenderer implements ThrowableRenderer {
URL locationURL = source.getLocation();
if (locationURL != null) {
//
// if a file: URL
// if a file: URL
//
if ("file".equals(locationURL.getProtocol())) {
String path = locationURL.getPath();
if (path != null) {
//
// find the last file separator character
// find the last file separator character
//
int lastSlash = path.lastIndexOf('/');
int lastBack = path.lastIndexOf(File.separatorChar);
@ -112,8 +128,8 @@ public final class CglibThrowableRenderer implements ThrowableRenderer {
lastSlash = lastBack;
}
//
// if no separator or ends with separator (a directory)
// then output the URL, otherwise just the file name.
// if no separator or ends with separator (a directory)
// then output the URL, otherwise just the file name.
//
if (lastSlash <= 0 || lastSlash == path.length() - 1) {
buf.append(locationURL);
@ -126,7 +142,7 @@ public final class CglibThrowableRenderer implements ThrowableRenderer {
}
}
}
} catch(SecurityException ex) {
} catch (SecurityException ex) {
}
buf.append(':');
Package pkg = cls.getPackage();
@ -139,27 +155,28 @@ public final class CglibThrowableRenderer implements ThrowableRenderer {
buf.append(']');
classMap.put(className, buf.substring(detailStart));
}
} catch(Exception ex) {
} catch (Exception ex) {
}
return buf.toString();
}
/**
* Find class given class name.
*
* @param className class name, may not be null.
* @return class, will not be null.
* @throws ClassNotFoundException thrown if class can not be found.
*/
private Class findClass(final String className) throws ClassNotFoundException {
try {
return Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e1) {
return getClass().getClassLoader().loadClass(className);
}
try {
return Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e1) {
return getClass().getClassLoader().loadClass(className);
}
}
}
}
}