View Javadoc

1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.jelly.tags.http;
18  
19  import java.io.IOException;
20  import java.net.MalformedURLException;
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import org.apache.commons.httpclient.HttpClient;
25  import org.apache.commons.httpclient.HttpMethod;
26  import org.apache.commons.httpclient.NameValuePair;
27  import org.apache.commons.jelly.JellyTagException;
28  import org.apache.commons.jelly.TagSupport;
29  import org.apache.commons.jelly.XMLOutput;
30  
31  /***
32   * The base tag for all http requests
33   *
34   * @author  dion
35   * @version $Id: HttpTagSupport.java 155420 2005-02-26 13:06:03Z dirkv $
36   */
37  public abstract class HttpTagSupport extends TagSupport {
38  
39      /*** unique identifier of the tag/ variable to store result in */
40      private String _var;
41  
42      /***
43       * the path to be tested relative to the host/port specifed on the parent
44       * {@link SuiteTag suite tag}.
45       * Either this property and the suite's host
46       * must be provided, or the {@link #getUrl() url} property must be specifed
47       */
48      private String _path;
49  
50      /***
51       * The complete uri to be processed
52       * Either this property or the {@link #getPath() path} and the suite's host
53       * must be provided.
54       */
55      private String _uri;
56  
57      /*** whether or not to follow redirects */
58      private boolean _followRedirects = false;
59      /*** list of parameters as name value pairs */
60      private List _parameters;
61      /*** list of headers as name value pairs */
62      private List _requestHeaders;
63      /*** the header name for the user agent */
64      private static final String HEADER_NAME_USER_AGENT = "User-Agent";
65  
66      /***
67       * Creates a new instance of HttpTag
68       */
69      public HttpTagSupport() {
70          setParameters(new ArrayList());
71          setRequestHeaders(new ArrayList());
72      }
73  
74      /***
75       * @return the url specified by the tag, either the url if not null, or
76       * a combination of the host, port and path
77       */
78      public String getResolvedUrl() {
79          if (getUri() != null) {
80              return getUri();
81          } else {
82              // build it from path, host and optionally port
83              SessionTag session = (SessionTag) findAncestorWithClass(
84                  SessionTag.class);
85              String host = session.getHost();
86              String port = session.getPort();
87              // short term hack, need to add port and security in
88              return "http://" + host + getPath();
89          }
90      }
91  
92      /***
93       * A method that must be implemented by subclasses to provide the
94       * {@link HttpMethod url method} implementation
95       *
96       * @return a HttpUrlMethod implementation
97       * @throws MalformedURLException when the {@link getUrl() url} or
98       * {@link #getPath() path} is invalid
99       */
100     protected abstract HttpMethod getHttpMethod()
101         throws MalformedURLException;
102 
103     /***
104      * Perform the tag functionality. In this case, get the http url method
105      * execute it and make it available for validation
106      *
107      * @param xmlOutput where to send output
108      * @throws JellyTagException when an error occurs
109      */
110     public void doTag(XMLOutput xmlOutput) throws JellyTagException {
111         // allow nested tags first, e.g body
112         invokeBody(xmlOutput);
113 
114         // track request execution
115         long start = System.currentTimeMillis();
116         HttpMethod urlMethod = null;
117         try {
118             urlMethod = getConfiguredHttpMethod();
119             getHttpClient().executeMethod(urlMethod);
120         }
121         catch (MalformedURLException e) {
122             throw new JellyTagException(e);
123         }
124         catch (IOException e) {
125             throw new JellyTagException(e);
126         }
127         long end = System.currentTimeMillis();
128 
129         // set variable to value
130         if (getVar() != null) {
131             getContext().setVariable(getVar(), urlMethod);
132             getContext().setVariable(getVar() + ".responseTime",
133                 String.valueOf(end - start));
134         }
135     }
136 
137     /***
138      * retrieve the {@link HttpUrlMethod method} from the subclass and
139      * configure it ready for execution
140      *
141      * @return a configured {@link HttpUrlMethod method}
142      * @throws MalformedURLException when retrieving the URL fails
143      */
144     private HttpMethod getConfiguredHttpMethod() throws
145     MalformedURLException {
146         // retrieve and configure url method
147         HttpMethod urlMethod = getHttpMethod();
148         urlMethod.setFollowRedirects(isFollowRedirects());
149         // add request headers
150         NameValuePair header = null;
151         for (int index = 0; index < getRequestHeaders().size(); index++) {
152             header = (NameValuePair) getRequestHeaders().get(index);
153             urlMethod.addRequestHeader(header.getName(), header.getValue());
154         }
155         // add parameters
156         setParameters(urlMethod);
157         // add the default user agent to the list if one doesn't exist
158         // and the session tag does exist and have a user agent
159         if (urlMethod.getRequestHeader(HttpTagSupport.HEADER_NAME_USER_AGENT)
160             == null && getSessionTag() != null
161             && getSessionTag().getUserAgent() != null) {
162 
163             urlMethod.addRequestHeader(HttpTagSupport.HEADER_NAME_USER_AGENT,
164                     getSessionTag().getUserAgent());
165         }
166         return urlMethod;
167     }
168 
169     /***
170      * Set the current parameters on the url method ready for processing
171      *
172      * @param method the {@link HttpUrlMethod method} to configure
173      * @throws MalformedURLException when {@link #getHttpUrlMethod()} does
174      */
175     protected void setParameters(HttpMethod method) throws
176     MalformedURLException {
177         if (getParameters().size() > 0) {
178             NameValuePair[] parameters = (NameValuePair[]) getParameters().
179                 toArray(new NameValuePair[0]);
180             method.setQueryString(parameters);
181         }
182     }
183 
184     /***
185      * retrieve the optional parent session tag
186      *
187      * @return the ancestor tag with class {@link SessionTag} or null if
188      *      not found
189      */
190     private SessionTag getSessionTag() {
191         SessionTag sessionTag = (SessionTag) findAncestorWithClass(
192             SessionTag.class);
193         return sessionTag;
194     }
195 
196     /***
197      * return a HttpClient shared on the session tag, or a new one if no
198      * session tag exists
199      *
200      * @return the shared http client from the session tag, or create a new one.
201      */
202     private HttpClient getHttpClient() {
203         SessionTag session = getSessionTag();
204         HttpClient client = null;
205         if (session != null) {
206             client = session.getHttpClient();
207             client.setStrictMode(session.isStrictMode());
208         } else {
209             client = new HttpClient();
210         }
211         return client;
212     }
213 
214     /***
215      * Add a parameter to the list
216      *
217      * @param name the parameter name
218      * @param value the parameter value
219      */
220     public void addParameter(String name, String value) {
221         getParameters().add(new NameValuePair(name, value));
222     }
223 
224     /***
225      * Add a request header to the list
226      *
227      * @param name the header name
228      * @param value the header value
229      */
230     public void addRequestHeader(String name, String value) {
231         getRequestHeaders().add(new NameValuePair(name, value));
232     }
233 
234     //--------------------------------------------------------------------------
235     // Property accessors/mutators
236     //--------------------------------------------------------------------------
237 
238     /***
239      * Getter for property var.
240      *
241      * @return Value of property var.
242      */
243     public String getVar() {
244         return _var;
245     }
246 
247     /***
248      * Setter for property var.
249      *
250      * @param var New value of property var.
251      */
252     public void setVar(String var) {
253         _var = var;
254     }
255 
256     /***
257      * Getter for property path.
258      *
259      * @return Value of property path.
260      */
261     public String getPath() {
262         return _path;
263     }
264 
265     /***
266      * Setter for property path.
267      *
268      * @param path New value of property path.
269      */
270     public void setPath(String path) {
271         _path = path;
272     }
273 
274     /***
275      * Getter for property uri.
276      *
277      * @return Value of property uri.
278      */
279     public String getUri() {
280         return _uri;
281     }
282 
283     /***
284      * Setter for property uri.
285      *
286      * @param uri New value of property uri.
287      */
288     public void setUri(String uri) {
289         _uri = uri;
290     }
291 
292     /***
293      * Getter for property followRedirects.
294      *
295      * @return Value of property followRedirects.
296      */
297     public boolean isFollowRedirects() {
298         return _followRedirects;
299     }
300 
301     /***
302      * Setter for property followRedirects.
303      *
304      * @param followRedirects New value of property followRedirects.
305      */
306     public void setFollowRedirects(boolean followRedirects) {
307         _followRedirects = followRedirects;
308     }
309 
310     /***
311      * Getter for property parameters.
312      *
313      * @return Value of property parameters.
314      */
315     public List getParameters() {
316         return _parameters;
317     }
318 
319     /***
320      * Setter for property parameters.
321      *
322      * @param parameters New value of property parameters.
323      */
324     public void setParameters(List parameters) {
325         _parameters = parameters;
326     }
327 
328     /***
329      * Getter for property requestHeaders.
330      *
331      * @return Value of property requestHeaders.
332      */
333     public List getRequestHeaders() {
334         return _requestHeaders;
335     }
336 
337     /***
338      * Setter for property requestHeaders.
339      *
340      * @param requestHeaders New value of property requestHeaders.
341      */
342     public void setRequestHeaders(List requestHeaders) {
343         _requestHeaders = requestHeaders;
344     }
345 
346 }