forked from jenkinsci/multiple-scms-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMultiSCMChangeLogParser.java
161 lines (136 loc) · 5.92 KB
/
MultiSCMChangeLogParser.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package org.jenkinsci.plugins.multiplescms;
import hudson.model.AbstractBuild;
import hudson.scm.ChangeLogParser;
import hudson.scm.ChangeLogSet;
import hudson.scm.ChangeLogSet.Entry;
import hudson.scm.RepositoryBrowser;
import hudson.scm.SCM;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.commons.lang.StringEscapeUtils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MultiSCMChangeLogParser extends ChangeLogParser {
public static final String ROOT_XML_TAG = "multi-scm-log";
public static final String SUB_LOG_TAG = "sub-log";
private final Map<String, ChangeLogParser> scmLogParsers;
private final Map<String, String> scmDisplayNames;
private final Map<String, RepositoryBrowser<?>> scmRepositoryBrowsers;
public MultiSCMChangeLogParser(List<SCM> scms) {
scmLogParsers = new HashMap<String, ChangeLogParser>();
scmDisplayNames = new HashMap<String, String>();
scmRepositoryBrowsers = new HashMap<String, RepositoryBrowser<?>>();
for(SCM scm : scms) {
String key = scm.getKey();
if(!scmLogParsers.containsKey(key)) {
scmLogParsers.put(key, scm.createChangeLogParser());
String displayName = scm.getDescriptor().getDisplayName();
if (key != displayName) {
displayName = String.format("%s (%s)", displayName, key);
}
scmDisplayNames.put(key, displayName);
scmRepositoryBrowsers.put(key, scm.getBrowser());
}
}
}
private class LogSplitter extends DefaultHandler {
private final MultiSCMChangeLogSet changeLogs;
private final AbstractBuild build;
private final File tempFile;
private String scmClass;
private StringBuffer buffer;
public LogSplitter(AbstractBuild build, String tempFilePath) {
changeLogs = new MultiSCMChangeLogSet(build);
this.tempFile= new File(tempFilePath);
this.build = build;
}
@Override
public void characters(char[] data, int startIndex, int length)
throws SAXException {
if(buffer != null) {
while(length > 0 && Character.isWhitespace(data[startIndex])) {
startIndex += 1;
length -= 1;
}
for (int i = 0; i < length; i++) {
buffer.append(data[startIndex + i]);
}
}
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attrs) throws SAXException {
if(qName.compareTo(SUB_LOG_TAG) == 0) {
scmClass = attrs.getValue("scm");
buffer = new StringBuffer();
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if(qName.compareTo(SUB_LOG_TAG) == 0) {
try {
OutputStreamWriter outputStream = new OutputStreamWriter(new FileOutputStream(tempFile));
//un-escaping the XMl so it is written to the temp file correctly
String data = StringEscapeUtils.unescapeXml(buffer.toString());
outputStream.write(data);
outputStream.close();
buffer = null;
ChangeLogParser parser = scmLogParsers.get(scmClass);
/*
* Due to XSTREAM serialization scmRepositoryBrowsers may be null.
*/
RepositoryBrowser<?> browser = null;
if (scmRepositoryBrowsers != null) {
browser = scmRepositoryBrowsers.get(scmClass);
}
if(parser != null) {
ChangeLogSet<? extends ChangeLogSet.Entry> cls;
if (browser != null) {
cls = parser.parse(build, browser, tempFile);
} else {
cls = parser.parse(build, tempFile);
}
changeLogs.add(scmClass, scmDisplayNames.get(scmClass), cls);
}
} catch (RuntimeException e) {
throw new SAXException("could not parse changelog file", e);
} catch (FileNotFoundException e) {
throw new SAXException("could not create temp changelog file", e);
} catch (IOException e) {
throw new SAXException("could not close temp changelog file", e);
}
}
}
public ChangeLogSet<? extends Entry> getChangeLogSets() {
return changeLogs;
}
}
@Override
public ChangeLogSet<? extends Entry> parse(AbstractBuild build, File changelogFile)
throws IOException, SAXException {
if(scmLogParsers == null)
return ChangeLogSet.createEmpty(build);
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(true);
SAXParser parser;
try {
parser = factory.newSAXParser();
} catch (ParserConfigurationException e) {
throw new SAXException("Could not create parser", e);
}
LogSplitter splitter = new LogSplitter(build, changelogFile.getPath() + ".temp2");
parser.parse(changelogFile, splitter);
return splitter.getChangeLogSets();
}
}