1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.linecorp.centraldogma.server.internal.storage.repository;
18
19 import java.util.Collections;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23 import java.util.concurrent.locks.Lock;
24 import java.util.concurrent.locks.ReentrantLock;
25
26 import javax.annotation.Nullable;
27
28 import com.fasterxml.jackson.databind.JsonNode;
29 import com.google.common.collect.ImmutableList;
30 import com.google.common.collect.ImmutableSet;
31
32 import com.linecorp.centraldogma.common.Entry;
33 import com.linecorp.centraldogma.common.Revision;
34 import com.linecorp.centraldogma.internal.Jackson;
35 import com.linecorp.centraldogma.server.mirror.Mirror;
36 import com.linecorp.centraldogma.server.mirror.MirrorCredential;
37 import com.linecorp.centraldogma.server.storage.project.Project;
38 import com.linecorp.centraldogma.server.storage.repository.MetaRepository;
39 import com.linecorp.centraldogma.server.storage.repository.Repository;
40
41 public final class DefaultMetaRepository extends RepositoryWrapper implements MetaRepository {
42
43 public static final String PATH_CREDENTIALS = "/credentials.json";
44
45 public static final String PATH_MIRRORS = "/mirrors.json";
46
47 public static final Set<String> metaRepoFiles = ImmutableSet.of(PATH_CREDENTIALS, PATH_MIRRORS);
48
49 private static final String PATH_CREDENTIALS_AND_MIRRORS = PATH_CREDENTIALS + ',' + PATH_MIRRORS;
50
51 private final Lock mirrorLock = new ReentrantLock();
52
53
54
55
56 private int mirrorRev = -1;
57
58
59
60
61 private Set<String> mirrorRepos = Collections.emptySet();
62
63 @Nullable
64 private Set<Mirror> mirrors;
65
66 public DefaultMetaRepository(Repository repo) {
67 super(repo);
68 }
69
70 @Override
71 public Set<Mirror> mirrors() {
72 mirrorLock.lock();
73 try {
74 final int headRev = normalizeNow(Revision.HEAD).major();
75 final Set<String> repos = parent().repos().list().keySet();
76 if (headRev > mirrorRev || !mirrorRepos.equals(repos)) {
77 mirrors = loadMirrors(headRev);
78 mirrorRev = headRev;
79 mirrorRepos = repos;
80 }
81
82 return mirrors;
83 } finally {
84 mirrorLock.unlock();
85 }
86 }
87
88 private Set<Mirror> loadMirrors(int rev) {
89
90 final Map<String, Entry<?>> entries =
91 find(new Revision(rev), PATH_CREDENTIALS_AND_MIRRORS, Collections.emptyMap()).join();
92
93 if (!entries.containsKey(PATH_MIRRORS)) {
94 return Collections.emptySet();
95 }
96
97 final JsonNode mirrorsJson = (JsonNode) entries.get(PATH_MIRRORS).content();
98 if (!mirrorsJson.isArray()) {
99 throw new RepositoryMetadataException(
100 PATH_MIRRORS + " must be an array: " + mirrorsJson.getNodeType());
101 }
102
103 if (mirrorsJson.size() == 0) {
104 return Collections.emptySet();
105 }
106
107 try {
108 final List<MirrorCredential> credentials = loadCredentials(entries);
109 final ImmutableSet.Builder<Mirror> mirrors = ImmutableSet.builder();
110
111 for (JsonNode m : mirrorsJson) {
112 final MirrorConfig c = Jackson.treeToValue(m, MirrorConfig.class);
113 if (c == null) {
114 throw new RepositoryMetadataException(PATH_MIRRORS + " contains null.");
115 }
116 final Mirror mirror = c.toMirror(parent(), credentials);
117 if (mirror != null) {
118 mirrors.add(mirror);
119 }
120 }
121
122 return mirrors.build();
123 } catch (RepositoryMetadataException e) {
124 throw e;
125 } catch (Exception e) {
126 throw new RepositoryMetadataException("failed to load the mirror configuration", e);
127 }
128 }
129
130 private static List<MirrorCredential> loadCredentials(Map<String, Entry<?>> entries) throws Exception {
131 final Entry<?> e = entries.get(PATH_CREDENTIALS);
132 if (e == null) {
133 return Collections.emptyList();
134 }
135
136 final JsonNode credentialsJson = (JsonNode) e.content();
137 if (!credentialsJson.isArray()) {
138 throw new RepositoryMetadataException(
139 PATH_CREDENTIALS + " must be an array: " + credentialsJson.getNodeType());
140 }
141
142 if (credentialsJson.size() == 0) {
143 return Collections.emptyList();
144 }
145
146 final ImmutableList.Builder<MirrorCredential> builder = ImmutableList.builder();
147 for (JsonNode c : credentialsJson) {
148 final MirrorCredential credential = Jackson.treeToValue(c, MirrorCredential.class);
149 if (credential == null) {
150 throw new RepositoryMetadataException(PATH_CREDENTIALS + " contains null.");
151 }
152 builder.add(credential);
153 }
154
155 return builder.build();
156 }
157 }