1 /******************************************************************************* 2 * Copyright (c) 2005, 2006 IBM Corporation and others. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * IBM Corporation - initial API and implementation 10 *******************************************************************************/ 11 package org.eclipse.releng.generators.rss; 12 13 //TODO: bug - can't run CreateFeed and AddEntry together when debug=2 - file locking problem? 14 15 import java.io.File; 16 import java.io.FileNotFoundException; 17 import java.io.FileOutputStream; 18 import java.io.IOException; 19 import java.io.OutputStreamWriter; 20 import java.util.Date; 21 22 import javax.xml.parsers.DocumentBuilder; 23 import javax.xml.parsers.DocumentBuilderFactory; 24 import javax.xml.parsers.ParserConfigurationException; 25 import javax.xml.transform.OutputKeys; 26 import javax.xml.transform.Transformer; 27 import javax.xml.transform.TransformerException; 28 import javax.xml.transform.TransformerFactory; 29 import javax.xml.transform.dom.DOMSource; 30 import javax.xml.transform.stream.StreamResult; 31 32 import org.apache.tools.ant.BuildException; 33 import org.apache.tools.ant.Task; 34 import org.apache.tools.ant.util.DateUtils; 35 36 import org.eclipse.releng.util.rss.Messages; 37 import org.eclipse.releng.util.rss.RSSFeedUtil; 38 39 import org.w3c.dom.Document; 40 import org.w3c.dom.Element; 41 import org.w3c.dom.Node; 42 import org.xml.sax.SAXException; 43 44 /** 45 * Parameters: 46 * debug - more output to console - eg., 0|1|2 47 * 48 * file - path to the XML file that will be created - eg., /path/to/file.to.create.xml 49 * project - project's name, used to label the feed - eg., Eclipse, EMF, UML2 50 * branch - build's branch, eg., 2.2.0 51 * buildID - build's ID, eg., S200605051234 52 * feedURL - URL of the feed where it will be published - eg., http://servername/path/to/feed.xml 53 * note that feedURL is not required if the feed already exists, only if a new feed file must be created 54 * buildURL - URL of the build being added to the feed - eg., http://servername/path/to/project/branch/buildID/ 55 * 56 * buildAlias - build's alias, eg., 2.2.0RC2 57 * 58 * dependencyURLs - upstream dependencies, eg., UML2 depends on emf and eclipse, so specify TWO URLs in properties file or ant task 59 * 60 * releaseNotesURL - URL of the build's release notes page - eg., http://www.eclipse.org/project/news/release-notes.php 61 * updateManagerURL - URL of the build's Update Manager site - eg., http://servername/path/to/project/updates/ 62 * downloadsURL - URL of the build's downloads - eg., http://servername/path/to/project/downloads/ 63 * 64 * jarSigningStatus - code to define jar signing status - eg., one of: 65 * NONE (or '') - no status available or not participating 66 * UNSIGNED - no jar signage available or done yet 67 * SIGNREADY - jars promoted to eclipse.org, ready for signing 68 * BUILDREADY - signed on eclipse.org, ready to be collected and bundled as zips and copied to UM site 69 * SIGNED - signed & bundled on download page and on UM site 70 * 71 * callistoStatus - code to define Callisto status, eg., one of: 72 * NONE (or '') - not part of Callisto or unknown status 73 * BUILDCOMPLETE - Have you finished your RC1 bits? 74 * 2006-05-02T20:50:00Z - When do you expect to finish them? 75 * TPTP - If you're waiting for another project, which one(s)? (TPTP is just an example) 76 * UMSITEREADY - Have you placed those bits in your update site? 77 * CALLISTOSITEREADY - Have you updated the features.xml file in the Callisto CVS directory? 78 * COMPLETE - Are you ready for RC1 to be declared? 79 * 80 * buildType - code to define type of build, eg., one of: 81 * N - Nightly 82 * I - Integration 83 * M - Maintenance 84 * S - Stable (Milestone or Release Candidate) 85 * R - Release 86 * MC - Maintenance-Callisto 87 * SC - Stable-Callisto 88 * RC - Release-Callisto 89 * 90 * Releases - comma or space-separated list of releases in quints of os,ws,arch,type/name,filename,... 91 * - eg., win32,win,x86,SDK,eclipse-SDK-3.2RC5-win32.zip,linux,gtk,x86_64,SDK,eclipse-SDK-3.2RC5-linux-gtk.tar.gz 92 * - (for examples and definitions of ws, os + arch, see below) 93 * 94 * JUnitTestURL - URL of the build's JUnit test results - eg., http://servername/path/to/project/branch/buildID/testResults.php 95 * performanceTestURL - URL of the build's performance tests - eg., http://servername/path/to/project/branch/buildID/performance/performance.php 96 * APITestURL - URL of the build's API test results - eg., http://servername/path/to/project/branch/buildID/testResults.php 97 * 98 * JUnitTestResults - comma or space-separated list of test results in quads of os,ws,arch,status,os,ws,status,arch,... - eg., win32,win,x86,PASS,linux,gtk,x86,PASS 99 * performanceTestResults - comma or space-separated list of test results in quads of os,ws,arch,status,os,ws,status,arch,... - eg., win32,win,x86_64,PASS,linux,gtk,x86_64,PASS 100 * APITestResults - comma or space-separated list of test results in quads of os,ws,arch,status,os,ws,status,arch,... - eg., win32,win,ppc,PASS,linux,gtk,ppc,PASS 101 * ws - window system - eg., ALL, win32, win64, linux, macos... 102 * os - operating system - eg., ALL, win, gtk, motif, carbon, ... 103 * arch - architecture, eg., ALL, x86, x86_64, ppc, ... 104 * status - status code for test results - eg., one of: PASS, PENDING, FAIL, UNKNOWN, SKIPPED 105 * 106 * @author nickb 107 * 108 */ 109 public class RSSFeedAddEntryTask extends Task { 110 111 private int debug = 0; 112 113 private static final String now = getTimestamp(); 114 115 //$ANALYSIS-IGNORE codereview.java.rules.portability.RulePortabilityLineSeparators 116 private static final String NL="\n"; //$NON-NLS-1$ 117 private static final String NS = ""; //$NON-NLS-1$ 118 private static final String SEP = "----"; //$NON-NLS-1$ 119 private static final String SP = " "; //$NON-NLS-1$ 120 121 private static final String splitter = "[,\t " + NL + "]+"; //$NON-NLS-1$ //$NON-NLS-2$ 122 123 //required fields 124 private File file; 125 private String project; 126 private String branch; 127 private String buildID; 128 private String feedURL; 129 private String buildURL; 130 131 //optional 132 private String buildAlias; 133 134 //optional 135 private String[] dependencyURLs = new String[] {}; 136 137 //optional 138 private String releaseNotesURL; 139 private String updateManagerURL; 140 private String downloadsURL; 141 private String jarSigningStatus; 142 private String callistoStatus; 143 private String buildType; 144 145 //optional 146 private String[] releases = new String[] {}; 147 148 //optional 149 private String JUnitTestURL; 150 private String performanceTestURL; 151 private String APITestURL; 152 private String[] JUnitTestResults; 153 private String[] performanceTestResults; 154 private String[] APITestResults; 155 156 //optional setDebug(int debug)157 public void setDebug(int debug) { this.debug = debug; } 158 159 //required fields setFile(String file)160 public void setFile(String file) { 161 if (isNullString(file)) 162 { System.err.println(Messages.getString("RSSFeedCommon.FileError")); } //$NON-NLS-1$ 163 else 164 { this.file = new File(file); } 165 } setProject(String project)166 public void setProject(String project) { 167 if (isNullString(project)) 168 { System.err.println(Messages.getString("RSSFeedCommon.ProjectError")); } //$NON-NLS-1$ 169 else 170 { this.project = project; } 171 } setBranch(String branch)172 public void setBranch(String branch) { 173 if (isNullString(branch)) 174 { System.err.println(Messages.getString("RSSFeedAddEntryTask.BranchError")); } //$NON-NLS-1$ 175 else 176 { this.branch = branch; } 177 } setBuildID(String buildID)178 public void setBuildID(String buildID) { 179 if (isNullString(buildID)) 180 { System.err.println(Messages.getString("RSSFeedAddEntryTask.BuildIDError")); } //$NON-NLS-1$ 181 else 182 { this.buildID = buildID; } 183 } setFeedURL(String feedURL)184 public void setFeedURL(String feedURL) { 185 if (isNullString(feedURL)) 186 { System.err.println(Messages.getString("RSSFeedCommon.FeedURLError")); } //$NON-NLS-1$ 187 else 188 { this.feedURL = feedURL; } 189 } setBuildURL(String buildURL)190 public void setBuildURL(String buildURL) { 191 if (isNullString(buildURL)) 192 { System.err.println(Messages.getString("RSSFeedAddEntryTask.BuildURLError")); } //$NON-NLS-1$ 193 else 194 { this.buildURL = buildURL; } 195 } 196 197 //optional: alias is usually something like "3.2.0M6" setBuildAlias(String buildAlias)198 public void setBuildAlias(String buildAlias) { this.buildAlias = buildAlias; } 199 200 //optional: upstream dependencies, eg., UML2 depends on emf and eclipse, so specify TWO URLs in properties file or ant task setDependencyURLs(String dependencyURLs)201 public void setDependencyURLs(String dependencyURLs) { if (!isNullString(dependencyURLs)) { this.dependencyURLs = dependencyURLs.split(splitter); } } 202 203 //optional: define releases available in this build for a series of operating systems, windowing systems, and type setReleases(String releases)204 public void setReleases(String releases) { if (!isNullString(releases)) { this.releases = releases.split(splitter); } } 205 206 //optional: informational links to release notes, downloads, update manager setReleaseNotesURL(String releaseNotesURL)207 public void setReleaseNotesURL(String releaseNotesURL) { this.releaseNotesURL = releaseNotesURL; } setUpdateManagerURL(String updateManagerURL)208 public void setUpdateManagerURL(String updateManagerURL) { this.updateManagerURL = updateManagerURL; } setDownloadsURL(String downloadsURL)209 public void setDownloadsURL(String downloadsURL) { this.downloadsURL = downloadsURL; } setJarSigningStatus(String jarSigningStatus)210 public void setJarSigningStatus(String jarSigningStatus) { this.jarSigningStatus = jarSigningStatus; } setCallistoStatus(String callistoStatus)211 public void setCallistoStatus(String callistoStatus) { this.callistoStatus = callistoStatus; } setBuildType(String buildType)212 public void setBuildType(String buildType) { 213 if (!isNullString(buildType)) 214 { 215 this.buildType = buildType; 216 } 217 else 218 { 219 this.buildType = buildID.replaceAll("[^NIMSR]", NS); //$NON-NLS-1$ 220 if (this.buildType.length()>1) 221 { 222 this.buildType=this.buildType.substring(0, 1); 223 } 224 } 225 226 } 227 228 //optional: test URLs and results setJUnitTestURL(String JUnitTestURL)229 public void setJUnitTestURL(String JUnitTestURL) { this.JUnitTestURL = JUnitTestURL; } setPerformanceTestURL(String performanceTestURL)230 public void setPerformanceTestURL(String performanceTestURL) { this.performanceTestURL = performanceTestURL; } setAPITestURL(String APITestURL)231 public void setAPITestURL(String APITestURL) { this.APITestURL = APITestURL; } setJUnitTestResults(String JUnitTestResults)232 public void setJUnitTestResults(String JUnitTestResults) { if (!isNullString(JUnitTestResults)) { this.JUnitTestResults = JUnitTestResults.split(splitter); } } setPerformanceTestResults(String performanceTestResults)233 public void setPerformanceTestResults(String performanceTestResults) { if (!isNullString(performanceTestResults)) { this.performanceTestResults = performanceTestResults.split(splitter); } } setAPITestResults(String APITestResults)234 public void setAPITestResults(String APITestResults) { if (!isNullString(APITestResults)) { this.APITestResults = APITestResults.split(splitter); } } 235 236 // The method executing the task execute()237 public void execute() throws BuildException { 238 if (debug>0) { 239 System.out.println(Messages.getString("RSSFeedAddEntryTask.AddingEntryTo") + project + SP + Messages.getString("RSSFeedCommon.RSSFeedFile") + SP + file.toString() + ", " + Messages.getString("RSSFeedCommon.ToBePublishedAt") + feedURL); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ 240 } 241 updateFeedXML(file); // load previous 242 } 243 244 //$ANALYSIS-IGNORE codereview.java.rules.exceptions.RuleExceptionsSpecificExceptions updateFeedXML(File file)245 private void updateFeedXML(File file){ 246 if (!file.exists()) { 247 System.out.println(Messages.getString("RSSFeedCommon.RSSFeedFile") + SP + file.toString() + SP + Messages.getString("RSSFeedAddEntryTask.DoesNotExist")); //$NON-NLS-1$ //$NON-NLS-2$ 248 RSSFeedCreateFeedTask creator=new RSSFeedCreateFeedTask(); 249 creator.setFile(file.toString()); 250 creator.setFeedURL(feedURL); 251 creator.setProject(project); 252 creator.setDebug(debug); 253 creator.execute(); 254 } 255 DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance(); 256 documentBuilderFactory.setNamespaceAware(true); 257 DocumentBuilder documentBuilder=null; 258 try { 259 documentBuilder=documentBuilderFactory.newDocumentBuilder(); 260 } 261 catch (ParserConfigurationException e) { 262 e.printStackTrace(); 263 } 264 Document document=null; 265 try { 266 document=documentBuilder.parse(file); 267 } 268 catch (SAXException e) { 269 e.printStackTrace(); 270 } 271 catch (IOException e) { 272 e.printStackTrace(); 273 } 274 275 Transformer transformer = null; 276 try { 277 transformer = createTransformer("UTF-8"); //$NON-NLS-1$ 278 } catch (TransformerException e) { 279 e.printStackTrace(); 280 } 281 282 Element element=document.getDocumentElement(); 283 for (Node child=element.getFirstChild(); child != null; child=child.getNextSibling()) { 284 if ("updated".equals(child.getLocalName())) { //$NON-NLS-1$ 285 if (debug > 0) { 286 System.out.println(Messages.getString("RSSFeedCommon.Set") + " <" + child.getLocalName()+ ">"+ now+ "</"+ child.getLocalName()+ ">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ 287 } 288 ((Element)child).setTextContent(now); 289 } 290 else if ("id".equals(child.getLocalName())) { //$NON-NLS-1$ 291 Node newNode=createEntry(document); 292 if (debug > 0) { 293 System.out.println(Messages.getString("RSSFeedAddEntryTask.AttachNew") + " <entry/>"); //$NON-NLS-1$ //$NON-NLS-2$ 294 } 295 try { 296 if (debug > 0) { 297 System.out.println(SEP); //$NON-NLS-1$ 298 transformer.transform(new DOMSource(newNode),new StreamResult(System.out)); 299 System.out.println(SEP); //$NON-NLS-1$ 300 } 301 } 302 catch (TransformerException e) { 303 e.printStackTrace(); 304 } 305 Node refNode=child.getNextSibling(); 306 element.insertBefore(document.createTextNode(NL + " "),refNode); //$NON-NLS-1$ 307 element.insertBefore(newNode,refNode); 308 break; 309 } 310 } 311 try { 312 transformer.transform(new DOMSource(document),new StreamResult(new OutputStreamWriter(new FileOutputStream(file)))); 313 if (debug > 1) { 314 System.out.println(SEP); //$NON-NLS-1$ 315 transformer.transform(new DOMSource(document),new StreamResult(System.out)); 316 System.out.println(SEP); //$NON-NLS-1$ 317 } 318 } 319 catch (FileNotFoundException e) { 320 e.printStackTrace(); 321 } 322 catch (TransformerException e) { 323 e.printStackTrace(); 324 } 325 } 326 327 createEntry(Document document)328 private Element createEntry(Document document) { 329 330 // <entry> 331 Element entry = document.createElement("entry"); //$NON-NLS-1$ 332 333 String[] txt = { NL + " ", NL + " ", NL + " ", NL + " ", NL + " " , NL + " " }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ 334 Element elem = null; 335 336 String projectVersionString = project + SP + (!isNullString(buildAlias)? //$NON-NLS-1$ 337 (buildAlias.startsWith(branch) ? 338 buildAlias + " (" + buildID + ")" : // 2.2.0RC2 (S200605051234) //$NON-NLS-1$ //$NON-NLS-2$ 339 buildAlias + " (" + branch + "." + buildID + ")") : // Foobar (2.2.0.S200605051234) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 340 branch + SP + buildID); // 2.2.0.S200605051234 //$NON-NLS-1$ 341 342 doVarSubs(); 343 344 // <title>[announce] " + project + SP + branch + SP + buildID + " is available</title> 345 elem = document.createElement("title"); //$NON-NLS-1$ 346 elem.setTextContent(Messages.getString("RSSFeedAddEntryTask.AnnouncePrefix") + projectVersionString + SP + Messages.getString("RSSFeedAddEntryTask.IsAvailable")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 347 attachNode(document, entry, elem, txt[1]); 348 349 // <link href=\"" + buildURL + "\"/> 350 elem = document.createElement("link"); //$NON-NLS-1$ 351 elem.setAttribute("href", !isNullString(buildURL) ? buildURL : projectVersionString); //$NON-NLS-1$ 352 attachNode(document, entry, elem, txt[1]); 353 354 // <id>" + buildURL + "</id> 355 elem = document.createElement("id"); //$NON-NLS-1$ 356 elem.setTextContent(!isNullString(buildURL) ? buildURL : projectVersionString); 357 attachNode(document, entry, elem, txt[1]); 358 359 // <updated>" + getTimestamp() + "</updated> 360 elem = document.createElement("updated"); //$NON-NLS-1$ 361 elem.setTextContent(now); 362 attachNode(document, entry, elem, txt[1]); 363 364 // <summary> 365 Element summary = document.createElement("summary"); //$NON-NLS-1$ 366 attachNode(document, entry, summary, txt[1]); 367 368 // <build callisto="" jars="" type="" href="" xmlns="http://www.eclipse.org/2006/BuildFeed"> 369 Element build = document.createElement("build"); //$NON-NLS-1$ 370 build.setAttribute("jars", jarSigningStatus); //$NON-NLS-1$ 371 build.setAttribute("callisto", callistoStatus); //$NON-NLS-1$ 372 build.setAttribute("type", buildType); //$NON-NLS-1$ 373 build.setAttribute("xmlns", "http://www.eclipse.org/2006/BuildFeed"); //$NON-NLS-1$ //$NON-NLS-2$ 374 if (!isNullString(buildURL)) { 375 build.setAttribute("href",buildURL); //$NON-NLS-1$ 376 } 377 attachNode(document, summary, build, txt[2]); 378 379 // <update>" + usiteURL + "</update> 380 if (!isNullString(updateManagerURL)) { 381 elem = document.createElement("update"); //$NON-NLS-1$ 382 elem.setTextContent(updateManagerURL); 383 attachNode(document, build, elem, txt[3]); 384 } 385 386 // <downloads>" + dropsURL + "</downloads> 387 if (!isNullString(downloadsURL)) { 388 elem = document.createElement("downloads"); //$NON-NLS-1$ 389 elem.setTextContent(downloadsURL); 390 attachNode(document, build, elem, txt[3]); 391 } 392 393 // <releasenotes>" + releaseNotesURL + "</releasenotes> 394 if (!isNullString(releaseNotesURL)) { 395 elem = document.createElement("releasenotes"); //$NON-NLS-1$ 396 elem.setTextContent(releaseNotesURL); 397 attachNode(document, build, elem, txt[3]); 398 } 399 400 // <releases> 401 // <release os="" ws="" type=""> + filename + </release> 402 if (releases!=null && releases.length>0) { 403 if (releases.length % 5 != 0) { 404 System.err.println(Messages.getString("RSSFeedAddEntryTask.WrongNumberOfVariables") + SP + Messages.getString("RSSFeedAddEntryTask.MustBeMultipleOf5") + SP + Messages.getString("RSSFeedAddEntryTask.InProperty") + SP + "releases"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 405 } 406 Element releasesElem = document.createElement("releases"); //$NON-NLS-1$ 407 for (int i = 0; i < releases.length; i+=5) 408 { 409 Element release = document.createElement("release"); //$NON-NLS-1$ 410 release.setAttribute("os", releases[i]); //$NON-NLS-1$ 411 release.setAttribute("ws", releases[i+1]); //$NON-NLS-1$ 412 release.setAttribute("arch", releases[i+2]); //$NON-NLS-1$ 413 release.setAttribute("type", releases[i+3]); //$NON-NLS-1$ 414 release.setTextContent(varSub(releases[i+4])); 415 attachNode(document, releasesElem, release, txt[4]); 416 } 417 attachNode(document, build, releasesElem, txt[3]); 418 } 419 420 // <tests> 421 Element tests = document.createElement("tests"); //$NON-NLS-1$ 422 423 // <test type=\"junit\" href=\"" + JUnitTestURL + "\"/> 424 if (!isNullString(JUnitTestURL)) { 425 Element test = document.createElement("test"); //$NON-NLS-1$ 426 test.setAttribute("type", "junit"); //$NON-NLS-1$ //$NON-NLS-2$ 427 test.setAttribute("href", JUnitTestURL); //$NON-NLS-1$ 428 if (JUnitTestResults!=null && JUnitTestResults.length>0) { 429 if (JUnitTestResults.length % 4 != 0) { 430 System.err.println(Messages.getString("RSSFeedAddEntryTask.WrongNumberOfVariables") + SP + Messages.getString("RSSFeedAddEntryTask.MustBeMultipleOf4") + SP + Messages.getString("RSSFeedAddEntryTask.InProperty") + SP + "JUnitTestResults"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 431 } 432 for (int i = 0; i < JUnitTestResults.length; i+=4) 433 { 434 Element result = document.createElement("result"); //$NON-NLS-1$ 435 result.setAttribute("os", JUnitTestResults[i]); //$NON-NLS-1$ 436 result.setAttribute("ws", JUnitTestResults[i+1]); //$NON-NLS-1$ 437 result.setAttribute("arch", JUnitTestResults[i+2]); //$NON-NLS-1$ 438 result.setTextContent(JUnitTestResults[i+3]); 439 attachNode(document, test, result, txt[5]); 440 } 441 // extra space to close containing tag 442 elem.appendChild(document.createTextNode(txt[4])); 443 } 444 attachNode(document, tests, test, txt[4]); 445 } 446 447 // <test type=\"performance\" href=\"" + performanceTestURL + "\"/> 448 if (!isNullString(performanceTestURL)) { 449 Element test = document.createElement("test"); //$NON-NLS-1$ 450 test.setAttribute("type", "performance"); //$NON-NLS-1$ //$NON-NLS-2$ 451 test.setAttribute("href", performanceTestURL); //$NON-NLS-1$ 452 if (performanceTestResults!=null && performanceTestResults.length>0) { 453 if (performanceTestResults.length % 4 != 0) { 454 System.err.println(Messages.getString("RSSFeedAddEntryTask.WrongNumberOfVariables") + SP + Messages.getString("RSSFeedAddEntryTask.MustBeMultipleOf4") + SP + Messages.getString("RSSFeedAddEntryTask.InProperty") + SP + "performanceTestResults"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 455 } 456 for (int i = 0; i < performanceTestResults.length; i+=4) 457 { 458 Element result = document.createElement("result"); //$NON-NLS-1$ 459 result.setAttribute("os", performanceTestResults[i]); //$NON-NLS-1$ 460 result.setAttribute("ws", performanceTestResults[i+1]); //$NON-NLS-1$ 461 result.setAttribute("arch", performanceTestResults[i+2]); //$NON-NLS-1$ 462 result.setTextContent(performanceTestResults[i+3]); 463 attachNode(document, test, result, txt[5]); 464 } 465 // extra space to close containing tag 466 test.appendChild(document.createTextNode(txt[4])); 467 } 468 attachNode(document, tests, test, txt[4]); 469 } 470 471 // <test type=\"performance\" href=\"" + performanceTestURL + "\"/> 472 if (!isNullString(APITestURL)) { 473 Element test = document.createElement("test"); //$NON-NLS-1$ 474 test.setAttribute("type", "api"); //$NON-NLS-1$ //$NON-NLS-2$ 475 test.setAttribute("href", APITestURL); //$NON-NLS-1$ 476 if (APITestResults!=null && APITestResults.length>0) { 477 if (APITestResults.length % 4 != 0) { 478 System.err.println(Messages.getString("RSSFeedAddEntryTask.WrongNumberOfVariables") + SP + Messages.getString("RSSFeedAddEntryTask.MustBeMultipleOf4") + SP + Messages.getString("RSSFeedAddEntryTask.InProperty") + SP + "APITestResults"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 479 } 480 for (int i = 0; i < APITestResults.length; i+=4) 481 { 482 Element result = document.createElement("result"); //$NON-NLS-1$ 483 result.setAttribute("os", APITestResults[i]); //$NON-NLS-1$ 484 result.setAttribute("ws", APITestResults[i+1]); //$NON-NLS-1$ 485 result.setAttribute("arch", APITestResults[i+2]); //$NON-NLS-1$ 486 result.setTextContent(APITestResults[i+3]); 487 attachNode(document, tests, result, txt[5]); 488 } 489 // extra space to close containing tag 490 test.appendChild(document.createTextNode(txt[4])); 491 } 492 attachNode(document, tests, test, txt[4]); 493 } 494 495 attachNode(document, build, tests, txt[3]); 496 497 if (dependencyURLs!=null && dependencyURLs.length>0) { 498 // <dependencies> 499 // <dependency>" + dependencyURL + "</dependency> 500 Element dependencies = document.createElement("dependencies"); //$NON-NLS-1$ 501 for (int i = 0; i < dependencyURLs.length; i++) 502 { 503 elem = document.createElement("dependency"); //$NON-NLS-1$ 504 elem.setTextContent(dependencyURLs[i]); 505 attachNode(document, dependencies, elem, txt[4]); 506 } 507 attachNode(document, build, dependencies, txt[3]); 508 } 509 510 return entry; 511 } 512 513 //$ANALYSIS-IGNORE codereview.java.rules.exceptions.RuleExceptionsSpecificExceptions attachNode(Document document,Element entry,Element elem,String txt)514 private void attachNode(Document document,Element entry,Element elem,String txt){ 515 entry.appendChild(document.createTextNode(txt)); 516 entry.appendChild(elem); 517 } 518 getTimestamp()519 private static String getTimestamp() { // eg., 2006-04-10T20:40:08Z 520 return DateUtils.format(new Date(), DateUtils.ISO8601_DATETIME_PATTERN) + "Z"; //$NON-NLS-1$ 521 } 522 doVarSubs()523 private void doVarSubs() 524 { 525 feedURL = varSub(feedURL); 526 buildURL = varSub(buildURL); 527 528 releaseNotesURL = varSub(releaseNotesURL); 529 updateManagerURL = varSub(updateManagerURL); 530 downloadsURL = varSub(downloadsURL); 531 532 JUnitTestURL = varSub(JUnitTestURL); 533 performanceTestURL = varSub(performanceTestURL); 534 APITestURL = varSub(APITestURL); 535 } 536 createTransformer(String encoding)537 public static Transformer createTransformer(String encoding) throws TransformerException 538 { 539 TransformerFactory transformerFactory = TransformerFactory.newInstance(); 540 541 try 542 { 543 transformerFactory.setAttribute("indent-number", new Integer(2)); //$NON-NLS-1$ 544 } 545 catch (IllegalArgumentException exception) 546 { 547 } 548 549 Transformer transformer = transformerFactory.newTransformer(); 550 551 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ 552 transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ 553 554 // Unless a width is set, there will be only line breaks but no indentation. 555 // The IBM JDK and the Sun JDK don't agree on the property name, 556 // so we set them both. 557 // 558 transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2"); //$NON-NLS-1$ //$NON-NLS-2$ 559 transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); //$NON-NLS-1$ //$NON-NLS-2$ 560 if (encoding != null) 561 { 562 transformer.setOutputProperty(OutputKeys.ENCODING, encoding); 563 } 564 return transformer; 565 } 566 567 /* 568 * variable substitution in URLs - eg., replace %%branch%% and %%buildID%% in buildURL 569 */ varSub(String urlstring)570 private String varSub(String urlstring) 571 { 572 if (!isNullString(urlstring) && urlstring.indexOf("%%")>=0) //$NON-NLS-1$ 573 { 574 return urlstring.replaceAll(Messages.getString("RSSFeedAddEntryTask.BranchKeyword"), branch).replaceAll(Messages.getString("RSSFeedAddEntryTask.BuildIDKeyword"), buildID).replaceAll(Messages.getString("RSSFeedAddEntryTask.BuildAliasKeyword"), buildAlias); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 575 } 576 return urlstring; 577 } 578 isNullString(String str)579 private static boolean isNullString(String str) 580 { 581 return RSSFeedUtil.isNullString(str); 582 } 583 584 }