Skip to content

Commit 1e70db2

Browse files
committed
LogService: Make getLevel() more robust against ClassNotFoundException
1 parent 80d0a38 commit 1e70db2

File tree

4 files changed

+44
-10
lines changed

4 files changed

+44
-10
lines changed

src/main/java/org/scijava/log/AbstractLogService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public LogSource getSource() {
104104
@Override
105105
public int getLevel() {
106106
if (classAndPackageLevels.isEmpty()) return currentLevel;
107-
return getLevelForClass(CallingClassUtils.getCallingClass().getName(),
107+
return getLevelForClass(CallingClassUtils.getCallingClassName(),
108108
currentLevel);
109109
}
110110

src/main/java/org/scijava/log/CallingClassUtils.java

+32
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,44 @@ private CallingClassUtils() {
4343
}
4444

4545
/**
46+
* Inspects the stack trace to return the name of the class that calls
47+
* this method, but ignores every class annotated with @IgnoreAsCallingClass.
48+
* <p>
49+
* If every class on the stack trace is annotated, then the class at the
50+
* root of the stack trace is returned.
51+
*/
52+
public static String getCallingClassName() {
53+
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
54+
for (int i = 1; i < stackTrace.length - 2; i++) {
55+
String className = stackTrace[i].getClassName();
56+
if (!hasIgnoreAsCallingClassAnnotation(className)) return className;
57+
}
58+
return stackTrace[stackTrace.length - 1].getClassName();
59+
}
60+
61+
private static boolean hasIgnoreAsCallingClassAnnotation(String className) {
62+
try {
63+
Class< ? > clazz = Class.forName(className);
64+
return clazz.isAnnotationPresent(IgnoreAsCallingClass.class);
65+
}
66+
catch (ClassNotFoundException ignore) {
67+
return false;
68+
}
69+
}
70+
71+
/**
72+
* @deprecated Use {@link #getCallingClassName()} instead.
73+
*
74+
* Warning: This method throws a IllegalStateException as soon as it comes
75+
* across a class that can't be loaded with the default class loader.
76+
*
4677
* Inspects the stack trace to return the class that calls this method, but
4778
* ignores every class annotated with @IgnoreAsCallingClass.
4879
*
4980
* @throws IllegalStateException if every method on the stack, is in a class
5081
* annotated with @IgnoreAsCallingClass.
5182
*/
83+
@Deprecated
5284
public static Class<?> getCallingClass() {
5385
try {
5486
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

src/main/java/org/scijava/log/IgnoreAsCallingClass.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
/**
3636
* Classes annotated with {@link IgnoreAsCallingClass} are ignored by
37-
* {@link CallingClassUtils#getCallingClass()}.
37+
* {@link CallingClassUtils#getCallingClassName()}.
3838
*
3939
* @author Matthias Arzt
4040
*/

src/test/java/org/scijava/log/CallingClassUtilsTest.java

+10-8
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131

3232
import org.junit.Test;
3333

34+
import java.util.function.Supplier;
35+
3436
import static org.junit.Assert.assertEquals;
3537

3638
/**
@@ -41,26 +43,26 @@
4143
public class CallingClassUtilsTest {
4244
@Test
4345
public void testGetCallingClass() {
44-
Class<?> callingClass = CallingClassUtils.getCallingClass();
45-
assertEquals(this.getClass(), callingClass);
46+
String callingClass = CallingClassUtils.getCallingClassName();
47+
assertEquals(this.getClass().getName(), callingClass);
4648
}
4749

4850
@Test
4951
public void testIgnoreAsCallingClass() {
50-
assertEquals(ClassA.class, ClassA.returnGetCallingClass());
51-
assertEquals(this.getClass(), ClassB.returnGetCallingClass());
52+
assertEquals(ClassA.class.getName(), ClassA.returnGetCallingClass());
53+
assertEquals(this.getClass().getName(), ClassB.returnGetCallingClass());
5254
}
5355

5456
public static class ClassA {
55-
static Class<?> returnGetCallingClass() {
56-
return CallingClassUtils.getCallingClass();
57+
static String returnGetCallingClass() {
58+
return CallingClassUtils.getCallingClassName();
5759
}
5860
}
5961

6062
@IgnoreAsCallingClass
6163
private static class ClassB {
62-
static Class<?> returnGetCallingClass() {
63-
return CallingClassUtils.getCallingClass();
64+
static String returnGetCallingClass() {
65+
return CallingClassUtils.getCallingClassName();
6466
}
6567
}
6668
}

0 commit comments

Comments
 (0)