2011/08/05 - Jakarta Cactus has been retired.

For more information, please explore the Attic.

View Javadoc

1   /* 
2    * ========================================================================
3    * 
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements.  See the NOTICE file distributed with
6    * this work for additional information regarding copyright ownership.
7    * The ASF licenses this file to You under the Apache License, Version 2.0
8    * (the "License"); you may not use this file except in compliance with
9    * the License.  You may obtain a copy of the License at
10   * 
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * 
19   * ========================================================================
20   */
21  package org.apache.cactus.integration.ant;
22  
23  import java.net.URL;
24  
25  import org.apache.cactus.container.ContainerRunner;
26  import org.apache.cactus.integration.ant.container.GenericContainer;
27  import org.apache.tools.ant.BuildException;
28  import org.apache.tools.ant.Task;
29  import org.codehaus.cargo.util.DefaultAntTaskFactory;
30  import org.codehaus.cargo.util.log.AntLogger;
31  
32  /**
33   * Task to automate running in-container unit test. It has the following
34   * syntax when used in Ant :
35   * <code><pre>
36   *   &lt;runservertests testURL="&t;url&gt;"
37   *          starttarget="&lt;start target name&gt;"
38   *          stoptarget="&lt;stop target name&gt;"
39   *          testtarget="&lt;test target name&gt;"/>
40   * </pre></code>
41   * where <code>&lt;url&gt;</code> is the URL that is used by this task to
42   * ensure that the server is running. Indeed, the algorithm is as follow :
43   * <ul>
44   *  <li>Checks if server is running by trying to open an HTTP connection to 
45   *  the URL,</li>
46   *  <li>If it fails, call the start target and loop until the HTTP connection
47   *  the URL can be established,</li>
48   *  <li>Call the test target. This target is supposed to start the test,
49   *  usually by running the junit Ant task,</li>
50   *  <li>When the tests are finished, call the stop target to stop the server.
51   *  Note: The stop target is called only if the server was not already running
52   *  when this task was executed.</li>
53   * </ul>
54   *
55   * @since Cactus 1.5
56   * @version $Id: RunServerTestsTask.java 239003 2004-05-31 20:05:27Z vmassol $
57   */
58  public class RunServerTestsTask extends Task
59  {
60  
61      // Instance Variables ------------------------------------------------------
62  
63      /**
64       * The generic container.
65       */
66      private GenericContainer container = new GenericContainer();
67  
68      /**
69       * The hook that is called when the tests should be run.
70       */
71      private GenericContainer.Hook testHook;
72  
73      /**
74       * The URL that is continuously pinged to verify if the server is running.
75       */
76      private URL testURL;
77  
78      /**
79       * Timeout after which we stop trying to connect to the test URL (in ms).
80       */
81      private long timeout = 180000;
82      
83      // Task Implementation -----------------------------------------------------
84  
85      /**
86       * {@inheritDoc}
87       * @see Task#execute()
88       */
89      public void execute() throws BuildException
90      {
91          if (!this.container.isStartUpSet())
92          {
93              throw new BuildException("You must specify either a nested [start] "
94                  + "element or the [starttarget] attribute");
95          }
96          
97          if (!this.container.isShutDownSet())
98          {
99              throw new BuildException("You must specify either a nested [stop] "
100                 + "element or the [stoptarget] attribute");
101         }
102 
103         if (this.testHook == null)
104         {
105             throw new BuildException("You must specify either a nested [test] "
106                 + "element or the [testtarget] attribute");
107         }
108 
109         // Verify that a test URL has been specified
110         if (this.testURL == null)
111         {
112             throw new BuildException(
113                 "The [testurl] attribute must be specified");
114         }
115 
116         this.container.setAntTaskFactory(new DefaultAntTaskFactory(
117                 getProject(), getTaskName(), 
118                 getLocation(), getOwningTarget())); 
119         ContainerRunner runner = new ContainerRunner(this.container);
120         runner.setLogger(new AntLogger(getProject()));
121         runner.setURL(this.testURL);
122         runner.setTimeout(this.timeout);
123         runner.startUpContainer();
124         try
125         {
126             this.testHook.execute();
127         }
128         finally
129         {
130             runner.shutDownContainer();
131         }
132     }
133 
134     // Public Methods ----------------------------------------------------------
135 
136     /**
137      * Creates a nested start element.
138      * 
139      * @return The start element
140      */
141     public final GenericContainer.Hook createStart()
142     {
143         if (this.container.isStartUpSet())
144         {
145             throw new BuildException(
146                 "This task supports only one nested [start] element");
147         }
148         return this.container.createStartUp();
149     }
150 
151     /**
152      * Sets the target to call to start the server.
153      *
154      * @param theStartTarget the Ant target to call
155      */
156     public void setStartTarget(String theStartTarget)
157     {
158         if (this.container.isStartUpSet())
159         {
160             throw new BuildException("Either specify the [starttarget] "
161                 + "attribute or the nested [start] element, but not both");
162         }
163         this.container.setStartUpTarget(theStartTarget);
164     }
165 
166     /**
167      * Creates a nested stop element.
168      * 
169      * @return The stop element
170      */
171     public final GenericContainer.Hook createStop()
172     {
173         if (this.container.isShutDownSet())
174         {
175             throw new BuildException(
176                 "This task supports only one nested [stop] element");
177         }
178         return this.container.createShutDown();
179     }
180 
181     /**
182      * Sets the target to call to stop the server.
183      *
184      * @param theStopTarget the Ant target to call
185      */
186     public void setStopTarget(String theStopTarget)
187     {
188         if (this.container.isShutDownSet())
189         {
190             throw new BuildException("Either specify the [stoptarget] "
191                 + "attribute or the nested [stop] element, but not both");
192         }
193         this.container.setShutDownTarget(theStopTarget);
194     }
195 
196     /**
197      * Creates a nested test element.
198      * 
199      * @return The test element
200      */
201     public final GenericContainer.Hook createTest()
202     {
203         if (this.testHook != null)
204         {
205             throw new BuildException(
206                 "This task supports only one nested [test] element");
207         }
208         this.testHook = container.new Hook();
209         return this.testHook;
210     }
211 
212     /**
213      * Sets the target to call to run the tests.
214      *
215      * @param theTestTarget the Ant target to call
216      */
217     public void setTestTarget(String theTestTarget)
218     {
219         if (this.testHook != null)
220         {
221             throw new BuildException("Either specify the [testtarget] "
222                 + "attribute or the nested [test] element, but not both");
223         }
224         this.testHook = container.new Hook();
225         this.testHook.setTarget(theTestTarget);
226     }
227 
228     /**
229      * Sets the URL to call for testing if the server is running.
230      *
231      * @param theTestURL the test URL to ping
232      */
233     public void setTestURL(URL theTestURL)
234     {
235         this.testURL = theTestURL;
236     }
237 
238     /**
239      * @param theTimeout the timeout after which we stop trying to call the test
240      *        URL.
241      */
242     public void setTimeout(long theTimeout)
243     {
244         this.timeout = theTimeout;
245     }
246 
247 }