1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.site;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.Reader;
25 import java.io.StringReader;
26 import java.io.StringWriter;
27 import java.util.HashMap;
28 import java.util.Locale;
29 import java.util.Map;
30
31 import javax.swing.text.html.HTML.Attribute;
32
33 import org.apache.maven.doxia.macro.MacroExecutionException;
34 import org.apache.maven.doxia.macro.MacroRequest;
35 import org.apache.maven.doxia.macro.manager.MacroNotFoundException;
36 import org.apache.maven.doxia.module.xdoc.XdocParser;
37 import org.apache.maven.doxia.parser.ParseException;
38 import org.apache.maven.doxia.parser.Parser;
39 import org.apache.maven.doxia.sink.Sink;
40 import org.codehaus.plexus.component.annotations.Component;
41 import org.codehaus.plexus.util.IOUtil;
42 import org.codehaus.plexus.util.xml.pull.XmlPullParser;
43
44
45
46
47
48
49
50
51
52
53
54
55
56 @Component(role = Parser.class, hint = "xdocs-template")
57 public class XdocsTemplateParser extends XdocParser {
58
59
60 public static final String TEMP_DIR = System.getProperty("java.io.tmpdir");
61
62
63 private final Map<String, Object> macroParameters = new HashMap<>();
64
65
66 private String sourceContent;
67
68
69 private String macroName;
70
71 @Override
72 public void parse(Reader source, Sink sink, String reference) throws ParseException {
73 try (StringWriter contentWriter = new StringWriter()) {
74 IOUtil.copy(source, contentWriter);
75 sourceContent = contentWriter.toString();
76 super.parse(new StringReader(sourceContent), sink, reference);
77 }
78 catch (IOException ioException) {
79 throw new ParseException("Error reading the input source", ioException);
80 }
81 finally {
82 sourceContent = null;
83 }
84 }
85
86 @Override
87 protected void handleStartTag(XmlPullParser parser, Sink sink) throws MacroExecutionException {
88 final String tagName = parser.getName();
89 if (tagName.equals(DOCUMENT_TAG.toString())) {
90 sink.body();
91 sink.rawText(parser.getText());
92 }
93 else if (tagName.equals(MACRO_TAG.toString()) && !isSecondParsing()) {
94 processMacroStart(parser);
95 setIgnorableWhitespace(true);
96 }
97 else if (tagName.equals(PARAM.toString()) && !isSecondParsing()) {
98 processParamStart(parser, sink);
99 }
100 else {
101 sink.rawText(parser.getText());
102 }
103 }
104
105 @Override
106 protected void handleEndTag(XmlPullParser parser, Sink sink) throws MacroExecutionException {
107 final String tagName = parser.getName();
108 if (!"hr".equalsIgnoreCase(tagName)) {
109 if (tagName.equals(DOCUMENT_TAG.toString())) {
110 sink.rawText(parser.getText());
111 sink.body_();
112 }
113 else if (macroName != null
114 && tagName.equals(MACRO_TAG.toString())
115 && !macroName.isEmpty()
116 && !isSecondParsing()) {
117 processMacroEnd(sink);
118 setIgnorableWhitespace(false);
119 }
120 else if (!tagName.equals(PARAM.toString())) {
121 sink.rawText(parser.getText());
122 }
123 }
124 }
125
126
127
128
129
130
131
132 private void processMacroStart(XmlPullParser parser) throws MacroExecutionException {
133 macroName = parser.getAttributeValue(null, Attribute.NAME.toString());
134
135 if (macroName == null || macroName.isEmpty()) {
136 final String message = String.format(Locale.ROOT,
137 "The '%s' attribute for the '%s' tag is required.",
138 Attribute.NAME, MACRO_TAG);
139 throw new MacroExecutionException(message);
140 }
141 }
142
143
144
145
146
147
148
149
150 private void processParamStart(XmlPullParser parser, Sink sink) throws MacroExecutionException {
151 if (macroName != null && !macroName.isEmpty()) {
152 final String paramName = parser
153 .getAttributeValue(null, Attribute.NAME.toString());
154 final String paramValue = parser
155 .getAttributeValue(null, Attribute.VALUE.toString());
156
157 if (paramName == null
158 || paramValue == null
159 || paramName.isEmpty()
160 || paramValue.isEmpty()) {
161 final String message = String.format(Locale.ROOT,
162 "'%s' and '%s' attributes for the '%s' tag are required"
163 + " inside the '%s' tag.",
164 Attribute.NAME, Attribute.VALUE, PARAM, MACRO_TAG);
165 throw new MacroExecutionException(message);
166 }
167
168 macroParameters.put(paramName, paramValue);
169 }
170 else {
171 sink.rawText(parser.getText());
172 }
173 }
174
175
176
177
178
179
180
181
182
183 private void processMacroEnd(Sink sink) throws MacroExecutionException {
184 final MacroRequest request = new MacroRequest(sourceContent,
185 new XdocsTemplateParser(), macroParameters,
186 new File(TEMP_DIR));
187
188 try {
189 executeMacro(macroName, request, sink);
190 }
191 catch (MacroNotFoundException exception) {
192 final String message = String.format(Locale.ROOT, "Macro '%s' not found.", macroName);
193 throw new MacroExecutionException(message, exception);
194 }
195
196 reinitializeMacroFields();
197 }
198
199
200
201
202 private void reinitializeMacroFields() {
203 macroName = "";
204 macroParameters.clear();
205 }
206 }