下面列出了怎么用org.apache.logging.log4j.util.StackLocatorUtil的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext,
final URI configLocation) {
if (currentContext) {
final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
if (ctx != null) {
return ctx;
}
return getDefault();
}
// it's quite possible that the provided ClassLoader may implement BundleReference which gives us a nice shortcut
if (loader instanceof BundleReference) {
return locateContext(((BundleReference) loader).getBundle(), configLocation);
}
final Class<?> callerClass = StackLocatorUtil.getCallerClass(fqcn);
if (callerClass != null) {
return locateContext(FrameworkUtil.getBundle(callerClass), configLocation);
}
final LoggerContext lc = ContextAnchor.THREAD_CONTEXT.get();
return lc == null ? getDefault() : lc;
}
@Override
public void shutdown(final String fqcn, final ClassLoader loader, final boolean currentContext,
final boolean allContexts) {
LoggerContext ctx = null;
if (currentContext) {
ctx = ContextAnchor.THREAD_CONTEXT.get();
} else if (loader != null) {
ctx = findContext(loader);
} else {
final Class<?> clazz = StackLocatorUtil.getCallerClass(fqcn);
if (clazz != null) {
ctx = findContext(clazz.getClassLoader());
}
if (ctx == null) {
ctx = ContextAnchor.THREAD_CONTEXT.get();
}
}
if (ctx != null) {
ctx.stop(DEFAULT_STOP_TIMEOUT, TimeUnit.MILLISECONDS);
}
}
@Override
public boolean hasContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
LoggerContext ctx;
if (currentContext) {
ctx = ContextAnchor.THREAD_CONTEXT.get();
} else if (loader != null) {
ctx = findContext(loader);
} else {
final Class<?> clazz = StackLocatorUtil.getCallerClass(fqcn);
if (clazz != null) {
ctx = findContext(clazz.getClassLoader());
} else {
ctx = ContextAnchor.THREAD_CONTEXT.get();
}
}
return ctx != null && ctx.isStarted();
}
@Override
public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext,
final URI configLocation) {
if (currentContext) {
final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
if (ctx != null) {
return ctx;
}
return getDefault();
} else if (loader != null) {
return locateContext(loader, configLocation);
} else {
final Class<?> clazz = StackLocatorUtil.getCallerClass(fqcn);
if (clazz != null) {
return locateContext(clazz.getClassLoader(), configLocation);
}
final LoggerContext lc = ContextAnchor.THREAD_CONTEXT.get();
if (lc != null) {
return lc;
}
return getDefault();
}
}
private static Class<?> callerClass(final Class<?> clazz) {
if (clazz != null) {
return clazz;
}
final Class<?> candidate = StackLocatorUtil.getCallerClass(3);
if (candidate == null) {
throw new UnsupportedOperationException("No class provided, and an appropriate one cannot be found.");
}
return candidate;
}
public static String[] getCallStack() {
int size = 100;
int adviceStackEntryCount = 2;
String[] callStack = new String[size];
for (int i = 0; i < size; i++) {
Class c = StackLocatorUtil.getCallerClass(i + adviceStackEntryCount);
if (c == null) {
return Arrays.copyOfRange(callStack, 0, i);
}
callStack[i] = c.getName();
}
return callStack;
}
@Benchmark
public Class<?>[] test11_getClassContextViaCallerClass() {
// let's not benchmark LinkedList or anything here
final Class<?>[] classes = new Class<?>[100];
Class<?> clazz;
for (int i = 0; null != (clazz = StackLocatorUtil.getCallerClass(i)); i++) {
classes[i] = clazz;
}
return classes;
}
private static Class<?> callerClass(final Class<?> clazz) {
if (clazz != null) {
return clazz;
}
final Class<?> candidate = StackLocatorUtil.getCallerClass(3);
if (candidate == null) {
throw new UnsupportedOperationException("No class provided, and an appropriate one cannot be found.");
}
return candidate;
}
private boolean isValid() {
if (!inUse) {
LOGGER.warn("Attempt to reuse LogBuilder was ignored. {}",
StackLocatorUtil.getCallerClass(2));
return false ;
}
if (this.threadId != Thread.currentThread().getId()) {
LOGGER.warn("LogBuilder can only be used on the owning thread. {}",
StackLocatorUtil.getCallerClass(2));
return false;
}
return true;
}
@Override
public void shutdown(final String fqcn, final ClassLoader loader, final boolean currentContext,
final boolean allContexts) {
LoggerContext ctx = null;
Bundle bundle = null;
if (currentContext) {
ctx = ContextAnchor.THREAD_CONTEXT.get();
ContextAnchor.THREAD_CONTEXT.remove();
}
if (ctx == null && loader instanceof BundleReference) {
bundle = ((BundleReference) loader).getBundle();
ctx = getLoggerContext(bundle);
removeLoggerContext(ctx);
}
if (ctx == null) {
final Class<?> callerClass = StackLocatorUtil.getCallerClass(fqcn);
if (callerClass != null) {
bundle = FrameworkUtil.getBundle(callerClass);
ctx = getLoggerContext(FrameworkUtil.getBundle(callerClass));
removeLoggerContext(ctx);
}
}
if (ctx == null) {
ctx = ContextAnchor.THREAD_CONTEXT.get();
ContextAnchor.THREAD_CONTEXT.remove();
}
if (ctx != null) {
ctx.stop(DEFAULT_STOP_TIMEOUT, TimeUnit.MILLISECONDS);
}
if (bundle != null && allContexts) {
final Bundle[] bundles = bundle.getBundleContext().getBundles();
for (final Bundle bdl : bundles) {
ctx = getLoggerContext(bdl);
if (ctx != null) {
ctx.stop(DEFAULT_STOP_TIMEOUT, TimeUnit.MILLISECONDS);
}
}
}
}
@Override
public boolean hasContext(final String fqcn, final ClassLoader loader, final boolean currentContext) {
if (currentContext && ContextAnchor.THREAD_CONTEXT.get() != null) {
return ContextAnchor.THREAD_CONTEXT.get().isStarted();
}
if (loader instanceof BundleReference) {
return hasContext(((BundleReference) loader).getBundle());
}
final Class<?> callerClass = StackLocatorUtil.getCallerClass(fqcn);
if (callerClass != null) {
return hasContext(FrameworkUtil.getBundle(callerClass));
}
return ContextAnchor.THREAD_CONTEXT.get() != null && ContextAnchor.THREAD_CONTEXT.get().isStarted();
}
/**
* Logs an event.
*
* @param loggerName The name of the Logger.
* @param fqcn The fully qualified class name of the caller.
* @param marker A Marker or null if none is present.
* @param level The event Level.
* @param data The Message.
* @param t A Throwable or null.
*/
@PerformanceSensitive("allocation")
public void log(final String loggerName, final String fqcn, final Marker marker, final Level level,
final Message data, final Throwable t) {
List<Property> props = null;
if (!propertiesRequireLookup) {
props = properties;
} else {
if (properties != null) {
props = new ArrayList<>(properties.size());
final LogEvent event = Log4jLogEvent.newBuilder()
.setMessage(data)
.setMarker(marker)
.setLevel(level)
.setLoggerName(loggerName)
.setLoggerFqcn(fqcn)
.setThrown(t)
.build();
for (int i = 0; i < properties.size(); i++) {
final Property prop = properties.get(i);
final String value = prop.isValueNeedsLookup() // since LOG4J2-1575
? config.getStrSubstitutor().replace(event, prop.getValue()) //
: prop.getValue();
props.add(Property.createProperty(prop.getName(), value));
}
}
}
StackTraceElement location = requiresLocation() ? StackLocatorUtil.calcLocation(fqcn) : null;
final LogEvent logEvent = logEventFactory.createEvent(loggerName, marker, fqcn, location, level, data, props, t);
try {
log(logEvent, LoggerConfigPredicate.ALL);
} finally {
// LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString())
ReusableLogEventFactory.release(logEvent);
}
}
/**
* Returns the StackTraceElement for the caller. This will be the entry that occurs right
* before the first occurrence of FQCN as a class name.
* @return the StackTraceElement for the caller.
*/
@Override
public StackTraceElement getSource() {
if (source != null) {
return source;
}
if (loggerFqcn == null || !includeLocation) {
return null;
}
source = StackLocatorUtil.calcLocation(loggerFqcn);
return source;
}
/**
* Constructs the wrapper for the Throwable that includes packaging data.
*
* @param throwable The Throwable to wrap, must not be null.
* @param visited The set of visited suppressed exceptions.
*/
ThrowableProxy(final Throwable throwable, final Set<Throwable> visited) {
this.throwable = throwable;
this.name = throwable.getClass().getName();
this.message = throwable.getMessage();
this.localizedMessage = throwable.getLocalizedMessage();
final Map<String, ThrowableProxyHelper.CacheEntry> map = new HashMap<>();
final Stack<Class<?>> stack = StackLocatorUtil.getCurrentStackTrace();
this.extendedStackTrace = ThrowableProxyHelper.toExtendedStackTrace(this, stack, map, null, throwable.getStackTrace());
final Throwable throwableCause = throwable.getCause();
final Set<Throwable> causeVisited = new HashSet<>(1);
this.causeProxy = throwableCause == null ? null : new ThrowableProxy(throwable, stack, map, throwableCause,
visited, causeVisited);
this.suppressedProxies = ThrowableProxyHelper.toSuppressedProxies(throwable, visited);
}
/**
* Returns the StackTraceElement for the caller. This will be the entry that occurs right
* before the first occurrence of FQCN as a class name.
* @return the StackTraceElement for the caller.
*/
@Override
public StackTraceElement getSource() {
if (source != null) {
return source;
}
if (loggerFqcn == null || !includeLocation) {
return null;
}
source = StackLocatorUtil.calcLocation(loggerFqcn);
return source;
}
/**
* Returns the caller location if requested, {@code null} otherwise.
*
* @param fqcn fully qualified caller name.
* @return the caller location if requested, {@code null} otherwise.
*/
private StackTraceElement calcLocationIfRequested(final String fqcn) {
// location: very expensive operation. LOG4J2-153:
// Only include if "includeLocation=true" is specified,
// exclude if not specified or if "false" was specified.
return includeLocation ? StackLocatorUtil.calcLocation(fqcn) : null;
}
@Override
public String getCallerClassName(int callStackDepth) {
return StackLocatorUtil.getCallerClass(callStackDepth).getName();
}
@Benchmark
public String test03_getCallerClassNameReflectively() {
return StackLocatorUtil.getCallerClass(3).getName();
}
@Benchmark
public Class<?> test07_getReflectiveCallerClassUtility() {
return StackLocatorUtil.getCallerClass(3);
}
private Class<?> locateCaller() {
return StackLocatorUtil.getCallerClass(ClassLocator.class.getName());
}
private String locateMethodName() {
return StackLocatorUtil.calcLocation(MethodLocator.class.getName()).getMethodName();
}
@PerformanceSensitive
// NOTE: This is a hot method. Current implementation compiles to 15 bytes of byte code.
// This is within the 35 byte MaxInlineSize threshold. Modify with care!
private StackTraceElement getLocation(String fqcn) {
return requiresLocation() ? StackLocatorUtil.calcLocation(fqcn) : null;
}
public LogBuilder withLocation() {
location = StackLocatorUtil.getStackTraceElement(2);
return this;
}
@Override
protected LoggerContext getContext() {
return getContext(StackLocatorUtil.getCallerClass(LoggerFinder.class));
}
@Override
protected LoggerContext getContext() {
final Class<?> anchor = StackLocatorUtil.getCallerClass(FQCN, PACKAGE);
return anchor == null ? LogManager.getContext() : getContext(StackLocatorUtil.getCallerClass(anchor));
}
@Override
protected LoggerContext getContext() {
return getContext(StackLocatorUtil.getCallerClass(java.util.logging.LogManager.class));
}
@Override
protected LoggerContext getContext() {
final Class<?> anchor = StackLocatorUtil.getCallerClass(FQCN, PACKAGE);
return anchor == null ? LogManager.getContext() : getContext(StackLocatorUtil.getCallerClass(anchor));
}
@Override
protected LoggerContext getContext() {
return getContext(StackLocatorUtil.getCallerClass(LogFactory.class));
}
/**
* Always log an event. This tends to be already guarded by an enabled check, so this method should not check for
* the logger level again
*
* @param fqcn The fully qualified class name of the <b>caller</b>
* @param level The logging level
* @param marker The Marker
* @param message The Message.
* @param t A Throwable or null.
*/
@Override
public void logMessage(final String fqcn, final Level level, final Marker marker, final Message message,
final Throwable t) {
if (requiresLocation()) {
logger.logMessage(level, marker, fqcn, StackLocatorUtil.calcLocation(fqcn), message, t);
}
logger.logMessage(fqcn, level, marker, message, t);
}
/**
* Returns a formatter Logger using the fully qualified name of the calling Class as the Logger name.
* <p>
* This logger lets you use a {@link java.util.Formatter} string in the message to format parameters.
* </p>
*
* @return The Logger for the calling class.
* @throws UnsupportedOperationException if the calling class cannot be determined.
* @since 2.4
*/
public static Logger getFormatterLogger() {
return getFormatterLogger(StackLocatorUtil.getCallerClass(2));
}