1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.internal.impl.synccontext.named;
20
21 import java.util.Collection;
22 import java.util.stream.Collectors;
23
24 import org.eclipse.aether.RepositorySystemSession;
25 import org.eclipse.aether.artifact.Artifact;
26 import org.eclipse.aether.metadata.Metadata;
27 import org.eclipse.aether.util.ConfigUtils;
28 import org.eclipse.aether.util.StringDigestUtil;
29
30 import static java.util.Objects.requireNonNull;
31
32
33
34
35
36
37
38
39
40
41
42 public class HashingNameMapper implements NameMapper {
43 private static final String CONFIG_PROP_DEPTH = "aether.syncContext.named.hashing.depth";
44
45 private final NameMapper delegate;
46
47 public HashingNameMapper(final NameMapper delegate) {
48 this.delegate = requireNonNull(delegate);
49 }
50
51 @Override
52 public boolean isFileSystemFriendly() {
53 return true;
54 }
55
56 @Override
57 public Collection<String> nameLocks(
58 RepositorySystemSession session,
59 Collection<? extends Artifact> artifacts,
60 Collection<? extends Metadata> metadatas) {
61 final int depth = ConfigUtils.getInteger(session, 2, CONFIG_PROP_DEPTH);
62 if (depth < 0 || depth > 4) {
63 throw new IllegalArgumentException("allowed depth value is between 0 and 4 (inclusive)");
64 }
65 return delegate.nameLocks(session, artifacts, metadatas).stream()
66 .map(n -> hashName(n, depth))
67 .collect(Collectors.toList());
68 }
69
70 private String hashName(final String name, final int depth) {
71 String hashedName = StringDigestUtil.sha1(name);
72 if (depth == 0) {
73 return hashedName;
74 }
75 StringBuilder prefix = new StringBuilder("");
76 int i = 0;
77 while (i < hashedName.length() && i / 2 < depth) {
78 prefix.append(hashedName, i, i + 2).append("/");
79 i += 2;
80 }
81 return prefix.append(hashedName).toString();
82 }
83 }