This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

View File

@@ -0,0 +1,185 @@
/*
* 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.juli.logging;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Hard-coded java.util.logging commons-logging implementation.
*/
class DirectJDKLog implements Log {
// no reason to hide this - but good reasons to not hide
public final Logger logger;
// Alternate config reader and console format
private static final String SIMPLE_FMT="java.util.logging.SimpleFormatter";
private static final String FORMATTER="org.apache.juli.formatter";
static {
if (System.getProperty("java.util.logging.config.class") == null &&
System.getProperty("java.util.logging.config.file") == null) {
// default configuration - it sucks. Let's override at least the
// formatter for the console
try {
Formatter fmt= (Formatter) Class.forName(System.getProperty(
FORMATTER, SIMPLE_FMT)).getConstructor().newInstance();
// it is also possible that the user modified jre/lib/logging.properties -
// but that's really stupid in most cases
Logger root=Logger.getLogger("");
for (Handler handler : root.getHandlers()) {
// I only care about console - that's what's used in default config anyway
if (handler instanceof ConsoleHandler) {
handler.setFormatter(fmt);
}
}
} catch (Throwable t) {
// maybe it wasn't included - the ugly default will be used.
}
}
}
public DirectJDKLog(String name ) {
logger=Logger.getLogger(name);
}
@Override
public final boolean isErrorEnabled() {
return logger.isLoggable(Level.SEVERE);
}
@Override
public final boolean isWarnEnabled() {
return logger.isLoggable(Level.WARNING);
}
@Override
public final boolean isInfoEnabled() {
return logger.isLoggable(Level.INFO);
}
@Override
public final boolean isDebugEnabled() {
return logger.isLoggable(Level.FINE);
}
@Override
public final boolean isFatalEnabled() {
return logger.isLoggable(Level.SEVERE);
}
@Override
public final boolean isTraceEnabled() {
return logger.isLoggable(Level.FINER);
}
@Override
public final void debug(Object message) {
log(Level.FINE, String.valueOf(message), null);
}
@Override
public final void debug(Object message, Throwable t) {
log(Level.FINE, String.valueOf(message), t);
}
@Override
public final void trace(Object message) {
log(Level.FINER, String.valueOf(message), null);
}
@Override
public final void trace(Object message, Throwable t) {
log(Level.FINER, String.valueOf(message), t);
}
@Override
public final void info(Object message) {
log(Level.INFO, String.valueOf(message), null);
}
@Override
public final void info(Object message, Throwable t) {
log(Level.INFO, String.valueOf(message), t);
}
@Override
public final void warn(Object message) {
log(Level.WARNING, String.valueOf(message), null);
}
@Override
public final void warn(Object message, Throwable t) {
log(Level.WARNING, String.valueOf(message), t);
}
@Override
public final void error(Object message) {
log(Level.SEVERE, String.valueOf(message), null);
}
@Override
public final void error(Object message, Throwable t) {
log(Level.SEVERE, String.valueOf(message), t);
}
@Override
public final void fatal(Object message) {
log(Level.SEVERE, String.valueOf(message), null);
}
@Override
public final void fatal(Object message, Throwable t) {
log(Level.SEVERE, String.valueOf(message), t);
}
// from commons logging. This would be my number one reason why java.util.logging
// is bad - design by committee can be really bad ! The impact on performance of
// using java.util.logging - and the ugliness if you need to wrap it - is far
// worse than the unfriendly and uncommon default format for logs.
private void log(Level level, String msg, Throwable ex) {
if (logger.isLoggable(level)) {
// Hack (?) to get the stack trace.
Throwable dummyException=new Throwable();
StackTraceElement locations[]=dummyException.getStackTrace();
// Caller will be the third element
String cname = "unknown";
String method = "unknown";
if (locations != null && locations.length >2) {
StackTraceElement caller = locations[2];
cname = caller.getClassName();
method = caller.getMethodName();
}
if (ex==null) {
logger.logp(level, cname, method, msg);
} else {
logger.logp(level, cname, method, msg, ex);
}
}
}
static Log getInstance(String name) {
return new DirectJDKLog( name );
}
}

View File

@@ -0,0 +1,251 @@
/*
* 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.juli.logging;
/**
* <p>A simple logging interface abstracting logging APIs. In order to be
* instantiated successfully by {@link LogFactory}, classes that implement
* this interface must have a constructor that takes a single String
* parameter representing the "name" of this Log.</p>
*
* <p> The six logging levels used by <code>Log</code> are (in order):</p>
* <ol>
* <li>trace (the least serious)</li>
* <li>debug</li>
* <li>info</li>
* <li>warn</li>
* <li>error</li>
* <li>fatal (the most serious)</li>
* </ol>
* <p>The mapping of these log levels to the concepts used by the underlying
* logging system is implementation dependent.
* The implementation should ensure, though, that this ordering behaves
* as expected.</p>
*
* <p>Performance is often a logging concern.
* By examining the appropriate property,
* a component can avoid expensive operations (producing information
* to be logged).</p>
*
* <p> For example,
* <code>
* if (log.isDebugEnabled()) {
* ... do something expensive ...
* log.debug(theResult);
* }
* </code>
* </p>
*
* <p>Configuration of the underlying logging system will generally be done
* external to the Logging APIs, through whatever mechanism is supported by
* that system.</p>
*
* @author <a href="mailto:sanders@apache.org">Scott Sanders</a>
* @author Rod Waldhoff
*/
public interface Log {
// ----------------------------------------------------- Logging Properties
/**
* <p> Is debug logging currently enabled? </p>
*
* <p> Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than debug. </p>
*
* @return <code>true</code> if debug level logging is enabled, otherwise
* <code>false</code>
*/
public boolean isDebugEnabled();
/**
* <p> Is error logging currently enabled? </p>
*
* <p> Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than error. </p>
*
* @return <code>true</code> if error level logging is enabled, otherwise
* <code>false</code>
*/
public boolean isErrorEnabled();
/**
* <p> Is fatal logging currently enabled? </p>
*
* <p> Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than fatal. </p>
*
* @return <code>true</code> if fatal level logging is enabled, otherwise
* <code>false</code>
*/
public boolean isFatalEnabled();
/**
* <p> Is info logging currently enabled? </p>
*
* <p> Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than info. </p>
*
* @return <code>true</code> if info level logging is enabled, otherwise
* <code>false</code>
*/
public boolean isInfoEnabled();
/**
* <p> Is trace logging currently enabled? </p>
*
* <p> Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than trace. </p>
*
* @return <code>true</code> if trace level logging is enabled, otherwise
* <code>false</code>
*/
public boolean isTraceEnabled();
/**
* <p> Is warn logging currently enabled? </p>
*
* <p> Call this method to prevent having to perform expensive operations
* (for example, <code>String</code> concatenation)
* when the log level is more than warn. </p>
*
* @return <code>true</code> if warn level logging is enabled, otherwise
* <code>false</code>
*/
public boolean isWarnEnabled();
// -------------------------------------------------------- Logging Methods
/**
* <p> Log a message with trace log level. </p>
*
* @param message log this message
*/
public void trace(Object message);
/**
* <p> Log an error with trace log level. </p>
*
* @param message log this message
* @param t log this cause
*/
public void trace(Object message, Throwable t);
/**
* <p> Log a message with debug log level. </p>
*
* @param message log this message
*/
public void debug(Object message);
/**
* <p> Log an error with debug log level. </p>
*
* @param message log this message
* @param t log this cause
*/
public void debug(Object message, Throwable t);
/**
* <p> Log a message with info log level. </p>
*
* @param message log this message
*/
public void info(Object message);
/**
* <p> Log an error with info log level. </p>
*
* @param message log this message
* @param t log this cause
*/
public void info(Object message, Throwable t);
/**
* <p> Log a message with warn log level. </p>
*
* @param message log this message
*/
public void warn(Object message);
/**
* <p> Log an error with warn log level. </p>
*
* @param message log this message
* @param t log this cause
*/
public void warn(Object message, Throwable t);
/**
* <p> Log a message with error log level. </p>
*
* @param message log this message
*/
public void error(Object message);
/**
* <p> Log an error with error log level. </p>
*
* @param message log this message
* @param t log this cause
*/
public void error(Object message, Throwable t);
/**
* <p> Log a message with fatal log level. </p>
*
* @param message log this message
*/
public void fatal(Object message);
/**
* <p> Log an error with fatal log level. </p>
*
* @param message log this message
* @param t log this cause
*/
public void fatal(Object message, Throwable t);
}

View File

@@ -0,0 +1,72 @@
/*
* 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.juli.logging;
/**
* <p>An exception that is thrown only if a suitable <code>LogFactory</code>
* or <code>Log</code> instance cannot be created by the corresponding
* factory methods.</p>
*
* @author Craig R. McClanahan
*/
public class LogConfigurationException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* Construct a new exception with <code>null</code> as its detail message.
*/
public LogConfigurationException() {
super();
}
/**
* Construct a new exception with the specified detail message.
*
* @param message The detail message
*/
public LogConfigurationException(String message) {
super(message);
}
/**
* Construct a new exception with the specified cause and a derived
* detail message.
*
* @param cause The underlying cause
*/
public LogConfigurationException(Throwable cause) {
super(cause);
}
/**
* Construct a new exception with the specified detail message and cause.
*
* @param message The detail message
* @param cause The underlying cause
*/
public LogConfigurationException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,248 @@
/*
* 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.juli.logging;
import java.lang.reflect.Constructor;
import java.nio.file.FileSystems;
import java.util.ServiceLoader;
import java.util.logging.LogManager;
/**
* This is a modified LogFactory that uses a simple {@link ServiceLoader} based
* discovery mechanism with a default of using JDK based logging. An
* implementation that uses the full Commons Logging discovery mechanism is
* available as part of the Tomcat extras download.
*
* Why? It is an attempt to strike a balance between simpler code (no discovery)
* and providing flexibility - particularly for those projects that embed Tomcat
* or some of Tomcat's components - is an alternative logging
* implementation is desired.
*
* Note that this implementation is not just a wrapper around JDK logging (like
* the original commons-logging impl). It adds 2 features - a simpler
* configuration (which is in fact a subset of log4j.properties) and a
* formatter that is less ugly.
*
* The removal of 'abstract' preserves binary backward compatibility. It is
* possible to preserve the abstract - and introduce another (hardcoded) factory
* - but I see no benefit.
*
* Since this class is not intended to be extended - all protected methods are
* removed. This can be changed - but again, there is little value in keeping
* dead code. Just take a quick look at the removed code ( and it's complexity).
*
* --------------
*
* Original comment:
* <p>Factory for creating {@link Log} instances, with discovery and
* configuration features similar to that employed by standard Java APIs
* such as JAXP.</p>
*
* <p><strong>IMPLEMENTATION NOTE</strong> - This implementation is heavily
* based on the SAXParserFactory and DocumentBuilderFactory implementations
* (corresponding to the JAXP pluggability APIs) found in Apache Xerces.</p>
*
*
* @author Craig R. McClanahan
* @author Costin Manolache
* @author Richard A. Sitze
*/
public class LogFactory {
private static final LogFactory singleton = new LogFactory();
private final Constructor<? extends Log> discoveredLogConstructor;
/**
* Private constructor that is not available for public use.
*/
private LogFactory() {
/*
* Work-around known a JRE bug.
* https://bugs.openjdk.java.net/browse/JDK-8194653
*
* Pre-load the default file system. No performance impact as we need to
* load the default file system anyway. Just do it earlier to avoid the
* potential deadlock.
*
* This can be removed once the oldest JRE supported by Tomcat includes
* a fix.
*/
FileSystems.getDefault();
// Look via a ServiceLoader for a Log implementation that has a
// constructor taking the String name.
ServiceLoader<Log> logLoader = ServiceLoader.load(Log.class);
Constructor<? extends Log> m=null;
for (Log log: logLoader) {
Class<? extends Log> c=log.getClass();
try {
m=c.getConstructor(String.class);
break;
}
catch (NoSuchMethodException | SecurityException e) {
throw new Error(e);
}
}
discoveredLogConstructor=m;
}
// --------------------------------------------------------- Public Methods
// only those 2 methods need to change to use a different direct logger.
/**
* <p>Construct (if necessary) and return a <code>Log</code> instance,
* using the factory's current set of configuration attributes.</p>
*
* <p><strong>NOTE</strong> - Depending upon the implementation of
* the <code>LogFactory</code> you are using, the <code>Log</code>
* instance you are returned may or may not be local to the current
* application, and may or may not be returned again on a subsequent
* call with the same name argument.</p>
*
* @param name Logical name of the <code>Log</code> instance to be
* returned (the meaning of this name is only known to the underlying
* logging implementation that is being wrapped)
*
* @return A log instance with the requested name
*
* @exception LogConfigurationException if a suitable <code>Log</code>
* instance cannot be returned
*/
public Log getInstance(String name) throws LogConfigurationException {
if (discoveredLogConstructor == null) {
return DirectJDKLog.getInstance(name);
}
try {
return discoveredLogConstructor.newInstance(name);
} catch (ReflectiveOperationException | IllegalArgumentException e) {
throw new LogConfigurationException(e);
}
}
/**
* Convenience method to derive a name from the specified class and
* call <code>getInstance(String)</code> with it.
*
* @param clazz Class for which a suitable Log name will be derived
*
* @return A log instance with a name of clazz.getName()
*
* @exception LogConfigurationException if a suitable <code>Log</code>
* instance cannot be returned
*/
public Log getInstance(Class<?> clazz) throws LogConfigurationException {
return getInstance( clazz.getName());
}
// ------------------------------------------------------- Static Variables
// --------------------------------------------------------- Static Methods
/**
* <p>Construct (if necessary) and return a <code>LogFactory</code>
* instance, using the following ordered lookup procedure to determine
* the name of the implementation class to be loaded.</p>
* <ul>
* <li>The <code>org.apache.commons.logging.LogFactory</code> system
* property.</li>
* <li>The JDK 1.3 Service Discovery mechanism</li>
* <li>Use the properties file <code>commons-logging.properties</code>
* file, if found in the class path of this class. The configuration
* file is in standard <code>java.util.Properties</code> format and
* contains the fully qualified name of the implementation class
* with the key being the system property defined above.</li>
* <li>Fall back to a default implementation class
* (<code>org.apache.commons.logging.impl.LogFactoryImpl</code>).</li>
* </ul>
*
* <p><em>NOTE</em> - If the properties file method of identifying the
* <code>LogFactory</code> implementation class is utilized, all of the
* properties defined in this file will be set as configuration attributes
* on the corresponding <code>LogFactory</code> instance.</p>
*
* @return The singleton LogFactory instance
*
* @exception LogConfigurationException if the implementation class is not
* available or cannot be instantiated.
*/
public static LogFactory getFactory() throws LogConfigurationException {
return singleton;
}
/**
* Convenience method to return a named logger, without the application
* having to care about factories.
*
* @param clazz Class from which a log name will be derived
*
* @return A log instance with a name of clazz.getName()
*
* @exception LogConfigurationException if a suitable <code>Log</code>
* instance cannot be returned
*/
public static Log getLog(Class<?> clazz)
throws LogConfigurationException {
return getFactory().getInstance(clazz);
}
/**
* Convenience method to return a named logger, without the application
* having to care about factories.
*
* @param name Logical name of the <code>Log</code> instance to be
* returned (the meaning of this name is only known to the underlying
* logging implementation that is being wrapped)
*
* @return A log instance with the requested name
*
* @exception LogConfigurationException if a suitable <code>Log</code>
* instance cannot be returned
*/
public static Log getLog(String name)
throws LogConfigurationException {
return getFactory().getInstance(name);
}
/**
* Release any internal references to previously created {@link LogFactory}
* instances that have been associated with the specified class loader
* (if any), after calling the instance method <code>release()</code> on
* each of them.
*
* @param classLoader ClassLoader for which to release the LogFactory
*/
public static void release(ClassLoader classLoader) {
// JULI's log manager looks at the current classLoader so there is no
// need to use the passed in classLoader, the default implementation
// does not so calling reset in that case will break things
if (!LogManager.getLogManager().getClass().getName().equals(
"java.util.logging.LogManager")) {
LogManager.getLogManager().reset();
}
}
}

View File

@@ -0,0 +1,37 @@
<!--
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.
-->
<body>
<h2>Overview</h2>
<p>This implementation of commons-logging uses a commons-logging.jar
specific to a particular logging framework, instead of discovery. This takes
out the guessing, is simpler, faster and more robust. Just like you chose a
logging implementation, you should also use a matching commons-logging - for
example you download log4j.jar and commons-logging-log4j.jar, or use jdk
logging and use commons-logging-jdk.jar.</p>
<p>A similar packaging is used by Eclipse SWT - they provide a common widget API,
but each platform uses a different implementation jar - instead of using a complex
discovery/plugin mechanism.
</p>
<p>This package generates commons-logging-jdk14.jar - i.e. the java.util implementation
of commons-logging api.</p>
</body>