diff --git a/plugin-modernizer-core/pom.xml b/plugin-modernizer-core/pom.xml
index a2135268f..52277a884 100644
--- a/plugin-modernizer-core/pom.xml
+++ b/plugin-modernizer-core/pom.xml
@@ -282,6 +282,11 @@
ssh-slaves
3.1021.va_cc11b_de26a_e
+
+ org.jenkins-ci.main
+ jenkins-core
+ 2.497
+
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateAcegiSecurityToSpringSecurity.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateAcegiSecurityToSpringSecurity.java
new file mode 100644
index 000000000..aee7d929c
--- /dev/null
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateAcegiSecurityToSpringSecurity.java
@@ -0,0 +1,153 @@
+package io.jenkins.tools.pluginmodernizer.core.recipes;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.ChangeMethodName;
+import org.openrewrite.java.ChangePackage;
+import org.openrewrite.java.ChangeType;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.tree.J;
+import org.openrewrite.java.tree.JLeftPadded;
+import org.openrewrite.java.tree.Space;
+import org.openrewrite.marker.Markers;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MigrateAcegiSecurityToSpringSecurity extends Recipe {
+ /**
+ * Logger
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(MigrateAcegiSecurityToSpringSecurity.class);
+
+ @Override
+ public String getDisplayName() {
+ return "Migrate Acegi Security to Spring Security";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Migrate acegi security to spring security.";
+ }
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return new JavaIsoVisitor<>() {
+ @Override
+ public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu, ExecutionContext ctx) {
+ // ChangePackage will take care for the most of the migration so don't need to add separate migrations
+ // For those import statements that ChangePackage will not account correctly, add separate logic
+ cu = (J.CompilationUnit)
+ new ChangePackage("org.acegisecurity", "org.springframework.security.core", false)
+ .getVisitor()
+ .visitNonNull(cu, ctx);
+
+ cu = (J.CompilationUnit) new ChangeType(
+ "org.springframework.security.core.GrantedAuthorityImpl",
+ "org.springframework.security.core.authority.SimpleGrantedAuthority",
+ null)
+ .getVisitor()
+ .visitNonNull(cu, ctx);
+
+ // Authentication classes
+ cu = (J.CompilationUnit) new ChangeType(
+ "org.acegisecurity.providers.AbstractAuthenticationToken",
+ "org.springframework.security.authentication.AbstractAuthenticationToken",
+ null)
+ .getVisitor()
+ .visitNonNull(cu, ctx);
+
+ List originalImports = cu.getImports();
+
+ cu = (J.CompilationUnit) new ChangeType(
+ "org.springframework.security.core.AuthenticationManager",
+ " org.springframework.security.authentication.AuthenticationManager",
+ null)
+ .getVisitor()
+ .visitNonNull(cu, ctx);
+ if (!cu.getImports().equals(originalImports)) {
+ cu = addImportIfNotExists(
+ cu, "AuthenticationManager", "org.springframework.security.authentication");
+ }
+ originalImports = cu.getImports();
+ cu = (J.CompilationUnit) new ChangeType(
+ "org.springframework.security.core.BadCredentialsException",
+ "org.springframework.security.authentication.BadCredentialsException",
+ null)
+ .getVisitor()
+ .visitNonNull(cu, ctx);
+
+ if (!cu.getImports().equals(originalImports)) {
+ cu = addImportIfNotExists(
+ cu, "BadCredentialsException", "org.springframework.security.authentication");
+ }
+
+ return super.visitCompilationUnit(cu, ctx);
+ }
+
+ @Override
+ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
+ method = (J.MethodInvocation) new ChangeMethodName(
+ "jenkins.model.Jenkins getAuthentication()", "getAuthentication2", null, null)
+ .getVisitor()
+ .visitNonNull(method, ctx);
+ // Migrate fireAuthenticated to fireAuthenticated2
+ if (method.getSimpleName().equals("fireAuthenticated")) {
+ method = method.withName(method.getName().withSimpleName("fireAuthenticated2"));
+ }
+ return super.visitMethodInvocation(method, ctx);
+ }
+
+ private J.CompilationUnit addImportIfNotExists(J.CompilationUnit cu, String className, String packageName) {
+ boolean importExists = cu.getImports().stream().anyMatch(anImport -> (packageName + "." + className)
+ .equals(anImport.getQualid().toString()));
+ if (!importExists) {
+ J.Identifier identifier = new J.Identifier(
+ UUID.randomUUID(),
+ Space.EMPTY,
+ Markers.EMPTY,
+ Collections.emptyList(),
+ className,
+ null,
+ null);
+
+ J.Identifier packageIdentifier = new J.Identifier(
+ UUID.randomUUID(),
+ Space.SINGLE_SPACE,
+ Markers.EMPTY,
+ Collections.emptyList(),
+ packageName,
+ null,
+ null);
+
+ J.FieldAccess fieldAccess = new J.FieldAccess(
+ UUID.randomUUID(),
+ Space.EMPTY,
+ Markers.EMPTY,
+ packageIdentifier,
+ JLeftPadded.build(identifier),
+ null);
+
+ J.Import newImport = new J.Import(
+ UUID.randomUUID(),
+ Space.format("\n"), // Ensure the import appears on a new line
+ Markers.EMPTY,
+ JLeftPadded.build(false), // static: false
+ fieldAccess,
+ null);
+
+ List modifiedImports = new ArrayList<>(cu.getImports());
+ modifiedImports.add(newImport);
+
+ return cu.withImports(modifiedImports);
+ }
+
+ return cu;
+ }
+ };
+ }
+}
diff --git a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateStaplerAndJavaxToJakarta.java b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateStaplerAndJavaxToJakarta.java
index b992e7a76..01dd259ca 100644
--- a/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateStaplerAndJavaxToJakarta.java
+++ b/plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateStaplerAndJavaxToJakarta.java
@@ -65,7 +65,7 @@ public TreeVisitor, ExecutionContext> getVisitor(Set acc) {
@Override
public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu, ExecutionContext ctx) {
if (acc.isEmpty()) {
- cu = (J.CompilationUnit) new ChangePackage("javax.servlet", "jakarta.servlet", false)
+ cu = (J.CompilationUnit) new ChangePackage("javax.servlet", "jakarta.servlet", true)
.getVisitor()
.visitNonNull(cu, ctx);
}
diff --git a/plugin-modernizer-core/src/main/resources/META-INF/rewrite/recipes.yml b/plugin-modernizer-core/src/main/resources/META-INF/rewrite/recipes.yml
index 5ee2d58e7..d29dc747f 100644
--- a/plugin-modernizer-core/src/main/resources/META-INF/rewrite/recipes.yml
+++ b/plugin-modernizer-core/src/main/resources/META-INF/rewrite/recipes.yml
@@ -153,6 +153,7 @@ recipeList:
- io.jenkins.tools.pluginmodernizer.core.recipes.UpgradeJenkinsTestHarnessVersion:
jenkinsVersion: 2.479.1
- io.jenkins.tools.pluginmodernizer.core.recipes.MigrateStaplerAndJavaxToJakarta
+ - io.jenkins.tools.pluginmodernizer.core.recipes.MigrateAcegiSecurityToSpringSecurity
- io.jenkins.tools.pluginmodernizer.RemoveDevelopersTag
- io.jenkins.tools.pluginmodernizer.RemoveDependencyVersionOverride
- io.jenkins.tools.pluginmodernizer.RemoveExtraMavenProperties
diff --git a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/DeclarativeRecipesTest.java b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/DeclarativeRecipesTest.java
index c51d4d6a9..949aff2cf 100644
--- a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/DeclarativeRecipesTest.java
+++ b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/DeclarativeRecipesTest.java
@@ -1852,11 +1852,25 @@ void upgradeNextMajorParentVersionTest() {
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
+ import org.acegisecurity.Authentication;
+ import org.acegisecurity.GrantedAuthority;
+ import org.acegisecurity.GrantedAuthorityImpl;
+ import org.acegisecurity.providers.AbstractAuthenticationToken;
+ import org.acegisecurity.context.SecurityContextHolder;
+ import org.acegisecurity.AuthenticationException;
+ import org.acegisecurity.AuthenticationManager;
+ import org.acegisecurity.BadCredentialsException;
+ import org.acegisecurity.userdetails.UserDetails;
+ import org.acegisecurity.userdetails.UserDetailsService;
+ import org.acegisecurity.userdetails.UsernameNotFoundException;
+ import jenkins.model.Jenkins;
+ import jenkins.security.SecurityListener;
public class Foo {
public void foo() {
StaplerRequest req = Stapler.getCurrentRequest();
StaplerResponse response = Stapler.getCurrentResponse();
+ Authentication auth = Jenkins.getAuthentication();
}
}
""",
@@ -1865,11 +1879,24 @@ public void foo() {
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest2;
import org.kohsuke.stapler.StaplerResponse2;
+ import org.springframework.security.core.Authentication;
+ import org.springframework.security.core.GrantedAuthority;
+ import org.springframework.security.authentication.AbstractAuthenticationToken;
+ import org.springframework.security.core.context.SecurityContextHolder;
+ import org.springframework.security.core.AuthenticationException;
+ import org.springframework.security.core.userdetails.UserDetails;
+ import org.springframework.security.core.userdetails.UserDetailsService;
+ import org.springframework.security.core.userdetails.UsernameNotFoundException;
+ import jenkins.model.Jenkins;
+ import jenkins.security.SecurityListener;
+ import org.springframework.security.authentication.AuthenticationManager;
+ import org.springframework.security.authentication.BadCredentialsException;
public class Foo {
public void foo() {
StaplerRequest2 req = Stapler.getCurrentRequest2();
StaplerResponse2 response = Stapler.getCurrentResponse2();
+ Authentication auth = Jenkins.getAuthentication2();
}
}
""")));
diff --git a/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateAcegiSecurityToSpringSecurityTest.java b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateAcegiSecurityToSpringSecurityTest.java
new file mode 100644
index 000000000..a55040d99
--- /dev/null
+++ b/plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/MigrateAcegiSecurityToSpringSecurityTest.java
@@ -0,0 +1,152 @@
+package io.jenkins.tools.pluginmodernizer.core.recipes;
+
+import static io.jenkins.tools.pluginmodernizer.core.recipes.DeclarativeRecipesTest.collectRewriteTestDependencies;
+import static org.openrewrite.java.Assertions.java;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.parallel.Execution;
+import org.junit.jupiter.api.parallel.ExecutionMode;
+import org.openrewrite.java.JavaParser;
+import org.openrewrite.test.RewriteTest;
+
+/**
+ * Test for {@link MigrateAcegiSecurityToSpringSecurity}.
+ */
+@Execution(ExecutionMode.CONCURRENT)
+public class MigrateAcegiSecurityToSpringSecurityTest implements RewriteTest {
+
+ @Test
+ void migrateAcegiToSpringSecurity() {
+ rewriteRun(
+ spec -> {
+ var parser = JavaParser.fromJavaVersion().logCompilationWarningsAndErrors(true);
+ collectRewriteTestDependencies().forEach(parser::addClasspathEntry);
+ spec.recipe(new MigrateAcegiSecurityToSpringSecurity()).parser(parser);
+ },
+ java(
+ """
+ import org.acegisecurity.Authentication;
+ import org.acegisecurity.GrantedAuthority;
+ import org.acegisecurity.GrantedAuthorityImpl;
+ import org.acegisecurity.providers.AbstractAuthenticationToken;
+ import org.acegisecurity.context.SecurityContextHolder;
+ import org.acegisecurity.AuthenticationException;
+ import org.acegisecurity.AuthenticationManager;
+ import org.acegisecurity.BadCredentialsException;
+ import org.acegisecurity.userdetails.UserDetails;
+ import org.acegisecurity.userdetails.UserDetailsService;
+ import org.acegisecurity.userdetails.UsernameNotFoundException;
+ import jenkins.model.Jenkins;
+ import jenkins.security.SecurityListener;
+
+ public class Foo implements UserDetails {
+ @Override
+ public GrantedAuthority[] getAuthorities() {
+ return new GrantedAuthority[] {
+ new GrantedAuthorityImpl("ROLE_USER")
+ };
+ }
+
+ @Override
+ public String getPassword() {
+ return "password123";
+ }
+
+ @Override
+ public String getUsername() {
+ return "testUser";
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return true;
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+ public UserDetails loadUserByUsername(String username) {
+ return new Foo();
+ }
+ public void foo() {
+ Authentication auth = Jenkins.getAuthentication();
+ Foo userDetails = new Foo();
+ SecurityListener.fireAuthenticated(userDetails);
+ }
+ }
+ """,
+ """
+ import org.springframework.security.core.Authentication;
+ import org.springframework.security.core.GrantedAuthority;
+ import org.springframework.security.core.authority.SimpleGrantedAuthority;
+ import org.springframework.security.authentication.AbstractAuthenticationToken;
+ import org.springframework.security.core.context.SecurityContextHolder;
+ import org.springframework.security.core.AuthenticationException;
+ import org.springframework.security.core.userdetails.UserDetails;
+ import org.springframework.security.core.userdetails.UserDetailsService;
+ import org.springframework.security.core.userdetails.UsernameNotFoundException;
+ import jenkins.model.Jenkins;
+ import jenkins.security.SecurityListener;
+ import org.springframework.security.authentication.AuthenticationManager;
+ import org.springframework.security.authentication.BadCredentialsException;
+
+ public class Foo implements UserDetails {
+ @Override
+ public GrantedAuthority[] getAuthorities() {
+ return new GrantedAuthority[] {
+ new SimpleGrantedAuthority("ROLE_USER")
+ };
+ }
+
+ @Override
+ public String getPassword() {
+ return "password123";
+ }
+
+ @Override
+ public String getUsername() {
+ return "testUser";
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return true;
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+ public UserDetails loadUserByUsername(String username) {
+ return new Foo();
+ }
+ public void foo() {
+ Authentication auth = Jenkins.getAuthentication2();
+ Foo userDetails = new Foo();
+ SecurityListener.fireAuthenticated2(userDetails);
+ }
+ }
+ """));
+ }
+}