1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Oracle designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Oracle in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 24 * or visit www.oracle.com if you need additional information or have any 25 * questions. 26 */ 27 package com.sun.javatest.report; 28 29 import com.sun.interview.ChoiceArrayQuestion; 30 import com.sun.interview.ChoiceQuestion; 31 import com.sun.interview.FileListQuestion; 32 import com.sun.interview.PropertiesQuestion; 33 import com.sun.interview.Question; 34 import com.sun.interview.StringListQuestion; 35 import com.sun.interview.TreeQuestion; 36 import com.sun.interview.YesNoQuestion; 37 import com.sun.javatest.ExcludeList; 38 import com.sun.javatest.JavaTestError; 39 import com.sun.javatest.Keywords; 40 import com.sun.javatest.Parameters; 41 import com.sun.javatest.Status; 42 import com.sun.javatest.TemplateUtilities; 43 import com.sun.javatest.TemplateUtilities.ConfigInfo; 44 import com.sun.javatest.TestDescription; 45 import com.sun.javatest.TestEnvironment; 46 import com.sun.javatest.TestFilter; 47 import com.sun.javatest.TestResult; 48 import com.sun.javatest.TestResult.Section; 49 import com.sun.javatest.TestResultTable; 50 import com.sun.javatest.WorkDirectory; 51 import com.sun.javatest.util.I18NResourceBundle; 52 import java.io.BufferedWriter; 53 import java.io.File; 54 import java.io.FileOutputStream; 55 import java.io.IOException; 56 import java.io.OutputStreamWriter; 57 import java.io.Writer; 58 import java.text.DateFormat; 59 import java.text.ParseException; 60 import java.text.SimpleDateFormat; 61 import java.util.Collections; 62 import java.util.Date; 63 import java.util.Enumeration; 64 import java.util.Iterator; 65 import java.util.List; 66 import java.util.Map; 67 import org.xml.sax.SAXException; 68 69 70 /** 71 * XML report (dump). 72 */ 73 public class XMLReport implements ReportFormat { 74 75 @Override 76 public ReportLink write(ReportSettings sett, File dir) throws IOException { 77 78 File repFile = new File(dir, REPORT_NAME); 79 Writer w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(repFile), XMLReportMaker.XML_CHARSET)); 80 try { 81 write(w, sett); 82 } catch (SAXException ex) { 83 throw new JavaTestError(i18n.getString("report.writing.err"), ex); 84 } 85 w.close(); 86 sett.xmlReportFile = repFile; 87 88 return new ReportLink(i18n.getString("index.xmltype.txt"), 89 getBaseDirName(), i18n.getString("index.desc.xml"),repFile); 90 91 } 92 93 @Override 94 public String getReportID() { 95 return ID; 96 } 97 98 @Override 99 public String getBaseDirName() { 100 return ID; 101 } 102 103 @Override 104 public String getTypeName() { 105 return ID; 106 } 107 108 @Override 109 public boolean acceptSettings(ReportSettings s) { 110 return s.isXmlEnabled(); 111 } 112 113 @Override 114 public List<ReportFormat> getSubReports() { 115 return Collections.<ReportFormat>emptyList(); 116 } 117 118 public void write(Writer w, ReportSettings sett) throws IOException, SAXException { 119 120 XMLReportMaker maker = new XMLReportMaker(w); 121 maker.sDocument(); 122 maker.sReport(); 123 maker.sWorkdirectories(); 124 File jti = null; 125 if (sett.getInterview() != null) { 126 jti = sett.getInterview().getFile(); 127 } 128 maker.sWorkdirectory( jti == null ? null : jti.getPath()); 129 130 writeTemplateInfo(maker, sett); 131 writeInterview(maker, sett); 132 writeStandardValues(maker, sett); 133 writeEnvironment(maker, sett); 134 135 maker.eWorkdirectory(); 136 maker.eWorkdirectories(); 137 writeResults(maker, sett); 138 maker.eReport(); 139 maker.eDocument(); 140 141 } 142 143 private void writeResults(final XMLReportMaker maker, final ReportSettings sett) throws SAXException, JavaTestError, IOException { 144 maker.sTestResults(); 145 146 File[] initFiles = sett.getInitialFiles(); 147 Iterator iter = null; 148 TestResultTable resultTable = sett.getInterview().getWorkDirectory().getTestResultTable(); 149 150 try { 151 if (initFiles == null) { 152 iter = resultTable.getIterator(new TestFilter[] {sett.getTestFilter()}); 153 } else { 154 iter = resultTable.getIterator(initFiles, new TestFilter[] {sett.getTestFilter()}); 155 } 156 for (; iter.hasNext(); ) { 157 TestResult tr = (TestResult) (iter.next()); 158 writeResult(maker, tr); 159 } 160 maker.eTestResults(); 161 } catch (TestResultTable.Fault f) { 162 throw new JavaTestError(i18n.getString("report.testResult.err"), f); 163 } 164 } 165 166 private void writeResult(final XMLReportMaker maker, final TestResult testResult) throws SAXException, IOException { 167 168 maker.sTestResult(testResult.getTestName(), testResult.getStatus(), 1); 169 try { 170 writeDescriptionData(maker, testResult); 171 writeEnvironment(maker, testResult); 172 writeResultProps(maker, testResult); 173 writeSections(maker, testResult); 174 writeAnnotations(maker, testResult); 175 } catch (TestResult.Fault e) { 176 System.err.println(i18n.getString("report.writing.err")); 177 e.printStackTrace(); 178 } finally { 179 maker.eTestResult(); 180 } 181 } 182 183 private void writeSections(final XMLReportMaker maker, final TestResult testResult) throws SAXException, IOException, TestResult.Fault { 184 185 maker.sSections(); 186 for (int i = 0; i < testResult.getSectionCount() ; i++) { 187 String st = testResult.getSectionTitles()[i]; 188 Section sec = testResult.getSection(i); 189 Status stat = sec.getStatus(); 190 maker.sSection(st, stat); 191 for (int j=0; j < sec.getOutputCount(); j++) { 192 String oName = sec.getOutputNames()[j]; 193 maker.sOutput(oName, sec.getOutput(oName)); 194 maker.eOutput(); 195 } 196 maker.eSection(); 197 } 198 maker.eSections(); 199 } 200 201 private void writeResultProps(final XMLReportMaker maker, final TestResult testResult) throws SAXException, TestResult.Fault { 202 203 String time = testResult.getProperty(TestResult.END); 204 205 maker.sResultProps(time); 206 Enumeration en = testResult.getPropertyNames(); 207 while (en.hasMoreElements()) { 208 String key = (String) en.nextElement(); 209 String val = testResult.getProperty(key); 210 if (!TestResult.END.equals(key)) { 211 maker.makeProperty(key, val); 212 } 213 } 214 maker.eResultProps(); 215 } 216 217 private void writeEnvironment(final XMLReportMaker maker, final TestResult testResult) throws SAXException { 218 219 Iterator keysIt; 220 try { 221 Map m = testResult.getEnvironment(); 222 keysIt = m.keySet().iterator(); 223 maker.sTestEnvironment(); 224 while (keysIt.hasNext()) { 225 String key = (String) keysIt.next(); 226 String val = (String) m.get(key); 227 maker.makeProperty(key, val); 228 } 229 maker.eTestEnvironment(); 230 } catch (TestResult.Fault e) { 231 232 } 233 } 234 235 private void writeDescriptionData(final XMLReportMaker maker, final TestResult testResult) throws SAXException, TestResult.Fault { 236 maker.sDescriptionData(); 237 238 TestDescription td = testResult.getDescription(); 239 Iterator<String> keysIt = td.getParameterKeys(); 240 241 maker.makeProperty("$root", td.getRootDir()); 242 maker.makeProperty("$file", td.getFile().getPath()); 243 244 while (keysIt.hasNext()) { 245 String key = keysIt.next(); 246 // dump keywords separately 247 if (!"keywords".equals(key)) { 248 String val = td.getParameter(key); 249 maker.makeProperty(key, val); 250 } 251 } 252 253 String [] kws = td.getKeywords(); 254 if (kws != null && kws.length > 0 ) { 255 maker.sKeyWords(); 256 maker.makeItems(kws); 257 maker.eKeyWords(); 258 } 259 maker.eDescriptionData(); 260 } 261 262 private void writeAnnotations(XMLReportMaker maker, TestResult testResult) throws SAXException { 263 TestResultTable.TreeNode tn = testResult.getParent(); 264 TestResultTable trt = null; 265 WorkDirectory wd = null; 266 267 if (tn != null) 268 trt = tn.getEnclosingTable(); 269 else 270 return; 271 272 if (trt != null) 273 wd = trt.getWorkDirectory(); 274 else 275 return; 276 277 Map<String,String> map = wd.getTestAnnotations(testResult); 278 if (map != null) { 279 maker.sTAnnotationData(); 280 for (String key: map.keySet()) { 281 maker.makeProperty(key, map.get(key)); 282 } // for 283 maker.eTAnnotationData(); 284 } 285 } 286 287 private void writeEnvironment(final XMLReportMaker maker, final ReportSettings sett) throws SAXException { 288 289 String name = null, descr = null; 290 291 if (sett.getInterview().getEnv() != null) { 292 name = sett.getInterview().getEnv().getName(); 293 descr= sett.getInterview().getEnv().getDescription(); 294 } 295 296 maker.sEnvironment(name, descr); 297 TestEnvironment env = sett.getInterview().getEnv(); 298 if (env != null) { 299 for (Iterator i = env.elements().iterator(); i.hasNext(); ) { 300 TestEnvironment.Element envElem = (TestEnvironment.Element) (i.next()); 301 maker.makeProperty(envElem.getKey(), envElem.getValue()); 302 } 303 } 304 maker.eEnvironment(); 305 } 306 307 private void writeStandardValues(final XMLReportMaker maker, ReportSettings sett) throws SAXException { 308 maker.sStdValues(); 309 writeTestsToRun(maker, sett); 310 writePriorStatusList(maker, sett); 311 writeExcludeLists(maker, sett); 312 maker.conCur(sett.getInterview().getConcurrency()); 313 maker.timeOut(sett.getInterview().getTimeoutFactor()); 314 writeKeyWords(maker, sett); 315 maker.eStdValues(); 316 } 317 318 private void writeKeyWords(final XMLReportMaker maker, final ReportSettings sett) throws SAXException { 319 // keywords 320 Keywords keywords = sett.getInterview().getKeywords(); 321 if (keywords != null) { 322 maker.sKeyWords(sett.getInterview().getKeywords().toString()); 323 maker.eKeyWords(); 324 } 325 } 326 327 private void writeExcludeLists(final XMLReportMaker maker, final ReportSettings sett) throws SAXException { 328 // Exclude 329 ExcludeList excludeList = sett.getInterview().getExcludeList(); 330 if (excludeList != null) { 331 Parameters.ExcludeListParameters exclParams = sett.getInterview().getExcludeListParameters(); 332 File[] excludeFiles = null; 333 if (exclParams instanceof Parameters.MutableExcludeListParameters) 334 excludeFiles = 335 ((Parameters.MutableExcludeListParameters) (exclParams)).getExcludeFiles(); 336 337 if (excludeFiles != null && excludeFiles.length > 0) { 338 maker.sExclList(); 339 maker.makeItems(excludeFiles); 340 maker.eExclList(); 341 } 342 } 343 } 344 345 private void writePriorStatusList(final XMLReportMaker maker, final ReportSettings sett) throws SAXException { 346 boolean[] b = sett.getInterview().getPriorStatusValues(); 347 if (b != null) { 348 int[] ss = {Status.PASSED, Status.FAILED, Status.ERROR, Status.NOT_RUN}; 349 maker.sPriorStatusList(); 350 for (int i = 0; i < b.length; i++) { 351 if (b[i]) { 352 maker.makeItem(Utils.statusIntToString(ss[i])); 353 } 354 } 355 maker.ePriorStatusList(); 356 } 357 } 358 359 private void writeTestsToRun(final XMLReportMaker maker, final ReportSettings sett) throws SAXException { 360 maker.sTests(); 361 String [] tests = sett.getInterview().getTests(); 362 if (tests != null && tests.length > 0) { 363 for (int i = 0; i < tests.length; i++) { 364 maker.makeItem(tests[i]); 365 } 366 } else { 367 maker.makeEntireTestTree(); 368 } 369 maker.eTests(); 370 } 371 372 private void writeTemplateInfo(final XMLReportMaker maker, final ReportSettings sett) throws SAXException { 373 String tPath = sett.getInterview().getTemplatePath(); 374 if (tPath != null) { 375 try { 376 ConfigInfo ci = TemplateUtilities.getConfigInfo(new File(tPath)); 377 maker.makeTemplateInfo(tPath, ci.getName(), ci.getDescription()); 378 } catch (IOException ex) { 379 // do nothing 380 } 381 } 382 } 383 384 385 private void writeInterview(final XMLReportMaker maker, final ReportSettings sett) throws SAXException { 386 387 maker.sInterview(); 388 Question [] questions = sett.getInterview().getPath(); 389 for (int i = 0; i < questions.length; i++) { 390 Question q = questions[i]; 391 maker.sQuestion(q.getStringValue(), q.getText(), q.getSummary()); 392 if (q instanceof TreeQuestion || q instanceof StringListQuestion || q instanceof FileListQuestion) { 393 writeListQuestion(maker, q); 394 } else if (q instanceof ChoiceQuestion || q instanceof YesNoQuestion || q instanceof ChoiceArrayQuestion) { 395 writeChoiceQuestion(maker, q); 396 } else if (q instanceof PropertiesQuestion) { 397 writePropertiesQuestion(maker, q); 398 } 399 maker.eQuestion(); 400 } 401 maker.eInterview(); 402 } 403 404 private void writeListQuestion(XMLReportMaker maker, Question q) throws SAXException { 405 maker.sListQuestion(); 406 if (q instanceof TreeQuestion) { 407 TreeQuestion tq = (TreeQuestion) q; 408 maker.makeItems(tq.getValue()); 409 } else if (q instanceof StringListQuestion ) { 410 StringListQuestion slq = (StringListQuestion) q; 411 maker.makeItems(slq.getValue()); 412 } else if (q instanceof FileListQuestion) { 413 FileListQuestion flq = (FileListQuestion) q; 414 maker.makeItems(flq.getValue()); 415 } 416 maker.eListQuestion(); 417 } 418 419 private void writePropertiesQuestion(XMLReportMaker maker, Question q) throws SAXException { 420 maker.sPropertiesQuestion(); 421 PropertiesQuestion pq = (PropertiesQuestion) q; 422 String [] grs = pq.getGroups(); 423 String h1 = pq.getKeyHeaderName(); 424 String h2 = pq.getValueHeaderName(); 425 if (grs != null) { 426 for (int i = 0; i < grs.length; i++) { 427 String name = grs[i]; 428 maker.sGroup(name, h1, h2); 429 if (name != null) { 430 String[][] table = pq.getGroup(name); 431 writeTable(maker, table); 432 } 433 maker.eGroup(name, h1, h2); 434 } 435 } 436 maker.ePropertiesQuestion(); 437 } 438 439 private void writeChoiceQuestion(XMLReportMaker maker, Question q) throws SAXException { 440 maker.sChoiceQuestion(); 441 if (q instanceof ChoiceQuestion ) { 442 ChoiceQuestion cq = (ChoiceQuestion) q; 443 maker.makeChoices(cq.getChoices(), cq.getDisplayChoices()); 444 } else if (q instanceof YesNoQuestion ) { 445 YesNoQuestion ynq = (YesNoQuestion) q; 446 maker.makeChoices(ynq.getChoices(), ynq.getDisplayChoices()); 447 } else if (q instanceof ChoiceArrayQuestion) { 448 ChoiceArrayQuestion caq = (ChoiceArrayQuestion) q; 449 maker.makeChoices(caq.getChoices(), caq.getDisplayChoices(), caq.getValue()); 450 } 451 maker.eChoiceQuestion(); 452 } 453 454 private void writeTable(XMLReportMaker maker, String[][] table) throws SAXException { 455 if (table != null ) { 456 for (int i=0 ; i < table.length ;i++) { 457 maker.makeRow(table[i][0], table[i][1]); 458 } 459 } 460 } 461 462 /** 463 * Utility class 464 */ 465 static class Utils { 466 467 /** 468 * Convert date to string in ISO-8601 or xs:dateTime format 469 * @param date Date 470 * @return ISO-8601 String 471 */ 472 static String dateToISO8601(Date date) { 473 DateFormat dfISO8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); 474 // format in (almost) ISO8601 format 475 String dateStr = dfISO8601.format(date); 476 // remap the timezone from 0000 to 00:00 (starts at char 22) 477 return dateStr.substring(0, 22) + ":" + dateStr.substring(22); 478 } 479 480 /** 481 * Convert string from JTR format to java.util.Date 482 * @throws java.text.ParseException 483 * @param dateStr String 484 * @return Date 485 */ 486 static Date jtrToDate(String dateStr) throws ParseException { 487 return TestResult.parseDate(dateStr); 488 } 489 490 /** 491 * Convert Status object to String 492 */ 493 static String statusToString(Status st) { 494 if (st.isError()) return "ERROR"; 495 if (st.isFailed()) return "FAILED"; 496 if (st.isNotRun()) return "NOT_RUN"; 497 if (st.isPassed()) return "PASSED"; 498 return "UNKNOWN"; 499 } 500 501 /** 502 * Convert Status integer value to String 503 */ 504 static String statusIntToString(int st) { 505 if (st == Status.ERROR) return "ERROR"; 506 if (st == Status.FAILED) return "FAILED"; 507 if (st == Status.NOT_RUN) return "NOT_RUN"; 508 if (st == Status.PASSED) return "PASSED"; 509 return "UNKNOWN"; 510 } 511 512 } 513 514 private static I18NResourceBundle i18n = I18NResourceBundle.getBundleForClass(XMLReport.class); 515 516 // The name of the root file for a set of report files. 517 static final String REPORT_NAME = "report.xml"; 518 519 private static final String ID = "xml"; 520 521 }