Skip to content

Commit

Permalink
Use the classpathFromResources mechanism to ensure the jars recipes n…
Browse files Browse the repository at this point in the history
…eed are always present
  • Loading branch information
sambsnyd committed Mar 12, 2024
1 parent 3a9bbfa commit f5c66f7
Show file tree
Hide file tree
Showing 37 changed files with 209 additions and 161 deletions.
25 changes: 12 additions & 13 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ group = "org.openrewrite.recipe"
description = "Enforce logging best practices and migrate between logging frameworks. Automatically."

val rewriteVersion = rewriteRecipe.rewriteVersion.get()

recipeDependencies {

parserClasspath("org.slf4j:slf4j-api:2.+")
parserClasspath("log4j:log4j:1.+")
parserClasspath("org.apache.logging.log4j:log4j-core:2.+")
parserClasspath("org.apache.logging.log4j:log4j-api:2.+")
parserClasspath("commons-logging:commons-logging:1.+")
parserClasspath("ch.qos.logback:logback-classic:1.3.+")
parserClasspath("org.projectlombok:lombok:1.18.+")
}

dependencies {
compileOnly("org.projectlombok:lombok:latest.release")
annotationProcessor("org.projectlombok:lombok:latest.release")
Expand All @@ -25,18 +37,5 @@ dependencies {
testImplementation("org.openrewrite:rewrite-test")
testImplementation("org.openrewrite:rewrite-java-tck")

testImplementation("org.projectlombok:lombok:latest.release")
testImplementation("org.assertj:assertj-core:latest.release")

testRuntimeOnly("org.openrewrite:rewrite-java-17")
testRuntimeOnly("commons-logging:commons-logging:1.2")
testRuntimeOnly("ch.qos.logback:logback-classic:1.3.11")

testRuntimeOnly("org.apache.logging.log4j:log4j-core:2.+")
testRuntimeOnly("org.apache.logging.log4j:log4j-api:2.+")

testRuntimeOnly("org.slf4j:slf4j-api:2.+")
testRuntimeOnly("log4j:log4j:1.+")

testRuntimeOnly("commons-logging:commons-logging:1.+")
}
30 changes: 17 additions & 13 deletions src/main/java/org/openrewrite/java/logging/AddLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
import java.util.Comparator;
import java.util.function.Function;

import static java.util.Objects.requireNonNull;

/**
* @author Edward Harman
*/
Expand All @@ -49,32 +51,33 @@ public AddLogger(J.ClassDeclaration scope, String loggerType, String factoryType
this.template = template.apply(this);
}

public static TreeVisitor<J, ExecutionContext> addLogger(J.ClassDeclaration scope, LoggingFramework loggingFramework, String loggerName) {
public static TreeVisitor<J, ExecutionContext> addLogger(J.ClassDeclaration scope, LoggingFramework loggingFramework, String loggerName, ExecutionContext ctx) {
switch (loggingFramework) {
case Log4J1:
return addLog4j1Logger(scope, loggerName);
return addLog4j1Logger(scope, loggerName, ctx);
case Log4J2:
return addLog4j2Logger(scope, loggerName);
return addLog4j2Logger(scope, loggerName, ctx);
case JUL:
return addJulLogger(scope, loggerName);
return addJulLogger(scope, loggerName, ctx);
case SLF4J:
default:
return addSlf4jLogger(scope, loggerName);
return addSlf4jLogger(scope, loggerName, ctx);
}
}

public static AddLogger addSlf4jLogger(J.ClassDeclaration scope, String loggerName) {
public static AddLogger addSlf4jLogger(J.ClassDeclaration scope, String loggerName, ExecutionContext ctx) {
return new AddLogger(scope, "org.slf4j.Logger", "org.slf4j.LoggerFactory", loggerName, visitor ->
JavaTemplate
.builder("private static final Logger #{} = LoggerFactory.getLogger(#{}.class);")
.contextSensitive()
.imports("org.slf4j.Logger", "org.slf4j.LoggerFactory")
.javaParser(JavaParser.fromJavaVersion().classpath("slf4j-api"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "slf4j-api-2.1"))
.build()
);
}

public static AddLogger addJulLogger(J.ClassDeclaration scope, String loggerName) {
public static AddLogger addJulLogger(J.ClassDeclaration scope, String loggerName, @SuppressWarnings("unused") ExecutionContext ctx) {
return new AddLogger(scope, "java.util.logging.Logger", "java.util.logging.LogManager", loggerName, visitor ->
JavaTemplate
.builder("private static final Logger #{} = LogManager.getLogger(\"#{}\");")
Expand All @@ -84,24 +87,24 @@ public static AddLogger addJulLogger(J.ClassDeclaration scope, String loggerName
);
}

public static AddLogger addLog4j1Logger(J.ClassDeclaration scope, String loggerName) {
public static AddLogger addLog4j1Logger(J.ClassDeclaration scope, String loggerName, ExecutionContext ctx) {
return new AddLogger(scope, "org.apache.log4j.Logger", "org.apache.log4j.LogManager", loggerName, visitor ->
JavaTemplate
.builder("private static final Logger #{} = LogManager.getLogger(#{}.class);")
.contextSensitive()
.imports("org.apache.log4j.Logger", "org.apache.log4j.LogManager")
.javaParser(JavaParser.fromJavaVersion().classpath("log4j"))
.javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "log4j-1.2"))
.build()
);
}

public static AddLogger addLog4j2Logger(J.ClassDeclaration scope, String loggerName) {
public static AddLogger addLog4j2Logger(J.ClassDeclaration scope, String loggerName, ExecutionContext ctx) {
return new AddLogger(scope, "org.apache.logging.log4j.Logger", "org.apache.logging.log4j.LogManager", loggerName, visitor ->
JavaTemplate
.builder("private static final Logger #{} = LogManager.getLogger(#{}.class);")
.contextSensitive()
.imports("org.apache.logging.log4j.Logger", "org.apache.logging.log4j.LogManager")
.javaParser(JavaParser.fromJavaVersion().classpath("log4j-api"))
.javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "log4j-api-2.23"))
.build()
);
}
Expand All @@ -115,11 +118,12 @@ public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, Ex
return cd;
}

//noinspection ComparatorMethodParameterNotUsed
Comparator<Statement> firstAfterEnumValueSet = (unused, o2) -> o2 instanceof J.EnumValueSet ? 1 : -1;
cd = template.apply(updateCursor(cd), cd.getBody().getCoordinates().addStatement(firstAfterEnumValueSet), loggerName, cd.getSimpleName());

// ensure the appropriate number of blank lines on next statement after new field
J.ClassDeclaration formatted = (J.ClassDeclaration) new AutoFormatVisitor<ExecutionContext>().visitNonNull(cd, ctx, getCursor().getParent());
J.ClassDeclaration formatted = (J.ClassDeclaration) new AutoFormatVisitor<ExecutionContext>().visitNonNull(cd, ctx, requireNonNull(getCursor().getParent()));
cd = cd.withBody(cd.getBody().withStatements(ListUtils.map(cd.getBody().getStatements(), (i, stat) -> {
if (i == 1) {
return stat.withPrefix(formatted.getBody().getStatements().get(i).getPrefix());
Expand Down
15 changes: 10 additions & 5 deletions src/main/java/org/openrewrite/java/logging/LoggingFramework.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.openrewrite.java.logging;

import org.openrewrite.ExecutionContext;
import org.openrewrite.internal.lang.Nullable;
import org.openrewrite.java.JavaParser;
import org.openrewrite.java.JavaTemplate;
Expand Down Expand Up @@ -47,32 +48,36 @@ public static LoggingFramework fromOption(@Nullable String option) {
return SLF4J;
}

public JavaTemplate getErrorTemplate(String message) {
public JavaTemplate getErrorTemplate(String message, ExecutionContext ctx) {
switch (this) {
case SLF4J:
return JavaTemplate
.builder("#{any(org.slf4j.Logger)}.error(" + message + ", #{any(java.lang.Throwable)})")
.contextSensitive()
.javaParser(JavaParser.fromJavaVersion().classpath("slf4j-api"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "slf4j-api-2.1"))
.build();
case Log4J1:
return JavaTemplate
.builder("#{any(org.apache.log4j.Category)}.error(" + message + ", #{any(java.lang.Throwable)})")
.contextSensitive()
.javaParser(JavaParser.fromJavaVersion().classpath("log4j"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "log4j-1.2"))
.build();

case Log4J2:
return JavaTemplate
.builder("#{any(org.apache.logging.log4j.Logger)}.error(" + message + ", #{any(java.lang.Throwable)})")
.contextSensitive()
.javaParser(JavaParser.fromJavaVersion().classpath("log4j-api"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "log4j-api-2.23"))
.build();
case COMMONS:
return JavaTemplate
.builder("#{any(org.apache.commons.logging.Log)}.error(" + message + ", #{any(java.lang.Throwable)})")
.contextSensitive()
.javaParser(JavaParser.fromJavaVersion().classpath("commons-logging"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "commons-logging-1.3"))
.build();
case JUL:
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,23 +81,23 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu
Set<J.VariableDeclarations> loggers = FindFieldsOfType.find(classCursor.getValue(), framework.getLoggerType());
if (!loggers.isEmpty()) {
J.Identifier logField = loggers.iterator().next().getVariables().get(0).getName();
m = replaceMethodInvocation(m, logField);
m = replaceMethodInvocation(m, logField, ctx);
} else if (annotationService.matches(classCursor, lombokLogAnnotationMatcher)) {
String fieldName = loggerName == null ? "log" : loggerName;
J.Identifier logField = new J.Identifier(Tree.randomId(), Space.SINGLE_SPACE, Markers.EMPTY, Collections.emptyList(), fieldName, null, null);
m = replaceMethodInvocation(m, logField);
m = replaceMethodInvocation(m, logField, ctx);
} else if (addLogger != null && addLogger) {
doAfterVisit(AddLogger.addLogger(classCursor.getValue(), framework, loggerName == null ? "logger" : loggerName));
doAfterVisit(AddLogger.addLogger(classCursor.getValue(), framework, loggerName == null ? "logger" : loggerName, ctx));
}
}
return m;
}

private J.MethodInvocation replaceMethodInvocation(J.MethodInvocation m, J.Identifier logField) {
private J.MethodInvocation replaceMethodInvocation(J.MethodInvocation m, J.Identifier logField, ExecutionContext ctx) {
if (framework == LoggingFramework.JUL) {
maybeAddImport("java.util.logging.Level");
}
return framework.getErrorTemplate("\"Exception\"").apply(
return framework.getErrorTemplate("\"Exception\"", ctx).apply(
new Cursor(getCursor().getParent(), m),
m.getCoordinates().replace(),
logField,
Expand Down
17 changes: 10 additions & 7 deletions src/main/java/org/openrewrite/java/logging/SystemErrToLogging.java
Original file line number Diff line number Diff line change
Expand Up @@ -144,21 +144,21 @@ private J.MethodInvocation logInsteadOfPrint(Cursor printCursor, ExecutionContex
J.Identifier logField = new J.Identifier(Tree.randomId(), Space.SINGLE_SPACE, Markers.EMPTY, Collections.emptyList(), fieldName, null, null);
print = replaceMethodInvocation(printCursor, ctx, exceptionPrintStackTrace, print, logField);
} else if (addLogger != null && addLogger) {
doAfterVisit(AddLogger.addLogger(classCursor.getValue(), framework, loggerName == null ? "logger" : loggerName));
doAfterVisit(AddLogger.addLogger(classCursor.getValue(), framework, loggerName == null ? "logger" : loggerName, ctx));
}
return print;
}

private J.MethodInvocation replaceMethodInvocation(Cursor printCursor, ExecutionContext ctx, @Nullable Expression exceptionPrintStackTrace, J.MethodInvocation print, J.Identifier computedLoggerName) {
if (exceptionPrintStackTrace == null) {
print = getErrorTemplateNoException()
print = getErrorTemplateNoException(ctx)
.apply(
printCursor,
print.getCoordinates().replace(),
computedLoggerName,
print.getArguments().get(0));
} else {
print = framework.getErrorTemplate("#{any(String)}")
print = framework.getErrorTemplate("#{any(String)}", ctx)
.apply(
printCursor,
print.getCoordinates().replace(),
Expand All @@ -176,26 +176,29 @@ private J.MethodInvocation replaceMethodInvocation(Cursor printCursor, Execution
.visitNonNull(print, ctx, printCursor);
}

public JavaTemplate getErrorTemplateNoException() {
public JavaTemplate getErrorTemplateNoException(ExecutionContext ctx) {
switch (framework) {
case SLF4J:
return JavaTemplate
.builder("#{any(org.slf4j.Logger)}.error(#{any(String)})")
.contextSensitive()
.javaParser(JavaParser.fromJavaVersion().classpath("slf4j-api"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "slf4j-api-2.1"))
.build();
case Log4J1:
return JavaTemplate
.builder("#{any(org.apache.log4j.Category)}.error(#{any(String)})")
.contextSensitive()
.javaParser(JavaParser.fromJavaVersion().classpath("log4j"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "log4j-1.2"))
.build();

case Log4J2:
return JavaTemplate
.builder("#{any(org.apache.logging.log4j.Logger)}.error(#{any(String)})")
.contextSensitive()
.javaParser(JavaParser.fromJavaVersion().classpath("log4j-api"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "log4j-api-2.23"))
.build();
case JUL:
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ private J.MethodInvocation logInsteadOfPrint(Cursor printCursor, ExecutionContex
J.Identifier logField = new J.Identifier(Tree.randomId(), Space.SINGLE_SPACE, Markers.EMPTY, Collections.emptyList(), fieldName, null, null);
print = replaceMethodInvocation(printCursor, ctx, print, logField);
} else if (addLogger != null && addLogger) {
doAfterVisit(AddLogger.addLogger(classCursor.getValue(), framework, loggerName == null ? "logger" : loggerName));
doAfterVisit(AddLogger.addLogger(classCursor.getValue(), framework, loggerName == null ? "logger" : loggerName, ctx));
}
return print;
}

private J.MethodInvocation replaceMethodInvocation(Cursor printCursor, ExecutionContext ctx, J.MethodInvocation print, J.Identifier computedLoggerName) {
print = getInfoTemplate().apply(
print = getInfoTemplate(ctx).apply(
printCursor,
print.getCoordinates().replace(),
computedLoggerName,
Expand All @@ -127,24 +127,27 @@ private J.MethodInvocation replaceMethodInvocation(Cursor printCursor, Execution
return print;
}

private JavaTemplate getInfoTemplate() {
private JavaTemplate getInfoTemplate(ExecutionContext ctx) {
String levelOrDefault = getLevel();
switch (framework) {
case SLF4J:
return JavaTemplate
.builder("#{any(org.slf4j.Logger)}." + levelOrDefault + "(#{any(String)})")
.javaParser(JavaParser.fromJavaVersion().classpath("slf4j-api"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "slf4j-api-2.1"))
.build();
case Log4J1:
return JavaTemplate
.builder("#{any(org.apache.log4j.Category)}." + levelOrDefault + "(#{any(String)})")
.javaParser(JavaParser.fromJavaVersion().classpath("log4j"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "log4j-1.2"))
.build();

case Log4J2:
return JavaTemplate
.builder("#{any(org.apache.logging.log4j.Logger)}." + levelOrDefault + "(#{any(String)})")
.javaParser(JavaParser.fromJavaVersion().classpath("log4j-api"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "log4j-api-2.23"))
.build();
case JUL:
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.openrewrite.Recipe;
import org.openrewrite.internal.lang.Nullable;

import java.time.Duration;
import java.util.Arrays;
import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, Execu
return JavaTemplate.builder("LoggerFactory.getLogger(#{})")
.contextSensitive()
.imports("org.slf4j.LoggerFactory")
.javaParser(JavaParser.fromJavaVersion().classpath("slf4j-api"))
.javaParser(JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "slf4j-api-2.1"))
.build()
.apply(new Cursor(getCursor().getParent(), mi), mi.getCoordinates().replace(), enclosingClazzName);
}
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit f5c66f7

Please sign in to comment.