1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.shared.release.transform.jdom2;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.StringReader;
24 import java.io.StringWriter;
25 import java.io.Writer;
26 import java.util.Iterator;
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
29
30 import org.apache.maven.model.Model;
31 import org.apache.maven.project.MavenProject;
32 import org.apache.maven.shared.release.ReleaseExecutionException;
33 import org.apache.maven.shared.release.config.ReleaseDescriptor;
34 import org.apache.maven.shared.release.transform.ModelETL;
35 import org.apache.maven.shared.release.util.ReleaseUtil;
36 import org.codehaus.plexus.util.WriterFactory;
37 import org.jdom2.CDATA;
38 import org.jdom2.Comment;
39 import org.jdom2.Document;
40 import org.jdom2.Element;
41 import org.jdom2.JDOMException;
42 import org.jdom2.Namespace;
43 import org.jdom2.filter.ContentFilter;
44 import org.jdom2.filter.ElementFilter;
45 import org.jdom2.input.SAXBuilder;
46 import org.jdom2.output.Format;
47 import org.jdom2.output.XMLOutputter;
48
49
50
51
52
53
54
55 public class JDomModelETL implements ModelETL {
56 private ReleaseDescriptor releaseDescriptor;
57
58 private MavenProject project;
59
60 private Document document;
61
62 private String intro = null;
63 private String outtro = null;
64
65 private String ls = ReleaseUtil.LS;
66
67
68
69
70
71
72 public void setLs(String ls) {
73 this.ls = ls;
74 }
75
76
77
78
79
80
81 public void setReleaseDescriptor(ReleaseDescriptor releaseDescriptor) {
82 this.releaseDescriptor = releaseDescriptor;
83 }
84
85
86
87
88
89
90 public void setProject(MavenProject project) {
91 this.project = project;
92 }
93
94 @Override
95 public void extract(File pomFile) throws ReleaseExecutionException {
96 try {
97 String content = ReleaseUtil.readXmlFile(pomFile, ls);
98
99 content = content.replaceAll("<([^!][^>]*?)\\s{2,}([^>]*?)>", "<$1 $2>");
100 content = content.replaceAll("(\\s{2,})/>", "$1 />");
101
102 SAXBuilder builder = new SAXBuilder();
103 document = builder.build(new StringReader(content));
104
105
106
107 normaliseLineEndings(document);
108
109
110 StringWriter w = new StringWriter();
111 Format format = Format.getRawFormat();
112 format.setLineSeparator(ls);
113 XMLOutputter out = new XMLOutputter(format);
114 out.output(document.getRootElement(), w);
115
116 int index = content.indexOf(w.toString());
117 if (index >= 0) {
118 intro = content.substring(0, index);
119 outtro = content.substring(index + w.toString().length());
120 } else {
121
122
123
124
125
126
127 final String SPACE = "\\s++";
128 final String XML = "<\\?(?:(?:[^\"'>]++)|(?:\"[^\"]*+\")|(?:'[^\']*+'))*+>";
129 final String INTSUB = "\\[(?:(?:[^\"'\\]]++)|(?:\"[^\"]*+\")|(?:'[^\']*+'))*+\\]";
130 final String DOCTYPE =
131 "<!DOCTYPE(?:(?:[^\"'\\[>]++)|(?:\"[^\"]*+\")|(?:'[^\']*+')|(?:" + INTSUB + "))*+>";
132 final String PI = XML;
133 final String COMMENT = "<!--(?:[^-]|(?:-[^-]))*+-->";
134
135 final String INTRO =
136 "(?:(?:" + SPACE + ")|(?:" + XML + ")|(?:" + DOCTYPE + ")|(?:" + COMMENT + ")|(?:" + PI + "))*";
137 final String OUTRO = "(?:(?:" + SPACE + ")|(?:" + COMMENT + ")|(?:" + PI + "))*";
138 final String POM = "(?s)(" + INTRO + ")(.*?)(" + OUTRO + ")";
139
140
141 Matcher matcher = Pattern.compile(POM).matcher(content);
142 if (matcher.matches()) {
143 intro = matcher.group(1);
144 outtro = matcher.group(matcher.groupCount());
145 }
146 }
147 } catch (JDOMException | IOException e) {
148 throw new ReleaseExecutionException("Error reading POM: " + e.getMessage(), e);
149 }
150 }
151
152 @Override
153 public void transform() {}
154
155 @Override
156 public void load(File targetFile) throws ReleaseExecutionException {
157 writePom(targetFile, document, releaseDescriptor, project.getModelVersion(), intro, outtro);
158 }
159
160 @Override
161 public Model getModel() {
162 return new JDomModel(document);
163 }
164
165 private void normaliseLineEndings(Document document) {
166 for (Iterator<?> i = document.getDescendants(new ContentFilter(ContentFilter.COMMENT)); i.hasNext(); ) {
167 Comment c = (Comment) i.next();
168 c.setText(ReleaseUtil.normalizeLineEndings(c.getText(), ls));
169 }
170 for (Iterator<?> i = document.getDescendants(new ContentFilter(ContentFilter.CDATA)); i.hasNext(); ) {
171 CDATA c = (CDATA) i.next();
172 c.setText(ReleaseUtil.normalizeLineEndings(c.getText(), ls));
173 }
174 }
175
176 private void writePom(
177 File pomFile,
178 Document document,
179 ReleaseDescriptor releaseDescriptor,
180 String modelVersion,
181 String intro,
182 String outtro)
183 throws ReleaseExecutionException {
184 Element rootElement = document.getRootElement();
185
186 if (releaseDescriptor.isAddSchema()) {
187 Namespace pomNamespace = Namespace.getNamespace("", "http://maven.apache.org/POM/" + modelVersion);
188 rootElement.setNamespace(pomNamespace);
189 Namespace xsiNamespace = Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
190 rootElement.addNamespaceDeclaration(xsiNamespace);
191
192 if (rootElement.getAttribute("schemaLocation", xsiNamespace) == null) {
193 rootElement.setAttribute(
194 "schemaLocation",
195 "http://maven.apache.org/POM/" + modelVersion + " https://maven.apache.org/xsd/maven-"
196 + modelVersion + ".xsd",
197 xsiNamespace);
198 }
199
200
201 ElementFilter elementFilter = new ElementFilter(Namespace.getNamespace(""));
202 for (Iterator<?> i = rootElement.getDescendants(elementFilter); i.hasNext(); ) {
203 Element e = (Element) i.next();
204 e.setNamespace(pomNamespace);
205 }
206 }
207
208 try (Writer writer = WriterFactory.newXmlWriter(pomFile)) {
209 if (intro != null) {
210 writer.write(intro);
211 }
212
213 Format format = Format.getRawFormat();
214 format.setLineSeparator(ls);
215 XMLOutputter out = new XMLOutputter(format);
216 out.output(document.getRootElement(), writer);
217
218 if (outtro != null) {
219 writer.write(outtro);
220 }
221 } catch (IOException e) {
222 throw new ReleaseExecutionException("Error writing POM: " + e.getMessage(), e);
223 }
224 }
225 }