1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.smartics.maven.plugin.buildmetadata;
17
18 import java.io.BufferedInputStream;
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.util.Enumeration;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.MissingResourceException;
27 import java.util.Properties;
28 import java.util.ResourceBundle;
29 import java.util.Set;
30 import java.util.StringTokenizer;
31
32 import org.apache.commons.io.IOUtils;
33 import org.apache.maven.doxia.sink.Sink;
34 import org.apache.maven.reporting.MavenReportException;
35 import org.codehaus.plexus.util.StringUtils;
36
37 import de.smartics.maven.plugin.buildmetadata.common.Constant;
38 import de.smartics.maven.plugin.buildmetadata.common.Property;
39 import de.smartics.maven.plugin.buildmetadata.common.Constant.Section;
40
41
42
43
44
45
46
47 public final class BuildReportRenderer
48 {
49
50
51
52
53
54
55
56
57
58 private final Sink sink;
59
60
61
62
63 private final ResourceBundle messages;
64
65
66
67
68 private final File buildMetaDataPropertiesFile;
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 private final List<Property> properties;
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 public BuildReportRenderer(final ResourceBundle messages, final Sink sink,
110 final File buildMetaDataPropertiesFile, final List<Property> properties)
111 {
112 this.sink = sink;
113 this.messages = messages;
114 this.buildMetaDataPropertiesFile = buildMetaDataPropertiesFile;
115 this.properties = properties;
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 public void renderReport() throws MavenReportException
134 {
135 sink.head();
136 sink.title();
137 sink.text(messages.getString("report.name"));
138 sink.title_();
139 sink.head_();
140
141 sink.body();
142 renderBody();
143 sink.body_();
144 sink.flush();
145 sink.close();
146 }
147
148
149
150
151
152
153 private void renderBody() throws MavenReportException
154 {
155 sink.section1();
156
157 sink.sectionTitle1();
158 sink.text(messages.getString("report.name"));
159 sink.sectionTitle1_();
160
161 sink.paragraph();
162 sink.text(messages.getString("report.description"));
163 sink.paragraph_();
164
165 final Properties buildMetaDataProperties = readBuildMetaDataProperties();
166
167 renderSections(buildMetaDataProperties);
168
169 renderFooter();
170 sink.section1_();
171 }
172
173 private void renderSections(final Properties buildMetaDataProperties)
174 {
175 for (final Section section : Constant.REPORT_PROPERTIES)
176 {
177 final List<String> properties = section.getProperties();
178 if (hasPropertiesProvided(buildMetaDataProperties, properties))
179 {
180 final String sectionKey = section.getTitleKey();
181 sink.sectionTitle2();
182 sink.text(messages.getString(sectionKey));
183 sink.sectionTitle2_();
184 renderTableStart();
185 for (final String key : properties)
186 {
187 renderCell(buildMetaDataProperties, key);
188 }
189 renderSelectedPropertiesForSection(buildMetaDataProperties, sectionKey);
190 renderTableEnd();
191 }
192 }
193
194 renderNonStandardProperties(buildMetaDataProperties);
195 }
196
197 private boolean hasPropertiesProvided(
198 final Properties buildMetaDataProperties, final List<String> properties)
199 {
200 for (final String key : properties)
201 {
202 final Object value = buildMetaDataProperties.get(key);
203 if (value != null && StringUtils.isNotBlank(String.valueOf(value)))
204 {
205 return true;
206 }
207 }
208
209 final Set<String> selectedProperties = createSelectedProperties();
210 for (final String key : selectedProperties)
211 {
212 final Object value = buildMetaDataProperties.get(key);
213 if (value != null && StringUtils.isNotBlank(String.valueOf(value)))
214 {
215 return true;
216 }
217 }
218
219 return false;
220 }
221
222 private void renderSelectedPropertiesForSection(
223 final Properties buildMetaDataProperties, final String sectionKey)
224 {
225 if (properties != null && !properties.isEmpty())
226 {
227 for (final Property property : properties)
228 {
229 if (sectionKey.equals(property.getSection()))
230 {
231 final String key = property.getName();
232 renderCell(buildMetaDataProperties, key);
233 }
234 }
235 }
236 }
237
238 private void renderNonStandardProperties(
239 final Properties buildMetaDataProperties)
240 {
241 final Properties nonStandardProperties =
242 Constant.calcNonStandardProperties(buildMetaDataProperties, properties);
243 if (!nonStandardProperties.isEmpty())
244 {
245 sink.sectionTitle2();
246 sink.text(messages.getString(Constant.SECTION_BUILD_MISC));
247 sink.sectionTitle2_();
248 renderTableStart();
249 for (final Enumeration<Object> en = nonStandardProperties.keys(); en
250 .hasMoreElements();)
251 {
252 final String key = String.valueOf(en.nextElement());
253 if (Constant.isIntendedForMiscSection(key))
254 {
255 renderCell(nonStandardProperties, key);
256 }
257 }
258 renderTableEnd();
259 }
260 }
261
262 private Set<String> createSelectedProperties()
263 {
264 final Set<String> selectedProperties = new HashSet<String>();
265
266 if (properties != null)
267 {
268 for (final Property property : properties)
269 {
270 selectedProperties.add(property.getName());
271 }
272 }
273
274 return selectedProperties;
275 }
276
277 private void renderTableEnd()
278 {
279 sink.table_();
280 }
281
282 private void renderTableStart()
283 {
284 sink.table();
285 sink.tableRow();
286 sink.tableHeaderCell("200");
287 final String topicLabel = messages.getString("report.table.header.topic");
288 sink.text(topicLabel);
289 sink.tableHeaderCell_();
290 sink.tableHeaderCell();
291 final String valueLabel = messages.getString("report.table.header.value");
292 sink.text(valueLabel);
293 sink.tableHeaderCell_();
294 sink.tableRow_();
295 }
296
297
298
299
300
301
302
303
304 private void renderCell(final Properties buildMetaDataProperties,
305 final String key)
306 {
307 final Object value = buildMetaDataProperties.get(key);
308 if (value != null)
309 {
310 sink.tableRow();
311 sink.tableCell();
312 sink.text(getLabel(key));
313 sink.tableCell_();
314 sink.tableCell();
315 if (Constant.PROP_NAME_MAVEN_ACTIVE_PROFILES.equals(key))
316 {
317 renderMultiTupleValue(buildMetaDataProperties, value,
318 Constant.MAVEN_ACTIVE_PROFILE_PREFIX);
319 }
320 else if (Constant.PROP_NAME_SCM_LOCALLY_MODIFIED_FILES.equals(key))
321 {
322 final String filesValue = Constant.prettifyFilesValue(value);
323 renderMultiValue(filesValue);
324 }
325 else if (Constant.PROP_NAME_MAVEN_GOALS.equals(key))
326 {
327 renderMultiValue(value);
328 }
329 else if (Constant.PROP_NAME_MAVEN_FILTERS.equals(key))
330 {
331 renderMultiValue(value);
332 }
333 else
334 {
335 renderSingleValue(value);
336 }
337 sink.tableCell_();
338 sink.tableRow_();
339 }
340 }
341
342 private void renderSingleValue(final Object value)
343 {
344 final String stringValue = String.valueOf(value);
345 if (stringValue != null && !isLink(stringValue))
346 {
347 sink.text(stringValue);
348 }
349 else
350 {
351 sink.link(stringValue);
352 sink.text(stringValue);
353 sink.link_();
354 }
355 }
356
357 private boolean isLink(final String input)
358 {
359 return (input.startsWith("http://") || input.startsWith("https://"));
360 }
361
362 private void renderMultiTupleValue(final Properties buildMetaDataProperties,
363 final Object value, final String subKeyPrefix)
364 {
365 final String stringValue = Constant.prettify((String) value);
366 if (hasMultipleValues(stringValue))
367 {
368 final StringTokenizer tokenizer = new StringTokenizer(stringValue, ",");
369 sink.numberedList(Sink.NUMBERING_DECIMAL);
370 while (tokenizer.hasMoreTokens())
371 {
372 final String profileName = tokenizer.nextToken().trim();
373 final String subKey = subKeyPrefix + '.' + profileName;
374 final Object subValue = buildMetaDataProperties.get(subKey);
375 final String item = profileName + ':' + subValue;
376 sink.listItem();
377 sink.text(item);
378 sink.listItem_();
379 }
380 sink.numberedList_();
381 }
382 else
383 {
384 sink.text(String.valueOf(value));
385 }
386 }
387
388 private void renderMultiValue(final Object value)
389 {
390 final String stringValue = Constant.prettify((String) value);
391 if (hasMultipleValues(stringValue))
392 {
393 final StringTokenizer tokenizer = new StringTokenizer(stringValue, ",");
394 sink.numberedList(Sink.NUMBERING_DECIMAL);
395 while (tokenizer.hasMoreTokens())
396 {
397 final String subValue = tokenizer.nextToken();
398 sink.listItem();
399 sink.text(String.valueOf(subValue));
400 sink.listItem_();
401 }
402 sink.numberedList_();
403 }
404 else
405 {
406 sink.text(stringValue);
407 }
408 }
409
410 private boolean hasMultipleValues(final String stringValue)
411 {
412 return stringValue.indexOf(',') != -1;
413 }
414
415 private String getLabel(final String key)
416 {
417 try
418 {
419 return messages.getString(key);
420 }
421 catch (final MissingResourceException e)
422 {
423 if (properties != null)
424 {
425 for (final Property property : properties)
426 {
427 final String label = property.getLabel();
428 if (StringUtils.isNotBlank(label)
429 && key.equals(property.getMappedName()))
430 {
431 return label;
432 }
433 }
434 }
435 return key;
436 }
437 }
438
439
440
441
442 private void renderFooter()
443 {
444 final String footerText = messages.getString("report.footer");
445 if (StringUtils.isNotBlank(footerText))
446 {
447 sink.rawText(footerText);
448 }
449 }
450
451
452
453
454
455
456
457 private Properties readBuildMetaDataProperties() throws MavenReportException
458 {
459 final Properties buildMetaDataProperties = new Properties();
460 InputStream inStream = null;
461 try
462 {
463 inStream =
464 new BufferedInputStream(new FileInputStream(
465 this.buildMetaDataPropertiesFile));
466 buildMetaDataProperties.load(inStream);
467 }
468 catch (final IOException e)
469 {
470 throw new MavenReportException("Cannot read build properties file '"
471 + this.buildMetaDataPropertiesFile + "'.",
472 e);
473 }
474 finally
475 {
476 IOUtils.closeQuietly(inStream);
477 }
478 return buildMetaDataProperties;
479 }
480
481
482
483 }