1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.util.version;
20
21 import java.nio.charset.StandardCharsets;
22 import java.util.Collections;
23 import java.util.Map;
24 import java.util.WeakHashMap;
25 import java.util.concurrent.atomic.AtomicLong;
26
27 import org.eclipse.aether.ConfigurationProperties;
28 import org.eclipse.aether.version.InvalidVersionSpecificationException;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class GenericVersionScheme extends VersionSchemeSupport {
56
57
58 private final Map<String, GenericVersion> versionCache = Collections.synchronizedMap(new WeakHashMap<>());
59
60
61 private final AtomicLong cacheHits = new AtomicLong(0);
62 private final AtomicLong cacheMisses = new AtomicLong(0);
63 private final AtomicLong totalRequests = new AtomicLong(0);
64
65
66 private static final AtomicLong GLOBAL_CACHE_HITS = new AtomicLong(0);
67 private static final AtomicLong GLOBAL_CACHE_MISSES = new AtomicLong(0);
68 private static final AtomicLong GLOBAL_TOTAL_REQUESTS = new AtomicLong(0);
69 private static final AtomicLong INSTANCE_COUNT = new AtomicLong(0);
70
71 static {
72
73 if (isStatisticsEnabled()) {
74 Runtime.getRuntime().addShutdownHook(new Thread(GenericVersionScheme::printGlobalStatistics));
75 }
76 }
77
78 public GenericVersionScheme() {
79 INSTANCE_COUNT.incrementAndGet();
80 }
81
82
83
84
85
86 private static boolean isStatisticsEnabled() {
87
88 String sysProp = System.getProperty(ConfigurationProperties.VERSION_SCHEME_CACHE_DEBUG);
89 if (sysProp != null) {
90 return Boolean.parseBoolean(sysProp);
91 }
92
93
94 return ConfigurationProperties.DEFAULT_VERSION_SCHEME_CACHE_DEBUG;
95 }
96
97 @Override
98 public GenericVersion parseVersion(final String version) throws InvalidVersionSpecificationException {
99 totalRequests.incrementAndGet();
100 GLOBAL_TOTAL_REQUESTS.incrementAndGet();
101
102 GenericVersion existing = versionCache.get(version);
103 if (existing != null) {
104 cacheHits.incrementAndGet();
105 GLOBAL_CACHE_HITS.incrementAndGet();
106 return existing;
107 } else {
108 cacheMisses.incrementAndGet();
109 GLOBAL_CACHE_MISSES.incrementAndGet();
110 return versionCache.computeIfAbsent(version, GenericVersion::new);
111 }
112 }
113
114
115
116
117 public String getCacheStatistics() {
118 long hits = cacheHits.get();
119 long misses = cacheMisses.get();
120 long total = totalRequests.get();
121 double hitRate = total > 0 ? (double) hits / total * 100.0 : 0.0;
122
123 return String.format(
124 "GenericVersionScheme Cache Stats: hits=%d, misses=%d, total=%d, hit-rate=%.2f%%, cache-size=%d",
125 hits, misses, total, hitRate, versionCache.size());
126 }
127
128
129
130
131 private static void printGlobalStatistics() {
132 long hits = GLOBAL_CACHE_HITS.get();
133 long misses = GLOBAL_CACHE_MISSES.get();
134 long total = GLOBAL_TOTAL_REQUESTS.get();
135 long instances = INSTANCE_COUNT.get();
136 double hitRate = total > 0 ? (double) hits / total * 100.0 : 0.0;
137
138 System.err.println("=== GenericVersionScheme Global Cache Statistics (WeakHashMap) ===");
139 System.err.println(String.format("Total instances created: %d", instances));
140 System.err.println(String.format("Total requests: %d", total));
141 System.err.println(String.format("Cache hits: %d", hits));
142 System.err.println(String.format("Cache misses: %d", misses));
143 System.err.println(String.format("Hit rate: %.2f%%", hitRate));
144 System.err.println(
145 String.format("Average requests per instance: %.2f", instances > 0 ? (double) total / instances : 0.0));
146 System.err.println("=== End Cache Statistics ===");
147 }
148
149
150
151
152
153
154
155
156
157 public static void main(String... args) {
158 System.out.println(
159 "Display parameters as parsed by Maven Resolver 'generic' scheme (in canonical form and as a list of tokens)"
160 + " and comparison result:");
161 if (args.length == 0) {
162 return;
163 }
164
165 GenericVersionScheme scheme = new GenericVersionScheme();
166 GenericVersion prev = null;
167 int i = 1;
168 for (String version : args) {
169 if (!StandardCharsets.US_ASCII.newEncoder().canEncode(version)) {
170 System.out.println("WW Use of non-ASCII characters for version strings is not recommended.");
171 }
172 try {
173 GenericVersion c = scheme.parseVersion(version);
174
175 if (prev != null) {
176 int compare = prev.compareTo(c);
177 System.out.println(
178 " " + prev + ' ' + ((compare == 0) ? "==" : ((compare < 0) ? "<" : ">")) + ' ' + version);
179 }
180
181 System.out.println((i++) + ". " + version + " -> " + c.asString() + "; tokens: " + c.asItems());
182
183 prev = c;
184 } catch (InvalidVersionSpecificationException e) {
185 System.err.println("Invalid version: " + version + " - " + e.getMessage());
186 }
187 }
188 }
189 }