1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.util.repository;
20
21 import java.util.Arrays;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.Locale;
26 import java.util.Map;
27 import java.util.concurrent.ConcurrentHashMap;
28 import java.util.function.Function;
29 import java.util.function.Predicate;
30
31 import org.eclipse.aether.RepositorySystemSession;
32 import org.eclipse.aether.repository.ArtifactRepository;
33 import org.eclipse.aether.repository.RemoteRepository;
34 import org.eclipse.aether.util.StringDigestUtil;
35
36 import static java.util.Objects.requireNonNull;
37
38
39
40
41
42
43
44
45
46 public final class RepositoryIdHelper {
47 private RepositoryIdHelper() {}
48
49 private static final Map<String, String> ILLEGAL_REPO_ID_REPLACEMENTS;
50
51 static {
52 HashMap<String, String> illegalRepoIdReplacements = new HashMap<>();
53 illegalRepoIdReplacements.put("\\", "-BACKSLASH-");
54 illegalRepoIdReplacements.put("/", "-SLASH-");
55 illegalRepoIdReplacements.put(":", "-COLON-");
56 illegalRepoIdReplacements.put("\"", "-QUOTE-");
57 illegalRepoIdReplacements.put("<", "-LT-");
58 illegalRepoIdReplacements.put(">", "-GT-");
59 illegalRepoIdReplacements.put("|", "-PIPE-");
60 illegalRepoIdReplacements.put("?", "-QMARK-");
61 illegalRepoIdReplacements.put("*", "-ASTERISK-");
62 ILLEGAL_REPO_ID_REPLACEMENTS = Collections.unmodifiableMap(illegalRepoIdReplacements);
63 }
64
65 private static final String CENTRAL_REPOSITORY_ID = "central";
66 private static final Collection<String> CENTRAL_URLS = Collections.unmodifiableList(Arrays.asList(
67 "https://repo.maven.apache.org/maven2",
68 "https://repo1.maven.org/maven2",
69 "https://maven-central.storage-download.googleapis.com/maven2"));
70 private static final Predicate<RemoteRepository> CENTRAL_DIRECT_ONLY =
71 remoteRepository -> CENTRAL_REPOSITORY_ID.equals(remoteRepository.getId())
72 && "https".equals(remoteRepository.getProtocol().toLowerCase(Locale.ENGLISH))
73 && CENTRAL_URLS.stream().anyMatch(remoteUrl -> {
74 String rurl = remoteRepository.getUrl().toLowerCase(Locale.ENGLISH);
75 if (rurl.endsWith("/")) {
76 rurl = rurl.substring(0, rurl.length() - 1);
77 }
78 return rurl.equals(remoteUrl);
79 })
80 && remoteRepository.getPolicy(false).isEnabled()
81 && !remoteRepository.getPolicy(true).isEnabled()
82 && remoteRepository.getMirroredRepositories().isEmpty()
83 && !remoteRepository.isRepositoryManager()
84 && !remoteRepository.isBlocked();
85
86
87
88
89
90
91
92
93
94
95 public static String remoteRepositoryUniqueId(RemoteRepository repository) {
96 if (CENTRAL_DIRECT_ONLY.test(repository)) {
97 return CENTRAL_REPOSITORY_ID;
98 } else {
99 StringBuilder buffer = new StringBuilder(256);
100 buffer.append(repository.getId());
101 buffer.append(" (").append(repository.getUrl());
102 buffer.append(", ").append(repository.getContentType());
103 boolean r = repository.getPolicy(false).isEnabled(),
104 s = repository.getPolicy(true).isEnabled();
105 if (r && s) {
106 buffer.append(", releases+snapshots");
107 } else if (r) {
108 buffer.append(", releases");
109 } else if (s) {
110 buffer.append(", snapshots");
111 } else {
112 buffer.append(", disabled");
113 }
114 if (repository.isRepositoryManager()) {
115 buffer.append(", managed(");
116 for (RemoteRepository mirroredRepo : repository.getMirroredRepositories()) {
117 buffer.append(remoteRepositoryUniqueId(mirroredRepo));
118 }
119 buffer.append(")");
120 }
121 if (repository.isBlocked()) {
122 buffer.append(", blocked");
123 }
124 buffer.append(")");
125 return idToPathSegment(repository) + "-" + StringDigestUtil.sha1(buffer.toString());
126 }
127 }
128
129
130
131
132 @SuppressWarnings("unchecked")
133 public static Function<ArtifactRepository, String> cachedIdToPathSegment(RepositorySystemSession session) {
134 requireNonNull(session, "session");
135 return (Function<ArtifactRepository, String>) session.getData()
136 .computeIfAbsent(
137 RepositoryIdHelper.class.getSimpleName() + "-idToPathSegmentFunction",
138 () -> cachedIdToPathSegmentFunction(session));
139 }
140
141
142
143
144
145 @SuppressWarnings("unchecked")
146 private static Function<ArtifactRepository, String> cachedIdToPathSegmentFunction(RepositorySystemSession session) {
147 if (session.getCache() != null) {
148 return repository -> ((ConcurrentHashMap<String, String>) session.getCache()
149 .computeIfAbsent(
150 session,
151 RepositoryIdHelper.class.getSimpleName() + "-idToPathSegmentCache",
152 ConcurrentHashMap::new))
153 .computeIfAbsent(repository.getId(), id -> idToPathSegment(repository));
154 } else {
155 return RepositoryIdHelper::idToPathSegment;
156 }
157 }
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 static String idToPathSegment(ArtifactRepository repository) {
173 if (repository instanceof RemoteRepository) {
174 StringBuilder result = new StringBuilder(repository.getId());
175 for (Map.Entry<String, String> entry : ILLEGAL_REPO_ID_REPLACEMENTS.entrySet()) {
176 String illegal = entry.getKey();
177 int pos = result.indexOf(illegal);
178 while (pos >= 0) {
179 result.replace(pos, pos + illegal.length(), entry.getValue());
180 pos = result.indexOf(illegal);
181 }
182 }
183 return result.toString();
184 } else {
185 return repository.getId();
186 }
187 }
188 }