"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThrowableProxy.java" between
apache-log4j-2.11.1-src.tar.gz and apache-log4j-2.11.2-src.tar.gz

About: Apache Log4j 2 is a logging library for Java. Source distribution (Java).

ThrowableProxy.java  (apache-log4j-2.11.1-src):ThrowableProxy.java  (apache-log4j-2.11.2-src)
skipping to change at line 20 skipping to change at line 20
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the license for the specific language governing permissions and * See the license for the specific language governing permissions and
* limitations under the license. * limitations under the license.
*/ */
package org.apache.logging.log4j.core.impl; package org.apache.logging.log4j.core.impl;
import java.io.Serializable; import java.io.Serializable;
import java.net.URL;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Stack; import java.util.Stack;
import org.apache.logging.log4j.core.pattern.PlainTextRenderer; import org.apache.logging.log4j.core.pattern.PlainTextRenderer;
import org.apache.logging.log4j.core.pattern.TextRenderer; import org.apache.logging.log4j.core.pattern.TextRenderer;
import org.apache.logging.log4j.core.util.Loader;
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.LoaderUtil;
import org.apache.logging.log4j.util.StackLocatorUtil; import org.apache.logging.log4j.util.StackLocatorUtil;
import org.apache.logging.log4j.util.Strings; import org.apache.logging.log4j.util.Strings;
/** /**
* Wraps a Throwable to add packaging information about each stack trace element . * Wraps a Throwable to add packaging information about each stack trace element .
* *
* <p> * <p>
* A proxy is used to represent a throwable that may not exist in a different cl ass loader or JVM. When an application * A proxy is used to represent a throwable that may not exist in a different cl ass loader or JVM. When an application
* deserializes a ThrowableProxy, the throwable may not be set, but the throwabl e's information is preserved in other * deserializes a ThrowableProxy, the throwable may not be set, but the throwabl e's information is preserved in other
* fields of the proxy like the message and stack trace. * fields of the proxy like the message and stack trace.
skipping to change at line 57 skipping to change at line 51
* *
* <p> * <p>
* TODO: Move this class to org.apache.logging.log4j.core because it is used fro m LogEvent. * TODO: Move this class to org.apache.logging.log4j.core because it is used fro m LogEvent.
* </p> * </p>
* <p> * <p>
* TODO: Deserialize: Try to rebuild Throwable if the target exception is in thi s class loader? * TODO: Deserialize: Try to rebuild Throwable if the target exception is in thi s class loader?
* </p> * </p>
*/ */
public class ThrowableProxy implements Serializable { public class ThrowableProxy implements Serializable {
private static final String TAB = "\t";
private static final String CAUSED_BY_LABEL = "Caused by: ";
private static final String SUPPRESSED_LABEL = "Suppressed: ";
private static final String WRAPPED_BY_LABEL = "Wrapped by: ";
/**
* Cached StackTracePackageElement and ClassLoader.
* <p>
* Consider this class private.
* </p>
*/
static class CacheEntry {
private final ExtendedClassInfo element;
private final ClassLoader loader;
public CacheEntry(final ExtendedClassInfo element, final ClassLoader loa
der) {
this.element = element;
this.loader = loader;
}
}
private static final ThrowableProxy[] EMPTY_THROWABLE_PROXY_ARRAY = new Thro
wableProxy[0];
private static final char EOL = '\n'; private static final char EOL = '\n';
private static final String EOL_STR = String.valueOf(EOL); private static final String EOL_STR = String.valueOf(EOL);
private static final long serialVersionUID = -2752771578252251910L; private static final long serialVersionUID = -2752771578252251910L;
private final ThrowableProxy causeProxy; private final ThrowableProxy causeProxy;
private int commonElementCount; private int commonElementCount;
skipping to change at line 113 skipping to change at line 84
* For JSON and XML IO via Jackson. * For JSON and XML IO via Jackson.
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
private ThrowableProxy() { private ThrowableProxy() {
this.throwable = null; this.throwable = null;
this.name = null; this.name = null;
this.extendedStackTrace = null; this.extendedStackTrace = null;
this.causeProxy = null; this.causeProxy = null;
this.message = null; this.message = null;
this.localizedMessage = null; this.localizedMessage = null;
this.suppressedProxies = EMPTY_THROWABLE_PROXY_ARRAY; this.suppressedProxies = ThrowableProxyHelper.EMPTY_THROWABLE_PROXY_ARRA Y;
} }
/** /**
* Constructs the wrapper for the Throwable that includes packaging data. * Constructs the wrapper for the Throwable that includes packaging data.
* *
* @param throwable The Throwable to wrap, must not be null. * @param throwable The Throwable to wrap, must not be null.
*/ */
public ThrowableProxy(final Throwable throwable) { public ThrowableProxy(final Throwable throwable) {
this(throwable, null); this(throwable, null);
} }
/** /**
* Constructs the wrapper for the Throwable that includes packaging data. * Constructs the wrapper for the Throwable that includes packaging data.
* *
* @param throwable The Throwable to wrap, must not be null. * @param throwable The Throwable to wrap, must not be null.
* @param visited The set of visited suppressed exceptions. * @param visited The set of visited suppressed exceptions.
*/ */
private ThrowableProxy(final Throwable throwable, final Set<Throwable> visit ed) { ThrowableProxy(final Throwable throwable, final Set<Throwable> visited) {
this.throwable = throwable; this.throwable = throwable;
this.name = throwable.getClass().getName(); this.name = throwable.getClass().getName();
this.message = throwable.getMessage(); this.message = throwable.getMessage();
this.localizedMessage = throwable.getLocalizedMessage(); this.localizedMessage = throwable.getLocalizedMessage();
final Map<String, CacheEntry> map = new HashMap<>(); final Map<String, ThrowableProxyHelper.CacheEntry> map = new HashMap<>() ;
final Stack<Class<?>> stack = StackLocatorUtil.getCurrentStackTrace(); final Stack<Class<?>> stack = StackLocatorUtil.getCurrentStackTrace();
this.extendedStackTrace = this.toExtendedStackTrace(stack, map, null, th rowable.getStackTrace()); this.extendedStackTrace = ThrowableProxyHelper.toExtendedStackTrace(this , stack, map, null, throwable.getStackTrace());
final Throwable throwableCause = throwable.getCause(); final Throwable throwableCause = throwable.getCause();
final Set<Throwable> causeVisited = new HashSet<>(1); final Set<Throwable> causeVisited = new HashSet<>(1);
this.causeProxy = throwableCause == null ? null : new ThrowableProxy(thr owable, stack, map, throwableCause, this.causeProxy = throwableCause == null ? null : new ThrowableProxy(thr owable, stack, map, throwableCause,
visited, causeVisited); visited, causeVisited);
this.suppressedProxies = this.toSuppressedProxies(throwable, visited); this.suppressedProxies = ThrowableProxyHelper.toSuppressedProxies(throwa ble, visited);
} }
/** /**
* Constructs the wrapper for a Throwable that is referenced as the cause by another Throwable. * Constructs the wrapper for a Throwable that is referenced as the cause by another Throwable.
* *
* @param parent The Throwable referencing this Throwable. * @param parent The Throwable referencing this Throwable.
* @param stack The Class stack. * @param stack The Class stack.
* @param map The cache containing the packaging data. * @param map The cache containing the packaging data.
* @param cause The Throwable to wrap. * @param cause The Throwable to wrap.
* @param suppressedVisited TODO * @param suppressedVisited TODO
* @param causeVisited TODO * @param causeVisited TODO
*/ */
private ThrowableProxy(final Throwable parent, final Stack<Class<?>> stack, private ThrowableProxy(final Throwable parent, final Stack<Class<?>> stack,
final Map<String, CacheEntry> map, final Map<String, ThrowableProxyHelper.CacheEntry> ma
p,
final Throwable cause, final Set<Throwable> suppresse dVisited, final Throwable cause, final Set<Throwable> suppresse dVisited,
final Set<Throwable> causeVisited) { final Set<Throwable> causeVisited) {
causeVisited.add(cause); causeVisited.add(cause);
this.throwable = cause; this.throwable = cause;
this.name = cause.getClass().getName(); this.name = cause.getClass().getName();
this.message = this.throwable.getMessage(); this.message = this.throwable.getMessage();
this.localizedMessage = this.throwable.getLocalizedMessage(); this.localizedMessage = this.throwable.getLocalizedMessage();
this.extendedStackTrace = this.toExtendedStackTrace(stack, map, parent.g etStackTrace(), cause.getStackTrace()); this.extendedStackTrace = ThrowableProxyHelper.toExtendedStackTrace(this , stack, map, parent.getStackTrace(), cause.getStackTrace());
final Throwable causeCause = cause.getCause(); final Throwable causeCause = cause.getCause();
this.causeProxy = causeCause == null || causeVisited.contains(causeCause ) ? null : new ThrowableProxy(parent, this.causeProxy = causeCause == null || causeVisited.contains(causeCause ) ? null : new ThrowableProxy(parent,
stack, map, causeCause, suppressedVisited, causeVisited); stack, map, causeCause, suppressedVisited, causeVisited);
this.suppressedProxies = this.toSuppressedProxies(cause, suppressedVisit ed); this.suppressedProxies = ThrowableProxyHelper.toSuppressedProxies(cause, suppressedVisited);
} }
@Override @Override
public boolean equals(final Object obj) { public boolean equals(final Object obj) {
if (this == obj) { if (this == obj) {
return true; return true;
} }
if (obj == null) { if (obj == null) {
return false; return false;
} }
skipping to change at line 209 skipping to change at line 181
} }
if (!Arrays.equals(this.extendedStackTrace, other.extendedStackTrace)) { if (!Arrays.equals(this.extendedStackTrace, other.extendedStackTrace)) {
return false; return false;
} }
if (!Arrays.equals(this.suppressedProxies, other.suppressedProxies)) { if (!Arrays.equals(this.suppressedProxies, other.suppressedProxies)) {
return false; return false;
} }
return true; return true;
} }
private void formatCause(final StringBuilder sb, final String prefix, final
ThrowableProxy cause,
final List<String> ignorePackages, final TextRender
er textRenderer, final String suffix, String lineSeparator) {
formatThrowableProxy(sb, prefix, CAUSED_BY_LABEL, cause, ignorePackages,
textRenderer, suffix, lineSeparator);
}
private void formatThrowableProxy(final StringBuilder sb, final String prefi
x, final String causeLabel,
final ThrowableProxy throwableProxy, final
List<String> ignorePackages,
final TextRenderer textRenderer, final Str
ing suffix, String lineSeparator) {
if (throwableProxy == null) {
return;
}
textRenderer.render(prefix, sb, "Prefix");
textRenderer.render(causeLabel, sb, "CauseLabel");
throwableProxy.renderOn(sb, textRenderer);
renderSuffix(suffix, sb, textRenderer);
textRenderer.render(lineSeparator, sb, "Text");
this.formatElements(sb, prefix, throwableProxy.commonElementCount,
throwableProxy.getStackTrace(), throwableProxy.extendedStackTrace, i
gnorePackages, textRenderer, suffix, lineSeparator);
this.formatSuppressed(sb, prefix + TAB, throwableProxy.suppressedProxies
, ignorePackages, textRenderer, suffix, lineSeparator);
this.formatCause(sb, prefix, throwableProxy.causeProxy, ignorePackages,
textRenderer, suffix, lineSeparator);
}
void renderOn(final StringBuilder output, final TextRenderer textRenderer) {
final String msg = this.message;
textRenderer.render(this.name, output, "Name");
if (msg != null) {
textRenderer.render(": ", output, "NameMessageSeparator");
textRenderer.render(msg, output, "Message");
}
}
private void formatSuppressed(final StringBuilder sb, final String prefix, f
inal ThrowableProxy[] suppressedProxies,
final List<String> ignorePackages, final TextR
enderer textRenderer, final String suffix, String lineSeparator) {
if (suppressedProxies == null) {
return;
}
for (final ThrowableProxy suppressedProxy : suppressedProxies) {
formatThrowableProxy(sb, prefix, SUPPRESSED_LABEL, suppressedProxy,
ignorePackages, textRenderer, suffix, lineSeparator);
}
}
private void formatElements(final StringBuilder sb, final String prefix, fin
al int commonCount,
final StackTraceElement[] causedTrace, final Ext
endedStackTraceElement[] extStackTrace,
final List<String> ignorePackages, final TextRen
derer textRenderer, final String suffix, String lineSeparator) {
if (ignorePackages == null || ignorePackages.isEmpty()) {
for (final ExtendedStackTraceElement element : extStackTrace) {
this.formatEntry(element, sb, prefix, textRenderer, suffix, line
Separator);
}
} else {
int count = 0;
for (int i = 0; i < extStackTrace.length; ++i) {
if (!this.ignoreElement(causedTrace[i], ignorePackages)) {
if (count > 0) {
appendSuppressedCount(sb, prefix, count, textRenderer, s
uffix, lineSeparator);
count = 0;
}
this.formatEntry(extStackTrace[i], sb, prefix, textRenderer,
suffix, lineSeparator);
} else {
++count;
}
}
if (count > 0) {
appendSuppressedCount(sb, prefix, count, textRenderer, suffix, l
ineSeparator);
}
}
if (commonCount != 0) {
textRenderer.render(prefix, sb, "Prefix");
textRenderer.render("\t... ", sb, "More");
textRenderer.render(Integer.toString(commonCount), sb, "More");
textRenderer.render(" more", sb, "More");
renderSuffix(suffix, sb, textRenderer);
textRenderer.render(lineSeparator, sb, "Text");
}
}
private void renderSuffix(final String suffix, final StringBuilder sb, final
TextRenderer textRenderer) {
if (!suffix.isEmpty()) {
textRenderer.render(" ", sb, "Suffix");
textRenderer.render(suffix, sb, "Suffix");
}
}
private void appendSuppressedCount(final StringBuilder sb, final String pref
ix, final int count,
final TextRenderer textRenderer, final St
ring suffix, String lineSeparator) {
textRenderer.render(prefix, sb, "Prefix");
if (count == 1) {
textRenderer.render("\t... ", sb, "Suppressed");
} else {
textRenderer.render("\t... suppressed ", sb, "Suppressed");
textRenderer.render(Integer.toString(count), sb, "Suppressed");
textRenderer.render(" lines", sb, "Suppressed");
}
renderSuffix(suffix, sb, textRenderer);
textRenderer.render(lineSeparator, sb, "Text");
}
private void formatEntry(final ExtendedStackTraceElement extStackTraceElemen
t, final StringBuilder sb,
final String prefix, final TextRenderer textRendere
r, final String suffix, String lineSeparator) {
textRenderer.render(prefix, sb, "Prefix");
textRenderer.render("\tat ", sb, "At");
extStackTraceElement.renderOn(sb, textRenderer);
renderSuffix(suffix, sb, textRenderer);
textRenderer.render(lineSeparator, sb, "Text");
}
/** /**
* Formats the specified Throwable. * Formats the specified Throwable.
* @param sb StringBuilder to contain the formatted Throwable. * @param sb StringBuilder to contain the formatted Throwable.
* @param cause The Throwable to format. * @param cause The Throwable to format.
* @param suffix * @param suffix
*/ */
public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause , final String suffix) { public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause , final String suffix) {
this.formatWrapper(sb, cause, null, PlainTextRenderer.getInstance(), suf fix); this.formatWrapper(sb, cause, null, PlainTextRenderer.getInstance(), suf fix);
} }
skipping to change at line 362 skipping to change at line 229
* @param sb StringBuilder to contain the formatted Throwable. * @param sb StringBuilder to contain the formatted Throwable.
* @param cause The Throwable to format. * @param cause The Throwable to format.
* @param ignorePackages The List of packages to be suppressed from the stac k trace. * @param ignorePackages The List of packages to be suppressed from the stac k trace.
* @param textRenderer The text renderer. * @param textRenderer The text renderer.
* @param suffix Append this to the end of each stack frame. * @param suffix Append this to the end of each stack frame.
* @param lineSeparator The end-of-line separator. * @param lineSeparator The end-of-line separator.
*/ */
@SuppressWarnings("ThrowableResultOfMethodCallIgnored") @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause , final List<String> ignorePackages, public void formatWrapper(final StringBuilder sb, final ThrowableProxy cause , final List<String> ignorePackages,
final TextRenderer textRenderer, final String suff ix, final String lineSeparator) { final TextRenderer textRenderer, final String suff ix, final String lineSeparator) {
final Throwable caused = cause.getCauseProxy() != null ? cause.getCauseP ThrowableProxyRenderer.formatWrapper(sb, cause, ignorePackages, textRen
roxy().getThrowable() : null; derer, suffix, lineSeparator);
if (caused != null) {
this.formatWrapper(sb, cause.causeProxy, ignorePackages, textRendere
r, suffix, lineSeparator);
sb.append(WRAPPED_BY_LABEL);
renderSuffix(suffix, sb, textRenderer);
}
cause.renderOn(sb, textRenderer);
renderSuffix(suffix, sb, textRenderer);
textRenderer.render(lineSeparator, sb, "Text");
this.formatElements(sb, Strings.EMPTY, cause.commonElementCount,
cause.getThrowable().getStackTrace(), cause.extendedStackTrace, igno
rePackages, textRenderer, suffix, lineSeparator);
} }
public ThrowableProxy getCauseProxy() { public ThrowableProxy getCauseProxy() {
return this.causeProxy; return this.causeProxy;
} }
/** /**
* Formats the Throwable that is the cause of this Throwable. * Formats the Throwable that is the cause of this Throwable.
* *
* @return The formatted Throwable that caused this Throwable. * @return The formatted Throwable that caused this Throwable.
skipping to change at line 423 skipping to change at line 280
* Formats the Throwable that is the cause of this Throwable. * Formats the Throwable that is the cause of this Throwable.
* *
* @param ignorePackages The List of packages to be suppressed from the stac k trace. * @param ignorePackages The List of packages to be suppressed from the stac k trace.
* @param textRenderer The text renderer. * @param textRenderer The text renderer.
* @param suffix Append this to the end of each stack frame. * @param suffix Append this to the end of each stack frame.
* @param lineSeparator The end-of-line separator. * @param lineSeparator The end-of-line separator.
* @return The formatted Throwable that caused this Throwable. * @return The formatted Throwable that caused this Throwable.
*/ */
public String getCauseStackTraceAsString(final List<String> ignorePackages, final TextRenderer textRenderer, final String suffix, final String lineSeparator ) { public String getCauseStackTraceAsString(final List<String> ignorePackages, final TextRenderer textRenderer, final String suffix, final String lineSeparator ) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
if (this.causeProxy != null) { ThrowableProxyRenderer.formatCauseStackTrace(this, sb, ignorePackages, t
this.formatWrapper(sb, this.causeProxy, ignorePackages, textRenderer extRenderer, suffix, lineSeparator);
, suffix, lineSeparator);
sb.append(WRAPPED_BY_LABEL);
renderSuffix(suffix, sb, textRenderer);
}
this.renderOn(sb, textRenderer);
renderSuffix(suffix, sb, textRenderer);
textRenderer.render(lineSeparator, sb, "Text");
this.formatElements(sb, Strings.EMPTY, 0, this.throwable.getStackTrace()
, this.extendedStackTrace,
ignorePackages, textRenderer, suffix, lineSeparator);
return sb.toString(); return sb.toString();
} }
/** /**
* Returns the number of elements that are being omitted because they are co mmon with the parent Throwable's stack * Returns the number of elements that are being omitted because they are co mmon with the parent Throwable's stack
* trace. * trace.
* *
* @return The number of elements omitted from the stack trace. * @return The number of elements omitted from the stack trace.
*/ */
public int getCommonElementCount() { public int getCommonElementCount() {
return this.commonElementCount; return this.commonElementCount;
} }
/** /**
* Set the value of {@link ThrowableProxy#commonElementCount}.
*
* Method is package-private, to be used internally for initialization.
*
* @param value New value of commonElementCount.
*/
void setCommonElementCount(final int value) {
this.commonElementCount = value;
}
/**
* Gets the stack trace including packaging information. * Gets the stack trace including packaging information.
* *
* @return The stack trace including packaging information. * @return The stack trace including packaging information.
*/ */
public ExtendedStackTraceElement[] getExtendedStackTrace() { public ExtendedStackTraceElement[] getExtendedStackTrace() {
return this.extendedStackTrace; return this.extendedStackTrace;
} }
/** /**
* Formats the stack trace including packaging information. * Formats the stack trace including packaging information.
skipping to change at line 508 skipping to change at line 367
* Formats the stack trace including packaging information. * Formats the stack trace including packaging information.
* *
* @param ignorePackages List of packages to be ignored in the trace. * @param ignorePackages List of packages to be ignored in the trace.
* @param textRenderer The message renderer. * @param textRenderer The message renderer.
* @param suffix Append this to the end of each stack frame. * @param suffix Append this to the end of each stack frame.
* @param lineSeparator The end-of-line separator. * @param lineSeparator The end-of-line separator.
* @return The formatted stack trace including packaging information. * @return The formatted stack trace including packaging information.
*/ */
public String getExtendedStackTraceAsString(final List<String> ignorePackage s, final TextRenderer textRenderer, final String suffix, final String lineSepara tor) { public String getExtendedStackTraceAsString(final List<String> ignorePackage s, final TextRenderer textRenderer, final String suffix, final String lineSepara tor) {
final StringBuilder sb = new StringBuilder(1024); final StringBuilder sb = new StringBuilder(1024);
textRenderer.render(name, sb, "Name"); formatExtendedStackTraceTo(sb, ignorePackages, textRenderer, suffix, lin
textRenderer.render(": ", sb, "NameMessageSeparator"); eSeparator);
textRenderer.render(this.message, sb, "Message");
renderSuffix(suffix, sb, textRenderer);
textRenderer.render(lineSeparator, sb, "Text");
final StackTraceElement[] causedTrace = this.throwable != null ? this.th
rowable.getStackTrace() : null;
this.formatElements(sb, Strings.EMPTY, 0, causedTrace, this.extendedStac
kTrace, ignorePackages, textRenderer, suffix, lineSeparator);
this.formatSuppressed(sb, TAB, this.suppressedProxies, ignorePackages, t
extRenderer, suffix, lineSeparator);
this.formatCause(sb, Strings.EMPTY, this.causeProxy, ignorePackages, tex
tRenderer, suffix, lineSeparator);
return sb.toString(); return sb.toString();
} }
/**
* Formats the stack trace including packaging information.
*
* @param sb Destination.
* @param ignorePackages List of packages to be ignored in the trace.
* @param textRenderer The message renderer.
* @param suffix Append this to the end of each stack frame.
* @param lineSeparator The end-of-line separator.
*/
public void formatExtendedStackTraceTo(final StringBuilder sb, final List<St
ring> ignorePackages, final TextRenderer textRenderer, final String suffix, fina
l String lineSeparator) {
ThrowableProxyRenderer.formatExtendedStackTraceTo(this, sb, ignorePackag
es, textRenderer, suffix, lineSeparator);
}
public String getLocalizedMessage() { public String getLocalizedMessage() {
return this.localizedMessage; return this.localizedMessage;
} }
public String getMessage() { public String getMessage() {
return this.message; return this.message;
} }
/** /**
* Return the FQCN of the Throwable. * Return the FQCN of the Throwable.
skipping to change at line 589 skipping to change at line 453
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + (this.causeProxy == null ? 0 : this.causeProxy .hashCode()); result = prime * result + (this.causeProxy == null ? 0 : this.causeProxy .hashCode());
result = prime * result + this.commonElementCount; result = prime * result + this.commonElementCount;
result = prime * result + (this.extendedStackTrace == null ? 0 : Arrays. hashCode(this.extendedStackTrace)); result = prime * result + (this.extendedStackTrace == null ? 0 : Arrays. hashCode(this.extendedStackTrace));
result = prime * result + (this.suppressedProxies == null ? 0 : Arrays.h ashCode(this.suppressedProxies)); result = prime * result + (this.suppressedProxies == null ? 0 : Arrays.h ashCode(this.suppressedProxies));
result = prime * result + (this.name == null ? 0 : this.name.hashCode()) ; result = prime * result + (this.name == null ? 0 : this.name.hashCode()) ;
return result; return result;
} }
private boolean ignoreElement(final StackTraceElement element, final List<St
ring> ignorePackages) {
if (ignorePackages != null) {
final String className = element.getClassName();
for (final String pkg : ignorePackages) {
if (className.startsWith(pkg)) {
return true;
}
}
}
return false;
}
/**
* Loads classes not located via Reflection.getCallerClass.
*
* @param lastLoader The ClassLoader that loaded the Class that called this
Class.
* @param className The name of the Class.
* @return The Class object for the Class or null if it could not be located
.
*/
private Class<?> loadClass(final ClassLoader lastLoader, final String classN
ame) {
// XXX: this is overly complicated
Class<?> clazz;
if (lastLoader != null) {
try {
clazz = lastLoader.loadClass(className);
if (clazz != null) {
return clazz;
}
} catch (final Throwable ignore) {
// Ignore exception.
}
}
try {
clazz = LoaderUtil.loadClass(className);
} catch (final ClassNotFoundException | NoClassDefFoundError e) {
return loadClass(className);
} catch (final SecurityException e) {
return null;
}
return clazz;
}
private Class<?> loadClass(final String className) {
try {
return Loader.loadClass(className, this.getClass().getClassLoader())
;
} catch (final ClassNotFoundException | NoClassDefFoundError | SecurityE
xception e) {
return null;
}
}
/**
* Construct the CacheEntry from the Class's information.
*
* @param stackTraceElement The stack trace element
* @param callerClass The Class.
* @param exact True if the class was obtained via Reflection.ge
tCallerClass.
* @return The CacheEntry.
*/
private CacheEntry toCacheEntry(final StackTraceElement stackTraceElement, f
inal Class<?> callerClass,
final boolean exact) {
String location = "?";
String version = "?";
ClassLoader lastLoader = null;
if (callerClass != null) {
try {
final CodeSource source = callerClass.getProtectionDomain().getC
odeSource();
if (source != null) {
final URL locationURL = source.getLocation();
if (locationURL != null) {
final String str = locationURL.toString().replace('\\',
'/');
int index = str.lastIndexOf("/");
if (index >= 0 && index == str.length() - 1) {
index = str.lastIndexOf("/", index - 1);
location = str.substring(index + 1);
} else {
location = str.substring(index + 1);
}
}
}
} catch (final Exception ex) {
// Ignore the exception.
}
final Package pkg = callerClass.getPackage();
if (pkg != null) {
final String ver = pkg.getImplementationVersion();
if (ver != null) {
version = ver;
}
}
try {
lastLoader = callerClass.getClassLoader();
} catch (final SecurityException e) {
lastLoader = null;
}
}
return new CacheEntry(new ExtendedClassInfo(exact, location, version), l
astLoader);
}
/**
* Resolve all the stack entries in this stack trace that are not common wit
h the parent.
*
* @param stack The callers Class stack.
* @param map The cache of CacheEntry objects.
* @param rootTrace The first stack trace resolve or null.
* @param stackTrace The stack trace being resolved.
* @return The StackTracePackageElement array.
*/
ExtendedStackTraceElement[] toExtendedStackTrace(final Stack<Class<?>> stack
, final Map<String, CacheEntry> map,
final StackTraceElement[] r
ootTrace,
final StackTraceElement[] s
tackTrace) {
int stackLength;
if (rootTrace != null) {
int rootIndex = rootTrace.length - 1;
int stackIndex = stackTrace.length - 1;
while (rootIndex >= 0 && stackIndex >= 0 && rootTrace[rootIndex].equ
als(stackTrace[stackIndex])) {
--rootIndex;
--stackIndex;
}
this.commonElementCount = stackTrace.length - 1 - stackIndex;
stackLength = stackIndex + 1;
} else {
this.commonElementCount = 0;
stackLength = stackTrace.length;
}
final ExtendedStackTraceElement[] extStackTrace = new ExtendedStackTrace
Element[stackLength];
Class<?> clazz = stack.isEmpty() ? null : stack.peek();
ClassLoader lastLoader = null;
for (int i = stackLength - 1; i >= 0; --i) {
final StackTraceElement stackTraceElement = stackTrace[i];
final String className = stackTraceElement.getClassName();
// The stack returned from getCurrentStack may be missing entries fo
r java.lang.reflect.Method.invoke()
// and its implementation. The Throwable might also contain stack en
tries that are no longer
// present as those methods have returned.
ExtendedClassInfo extClassInfo;
if (clazz != null && className.equals(clazz.getName())) {
final CacheEntry entry = this.toCacheEntry(stackTraceElement, cl
azz, true);
extClassInfo = entry.element;
lastLoader = entry.loader;
stack.pop();
clazz = stack.isEmpty() ? null : stack.peek();
} else {
final CacheEntry cacheEntry = map.get(className);
if (cacheEntry != null) {
final CacheEntry entry = cacheEntry;
extClassInfo = entry.element;
if (entry.loader != null) {
lastLoader = entry.loader;
}
} else {
final CacheEntry entry = this.toCacheEntry(stackTraceElement
,
this.loadClass(lastLoader, className), false);
extClassInfo = entry.element;
map.put(className, entry);
if (entry.loader != null) {
lastLoader = entry.loader;
}
}
}
extStackTrace[i] = new ExtendedStackTraceElement(stackTraceElement,
extClassInfo);
}
return extStackTrace;
}
@Override @Override
public String toString() { public String toString() {
final String msg = this.message; final String msg = this.message;
return msg != null ? this.name + ": " + msg : this.name; return msg != null ? this.name + ": " + msg : this.name;
} }
private ThrowableProxy[] toSuppressedProxies(final Throwable thrown, Set<Thr
owable> suppressedVisited) {
try {
final Throwable[] suppressed = thrown.getSuppressed();
if (suppressed == null) {
return EMPTY_THROWABLE_PROXY_ARRAY;
}
final List<ThrowableProxy> proxies = new ArrayList<>(suppressed.leng
th);
if (suppressedVisited == null) {
suppressedVisited = new HashSet<>(proxies.size());
}
for (int i = 0; i < suppressed.length; i++) {
final Throwable candidate = suppressed[i];
if (!suppressedVisited.contains(candidate)) {
suppressedVisited.add(candidate);
proxies.add(new ThrowableProxy(candidate, suppressedVisited)
);
}
}
return proxies.toArray(new ThrowableProxy[proxies.size()]);
} catch (final Exception e) {
StatusLogger.getLogger().error(e);
}
return null;
}
} }
 End of changes. 19 change blocks. 
420 lines changed or deleted 43 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)