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
44
45
46
47
48
49
50 public static final String CONFIG_PROP_DEPTH = NamedLockFactoryAdapter.CONFIG_PROPS_PREFIX + "hashing.depth";
51
52 public static final int DEFAULT_DEPTH = 2;
53
54 private final NameMapper delegate;
55
56 public HashingNameMapper(final NameMapper delegate) {
57 this.delegate = requireNonNull(delegate);
58 }
59
60 @Override
61 public boolean isFileSystemFriendly() {
62 return true;
63 }
64
65 @Override
66 public Collection<String> nameLocks(
67 RepositorySystemSession session,
68 Collection<? extends Artifact> artifacts,
69 Collection<? extends Metadata> metadatas) {
70 final int depth = ConfigUtils.getInteger(session, DEFAULT_DEPTH, CONFIG_PROP_DEPTH);
71 if (depth < 0 || depth > 4) {
72 throw new IllegalArgumentException("allowed depth value is between 0 and 4 (inclusive)");
73 }
74 return delegate.nameLocks(session, artifacts, metadatas).stream()
75 .map(n -> hashName(n, depth))
76 .collect(Collectors.toList());
77 }
78
79 private String hashName(final String name, final int depth) {
80 String hashedName = StringDigestUtil.sha1(name);
81 if (depth == 0) {
82 return hashedName;
83 }
84 StringBuilder prefix = new StringBuilder();
85 int i = 0;
86 while (i < hashedName.length() && i / 2 < depth) {
87 prefix.append(hashedName, i, i + 2).append("/");
88 i += 2;
89 }
90 return prefix.append(hashedName).toString();
91 }
92 }