1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package com.xpn.xwiki.doc.rcs; |
21 |
|
|
22 |
|
import java.io.StringReader; |
23 |
|
import java.util.ArrayList; |
24 |
|
import java.util.BitSet; |
25 |
|
import java.util.Collection; |
26 |
|
import java.util.Date; |
27 |
|
import java.util.Iterator; |
28 |
|
import java.util.List; |
29 |
|
|
30 |
|
import org.apache.commons.codec.DecoderException; |
31 |
|
import org.apache.commons.codec.net.URLCodec; |
32 |
|
import org.apache.commons.lang3.StringUtils; |
33 |
|
import org.slf4j.Logger; |
34 |
|
import org.slf4j.LoggerFactory; |
35 |
|
import org.suigeneris.jrcs.diff.PatchFailedException; |
36 |
|
import org.suigeneris.jrcs.rcs.Archive; |
37 |
|
import org.suigeneris.jrcs.rcs.InvalidFileFormatException; |
38 |
|
import org.suigeneris.jrcs.rcs.InvalidTrunkVersionNumberException; |
39 |
|
import org.suigeneris.jrcs.rcs.Version; |
40 |
|
import org.suigeneris.jrcs.rcs.impl.Node; |
41 |
|
import org.suigeneris.jrcs.rcs.impl.NodeNotFoundException; |
42 |
|
import org.suigeneris.jrcs.rcs.impl.TrunkNode; |
43 |
|
import org.suigeneris.jrcs.rcs.parse.ParseException; |
44 |
|
import org.suigeneris.jrcs.util.ToString; |
45 |
|
|
46 |
|
import com.xpn.xwiki.XWikiContext; |
47 |
|
import com.xpn.xwiki.XWikiException; |
48 |
|
import com.xpn.xwiki.doc.XWikiDocument; |
49 |
|
|
50 |
|
|
51 |
|
@link |
52 |
|
|
53 |
|
@version |
54 |
|
@since |
55 |
|
|
|
|
| 98.6% |
Uncovered Elements: 1 (69) |
Complexity: 12 |
Complexity Density: 0.24 |
|
56 |
|
public class XWikiRCSArchive extends Archive |
57 |
|
{ |
58 |
|
|
59 |
|
private static final Logger LOGGER = LoggerFactory.getLogger(XWikiRCSArchive.class); |
60 |
|
|
61 |
|
|
62 |
|
@link |
63 |
|
|
64 |
|
@param@link |
65 |
|
@param |
66 |
|
@throws |
67 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (30) |
Complexity: 5 |
Complexity Density: 0.23 |
|
68 |
279 |
public XWikiRCSArchive(Collection<XWikiRCSNodeInfo> nodeInfos, XWikiContext context) throws XWikiException... |
69 |
|
{ |
70 |
279 |
super(new Object[0], ""); |
71 |
279 |
this.nodes.clear(); |
72 |
279 |
this.head = null; |
73 |
279 |
if (nodeInfos.size() > 0) { |
74 |
273 |
for (XWikiRCSNodeInfo nodeInfo : nodeInfos) { |
75 |
345 |
XWikiJRCSNode node = new XWikiJRCSNode(nodeInfo.getId().getVersion(), null); |
76 |
345 |
node.setAuthor(nodeInfo.getAuthor()); |
77 |
345 |
node.setDate(nodeInfo.getDate()); |
78 |
345 |
node.setLog(nodeInfo.getComment()); |
79 |
345 |
XWikiRCSNodeContent content = nodeInfo.getContent(context); |
80 |
|
|
81 |
345 |
node.setText(StringUtils.defaultString(content.getPatch().getContent())); |
82 |
345 |
node.setDiff(nodeInfo.isDiff()); |
83 |
345 |
this.nodes.put(node.getVersion(), node); |
84 |
|
} |
85 |
273 |
XWikiJRCSNode last = null; |
86 |
618 |
for (Iterator it = this.nodes.keySet().iterator(); it.hasNext();) { |
87 |
345 |
Version ver = (Version) it.next(); |
88 |
345 |
XWikiJRCSNode node = (XWikiJRCSNode) this.nodes.get(ver); |
89 |
345 |
if (last != null) { |
90 |
72 |
last.setRCSNext(node); |
91 |
|
} |
92 |
345 |
last = node; |
93 |
345 |
if (this.head == null) { |
94 |
273 |
this.head = node; |
95 |
|
} |
96 |
|
} |
97 |
|
} |
98 |
|
} |
99 |
|
|
100 |
|
|
101 |
|
@link |
102 |
|
|
103 |
|
@param |
104 |
|
@throws |
105 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
106 |
134 |
public XWikiRCSArchive(String archiveText) throws ParseException... |
107 |
|
{ |
108 |
134 |
super("", new StringReader(archiveText)); |
109 |
|
} |
110 |
|
|
111 |
|
|
112 |
|
@link@link |
113 |
|
|
|
|
| 74.3% |
Uncovered Elements: 18 (70) |
Complexity: 23 |
Complexity Density: 0.53 |
|
114 |
|
private static class XWikiJRCSNode extends TrunkNode |
115 |
|
{ |
116 |
|
|
117 |
|
public static String sauthorIfEmpty = "_"; |
118 |
|
|
119 |
|
|
120 |
|
public static String sfullVersion = "full"; |
121 |
|
|
122 |
|
|
123 |
|
public static String sdiffVersion = "diff"; |
124 |
|
|
125 |
|
|
126 |
|
@param |
127 |
|
@param |
128 |
|
@throws |
129 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
130 |
495 |
public XWikiJRCSNode(Version vernum, TrunkNode next)... |
131 |
|
throws InvalidTrunkVersionNumberException |
132 |
|
{ |
133 |
495 |
super(vernum, next); |
134 |
|
} |
135 |
|
|
136 |
|
@param |
|
|
| 100% |
Uncovered Elements: 0 (7) |
Complexity: 1 |
Complexity Density: 0.14 |
|
137 |
150 |
public XWikiJRCSNode(Node other)... |
138 |
|
{ |
139 |
150 |
this(other.version, null); |
140 |
150 |
this.setDate(other.getDate()); |
141 |
150 |
this.author = other.getAuthor(); |
142 |
150 |
this.setState(other.getState()); |
143 |
150 |
this.setLog(other.getLog()); |
144 |
150 |
this.setLocker(other.getLocker()); |
145 |
150 |
this.setText(other.getText()); |
146 |
|
} |
147 |
|
|
148 |
|
|
149 |
|
@param |
150 |
|
@see |
151 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
152 |
495 |
public void setDate(Date date)... |
153 |
|
{ |
154 |
495 |
this.date = date; |
155 |
|
} |
156 |
|
|
157 |
|
|
158 |
|
static BitSet safeAuthorChars = new BitSet(); |
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 2 |
Complexity Density: 0.5 |
|
159 |
14 |
static {... |
160 |
14 |
safeAuthorChars.set('-'); |
161 |
378 |
for (char c = 'A', c1 = 'a'; c <= 'Z'; c++, c1++) { |
162 |
364 |
safeAuthorChars.set(c); |
163 |
364 |
safeAuthorChars.set(c1); |
164 |
|
} |
165 |
|
} |
166 |
|
|
167 |
|
@param |
|
|
| 71.4% |
Uncovered Elements: 2 (7) |
Complexity: 3 |
Complexity Density: 0.6 |
|
168 |
345 |
@Override... |
169 |
|
public void setAuthor(String user) |
170 |
|
{ |
171 |
|
|
172 |
345 |
if (user == null || "".equals(user)) { |
173 |
0 |
super.setAuthor(sauthorIfEmpty); |
174 |
|
} else { |
175 |
345 |
byte[] enc = URLCodec.encodeUrl(safeAuthorChars, user.getBytes()); |
176 |
345 |
String senc = new String(enc).replace('%', '_'); |
177 |
345 |
super.setAuthor(senc); |
178 |
|
} |
179 |
|
} |
180 |
|
|
181 |
|
|
182 |
|
@return |
183 |
|
@see |
184 |
|
|
|
|
| 53.3% |
Uncovered Elements: 7 (15) |
Complexity: 4 |
Complexity Density: 0.36 |
|
185 |
149 |
public String getAuthor1()... |
186 |
|
{ |
187 |
149 |
String result = super.getAuthor(); |
188 |
149 |
if (sauthorIfEmpty.equals(result)) { |
189 |
0 |
return ""; |
190 |
|
} else { |
191 |
149 |
result = result.replace('_', '%'); |
192 |
149 |
try { |
193 |
149 |
byte[] dec = URLCodec.decodeUrl(result.getBytes()); |
194 |
149 |
result = new String(dec); |
195 |
|
} catch (DecoderException e) { |
196 |
|
|
197 |
0 |
result = super.getAuthor(); |
198 |
0 |
if (!result.matches("^(\\w|\\d|\\.)++$")) { |
199 |
|
|
200 |
0 |
result = ""; |
201 |
|
} |
202 |
|
} |
203 |
|
} |
204 |
149 |
return result; |
205 |
|
} |
206 |
|
|
207 |
|
@return |
|
|
| 100% |
Uncovered Elements: 0 (7) |
Complexity: 3 |
Complexity Density: 0.6 |
|
208 |
300 |
public boolean isDiff()... |
209 |
|
{ |
210 |
300 |
boolean isdiff = !sfullVersion.equals(getState()); |
211 |
300 |
if (getTextString() != null && isdiff != !getTextString().startsWith("<")) { |
212 |
2 |
LOGGER.warn("isDiff: Archive is inconsistent. Text and diff field are contradicting. version=" |
213 |
|
+ getVersion()); |
214 |
2 |
isdiff = !isdiff; |
215 |
|
} |
216 |
300 |
return isdiff; |
217 |
|
} |
218 |
|
|
219 |
|
@param |
|
|
| 62.5% |
Uncovered Elements: 3 (8) |
Complexity: 4 |
Complexity Density: 1 |
|
220 |
345 |
public void setDiff(boolean isdiff)... |
221 |
|
{ |
222 |
345 |
if (getTextString() != null && isdiff != !getTextString().startsWith("<")) { |
223 |
0 |
LOGGER.warn("setDiff: Archive is inconsistent. Text and diff field are contradicting. version=" |
224 |
|
+ getVersion()); |
225 |
0 |
isdiff = !isdiff; |
226 |
|
} |
227 |
345 |
setState(isdiff ? sdiffVersion : sfullVersion); |
228 |
|
} |
229 |
|
|
230 |
|
@return |
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
231 |
150 |
public boolean hasOldFormat()... |
232 |
|
{ |
233 |
150 |
return !sfullVersion.equals(getState()) && !sdiffVersion.equals(getState()); |
234 |
|
} |
235 |
|
|
236 |
|
|
237 |
|
@return |
238 |
|
@see |
239 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
240 |
1440 |
public String getTextString()... |
241 |
|
{ |
242 |
1440 |
return mergedText()[0].toString(); |
243 |
|
} |
244 |
|
|
|
|
| 0% |
Uncovered Elements: 5 (5) |
Complexity: 2 |
Complexity Density: 0.67 |
|
245 |
0 |
@Override... |
246 |
|
public void patch(List original, boolean annotate) throws InvalidFileFormatException, PatchFailedException |
247 |
|
{ |
248 |
0 |
if (isDiff()) { |
249 |
0 |
super.patch(original, annotate); |
250 |
|
} else { |
251 |
|
|
252 |
|
|
253 |
0 |
throw new IllegalArgumentException(); |
254 |
|
|
255 |
|
|
256 |
|
|
257 |
|
|
258 |
|
} |
259 |
|
} |
260 |
|
} |
261 |
|
|
262 |
|
|
263 |
|
@return@link@link |
264 |
|
@param@link |
265 |
|
@throws |
266 |
|
@throws |
267 |
|
@throws |
268 |
|
|
|
|
| 97% |
Uncovered Elements: 1 (33) |
Complexity: 5 |
Complexity Density: 0.19 |
|
269 |
134 |
public Collection getNodes(long docId) throws NodeNotFoundException, InvalidFileFormatException,... |
270 |
|
PatchFailedException |
271 |
|
{ |
272 |
134 |
Collection result = new ArrayList(this.nodes.values().size()); |
273 |
284 |
for (Iterator it = this.nodes.values().iterator(); it.hasNext();) { |
274 |
150 |
XWikiJRCSNode node = new XWikiJRCSNode((Node) it.next()); |
275 |
150 |
XWikiRCSNodeInfo nodeInfo = new XWikiRCSNodeInfo(); |
276 |
150 |
nodeInfo.setId(new XWikiRCSNodeId(docId, node.getVersion())); |
277 |
150 |
nodeInfo.setDiff(node.isDiff()); |
278 |
|
|
279 |
150 |
if (!node.hasOldFormat()) { |
280 |
149 |
nodeInfo.setAuthor(node.getAuthor1()); |
281 |
149 |
nodeInfo.setComment(node.getLog()); |
282 |
149 |
nodeInfo.setDate(node.getDate()); |
283 |
|
} else { |
284 |
|
|
285 |
|
|
286 |
1 |
try { |
287 |
1 |
String xml = getRevisionAsString(node.getVersion()); |
288 |
1 |
XWikiDocument doc = new XWikiDocument(); |
289 |
1 |
doc.fromXML(xml); |
290 |
|
|
291 |
1 |
nodeInfo.setAuthor(doc.getAuthor()); |
292 |
1 |
nodeInfo.setComment(doc.getComment()); |
293 |
1 |
nodeInfo.setDate(doc.getDate()); |
294 |
|
} catch (Exception e) { |
295 |
|
|
296 |
|
|
297 |
|
|
298 |
|
|
299 |
|
|
300 |
|
|
301 |
|
|
302 |
0 |
LOGGER.warn("Error in revision [" + node.getVersion().toString() + "]: [" + e.getMessage() |
303 |
|
+ "]. Ignoring non-fatal error, the Author, Comment and Date are not set."); |
304 |
|
} |
305 |
|
} |
306 |
|
|
307 |
150 |
XWikiRCSNodeContent content = new XWikiRCSNodeContent(nodeInfo.getId()); |
308 |
150 |
content.setPatch(new XWikiPatch(node.getTextString(), node.isDiff())); |
309 |
150 |
nodeInfo.setContent(content); |
310 |
150 |
result.add(nodeInfo); |
311 |
150 |
result.add(content); |
312 |
|
} |
313 |
|
|
314 |
134 |
if (result.size() > 0) { |
315 |
128 |
((XWikiRCSNodeInfo) ((ArrayList) result).get(0)).setDiff(false); |
316 |
128 |
((XWikiRCSNodeContent) ((ArrayList) result).get(1)).getPatch().setDiff(false); |
317 |
|
} |
318 |
134 |
return result; |
319 |
|
} |
320 |
|
|
321 |
|
|
322 |
|
@return |
323 |
|
@param |
324 |
|
@throws |
325 |
|
@throws |
326 |
|
@throws |
327 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
328 |
1 |
public String getRevisionAsString(Version version) throws NodeNotFoundException,... |
329 |
|
InvalidFileFormatException, PatchFailedException |
330 |
|
{ |
331 |
1 |
return ToString.arrayToString(super.getRevision(version), RCS_NEWLINE); |
332 |
|
} |
333 |
|
} |