Project Report: fawkez

Packagesummary org.jcoderz.commons.taskdefs

org.jcoderz.commons.taskdefs.LuntBuildTask

LineHitsNoteSource
1  /*
2   * $Id: LuntBuildTask.java 1011 2008-06-16 17:57:36Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  
34  package org.jcoderz.commons.taskdefs;
35  
36  import java.io.File;
37  import java.io.FileNotFoundException;
38  import java.io.FileOutputStream;
39  import java.io.IOException;
40  import java.io.InputStream;
41  import java.io.OutputStream;
42  import java.net.HttpURLConnection;
43  import java.net.MalformedURLException;
44  import java.net.URL;
45  import java.util.ArrayList;
46  import java.util.Iterator;
47  import java.util.List;
48  
49  import org.apache.tools.ant.BuildException;
50  import org.apache.tools.ant.Project;
51  import org.apache.tools.ant.Task;
52  import org.jcoderz.commons.util.IoUtil;
53  
54  import com.caucho.hessian.client.HessianProxyFactory;
55  import com.luntsys.luntbuild.facades.BuildParams;
56  import com.luntsys.luntbuild.facades.Constants;
57  import com.luntsys.luntbuild.facades.ILuntbuild;
58  import com.luntsys.luntbuild.facades.lb12.BuildFacade;
59  import com.luntsys.luntbuild.facades.lb12.ScheduleFacade;
60  
61  /**
62   * Ant task to trigger a build on the Luntbuild system and download results
63   * afterwards.
64   * 
65   * @author Albrecht Messner
66   */
670 public class LuntBuildTask
68    extends Task
69  {
70    /**
71     * Schedule start policy: allows multiple schedules to be running
72     * simultaneously.
73     */
74    public static final String START_MULTIPLE = "startMultiple";
75    /**
76     * Schedule start policy: skips execution if schedule is currently running.
77     */
78    public static final String SKIP_IF_RUNNING = "skipIfRunning";
79    /**
80     * Schedule start policy: fails this task if schedule is currently running.
81     */
82    public static final String FAIL_IF_RUNNING = "failIfRunning";
83    
840   private static final List POLICY_LIST = new ArrayList();
85    static
86    {
870     POLICY_LIST.add(START_MULTIPLE);
880     POLICY_LIST.add(SKIP_IF_RUNNING);
890     POLICY_LIST.add(FAIL_IF_RUNNING);
900   }
91    
92    /** Wait time between kicking off schedule and start polling status
93     *  and between schedule termination and log retrieval. */
94    private static final int WAIT_PERIOD = 5000;
95    /** Interval to poll build server. */
96    private static final int POLL_INTERVAL = 2000;
97  
98    private String mLuntUrl;
99    private String mUserName;
100    private String mPassword;
101    private String mProjectName;
102    private String mScheduleName;
1030   private String mStartPolicy = FAIL_IF_RUNNING;
1040   private boolean mWaitForSchedule = true;
105    private String mToDir;
1060   private final List mArtifacts = new ArrayList();
107  
108    private ILuntbuild mLuntServer;
109    
110    /**
111     * @param luntUrl The luntUrl to set.
112     */
113    public void setLuntUrl (String luntUrl)
114    {
1150     mLuntUrl = luntUrl;
1160   }
117  
118    /**
119     * @param userName The userName to set.
120     */
121    public void setUserName (String userName)
122    {
1230     mUserName = userName;
1240   }
125    
126    /**
127     * @param password The password to set.
128     */
129    public void setPassword (String password)
130    {
1310     mPassword = password;
1320   }
133  
134    /**
135     * @param projectName The projectName to set.
136     */
137    public void setProjectName (String projectName)
138    {
1390     mProjectName = projectName;
1400   }
141    
142    /**
143     * @param scheduleName The scheduleName to set.
144     */
145    public void setScheduleName (String scheduleName)
146    {
1470     mScheduleName = scheduleName;
1480   }
149    
150    /**
151     * @param startPolicy The startPolicy to set.
152     */
153    public void setStartPolicy (String startPolicy)
154    {
1550(1)    if (!POLICY_LIST.contains(startPolicy))
156      {
1570       throw new BuildException("Invalid start policy " + startPolicy
158             + ", must be one of " + POLICY_LIST);
159      }
1600     mStartPolicy = startPolicy;
1610   }
162    
163    /**
164     * @param waitForSchedule The waitForSchedule to set.
165     */
166    public void setWaitForSchedule (boolean waitForSchedule)
167    {
1680     mWaitForSchedule = waitForSchedule;
1690   }
170  
171    /**
172     * @param toDir The toDir to set.
173     */
174    public void setToDir (String toDir)
175    {
1760     mToDir = toDir;
1770   }
178  
179    /**
180     * Adds an artifact for retrieval.
181     * @param artifact the artifact to add
182     */
183    public void addArtifact (Artifact artifact)
184    {
1850     mArtifacts.add(artifact);
1860   }
187  
188    /**
189     * Execute this ant task.
190     * @throws BuildException if a build error occurs
191     */
192    public void execute () throws BuildException
193    {
1940     checkParameters();
195      try
196      {
197        
1980       final ScheduleFacade schedule = getSchedule();
199        final boolean startSchedule;
2000       if (schedule.getStatus() == Constants.SCHEDULE_STATUS_RUNNING)
201        {
2020(2)        if (mStartPolicy.equals(START_MULTIPLE))
203          {
2040           startSchedule = true;
205          }
2060(3)        else if (mStartPolicy.equals(SKIP_IF_RUNNING))
207          {
2080           startSchedule = false;
209          }
210          else
211          {
2120           throw new BuildException(
213              "Can't start build because schedule is already running");
214          }
215        }
216        else
217        {
2180         startSchedule = true;
219        }
220        
2210       if (startSchedule)
222        {
2230         startSchedule();
224        }
225        
226      }
2270     catch (BuildException x)
228      {
2290       throw x;
230      }
2310     catch (Exception x)
232      {
2330       throw new BuildException(x);
2340     }
2350   }
236  
237    private void startSchedule () throws InterruptedException, IOException
238    {
2390     log("Starting build for " + mProjectName + "/" + mScheduleName
240          + " on server " + mLuntUrl, Project.MSG_INFO);
2410     getLuntServer().triggerBuild(mProjectName, mScheduleName, getBuildParams());
242  
2430     if (mWaitForSchedule)
244      {
2450       waitForSchedule();
246      }
2470   }
248  
249    private void waitForSchedule () throws InterruptedException, IOException
250    {
2510     Thread.sleep(WAIT_PERIOD);
2520     log("Waiting for build "
253          + getLuntServer().getLastBuild(mProjectName, mScheduleName).getVersion()
254          + " to finish");
255   
2560     while (getSchedule().getStatus() == Constants.SCHEDULE_STATUS_RUNNING)
257      {
2580       log("Schedule running", Project.MSG_VERBOSE);
2590       Thread.sleep(POLL_INTERVAL);
260      }
2610     final int termStatus = getSchedule().getStatus();
2620     switch (termStatus)
263      {
264        case Constants.SCHEDULE_STATUS_SUCCESS:
2650         log("LuntBuild schedule " + mProjectName + "/" + mScheduleName
266              + " succeeded");
2670         dumpLogFile();
2680         retrieveArtifacts();
2690         break;
270        case Constants.SCHEDULE_STATUS_FAILED:
2710         log("LuntBuild schedule " + mProjectName + "/" + mScheduleName
272              + " FAILED");
2730         dumpLogFile();
2740         throw new BuildException("LuntBuild schedule " + mProjectName + "/"
275              + mScheduleName + " FAILED");
276        default:
2770         throw new BuildException("Unexpected status for schedule "
278              + mProjectName + "/" + mScheduleName + ": " + termStatus);
279      }
2800   }
281  
282    private ScheduleFacade getSchedule () throws MalformedURLException
283    {
2840     return getLuntServer().getScheduleByName(mProjectName, mScheduleName);
285    }
286  
287    /**
288     * @throws IOException
289     * 
290     */
291    private void retrieveArtifacts () throws IOException
292    {
2930     final BuildFacade currentBuild
294        = getLuntServer().getLastBuild(mProjectName, mScheduleName);
2950     final String buildLogUrl = currentBuild.getBuildLogUrl();
2960     final String path = buildLogUrl.substring(0, buildLogUrl.lastIndexOf('/'));
2970     final String artifactsBaseUrl = path + "/artifacts/";
2980     log("Artifacts base URL: " + artifactsBaseUrl, Project.MSG_VERBOSE);
2990     HttpURLConnection.setFollowRedirects(true);
300      
3010     for (final Iterator it = mArtifacts.iterator(); it.hasNext(); )
302      {
3030       final String artifactName = ((Artifact) it.next()).getName();
3040       final File outputFile = new File(new File(mToDir), artifactName);
3050       if (outputFile.exists())
306        {
3070         throw new BuildException("Output file " + outputFile
308              + " already exists");
309        }
3100       final String artifactUrl = artifactsBaseUrl + artifactName;
3110       log("Retrieving artifact " + artifactName);
3120       log("Retrieving from URL: " + artifactUrl, Project.MSG_VERBOSE);
3130       log("Writing to file: " + mToDir + File.separator + outputFile,
314            Project.MSG_VERBOSE);
3150       final HttpURLConnection con
316            = (HttpURLConnection) new URL(artifactUrl).openConnection();
3170       con.setDoOutput(true);
3180       con.addRequestProperty("Keep-alive", "false");
319        
3200       con.connect();
3210       if (con.getResponseCode() != HttpURLConnection.HTTP_OK)
322        {
3230         throw new BuildException("Failed while retrieving artifact "
324              + artifactUrl + ": " + con.getResponseMessage());
325        }
326        
3270       writeArtifactToFile(outputFile, con);
3280     }
3290   }
330  
331    private void writeArtifactToFile (
332        final File outputFile, final HttpURLConnection con)
333      throws IOException, FileNotFoundException
334    {
3350     InputStream artifactInput = null;
3360     OutputStream artifactOutput = null;
337      try
338      {
3390       artifactInput = con.getInputStream();
3400       artifactOutput = new FileOutputStream(outputFile);
341        
3420       IoUtil.copy(artifactInput, artifactOutput);
343      }
344      finally
345      {
3460       IoUtil.close(artifactInput);
3470       IoUtil.close(artifactOutput);
3480     }
3490   }
350  
351    /**
352     * @throws InterruptedException
353     * @throws IOException
354     * 
355     */
356    private void dumpLogFile () throws InterruptedException, IOException
357    {
3580     Thread.sleep(WAIT_PERIOD);
3590     final BuildFacade currentBuild
360        = getLuntServer().getLastBuild(mProjectName, mScheduleName);
361  
3620     final String buildLogUrlHtml = currentBuild.getBuildLogUrl();
3630     log("Build log URL (HTML format): " + buildLogUrlHtml, Project.MSG_VERBOSE);
3640     final String buildLogUrlTxt = buildLogUrlHtml.substring(0,
365          buildLogUrlHtml.lastIndexOf(".html")) + ".txt";
3660     log("Build log URL (Text format): " + buildLogUrlTxt, Project.MSG_VERBOSE);
367  
3680     final URL buildLog = new URL(buildLogUrlTxt);
3690     final HttpURLConnection con = (HttpURLConnection) buildLog.openConnection();
3700     log("Got HTTP code " + con.getResponseCode(), Project.MSG_VERBOSE);
371  
3720     InputStream is = null;
373      try
374      {
3750       is = con.getInputStream();
3760       final byte[] data = IoUtil.readFully(is);
3770       final String buildLogData = new String(data);
3780       log("===== START Build log =====", Project.MSG_INFO);
3790       log(buildLogData, Project.MSG_INFO);
3800       log("===== END Build log =====", Project.MSG_INFO);
381      }
382      finally
383      {
3840       IoUtil.close(is);
3850     }
3860   }
387  
388    private BuildParams getBuildParams ()
389    {
3900     final BuildParams params = new BuildParams();
391      
3920     params.setBuildNecessaryCondition("always");
3930     params.setBuildType(Constants.BUILD_TYPE_CLEAN);
3940     params.setLabelStrategy(Constants.LABEL_NONE);
3950     params.setNotifyStrategy(Constants.NOTIFY_NONE);
3960     params.setPostbuildStrategy(Constants.POSTBUILD_NONE);
397      // params.setScheduleId()
3980     params.setTriggerDependencyStrategy(
399          Constants.TRIGGER_NONE_DEPENDENT_SCHEDULES);
400      
4010     return params;
402    }
403    
404    /**
405     * @param luntUrl
406    */
407    private void checkNotNull (Object obj, String name)
408    {
4090     if (obj == null)
410      {
4110       throw new BuildException("Parameter " + name + " missing");
412      }
4130   }
414  
415    /**
416     * 
417     */
418    private void checkParameters ()
419    {
4200     checkNotNull(mLuntUrl, "luntUrl");
4210     checkNotNull(mUserName, "userName");
4220     checkNotNull(mPassword, "password");
4230     checkNotNull(mProjectName, "projectName");
4240     checkNotNull(mScheduleName, "scheduleName");
4250(4)    if (mArtifacts.size() > 0)
426      {
4270       if (mToDir == null)
428        {
4290         throw new BuildException("'toDir' must be set if artifacts are set");
430        }
431        else
432        {
4330         AntTaskUtil.ensureDirectory(new File(mToDir));
434        }
4350       if (!mWaitForSchedule)
436        {
4370         throw new BuildException(
438            "Can't retrieve artifacts when waitForBuild == false");
439        }
440      }
4410   }
442  
443    private ILuntbuild getLuntServer () throws MalformedURLException
444    {
4450     if (mLuntServer == null)
446      {
4470       final HessianProxyFactory factory = new HessianProxyFactory();
4480       factory.setUser(mUserName);
4490       factory.setPassword(mPassword);
4500       mLuntServer = (ILuntbuild) factory.create(ILuntbuild.class, mLuntUrl);
451      }
4520     return mLuntServer;
453    }
454    
455    /**
456     * Represents an artifact to retrieve. This class basically consists of a
457     * name.
458     */
4590   public static final class Artifact
460    {
461      private String mName;
462      
463      /**
464       * @param name The name to set.
465       */
466      public void setName (String name)
467      {
4680       mName = name;
4690     }
470      
471      /**
472       * @return Returns the name.
473       */
474      public String getName ()
475      {
4760       return mName;
477      }
478    }
479  }

Findings in this File

c (5) Got an exception - java.lang.RuntimeException: Unable to get class information for @throws tag 'BuildException'.
w (1) 155 : 0 class org.jcoderz.commons.taskdefs.LuntBuildTask defines List based fields but uses them like Sets
i (2) 202 : 0 method org.jcoderz.commons.taskdefs.LuntBuildTask.execute() makes literal string comparisons passing the literal as an argument
i (3) 206 : 0 method org.jcoderz.commons.taskdefs.LuntBuildTask.execute() makes literal string comparisons passing the literal as an argument
d (4) 425 : 9 Substitute calls to size() == 0 (or size() != 0) with calls to isEmpty()