1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.index.reader;
20
21 import java.io.Closeable;
22 import java.io.IOException;
23 import java.text.ParseException;
24 import java.util.Date;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.util.Properties;
28 import java.util.UUID;
29 import java.util.concurrent.atomic.AtomicBoolean;
30
31 import org.apache.maven.index.reader.WritableResourceHandler.WritableResource;
32
33 import static java.util.Objects.requireNonNull;
34 import static org.apache.maven.index.reader.Utils.loadProperties;
35 import static org.apache.maven.index.reader.Utils.storeProperties;
36
37
38
39
40
41
42
43
44
45
46
47 public class IndexWriter implements Closeable {
48 private static final int INDEX_V1 = 1;
49
50 private final AtomicBoolean closed;
51
52 private final WritableResourceHandler local;
53
54 private final Properties localIndexProperties;
55
56 private final boolean incremental;
57
58 private final String nextChunkCounter;
59
60 private final String nextChunkName;
61
62 public IndexWriter(final WritableResourceHandler local, final String indexId, final boolean incrementalSupported)
63 throws IOException {
64 requireNonNull(local, "local resource handler null");
65 requireNonNull(indexId, "indexId null");
66 this.closed = new AtomicBoolean(false);
67 this.local = local;
68 Properties indexProperties = loadProperties(local.locate(Utils.INDEX_FILE_PREFIX + ".properties"));
69 if (incrementalSupported && indexProperties != null) {
70 this.localIndexProperties = indexProperties;
71
72 String localIndexId = localIndexProperties.getProperty("nexus.index.id");
73 if (localIndexId == null || !localIndexId.equals(indexId)) {
74 throw new IllegalArgumentException(
75 "index already exists and indexId mismatch or unreadable: " + localIndexId + ", " + indexId);
76 }
77 this.incremental = true;
78 this.nextChunkCounter = calculateNextChunkCounter();
79 this.nextChunkName = Utils.INDEX_FILE_PREFIX + "." + nextChunkCounter + ".gz";
80 } else {
81
82 this.localIndexProperties = new Properties();
83 this.localIndexProperties.setProperty("nexus.index.id", indexId);
84 this.localIndexProperties.setProperty(
85 "nexus.index.chain-id", UUID.randomUUID().toString());
86 this.incremental = false;
87 this.nextChunkCounter = null;
88 this.nextChunkName = Utils.INDEX_FILE_PREFIX + ".gz";
89 }
90 }
91
92
93
94
95 public String getIndexId() {
96 return localIndexProperties.getProperty("nexus.index.id");
97 }
98
99
100
101
102
103
104 public Date getPublishedTimestamp() {
105 try {
106 String timestamp = localIndexProperties.getProperty("nexus.index.timestamp");
107 if (timestamp != null) {
108 return Utils.INDEX_DATE_FORMAT.parse(timestamp);
109 }
110 return null;
111 } catch (ParseException e) {
112 throw new RuntimeException("Corrupt date", e);
113 }
114 }
115
116
117
118
119 public boolean isIncremental() {
120 return incremental;
121 }
122
123
124
125
126
127 public String getChainId() {
128 return localIndexProperties.getProperty("nexus.index.chain-id");
129 }
130
131
132
133
134 public String getNextChunkName() {
135 return nextChunkName;
136 }
137
138
139
140
141 public int writeChunk(final Iterator<Map<String, String>> iterator) throws IOException {
142 int written;
143
144 try (WritableResource writableResource = local.locate(nextChunkName)) {
145 try (ChunkWriter chunkWriter =
146 new ChunkWriter(nextChunkName, writableResource.write(), INDEX_V1, new Date())) {
147 written = chunkWriter.writeChunk(iterator);
148 }
149 if (incremental) {
150
151 }
152 return written;
153 }
154 }
155
156
157
158
159
160
161
162 @Override
163 public void close() throws IOException {
164 if (closed.compareAndSet(false, true)) {
165 try {
166 if (incremental) {
167 localIndexProperties.setProperty("nexus.index.last-incremental", nextChunkCounter);
168 }
169 localIndexProperties.setProperty("nexus.index.timestamp", Utils.INDEX_DATE_FORMAT.format(new Date()));
170 storeProperties(local.locate(Utils.INDEX_FILE_PREFIX + ".properties"), localIndexProperties);
171 } finally {
172 local.close();
173 }
174 }
175 }
176
177
178
179
180 private String calculateNextChunkCounter() {
181 String lastChunkCounter = localIndexProperties.getProperty("nexus.index.last-incremental");
182 if (lastChunkCounter != null) {
183 return String.valueOf(Integer.parseInt(lastChunkCounter) + 1);
184 } else {
185 return "1";
186 }
187 }
188 }