|
20 | 20 | import org.openrewrite.*; |
21 | 21 | import org.openrewrite.internal.ListUtils; |
22 | 22 | import org.openrewrite.internal.lang.Nullable; |
| 23 | +import org.openrewrite.maven.internal.MavenDownloadingException; |
23 | 24 | import org.openrewrite.maven.tree.*; |
24 | 25 | import org.openrewrite.semver.Semver; |
25 | 26 | import org.openrewrite.semver.VersionComparator; |
@@ -75,6 +76,14 @@ public class UpgradeDependencyVersion extends Recipe { |
75 | 76 | @Nullable |
76 | 77 | Boolean overrideManagedVersion; |
77 | 78 |
|
| 79 | + @Option(displayName = "Metadata failure mode", |
| 80 | + description = "In the event that metadata for a matching dependency cannot be determined, this option determines how to handle the failure", |
| 81 | + example = "fail", |
| 82 | + valid = {"ignore", "warn", "fail"}, |
| 83 | + required = false) |
| 84 | + @Nullable |
| 85 | + String metadataFailureMode; |
| 86 | + |
78 | 87 | @SuppressWarnings("ConstantConditions") |
79 | 88 | @Override |
80 | 89 | public Validated validate() { |
@@ -140,105 +149,139 @@ public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) { |
140 | 149 | @Override |
141 | 150 | public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { |
142 | 151 | Xml.Tag t = super.visitTag(tag, ctx); |
143 | | - if (isDependencyTag(groupId, artifactId)) { |
144 | | - |
145 | | - ResolvedDependency d = findDependency(tag); |
146 | | - if (d != null && d.getRepository() != null) { |
147 | | - //If the resolved dependency exists AND it does not represent an artifact that was parsed |
148 | | - //as a source file, attempt to find a new version. |
149 | | - String newerVersion = findNewerVersion(d.getGroupId(), d.getArtifactId(), d.getVersion(), ctx); |
150 | | - if (newerVersion != null) { |
151 | | - ResolvedManagedDependency dm = findManagedDependency(t); |
152 | | - if (dm != null) { |
153 | | - String requestedVersion = dm.getRequested().getVersion(); |
154 | | - if (requestedVersion.startsWith("${")) { |
155 | | - doAfterVisit(new ChangePropertyValue(requestedVersion.substring(2, requestedVersion.length() - 1), newerVersion, overrideManagedVersion, false)); |
156 | | - return t; |
| 152 | + try { |
| 153 | + if (isDependencyTag(groupId, artifactId)) { |
| 154 | + |
| 155 | + ResolvedDependency d = findDependency(tag); |
| 156 | + if (d != null && d.getRepository() != null) { |
| 157 | + //If the resolved dependency exists AND it does not represent an artifact that was parsed |
| 158 | + //as a source file, attempt to find a new version. |
| 159 | + String newerVersion = findNewerVersion(d.getGroupId(), d.getArtifactId(), d.getVersion(), ctx); |
| 160 | + if (newerVersion != null) { |
| 161 | + ResolvedManagedDependency dm = findManagedDependency(t); |
| 162 | + if (dm != null) { |
| 163 | + String requestedVersion = dm.getRequested().getVersion(); |
| 164 | + if (requestedVersion.startsWith("${")) { |
| 165 | + doAfterVisit(new ChangePropertyValue(requestedVersion.substring(2, requestedVersion.length() - 1), newerVersion, overrideManagedVersion, false)); |
| 166 | + return t; |
| 167 | + } |
157 | 168 | } |
158 | | - } |
159 | 169 |
|
160 | | - Optional<Xml.Tag> version = t.getChild("version"); |
161 | | - if (version.isPresent()) { |
162 | | - String requestedVersion = d.getRequested().getVersion(); |
163 | | - if (requestedVersion != null && requestedVersion.startsWith("${")) { |
164 | | - doAfterVisit(new ChangePropertyValue(requestedVersion.substring(2, requestedVersion.length() - 1), newerVersion, overrideManagedVersion, false)); |
165 | | - return t; |
| 170 | + Optional<Xml.Tag> version = t.getChild("version"); |
| 171 | + if (version.isPresent()) { |
| 172 | + String requestedVersion = d.getRequested().getVersion(); |
| 173 | + if (requestedVersion != null && requestedVersion.startsWith("${")) { |
| 174 | + doAfterVisit(new ChangePropertyValue(requestedVersion.substring(2, requestedVersion.length() - 1), newerVersion, overrideManagedVersion, false)); |
| 175 | + return t; |
| 176 | + } |
| 177 | + t = (Xml.Tag) new ChangeTagValueVisitor<>(version.get(), newerVersion).visitNonNull(t, 0, getCursor()); |
| 178 | + } else if (Boolean.TRUE.equals(overrideManagedVersion)) { |
| 179 | + //If the version is not present and the override managed version is set, add a new, explicit version tag. |
| 180 | + Xml.Tag versionTag = Xml.Tag.build("<version>" + newerVersion + "</version>"); |
| 181 | + //noinspection ConstantConditions |
| 182 | + t = (Xml.Tag) new AddToTagVisitor<ExecutionContext>(t, versionTag, new MavenTagInsertionComparator(t.getChildren())).visitNonNull(t, ctx, getCursor().getParent()); |
166 | 183 | } |
167 | | - t = (Xml.Tag) new ChangeTagValueVisitor<Integer>(version.get(), newerVersion).visitNonNull(t, 0, getCursor()); |
168 | | - } else if (Boolean.TRUE.equals(overrideManagedVersion)) { |
169 | | - //If the version is not present and the override managed version is set, add a new, explicit version tag. |
170 | | - Xml.Tag versionTag = Xml.Tag.build("<version>" + newerVersion + "</version>"); |
171 | | - //noinspection ConstantConditions |
172 | | - t = (Xml.Tag) new AddToTagVisitor<ExecutionContext>(t, versionTag, new MavenTagInsertionComparator(t.getChildren())).visitNonNull(t, ctx, getCursor().getParent()); |
173 | 184 | } |
174 | 185 | } |
175 | | - } |
176 | | - } else if (isManagedDependencyTag(groupId, artifactId)) { |
| 186 | + } else if (isManagedDependencyTag(groupId, artifactId)) { |
177 | 187 |
|
178 | | - ResolvedManagedDependency matchedManagedDependency = findManagedDependency(t); |
179 | | - if (matchedManagedDependency != null) { |
180 | | - if (!projectArtifacts.contains(new GroupArtifact(matchedManagedDependency.getGroupId(), matchedManagedDependency.getArtifactId())) && |
181 | | - matchesGlob(matchedManagedDependency.getGroupId(), groupId) && matchesGlob(matchedManagedDependency.getArtifactId(), artifactId)) { |
| 188 | + ResolvedManagedDependency matchedManagedDependency = findManagedDependency(t); |
| 189 | + if (matchedManagedDependency != null) { |
| 190 | + if (!projectArtifacts.contains(new GroupArtifact(matchedManagedDependency.getGroupId(), matchedManagedDependency.getArtifactId())) && |
| 191 | + matchesGlob(matchedManagedDependency.getGroupId(), groupId) && matchesGlob(matchedManagedDependency.getArtifactId(), artifactId)) { |
182 | 192 |
|
183 | | - String requestedVersion = matchedManagedDependency.getRequested().getVersion(); |
184 | | - assert (matchedManagedDependency.getVersion() != null); |
185 | | - String newerVersion = findNewerVersion(matchedManagedDependency.getGroupId(), matchedManagedDependency.getArtifactId(), matchedManagedDependency.getVersion(), ctx); |
186 | | - if (newerVersion != null) { |
187 | | - if (requestedVersion.startsWith("${")) { |
188 | | - doAfterVisit(new ChangePropertyValue(requestedVersion.substring(2, requestedVersion.length() - 1), newerVersion, overrideManagedVersion, false)); |
189 | | - return t; |
190 | | - } |
191 | | - Xml.Tag childVersionTag = t.getChild("version").orElse(null); |
192 | | - if (childVersionTag != null) { |
193 | | - t = (Xml.Tag) new ChangeTagValueVisitor<Integer>(childVersionTag, newerVersion).visitNonNull(t, 0, getCursor()); |
| 193 | + String requestedVersion = matchedManagedDependency.getRequested().getVersion(); |
| 194 | + assert (matchedManagedDependency.getVersion() != null); |
| 195 | + String newerVersion = findNewerVersion(matchedManagedDependency.getGroupId(), matchedManagedDependency.getArtifactId(), matchedManagedDependency.getVersion(), ctx); |
| 196 | + if (newerVersion != null) { |
| 197 | + if (requestedVersion.startsWith("${")) { |
| 198 | + doAfterVisit(new ChangePropertyValue(requestedVersion.substring(2, requestedVersion.length() - 1), newerVersion, overrideManagedVersion, false)); |
| 199 | + return t; |
| 200 | + } |
| 201 | + Xml.Tag childVersionTag = t.getChild("version").orElse(null); |
| 202 | + if (childVersionTag != null) { |
| 203 | + t = (Xml.Tag) new ChangeTagValueVisitor<Integer>(childVersionTag, newerVersion).visitNonNull(t, 0, getCursor()); |
| 204 | + } |
194 | 205 | } |
195 | 206 | } |
196 | | - } |
197 | | - } else { |
198 | | - for (ResolvedManagedDependency dm : getResolutionResult().getPom().getDependencyManagement()) { |
199 | | - if (dm.getBomGav() != null) { |
200 | | - String tagGroup = getResolutionResult().getPom().getValue(tag.getChildValue("groupId").orElse(getResolutionResult().getPom().getGroupId())); |
201 | | - String tagArtifactId = getResolutionResult().getPom().getValue(tag.getChildValue("artifactId").orElse("")); |
202 | | - |
203 | | - if (!projectArtifacts.contains(new GroupArtifact(tagGroup, tagArtifactId))) { |
204 | | - ResolvedGroupArtifactVersion bom = dm.getBomGav(); |
205 | | - |
206 | | - if (tagGroup != null && tagArtifactId != null && tagGroup.equals(bom.getGroupId()) && tagArtifactId.equals(bom.getArtifactId())) { |
207 | | - |
208 | | - //noinspection ConstantConditions |
209 | | - String requestedVersion = dm.getRequestedBom().getVersion(); |
210 | | - String newerVersion = findNewerVersion(bom.getGroupId(), bom.getArtifactId(), bom.getVersion(), ctx); |
211 | | - if (newerVersion != null) { |
212 | | - if (requestedVersion.startsWith("${")) { |
213 | | - doAfterVisit(new ChangePropertyValue(requestedVersion.substring(2, requestedVersion.length() - 1), newerVersion, overrideManagedVersion, false)); |
214 | | - return t; |
215 | | - } |
216 | | - Xml.Tag childVersionTag = t.getChild("version").orElse(null); |
217 | | - if (childVersionTag != null) { |
218 | | - t = (Xml.Tag) new ChangeTagValueVisitor<Integer>(childVersionTag, newerVersion).visitNonNull(t, 0, getCursor()); |
| 207 | + } else { |
| 208 | + for (ResolvedManagedDependency dm : getResolutionResult().getPom().getDependencyManagement()) { |
| 209 | + if (dm.getBomGav() != null) { |
| 210 | + String tagGroup = getResolutionResult().getPom().getValue(tag.getChildValue("groupId").orElse(getResolutionResult().getPom().getGroupId())); |
| 211 | + String tagArtifactId = getResolutionResult().getPom().getValue(tag.getChildValue("artifactId").orElse("")); |
| 212 | + |
| 213 | + if (!projectArtifacts.contains(new GroupArtifact(tagGroup, tagArtifactId))) { |
| 214 | + ResolvedGroupArtifactVersion bom = dm.getBomGav(); |
| 215 | + |
| 216 | + if (tagGroup != null && tagArtifactId != null && tagGroup.equals(bom.getGroupId()) && tagArtifactId.equals(bom.getArtifactId())) { |
| 217 | + |
| 218 | + //noinspection ConstantConditions |
| 219 | + String requestedVersion = dm.getRequestedBom().getVersion(); |
| 220 | + String newerVersion = findNewerVersion(bom.getGroupId(), bom.getArtifactId(), bom.getVersion(), ctx); |
| 221 | + if (newerVersion != null) { |
| 222 | + if (requestedVersion.startsWith("${")) { |
| 223 | + doAfterVisit(new ChangePropertyValue(requestedVersion.substring(2, requestedVersion.length() - 1), newerVersion, overrideManagedVersion, false)); |
| 224 | + return t; |
| 225 | + } |
| 226 | + Xml.Tag childVersionTag = t.getChild("version").orElse(null); |
| 227 | + if (childVersionTag != null) { |
| 228 | + t = (Xml.Tag) new ChangeTagValueVisitor<Integer>(childVersionTag, newerVersion).visitNonNull(t, 0, getCursor()); |
| 229 | + } |
219 | 230 | } |
| 231 | + break; |
220 | 232 | } |
221 | | - break; |
222 | 233 | } |
223 | 234 | } |
224 | 235 | } |
225 | 236 | } |
226 | 237 | } |
| 238 | + } catch (MavenDownloadingException exception) { |
| 239 | + FailureMode failureMode = FailureMode.getFailureMode(metadataFailureMode); |
| 240 | + if (failureMode == FailureMode.FAIL) { |
| 241 | + throw exception; |
| 242 | + } else if (failureMode == FailureMode.IGNORE) { |
| 243 | + ctx.getOnError().accept(exception); |
| 244 | + } else if (failureMode == FailureMode.WARN) { |
| 245 | + return t.withMarkers(t.getMarkers().searchResult(UncaughtVisitorException.getSanitizedStackTrace(exception))); |
| 246 | + } |
227 | 247 | } |
228 | 248 | return t; |
229 | 249 | } |
230 | 250 |
|
231 | 251 | @Nullable |
232 | 252 | private String findNewerVersion(String groupId, String artifactId, String version, ExecutionContext ctx) { |
233 | | - |
234 | | - MavenMetadata mavenMetadata = downloadMetadata(groupId, artifactId, ctx); |
235 | | - List<String> versions = new ArrayList<>(); |
236 | | - for (String v : mavenMetadata.getVersioning().getVersions()) { |
237 | | - if (versionComparator.isValid(version, v)) { |
238 | | - versions.add(v); |
| 253 | + try { |
| 254 | + MavenMetadata mavenMetadata = downloadMetadata(groupId, artifactId, ctx); |
| 255 | + List<String> versions = new ArrayList<>(); |
| 256 | + for (String v : mavenMetadata.getVersioning().getVersions()) { |
| 257 | + if (versionComparator.isValid(version, v)) { |
| 258 | + versions.add(v); |
| 259 | + } |
239 | 260 | } |
| 261 | + return versionComparator.upgrade(version, versions).orElse(null); |
| 262 | + } catch (IllegalStateException e) { |
| 263 | + //This can happen when we encounter exotic versions. Pass the error to the error handler and |
| 264 | + //in the spirit of "do no harm", return null. |
| 265 | + ctx.getOnError().accept(e); |
| 266 | + return null; |
240 | 267 | } |
241 | | - return versionComparator.upgrade(version, versions).orElse(null); |
242 | 268 | } |
243 | 269 | } |
| 270 | + |
| 271 | + private enum FailureMode { |
| 272 | + IGNORE, |
| 273 | + WARN, |
| 274 | + FAIL; |
| 275 | + |
| 276 | + private static FailureMode getFailureMode(@Nullable String configuration) { |
| 277 | + if ("ignore".equals(configuration)) { |
| 278 | + return FailureMode.IGNORE; |
| 279 | + } else if ("warn".equals(configuration)) { |
| 280 | + return FailureMode.WARN; |
| 281 | + } else { |
| 282 | + return FailureMode.FAIL; |
| 283 | + } |
| 284 | + } |
| 285 | + } |
| 286 | + |
244 | 287 | } |
0 commit comments