Skip to content

Commit 73b1fe8

Browse files
committed
Improvements after review feedback
1 parent 894f5eb commit 73b1fe8

File tree

6 files changed

+99
-183
lines changed

6 files changed

+99
-183
lines changed

impl/maven-core/src/test/java/org/apache/maven/project/DefaultMavenProjectBuilderTest.java

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -414,17 +414,15 @@ void testActivatedDefaultProfileBySource(String fsName, Configuration fsConfig,
414414
String actualLocation = location.getSource().getLocation();
415415
String expectedPath = "pom-with-profiles" + separator + "pom.xml";
416416

417-
// Log the actual vs expected for debugging
418-
System.out.println("=== Cross-Platform Path Test [" + fsName + "] ===");
419-
System.out.println("Expected path pattern: " + expectedPath);
420-
System.out.println("Actual location: " + actualLocation);
421-
System.out.println("Contains expected pattern: " + actualLocation.contains(expectedPath));
422-
System.out.println("File.separator on this system: '" + File.separator + "'");
423-
424417
// The test will pass with File.separator but this shows the platform differences
425418
assertThat(
426419
"Location should contain path with proper separators for " + fsName + " (actual: " + actualLocation
427-
+ ")",
420+
+ ")\n"
421+
+ "=== Cross-Platform Path Test [" + fsName + "] ===\n"
422+
+ "Expected path pattern: " + expectedPath + "\n"
423+
+ "Actual location: " + actualLocation + "\n"
424+
+ "Contains expected pattern: " + actualLocation.contains(expectedPath) + "\n"
425+
+ "File.separator on this system: '" + File.separator + "'",
428426
actualLocation,
429427
containsString("pom-with-profiles/pom.xml"));
430428
}
@@ -487,17 +485,15 @@ void testActivatedExternalProfileBySource(String fsName, Configuration fsConfig,
487485
String actualLocation = location.getSource().getLocation();
488486
String expectedPath = "pom-with-profiles" + separator + "pom.xml";
489487

490-
// Log the actual vs expected for debugging
491-
System.out.println("=== Cross-Platform Path Test [" + fsName + "] - External Profile ===");
492-
System.out.println("Expected path pattern: " + expectedPath);
493-
System.out.println("Actual location: " + actualLocation);
494-
System.out.println("Contains expected pattern: " + actualLocation.contains(expectedPath));
495-
System.out.println("File.separator on this system: '" + File.separator + "'");
496-
497488
// The test will pass with File.separator but this shows the platform differences
498489
assertThat(
499490
"Location should contain path with proper separators for " + fsName + " (actual: " + actualLocation
500-
+ ")",
491+
+ ")\n"
492+
+ "=== Cross-Platform Path Test [" + fsName + "] - External Profile ===\n"
493+
+ "Expected path pattern: " + expectedPath + "\n"
494+
+ "Actual location: " + actualLocation + "\n"
495+
+ "Contains expected pattern: " + actualLocation.contains(expectedPath) + "\n"
496+
+ "File.separator on this system: '" + File.separator + "'",
501497
actualLocation,
502498
containsString("pom-with-profiles/pom.xml"));
503499

impl/maven-impl/src/main/java/org/apache/maven/impl/cache/DefaultRequestCache.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public DefaultRequestCache() {
8888
* @param stats the cache statistics to format
8989
* @return a formatted string containing cache statistics
9090
*/
91-
private static String formatCacheStatistics(CacheStatistics stats) {
91+
static String formatCacheStatistics(CacheStatistics stats) {
9292
StringBuilder sb = new StringBuilder();
9393
sb.append("Request Cache Statistics:\n");
9494
sb.append(" Total requests: ").append(stats.getTotalRequests()).append("\n");

impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelObjectPool.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import org.apache.maven.api.model.Dependency;
3131
import org.apache.maven.api.model.ModelObjectProcessor;
3232
import org.apache.maven.impl.cache.Cache;
33+
import org.slf4j.Logger;
34+
import org.slf4j.LoggerFactory;
3335

3436
/**
3537
* Default implementation of ModelObjectProcessor that provides memory optimization
@@ -55,6 +57,8 @@ public class DefaultModelObjectPool implements ModelObjectProcessor {
5557
private static final Map<Class<?>, AtomicLong> CACHE_HITS = new ConcurrentHashMap<>();
5658
private static final Map<Class<?>, AtomicLong> CACHE_MISSES = new ConcurrentHashMap<>();
5759

60+
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultModelObjectPool.class);
61+
5862
@Override
5963
@SuppressWarnings("unchecked")
6064
public <T> T process(T object) {
@@ -111,7 +115,7 @@ private static Cache.ReferenceType getReferenceTypeForClass(Class<?> objectType)
111115
try {
112116
return Cache.ReferenceType.valueOf(perTypeValue.toUpperCase());
113117
} catch (IllegalArgumentException e) {
114-
System.err.println("Unknown reference type for " + className + ": " + perTypeValue + ", using default");
118+
LOGGER.warn("Unknown reference type for " + className + ": " + perTypeValue + ", using default");
115119
}
116120
}
117121

@@ -128,7 +132,7 @@ private static Cache.ReferenceType getDefaultReferenceType() {
128132
System.getProperty(Constants.MAVEN_MODEL_PROCESSOR_REFERENCE_TYPE, Cache.ReferenceType.HARD.name());
129133
return Cache.ReferenceType.valueOf(referenceTypeProperty.toUpperCase());
130134
} catch (IllegalArgumentException e) {
131-
System.err.println("Unknown default reference type, using HARD");
135+
LOGGER.warn("Unknown default reference type, using HARD");
132136
return Cache.ReferenceType.HARD;
133137
}
134138
}

impl/maven-impl/src/test/java/org/apache/maven/impl/cache/ReferenceTypeStatisticsIntegrationTest.java

Lines changed: 0 additions & 117 deletions
This file was deleted.

impl/maven-impl/src/test/java/org/apache/maven/impl/cache/ReferenceTypeStatisticsTest.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,75 @@ void shouldHandleEmptyStatistics() {
9393
var refTypeStats = statistics.getReferenceTypeStatistics();
9494
assertTrue(refTypeStats.isEmpty());
9595
}
96+
97+
@Test
98+
void shouldDisplayReferenceTypeStatisticsInOutput() {
99+
CacheStatistics statistics = new CacheStatistics();
100+
101+
// Simulate cache usage with different reference types
102+
statistics.recordCacheCreation("HARD", "HARD", CacheRetention.SESSION_SCOPED);
103+
statistics.recordCacheCreation("SOFT", "WEAK", CacheRetention.REQUEST_SCOPED);
104+
statistics.recordCacheCreation("WEAK", "SOFT", CacheRetention.PERSISTENT);
105+
106+
// Simulate cache accesses
107+
statistics.recordCacheAccess("HARD", "HARD", true);
108+
statistics.recordCacheAccess("HARD", "HARD", true);
109+
statistics.recordCacheAccess("HARD", "HARD", false);
110+
111+
statistics.recordCacheAccess("SOFT", "WEAK", true);
112+
statistics.recordCacheAccess("SOFT", "WEAK", false);
113+
statistics.recordCacheAccess("SOFT", "WEAK", false);
114+
115+
statistics.recordCacheAccess("WEAK", "SOFT", false);
116+
117+
// Simulate some regular cache statistics
118+
statistics.recordHit("TestRequest", CacheRetention.SESSION_SCOPED);
119+
statistics.recordMiss("TestRequest", CacheRetention.SESSION_SCOPED);
120+
121+
// Capture the formatted output (not used in this test, but could be useful for future enhancements)
122+
123+
String output = DefaultRequestCache.formatCacheStatistics(statistics);
124+
125+
// Verify that reference type information is included
126+
assertTrue(output.contains("Reference type usage:"), "Should contain reference type section\n" + output);
127+
assertTrue(output.contains("HARD/HARD:"), "Should show HARD/HARD reference type\n" + output);
128+
assertTrue(output.contains("SOFT/WEAK:"), "Should show SOFT/WEAK reference type\n" + output);
129+
assertTrue(output.contains("WEAK/SOFT:"), "Should show WEAK/SOFT reference type\n" + output);
130+
assertTrue(output.contains("caches"), "Should show cache creation count\n" + output);
131+
assertTrue(output.contains("accesses"), "Should show access count\n" + output);
132+
assertTrue(output.contains("hit ratio"), "Should show hit ratio\n" + output);
133+
134+
// Verify that different hit ratios are shown correctly
135+
assertTrue(output.contains("66.7%") || output.contains("66.6%"), "Should show HARD/HARD hit ratio (~66.7%)");
136+
assertTrue(output.contains("33.3%"), "Should show SOFT/WEAK hit ratio (33.3%)");
137+
assertTrue(output.contains("0.0%"), "Should show WEAK/SOFT hit ratio (0.0%)");
138+
}
139+
140+
@Test
141+
void shouldShowMemoryPressureIndicators() {
142+
CacheStatistics statistics = new CacheStatistics();
143+
144+
// Create scenario that might indicate memory pressure
145+
statistics.recordCacheCreation("HARD", "HARD", CacheRetention.SESSION_SCOPED);
146+
statistics.recordCacheCreation("SOFT", "SOFT", CacheRetention.SESSION_SCOPED);
147+
148+
// Simulate many cache accesses with hard references (potential OOM risk)
149+
for (int i = 0; i < 1000; i++) {
150+
statistics.recordCacheAccess("HARD", "HARD", true);
151+
}
152+
153+
// Simulate some soft reference usage
154+
for (int i = 0; i < 100; i++) {
155+
statistics.recordCacheAccess("SOFT", "SOFT", i % 2 == 0);
156+
}
157+
158+
String output = DefaultRequestCache.formatCacheStatistics(statistics);
159+
160+
System.out.println("=== Memory Pressure Analysis ===");
161+
System.out.println(output);
162+
163+
// Should show high usage of hard references
164+
assertTrue(output.contains("HARD/HARD:"), "Should show hard reference usage");
165+
assertTrue(output.contains("1000 accesses"), "Should show high access count for hard references");
166+
}
96167
}

src/site/markdown/cache-configuration.md

Lines changed: 9 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,18 @@ This document describes the enhanced cache configuration functionality in Maven'
2222

2323
## Overview
2424

25-
The DefaultRequestCache has been enhanced to support configurable reference types and cache scopes through user-defined selectors. This allows fine-grained control over caching behavior for different request types.
25+
The DefaultRequestCache supports configurable reference types and cache scopes through user-defined selectors. This allows fine-grained control over caching behavior for different request types.
2626

2727
## Key Features
2828

2929
### 1. Early Return for ProtoSession
30-
- The `doCache` method now returns early when the request session is not a `Session` instance (e.g., `ProtoSession`)
31-
- This prevents caching attempts for non-session contexts
30+
- The `doCache` method now returns early when the request session is not a `Session` instance (e.g., `ProtoSession`).
31+
- This prevents caching attempts for non-session contexts.
3232

3333
### 2. Configurable Cache Behavior
34-
- Cache scope and reference type can be configured via session user properties
35-
- Configuration uses CSS-like selectors to match request types
36-
- Supports parent-child request relationships
37-
38-
### 3. Backward Compatibility
39-
- Existing `CacheMetadata` interface still supported
40-
- Default behavior unchanged when no configuration provided
41-
- Legacy hardcoded behavior maintained as fallback
34+
- Cache scope and reference type can be configured via session user properties.
35+
- Configuration uses CSS-like selectors to match request types.
36+
- Supports parent-child request relationships.
4237

4338
## Configuration Syntax
4439

@@ -59,9 +54,9 @@ Where:
5954
- `ref`: Reference type for cache entries (optional)
6055

6156
**Note**:
62-
- You can specify only `scope` or only `ref` - missing values will be merged from less specific selectors or use defaults
63-
- Selectors match against all interfaces implemented by the request class, not just the class name
64-
- This allows matching against `ModelBuilderRequest` interface even if the actual class is `DefaultModelBuilderRequest`
57+
- You can specify only `scope` or only `ref` - missing values will be merged from less specific selectors or use defaults.
58+
- Selectors match against all interfaces implemented by the request class, not just the class name.
59+
- This allows matching against `ModelBuilderRequest` interface even if the actual class is `DefaultModelBuilderRequest`.
6560

6661
### Available Values
6762

@@ -139,39 +134,6 @@ For a `ModelBuilderRequest` with `ModelBuildRequest` parent:
139134

140135
## Implementation Details
141136

142-
### New Classes
143-
- `CacheConfig`: Record holding complete scope and reference type configuration
144-
- `PartialCacheConfig`: Record holding partial configuration (allows null values)
145-
- `CacheSelector`: Represents a selector rule with matching logic
146-
- `CacheSelectorParser`: Parses configuration strings into selectors
147-
- `CacheConfigurationResolver`: Resolves and merges configuration for requests
148-
149-
### Modified Classes
150-
- `DefaultRequestCache.doCache()`: Enhanced with configurable behavior
151-
- `CacheSelector.matches()`: Enhanced to match against all implemented interfaces
152-
- Early return for non-Session requests
153-
- Removed hardcoded reference types
154-
- Integrated configuration resolution
155-
156-
## Migration Guide
157-
158-
### For Users
159-
- No changes required for existing builds
160-
- New configuration is opt-in via user properties
161-
- Existing behavior preserved when no configuration provided
162-
163-
### For Developers
164-
- `CacheMetadata` interface still supported for backward compatibility
165-
- New configuration takes precedence over `CacheMetadata`
166-
- Default reference types changed to SOFT for consistency
167-
168-
## Testing
169-
170-
The implementation includes comprehensive tests:
171-
- `CacheConfigurationTest`: Unit tests for configuration parsing and resolution
172-
- Integration tests for selector matching and priority
173-
- Backward compatibility tests
174-
175137
## Performance Considerations
176138

177139
- Configuration parsing is cached per session to avoid re-parsing

0 commit comments

Comments
 (0)