in src/main/java/org/apache/log4j/spi/LocationInfo.java [133:246]
public LocationInfo(Throwable t, String fqnOfCallingClass) {
if(t == null || fqnOfCallingClass == null)
return;
if (getLineNumberMethod != null) {
try {
Object[] noArgs = null;
Object[] elements = (Object[]) getStackTraceMethod.invoke(t, noArgs);
String prevClass = NA;
for(int i = elements.length - 1; i >= 0; i--) {
String thisClass = (String) getClassNameMethod.invoke(elements[i], noArgs);
if(fqnOfCallingClass.equals(thisClass)) {
int caller = i + 1;
if (caller < elements.length) {
className = prevClass;
methodName = (String) getMethodNameMethod.invoke(elements[caller], noArgs);
fileName = (String) getFileNameMethod.invoke(elements[caller], noArgs);
if (fileName == null) {
fileName = NA;
}
int line = ((Integer) getLineNumberMethod.invoke(elements[caller], noArgs)).intValue();
if (line < 0) {
lineNumber = NA;
} else {
lineNumber = String.valueOf(line);
}
StringBuffer buf = new StringBuffer();
buf.append(className);
buf.append(".");
buf.append(methodName);
buf.append("(");
buf.append(fileName);
buf.append(":");
buf.append(lineNumber);
buf.append(")");
this.fullInfo = buf.toString();
}
return;
}
prevClass = thisClass;
}
return;
} catch(IllegalAccessException ex) {
LogLog.debug("LocationInfo failed using JDK 1.4 methods", ex);
} catch(InvocationTargetException ex) {
if (ex.getTargetException() instanceof InterruptedException
|| ex.getTargetException() instanceof InterruptedIOException) {
Thread.currentThread().interrupt();
}
LogLog.debug("LocationInfo failed using JDK 1.4 methods", ex);
} catch(RuntimeException ex) {
LogLog.debug("LocationInfo failed using JDK 1.4 methods", ex);
}
}
String s;
// Protect against multiple access to sw.
synchronized(sw) {
t.printStackTrace(pw);
s = sw.toString();
sw.getBuffer().setLength(0);
}
//System.out.println("s is ["+s+"].");
int ibegin, iend;
// Given the current structure of the package, the line
// containing "org.apache.log4j.Category." should be printed just
// before the caller.
// This method of searching may not be fastest but it's safer
// than counting the stack depth which is not guaranteed to be
// constant across JVM implementations.
ibegin = s.lastIndexOf(fqnOfCallingClass);
if(ibegin == -1)
return;
//
// if the next character after the class name exists
// but is not a period, see if the classname is
// followed by a period earlier in the trace.
// Minimizes mistakeningly matching on a class whose
// name is a substring of the desired class.
// See bug 44888.
if (ibegin + fqnOfCallingClass.length() < s.length() &&
s.charAt(ibegin + fqnOfCallingClass.length()) != '.') {
int i = s.lastIndexOf(fqnOfCallingClass + ".");
if (i != -1) {
ibegin = i;
}
}
ibegin = s.indexOf(Layout.LINE_SEP, ibegin);
if(ibegin == -1)
return;
ibegin+= Layout.LINE_SEP_LEN;
// determine end of line
iend = s.indexOf(Layout.LINE_SEP, ibegin);
if(iend == -1)
return;
// VA has a different stack trace format which doesn't
// need to skip the inital 'at'
if(!inVisualAge) {
// back up to first blank character
ibegin = s.lastIndexOf("at ", iend);
if(ibegin == -1)
return;
// Add 3 to skip "at ";
ibegin += 3;
}
// everything between is the requested stack item
this.fullInfo = s.substring(ibegin, iend);
}