Skip to content

Commit 6418127

Browse files
authored
Merge pull request #101 from oracle/pabhat/jakarta-migrate-maven-plugin-config
Recipe to migrate artifactItem to Jakarta for the configuration of a maven plugin
2 parents 2fab05f + 3f5a067 commit 6418127

File tree

4 files changed

+894
-2
lines changed

4 files changed

+894
-2
lines changed

rewrite-weblogic/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<dependency>
4545
<groupId>org.openrewrite.recipe</groupId>
4646
<artifactId>rewrite-recipe-bom</artifactId>
47-
<version>3.4.0</version>
47+
<version>3.9.0</version>
4848
<type>pom</type>
4949
<scope>import</scope>
5050
</dependency>
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/*
2+
* Copyright (c) 2025 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Universal Permissive License v 1.0 as shown at
5+
* https://oss.oracle.com/licenses/upl.
6+
*
7+
*/
8+
package com.oracle.weblogic.rewrite.jakarta;
9+
10+
import static org.openrewrite.internal.StringUtils.matchesGlob;
11+
12+
import java.util.ArrayList;
13+
import java.util.Collection;
14+
import java.util.Collections;
15+
import java.util.Optional;
16+
17+
import org.jspecify.annotations.Nullable;
18+
19+
import org.openrewrite.ExecutionContext;
20+
import org.openrewrite.maven.MavenDownloadingException;
21+
import org.openrewrite.maven.MavenIsoVisitor;
22+
import org.openrewrite.Option;
23+
import org.openrewrite.Recipe;
24+
import org.openrewrite.TreeVisitor;
25+
26+
import org.openrewrite.maven.table.MavenMetadataFailures;
27+
import org.openrewrite.maven.tree.MavenMetadata;
28+
import org.openrewrite.semver.Semver;
29+
import org.openrewrite.semver.VersionComparator;
30+
import org.openrewrite.xml.XPathMatcher;
31+
import org.openrewrite.xml.tree.Xml;
32+
33+
import lombok.EqualsAndHashCode;
34+
import lombok.Value;
35+
36+
/**
37+
* UpgradeMavenPluginArtifactItems is an imperative recipe to upgrade the groupId, artifactId and version of an artifactIem,
38+
* of a Maven plugin.
39+
*/
40+
41+
@Value
42+
@EqualsAndHashCode(callSuper = false)
43+
public class UpgradeMavenPluginArtifactItems extends Recipe {
44+
45+
@EqualsAndHashCode.Exclude
46+
transient MavenMetadataFailures metadataFailures = new MavenMetadataFailures(this);
47+
48+
@Option(displayName = "Old group ID",
49+
description = "The old group ID to replace.",
50+
example = "javax")
51+
String oldGroupId;
52+
53+
@Option(displayName = "Old artifact ID",
54+
description = "The old artifact ID to replace.",
55+
example = "javax")
56+
String oldArtifactId;
57+
58+
@Option(displayName = "New group ID",
59+
description = "The new group ID to use.",
60+
example = "jakarta.platform")
61+
String newGroupId;
62+
63+
@Option(displayName = "New artifact ID",
64+
description = "The new artifact ID to use.",
65+
example = "javaee-api")
66+
String newArtifactId;
67+
68+
@Option(displayName = "New version",
69+
description = "An exact version number.",
70+
example = "9.1",
71+
required = false)
72+
@Nullable
73+
String newVersion;
74+
75+
private static final XPathMatcher PLUGIN_ARTIFACT_ITEM_MATCHER = new XPathMatcher("/project/build/plugins/plugin/executions/execution/configuration/artifactItems/artifactItem");
76+
77+
private static final String GROUP_ID = "groupId";
78+
private static final String ARTIFACT_ID = "artifactId";
79+
private static final String ARTIFACT_VERSION = "version";
80+
81+
@Override
82+
public String getDescription() {
83+
return "Change the groupId and the artifactId of an artifactItem in the configuration section of a plugin's execution. " +
84+
"This recipe does not perform any validation and assumes all values passed are valid.";
85+
}
86+
87+
@Override
88+
public String getDisplayName() {
89+
return "Upgrade group, artifact ID and version of an artifactItem, of a maven plugin execution configuration";
90+
}
91+
92+
@Override
93+
public TreeVisitor<?, ExecutionContext> getVisitor() {
94+
return new MavenIsoVisitor<ExecutionContext>() {
95+
@Nullable
96+
final VersionComparator versionComparator = newVersion != null ? Semver.validate(newVersion, null).getValue() : null;
97+
@Nullable
98+
private Collection<String> availableVersions;
99+
100+
@Override
101+
public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) {
102+
Xml.Tag t = super.visitTag(tag, ctx);
103+
if (PLUGIN_ARTIFACT_ITEM_MATCHER.matches(getCursor())) {
104+
// Find out whether oldGroupId really exists, consider the value defined as a project property as well
105+
boolean isGroupIdFound = tag.getChildValue(GROUP_ID)
106+
.map(a -> matchesGlob(a, oldGroupId))
107+
.orElse(oldGroupId == null);
108+
isGroupIdFound = isElementFound(tag, isGroupIdFound, GROUP_ID, oldGroupId);
109+
110+
// Find out whether oldArtifactId really exists, consider the value defined as a project property as well
111+
boolean isArtifactIdFound = tag.getChildValue(ARTIFACT_ID)
112+
.map(a -> matchesGlob(a, oldArtifactId))
113+
.orElse(oldArtifactId == null);
114+
isArtifactIdFound = isElementFound(tag, isArtifactIdFound, ARTIFACT_ID, oldArtifactId);
115+
116+
// Change the child tag value only when oldGroupId and oldArtifactId is found
117+
if (isGroupIdFound && isArtifactIdFound) {
118+
if (newGroupId != null) {
119+
t = changeChildTagValue(t, GROUP_ID, newGroupId, ctx);
120+
}
121+
122+
if (newArtifactId != null) {
123+
t = changeChildTagValue(t, ARTIFACT_ID, newArtifactId, ctx);
124+
}
125+
126+
String currentVersion = t.getChildValue(ARTIFACT_VERSION).orElse(null);
127+
if (newVersion != null) {
128+
try {
129+
String resolvedNewVersion = resolveSemverVersion(ctx, newGroupId, newArtifactId, currentVersion);
130+
Optional<Xml.Tag> versionTag = t.getChild(ARTIFACT_VERSION);
131+
boolean versionTagPresent = versionTag.isPresent();
132+
if (versionTagPresent) {
133+
t = changeChildTagValue(t, ARTIFACT_VERSION, resolvedNewVersion, ctx);
134+
}
135+
} catch (MavenDownloadingException e) {
136+
return e.warn(tag);
137+
}
138+
}
139+
}
140+
}
141+
return t;
142+
}
143+
144+
private boolean isElementFound(Xml.Tag tag, boolean isElementFound, String groupId, String oldGroupId) {
145+
if (!isElementFound) {
146+
if (tag.getChildValue(groupId).isPresent() && tag.getChildValue(groupId).get().trim().startsWith("${")) {
147+
String propertyKey = tag.getChildValue(groupId).get().trim();
148+
String value = getResolutionResult().getPom().getValue(propertyKey);
149+
isElementFound = value != null && matchesGlob(value, oldGroupId);
150+
}
151+
}
152+
return isElementFound;
153+
}
154+
155+
@SuppressWarnings("ConstantConditions")
156+
private String resolveSemverVersion(ExecutionContext ctx, String groupId, String artifactId, @Nullable String currentVersion) throws MavenDownloadingException {
157+
if (versionComparator == null) {
158+
return newVersion;
159+
}
160+
String finalCurrentVersion = currentVersion != null ? currentVersion : newVersion;
161+
if (availableVersions == null) {
162+
availableVersions = new ArrayList<>();
163+
MavenMetadata mavenMetadata = metadataFailures.insertRows(ctx, () -> downloadMetadata(groupId, artifactId, ctx));
164+
for (String v : mavenMetadata.getVersioning().getVersions()) {
165+
if (versionComparator.isValid(finalCurrentVersion, v)) {
166+
availableVersions.add(v);
167+
}
168+
}
169+
}
170+
return availableVersions.isEmpty() ? newVersion : Collections.max(availableVersions, versionComparator);
171+
}
172+
};
173+
}
174+
}

0 commit comments

Comments
 (0)