1 package net.sf.statsvn.input;
2
3 import java.util.Collection;
4 import java.util.HashMap;
5 import java.util.Iterator;
6 import java.util.Map;
7
8 import javax.xml.parsers.DocumentBuilder;
9 import javax.xml.parsers.DocumentBuilderFactory;
10 import javax.xml.parsers.ParserConfigurationException;
11
12 import net.sf.statcvs.output.ConfigurationOptions;
13 import net.sf.statsvn.output.SvnConfigurationOptions;
14
15 import org.w3c.dom.Document;
16 import org.w3c.dom.Element;
17 import org.w3c.dom.NodeList;
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 public class CacheBuilder {
38 private final SvnLogBuilder builder;
39
40 private final RepositoryFileManager repositoryFileManager;
41
42 private Element currentPath = null;
43
44 private Document document = null;
45
46 private String currentFilename;
47
48 private Element cache = null;
49
50
51
52
53
54
55
56
57 public CacheBuilder(final SvnLogBuilder builder, final RepositoryFileManager repositoryFileManager) {
58 this.builder = builder;
59 this.repositoryFileManager = repositoryFileManager;
60 }
61
62
63
64
65
66
67
68
69
70
71
72
73
74 private void addDOMPath(final String name, final String latestRevision, final String binaryStatus) {
75 currentPath = document.createElement(CacheConfiguration.PATH);
76 currentPath.setAttribute(CacheConfiguration.NAME, name);
77 currentPath.setAttribute(CacheConfiguration.LATEST_REVISION, latestRevision);
78 currentPath.setAttribute(CacheConfiguration.BINARY_STATUS, binaryStatus);
79 cache.appendChild(currentPath);
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94 private void updateDOMPath(final Element path, final boolean isBinary, final String revisionNumber) {
95 int oldRevision = 0;
96 int newRevision = -1;
97 try {
98 oldRevision = Integer.parseInt(path.getAttribute(CacheConfiguration.LATEST_REVISION));
99 newRevision = Integer.parseInt(revisionNumber);
100 } catch (final NumberFormatException e) {
101 SvnConfigurationOptions.getTaskLogger().log(
102 "Ignoring invalid revision number " + revisionNumber + " for " + path.getAttribute(CacheConfiguration.NAME));
103 newRevision = -1;
104 }
105 String binaryStatus = CacheConfiguration.NOT_BINARY;
106 if (isBinary) {
107 binaryStatus = CacheConfiguration.BINARY;
108 }
109 if (newRevision >= oldRevision) {
110 path.setAttribute(CacheConfiguration.LATEST_REVISION, revisionNumber);
111 path.setAttribute(CacheConfiguration.BINARY_STATUS, binaryStatus);
112 }
113 }
114
115
116
117
118
119
120
121
122 private Element findDOMPath(final String name) {
123 if (currentPath != null && name.equals(currentPath.getAttribute(CacheConfiguration.NAME))) {
124 return currentPath;
125 }
126 final NodeList paths = cache.getChildNodes();
127 for (int i = 0; i < paths.getLength(); i++) {
128 final Element path = (Element) paths.item(i);
129 if (name.equals(path.getAttribute(CacheConfiguration.NAME))) {
130 return path;
131 }
132 }
133 return null;
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147 private void addDOMRevision(final String number, final String added, final String removed, final String binaryStatus) {
148 final Element revision = document.createElement(CacheConfiguration.REVISION);
149 revision.setAttribute(CacheConfiguration.NUMBER, number);
150 revision.setAttribute(CacheConfiguration.ADDED, added);
151 revision.setAttribute(CacheConfiguration.REMOVED, removed);
152 revision.setAttribute(CacheConfiguration.BINARY_STATUS, binaryStatus);
153 currentPath.appendChild(revision);
154 }
155
156
157
158
159
160
161
162
163 public void buildPath(final String name, final String revision, final String binaryStatus) {
164 currentFilename = repositoryFileManager.absoluteToRelativePath(name);
165 addDOMPath(name, revision, binaryStatus);
166
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184 public void buildRevision(final String number, final String added, final String removed, final String binaryStatus) {
185 if (!added.equals("-1") && !removed.equals("-1")) {
186 addDOMRevision(number, added, removed, binaryStatus);
187 builder.updateRevision(currentFilename, number, Integer.parseInt(added), Integer.parseInt(removed));
188 }
189 }
190
191
192
193
194
195
196 public void buildRoot() throws ParserConfigurationException {
197 final DocumentBuilderFactory factoryDOM = DocumentBuilderFactory.newInstance();
198 DocumentBuilder builderDOM;
199 builderDOM = factoryDOM.newDocumentBuilder();
200 document = builderDOM.newDocument();
201 cache = document.createElement(CacheConfiguration.CACHE);
202 cache.setAttribute(CacheConfiguration.PROJECT, ConfigurationOptions.getProjectName());
203 cache.setAttribute(CacheConfiguration.XML_VERSION, "1.0");
204 document.appendChild(cache);
205 }
206
207
208
209
210
211
212 public Document getDocument() {
213 return document;
214 }
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233 public synchronized void newRevision(String name, final String number, final String added, final String removed, final boolean binaryStatus) {
234 name = repositoryFileManager.relativeToAbsolutePath(name);
235 checkDocument();
236 if (document != null) {
237 currentPath = findDOMPath(name);
238 if (currentPath == null) {
239
240 addDOMPath(name, "0", CacheConfiguration.UNKNOWN);
241 }
242 String sBinaryStatus = CacheConfiguration.NOT_BINARY;
243 if (binaryStatus) {
244 sBinaryStatus = CacheConfiguration.BINARY;
245 }
246 addDOMRevision(number, added, removed, sBinaryStatus);
247 }
248 }
249
250 private void checkDocument() {
251 if (document == null) {
252 try {
253 buildRoot();
254 } catch (final ParserConfigurationException e) {
255 document = null;
256 }
257 }
258 }
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273 public void updateBinaryStatus(final Collection fileBuilders, final String revisionNumber) {
274
275 final Map mFileBuilders = new HashMap();
276 for (final Iterator iter = fileBuilders.iterator(); iter.hasNext();) {
277 final FileBuilder fileBuilder = (FileBuilder) iter.next();
278 mFileBuilders.put(fileBuilder.getName(), fileBuilder);
279 }
280 if (!mFileBuilders.isEmpty()) {
281
282
283
284
285 checkDocument();
286 final NodeList paths = cache.getChildNodes();
287 for (int i = 0; i < paths.getLength(); i++) {
288 final Element path = (Element) paths.item(i);
289 if (mFileBuilders.containsKey(repositoryFileManager.absoluteToRelativePath(path.getAttribute(CacheConfiguration.NAME)))) {
290 final FileBuilder fileBuilder = (FileBuilder) mFileBuilders.get(repositoryFileManager.absoluteToRelativePath(path
291 .getAttribute(CacheConfiguration.NAME)));
292 updateDOMPath(path, fileBuilder.isBinary(), revisionNumber);
293 mFileBuilders.remove(repositoryFileManager.absoluteToRelativePath(path.getAttribute(CacheConfiguration.NAME)));
294 }
295 }
296
297 final Collection cFileBuilders = mFileBuilders.values();
298 for (final Iterator iter = cFileBuilders.iterator(); iter.hasNext();) {
299 final FileBuilder fileBuilder = (FileBuilder) iter.next();
300 String binaryStatus = CacheConfiguration.NOT_BINARY;
301 if (fileBuilder.isBinary()) {
302 binaryStatus = CacheConfiguration.BINARY;
303 }
304 addDOMPath(repositoryFileManager.relativeToAbsolutePath(fileBuilder.getName()), revisionNumber, binaryStatus);
305 }
306 }
307
308 }
309
310
311
312
313
314
315
316
317
318
319
320 public synchronized boolean isBinary(final String fileName, final String revisionNumber) {
321 int latestRevision = 0;
322 int revisionToCheck = -1;
323 checkDocument();
324 final Element path = findDOMPath(repositoryFileManager.relativeToAbsolutePath(fileName));
325 if (path == null) {
326 return false;
327 }
328 try {
329 latestRevision = Integer.parseInt(path.getAttribute(CacheConfiguration.LATEST_REVISION));
330 revisionToCheck = Integer.parseInt(revisionNumber);
331 } catch (final NumberFormatException e) {
332 SvnConfigurationOptions.getTaskLogger().log(
333 "Ignoring invalid revision number " + revisionNumber + " for " + path.getAttribute(CacheConfiguration.NAME));
334 revisionToCheck = -1;
335 }
336 if (latestRevision >= revisionToCheck) {
337 final String binaryStatus = path.getAttribute(CacheConfiguration.BINARY_STATUS);
338 if (binaryStatus.equals(CacheConfiguration.BINARY)) {
339 return true;
340 }
341 }
342 return false;
343 }
344 }