Home | History | Annotate | Download | only in rss
      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 }