[jboss-svn-commits] JBoss Common SVN: r4220 - jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Apr 5 21:23:59 EDT 2010
Author: david.lloyd at jboss.com
Date: 2010-04-05 21:23:59 -0400 (Mon, 05 Apr 2010)
New Revision: 4220
Modified:
jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/FormatStringParser.java
jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/Formatters.java
Log:
JBLOGGING-42: Add "%s" = just the log msg with no exception, "%e" = basic exception stack trace, "%E" = extended exception stack trace
Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/FormatStringParser.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/FormatStringParser.java 2010-04-05 23:42:17 UTC (rev 4219)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/FormatStringParser.java 2010-04-06 01:23:59 UTC (rev 4220)
@@ -95,6 +95,14 @@
stepList.add(Formatters.dateFormatStep(timeZone, argument, leftJustify, minimumWidth, maximumWidth));
break;
}
+ case 'e': {
+ stepList.add(Formatters.exceptionFormatStep(leftJustify, minimumWidth, maximumWidth, false));
+ break;
+ }
+ case 'E': {
+ stepList.add(Formatters.exceptionFormatStep(leftJustify, minimumWidth, maximumWidth, true));
+ break;
+ }
case 'F': {
stepList.add(Formatters.fileNameFormatStep(leftJustify, minimumWidth, maximumWidth));
break;
@@ -131,6 +139,10 @@
stepList.add(Formatters.relativeTimeFormatStep(time, leftJustify, minimumWidth, maximumWidth));
break;
}
+ case 's': {
+ stepList.add(Formatters.simpleMessageFormatStep(leftJustify, minimumWidth, maximumWidth));
+ break;
+ }
case 't': {
stepList.add(Formatters.threadNameFormatStep(leftJustify, minimumWidth, maximumWidth));
break;
Modified: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/Formatters.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/Formatters.java 2010-04-05 23:42:17 UTC (rev 4219)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/formatters/Formatters.java 2010-04-06 01:23:59 UTC (rev 4220)
@@ -22,6 +22,9 @@
package org.jboss.logmanager.formatters;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
import org.jboss.logmanager.ExtLogRecord;
import java.util.logging.Level;
@@ -339,6 +342,262 @@
}
/**
+ * Create a format step which emits the formatted log message text (simple version, no exception traces) with the given justification rules.
+ *
+ * @param leftJustify {@code true} to left justify, {@code false} to right justify
+ * @param minimumWidth the minimum field width, or 0 for none
+ * @param maximumWidth the maximum field width (must be greater than {@code minimumFieldWidth}), or 0 for none
+ * @return the format step
+ */
+ public static FormatStep simpleMessageFormatStep(final boolean leftJustify, final int minimumWidth, final int maximumWidth) {
+ return new JustifyingFormatStep(leftJustify, minimumWidth, maximumWidth) {
+ public void renderRaw(final StringBuilder builder, final ExtLogRecord record) {
+ builder.append(record.getFormattedMessage());
+ }
+ };
+ }
+
+ private static final PrivilegedAction<ClassLoader> GET_TCCL_ACTION = new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ };
+
+ /**
+ * Create a format step which emits the stack trace of an exception with the given justification rules.
+ *
+ * @param leftJustify {@code true} to left justify, {@code false} to right justify
+ * @param minimumWidth the minimum field width, or 0 for none
+ * @param maximumWidth the maximum field width (must be greater than {@code minimumFieldWidth}), or 0 for none
+ * @param extended {@code true} if the stack trace should attempt to include extended JAR version information
+ * @return the format step
+ */
+ public static FormatStep exceptionFormatStep(final boolean leftJustify, final int minimumWidth, final int maximumWidth, final boolean extended) {
+ return new JustifyingFormatStep(leftJustify, minimumWidth, maximumWidth) {
+ public void renderRaw(final StringBuilder builder, final ExtLogRecord record) {
+ final Throwable t = record.getThrown();
+ if (t != null) {
+ builder.append(": ").append(t).append('\n');
+ final StackTraceElement[] stackTrace = t.getStackTrace();
+ final Map<String, String> cache = extended ? new HashMap<String, String>() : null;
+ if (extended) {
+ for (StackTraceElement element : stackTrace) {
+ renderExtended(builder, element, cache);
+ }
+ } else {
+ for (StackTraceElement element : stackTrace) {
+ renderTrivial(builder, element);
+ }
+ }
+ final Throwable cause = t.getCause();
+ if (cause != null) {
+ renderCause(builder, t, cause, cache, extended);
+ }
+ }
+ }
+
+ private void renderTrivial(final StringBuilder builder, final StackTraceElement element) {
+ builder.append("\tat ").append(element).append('\n');
+ }
+
+ private void renderExtended(final StringBuilder builder, final StackTraceElement element, final Map<String, String> cache) {
+ builder.append("\tat ").append(element);
+ final String className = element.getClassName();
+ final String cached;
+ if ((cached = cache.get(className)) != null) {
+ builder.append(cached).append('\n');
+ return;
+ }
+ final int dotIdx = className.lastIndexOf('.');
+ if (dotIdx == -1) {
+ return;
+ }
+ final String packageName = className.substring(0, dotIdx);
+
+ // try to guess the real Class object
+ final Class<?> exceptionClass = guessClass(className);
+
+ // now try to guess the real Package object
+ Package exceptionPackage = null;
+ if (exceptionClass != null) {
+ exceptionPackage = exceptionClass.getPackage();
+ }
+ if (exceptionPackage == null) try {
+ exceptionPackage = Package.getPackage(packageName);
+ } catch (Throwable t) {
+ // ignore
+ }
+
+ // now try to extract the version from the Package
+ String packageVersion = null;
+ if (exceptionPackage != null) try {
+ packageVersion = exceptionPackage.getImplementationVersion();
+ } catch (Throwable t) {
+ // ignore
+ }
+
+ // now try to find the originating resource of the class
+ URL resource = null;
+ final SecurityManager sm = System.getSecurityManager();
+ final String classResourceName = className.replace('.', '/') + ".class";
+ if (exceptionClass != null) {
+ try {
+ resource = sm == null ?
+ exceptionClass.getProtectionDomain().getCodeSource().getLocation() :
+ AccessController.doPrivileged(new PrivilegedAction<URL>() {
+ public URL run() {
+ return exceptionClass.getProtectionDomain().getCodeSource().getLocation();
+ }
+ });
+ } catch (Throwable t) {
+ // ignore
+ }
+ if (resource == null) try {
+ resource = sm == null ?
+ exceptionClass.getClassLoader().getResource(classResourceName) :
+ AccessController.doPrivileged(new PrivilegedAction<URL>() {
+ public URL run() {
+ return exceptionClass.getClassLoader().getResource(classResourceName);
+ }
+ });
+ } catch (Throwable t) {
+ // ignore
+ }
+ }
+
+ // now try to extract the JAR name from the resource URL
+ String jarName = null;
+ if (resource != null) {
+ final String path = resource.getPath();
+ final String protocol = resource.getProtocol();
+ if ("jar".equals(protocol)) {
+ // the last path segment before "!/" should be the JAR name
+ final int sepIdx = path.lastIndexOf("!/");
+ if (sepIdx != -1) {
+ // hit!
+ final String firstPart = path.substring(0, sepIdx);
+ // now find the last file separator before the JAR separator
+ final int lsIdx = Math.max(firstPart.lastIndexOf('/'), firstPart.lastIndexOf('\\'));
+ if (lsIdx != -1) {
+ jarName = firstPart.substring(lsIdx + 1);
+ } else {
+ jarName = firstPart;
+ }
+ }
+ } else if ("module".equals(protocol)) {
+ jarName = resource.getFile();
+ }
+ if (jarName == null) {
+ // OK, that would have been too easy. Next let's just grab the last piece before the class name
+ int endIdx = path.lastIndexOf(classResourceName);
+ if (endIdx != -1) {
+ do {
+ endIdx--;
+ } while (path.charAt(endIdx) == '/' || path.charAt(endIdx) == '\\');
+ final String firstPart = path.substring(0, endIdx);
+ final int lsIdx = Math.max(firstPart.lastIndexOf('/'), firstPart.lastIndexOf('\\'));
+ if (lsIdx != -1) {
+ jarName = firstPart.substring(lsIdx + 1);
+ } else {
+ jarName = firstPart;
+ }
+ }
+ }
+ if (jarName == null) {
+ // OK, just use the last segment
+ final int endIdx = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
+ if (endIdx != -1) {
+ jarName = path.substring(endIdx + 1);
+ } else {
+ jarName = path;
+ }
+ }
+ }
+
+ // finally, render the mess
+ boolean started = false;
+ final StringBuilder tagBuilder = new StringBuilder();
+ if (jarName != null) {
+ started = true;
+ tagBuilder.append(" [").append(jarName).append(':');
+ }
+ if (packageVersion != null) {
+ if (! started) {
+ tagBuilder.append(" [:");
+ started = true;
+ }
+ tagBuilder.append(packageVersion);
+ }
+ if (started) {
+ tagBuilder.append(']');
+ final String tag = tagBuilder.toString();
+ cache.put(className, tag);
+ builder.append(tag);
+ } else {
+ cache.put(className, "");
+ }
+ builder.append('\n');
+ }
+
+ private Class<?> guessClass(final String name) {
+ final SecurityManager sm = System.getSecurityManager();
+ try {
+ try {
+ final ClassLoader tccl = sm != null ? AccessController.doPrivileged(GET_TCCL_ACTION) : GET_TCCL_ACTION.run();
+ if (tccl != null) return Class.forName(name, false, tccl);
+ } catch (ClassNotFoundException e) {
+ // ok, try something else...
+ }
+ try {
+ return Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ // ok, try something else...
+ }
+ return Class.forName(name, false, null);
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+
+ private void renderCause(final StringBuilder builder, final Throwable t, final Throwable cause, final Map<String, String> cache, final boolean extended) {
+
+ final StackTraceElement[] causeStack = cause.getStackTrace();
+ final StackTraceElement[] currentStack = t.getStackTrace();
+
+ int m = causeStack.length - 1;
+ int n = currentStack.length - 1;
+
+ // Walk the stacks backwards from the end, until we find an element that is different
+ while (m >= 0 && n >= 0 && causeStack[m].equals(currentStack[n])) {
+ m--; n--;
+ }
+ int framesInCommon = causeStack.length - 1 - m;
+
+ builder.append("Caused by: ").append(cause).append('\n');
+
+ if (extended) {
+ for (int i=0; i <= m; i++) {
+ renderExtended(builder, causeStack[i], cache);
+ }
+ } else {
+ for (int i=0; i <= m; i++) {
+ renderTrivial(builder, causeStack[i]);
+ }
+ }
+ if (framesInCommon != 0) {
+ builder.append("\t... ").append(framesInCommon).append(" more").append('\n');
+ }
+
+ // Recurse if we have a cause
+ final Throwable ourCause = cause.getCause();
+ if (ourCause != null) {
+ renderCause(builder, cause, ourCause, cache, extended);
+ }
+ }
+ };
+ }
+
+ /**
* Create a format step which emits the log message resource key (if any) with the given justification rules.
*
* @param leftJustify {@code true} to left justify, {@code false} to right justify
More information about the jboss-svn-commits
mailing list