This is an automated email from the ASF dual-hosted git repository. pkarwasz pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit c4ce19f4f6134ce36551ace8c9c7d65b70ea4d4f Author: Gary Gregory <[email protected]> AuthorDate: Sat Feb 5 15:53:20 2022 -0500 Log4j 1.2 bridge missing some LocationInfo constructors. Conflicts: log4j-1.2-api/src/main/java/org/apache/log4j/spi/LocationInfo.java --- .../java/org/apache/log4j/spi/LocationInfo.java | 96 +++++++++++++++++----- .../org/apache/log4j/spi/LocationInfoTest.java | 82 ++++++++++++++++++ src/changes/changes.xml | 3 + 3 files changed, 162 insertions(+), 19 deletions(-) diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LocationInfo.java b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LocationInfo.java index c5e5b5e..a3f2fd1 100644 --- a/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LocationInfo.java +++ b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/LocationInfo.java @@ -16,62 +16,120 @@ */ package org.apache.log4j.spi; +import java.io.Serializable; +import java.util.Objects; + /** * The internal representation of caller location information. - * + * * @since 0.8.3 */ -public class LocationInfo implements java.io.Serializable { +public class LocationInfo implements Serializable { + + /** + * When location information is not available the constant <code>NA</code> is returned. Current value of this string + * constant is <b>?</b>. + */ + public final static String NA = "?"; + + static final long serialVersionUID = -1325822038990805636L; - private final StackTraceElement element; + private final StackTraceElement stackTraceElement; public String fullInfo; /** - * Constructor for LocationInfo. - * @param element The StackTraceElement representing the caller. + * Constructs a new instance. */ - public LocationInfo(StackTraceElement element) { - this.element = element; + public LocationInfo(final StackTraceElement stackTraceElement) { + this.stackTraceElement = Objects.requireNonNull(stackTraceElement, "stackTraceElement"); + this.fullInfo = stackTraceElement.toString(); } /** - * When location information is not available the constant <code>NA</code> is returned. Current value of this string - * constant is <b>?</b>. + * Constructs a new instance. + * + * @param file source file name + * @param declaringClass class name + * @param methodName method + * @param line source line number + * + * @since 1.2.15 */ - public final static String NA = "?"; + public LocationInfo(final String file, final String declaringClass, final String methodName, final String line) { + this(new StackTraceElement(declaringClass, methodName, file, Integer.parseInt(line))); + } - static final long serialVersionUID = -1325822038990805636L; + /** + * Constructs a new instance. + */ + public LocationInfo(final Throwable throwable, final String fqnOfCallingClass) { + String declaringClass = null, methodName = null, file = null, line = null; + if (throwable != null && fqnOfCallingClass != null) { + final StackTraceElement[] elements = throwable.getStackTrace(); + String prevClass = NA; + for (int i = elements.length - 1; i >= 0; i--) { + final String thisClass = elements[i].getClassName(); + if (fqnOfCallingClass.equals(thisClass)) { + final int caller = i + 1; + if (caller < elements.length) { + declaringClass = prevClass; + methodName = elements[caller].getMethodName(); + file = elements[caller].getFileName(); + if (file == null) { + file = NA; + } + final int lineNo = elements[caller].getLineNumber(); + if (lineNo < 0) { + line = NA; + } else { + line = String.valueOf(lineNo); + } + final StringBuilder builder = new StringBuilder(); + builder.append(declaringClass); + builder.append("."); + builder.append(methodName); + builder.append("("); + builder.append(file); + builder.append(":"); + builder.append(line); + builder.append(")"); + this.fullInfo = builder.toString(); + } + break; + } + prevClass = thisClass; + } + } + this.stackTraceElement = new StackTraceElement(declaringClass, methodName, file, Integer.parseInt(line)); + this.fullInfo = stackTraceElement.toString(); + } /** * Return the fully qualified class name of the caller making the logging request. - @return The class name. */ public String getClassName() { - return element.getClassName(); + return stackTraceElement.getClassName(); } /** * Return the file name of the caller. - @return the file name. */ public String getFileName() { - return element.getFileName(); + return stackTraceElement.getFileName(); } /** * Returns the line number of the caller. - @return The line number. */ public String getLineNumber() { - return Integer.toString(element.getLineNumber()); + return Integer.toString(stackTraceElement.getLineNumber()); } /** * Returns the method name of the caller. - @return The method name. */ public String getMethodName() { - return element.getMethodName(); + return stackTraceElement.getMethodName(); } } diff --git a/log4j-1.2-api/src/test/java/org/apache/log4j/spi/LocationInfoTest.java b/log4j-1.2-api/src/test/java/org/apache/log4j/spi/LocationInfoTest.java new file mode 100644 index 0000000..a6daefc --- /dev/null +++ b/log4j-1.2-api/src/test/java/org/apache/log4j/spi/LocationInfoTest.java @@ -0,0 +1,82 @@ +/* + * 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.log4j.spi; + +import junit.framework.TestCase; + +/** + * Tests for LocationInfo. + */ +public class LocationInfoTest extends TestCase { + + /** + * Tests four parameter constructor. + */ + public void testFourParamConstructor() { + final String className = LocationInfoTest.class.getName(); + final String methodName = "testFourParamConstructor"; + final String fileName = "LocationInfoTest.java"; + final String lineNumber = "41"; + LocationInfo li = new LocationInfo(fileName, className, methodName, lineNumber); + assertEquals(className, li.getClassName()); + assertEquals(methodName, li.getMethodName()); + assertEquals(fileName, li.getFileName()); + assertEquals(lineNumber, li.getLineNumber()); + assertEquals(className + "." + methodName + "(" + fileName + ":" + lineNumber + ")", li.fullInfo); + } + + /** + * Class with name that is a substring of its caller. + */ + private static class NameSubstring { + /** + * Construct a LocationInfo. Location should be immediate caller of this method. + * + * @return location info. + */ + public static LocationInfo getInfo() { + return new LocationInfo(new Throwable(), NameSubstring.class.getName()); + + } + } + + /** + * Class whose name is contains the name of the class that obtains the LocationInfo. + */ + private static class NameSubstringCaller { + /** + * Construct a locationInfo. Location should be this location. + * + * @return location info. + */ + public static LocationInfo getInfo() { + return NameSubstring.getInfo(); + } + + } + + /** + * Tests creation of location info when the logger class name is a substring of one of the other classes in the stack + * trace. See bug 44888. + */ + public void testLocationInfo() { + LocationInfo li = NameSubstringCaller.getInfo(); + assertEquals(NameSubstringCaller.class.getName(), li.getClassName()); + assertEquals("getInfo", li.getMethodName()); + } + +} diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 7d288e7..0226b41 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -331,6 +331,9 @@ <action dev="ggregory" type="fix" due-to="Gary Gregory"> Log4j 1.2 bridge missing some ThrowableInformation constructors. </action> + <action dev="ggregory" type="fix" due-to="Gary Gregory"> + Log4j 1.2 bridge missing some LocationInfo constructors. + </action> <action dev="ggregory" type="fix"> JndiManager reverts to 2.17.0 behavior: Read the system property for each call. </action>
