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 //TODO: enable support for running task on Windows (problems with ssh, scp, cvs)
14 //TODO: enable support for connecting to Windows server? (`mkdir -p` not supported)
15 
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.io.FileNotFoundException;
19 import java.io.FileOutputStream;
20 import java.io.IOException;
21 
22 import org.apache.tools.ant.BuildException;
23 import org.apache.tools.ant.Task;
24 
25 import org.eclipse.releng.util.rss.Messages;
26 import org.eclipse.releng.util.rss.RSSFeedUtil;
27 
28 /**
29  * Parameters:
30  *   debug - more output to console - eg., 0|1|2
31  *
32  *   file - path to the XML file that will be published - eg., /path/to/file.to.publish.xml
33  *
34  *   cvsExec - path to the executable for cvs, eg., /usr/bin/cvs
35  *   cvsRoot - cvs root used to commit the file - eg., username@cvsserver:/cvsroot/path
36  *   cvsPath - cvs module to update - eg., project/news/ (into which builds.xml would go)
37  *   cvsTemp - path to the temp folder to use for cvs checkout
38  *
39  *   scpExec - path to the executable for scp, eg., /usr/bin/scp
40  *   scpTarget - scp target path for publishing the file - eg., username@server:/path/to/target/file.xml
41  *
42  * Optionally, if the target folder might not exist, you can use ssh to create it before scp'ing
43  *   sshExec - path to the executable for ssh, eg., /usr/bin/ssh
44  *
45  * @author nickb
46  *
47  */
48 public class RSSFeedPublisherTask extends Task {
49 
50   private int debug = 0;
51 
52   private static final String CL = ":"; //$NON-NLS-1$
53   private static final String FS = File.separator;
54   private static final String SP = " "; //$NON-NLS-1$
55 
56   // default values for optional fields
57   private static final String DEFAULT_CVSTemp = "/tmp/tmp-RSSFeedPublisherTask"; //$NON-NLS-1$
58   private static final String DEFAULT_CVSExec = "cvs"; //$NON-NLS-1$
59   private static final String DEFAULT_SCPExec = "scp"; //$NON-NLS-1$
60 
61   private static final RSSFeedUtil util = new RSSFeedUtil();
62 
63   //required fields
64   private File file;
65 
66   // required if doing CVS
67   private String CVSExec;
68   private String CVSRoot;
69   private String CVSPath;
70   private String CVSTemp;
71 
72   // required if doing SCP
73   private String SCPExec;
74   private String SCPTarget;
75 
76   // required if doing SCP and target dir may not already exist
77   private String SSHExec;
78 
79   //optional
setDebug(int debug)80   public void setDebug(int debug) { this.debug = debug; }
81 
82   //required
setFile(String file)83   public void setFile(String file) {
84     if (!isNullString(file)) { this.file = new File(file); }
85   }
86 
87   //required for CVS commit (with default)
setCVSExec(String CVSExec)88   public void setCVSExec(String CVSExec) {
89     if (!isNullString(CVSExec)) {
90       this.CVSExec = CVSExec;
91     } else {
92       this.CVSExec = DEFAULT_CVSExec;
93     }
94   }
95 
96   //required for CVS commit
setCVSRoot(String CVSRoot)97   public void setCVSRoot(String CVSRoot) { this.CVSRoot = CVSRoot; }
setCVSPath(String CVSPath)98   public void setCVSPath(String CVSPath) { this.CVSPath = CVSPath; }
99 
100   //required for CVS commit (with default)
setCVSTemp(String CVSTemp)101   public void setCVSTemp(String CVSTemp) {
102     if (!isNullString(CVSTemp)) {
103       this.CVSTemp = CVSTemp;
104     } else {
105       this.CVSTemp = DEFAULT_CVSTemp;
106     }
107   }
108 
109   //required for CVS commit (with default)
setSCPExec(String SCPExec)110   public void setSCPExec(String SCPExec) {
111     if (!isNullString(SCPExec)) {
112       this.SCPExec = SCPExec;
113     } else {
114       this.SCPExec = DEFAULT_SCPExec;
115     }
116   }
setSCPTarget(String SCPTarget)117   public void setSCPTarget(String SCPTarget) { this.SCPTarget = SCPTarget; }
118 
119   // required if doing SCP and target dir may not already exist (with default, not assigned)
setSSHExec(String SSHExec)120   public void setSSHExec(String SSHExec) {
121       this.SSHExec = SSHExec;
122   }
123 
124   // The method executing the task
execute()125   public void execute() throws BuildException {
126 
127     if (file==null || !file.exists() || !file.isFile()) {
128       System.err.println(Messages.getString("RSSFeedPublisherTask.ErrorInvalidFile") + CL + SP + file + "!"); //$NON-NLS-1$ //$NON-NLS-2$
129     } else {
130       if (debug>0) { System.out.println(Messages.getString("RSSFeedPublisherTask.Publish") + SP + file); } //$NON-NLS-1$
131       if ((!isNullString(CVSRoot) && !isNullString(CVSPath)) || !isNullString(SCPTarget)) {
132         if ((!isNullString(CVSRoot) && !isNullString(CVSPath))) {
133           commitFeedToCVS();
134         }
135         if (!isNullString(SCPTarget)) {
136           publishFeedWithSCP();
137         }
138       } else {
139         System.err.println(Messages.getString("RSSFeedPublisherTask.ErrorNothingToDo")); //$NON-NLS-1$
140       }
141     }
142   }
143 
commitFeedToCVS()144   private void commitFeedToCVS()
145   {
146     if (debug>1) {
147       System.out.println(Messages.getString("RSSFeedPublisherTask.UsingCVSRoot") + SP + CVSRoot); //$NON-NLS-1$
148       System.out.println(Messages.getString("RSSFeedPublisherTask.UsingCVSPath") + SP + CVSPath); //$NON-NLS-1$
149     }
150 //  <!-- 3. get filename (eg., builds.xml) from file (which could include a path, eg. ./data/news/builds.xml) -->
151 //  <pathconvert property="filename"><path path="${file}"/><mapper type="flatten"/></pathconvert>
152     String filename = file.getName();
153 
154 //  <!-- 4. create target temp folder & check out existing version from CVS -->
155 //  <mkdir dir="${cvsTemp}"/>
156     File CVSTempDir = new File(CVSTemp);
157     if (CVSTempDir.isFile()) { // if dir exists as a file, we need a new tmp folder name
158       CVSTemp += ".tmp";  //$NON-NLS-1$
159       CVSTempDir = new File(CVSTemp);
160     }
161     if (CVSTempDir.isDirectory()) {
162       if (!CVSTempDir.delete()) {
163         System.err.println(Messages.getString("RSSFeedPublisherTask.ErrorCouldNotDeleteTempFolder") + SP + CVSTempDir); //$NON-NLS-1$
164       }
165     }
166     CVSTempDir.mkdir();
167     if (debug>1) {
168       System.out.println(Messages.getString("RSSFeedPublisherTask.UsingCVSTemp") + SP + CVSTempDir); //$NON-NLS-1$
169     }
170 
171 //  <exec executable="${cvsExec}" dir="${cvsTemp}"><arg line="-d ${cvsRoot} co -d checkoutDir ${cvsPath}"/></exec>
172     runCVSExecTask("co -d checkoutDir" + SP + CVSPath, CVSTemp); //$NON-NLS-1$
173 
174 //  <!-- 5. check if the file already exists in CVS to see if we need to add it -->
175 //  <available file="${cvsTemp}/checkoutDir/${filename}" type="file" property="fileInCVS"/>
176     File destFile = new File(CVSTemp + FS + "checkoutDir" + FS + filename); //$NON-NLS-1$
177     boolean fileInCVS = destFile.isFile();
178 
179 //  <!-- 6. overwrite CVS copy with new version; or if new, copy file to destination for add then check-in -->
180 //  <copy file="../${file}" overwrite="true" todir="${cvsTemp}/checkoutDir"/>
181     try
182     {
183       RSSFeedUtil.transferData(new FileInputStream(file),new FileOutputStream(destFile));
184     }
185     catch (FileNotFoundException e)
186     {
187       e.printStackTrace();
188     }
189     catch (IOException e)
190     {
191       e.printStackTrace();
192     }
193 
194 //  <!-- 7. add to CVS (if new) -->
195 //  <antcall target="addFileToCVS"/>
196 //  <!-- 7. Add file to CVS (if file is new) -->
197 //  <target name="addFileToCVS" depends="init" unless="fileInCVS" description="Add file to CVS (if file is new)">
198 //  <exec executable="${cvsExec}" dir="${cvsTemp}/checkoutDir"><arg line="-d ${cvsRoot} add ${filename}"/></exec>
199 //  </target>
200     if (!fileInCVS) {
201       runCVSExecTask("add " + filename, CVSTemp + FS + "checkoutDir");  //$NON-NLS-1$ //$NON-NLS-2$
202     }
203 
204 //  <!-- 8. check in file -->
205 //  <exec executable="${cvsExec}" dir="${cvsTemp}/checkoutDir"><arg line="-d ${cvsRoot} ci -m '' ${filename}"/></exec>
206     runCVSExecTask("ci -m '' " + filename, CVSTemp + FS + "checkoutDir"); //$NON-NLS-1$ //$NON-NLS-2$
207   }
208 
publishFeedWithSCP()209   private void publishFeedWithSCP()
210   {
211     if (debug>1) {
212       System.out.println(Messages.getString("RSSFeedPublisherTask.PublishToSCPTarget") + SP + SCPTarget); //$NON-NLS-1$
213     }
214 
215 //    <exec executable="${sshExec}"><arg line="${sshMakeDirCommand}"/></exec>
216     if (!isNullString(SSHExec) && SCPTarget.indexOf(CL)>0) {
217       String userAtHost = SCPTarget.substring(0, SCPTarget.indexOf(CL));
218       String targetPath = SCPTarget.substring(SCPTarget.indexOf(CL)+1,SCPTarget.lastIndexOf(FS));
219       util.runExecTask(SSHExec, userAtHost + " \"mkdir -p" + SP + targetPath + "\"", null); //$NON-NLS-1$ //$NON-NLS-2$
220     }
221 
222 //    <exec executable="${scpExec}" dir="../"><arg line="${file} ${scpTarget}"/></exec>
223     util.runExecTask(SCPExec, file.toString() + SP + SCPTarget, null);
224   }
225 
runCVSExecTask(String task, String dir)226   private void runCVSExecTask(String task, String dir)
227   {
228     util.runExecTask(CVSExec, "-d " + CVSRoot + " -q " + task, dir); //$NON-NLS-1$ //$NON-NLS-2$
229   }
230 
isNullString(String str)231   private static boolean isNullString(String str)
232   {
233     return RSSFeedUtil.isNullString(str);
234   }
235 
236 }