/******************************************************************************* * Copyright (c) 2005, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.releng.services.rss; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.ExecTask; import org.eclipse.releng.generators.rss.RSSFeedUpdateEntryTask; import org.eclipse.releng.util.rss.Messages; import org.eclipse.releng.util.rss.RSSFeedUtil; /** * Parameters: * debug - more output to console - eg., 0|1|2 * * file - path to the XML file that will be published - eg., /path/to/file.to.publish.xml * feedURL - URL of the feed where it will be published - eg., http://servername/path/to/feed.xml * * feedWatchActions - semi-comma-separated list of triplets: * (Xpath to watch for); (what to execute if condition is met); (commandline args to the executable)... * eg., to watch for ANY change in the feed and respond by sending email * /*[name() = 'feed']/*[name() = 'updated']/text(); sendEmailAlert.sh; null * eg., to watch for ANY changes in the current build * //*[name() = 'entry'][1]/*[name() = 'updated']/text(); sendEmailAlert.sh; null * eg., to watch for changes in the current build's performance test results on linux-gtk * //*[name() = 'entry'][1]/*[name() = 'summary']/*[@type = 'performance'][1]/*[name() = 'results'][@os = 'linux'][@ws = 'gtk']/text(); sendEmailAlert.sh; null * * @author nickb * */ public class RSSFeedWatcherTask extends Task { private int debug = 0; private static final String CL = ":"; //$NON-NLS-1$ private static final String DOT = "."; //$NON-NLS-1$ private static final String NS = ""; //$NON-NLS-1$ private static final String SP = " "; //$NON-NLS-1$ private static final String splitter = "[;\t\r\n]+"; //$NON-NLS-1$ private static final String feedWatchActionError = "feedWatchAction.Error"; //$NON-NLS-1$ private static final String feedWatchActionOuput = "feedWatchAction.Output"; //$NON-NLS-1$ private static final String feedWatchActionResult = "feedWatchAction.Result"; //$NON-NLS-1$ private static final String feedWatchActionNewValue = "feedWatchAction.NewValue"; //$NON-NLS-1$ private static final String feedWatchActionOldValue = "feedWatchAction.OldValue"; //$NON-NLS-1$ private static final String feedWatchActionTheValue = "feedWatchAction.TheValue"; //$NON-NLS-1$ private static final RSSFeedUtil util = new RSSFeedUtil(); //required fields private File file; private File tmpFile; private String feedURL; private String[] feedWatchActions = new String[] {}; //optional public void setDebug(int debug) { this.debug = debug; } //required public void setFile(String file) { if (!isNullString(file)) { this.file = new File(file); this.tmpFile = new File(file + ".tmp"); //$NON-NLS-1$ } } public void setFeedURL(String feedURL) { if (isNullString(feedURL)) { System.err.println(Messages.getString("RSSFeedCommon.FeedURLError")); } //$NON-NLS-1$ else { this.feedURL = feedURL; } } public void setFeedWatchActions(String feedWatchActions) { int missingActions = 0; if (!isNullString(feedWatchActions)) { this.feedWatchActions = feedWatchActions.split(splitter); missingActions = this.feedWatchActions.length % 3; if (missingActions > 0) { missingActions = 3 - missingActions; } } if (missingActions > 0) { for (int i = 0; i < missingActions; i++) { System.out.println((i==0 && missingActions==2 ? Messages.getString("RSSFeedWatcherTask.WarningNoScriptAction") : Messages.getString("RSSFeedWatcherTask.WarningNoCommandlineParams")) + SP + feedWatchActions ); //$NON-NLS-1$ //$NON-NLS-2$ feedWatchActions += "; null"; //$NON-NLS-1$ } this.feedWatchActions = feedWatchActions.split(splitter); } } // The method executing the task public void execute() throws BuildException { if (debug>0) { util.setDebug(debug); } if (file==null || !file.exists() || !file.isFile()) { // if there's no local copy of the feed, get a copy, then exit with instructions downloadFeed(file,debug>=0); System.out.println(Messages.getString("RSSFeedWatcherTask.PleaseRunThisTaskLater") + SP + file); //$NON-NLS-1$ System.out.println(Messages.getString("RSSFeedWatcherTask.ToTheLatestVersion") + SP + feedURL); //$NON-NLS-1$ } else { if (feedWatchActions==null || feedWatchActions.length<1) { System.err.println(Messages.getString("RSSFeedWatcherTask.ErrorNoWatchActions")); //$NON-NLS-1$ } else { checkFeed(); } } } private void checkFeed() { if (file.isDirectory()) { System.err.println(Messages.getString("RSSFeedWatcherTask.ErrorDestinationFileIsADirectory")); //$NON-NLS-1$ } else { downloadFeed(tmpFile,debug>0); } if (tmpFile.isFile()) { 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$ RSSFeedUpdateEntryTask oldFeedWatcher = null; RSSFeedUpdateEntryTask newFeedWatcher = null; int j=0; for (int i = 0; i < feedWatchActions.length; i+=3) { String xpath = feedWatchActions[i].trim(); String action = feedWatchActions[i+1].trim(); String commandline = feedWatchActions[i+2].trim(); oldFeedWatcher = new RSSFeedUpdateEntryTask(); oldFeedWatcher.setFile(file.toString()); if (debug>0) { oldFeedWatcher.setDebug(debug); } oldFeedWatcher.setXpath(xpath); oldFeedWatcher.execute(); if (oldFeedWatcher.getFoundNode() != null) { newFeedWatcher = new RSSFeedUpdateEntryTask(); newFeedWatcher.setFile(tmpFile.toString()); if (debug>0) { newFeedWatcher.setDebug(debug); } newFeedWatcher.setXpath(xpath); newFeedWatcher.execute(); String oldContent = oldFeedWatcher.getFoundNode().getTextContent(); String newContent = newFeedWatcher.getFoundNode().getTextContent(); if (debug>1) { System.out.println(Messages.getString("RSSFeedWatcherTask.GotOldNodeContents") + CL + SP + oldContent); //$NON-NLS-1$ System.out.println(Messages.getString("RSSFeedWatcherTask.GotNewNodeContents") + CL + SP + newContent); //$NON-NLS-1$ } if (!"null".equals(action)) { //$NON-NLS-1$ commandline = (debug>0?"-debug " + debug + SP:NS) + ("null".equals(commandline)?NS:commandline) + //$NON-NLS-1$ //$NON-NLS-2$ " -feedURL " + feedURL + //$NON-NLS-1$ " -xpath \"" + xpath + "\"" + //$NON-NLS-1$ //$NON-NLS-2$ " -oldvalue \"" + oldContent + "\"" + //$NON-NLS-1$ //$NON-NLS-2$ " -newvalue \"" + newContent + "\""; //$NON-NLS-1$ //$NON-NLS-2$ } // store actual value - either the changed value or the original value (if unchanged) this.getProject().setProperty(feedWatchActionTheValue + DOT + j,!isNullString(newContent)?newContent:oldContent); if (newFeedWatcher.getFoundNode() == null || // changed from exists to not exists, or !oldContent.equals(newContent) // node has changed ) { // collect property from newNode and pass it to THIS task so that the local ant script can see it if (!isNullString(oldContent)) { this.getProject().setProperty(feedWatchActionOldValue + DOT + j,oldContent); } if (!isNullString(newContent)) { this.getProject().setProperty(feedWatchActionNewValue + DOT + j,newContent); } if (!"null".equals(action)) { //$NON-NLS-1$ System.out.println(Messages.getString("RSSFeedWatcherTask.RunExecTask") + CL + SP + action + SP + commandline); //$NON-NLS-1$ ExecTask exec = util.runExecTask((new File(action)).getAbsolutePath(), commandline, null); // collect properties from exec task and pass them to THIS task so that the local ant script can see them String out = null; out = exec.getProject().getProperty(RSSFeedUtil.RUN_EXEC_TASK_ERROR); if (!isNullString(out)) { this.getProject().setProperty(feedWatchActionError + DOT + j, out); } out = exec.getProject().getProperty(RSSFeedUtil.RUN_EXEC_TASK_RESULT); if (!isNullString(out)) { this.getProject().setProperty(feedWatchActionOuput + DOT + j, out); } out = exec.getProject().getProperty(RSSFeedUtil.RUN_EXEC_TASK_RESULT); if (!RSSFeedUtil.EXPECTED_RESULT.equals(out)) { this.getProject().setProperty(feedWatchActionResult + DOT + j, out); } } } else { System.out.println(Messages.getString("RSSFeedWatcherTask.NodeUnchanged")); //$NON-NLS-1$ } } else { System.out.println(Messages.getString("RSSFeedWatcherTask.NodeNotFound")); //$NON-NLS-1$ } j++; } try { RSSFeedUtil.transferData(new FileInputStream(tmpFile), new FileOutputStream(file)); tmpFile.deleteOnExit(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } private void downloadFeed(File destFile, boolean verbose) { try { if (verbose) { System.out.println(Messages.getString("RSSFeedWatcherTask.Download") + CL + SP + feedURL); //$NON-NLS-1$ System.out.println(Messages.getString("RSSFeedWatcherTask.To") + CL + SP + destFile + SP); //$NON-NLS-1$ } RSSFeedUtil.transferData((new URL(feedURL)).openStream(), new FileOutputStream(destFile)); if (verbose) { System.out.println(Messages.getString("RSSFeedWatcherTask.Done")); //$NON-NLS-1$ System.out.println(SP); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private static boolean isNullString(String str) { return RSSFeedUtil.isNullString(str); } }