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.services.rss; 12 13 import java.io.File; 14 import java.io.FileInputStream; 15 import java.io.FileNotFoundException; 16 import java.io.FileOutputStream; 17 import java.io.IOException; 18 import java.net.MalformedURLException; 19 import java.net.URL; 20 21 import org.apache.tools.ant.BuildException; 22 import org.apache.tools.ant.Task; 23 import org.apache.tools.ant.taskdefs.ExecTask; 24 25 import org.eclipse.releng.generators.rss.RSSFeedUpdateEntryTask; 26 import org.eclipse.releng.util.rss.Messages; 27 import org.eclipse.releng.util.rss.RSSFeedUtil; 28 29 /** 30 * Parameters: 31 * debug - more output to console - eg., 0|1|2 32 * 33 * file - path to the XML file that will be published - eg., /path/to/file.to.publish.xml 34 * feedURL - URL of the feed where it will be published - eg., http://servername/path/to/feed.xml 35 * 36 * feedWatchActions - semi-comma-separated list of triplets: 37 * (Xpath to watch for); (what to execute if condition is met); (commandline args to the executable)... 38 * eg., to watch for ANY change in the feed and respond by sending email 39 * /*[name() = 'feed']/*[name() = 'updated']/text(); sendEmailAlert.sh; null 40 * eg., to watch for ANY changes in the current build 41 * //*[name() = 'entry'][1]/*[name() = 'updated']/text(); sendEmailAlert.sh; null 42 * eg., to watch for changes in the current build's performance test results on linux-gtk 43 * //*[name() = 'entry'][1]/*[name() = 'summary']/*[@type = 'performance'][1]/*[name() = 'results'][@os = 'linux'][@ws = 'gtk']/text(); sendEmailAlert.sh; null 44 * 45 * @author nickb 46 * 47 */ 48 public class RSSFeedWatcherTask extends Task { 49 50 private int debug = 0; 51 52 private static final String CL = ":"; //$NON-NLS-1$ 53 private static final String DOT = "."; //$NON-NLS-1$ 54 private static final String NS = ""; //$NON-NLS-1$ 55 private static final String SP = " "; //$NON-NLS-1$ 56 57 private static final String splitter = "[;\t\r\n]+"; //$NON-NLS-1$ 58 59 private static final String feedWatchActionError = "feedWatchAction.Error"; //$NON-NLS-1$ 60 private static final String feedWatchActionOuput = "feedWatchAction.Output"; //$NON-NLS-1$ 61 private static final String feedWatchActionResult = "feedWatchAction.Result"; //$NON-NLS-1$ 62 private static final String feedWatchActionNewValue = "feedWatchAction.NewValue"; //$NON-NLS-1$ 63 private static final String feedWatchActionOldValue = "feedWatchAction.OldValue"; //$NON-NLS-1$ 64 private static final String feedWatchActionTheValue = "feedWatchAction.TheValue"; //$NON-NLS-1$ 65 66 private static final RSSFeedUtil util = new RSSFeedUtil(); 67 68 //required fields 69 private File file; 70 private File tmpFile; 71 private String feedURL; 72 private String[] feedWatchActions = new String[] {}; 73 74 //optional 75 public void setDebug(int debug) { this.debug = debug; } 76 77 //required 78 public void setFile(String file) { 79 if (!isNullString(file)) { 80 this.file = new File(file); 81 this.tmpFile = new File(file + ".tmp"); //$NON-NLS-1$ 82 } 83 } 84 public void setFeedURL(String feedURL) { 85 if (isNullString(feedURL)) 86 { System.err.println(Messages.getString("RSSFeedCommon.FeedURLError")); } //$NON-NLS-1$ 87 else 88 { this.feedURL = feedURL; } 89 } 90 public void setFeedWatchActions(String feedWatchActions) { 91 int missingActions = 0; 92 if (!isNullString(feedWatchActions)) { 93 this.feedWatchActions = feedWatchActions.split(splitter); 94 missingActions = this.feedWatchActions.length % 3; if (missingActions > 0) { missingActions = 3 - missingActions; } 95 } 96 if (missingActions > 0) { 97 for (int i = 0; i < missingActions; i++) 98 { 99 System.out.println((i==0 && missingActions==2 ? Messages.getString("RSSFeedWatcherTask.WarningNoScriptAction") : Messages.getString("RSSFeedWatcherTask.WarningNoCommandlineParams")) + SP + feedWatchActions ); //$NON-NLS-1$ //$NON-NLS-2$ 100 feedWatchActions += "; null"; //$NON-NLS-1$ 101 } 102 this.feedWatchActions = feedWatchActions.split(splitter); 103 } 104 } 105 106 // The method executing the task 107 public void execute() throws BuildException { 108 if (debug>0) { util.setDebug(debug); } 109 if (file==null || !file.exists() || !file.isFile()) { 110 // if there's no local copy of the feed, get a copy, then exit with instructions 111 downloadFeed(file,debug>=0); 112 System.out.println(Messages.getString("RSSFeedWatcherTask.PleaseRunThisTaskLater") + SP + file); //$NON-NLS-1$ 113 System.out.println(Messages.getString("RSSFeedWatcherTask.ToTheLatestVersion") + SP + feedURL); //$NON-NLS-1$ 114 } else { 115 if (feedWatchActions==null || feedWatchActions.length<1) { 116 System.err.println(Messages.getString("RSSFeedWatcherTask.ErrorNoWatchActions")); //$NON-NLS-1$ 117 } else { 118 checkFeed(); 119 } 120 } 121 } 122 123 private void checkFeed() { 124 if (file.isDirectory()) { 125 System.err.println(Messages.getString("RSSFeedWatcherTask.ErrorDestinationFileIsADirectory")); //$NON-NLS-1$ 126 } else { 127 downloadFeed(tmpFile,debug>0); 128 } 129 130 if (tmpFile.isFile()) { 131 if (debug>0) { System.out.println(Messages.getString("RSSFeedWatcherTask.Compare") + SP + file + Messages.getString("RSSFeedWatcherTask.with") + tmpFile + CL); } //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 132 133 RSSFeedUpdateEntryTask oldFeedWatcher = null; 134 RSSFeedUpdateEntryTask newFeedWatcher = null; 135 int j=0; 136 137 for (int i = 0; i < feedWatchActions.length; i+=3) 138 { 139 String xpath = feedWatchActions[i].trim(); 140 String action = feedWatchActions[i+1].trim(); 141 String commandline = feedWatchActions[i+2].trim(); 142 143 oldFeedWatcher = new RSSFeedUpdateEntryTask(); 144 oldFeedWatcher.setFile(file.toString()); 145 if (debug>0) { oldFeedWatcher.setDebug(debug); } 146 oldFeedWatcher.setXpath(xpath); 147 oldFeedWatcher.execute(); 148 149 if (oldFeedWatcher.getFoundNode() != null) { 150 newFeedWatcher = new RSSFeedUpdateEntryTask(); 151 newFeedWatcher.setFile(tmpFile.toString()); 152 if (debug>0) { newFeedWatcher.setDebug(debug); } 153 newFeedWatcher.setXpath(xpath); 154 newFeedWatcher.execute(); 155 156 String oldContent = oldFeedWatcher.getFoundNode().getTextContent(); 157 String newContent = newFeedWatcher.getFoundNode().getTextContent(); 158 159 if (debug>1) { 160 System.out.println(Messages.getString("RSSFeedWatcherTask.GotOldNodeContents") + CL + SP + oldContent); //$NON-NLS-1$ 161 System.out.println(Messages.getString("RSSFeedWatcherTask.GotNewNodeContents") + CL + SP + newContent); //$NON-NLS-1$ 162 } 163 164 if (!"null".equals(action)) { //$NON-NLS-1$ 165 commandline = 166 (debug>0?"-debug " + debug + SP:NS) + ("null".equals(commandline)?NS:commandline) + //$NON-NLS-1$ //$NON-NLS-2$ 167 " -feedURL " + feedURL + //$NON-NLS-1$ 168 " -xpath \"" + xpath + "\"" + //$NON-NLS-1$ //$NON-NLS-2$ 169 " -oldvalue \"" + oldContent + "\"" + //$NON-NLS-1$ //$NON-NLS-2$ 170 " -newvalue \"" + newContent + "\""; //$NON-NLS-1$ //$NON-NLS-2$ 171 } 172 173 // store actual value - either the changed value or the original value (if unchanged) 174 this.getProject().setProperty(feedWatchActionTheValue + DOT + j,!isNullString(newContent)?newContent:oldContent); 175 176 if (newFeedWatcher.getFoundNode() == null || // changed from exists to not exists, or 177 !oldContent.equals(newContent) // node has changed 178 ) { 179 // collect property from newNode and pass it to THIS task so that the local ant script can see it 180 if (!isNullString(oldContent)) { this.getProject().setProperty(feedWatchActionOldValue + DOT + j,oldContent); } 181 if (!isNullString(newContent)) { this.getProject().setProperty(feedWatchActionNewValue + DOT + j,newContent); } 182 183 if (!"null".equals(action)) { //$NON-NLS-1$ 184 System.out.println(Messages.getString("RSSFeedWatcherTask.RunExecTask") + CL + SP + action + SP + commandline); //$NON-NLS-1$ 185 ExecTask exec = util.runExecTask((new File(action)).getAbsolutePath(), commandline, null); 186 187 // collect properties from exec task and pass them to THIS task so that the local ant script can see them 188 String out = null; 189 190 out = exec.getProject().getProperty(RSSFeedUtil.RUN_EXEC_TASK_ERROR); 191 if (!isNullString(out)) { this.getProject().setProperty(feedWatchActionError + DOT + j, out); } 192 193 out = exec.getProject().getProperty(RSSFeedUtil.RUN_EXEC_TASK_RESULT); 194 if (!isNullString(out)) { this.getProject().setProperty(feedWatchActionOuput + DOT + j, out); } 195 196 out = exec.getProject().getProperty(RSSFeedUtil.RUN_EXEC_TASK_RESULT); 197 if (!RSSFeedUtil.EXPECTED_RESULT.equals(out)) { this.getProject().setProperty(feedWatchActionResult + DOT + j, out); } 198 } 199 } else { 200 System.out.println(Messages.getString("RSSFeedWatcherTask.NodeUnchanged")); //$NON-NLS-1$ 201 } 202 } else { 203 System.out.println(Messages.getString("RSSFeedWatcherTask.NodeNotFound")); //$NON-NLS-1$ 204 } 205 j++; 206 } 207 208 try 209 { 210 RSSFeedUtil.transferData(new FileInputStream(tmpFile), new FileOutputStream(file)); 211 tmpFile.deleteOnExit(); 212 } 213 catch (FileNotFoundException e) 214 { 215 e.printStackTrace(); 216 } 217 catch (IOException e) 218 { 219 e.printStackTrace(); 220 } 221 } 222 } 223 224 private void downloadFeed(File destFile, boolean verbose) 225 { 226 try 227 { 228 if (verbose) { 229 System.out.println(Messages.getString("RSSFeedWatcherTask.Download") + CL + SP + feedURL); //$NON-NLS-1$ 230 System.out.println(Messages.getString("RSSFeedWatcherTask.To") + CL + SP + destFile + SP); //$NON-NLS-1$ 231 } 232 RSSFeedUtil.transferData((new URL(feedURL)).openStream(), new FileOutputStream(destFile)); 233 if (verbose) { 234 System.out.println(Messages.getString("RSSFeedWatcherTask.Done")); //$NON-NLS-1$ 235 System.out.println(SP); 236 } 237 } 238 catch (MalformedURLException e) 239 { 240 e.printStackTrace(); 241 } 242 catch (FileNotFoundException e) 243 { 244 e.printStackTrace(); 245 } 246 catch (IOException e) 247 { 248 e.printStackTrace(); 249 } 250 } 251 252 private static boolean isNullString(String str) 253 { 254 return RSSFeedUtil.isNullString(str); 255 } 256 257 }