0
# Utilities and Helpers
1
2
Utility classes for common Maven operations including Maven wrapper support and dependency visualization.
3
4
## Capabilities
5
6
### Maven Wrapper Utilities
7
8
#### MavenWrapper
9
10
Utilities for working with Maven wrapper scripts and configuration.
11
12
```java { .api }
13
/**
14
* Utilities for working with Maven wrapper (mvnw) scripts
15
*/
16
public class MavenWrapper {
17
/**
18
* Check if project has Maven wrapper
19
* @param projectRoot Project root directory
20
* @return true if Maven wrapper exists
21
*/
22
public static boolean hasMavenWrapper(Path projectRoot);
23
24
/**
25
* Get Maven wrapper version from project
26
* @param projectRoot Project root directory
27
* @return Maven wrapper version or null if not found
28
*/
29
public static @Nullable String getWrapperVersion(Path projectRoot);
30
31
/**
32
* Update Maven wrapper to specified version
33
* @param projectRoot Project root directory
34
* @param version New Maven version
35
* @throws IOException if update fails
36
*/
37
public static void updateWrapper(Path projectRoot, String version) throws IOException;
38
39
/**
40
* Create Maven wrapper in project
41
* @param projectRoot Project root directory
42
* @param mavenVersion Maven version to use
43
* @throws IOException if creation fails
44
*/
45
public static void createWrapper(Path projectRoot, String mavenVersion) throws IOException;
46
47
/**
48
* Get Maven wrapper properties
49
* @param projectRoot Project root directory
50
* @return Properties from wrapper configuration
51
*/
52
public static Properties getWrapperProperties(Path projectRoot);
53
}
54
```
55
56
**Usage Examples:**
57
58
```java
59
Path projectRoot = Paths.get("/path/to/maven/project");
60
61
// Check for Maven wrapper
62
if (MavenWrapper.hasMavenWrapper(projectRoot)) {
63
String version = MavenWrapper.getWrapperVersion(projectRoot);
64
System.out.println("Maven wrapper version: " + version);
65
66
// Update wrapper to newer version
67
MavenWrapper.updateWrapper(projectRoot, "3.9.4");
68
} else {
69
// Create new Maven wrapper
70
MavenWrapper.createWrapper(projectRoot, "3.9.4");
71
}
72
73
// Get wrapper configuration
74
Properties props = MavenWrapper.getWrapperProperties(projectRoot);
75
String distributionUrl = props.getProperty("distributionUrl");
76
System.out.println("Distribution URL: " + distributionUrl);
77
```
78
79
### Artifact Downloading
80
81
#### MavenArtifactDownloader
82
83
Utility for downloading Maven artifacts from repositories.
84
85
```java { .api }
86
/**
87
* Utility for downloading Maven artifacts from repositories
88
*/
89
public class MavenArtifactDownloader {
90
/**
91
* Create downloader with default configuration
92
*/
93
public MavenArtifactDownloader();
94
95
/**
96
* Create downloader with custom repositories
97
* @param repositories List of Maven repositories to use
98
*/
99
public MavenArtifactDownloader(List<MavenRepository> repositories);
100
101
/**
102
* Create downloader with configuration
103
* @param repositories List of Maven repositories
104
* @param cache Optional artifact cache
105
* @param timeout Download timeout in milliseconds
106
*/
107
public MavenArtifactDownloader(List<MavenRepository> repositories,
108
@Nullable MavenArtifactCache cache,
109
int timeout);
110
}
111
```
112
113
**Key Methods:**
114
115
```java { .api }
116
/**
117
* Download artifact JAR file
118
* @param gav Group:Artifact:Version coordinate
119
* @return Downloaded artifact bytes
120
* @throws MavenDownloadingException if download fails
121
*/
122
public byte[] downloadArtifact(GroupArtifactVersion gav) throws MavenDownloadingException;
123
124
/**
125
* Download artifact with classifier
126
* @param gav Group:Artifact:Version coordinate
127
* @param classifier Artifact classifier (e.g., "sources", "javadoc")
128
* @return Downloaded artifact bytes
129
* @throws MavenDownloadingException if download fails
130
*/
131
public byte[] downloadArtifact(GroupArtifactVersion gav, String classifier) throws MavenDownloadingException;
132
133
/**
134
* Download artifact POM file
135
* @param gav Group:Artifact:Version coordinate
136
* @return Downloaded POM content
137
* @throws MavenDownloadingException if download fails
138
*/
139
public String downloadPom(GroupArtifactVersion gav) throws MavenDownloadingException;
140
141
/**
142
* Download artifact metadata
143
* @param ga Group:Artifact coordinate
144
* @return Maven metadata information
145
* @throws MavenDownloadingException if download fails
146
*/
147
public MavenMetadata downloadMetadata(GroupArtifact ga) throws MavenDownloadingException;
148
149
/**
150
* Check if artifact exists in repositories
151
* @param gav Group:Artifact:Version coordinate
152
* @return true if artifact exists
153
*/
154
public boolean artifactExists(GroupArtifactVersion gav);
155
156
/**
157
* Get available versions for artifact
158
* @param ga Group:Artifact coordinate
159
* @return List of available versions
160
* @throws MavenDownloadingException if retrieval fails
161
*/
162
public List<String> getAvailableVersions(GroupArtifact ga) throws MavenDownloadingException;
163
```
164
165
**Usage Examples:**
166
167
```java
168
// Create repositories
169
List<MavenRepository> repos = Arrays.asList(
170
MavenRepository.builder()
171
.id("central")
172
.uri("https://repo1.maven.org/maven2/")
173
.releases(true)
174
.snapshots(false)
175
.build(),
176
MavenRepository.builder()
177
.id("snapshots")
178
.uri("https://oss.sonatype.org/content/repositories/snapshots/")
179
.releases(false)
180
.snapshots(true)
181
.build()
182
);
183
184
// Create downloader
185
MavenArtifactDownloader downloader = new MavenArtifactDownloader(repos);
186
187
// Download specific artifact
188
GroupArtifactVersion gav = new GroupArtifactVersion("org.junit.jupiter", "junit-jupiter", "5.8.2");
189
try {
190
byte[] artifactBytes = downloader.downloadArtifact(gav);
191
System.out.println("Downloaded artifact: " + artifactBytes.length + " bytes");
192
193
// Download sources
194
byte[] sourcesBytes = downloader.downloadArtifact(gav, "sources");
195
System.out.println("Downloaded sources: " + sourcesBytes.length + " bytes");
196
197
// Download POM
198
String pomContent = downloader.downloadPom(gav);
199
System.out.println("Downloaded POM:\n" + pomContent);
200
201
} catch (MavenDownloadingException e) {
202
System.err.println("Download failed: " + e.getMessage());
203
}
204
205
// Check artifact availability
206
GroupArtifact ga = new GroupArtifact("org.springframework", "spring-core");
207
if (downloader.artifactExists(new GroupArtifactVersion(ga.getGroupId(), ga.getArtifactId(), "5.3.21"))) {
208
List<String> versions = downloader.getAvailableVersions(ga);
209
System.out.println("Available versions: " + versions);
210
}
211
```
212
213
### Dependency Visualization
214
215
#### PrintMavenAsDot
216
217
Recipe to visualize Maven dependencies as DOT graph format for Graphviz.
218
219
```java { .api }
220
/**
221
* Recipe to generate DOT graph representation of Maven dependencies
222
*/
223
public class PrintMavenAsDot extends Recipe {
224
/**
225
* Create recipe with default configuration
226
*/
227
public PrintMavenAsDot();
228
229
/**
230
* Create recipe with scope filter
231
* @param scope Optional scope to limit visualization (e.g., "compile", "test")
232
*/
233
public PrintMavenAsDot(@Nullable String scope);
234
235
/**
236
* Create recipe with full configuration
237
* @param scope Optional scope filter
238
* @param includeTransitive Include transitive dependencies
239
* @param maxDepth Maximum dependency depth to visualize
240
*/
241
public PrintMavenAsDot(@Nullable String scope, boolean includeTransitive, int maxDepth);
242
}
243
```
244
245
**Usage Examples:**
246
247
```java
248
// Generate DOT graph for all dependencies
249
PrintMavenAsDot dotGenerator = new PrintMavenAsDot();
250
RecipeRun run = dotGenerator.run(List.of(pomDocument), ctx);
251
252
// Get generated DOT content
253
List<PrintMavenAsDot.DotGraph> graphs = run.getDataTable(PrintMavenAsDot.DotGraph.class);
254
for (PrintMavenAsDot.DotGraph graph : graphs) {
255
String dotContent = graph.getDotContent();
256
257
// Save to file
258
Files.write(Paths.get("dependencies.dot"), dotContent.getBytes());
259
260
// Or render with Graphviz
261
Process graphviz = Runtime.getRuntime().exec("dot -Tpng -o dependencies.png");
262
try (OutputStream out = graphviz.getOutputStream()) {
263
out.write(dotContent.getBytes());
264
}
265
graphviz.waitFor();
266
}
267
268
// Generate focused graph for compile dependencies only
269
PrintMavenAsDot compileGraph = new PrintMavenAsDot("compile", true, 3);
270
RecipeRun compileRun = compileGraph.run(List.of(pomDocument), ctx);
271
```
272
273
### Version Retention Utilities
274
275
#### RetainVersions
276
277
Utility for version retention policies and cleanup operations.
278
279
```java { .api }
280
/**
281
* Utility for managing version retention policies
282
*/
283
public class RetainVersions {
284
/**
285
* Create retention policy with default settings
286
*/
287
public RetainVersions();
288
289
/**
290
* Create retention policy with configuration
291
* @param retainCount Number of versions to retain
292
* @param retainDays Number of days to retain versions
293
* @param retainSnapshots Whether to retain snapshot versions
294
*/
295
public RetainVersions(int retainCount, int retainDays, boolean retainSnapshots);
296
}
297
```
298
299
**Key Methods:**
300
301
```java { .api }
302
/**
303
* Get versions to retain based on policy
304
* @param availableVersions List of available versions
305
* @return List of versions that should be retained
306
*/
307
public List<String> getVersionsToRetain(List<String> availableVersions);
308
309
/**
310
* Get versions to delete based on policy
311
* @param availableVersions List of available versions
312
* @return List of versions that can be deleted
313
*/
314
public List<String> getVersionsToDelete(List<String> availableVersions);
315
316
/**
317
* Check if version should be retained
318
* @param version Version to check
319
* @param availableVersions All available versions
320
* @return true if version should be retained
321
*/
322
public boolean shouldRetain(String version, List<String> availableVersions);
323
```
324
325
**Usage Examples:**
326
327
```java
328
// Create retention policy: keep 5 latest versions, 30 days, no snapshots
329
RetainVersions policy = new RetainVersions(5, 30, false);
330
331
List<String> availableVersions = Arrays.asList(
332
"1.0.0", "1.1.0", "1.2.0", "1.3.0", "1.4.0", "1.5.0",
333
"2.0.0-SNAPSHOT", "1.6.0", "1.7.0"
334
);
335
336
List<String> toRetain = policy.getVersionsToRetain(availableVersions);
337
List<String> toDelete = policy.getVersionsToDelete(availableVersions);
338
339
System.out.println("Retain: " + toRetain);
340
System.out.println("Delete: " + toDelete);
341
```
342
343
### Maven Settings Utilities
344
345
#### MavenSettings Helper Methods
346
347
```java { .api }
348
/**
349
* Additional helper methods for MavenSettings
350
*/
351
public class MavenSettings {
352
/**
353
* Load settings from default location (~/.m2/settings.xml)
354
* @return MavenSettings instance or null if not found
355
*/
356
public static @Nullable MavenSettings loadDefault();
357
358
/**
359
* Load settings from specific file
360
* @param settingsFile Path to settings.xml file
361
* @return MavenSettings instance
362
* @throws IOException if file cannot be read
363
*/
364
public static MavenSettings load(Path settingsFile) throws IOException;
365
366
/**
367
* Merge global and user settings
368
* @param globalSettings Global settings (from Maven installation)
369
* @param userSettings User settings (from ~/.m2/settings.xml)
370
* @return Merged settings
371
*/
372
public static MavenSettings merge(@Nullable MavenSettings globalSettings,
373
@Nullable MavenSettings userSettings);
374
375
/**
376
* Get effective repositories (including mirrors)
377
* @return List of effective repositories
378
*/
379
public List<MavenRepository> getEffectiveRepositories();
380
381
/**
382
* Get server authentication for repository
383
* @param repositoryId Repository ID
384
* @return Server configuration or null if not found
385
*/
386
public @Nullable Server getServer(String repositoryId);
387
388
/**
389
* Resolve property placeholders in settings
390
* @param value Value that may contain placeholders
391
* @return Resolved value
392
*/
393
public String resolveProperty(String value);
394
}
395
```
396
397
### Tag Insertion Utilities
398
399
#### MavenTagInsertionComparator
400
401
Comparator for ordering Maven POM elements according to Maven conventions.
402
403
```java { .api }
404
/**
405
* Comparator for ordering Maven POM elements according to standard conventions
406
* Used to maintain proper element ordering when adding new elements
407
*/
408
public class MavenTagInsertionComparator implements Comparator<Content> {
409
/**
410
* Create comparator for specific parent tag
411
* @param parentTagName Name of parent tag (e.g., "dependencies", "plugins")
412
*/
413
public MavenTagInsertionComparator(String parentTagName);
414
415
@Override
416
public int compare(Content c1, Content c2);
417
418
/**
419
* Get standard ordering for Maven POM elements
420
* @return Map of element names to their priority order
421
*/
422
public static Map<String, Integer> getStandardOrdering();
423
}
424
```
425
426
**Usage Examples:**
427
428
```java
429
// Use comparator when adding dependencies
430
MavenTagInsertionComparator comparator = new MavenTagInsertionComparator("dependencies");
431
432
// Sort existing dependencies
433
List<Xml.Tag> dependencies = getDependencyTags();
434
dependencies.sort((tag1, tag2) -> comparator.compare(tag1, tag2));
435
436
// Insert new dependency in correct position
437
Xml.Tag newDependency = createDependencyTag("org.junit.jupiter", "junit-jupiter", "5.8.2");
438
int insertPosition = Collections.binarySearch(dependencies, newDependency, comparator);
439
if (insertPosition < 0) {
440
insertPosition = -insertPosition - 1;
441
}
442
dependencies.add(insertPosition, newDependency);
443
```
444
445
### Assertion Utilities
446
447
#### Assertions
448
449
Test assertions for Maven-related functionality.
450
451
```java { .api }
452
/**
453
* Test assertions for Maven-related functionality
454
* Used in testing Maven transformations and analysis
455
*/
456
public class Assertions {
457
/**
458
* Assert that POM contains dependency
459
* @param pom POM to check
460
* @param groupId Expected group ID
461
* @param artifactId Expected artifact ID
462
*/
463
public static void assertHasDependency(Pom pom, String groupId, String artifactId);
464
465
/**
466
* Assert that POM contains dependency with version
467
* @param pom POM to check
468
* @param groupId Expected group ID
469
* @param artifactId Expected artifact ID
470
* @param version Expected version
471
*/
472
public static void assertHasDependency(Pom pom, String groupId, String artifactId, String version);
473
474
/**
475
* Assert that POM contains plugin
476
* @param pom POM to check
477
* @param groupId Expected plugin group ID
478
* @param artifactId Expected plugin artifact ID
479
*/
480
public static void assertHasPlugin(Pom pom, String groupId, String artifactId);
481
482
/**
483
* Assert that POM contains property
484
* @param pom POM to check
485
* @param key Expected property key
486
* @param value Expected property value
487
*/
488
public static void assertHasProperty(Pom pom, String key, String value);
489
490
/**
491
* Assert that dependency has scope
492
* @param dependency Dependency to check
493
* @param expectedScope Expected scope
494
*/
495
public static void assertDependencyScope(Dependency dependency, Scope expectedScope);
496
497
/**
498
* Assert that dependencies are in correct order
499
* @param dependencies List of dependencies to check
500
*/
501
public static void assertDependencyOrder(List<Dependency> dependencies);
502
}
503
```
504
505
**Usage Examples:**
506
507
```java
508
// In tests
509
@Test
510
public void testAddDependency() {
511
AddDependency recipe = new AddDependency("org.junit.jupiter", "junit-jupiter", "5.8.2",
512
null, "test", null, null, null, null, null, null, null);
513
514
RecipeRun run = recipe.run(List.of(pomDocument), ctx);
515
Pom resultPom = getResultPom(run);
516
517
// Assert dependency was added
518
Assertions.assertHasDependency(resultPom, "org.junit.jupiter", "junit-jupiter");
519
Assertions.assertHasDependency(resultPom, "org.junit.jupiter", "junit-jupiter", "5.8.2");
520
521
// Assert dependency has correct scope
522
Dependency junitDep = resultPom.getDependencies().stream()
523
.filter(dep -> dep.getArtifactId().equals("junit-jupiter"))
524
.findFirst()
525
.orElse(null);
526
527
assertNotNull(junitDep);
528
Assertions.assertDependencyScope(junitDep, Scope.Test);
529
}
530
```
531
532
### Trait System Integration
533
534
#### Maven Element Traits
535
536
```java { .api }
537
/**
538
* Factory class for creating Maven-specific traits
539
*/
540
public class Traits {
541
/**
542
* Create trait for Maven dependency elements
543
* @param element Source element
544
* @return MavenDependency trait
545
*/
546
public static MavenDependency mavenDependency(SourceFile element);
547
548
/**
549
* Create trait for Maven plugin elements
550
* @param element Source element
551
* @return MavenPlugin trait
552
*/
553
public static MavenPlugin mavenPlugin(SourceFile element);
554
}
555
556
/**
557
* Trait for Maven dependency elements
558
*/
559
public class MavenDependency {
560
/**
561
* Get dependency coordinate
562
*/
563
public GroupArtifactVersion getCoordinate();
564
565
/**
566
* Get dependency scope
567
*/
568
public Scope getScope();
569
570
/**
571
* Check if dependency is optional
572
*/
573
public boolean isOptional();
574
575
/**
576
* Get dependency exclusions
577
*/
578
public List<GroupArtifact> getExclusions();
579
}
580
581
/**
582
* Trait for Maven plugin elements
583
*/
584
public class MavenPlugin {
585
/**
586
* Get plugin coordinate
587
*/
588
public GroupArtifactVersion getCoordinate();
589
590
/**
591
* Get plugin configuration
592
*/
593
public @Nullable Object getConfiguration();
594
595
/**
596
* Get plugin executions
597
*/
598
public List<PluginExecution> getExecutions();
599
}
600
```
601
602
### Complete Utility Usage Example
603
604
```java
605
/**
606
* Comprehensive example using multiple utilities together
607
*/
608
public class MavenProjectAnalyzer {
609
public void analyzeProject(Path projectRoot) throws Exception {
610
// Check for Maven wrapper
611
if (MavenWrapper.hasMavenWrapper(projectRoot)) {
612
String wrapperVersion = MavenWrapper.getWrapperVersion(projectRoot);
613
System.out.println("Maven wrapper version: " + wrapperVersion);
614
}
615
616
// Load Maven settings
617
MavenSettings settings = MavenSettings.loadDefault();
618
List<MavenRepository> repositories = settings != null ?
619
settings.getEffectiveRepositories() :
620
Collections.singletonList(MavenRepository.MAVEN_CENTRAL);
621
622
// Set up artifact downloader
623
MavenArtifactDownloader downloader = new MavenArtifactDownloader(repositories);
624
625
// Parse POM with caching
626
InMemoryMavenPomCache pomCache = new InMemoryMavenPomCache();
627
MavenParser parser = MavenParser.builder()
628
.pomCache(pomCache)
629
.build();
630
631
Path pomFile = projectRoot.resolve("pom.xml");
632
String pomContent = Files.readString(pomFile);
633
634
ExecutionContext ctx = new InMemoryExecutionContext();
635
List<SourceFile> parsed = parser.parse(ctx, pomContent);
636
637
Xml.Document pomDoc = (Xml.Document) parsed.get(0);
638
MavenResolutionResult result = pomDoc.getMarkers()
639
.findFirst(MavenResolutionResult.class)
640
.orElse(null);
641
642
if (result != null) {
643
ResolvedPom resolvedPom = result.getPom();
644
645
// Generate dependency visualization
646
PrintMavenAsDot dotGenerator = new PrintMavenAsDot("compile", true, 3);
647
RecipeRun dotRun = dotGenerator.run(List.of(pomDoc), ctx);
648
649
List<PrintMavenAsDot.DotGraph> graphs = dotRun.getDataTable(PrintMavenAsDot.DotGraph.class);
650
if (!graphs.isEmpty()) {
651
Files.write(projectRoot.resolve("dependencies.dot"),
652
graphs.get(0).getDotContent().getBytes());
653
}
654
655
// Check for outdated dependencies
656
for (ResolvedDependency dep : resolvedPom.getDependencies()) {
657
GroupArtifact ga = new GroupArtifact(dep.getGroupId(), dep.getArtifactId());
658
List<String> availableVersions = downloader.getAvailableVersions(ga);
659
660
// Use retention policy to identify latest versions
661
RetainVersions policy = new RetainVersions(1, Integer.MAX_VALUE, false);
662
List<String> latest = policy.getVersionsToRetain(availableVersions);
663
664
if (!latest.isEmpty() && !latest.get(0).equals(dep.getVersion())) {
665
System.out.println("Outdated dependency: " + dep.getGroupId() + ":" +
666
dep.getArtifactId() + " (" + dep.getVersion() +
667
" -> " + latest.get(0) + ")");
668
}
669
}
670
}
671
}
672
}
673
```