1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package de.smartics.maven.plugin.buildmetadata.io;
17
18 import java.io.IOException;
19 import java.text.DateFormat;
20 import java.text.ParseException;
21 import java.text.SimpleDateFormat;
22 import java.util.Date;
23 import java.util.Enumeration;
24 import java.util.List;
25 import java.util.Locale;
26 import java.util.Map;
27 import java.util.Properties;
28 import java.util.StringTokenizer;
29
30 import org.apache.commons.lang.time.DateFormatUtils;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.codehaus.plexus.util.StringUtils;
34 import org.w3c.dom.DOMException;
35 import org.w3c.dom.Document;
36 import org.w3c.dom.Element;
37 import org.w3c.dom.Text;
38
39 import de.smartics.maven.plugin.buildmetadata.common.Constant;
40 import de.smartics.maven.plugin.buildmetadata.common.Property;
41 import de.smartics.maven.plugin.buildmetadata.common.SortedProperties;
42
43
44
45
46
47
48
49
50
51
52 public final class SdocBuilder
53 {
54
55
56
57
58
59
60
61
62
63
64 private static final String XML_SCHEMA_INSTANCE =
65 "http://www.w3.org/2001/XMLSchema-instance";
66
67
68
69
70
71
72
73 private static final String CODE_URI =
74 "http://www.smartics.de/project/process/implementation/buildmetadata";
75
76
77
78
79
80
81
82
83 private static final String GI_VERSION = "version";
84
85
86
87
88
89
90
91 private static final String GI_NAME = "name";
92
93
94
95
96 private static final Log LOG = LogFactory.getLog(SdocBuilder.class);
97
98
99
100
101
102
103 private final Document document;
104
105
106
107
108 private final Properties buildMetaDataProperties;
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130 private final List<Property> selectedProperties;
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145 public SdocBuilder(final Document document,
146 final Properties buildMetaDataProperties,
147 final List<Property> selectedProperties)
148 {
149 this.document = document;
150 this.buildMetaDataProperties = buildMetaDataProperties;
151 this.selectedProperties = selectedProperties;
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public Document writeDocumentContent() throws IOException
171 {
172 final Element docRoot = createDocRoot();
173
174 createContentElement(GI_NAME, Constant.PROP_NAME_FULL_VERSION, docRoot);
175 createContentElement(GI_VERSION, Constant.PROP_NAME_VERSION, docRoot);
176 createContentElement("groupId", Constant.PROP_NAME_GROUP_ID, docRoot);
177 createContentElement("artifactId", Constant.PROP_NAME_ARTIFACT_ID, docRoot);
178 final String date = formatDate(Constant.PROP_NAME_BUILD_DATE);
179 createValueElement("date", date, docRoot);
180 createContentElement("timestamp", Constant.PROP_NAME_BUILD_TIMESTAMP,
181 docRoot);
182
183 createScmElement(docRoot);
184 createRuntimeElement(docRoot);
185 createMiscElement(docRoot);
186
187 return document;
188 }
189
190 private String formatDate(final String datePropertyKey)
191 {
192 final String originalDateString =
193 buildMetaDataProperties.getProperty(datePropertyKey);
194 if (StringUtils.isNotBlank(originalDateString))
195 {
196 try
197 {
198 final String originalPattern =
199 buildMetaDataProperties
200 .getProperty(Constant.PROP_NAME_BUILD_DATE_PATTERN);
201 final DateFormat format =
202 new SimpleDateFormat(originalPattern, Locale.ENGLISH);
203 final Date date = format.parse(originalDateString);
204 final String dateString =
205 DateFormatUtils.ISO_DATETIME_FORMAT.format(date);
206 return dateString;
207 }
208 catch (final ParseException e)
209 {
210 if (LOG.isDebugEnabled())
211 {
212 LOG.debug("Cannot parse date of property '" + datePropertyKey + "': "
213 + originalDateString + ". Skipping...");
214 }
215 return null;
216 }
217 }
218 return null;
219 }
220
221 private void createScmElement(final Element docRoot)
222 {
223 final Element parent = document.createElement("scm");
224 createContentElement("revision", Constant.PROP_NAME_SCM_REVISION_ID, parent);
225 final String date = formatDate(Constant.PROP_NAME_SCM_REVISION_DATE);
226 createValueElement("revision-date", date, parent);
227 createContentElement("url", Constant.PROP_NAME_SCM_URL, parent);
228 createLocallyModifiedFiles(parent);
229 docRoot.appendChild(parent);
230 }
231
232 private void createLocallyModifiedFiles(final Element scm)
233 {
234 final String value =
235 buildMetaDataProperties
236 .getProperty(Constant.PROP_NAME_SCM_LOCALLY_MODIFIED_FILES);
237
238 if (StringUtils.isNotBlank(value))
239 {
240 final Element parent = document.createElement("locally-modified-files");
241
242 final String filesValue = Constant.prettifyFilesValue(value);
243 renderFiles(parent, filesValue);
244 scm.appendChild(parent);
245 }
246 }
247
248 private void renderFiles(final Element lmf, final String value)
249 {
250 final String stringValue = Constant.prettify(value);
251 final StringTokenizer tokenizer = new StringTokenizer(stringValue, ",");
252 while (tokenizer.hasMoreTokens())
253 {
254 final String subValue = tokenizer.nextToken();
255 final int colonIndex = subValue.indexOf(':');
256 if (colonIndex > -1)
257 {
258 final String filePath = subValue.substring(0, colonIndex);
259 final Element file = createValueElement("file", filePath, lmf);
260 if (file != null && colonIndex < subValue.length() - 1)
261 {
262 final String modType = subValue.substring(colonIndex + 1).trim();
263 file.setAttribute("modtype", modType);
264 }
265 }
266 }
267 }
268
269 private void createRuntimeElement(final Element docRoot)
270 {
271 final Element parent = document.createElement("runtime");
272
273 createContentElement("build-server", Constant.PROP_NAME_HOSTNAME, parent);
274 createContentElement("build-user", Constant.PROP_NAME_BUILD_USER, parent);
275
276 createOsElement(parent);
277 createJavaElement(parent);
278 createMavenElement(parent);
279 createEnvElement(parent);
280
281 docRoot.appendChild(parent);
282 }
283
284 private void createOsElement(final Element runtime)
285 {
286 final Element parent = document.createElement("os");
287 createContentElement("arch", Constant.PROP_NAME_OS_ARCH, parent);
288 createContentElement(GI_NAME, Constant.PROP_NAME_OS_NAME, parent);
289 createContentElement(GI_VERSION, Constant.PROP_NAME_OS_VERSION, parent);
290 if (parent.hasChildNodes())
291 {
292 runtime.appendChild(parent);
293 }
294 }
295
296 private void createJavaElement(final Element runtime)
297 {
298 final Element parent = document.createElement("java");
299 createContentElement(GI_NAME, Constant.PROP_NAME_JAVA_RUNTIME_NAME, parent);
300 createContentElement(GI_VERSION, Constant.PROP_NAME_JAVA_RUNTIME_VERSION,
301 parent);
302 createContentElement("vendor", Constant.PROP_NAME_JAVA_VENDOR, parent);
303 createContentElement("vm", Constant.PROP_NAME_JAVA_VM, parent);
304 createContentElement("compiler", Constant.PROP_NAME_JAVA_COMPILER, parent);
305 createContentElement("options", Constant.PROP_NAME_JAVA_OPTS, parent);
306 if (parent.hasChildNodes())
307 {
308 runtime.appendChild(parent);
309 }
310 }
311
312 private void createMavenElement(final Element runtime)
313 {
314 final Element parent = document.createElement("maven");
315 createContentElement(GI_VERSION, Constant.PROP_NAME_MAVEN_VERSION, parent);
316
317 final Element goals = document.createElement("goals");
318 final String goalsString =
319 buildMetaDataProperties.getProperty(Constant.PROP_NAME_MAVEN_GOALS);
320 renderGoals(goals, goalsString);
321 parent.appendChild(goals);
322
323 final Element profiles = document.createElement("profiles");
324 final String profilesString =
325 buildMetaDataProperties
326 .getProperty(Constant.PROP_NAME_MAVEN_ACTIVE_PROFILES);
327 if (StringUtils.isNotBlank(profilesString))
328 {
329 renderProfiles(profiles, profilesString);
330 parent.appendChild(profiles);
331 }
332
333 createContentElement("options", Constant.PROP_NAME_MAVEN_OPTS, parent);
334 if (parent.hasChildNodes())
335 {
336 runtime.appendChild(parent);
337 }
338 }
339
340 private void renderGoals(final Element goals, final String value)
341 {
342 if (StringUtils.isNotBlank(value))
343 {
344 final String stringValue = Constant.prettify(value);
345 final StringTokenizer tokenizer = new StringTokenizer(stringValue, ",");
346 while (tokenizer.hasMoreTokens())
347 {
348 final String goal = tokenizer.nextToken();
349 createValueElement("goal", goal.trim(), goals);
350 }
351 }
352 }
353
354 private void renderProfiles(final Element profiles, final String value)
355 {
356 final String stringValue = Constant.prettify(value);
357 final StringTokenizer tokenizer = new StringTokenizer(stringValue, ",");
358 while (tokenizer.hasMoreTokens())
359 {
360 final String profileName = tokenizer.nextToken().trim();
361 final Element profile =
362 createValueElement("profile", profileName, profiles);
363 if (profile != null)
364 {
365 final String profileSourceKey =
366 Constant.MAVEN_ACTIVE_PROFILE_PREFIX + '.' + profileName;
367 final String source =
368 buildMetaDataProperties.getProperty(profileSourceKey);
369 profile.setAttribute("source", source);
370 }
371 }
372 }
373
374 private void createEnvElement(final Element runtime)
375 {
376 final Element parent = document.createElement("env");
377
378 final Properties sorted =
379 SortedProperties.createSorted(buildMetaDataProperties);
380 final String matchPrefix = Constant.MAVEN_EXECUTION_PROPERTIES_PREFIX + '.';
381 for (final Map.Entry<Object, Object> entry : sorted.entrySet())
382 {
383 final String key = String.valueOf(entry.getKey());
384 if (key.startsWith(matchPrefix))
385 {
386 final String value = String.valueOf(entry.getValue());
387 final Element env = createValueElement("var", value, parent);
388 if (env != null)
389 {
390 env.setAttribute(GI_NAME, key);
391 }
392 }
393 }
394
395 if (parent.hasChildNodes())
396 {
397 runtime.appendChild(parent);
398 }
399 }
400
401 private void createMiscElement(final Element docRoot)
402 {
403 final Properties nonStandardProperties =
404 Constant.calcNonStandardProperties(buildMetaDataProperties,
405 selectedProperties);
406 if (!nonStandardProperties.isEmpty())
407 {
408 final Element parent = document.createElement("misc");
409
410 for (final Enumeration<Object> en = nonStandardProperties.keys(); en
411 .hasMoreElements();)
412 {
413 final String key = String.valueOf(en.nextElement());
414 createMetaDataElement(parent, key);
415 }
416 docRoot.appendChild(parent);
417 }
418 }
419
420 private void createMetaDataElement(final Element parent, final String key)
421 {
422 if (Constant.isIntendedForMiscSection(key))
423 {
424 final Element metadata = createContentElement("metadata", key, parent);
425 if (metadata != null)
426 {
427 metadata.setAttribute(GI_NAME, key);
428 }
429 }
430 }
431
432 private Element createDocRoot() throws DOMException
433 {
434 final Element docRoot = document.createElement("buildmetadata");
435 docRoot.setAttribute("xmlns:xsi", XML_SCHEMA_INSTANCE);
436 docRoot.setAttribute("xmlns", CODE_URI);
437 docRoot.setAttribute("xsi:schemaLocation", CODE_URI + ' ' + CODE_URI);
438 document.appendChild(docRoot);
439 return docRoot;
440 }
441
442 private Element createContentElement(final String gi,
443 final String propertyKey, final Element parent)
444 {
445 final String content = buildMetaDataProperties.getProperty(propertyKey);
446 return createValueElement(gi, content, parent);
447 }
448
449 private Element createValueElement(final String gi, final String value,
450 final Element parent)
451 {
452 if (value != null)
453 {
454 final Element element = document.createElement(gi);
455 final Text text = document.createTextNode(value);
456 element.appendChild(text);
457 parent.appendChild(element);
458 return element;
459 }
460 return null;
461 }
462
463
464
465 }