diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/AddPluginRepository.java b/rewrite-maven/src/main/java/org/openrewrite/maven/AddPluginRepository.java deleted file mode 100644 index 1a861e51f7c..00000000000 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/AddPluginRepository.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright 2022 the original author or authors. - *

- * Licensed 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 - *

- * https://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.openrewrite.maven; - -import lombok.EqualsAndHashCode; -import lombok.Value; -import org.intellij.lang.annotations.Language; -import org.openrewrite.ExecutionContext; -import org.openrewrite.Option; -import org.openrewrite.Recipe; -import org.openrewrite.TreeVisitor; -import org.openrewrite.internal.lang.Nullable; -import org.openrewrite.xml.AddToTagVisitor; -import org.openrewrite.xml.ChangeTagValueVisitor; -import org.openrewrite.xml.RemoveContentVisitor; -import org.openrewrite.xml.XPathMatcher; -import org.openrewrite.xml.tree.Xml; - -import java.util.Objects; -import java.util.Optional; - -@Value -@EqualsAndHashCode(callSuper = false) -public class AddPluginRepository extends Recipe { - private static final XPathMatcher PLUGIN_REPOS_MATCHER = new XPathMatcher("/project/pluginRepositories"); - - @Option(example = "repo-id", displayName = "Plugin repository ID", - description = "A unique name to describe the plugin repository.") - String id; - - @Option(example = "http://myrepo.maven.com/repo", displayName = "Plugin repository URL", - description = "The URL of the plugin repository.") - String url; - - @Option(example = "My Great Repo Name", required = false, - displayName = "Plugin repository name", - description = "A display name for the plugin repository.") - @Nullable - String pluginRepoName; - - @Option(example = "default", required = false, - displayName = "Plugin repository layout", - description = "The Maven layout of the plugin repository.") - @Nullable - String layout; - - @Option(required = false, - displayName = "Enable snapshots", - description = "Snapshots from the plugin repository are available.") - @Nullable - Boolean snapshotsEnabled; - - @Option(example = "warn", required = false, - displayName = "Snapshots checksum policy", - description = "Governs whether snapshots require checksums.") - @Nullable - String snapshotsChecksumPolicy; - - @Option(example = "always", required = false, - displayName = "Snapshots update policy", - description = "The policy governing snapshot updating interval.") - @Nullable - String snapshotsUpdatePolicy; - - @Option(required = false, - displayName = "Releases enabled", - description = "Releases from the plugin repository are available") - @Nullable - Boolean releasesEnabled; - - @Option(example = "fail", required = false, - displayName = "Releases checksum policy", - description = "Governs whether releases require checksums.") - @Nullable - String releasesChecksumPolicy; - - @Option(example = "never", required = false, - displayName = "Releases update policy", - description = "The policy governing release updating interval.") - @Nullable - String releasesUpdatePolicy; - - @Override - public String getDisplayName() { - return "Add plugin repository"; - } - - @Override - public String getDescription() { - return "Adds a new Maven Plugin Repository or updates a matching plugin repository."; - } - - @Override - public TreeVisitor getVisitor() { - return new MavenIsoVisitor() { - @Override - public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) { - Xml.Tag root = document.getRoot(); - if (!root.getChild("pluginRepositories").isPresent()) { - document = (Xml.Document) new AddToTagVisitor<>(root, Xml.Tag.build("")) - .visitNonNull(document, ctx, getCursor().getParentOrThrow()); - } - return super.visitDocument(document, ctx); - } - - @Override - public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { - Xml.Tag pluginRepositories = super.visitTag(tag, ctx); - - if (PLUGIN_REPOS_MATCHER.matches(getCursor())) { - Optional maybePluginRepo = pluginRepositories.getChildren().stream() - .filter(pluginRepo -> - "pluginRepository".equals(pluginRepo.getName()) - && (id.equals(pluginRepo.getChildValue("id").orElse(null)) || (isReleasesEqual(pluginRepo) && isSnapshotsEqual(pluginRepo))) - && url.equals(pluginRepo.getChildValue("url").orElse(null)) - ) - .findAny(); - - if (maybePluginRepo.isPresent()) { - Xml.Tag pluginRepo = maybePluginRepo.get(); - if (pluginRepoName != null && !Objects.equals(pluginRepoName, pluginRepo.getChildValue("name").orElse(null))) { - //noinspection OptionalGetWithoutIsPresent - pluginRepositories = (Xml.Tag) new ChangeTagValueVisitor<>(pluginRepo.getChild("name").get(), pluginRepoName) - .visitNonNull(pluginRepositories, ctx, getCursor().getParentOrThrow()); - } - if (pluginRepoName != null && layout != null && !Objects.equals(layout, pluginRepo.getChildValue("layout").orElse(null))) { - //noinspection OptionalGetWithoutIsPresent - pluginRepositories = (Xml.Tag) new ChangeTagValueVisitor<>(pluginRepo.getChild("layout").get(), pluginRepoName) - .visitNonNull(pluginRepositories, ctx, getCursor().getParentOrThrow()); - maybeUpdateModel(); - } - if (!isReleasesEqual(pluginRepo)) { - Xml.Tag releases = pluginRepo.getChild("releases").orElse(null); - if (releases == null) { - pluginRepositories = (Xml.Tag) new AddToTagVisitor<>(pluginRepo, Xml.Tag.build(assembleReleases())) - .visitNonNull(pluginRepositories, ctx, getCursor().getParentOrThrow()); - } else { - pluginRepositories = (Xml.Tag) new RemoveContentVisitor<>(releases, true) - .visitNonNull(pluginRepositories, ctx, getCursor().getParentOrThrow()); - if (!isNoSnapshots()) { - pluginRepositories = (Xml.Tag) new AddToTagVisitor<>(pluginRepo, Xml.Tag.build(assembleReleases())) - .visitNonNull(pluginRepositories, ctx, getCursor().getParentOrThrow()); - } - } - maybeUpdateModel(); - } - if (!isSnapshotsEqual(pluginRepo)) { - Xml.Tag snapshots = pluginRepo.getChild("snapshots").orElse(null); - if (snapshots == null) { - pluginRepositories = (Xml.Tag) new AddToTagVisitor<>(pluginRepo, Xml.Tag.build(assembleSnapshots())).visitNonNull(pluginRepositories, ctx, getCursor().getParentOrThrow()); - } else { - pluginRepositories = (Xml.Tag) new RemoveContentVisitor<>(snapshots, true).visitNonNull(pluginRepositories, ctx, getCursor().getParentOrThrow()); - if (!isNoSnapshots()) { - pluginRepositories = (Xml.Tag) new AddToTagVisitor<>(pluginRepo, Xml.Tag.build(assembleSnapshots())).visitNonNull(pluginRepositories, ctx, getCursor().getParentOrThrow()); - } - } - maybeUpdateModel(); - } - } else { - @Language("xml") - String sb = "\n" + - assembleTagWithValue("id", id) + - assembleTagWithValue("url", url) + - assembleTagWithValue("name", pluginRepoName) + - assembleTagWithValue("layout", layout) + - assembleReleases() + - assembleSnapshots() + - "\n"; - - Xml.Tag pluginRepoTag = Xml.Tag.build(sb); - pluginRepositories = (Xml.Tag) new AddToTagVisitor<>(pluginRepositories, pluginRepoTag).visitNonNull(pluginRepositories, ctx, getCursor().getParentOrThrow()); - maybeUpdateModel(); - } - } - return pluginRepositories; - } - }; - } - - private String assembleTagWithValue(String tag, @Nullable String value) { - StringBuilder sb = new StringBuilder(); - if (value != null) { - sb.append("<"); - sb.append(tag); - sb.append(">"); - sb.append(value); - sb.append("\n"); - } - return sb.toString(); - } - - private String assembleReleases() { - StringBuilder sb = new StringBuilder(); - if (releasesUpdatePolicy != null || releasesEnabled != null || releasesChecksumPolicy != null) { - sb.append(""); - if (releasesEnabled != null) { - sb.append(assembleTagWithValue("enabled", String.valueOf(releasesEnabled.booleanValue()))); - } - if (releasesUpdatePolicy != null) { - sb.append(assembleTagWithValue("updatePolicy", releasesUpdatePolicy)); - } - if (releasesChecksumPolicy != null) { - sb.append(assembleTagWithValue("checksumPolicy", releasesChecksumPolicy)); - } - sb.append("\n"); - } - return sb.toString(); - } - - private String assembleSnapshots() { - StringBuilder sb = new StringBuilder(); - if (snapshotsEnabled != null || snapshotsChecksumPolicy != null || snapshotsUpdatePolicy != null) { - sb.append(""); - if (snapshotsEnabled != null) { - sb.append(assembleTagWithValue("enabled", String.valueOf(snapshotsEnabled.booleanValue()))); - } - if (snapshotsUpdatePolicy != null) { - sb.append(assembleTagWithValue("updatePolicy", snapshotsUpdatePolicy)); - } - if (snapshotsChecksumPolicy != null) { - sb.append(assembleTagWithValue("checksumPolicy", snapshotsChecksumPolicy)); - } - sb.append("\n"); - } - return sb.toString(); - } - - private boolean isReleasesEqual(Xml.Tag pluginRepo) { - Xml.Tag releases = pluginRepo.getChild("releases").orElse(null); - if (releases == null) { - return isNoReleases(); - } else { - return Objects.equals(releasesEnabled == null ? null : String.valueOf(releasesEnabled.booleanValue()), releases.getChildValue("enabled").orElse(null)) - && Objects.equals(releasesUpdatePolicy, releases.getChildValue("updatePolicy").orElse(null)) - && Objects.equals(releasesChecksumPolicy, releases.getChildValue("checksumPolicy").orElse(null)); - } - } - - private boolean isNoReleases() { - return releasesEnabled == null && releasesUpdatePolicy == null && releasesChecksumPolicy == null; - } - - private boolean isSnapshotsEqual(Xml.Tag pluginRepo) { - Xml.Tag snapshots = pluginRepo.getChild("snapshots").orElse(null); - if (snapshots == null) { - return isNoSnapshots(); - } else { - return Objects.equals(snapshotsEnabled == null ? null : String.valueOf(snapshotsEnabled.booleanValue()), snapshots.getChildValue("enabled").orElse(null)) - && Objects.equals(snapshotsUpdatePolicy, snapshots.getChildValue("updatePolicy").orElse(null)) - && Objects.equals(snapshotsChecksumPolicy, snapshots.getChildValue("checksumPolicy").orElse(null)); - } - } - - private boolean isNoSnapshots() { - return snapshotsEnabled == null && snapshotsUpdatePolicy == null && snapshotsChecksumPolicy == null; - } - -} diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/AddRepository.java b/rewrite-maven/src/main/java/org/openrewrite/maven/AddRepository.java index 79a4e29ac42..50c7537780e 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/AddRepository.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/AddRepository.java @@ -16,6 +16,7 @@ package org.openrewrite.maven; import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; import lombok.Value; import org.intellij.lang.annotations.Language; import org.openrewrite.ExecutionContext; @@ -35,7 +36,6 @@ @Value @EqualsAndHashCode(callSuper = false) public class AddRepository extends Recipe { - private static final XPathMatcher REPOS_MATCHER = new XPathMatcher("/project/repositories"); @Option(example = "repo-id", displayName = "Repository ID", description = "A unique name to describe the repository.") @@ -93,6 +93,20 @@ public class AddRepository extends Recipe { @Nullable String releasesUpdatePolicy; + @Option(displayName = "Repository type", + description = "The type of repository to add.", + example = "Repository") + Type type; + + @RequiredArgsConstructor + public enum Type { + Repository("repository", "repositories"), + PluginRepository("pluginRepository", "pluginRepositories"); + + final String xmlTagSingle; + final String xmlTagPlural; + } + @Override public String getDisplayName() { return "Add repository"; @@ -106,11 +120,13 @@ public String getDescription() { @Override public TreeVisitor getVisitor() { return new MavenIsoVisitor() { + private final XPathMatcher REPOS_MATCHER = new XPathMatcher("/project/" + type.xmlTagPlural); + @Override public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) { Xml.Tag root = document.getRoot(); - if (!root.getChild("repositories").isPresent()) { - document = (Xml.Document) new AddToTagVisitor<>(root, Xml.Tag.build("")) + if (!root.getChild(type.xmlTagPlural).isPresent()) { + document = (Xml.Document) new AddToTagVisitor<>(root, Xml.Tag.build("<" + type.xmlTagPlural + "/>")) .visitNonNull(document, ctx, getCursor().getParentOrThrow()); } return super.visitDocument(document, ctx); @@ -123,7 +139,7 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { if (REPOS_MATCHER.matches(getCursor())) { Optional maybeRepo = repositories.getChildren().stream() .filter(repo -> - "repository".equals(repo.getName()) && + type.xmlTagSingle.equals(repo.getName()) && (id.equals(repo.getChildValue("id").orElse(null)) || (isReleasesEqual(repo) && isSnapshotsEqual(repo))) && url.equals(repo.getChildValue("url").orElse(null)) ) @@ -171,14 +187,14 @@ public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { } } else { @Language("xml") - String sb = "\n" + + String sb = "<" + type.xmlTagSingle + ">\n" + assembleTagWithValue("id", id) + assembleTagWithValue("url", url) + assembleTagWithValue("name", repoName) + assembleTagWithValue("layout", layout) + assembleReleases() + assembleSnapshots() + - "\n"; + "\n"; Xml.Tag repoTag = Xml.Tag.build(sb); repositories = (Xml.Tag) new AddToTagVisitor<>(repositories, repoTag).visitNonNull(repositories, ctx, getCursor().getParentOrThrow()); diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/AddPluginRepositoryTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/AddPluginRepositoryTest.java deleted file mode 100644 index bfb33b2ca58..00000000000 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/AddPluginRepositoryTest.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2022 the original author or authors. - *

- * Licensed 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 - *

- * https://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.openrewrite.maven; - -import org.junit.jupiter.api.Test; -import org.openrewrite.DocumentExample; -import org.openrewrite.test.RewriteTest; - -import static org.openrewrite.maven.Assertions.pomXml; - -class AddPluginRepositoryTest implements RewriteTest { - - @DocumentExample - @Test - void addSimpleRepo() { - rewriteRun( - spec -> spec.recipe(new AddPluginRepository("myRepo", "http://myrepo.maven.com/repo", null, null, - null, null, null, - null, null, null)), - pomXml( - """ - - com.mycompany.app - my-app - 1 - - """, - """ - - com.mycompany.app - my-app - 1 - - - myRepo - http://myrepo.maven.com/repo - - - - """ - ) - ); - } - - @Test - void updateExistingRepo() { - rewriteRun( - spec -> spec.recipe(new AddPluginRepository("myRepo", "http://myrepo.maven.com/repo", "bb", null, - null, null, null, - null, null, null)), - pomXml( - """ - - com.mycompany.app - my-app - 1 - - - myRepo - http://myrepo.maven.com/repo - qq - - - - """, - """ - - com.mycompany.app - my-app - 1 - - - myRepo - http://myrepo.maven.com/repo - bb - - - - """ - ) - ); - } - - @Test - void doNotRemoveRepoName() { - rewriteRun( - spec -> spec.recipe(new AddPluginRepository("myRepo", "http://myrepo.maven.com/repo", null, null, - null, null, null, - null, null, null)), - pomXml( - """ - - com.mycompany.app - my-app - 1 - - - myRepo - http://myrepo.maven.com/repo - qq - - - - """ - ) - ); - } - - @Test - void removeSnapshots() { - rewriteRun( - spec -> spec.recipe(new AddPluginRepository("myRepo", "http://myrepo.maven.com/repo", null, null, - null, null, null, - null, null, null)), - pomXml( - """ - - com.mycompany.app - my-app - 1 - - - myRepo - http://myrepo.maven.com/repo - - true - - - - - """, - """ - - com.mycompany.app - my-app - 1 - - - myRepo - http://myrepo.maven.com/repo - - - - """ - ) - ); - } - - @Test - void updateSnapshots1() { - rewriteRun( - spec -> spec.recipe(new AddPluginRepository("myRepo", "http://myrepo.maven.com/repo", null, null, - false, "whatever", null, - null, null, null)), - pomXml( - """ - - com.mycompany.app - my-app - 1 - - - myRepo - http://myrepo.maven.com/repo - - true - - - - - """, - """ - - com.mycompany.app - my-app - 1 - - - myRepo - http://myrepo.maven.com/repo - - false - whatever - - - - - """ - ) - ); - } - - @Test - void updateSnapshots2() { - rewriteRun( - spec -> spec.recipe(new AddPluginRepository("myRepo", "http://myrepo.maven.com/repo", null, null, - null, "whatever", null, - null, null, null)), - pomXml( - """ - - com.mycompany.app - my-app - 1 - - - myRepo - http://myrepo.maven.com/repo - - true - - - - - """, - """ - - com.mycompany.app - my-app - 1 - - - myRepo - http://myrepo.maven.com/repo - - whatever - - - - - """ - ) - ); - } - - @Test - void noIdMatch1SameSnapshots() { - rewriteRun( - spec -> spec.recipe(new AddPluginRepository("myRepo", "http://myrepo.maven.com/repo", null, null, - true, null, null, - null, null, null)), - pomXml( - """ - - com.mycompany.app - my-app - 1 - - - myRepo-X - http://myrepo.maven.com/repo - - true - - - - - """ - ) - ); - } -} diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/AddRepositoryTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/AddRepositoryTest.java index 90b3da09f22..c9b1beeed3f 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/AddRepositoryTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/AddRepositoryTest.java @@ -29,7 +29,7 @@ void addSimpleRepo() { rewriteRun( spec -> spec.recipe(new AddRepository("myRepo", "http://myrepo.maven.com/repo", null, null, null, null, null, - null, null, null)), + null, null, null, AddRepository.Type.Repository)), pomXml( """ @@ -55,12 +55,43 @@ void addSimpleRepo() { ); } + @Test + void addSimplePluginRepo() { + rewriteRun( + spec -> spec.recipe(new AddRepository("myRepo", "http://myrepo.maven.com/repo", null, null, + null, null, null, + null, null, null, AddRepository.Type.PluginRepository)), + pomXml( + """ + + com.mycompany.app + my-app + 1 + + """, + """ + + com.mycompany.app + my-app + 1 + + + myRepo + http://myrepo.maven.com/repo + + + + """ + ) + ); + } + @Test void updateExistingRepo() { rewriteRun( spec -> spec.recipe(new AddRepository("myRepo", "http://myrepo.maven.com/repo", "bb", null, null, null, null, - null, null, null)), + null, null, null, AddRepository.Type.Repository)), pomXml( """ @@ -99,7 +130,7 @@ void doNotRemoveRepoName() { rewriteRun( spec -> spec.recipe(new AddRepository("myRepo", "http://myrepo.maven.com/repo", null, null, null, null, null, - null, null, null)), + null, null, null, AddRepository.Type.Repository)), pomXml( """ @@ -124,7 +155,7 @@ void removeSnapshots() { rewriteRun( spec -> spec.recipe(new AddRepository("myRepo", "http://myrepo.maven.com/repo", null, null, null, null, null, - null, null, null)), + null, null, null, AddRepository.Type.Repository)), pomXml( """ @@ -164,7 +195,7 @@ void updateSnapshots1() { rewriteRun( spec -> spec.recipe(new AddRepository("myRepo", "http://myrepo.maven.com/repo", null, null, false, "whatever", null, - null, null, null)), + null, null, null, AddRepository.Type.Repository)), pomXml( """ @@ -208,7 +239,7 @@ void updateSnapshots2() { rewriteRun( spec -> spec.recipe(new AddRepository("myRepo", "http://myrepo.maven.com/repo", null, null, null, "whatever", null, - null, null, null)), + null, null, null, AddRepository.Type.Repository)), pomXml( """ @@ -251,7 +282,7 @@ void noIdMatch1SameSnapshots() { rewriteRun( spec -> spec.recipe(new AddRepository("myRepo", "http://myrepo.maven.com/repo", null, null, true, null, null, - null, null, null)), + null, null, null, AddRepository.Type.Repository)), pomXml( """ @@ -280,7 +311,7 @@ void updateToSpringBoot30Snapshot() { spec -> spec.recipes( new AddRepository("boot-snapshots", "https://repo.spring.io/snapshot", null, null, true, null, null, - null, null, null), + null, null, null, AddRepository.Type.Repository), new UpgradeParentVersion("org.springframework.boot", "spring-boot-starter-parent", "3.0.0-SNAPSHOT", null) ), pomXml(