1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.shared.release.phase;
20
21 import java.io.File;
22 import java.nio.file.FileSystems;
23 import java.nio.file.Paths;
24 import java.text.DateFormat;
25 import java.text.SimpleDateFormat;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Date;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Properties;
33 import java.util.Set;
34 import java.util.TimeZone;
35
36 import org.apache.maven.artifact.Artifact;
37 import org.apache.maven.artifact.ArtifactUtils;
38 import org.apache.maven.model.Build;
39 import org.apache.maven.model.BuildBase;
40 import org.apache.maven.model.Model;
41 import org.apache.maven.model.ModelBase;
42 import org.apache.maven.model.Plugin;
43 import org.apache.maven.model.Profile;
44 import org.apache.maven.project.MavenProject;
45 import org.apache.maven.scm.ScmException;
46 import org.apache.maven.scm.ScmFileSet;
47 import org.apache.maven.scm.command.edit.EditScmResult;
48 import org.apache.maven.scm.manager.NoSuchScmProviderException;
49 import org.apache.maven.scm.provider.ScmProvider;
50 import org.apache.maven.scm.repository.ScmRepository;
51 import org.apache.maven.scm.repository.ScmRepositoryException;
52 import org.apache.maven.shared.release.ReleaseExecutionException;
53 import org.apache.maven.shared.release.ReleaseFailureException;
54 import org.apache.maven.shared.release.ReleaseResult;
55 import org.apache.maven.shared.release.config.ReleaseDescriptor;
56 import org.apache.maven.shared.release.env.ReleaseEnvironment;
57 import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
58 import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
59 import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
60 import org.apache.maven.shared.release.scm.ScmTranslator;
61 import org.apache.maven.shared.release.transform.MavenCoordinate;
62 import org.apache.maven.shared.release.transform.ModelETL;
63 import org.apache.maven.shared.release.transform.ModelETLFactory;
64 import org.apache.maven.shared.release.transform.ModelETLRequest;
65 import org.apache.maven.shared.release.transform.jdom2.JDomModelETLFactory;
66 import org.apache.maven.shared.release.util.CiFriendlyVersion;
67 import org.apache.maven.shared.release.util.MavenExpression;
68 import org.apache.maven.shared.release.util.ReleaseUtil;
69 import org.codehaus.plexus.util.StringUtils;
70
71 import static java.util.Objects.requireNonNull;
72 import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
73
74
75
76
77
78
79 public abstract class AbstractRewritePomsPhase extends AbstractReleasePhase implements ResourceGenerator {
80
81
82
83 private final ScmRepositoryConfigurator scmRepositoryConfigurator;
84
85 private final Map<String, ModelETLFactory> modelETLFactories;
86
87
88
89
90 private Map<String, ScmTranslator> scmTranslators;
91
92
93
94
95 private String modelETL = JDomModelETLFactory.NAME;
96
97 private long startTime = -1 * 1000;
98
99 private final Set<String> exclusionPatterns = new HashSet<>();
100
101 protected AbstractRewritePomsPhase(
102 ScmRepositoryConfigurator scmRepositoryConfigurator,
103 Map<String, ModelETLFactory> modelETLFactories,
104 Map<String, ScmTranslator> scmTranslators) {
105 this.scmRepositoryConfigurator = requireNonNull(scmRepositoryConfigurator);
106 this.modelETLFactories = requireNonNull(modelETLFactories);
107 this.scmTranslators = requireNonNull(scmTranslators);
108 }
109
110
111
112
113
114
115 protected final Map<String, ScmTranslator> getScmTranslators() {
116 return scmTranslators;
117 }
118
119
120
121
122
123
124 public void setModelETL(String modelETL) {
125 this.modelETL = modelETL;
126 }
127
128
129
130
131
132
133 public void setStartTime(long startTime) {
134 this.startTime = startTime;
135 }
136
137
138
139
140
141
142 protected abstract String getPomSuffix();
143
144 @Override
145 public ReleaseResult execute(
146 ReleaseDescriptor releaseDescriptor,
147 ReleaseEnvironment releaseEnvironment,
148 List<MavenProject> reactorProjects)
149 throws ReleaseExecutionException, ReleaseFailureException {
150 ReleaseResult result = new ReleaseResult();
151
152 List<String> additionalExcludes = releaseDescriptor.getCheckModificationExcludes();
153
154 if (additionalExcludes != null) {
155 exclusionPatterns.addAll(additionalExcludes);
156 }
157
158 transform(releaseDescriptor, releaseEnvironment, reactorProjects, false, result);
159
160 result.setResultCode(ReleaseResult.SUCCESS);
161
162 return result;
163 }
164
165 @Override
166 public ReleaseResult simulate(
167 ReleaseDescriptor releaseDescriptor,
168 ReleaseEnvironment releaseEnvironment,
169 List<MavenProject> reactorProjects)
170 throws ReleaseExecutionException, ReleaseFailureException {
171 ReleaseResult result = new ReleaseResult();
172
173 transform(releaseDescriptor, releaseEnvironment, reactorProjects, true, result);
174
175 result.setResultCode(ReleaseResult.SUCCESS);
176
177 return result;
178 }
179
180 @Override
181 public ReleaseResult clean(List<MavenProject> reactorProjects) {
182 ReleaseResult result = new ReleaseResult();
183
184 if (reactorProjects != null) {
185 for (MavenProject project : reactorProjects) {
186 File pomFile = ReleaseUtil.getStandardPom(project);
187
188 if (pomFile != null) {
189 File file = new File(pomFile.getParentFile(), pomFile.getName() + "." + getPomSuffix());
190 if (file.exists()) {
191 file.delete();
192 }
193 }
194 }
195 }
196
197 result.setResultCode(ReleaseResult.SUCCESS);
198
199 return result;
200 }
201
202 private void transform(
203 ReleaseDescriptor releaseDescriptor,
204 ReleaseEnvironment releaseEnvironment,
205 List<MavenProject> reactorProjects,
206 boolean simulate,
207 ReleaseResult result)
208 throws ReleaseExecutionException, ReleaseFailureException {
209 result.setStartTime((startTime >= 0) ? startTime : System.currentTimeMillis());
210
211 for (MavenProject project : reactorProjects) {
212 final String path = project.getFile().getPath();
213 if (exclusionPatterns.stream().noneMatch(exclusionPattern -> FileSystems.getDefault()
214 .getPathMatcher("glob:" + exclusionPattern)
215 .matches(Paths.get(path)))) {
216 logDebug(
217 result,
218 "Transforming " + path + ' '
219 + buffer().project(project.getArtifactId()) + " '" + project.getName() + "'"
220 + (simulate ? " with ." + getPomSuffix() + " suffix" : "") + "...");
221
222 transformProject(project, releaseDescriptor, releaseEnvironment, simulate, result);
223 }
224 }
225 }
226
227 private void transformProject(
228 MavenProject project,
229 ReleaseDescriptor releaseDescriptor,
230 ReleaseEnvironment releaseEnvironment,
231 boolean simulate,
232 ReleaseResult result)
233 throws ReleaseExecutionException, ReleaseFailureException {
234 File pomFile = ReleaseUtil.getStandardPom(project);
235
236 ModelETLRequest request = new ModelETLRequest();
237 request.setProject(project);
238 request.setReleaseDescriptor(releaseDescriptor);
239
240 ModelETL etl = modelETLFactories.get(modelETL).newInstance(request);
241
242 etl.extract(pomFile);
243
244 ScmRepository scmRepository = null;
245 ScmProvider provider = null;
246
247 if (isUpdateScm()) {
248 try {
249 scmRepository = scmRepositoryConfigurator.getConfiguredRepository(
250 releaseDescriptor, releaseEnvironment.getSettings());
251
252 provider = scmRepositoryConfigurator.getRepositoryProvider(scmRepository);
253 } catch (ScmRepositoryException e) {
254 throw new ReleaseScmRepositoryException(e.getMessage(), e.getValidationMessages());
255 } catch (NoSuchScmProviderException e) {
256 throw new ReleaseExecutionException("Unable to configure SCM repository: " + e.getMessage(), e);
257 }
258 }
259
260 transformDocument(project, etl.getModel(), releaseDescriptor, scmRepository, result, simulate);
261
262 File outputFile;
263 if (simulate) {
264 outputFile = new File(pomFile.getParentFile(), pomFile.getName() + "." + getPomSuffix());
265 } else {
266 outputFile = pomFile;
267 prepareScm(pomFile, releaseDescriptor, scmRepository, provider);
268 }
269 etl.load(outputFile);
270 }
271
272 private void transformDocument(
273 MavenProject project,
274 Model modelTarget,
275 ReleaseDescriptor releaseDescriptor,
276 ScmRepository scmRepository,
277 ReleaseResult result,
278 boolean simulate)
279 throws ReleaseExecutionException, ReleaseFailureException {
280 Model model = project.getModel();
281
282 Properties properties = modelTarget.getProperties();
283
284 rewriteParent(project, modelTarget, result, releaseDescriptor, simulate);
285
286 String projectId = ArtifactUtils.versionlessKey(project.getGroupId(), project.getArtifactId());
287
288 rewriteVersion(modelTarget, releaseDescriptor, projectId, project);
289
290 Build buildTarget = modelTarget.getBuild();
291 if (buildTarget != null) {
292
293 rewriteArtifactVersions(
294 toMavenCoordinates(buildTarget.getExtensions()),
295 model,
296 properties,
297 result,
298 releaseDescriptor,
299 simulate);
300
301 rewriteArtifactVersions(
302 toMavenCoordinates(buildTarget.getPlugins()),
303 model,
304 properties,
305 result,
306 releaseDescriptor,
307 simulate);
308
309 for (Plugin plugin : buildTarget.getPlugins()) {
310 rewriteArtifactVersions(
311 toMavenCoordinates(plugin.getDependencies()),
312 model,
313 properties,
314 result,
315 releaseDescriptor,
316 simulate);
317 }
318
319 if (buildTarget.getPluginManagement() != null) {
320 rewriteArtifactVersions(
321 toMavenCoordinates(buildTarget.getPluginManagement().getPlugins()),
322 model,
323 properties,
324 result,
325 releaseDescriptor,
326 simulate);
327
328 for (Plugin plugin : buildTarget.getPluginManagement().getPlugins()) {
329 rewriteArtifactVersions(
330 toMavenCoordinates(plugin.getDependencies()),
331 model,
332 properties,
333 result,
334 releaseDescriptor,
335 simulate);
336 }
337 }
338 }
339
340 for (Profile profile : modelTarget.getProfiles()) {
341 BuildBase profileBuild = profile.getBuild();
342 if (profileBuild != null) {
343 rewriteArtifactVersions(
344 toMavenCoordinates(profileBuild.getPlugins()),
345 model,
346 properties,
347 result,
348 releaseDescriptor,
349 simulate);
350
351 for (Plugin plugin : profileBuild.getPlugins()) {
352 rewriteArtifactVersions(
353 toMavenCoordinates(plugin.getDependencies()),
354 model,
355 properties,
356 result,
357 releaseDescriptor,
358 simulate);
359 }
360
361 if (profileBuild.getPluginManagement() != null) {
362 rewriteArtifactVersions(
363 toMavenCoordinates(
364 profileBuild.getPluginManagement().getPlugins()),
365 model,
366 properties,
367 result,
368 releaseDescriptor,
369 simulate);
370
371 for (Plugin plugin : profileBuild.getPluginManagement().getPlugins()) {
372 rewriteArtifactVersions(
373 toMavenCoordinates(plugin.getDependencies()),
374 model,
375 properties,
376 result,
377 releaseDescriptor,
378 simulate);
379 }
380 }
381 }
382 }
383
384 List<ModelBase> modelBases = new ArrayList<>();
385 modelBases.add(modelTarget);
386 modelBases.addAll(modelTarget.getProfiles());
387
388 for (ModelBase modelBase : modelBases) {
389 rewriteArtifactVersions(
390 toMavenCoordinates(modelBase.getDependencies()),
391 model,
392 properties,
393 result,
394 releaseDescriptor,
395 simulate);
396
397 if (modelBase.getDependencyManagement() != null) {
398 rewriteArtifactVersions(
399 toMavenCoordinates(modelBase.getDependencyManagement().getDependencies()),
400 model,
401 properties,
402 result,
403 releaseDescriptor,
404 simulate);
405 }
406
407 if (modelBase.getReporting() != null) {
408 rewriteArtifactVersions(
409 toMavenCoordinates(modelBase.getReporting().getPlugins()),
410 model,
411 properties,
412 result,
413 releaseDescriptor,
414 simulate);
415 }
416 }
417
418 transformScm(project, modelTarget, releaseDescriptor, projectId, scmRepository, result);
419
420 if (properties != null) {
421 rewriteBuildOutputTimestampProperty(properties, result);
422 }
423 }
424
425 private void rewriteBuildOutputTimestampProperty(Properties properties, ReleaseResult result) {
426 String buildOutputTimestamp = properties.getProperty("project.build.outputTimestamp");
427 if (buildOutputTimestamp == null || (buildOutputTimestamp == null || buildOutputTimestamp.isEmpty())) {
428
429 return;
430 }
431
432 if (StringUtils.isNumeric(buildOutputTimestamp)) {
433
434 buildOutputTimestamp = String.valueOf(result.getStartTime() / 1000);
435 } else if (buildOutputTimestamp.length() <= 1) {
436
437 return;
438 } else {
439
440 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
441 df.setTimeZone(TimeZone.getTimeZone("UTC"));
442 buildOutputTimestamp = df.format(new Date(result.getStartTime()));
443 }
444 properties.setProperty("project.build.outputTimestamp", buildOutputTimestamp);
445 }
446
447 private void rewriteVersion(
448 Model modelTarget, ReleaseDescriptor releaseDescriptor, String projectId, MavenProject project)
449 throws ReleaseFailureException {
450 String version = getNextVersion(releaseDescriptor, projectId);
451 if (version == null) {
452 throw new ReleaseFailureException("Version for '" + project.getName() + "' was not mapped");
453 }
454
455 modelTarget.setVersion(version);
456 }
457
458 private void rewriteParent(
459 MavenProject project,
460 Model targetModel,
461 ReleaseResult result,
462 ReleaseDescriptor releaseDescriptor,
463 boolean simulate)
464 throws ReleaseFailureException {
465 if (project.hasParent()) {
466 MavenProject parent = project.getParent();
467 String key = ArtifactUtils.versionlessKey(parent.getGroupId(), parent.getArtifactId());
468 String parentVersion = getNextVersion(releaseDescriptor, key);
469 if (parentVersion == null) {
470
471 parentVersion = getResolvedSnapshotVersion(key, releaseDescriptor);
472 }
473 if (parentVersion == null) {
474 String original = getOriginalVersion(releaseDescriptor, key, simulate);
475 if (parent.getVersion().equals(original)) {
476 throw new ReleaseFailureException("Version for parent '" + parent.getName() + "' was not mapped");
477 }
478 } else {
479 if (!CiFriendlyVersion.isCiFriendlyVersion(
480 targetModel.getParent().getVersion())) {
481 targetModel.getParent().setVersion(parentVersion);
482 } else {
483 logInfo(
484 result,
485 " Ignoring parent version update for CI friendly expression " + parent.getVersion());
486 }
487 }
488 }
489 }
490
491 private void rewriteArtifactVersions(
492 Collection<MavenCoordinate> elements,
493 Model projectModel,
494 Properties properties,
495 ReleaseResult result,
496 ReleaseDescriptor releaseDescriptor,
497 boolean simulate)
498 throws ReleaseExecutionException, ReleaseFailureException {
499 if (elements == null) {
500 return;
501 }
502 for (MavenCoordinate coordinate : elements) {
503 rewriteArtifactVersion(coordinate, projectModel, properties, result, releaseDescriptor, simulate);
504 }
505 }
506
507 private void rewriteArtifactVersion(
508 MavenCoordinate artifact,
509 Model projectModel,
510 Properties properties,
511 ReleaseResult result,
512 ReleaseDescriptor releaseDescriptor,
513 boolean simulate)
514 throws ReleaseExecutionException, ReleaseFailureException {
515 String projectId = ArtifactUtils.versionlessKey(projectModel.getGroupId(), projectModel.getArtifactId());
516 String rawVersion = artifact.getVersion();
517 if (rawVersion == null) {
518
519 return;
520 }
521
522 String rawGroupId = artifact.getGroupId();
523 if (rawGroupId == null) {
524 if ("plugin".equals(artifact.getName())) {
525 rawGroupId = "org.apache.maven.plugins";
526 } else {
527
528 return;
529 }
530 }
531 String groupId = ReleaseUtil.interpolate(rawGroupId, projectModel);
532
533 String rawArtifactId = artifact.getArtifactId();
534 if (rawArtifactId == null) {
535
536 return;
537 }
538 String artifactId = ReleaseUtil.interpolate(rawArtifactId, projectModel);
539
540 String key = ArtifactUtils.versionlessKey(groupId, artifactId);
541 String resolvedSnapshotVersion = getResolvedSnapshotVersion(key, releaseDescriptor);
542 String mappedVersion = getNextVersion(releaseDescriptor, key);
543 String originalVersion = getOriginalVersion(releaseDescriptor, key, simulate);
544 if (originalVersion == null) {
545 originalVersion = getOriginalResolvedSnapshotVersion(key, releaseDescriptor);
546 }
547
548
549 if (mappedVersion != null
550 && mappedVersion.endsWith(Artifact.SNAPSHOT_VERSION)
551 && !rawVersion.endsWith(Artifact.SNAPSHOT_VERSION)
552 && !releaseDescriptor.isUpdateDependencies()) {
553 return;
554 }
555
556 if (mappedVersion != null) {
557 if (rawVersion.equals(originalVersion)) {
558 logInfo(result, " Updating " + key + " to " + mappedVersion);
559 artifact.setVersion(mappedVersion);
560 } else {
561 String property = MavenExpression.extractPropertyFromExpression(rawVersion);
562 if (property != null) {
563 if (property.startsWith("project.") || property.startsWith("pom.") || "version".equals(property)) {
564
565
566 if (!mappedVersion.equals(getNextVersion(releaseDescriptor, projectId))) {
567 logInfo(result, " Updating " + key + " to " + mappedVersion);
568 artifact.setVersion(mappedVersion);
569 } else {
570 logInfo(result, " Ignoring artifact version update for expression " + rawVersion);
571 }
572 } else {
573 rewritePropertyUsedInVersionExpression(
574 projectId,
575 key,
576 rawVersion,
577 mappedVersion,
578 originalVersion,
579 property,
580 properties,
581 result,
582 releaseDescriptor);
583 }
584 }
585 }
586 } else if (resolvedSnapshotVersion != null) {
587 logInfo(result, " Updating " + key + " to " + resolvedSnapshotVersion);
588
589 artifact.setVersion(resolvedSnapshotVersion);
590 } else {
591
592 }
593 }
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611 @SuppressWarnings("checkstyle:ParameterNumber")
612 boolean rewritePropertyUsedInVersionExpression(
613 String projectKey,
614 String artifactKey,
615 String rawVersion,
616 String mappedVersion,
617 String originalVersion,
618 String property,
619 Properties properties,
620 ReleaseResult result,
621 ReleaseDescriptor releaseDescriptor)
622 throws ReleaseFailureException {
623 if (properties == null) {
624 logInfo(
625 result,
626 " Ignoring artifact version update for " + artifactKey + " as expression " + rawVersion
627 + " cannot be locally resolved");
628 return false;
629 }
630
631 boolean isUpdated = false;
632 String propertyValue = properties.getProperty(property);
633 if (propertyValue != null) {
634 if (propertyValue.equals(originalVersion)) {
635 logInfo(result, " Updating " + rawVersion + " to " + mappedVersion);
636
637 properties.setProperty(property, mappedVersion);
638 isUpdated = true;
639 } else if (mappedVersion.equals(propertyValue)) {
640
641 logInfo(
642 result,
643 " Ignoring artifact version update for expression " + rawVersion
644 + " because it is already updated");
645 } else if (!mappedVersion.equals(rawVersion)) {
646
647
648
649 if (mappedVersion.matches("\\$\\{project.+\\}")
650 || mappedVersion.matches("\\$\\{pom.+\\}")
651 || "${version}".equals(mappedVersion)) {
652 logInfo(result, " Ignoring artifact version update for expression " + mappedVersion);
653
654 } else {
655
656 throw new ReleaseFailureException("The artifact (" + artifactKey + ") requires a "
657 + "different version (" + mappedVersion + ") than what is found ("
658 + propertyValue + ") for the expression (" + rawVersion + ") in the "
659 + "project (" + projectKey + ").");
660 }
661 }
662 } else {
663 if (CiFriendlyVersion.isCiFriendlyProperty(property)) {
664 logInfo(result, " Ignoring artifact version update for CI friendly expression " + rawVersion);
665 } else {
666
667 logInfo(
668 result,
669 " Ignoring artifact version update for " + artifactKey + " as expression " + rawVersion
670 + " cannot be locally resolved");
671 }
672 }
673 return isUpdated;
674 }
675
676 private void prepareScm(
677 File pomFile, ReleaseDescriptor releaseDescriptor, ScmRepository repository, ScmProvider provider)
678 throws ReleaseExecutionException, ReleaseScmCommandException {
679 try {
680 if (isUpdateScm() && (releaseDescriptor.isScmUseEditMode() || provider.requiresEditMode())) {
681 EditScmResult result = provider.edit(
682 repository, new ScmFileSet(new File(releaseDescriptor.getWorkingDirectory()), pomFile));
683
684 if (!result.isSuccess()) {
685 throw new ReleaseScmCommandException("Unable to enable editing on the POM", result);
686 }
687 }
688 } catch (ScmException e) {
689 throw new ReleaseExecutionException("An error occurred enabling edit mode: " + e.getMessage(), e);
690 }
691 }
692
693
694
695
696
697
698
699
700 protected abstract String getResolvedSnapshotVersion(
701 String artifactVersionlessKey, ReleaseDescriptor releaseDscriptor);
702
703
704
705
706
707
708
709
710
711 protected abstract String getOriginalVersion(
712 ReleaseDescriptor releaseDescriptor, String projectKey, boolean simulate);
713
714
715
716
717
718
719
720
721 protected abstract String getNextVersion(ReleaseDescriptor releaseDescriptor, String key);
722
723
724
725
726
727
728
729
730
731
732
733
734 protected abstract void transformScm(
735 MavenProject project,
736 Model modelTarget,
737 ReleaseDescriptor releaseDescriptor,
738 String projectId,
739 ScmRepository scmRepository,
740 ReleaseResult result)
741 throws ReleaseExecutionException;
742
743
744
745
746
747
748
749 protected boolean isUpdateScm() {
750 return true;
751 }
752
753
754
755
756
757
758
759
760 protected String getOriginalResolvedSnapshotVersion(
761 String artifactVersionlessKey, ReleaseDescriptor releaseDescriptor) {
762 return releaseDescriptor.getDependencyOriginalVersion(artifactVersionlessKey);
763 }
764
765
766
767
768
769
770
771
772
773
774 protected static String translateUrlPath(String trunkPath, String tagPath, String urlPath) {
775 trunkPath = trunkPath.trim();
776 tagPath = tagPath.trim();
777
778 if (trunkPath.endsWith("/")) {
779 trunkPath = trunkPath.substring(0, trunkPath.length() - 1);
780 }
781 if (tagPath.endsWith("/")) {
782 tagPath = tagPath.substring(0, tagPath.length() - 1);
783 }
784 char[] tagPathChars = trunkPath.toCharArray();
785 char[] trunkPathChars = tagPath.toCharArray();
786
787 int i = 0;
788 while ((i < tagPathChars.length) && (i < trunkPathChars.length) && tagPathChars[i] == trunkPathChars[i]) {
789 ++i;
790 }
791
792
793 if (i == 0 || urlPath.indexOf(trunkPath.substring(i)) < 0) {
794 return tagPath;
795 } else {
796 return StringUtils.replace(urlPath, trunkPath.substring(i), tagPath.substring(i));
797 }
798 }
799
800 private Collection<MavenCoordinate> toMavenCoordinates(List<?> objects) {
801 Collection<MavenCoordinate> coordinates = new ArrayList<>(objects.size());
802 for (Object object : objects) {
803 if (object instanceof MavenCoordinate) {
804 coordinates.add((MavenCoordinate) object);
805 } else {
806 throw new UnsupportedOperationException();
807 }
808 }
809 return coordinates;
810 }
811 }