Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (101)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (309)
Collections:
Other Resources:
Source Code for Apache Log4j API
Apache Log4j API
provides the interface that applications should code to and provides the adapter
components required for implementers to create a logging implementation.
Apache Log4j API is a required module to use Apache Log4j.
Bytecode (Java 8) for Apache Log4j API is provided in a separate JAR file like log4j-api-2.14.1.jar.
Source Code files for Apache Log4j API are provided in both binary packge like apache-log4j-2.14.1-bin.zip and source package like apache-log4j-2.14.1-src.zip. You can download them at Apache Log4j Website.
You can also browse Source Code files for Apache Log4j API 2.14.1 below.
✍: FYIcenter.com
⏎ org/apache/logging/log4j/message/ParameterFormatter.java
/* * 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.logging.log4j.message; import org.apache.logging.log4j.util.StringBuilders; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.IdentityHashMap; import java.util.Map; import java.util.Set; /** * Supports parameter formatting as used in ParameterizedMessage and ReusableParameterizedMessage. */ final class ParameterFormatter { /** * Prefix for recursion. */ static final String RECURSION_PREFIX = "[..."; /** * Suffix for recursion. */ static final String RECURSION_SUFFIX = "...]"; /** * Prefix for errors. */ static final String ERROR_PREFIX = "[!!!"; /** * Separator for errors. */ static final String ERROR_SEPARATOR = "=>"; /** * Separator for error messages. */ static final String ERROR_MSG_SEPARATOR = ":"; /** * Suffix for errors. */ static final String ERROR_SUFFIX = "!!!]"; private static final char DELIM_START = '{'; private static final char DELIM_STOP = '}'; private static final char ESCAPE_CHAR = '\\'; private static final ThreadLocal<SimpleDateFormat> SIMPLE_DATE_FORMAT_REF = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); private ParameterFormatter() { } /** * Counts the number of unescaped placeholders in the given messagePattern. * * @param messagePattern the message pattern to be analyzed. * @return the number of unescaped placeholders. */ static int countArgumentPlaceholders(final String messagePattern) { if (messagePattern == null) { return 0; } final int length = messagePattern.length(); int result = 0; boolean isEscaped = false; for (int i = 0; i < length - 1; i++) { final char curChar = messagePattern.charAt(i); if (curChar == ESCAPE_CHAR) { isEscaped = !isEscaped; } else if (curChar == DELIM_START) { if (!isEscaped && messagePattern.charAt(i + 1) == DELIM_STOP) { result++; i++; } isEscaped = false; } else { isEscaped = false; } } return result; } /** * Counts the number of unescaped placeholders in the given messagePattern. * * @param messagePattern the message pattern to be analyzed. * @return the number of unescaped placeholders. */ static int countArgumentPlaceholders2(final String messagePattern, final int[] indices) { if (messagePattern == null) { return 0; } final int length = messagePattern.length(); int result = 0; boolean isEscaped = false; for (int i = 0; i < length - 1; i++) { final char curChar = messagePattern.charAt(i); if (curChar == ESCAPE_CHAR) { isEscaped = !isEscaped; indices[0] = -1; // escaping means fast path is not available... result++; } else if (curChar == DELIM_START) { if (!isEscaped && messagePattern.charAt(i + 1) == DELIM_STOP) { indices[result] = i; result++; i++; } isEscaped = false; } else { isEscaped = false; } } return result; } /** * Counts the number of unescaped placeholders in the given messagePattern. * * @param messagePattern the message pattern to be analyzed. * @return the number of unescaped placeholders. */ static int countArgumentPlaceholders3(final char[] messagePattern, final int length, final int[] indices) { int result = 0; boolean isEscaped = false; for (int i = 0; i < length - 1; i++) { final char curChar = messagePattern[i]; if (curChar == ESCAPE_CHAR) { isEscaped = !isEscaped; } else if (curChar == DELIM_START) { if (!isEscaped && messagePattern[i + 1] == DELIM_STOP) { indices[result] = i; result++; i++; } isEscaped = false; } else { isEscaped = false; } } return result; } /** * Replace placeholders in the given messagePattern with arguments. * * @param messagePattern the message pattern containing placeholders. * @param arguments the arguments to be used to replace placeholders. * @return the formatted message. */ static String format(final String messagePattern, final Object[] arguments) { final StringBuilder result = new StringBuilder(); final int argCount = arguments == null ? 0 : arguments.length; formatMessage(result, messagePattern, arguments, argCount); return result.toString(); } /** * Replace placeholders in the given messagePattern with arguments. * * @param buffer the buffer to write the formatted message into * @param messagePattern the message pattern containing placeholders. * @param arguments the arguments to be used to replace placeholders. */ static void formatMessage2(final StringBuilder buffer, final String messagePattern, final Object[] arguments, final int argCount, final int[] indices) { if (messagePattern == null || arguments == null || argCount == 0) { buffer.append(messagePattern); return; } int previous = 0; for (int i = 0; i < argCount; i++) { buffer.append(messagePattern, previous, indices[i]); previous = indices[i] + 2; recursiveDeepToString(arguments[i], buffer); } buffer.append(messagePattern, previous, messagePattern.length()); } /** * Replace placeholders in the given messagePattern with arguments. * * @param buffer the buffer to write the formatted message into * @param messagePattern the message pattern containing placeholders. * @param arguments the arguments to be used to replace placeholders. */ static void formatMessage3(final StringBuilder buffer, final char[] messagePattern, final int patternLength, final Object[] arguments, final int argCount, final int[] indices) { if (messagePattern == null) { return; } if (arguments == null || argCount == 0) { buffer.append(messagePattern); return; } int previous = 0; for (int i = 0; i < argCount; i++) { buffer.append(messagePattern, previous, indices[i]); previous = indices[i] + 2; recursiveDeepToString(arguments[i], buffer); } buffer.append(messagePattern, previous, patternLength); } /** * Replace placeholders in the given messagePattern with arguments. * * @param buffer the buffer to write the formatted message into * @param messagePattern the message pattern containing placeholders. * @param arguments the arguments to be used to replace placeholders. */ static void formatMessage(final StringBuilder buffer, final String messagePattern, final Object[] arguments, final int argCount) { if (messagePattern == null || arguments == null || argCount == 0) { buffer.append(messagePattern); return; } int escapeCounter = 0; int currentArgument = 0; int i = 0; final int len = messagePattern.length(); for (; i < len - 1; i++) { // last char is excluded from the loop final char curChar = messagePattern.charAt(i); if (curChar == ESCAPE_CHAR) { escapeCounter++; } else { if (isDelimPair(curChar, messagePattern, i)) { // looks ahead one char i++; // write escaped escape chars writeEscapedEscapeChars(escapeCounter, buffer); if (isOdd(escapeCounter)) { // i.e. escaped: write escaped escape chars writeDelimPair(buffer); } else { // unescaped writeArgOrDelimPair(arguments, argCount, currentArgument, buffer); currentArgument++; } } else { handleLiteralChar(buffer, escapeCounter, curChar); } escapeCounter = 0; } } handleRemainingCharIfAny(messagePattern, len, buffer, escapeCounter, i); } /** * Returns {@code true} if the specified char and the char at {@code curCharIndex + 1} in the specified message * pattern together form a "{}" delimiter pair, returns {@code false} otherwise. */ // Profiling showed this method is important to log4j performance. Modify with care! // 22 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 private static boolean isDelimPair(final char curChar, final String messagePattern, final int curCharIndex) { return curChar == DELIM_START && messagePattern.charAt(curCharIndex + 1) == DELIM_STOP; } /** * Detects whether the message pattern has been fully processed or if an unprocessed character remains and processes * it if necessary, returning the resulting position in the result char array. */ // Profiling showed this method is important to log4j performance. Modify with care! // 28 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 private static void handleRemainingCharIfAny(final String messagePattern, final int len, final StringBuilder buffer, final int escapeCounter, final int i) { if (i == len - 1) { final char curChar = messagePattern.charAt(i); handleLastChar(buffer, escapeCounter, curChar); } } /** * Processes the last unprocessed character and returns the resulting position in the result char array. */ // Profiling showed this method is important to log4j performance. Modify with care! // 28 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 private static void handleLastChar(final StringBuilder buffer, final int escapeCounter, final char curChar) { if (curChar == ESCAPE_CHAR) { writeUnescapedEscapeChars(escapeCounter + 1, buffer); } else { handleLiteralChar(buffer, escapeCounter, curChar); } } /** * Processes a literal char (neither an '\' escape char nor a "{}" delimiter pair) and returns the resulting * position. */ // Profiling showed this method is important to log4j performance. Modify with care! // 16 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 private static void handleLiteralChar(final StringBuilder buffer, final int escapeCounter, final char curChar) { // any other char beside ESCAPE or DELIM_START/STOP-combo // write unescaped escape chars writeUnescapedEscapeChars(escapeCounter, buffer); buffer.append(curChar); } /** * Writes "{}" to the specified result array at the specified position and returns the resulting position. */ // Profiling showed this method is important to log4j performance. Modify with care! // 18 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 private static void writeDelimPair(final StringBuilder buffer) { buffer.append(DELIM_START); buffer.append(DELIM_STOP); } /** * Returns {@code true} if the specified parameter is odd. */ // Profiling showed this method is important to log4j performance. Modify with care! // 11 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 private static boolean isOdd(final int number) { return (number & 1) == 1; } /** * Writes a '\' char to the specified result array (starting at the specified position) for each <em>pair</em> of * '\' escape chars encountered in the message format and returns the resulting position. */ // Profiling showed this method is important to log4j performance. Modify with care! // 11 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 private static void writeEscapedEscapeChars(final int escapeCounter, final StringBuilder buffer) { final int escapedEscapes = escapeCounter >> 1; // divide by two writeUnescapedEscapeChars(escapedEscapes, buffer); } /** * Writes the specified number of '\' chars to the specified result array (starting at the specified position) and * returns the resulting position. */ // Profiling showed this method is important to log4j performance. Modify with care! // 20 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 private static void writeUnescapedEscapeChars(int escapeCounter, final StringBuilder buffer) { while (escapeCounter > 0) { buffer.append(ESCAPE_CHAR); escapeCounter--; } } /** * Appends the argument at the specified argument index (or, if no such argument exists, the "{}" delimiter pair) to * the specified result char array at the specified position and returns the resulting position. */ // Profiling showed this method is important to log4j performance. Modify with care! // 25 bytes (allows immediate JVM inlining: < 35 bytes) LOG4J2-1096 private static void writeArgOrDelimPair(final Object[] arguments, final int argCount, final int currentArgument, final StringBuilder buffer) { if (currentArgument < argCount) { recursiveDeepToString(arguments[currentArgument], buffer); } else { writeDelimPair(buffer); } } /** * This method performs a deep toString of the given Object. * Primitive arrays are converted using their respective Arrays.toString methods while * special handling is implemented for "container types", i.e. Object[], Map and Collection because those could * contain themselves. * <p> * It should be noted that neither AbstractMap.toString() nor AbstractCollection.toString() implement such a * behavior. They only check if the container is directly contained in itself, but not if a contained container * contains the original one. Because of that, Arrays.toString(Object[]) isn't safe either. * Confusing? Just read the last paragraph again and check the respective toString() implementation. * </p> * <p> * This means, in effect, that logging would produce a usable output even if an ordinary System.out.println(o) * would produce a relatively hard-to-debug StackOverflowError. * </p> * @param o The object. * @return The String representation. */ static String deepToString(final Object o) { if (o == null) { return null; } // Check special types to avoid unnecessary StringBuilder usage if (o instanceof String) { return (String) o; } if (o instanceof Integer) { return Integer.toString((Integer) o); } if (o instanceof Long) { return Long.toString((Long) o); } if (o instanceof Double) { return Double.toString((Double) o); } if (o instanceof Boolean) { return Boolean.toString((Boolean) o); } if (o instanceof Character) { return Character.toString((Character) o); } if (o instanceof Short) { return Short.toString((Short) o); } if (o instanceof Float) { return Float.toString((Float) o); } if (o instanceof Byte) { return Byte.toString((Byte) o); } final StringBuilder str = new StringBuilder(); recursiveDeepToString(o, str); return str.toString(); } /** * This method performs a deep {@code toString()} of the given {@code Object}. * <p> * Primitive arrays are converted using their respective {@code Arrays.toString()} methods, while * special handling is implemented for <i>container types</i>, i.e. {@code Object[]}, {@code Map} and {@code Collection}, * because those could contain themselves. * <p> * It should be noted that neither {@code AbstractMap.toString()} nor {@code AbstractCollection.toString()} implement such a behavior. * They only check if the container is directly contained in itself, but not if a contained container contains the original one. * Because of that, {@code Arrays.toString(Object[])} isn't safe either. * Confusing? Just read the last paragraph again and check the respective {@code toString()} implementation. * <p> * This means, in effect, that logging would produce a usable output even if an ordinary {@code System.out.println(o)} * would produce a relatively hard-to-debug {@code StackOverflowError}. * * @param o the {@code Object} to convert into a {@code String} * @param str the {@code StringBuilder} that {@code o} will be appended to */ static void recursiveDeepToString(final Object o, final StringBuilder str) { recursiveDeepToString(o, str, null); } /** * This method performs a deep {@code toString()} of the given {@code Object}. * <p> * Primitive arrays are converted using their respective {@code Arrays.toString()} methods, while * special handling is implemented for <i>container types</i>, i.e. {@code Object[]}, {@code Map} and {@code Collection}, * because those could contain themselves. * <p> * {@code dejaVu} is used in case of those container types to prevent an endless recursion. * <p> * It should be noted that neither {@code AbstractMap.toString()} nor {@code AbstractCollection.toString()} implement such a behavior. * They only check if the container is directly contained in itself, but not if a contained container contains the original one. * Because of that, {@code Arrays.toString(Object[])} isn't safe either. * Confusing? Just read the last paragraph again and check the respective {@code toString()} implementation. * <p> * This means, in effect, that logging would produce a usable output even if an ordinary {@code System.out.println(o)} * would produce a relatively hard-to-debug {@code StackOverflowError}. * * @param o the {@code Object} to convert into a {@code String} * @param str the {@code StringBuilder} that {@code o} will be appended to * @param dejaVu a set of container objects directly or transitively containing {@code o} */ private static void recursiveDeepToString(final Object o, final StringBuilder str, final Set<Object> dejaVu) { if (appendSpecialTypes(o, str)) { return; } if (isMaybeRecursive(o)) { appendPotentiallyRecursiveValue(o, str, dejaVu); } else { tryObjectToString(o, str); } } private static boolean appendSpecialTypes(final Object o, final StringBuilder str) { return StringBuilders.appendSpecificTypes(str, o) || appendDate(o, str); } private static boolean appendDate(final Object o, final StringBuilder str) { if (!(o instanceof Date)) { return false; } final Date date = (Date) o; final SimpleDateFormat format = SIMPLE_DATE_FORMAT_REF.get(); str.append(format.format(date)); return true; } /** * Returns {@code true} if the specified object is an array, a Map or a Collection. */ private static boolean isMaybeRecursive(final Object o) { return o.getClass().isArray() || o instanceof Map || o instanceof Collection; } private static void appendPotentiallyRecursiveValue( final Object o, final StringBuilder str, final Set<Object> dejaVu) { final Class<?> oClass = o.getClass(); if (oClass.isArray()) { appendArray(o, str, dejaVu, oClass); } else if (o instanceof Map) { appendMap(o, str, dejaVu); } else if (o instanceof Collection) { appendCollection(o, str, dejaVu); } else { throw new IllegalArgumentException("was expecting a container, found " + oClass); } } private static void appendArray( final Object o, final StringBuilder str, final Set<Object> dejaVu, final Class<?> oClass) { if (oClass == byte[].class) { str.append(Arrays.toString((byte[]) o)); } else if (oClass == short[].class) { str.append(Arrays.toString((short[]) o)); } else if (oClass == int[].class) { str.append(Arrays.toString((int[]) o)); } else if (oClass == long[].class) { str.append(Arrays.toString((long[]) o)); } else if (oClass == float[].class) { str.append(Arrays.toString((float[]) o)); } else if (oClass == double[].class) { str.append(Arrays.toString((double[]) o)); } else if (oClass == boolean[].class) { str.append(Arrays.toString((boolean[]) o)); } else if (oClass == char[].class) { str.append(Arrays.toString((char[]) o)); } else { // special handling of container Object[] final Set<Object> effectiveDejaVu = getOrCreateDejaVu(dejaVu); final boolean seen = !effectiveDejaVu.add(o); if (seen) { final String id = identityToString(o); str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX); } else { final Object[] oArray = (Object[]) o; str.append('['); boolean first = true; for (final Object current : oArray) { if (first) { first = false; } else { str.append(", "); } recursiveDeepToString(current, str, cloneDejaVu(effectiveDejaVu)); } str.append(']'); } } } /** * Specialized handler for {@link Map}s. */ private static void appendMap( final Object o, final StringBuilder str, final Set<Object> dejaVu) { final Set<Object> effectiveDejaVu = getOrCreateDejaVu(dejaVu); final boolean seen = !effectiveDejaVu.add(o); if (seen) { final String id = identityToString(o); str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX); } else { final Map<?, ?> oMap = (Map<?, ?>) o; str.append('{'); boolean isFirst = true; for (final Object o1 : oMap.entrySet()) { final Map.Entry<?, ?> current = (Map.Entry<?, ?>) o1; if (isFirst) { isFirst = false; } else { str.append(", "); } final Object key = current.getKey(); final Object value = current.getValue(); recursiveDeepToString(key, str, cloneDejaVu(effectiveDejaVu)); str.append('='); recursiveDeepToString(value, str, cloneDejaVu(effectiveDejaVu)); } str.append('}'); } } /** * Specialized handler for {@link Collection}s. */ private static void appendCollection( final Object o, final StringBuilder str, final Set<Object> dejaVu) { final Set<Object> effectiveDejaVu = getOrCreateDejaVu(dejaVu); final boolean seen = !effectiveDejaVu.add(o); if (seen) { final String id = identityToString(o); str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX); } else { final Collection<?> oCol = (Collection<?>) o; str.append('['); boolean isFirst = true; for (final Object anOCol : oCol) { if (isFirst) { isFirst = false; } else { str.append(", "); } recursiveDeepToString(anOCol, str, cloneDejaVu(effectiveDejaVu)); } str.append(']'); } } private static Set<Object> getOrCreateDejaVu(Set<Object> dejaVu) { return dejaVu == null ? createDejaVu() : dejaVu; } private static Set<Object> createDejaVu() { return Collections.newSetFromMap(new IdentityHashMap<>()); } private static Set<Object> cloneDejaVu(Set<Object> dejaVu) { Set<Object> clonedDejaVu = createDejaVu(); clonedDejaVu.addAll(dejaVu); return clonedDejaVu; } private static void tryObjectToString(final Object o, final StringBuilder str) { // it's just some other Object, we can only use toString(). try { str.append(o.toString()); } catch (final Throwable t) { handleErrorInObjectToString(o, str, t); } } private static void handleErrorInObjectToString(final Object o, final StringBuilder str, final Throwable t) { str.append(ERROR_PREFIX); str.append(identityToString(o)); str.append(ERROR_SEPARATOR); final String msg = t.getMessage(); final String className = t.getClass().getName(); str.append(className); if (!className.equals(msg)) { str.append(ERROR_MSG_SEPARATOR); str.append(msg); } str.append(ERROR_SUFFIX); } /** * This method returns the same as if Object.toString() would not have been * overridden in obj. * <p> * Note that this isn't 100% secure as collisions can always happen with hash codes. * </p> * <p> * Copied from Object.hashCode(): * </p> * <blockquote> * As much as is reasonably practical, the hashCode method defined by * class {@code Object} does return distinct integers for distinct * objects. (This is typically implemented by converting the internal * address of the object into an integer, but this implementation * technique is not required by the Java™ programming language.) * </blockquote> * * @param obj the Object that is to be converted into an identity string. * @return the identity string as also defined in Object.toString() */ static String identityToString(final Object obj) { if (obj == null) { return null; } return obj.getClass().getName() + '@' + Integer.toHexString(System.identityHashCode(obj)); } }
⏎ org/apache/logging/log4j/message/ParameterFormatter.java
Or download all of them as a single archive file:
File name: log4j-api-2.14.1-sources.jar File size: 264773 bytes Release date: 2021-03-06 Download
⇒ Source Code for Apache Log4j Core Implementation
⇐ Downloading Apache Log4j Binary Package
2015-11-17, 23391👍, 0💬
Popular Posts:
The Digester package lets you configure an XML -> Java object mapping module, which triggers certain...
What Is mail.jar of JavaMail 1.4? I got the JAR file from javamail-1_4.zip. mail.jar in javamail-1_4...
commons-fileupload-1.3.3 -sources.jaris the source JAR file for Apache Commons FileUpload 1.3., whic...
What is the sax\Writer.java provided in the Apache Xerces package? I have Apache Xerces 2.11.0 insta...
commons-io-1.4.jar is the JAR file for Commons IO 1.4, which is a library of utilities to assist wit...