1 package org.apache.maven.plugin.failsafe.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.commons.io.IOUtils;
23 import org.apache.maven.surefire.suite.RunResult;
24 import org.w3c.dom.Node;
25 import org.xml.sax.InputSource;
26
27 import javax.xml.xpath.XPath;
28 import javax.xml.xpath.XPathConstants;
29 import javax.xml.xpath.XPathFactory;
30 import java.io.File;
31 import java.io.FileInputStream;
32 import java.io.FileOutputStream;
33 import java.io.IOException;
34 import java.util.Locale;
35
36 import static java.lang.Boolean.parseBoolean;
37 import static java.lang.Integer.parseInt;
38 import static java.lang.String.format;
39 import static org.apache.commons.lang3.StringEscapeUtils.escapeXml10;
40 import static org.apache.commons.lang3.StringEscapeUtils.unescapeXml;
41 import static org.apache.maven.surefire.util.internal.StringUtils.UTF_8;
42 import static org.apache.maven.surefire.util.internal.StringUtils.isBlank;
43
44
45
46
47
48 public final class FailsafeSummaryXmlUtils
49 {
50 private static final String FAILSAFE_SUMMARY_XML_SCHEMA_LOCATION =
51 "https://maven.apache.org/surefire/maven-surefire-plugin/xsd/failsafe-summary.xsd";
52
53 private static final String MESSAGE_NIL_ELEMENT =
54 "<failureMessage xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>";
55
56 private static final String MESSAGE_ELEMENT =
57 "<failureMessage>%s</failureMessage>";
58
59 private static final String FAILSAFE_SUMMARY_XML_TEMPLATE =
60 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
61 + "<failsafe-summary xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
62 + " xsi:noNamespaceSchemaLocation=\"" + FAILSAFE_SUMMARY_XML_SCHEMA_LOCATION + "\""
63 + " result=\"%s\" timeout=\"%s\">\n"
64 + " <completed>%d</completed>\n"
65 + " <errors>%d</errors>\n"
66 + " <failures>%d</failures>\n"
67 + " <skipped>%d</skipped>\n"
68 + " %s\n"
69 + "</failsafe-summary>";
70
71 private FailsafeSummaryXmlUtils()
72 {
73 throw new IllegalStateException( "No instantiable constructor." );
74 }
75
76 public static RunResult toRunResult( File failsafeSummaryXml ) throws Exception
77 {
78 XPathFactory xpathFactory = XPathFactory.newInstance();
79 XPath xpath = xpathFactory.newXPath();
80
81 FileInputStream is = new FileInputStream( failsafeSummaryXml );
82
83 try
84 {
85 Node root = (Node) xpath.evaluate( "/", new InputSource( is ), XPathConstants.NODE );
86
87 String completed = xpath.evaluate( "/failsafe-summary/completed", root );
88 String errors = xpath.evaluate( "/failsafe-summary/errors", root );
89 String failures = xpath.evaluate( "/failsafe-summary/failures", root );
90 String skipped = xpath.evaluate( "/failsafe-summary/skipped", root );
91 String failureMessage = xpath.evaluate( "/failsafe-summary/failureMessage", root );
92 String timeout = xpath.evaluate( "/failsafe-summary/@timeout", root );
93
94 return new RunResult( parseInt( completed ), parseInt( errors ), parseInt( failures ), parseInt( skipped ),
95 isBlank( failureMessage ) ? null : unescapeXml( failureMessage ),
96 parseBoolean( timeout )
97 );
98 }
99 finally
100 {
101 is.close();
102 }
103 }
104
105 public static void fromRunResultToFile( RunResult fromRunResult, File toFailsafeSummaryXml )
106 throws IOException
107 {
108 String failure = fromRunResult.getFailure();
109 String msg = isBlank( failure ) ? MESSAGE_NIL_ELEMENT : format( MESSAGE_ELEMENT, escapeXml10( failure ) );
110 String xml = format( Locale.ROOT, FAILSAFE_SUMMARY_XML_TEMPLATE,
111 fromRunResult.getFailsafeCode(),
112 String.valueOf( fromRunResult.isTimeout() ),
113 fromRunResult.getCompletedCount(),
114 fromRunResult.getErrors(),
115 fromRunResult.getFailures(),
116 fromRunResult.getSkipped(),
117 msg );
118
119 FileOutputStream os = new FileOutputStream( toFailsafeSummaryXml );
120 try
121 {
122 IOUtils.write( xml, os, UTF_8 );
123 }
124 finally
125 {
126 os.close();
127 }
128 }
129
130 public static void writeSummary( RunResult mergedSummary, File mergedSummaryFile, boolean inProgress )
131 throws Exception
132 {
133 if ( !mergedSummaryFile.getParentFile().isDirectory() )
134 {
135
136 mergedSummaryFile.getParentFile().mkdirs();
137 }
138
139 if ( mergedSummaryFile.exists() && inProgress )
140 {
141 RunResult runResult = toRunResult( mergedSummaryFile );
142 mergedSummary = mergedSummary.aggregate( runResult );
143 }
144
145 fromRunResultToFile( mergedSummary, mergedSummaryFile );
146 }
147 }