You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by ca...@apache.org on 2007/02/21 22:38:44 UTC
svn commit: r510242 - in /logging/log4j/trunk:
src/java/org/apache/log4j/spi/ tests/src/java/org/apache/log4j/spi/
Author: carnold
Date: Wed Feb 21 13:38:44 2007
New Revision: 510242
URL: http://svn.apache.org/viewvc?view=rev&rev=510242
Log:
Bug 41219: Stacktraces of exceptions disappear occassionally
Added:
logging/log4j/trunk/src/java/org/apache/log4j/spi/NullWriter.java
logging/log4j/trunk/src/java/org/apache/log4j/spi/VectorWriter.java
Modified:
logging/log4j/trunk/src/java/org/apache/log4j/spi/ThrowableInformation.java
logging/log4j/trunk/tests/src/java/org/apache/log4j/spi/ThrowableInformationTest.java
Added: logging/log4j/trunk/src/java/org/apache/log4j/spi/NullWriter.java
URL: http://svn.apache.org/viewvc/logging/log4j/trunk/src/java/org/apache/log4j/spi/NullWriter.java?view=auto&rev=510242
==============================================================================
--- logging/log4j/trunk/src/java/org/apache/log4j/spi/NullWriter.java (added)
+++ logging/log4j/trunk/src/java/org/apache/log4j/spi/NullWriter.java Wed Feb 21 13:38:44 2007
@@ -0,0 +1,39 @@
+/*
+ * 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.log4j.spi;
+import java.io.Writer;
+
+/**
+ * NullWriter is an obsolete class provided only for
+ * binary compatibility with earlier versions of log4j and should not be used.
+ *
+ * @deprecated
+ */
+class NullWriter extends Writer {
+
+ public void close() {
+ // blank
+ }
+
+ public void flush() {
+ // blank
+ }
+
+ public void write(char[] cbuf, int off, int len) {
+ // blank
+ }
+}
Modified: logging/log4j/trunk/src/java/org/apache/log4j/spi/ThrowableInformation.java
URL: http://svn.apache.org/viewvc/logging/log4j/trunk/src/java/org/apache/log4j/spi/ThrowableInformation.java?view=diff&rev=510242&r1=510241&r2=510242
==============================================================================
--- logging/log4j/trunk/src/java/org/apache/log4j/spi/ThrowableInformation.java (original)
+++ logging/log4j/trunk/src/java/org/apache/log4j/spi/ThrowableInformation.java Wed Feb 21 13:38:44 2007
@@ -16,14 +16,16 @@
package org.apache.log4j.spi;
-import java.io.PrintWriter;
-import java.io.Writer;
+import org.apache.log4j.helpers.PlatformInfo;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
import java.lang.reflect.Method;
-
-import java.util.Vector;
-
-import org.apache.log4j.helpers.PlatformInfo;
+import java.util.ArrayList;
+import java.util.List;
/**
@@ -45,9 +47,10 @@
public ThrowableInformation(final Throwable throwable) {
this.throwable = throwable;
- VectorWriter vw = new VectorWriter();
- extractStringRep(throwable, vw);
- rep = vw.toStringArray();
+ ArrayList lines = new ArrayList();
+ extractStringRep(throwable, lines);
+ rep = new String[lines.size()];
+ lines.toArray(rep);
}
public ThrowableInformation(String[] rep) {
@@ -63,8 +66,27 @@
return throwable;
}
- public void extractStringRep(Throwable t, VectorWriter vw) {
- t.printStackTrace(vw);
+ /**
+ * Extract string representation of throwable.
+ * @param t throwable, may not be null.
+ * @param lines list to receive stack trace, may not be null.
+ */
+ private static void extractStringRep(final Throwable t, final List lines) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ t.printStackTrace(pw);
+ pw.flush();
+ LineNumberReader reader = new LineNumberReader(
+ new StringReader(sw.toString()));
+ try {
+ String line = reader.readLine();
+ while(line != null) {
+ lines.add(line);
+ line = reader.readLine();
+ }
+ } catch(IOException ex) {
+ lines.add(ex.toString());
+ }
// Check if the Throwable t has a nested Throwable. If so, invoke
// extractStringRep recursively.
@@ -95,8 +117,8 @@
Throwable nextT =
(Throwable) nextThrowableMethod.invoke(t, new Object[0]);
if (nextT != null) {
- vw.print("Root cause follows.");
- extractStringRep(nextT, vw);
+ lines.add("Root cause follows.");
+ extractStringRep(nextT, lines);
}
}
} catch (Exception e) {
@@ -124,11 +146,7 @@
ThrowableInformation r = (ThrowableInformation) o;
if (rep == null) {
- if (r.rep != null) {
- return false;
- } else {
- return true;
- }
+ return (r.rep == null);
}
// at this point we know that both rep and r.rep are non-null.
@@ -144,92 +162,5 @@
}
return true;
- }
-}
-
-
-/**
- * VectorWriter is a seemingly trivial implemtantion of PrintWriter. The
- * throwable instance that we are trying to represnt is asked to print itself to
- * a VectorWriter.
- *
- * By our design choice, r string representation of the throwable does not
- * contain any line separators. It follows that println() methods of
- * VectorWriter ignore the 'ln' part.
- */
-class VectorWriter extends PrintWriter {
- private Vector v;
-
- VectorWriter() {
- super(new NullWriter());
- v = new Vector();
- }
-
- public void print(Object o) {
- v.addElement(o.toString());
- }
-
- public void print(char[] chars) {
- v.addElement(new String(chars));
- }
-
- public void print(String s) {
- v.addElement(s);
- }
-
- public void println(Object o) {
- v.addElement(String.valueOf(o));
- }
-
- // JDK 1.1.x apprenly uses this form of println while in
- // printStackTrace()
- public void println(char[] chars) {
- v.addElement(new String(chars));
- }
-
- public void println(String s) {
- v.addElement(s);
- }
-
- public void write(char[] chars) {
- v.addElement(new String(chars));
- }
-
- public void write(char[] chars, int off, int len) {
- v.addElement(new String(chars, off, len));
- }
-
- public void write(String s, int off, int len) {
- v.addElement(s.substring(off, off + len));
- }
-
- public void write(String s) {
- v.addElement(s);
- }
-
- public String[] toStringArray() {
- int len = v.size();
- String[] sa = new String[len];
-
- for (int i = 0; i < len; i++) {
- sa[i] = (String) v.elementAt(i);
- }
-
- return sa;
- }
-}
-
-
-class NullWriter extends Writer {
- public void close() {
- // blank
- }
-
- public void flush() {
- // blank
- }
-
- public void write(char[] cbuf, int off, int len) {
- // blank
}
}
Added: logging/log4j/trunk/src/java/org/apache/log4j/spi/VectorWriter.java
URL: http://svn.apache.org/viewvc/logging/log4j/trunk/src/java/org/apache/log4j/spi/VectorWriter.java?view=auto&rev=510242
==============================================================================
--- logging/log4j/trunk/src/java/org/apache/log4j/spi/VectorWriter.java (added)
+++ logging/log4j/trunk/src/java/org/apache/log4j/spi/VectorWriter.java Wed Feb 21 13:38:44 2007
@@ -0,0 +1,94 @@
+/*
+ * 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.log4j.spi;
+
+import java.io.PrintWriter;
+import java.util.Vector;
+
+/**
+ * VectorWriter is an obsolete class provided only for
+ * binary compatibility with earlier versions of log4j and should not be used.
+ *
+ * @deprecated
+ */
+class VectorWriter extends PrintWriter {
+
+ private Vector v;
+
+ /**
+ * @deprecated
+ */
+ VectorWriter() {
+ super(new NullWriter());
+ v = new Vector();
+ }
+
+ public void print(Object o) {
+ v.addElement(String.valueOf(o));
+ }
+
+ public void print(char[] chars) {
+ v.addElement(new String(chars));
+ }
+
+ public void print(String s) {
+ v.addElement(s);
+ }
+
+ public void println(Object o) {
+ v.addElement(String.valueOf(o));
+ }
+
+ // JDK 1.1.x apprenly uses this form of println while in
+ // printStackTrace()
+ public
+ void println(char[] chars) {
+ v.addElement(new String(chars));
+ }
+
+ public
+ void println(String s) {
+ v.addElement(s);
+ }
+
+ public void write(char[] chars) {
+ v.addElement(new String(chars));
+ }
+
+ public void write(char[] chars, int off, int len) {
+ v.addElement(new String(chars, off, len));
+ }
+
+ public void write(String s, int off, int len) {
+ v.addElement(s.substring(off, off+len));
+ }
+
+ public void write(String s) {
+ v.addElement(s);
+ }
+
+ public String[] toStringArray() {
+ int len = v.size();
+ String[] sa = new String[len];
+ for(int i = 0; i < len; i++) {
+ sa[i] = (String) v.elementAt(i);
+ }
+ return sa;
+ }
+
+}
+
Modified: logging/log4j/trunk/tests/src/java/org/apache/log4j/spi/ThrowableInformationTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/trunk/tests/src/java/org/apache/log4j/spi/ThrowableInformationTest.java?view=diff&rev=510242&r1=510241&r2=510242
==============================================================================
--- logging/log4j/trunk/tests/src/java/org/apache/log4j/spi/ThrowableInformationTest.java (original)
+++ logging/log4j/trunk/tests/src/java/org/apache/log4j/spi/ThrowableInformationTest.java Wed Feb 21 13:38:44 2007
@@ -18,6 +18,8 @@
import junit.framework.TestCase;
+import java.io.PrintWriter;
+
/**
*
* @author Ceki Gülcü
@@ -44,19 +46,19 @@
public void testEqualsObject() {
Throwable e1 = new Exception("exeption 1");
Throwable e2 = new Exception("exeption 2");
-
+
ThrowableInformation te1 = new ThrowableInformation(e1);
ThrowableInformation te2 = new ThrowableInformation(e2);
-
+
assertEquals(te1, te1);
assertEquals(te2, te2);
-
+
boolean eq1 = te1.equals(te2);
assertEquals(false, eq1);
boolean eq2 = te1.equals(null);
assertEquals(false, eq2);
-
+
assertEquals(te1.hashCode(), te1.hashCode());
assertEquals(te2.hashCode(), te2.hashCode());
}
@@ -67,5 +69,257 @@
{
super(arg0);
}
-
+
+ /**
+ * Custom throwable that only calls methods
+ * overridden by VectorWriter in log4j 1.2.14 and earlier.
+ */
+ private static final class OverriddenThrowable extends Throwable {
+ /**
+ * Create new instance.
+ */
+ public OverriddenThrowable() {
+ }
+
+ /**
+ * Print stack trace.
+ *
+ * @param s print writer.
+ */
+ public void printStackTrace(final PrintWriter s) {
+ s.print((Object) "print(Object)");
+ s.print("print(char[])".toCharArray());
+ s.print("print(String)");
+ s.println((Object) "println(Object)");
+ s.println("println(char[])".toCharArray());
+ s.println("println(String)");
+ s.write("write(char[])".toCharArray());
+ s.write("write(char[], int, int)".toCharArray(), 2, 8);
+ s.write("write(String, int, int)", 2, 8);
+ }
+ }
+
+ /**
+ * Test capturing stack trace from a throwable that only uses the
+ * PrintWriter methods overridden in log4j 1.2.14 and earlier.
+ */
+ public void testOverriddenBehavior() {
+ ThrowableInformation ti = new ThrowableInformation(new OverriddenThrowable());
+ String[] rep = ti.getThrowableStrRep();
+ assertEquals(4, rep.length);
+ assertEquals("print(Object)print(char[])print(String)println(Object)", rep[0]);
+ assertEquals("println(char[])", rep[1]);
+ assertEquals("println(String)", rep[2]);
+ assertEquals("write(char[])ite(charite(Stri", rep[3]);
+ }
+
+ /**
+ * Custom throwable that calls methods
+ * not overridden by VectorWriter in log4j 1.2.14 and earlier.
+ */
+ private static final class NotOverriddenThrowable extends Throwable {
+ /**
+ * Create new instance.
+ */
+ public NotOverriddenThrowable() {
+ }
+
+ /**
+ * Print stack trace.
+ *
+ * @param s print writer.
+ */
+ public void printStackTrace(final PrintWriter s) {
+ s.print(true);
+ s.print('a');
+ s.print(1);
+ s.print(2L);
+ s.print(Float.MAX_VALUE);
+ s.print(Double.MIN_VALUE);
+ s.println(true);
+ s.println('a');
+ s.println(1);
+ s.println(2L);
+ s.println(Float.MAX_VALUE);
+ s.println(Double.MIN_VALUE);
+ s.write('C');
+ }
+ }
+
+ /**
+ * Test capturing stack trace from a throwable that uses the
+ * PrintWriter methods not overridden in log4j 1.2.14 and earlier.
+ */
+ public void testNotOverriddenBehavior() {
+ ThrowableInformation ti = new ThrowableInformation(new NotOverriddenThrowable());
+ String[] rep = ti.getThrowableStrRep();
+ assertEquals(7, rep.length);
+ StringBuffer buf = new StringBuffer(String.valueOf(true));
+ buf.append('a');
+ buf.append(String.valueOf(1));
+ buf.append(String.valueOf(2L));
+ buf.append(String.valueOf(Float.MAX_VALUE));
+ buf.append(String.valueOf(Double.MIN_VALUE));
+ buf.append(String.valueOf(true));
+ assertEquals(buf.toString(), rep[0]);
+ assertEquals("a", rep[1]);
+ assertEquals(String.valueOf(1), rep[2]);
+ assertEquals(String.valueOf(2L), rep[3]);
+ assertEquals(String.valueOf(Float.MAX_VALUE), rep[4]);
+ assertEquals(String.valueOf(Double.MIN_VALUE), rep[5]);
+ assertEquals("C", rep[6]);
+ }
+
+ /**
+ * Custom throwable that calls methods of VectorWriter
+ * with null.
+ */
+ private static final class NullThrowable extends Throwable {
+ /**
+ * Create new instance.
+ */
+ public NullThrowable() {
+ }
+
+ /**
+ * Print stack trace.
+ *
+ * @param s print writer.
+ */
+ public void printStackTrace(final PrintWriter s) {
+ s.print((Object) null);
+ s.print((String) null);
+ s.println((Object) null);
+ s.println((String) null);
+ }
+ }
+
+ /**
+ * Test capturing stack trace from a throwable that passes
+ * null to PrintWriter methods.
+ */
+
+ public void testNull() {
+ ThrowableInformation ti = new ThrowableInformation(new NullThrowable());
+ String[] rep = ti.getThrowableStrRep();
+ assertEquals(2, rep.length);
+ String nullStr = String.valueOf((Object) null);
+ assertEquals(nullStr + nullStr + nullStr, rep[0]);
+ assertEquals(nullStr, rep[1]);
+ }
+
+ /**
+ * Custom throwable that does nothing in printStackTrace.
+ */
+ private static final class EmptyThrowable extends Throwable {
+ /**
+ * Create new instance.
+ */
+ public EmptyThrowable() {
+ }
+
+ /**
+ * Print stack trace.
+ *
+ * @param s print writer.
+ */
+ public void printStackTrace(final PrintWriter s) {
+ }
+ }
+
+ /**
+ * Test capturing stack trace from a throwable that
+ * does nothing on a call to printStackTrace.
+ */
+
+ public void testEmpty() {
+ ThrowableInformation ti = new ThrowableInformation(new EmptyThrowable());
+ String[] rep = ti.getThrowableStrRep();
+ assertEquals(0, rep.length);
+ }
+
+ /**
+ * Custom throwable that emits a specified string in printStackTrace.
+ */
+ private static final class StringThrowable extends Throwable {
+ /**
+ * Stack trace.
+ */
+ private final String stackTrace;
+ /**
+ * Create new instance.
+ * @param trace stack trace.
+ */
+ public StringThrowable(final String trace) {
+ stackTrace = trace;
+ }
+
+ /**
+ * Print stack trace.
+ *
+ * @param s print writer.
+ */
+ public void printStackTrace(final PrintWriter s) {
+ s.print(stackTrace);
+ }
+ }
+
+ /**
+ * Test capturing stack trace from throwable that just has a line feed.
+ */
+ public void testLineFeed() {
+ ThrowableInformation ti = new ThrowableInformation(new StringThrowable("\n"));
+ String[] rep = ti.getThrowableStrRep();
+ assertEquals(1, rep.length);
+ assertEquals("", rep[0]);
+ }
+
+ /**
+ * Test capturing stack trace from throwable that just has a carriage return.
+ */
+ public void testCarriageReturn() {
+ ThrowableInformation ti = new ThrowableInformation(new StringThrowable("\r"));
+ String[] rep = ti.getThrowableStrRep();
+ assertEquals(1, rep.length);
+ assertEquals("", rep[0]);
+ }
+
+ /**
+ * Test parsing of line breaks.
+ */
+ public void testParsing() {
+ ThrowableInformation ti = new ThrowableInformation(
+ new StringThrowable("Line1\rLine2\nLine3\r\nLine4\n\rLine6"));
+ String[] rep = ti.getThrowableStrRep();
+ assertEquals(6, rep.length);
+ assertEquals("Line1", rep[0]);
+ assertEquals("Line2", rep[1]);
+ assertEquals("Line3", rep[2]);
+ assertEquals("Line4", rep[3]);
+ assertEquals("", rep[4]);
+ assertEquals("Line6", rep[5]);
+ }
+
+ /**
+ * Test capturing stack trace from throwable that a line feed followed by blank.
+ */
+ public void testLineFeedBlank() {
+ ThrowableInformation ti = new ThrowableInformation(new StringThrowable("\n "));
+ String[] rep = ti.getThrowableStrRep();
+ assertEquals(2, rep.length);
+ assertEquals("", rep[0]);
+ assertEquals(" ", rep[1]);
+ }
+
+ /**
+ * Test that getThrowable returns the throwable provided to the constructor.
+ * @deprecated
+ */
+ public void testGetThrowable() {
+ Throwable t = new StringThrowable("Hello, World");
+ ThrowableInformation ti = new ThrowableInformation(t);
+ assertSame(t, ti.getThrowable());
+ }
+
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org