001 /* 002 * Copyright 1999-2001,2004 The Apache Software Foundation. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.apache.commons.latka.jelly; 018 019 import java.io.IOException; 020 import java.net.URL; 021 022 import org.apache.commons.jelly.JellyTagException; 023 import org.apache.commons.jelly.TagSupport; 024 import org.apache.commons.jelly.XMLOutput; 025 026 import org.apache.commons.latka.LatkaException; 027 import org.apache.commons.latka.event.LatkaEventInfo; 028 import org.apache.commons.latka.event.RequestErrorEvent; 029 import org.apache.commons.latka.event.RequestSkippedEvent; 030 import org.apache.commons.latka.event.RequestSucceededEvent; 031 import org.apache.commons.latka.http.Proxy; 032 import org.apache.commons.latka.http.Request; 033 import org.apache.commons.latka.http.Response; 034 import org.apache.commons.latka.http.Session; 035 import org.apache.commons.latka.http.SessionImpl; 036 037 import org.apache.log4j.Category; 038 039 /** 040 * 041 * @author Morgan Delagrange 042 */ 043 public class RequestTag extends TagSupport { 044 045 protected String _host = null; 046 protected int _port = -1; 047 protected String _proxyHost = null; 048 protected int _proxyPort = -1; 049 protected String _label = null; 050 protected int _method = Request.HTTP_METHOD_GET; 051 protected String _path = null; 052 protected boolean _secure = false; 053 protected boolean _followRedirects = true; 054 protected String _httpVersion = "1.1"; 055 056 protected Request _request = null; 057 protected Response _response = null; 058 protected Session _session = null; 059 protected boolean _requestExecuted = false; 060 061 protected static final Category _log = Category.getInstance(RequestTag.class); 062 063 /** 064 * Wraps Latka tests, provides some defaults for host, port etc. 065 * 066 * @param xmlOutput a place to write output 067 * @throws JellyTagException if an HTTP request could not be created 068 */ 069 public void doTag(XMLOutput xmlOutput) throws JellyTagException { 070 try { 071 _request = createRequest(); 072 } catch (LatkaException e) { 073 throw new JellyTagException("could not create HTTP request",e); 074 } 075 076 LatkaEventInfo listener = 077 JellyUtils.getInstance().getLatkaEventInfo(getContext()); 078 if (listener.didSessionSucceed(findSession()) == false) { 079 listener.requestSkipped(new RequestSkippedEvent(_request,null)); 080 return; 081 } 082 083 // may set headers and such 084 invokeBody(xmlOutput); 085 086 // even when there are no validations, we execute the request 087 // to make sure the URL is accessible 088 089 // will throw an unrecoverable LatkaException if the request could not 090 // be created, typically because of a malformed URL 091 Response response = null; 092 try { 093 response = getResponse(); 094 } catch (LatkaException e) { 095 throw new JellyTagException("could not obtain HTTP response",e); 096 } 097 098 // if there's been a response, and the request has a label 099 // make the response available to the jelly context 100 if (response != null && _label != null) { 101 getContext().setVariable(_label, response); 102 } 103 104 if (listener.didRequestSucceed(_request)) { 105 listener.requestSucceeded(new RequestSucceededEvent( 106 response.getRequest(), response)); 107 } 108 109 } 110 111 /** 112 * 113 * @return Request 114 * @exception IOException 115 * Error creating the request (unrecoverable, the script 116 * must fail) 117 */ 118 private Request createRequest() throws LatkaException { 119 String host = _host; 120 int port = _port; 121 String proxyHost = _proxyHost; 122 int proxyPort = _proxyPort; 123 124 if (host == null || port == -1 || proxyHost == null || proxyPort == -1) { 125 SuiteSettings settings = getSuiteSettings(); 126 if (host == null) { 127 host = settings.getDefaultHost(); 128 } 129 if (port == -1) { 130 port = settings.getDefaultPort(); 131 } 132 if (proxyHost == null) { 133 proxyHost = settings.getDefaultProxyHost(); 134 } 135 if (proxyPort == -1) { 136 proxyPort = settings.getDefaultProxyPort(); 137 } 138 } 139 140 Session session = findSession(); 141 142 Proxy proxy = null; 143 if (proxyHost != null) { 144 proxy = new Proxy(proxyHost,proxyPort); 145 } 146 147 URL url = null; 148 try { 149 url = new URL(_secure ? "https" : "http", host, port, _path); 150 } catch (IOException e) { 151 throw new LatkaException(e); 152 } 153 return session.createRequest(_label,url,_method,_httpVersion,_followRedirects,proxy); 154 } 155 156 public Request getRequest() { 157 return _request; 158 } 159 160 protected Session findSession() { 161 if (_session == null) { 162 SessionTag tag = (SessionTag) findAncestorWithClass(SessionTag.class); 163 if (tag == null) { 164 _session = new SessionImpl(); 165 } else { 166 _session = tag.getSession(); 167 } 168 } 169 170 return _session; 171 } 172 173 public boolean getRequestExecuted() { 174 return _requestExecuted; 175 } 176 177 /** 178 * The first time this method is called, a live HTTP 179 * call will be made to the server, returning null 180 * if the response cannot be obtained. Subsequent 181 * calls return a cached response. 182 * 183 * @return Response for the request specified by the Latka script 184 * @exception LatkaException 185 * error creating the Request (unrecoverable) 186 */ 187 public Response getResponse() throws LatkaException { 188 if (_requestExecuted == false) { 189 _requestExecuted = true; 190 191 LatkaEventInfo listener = 192 JellyUtils.getInstance().getLatkaEventInfo(getContext()); 193 try { 194 _response = _request.execute(); 195 196 _log.warn("Eventually this debug needs to go."); 197 if (_log.isDebugEnabled()) { 198 _log.debug(_response.getResource()); 199 } 200 } catch (IOException e) { 201 listener.requestError(new RequestErrorEvent(_request, null, e)); 202 return null; 203 } 204 205 // hack because sometimes we need to generate a new request after 206 // a redirect 207 _request = _response.getRequest(); 208 } 209 210 return _response; 211 } 212 213 /** 214 * get the suite settings from SuiteTag 215 * 216 * @return SuiteSettings object 217 */ 218 protected SuiteSettings getSuiteSettings() { 219 SuiteTag tag = 220 (SuiteTag) findAncestorWithClass(org.apache.commons.latka.jelly.SuiteTag.class); 221 return tag.getSuiteSettings(); 222 } 223 224 /** 225 * Setter for host 226 * 227 * @param host 228 * host for the request 229 */ 230 public void setHost(String host) { 231 _host = host; 232 } 233 234 /** 235 * Setter for port 236 * 237 * @param port 238 * port for all requests 239 */ 240 public void setPort(int port) { 241 _port = port; 242 } 243 244 245 /** 246 * Setter for defaultProxyHost 247 * 248 * @param defaultHost 249 * defaultProxyHost for all requests 250 */ 251 public void setProxyHost(String host) { 252 _proxyHost = host; 253 } 254 255 /** 256 * Setter for defaultProxyPort 257 * 258 * @param defaultPort 259 * defaultProxyPort for all requests 260 * @return 261 */ 262 public void setProxyPort(int port) { 263 _proxyPort = port; 264 } 265 266 /** 267 * Set the label for this suite 268 * 269 * @param label suite label 270 */ 271 public void setLabel(String label) { 272 _label = label; 273 } 274 275 /** 276 * Sets the HTTP method to use. Supports post, get, 277 * and head. Default is "get". 278 * 279 * @param method set method to post, get or head 280 * @exception UnsupportedOperationException 281 * if an unsupported HTTP method is set 282 */ 283 public void setMethod(String method) throws UnsupportedOperationException { 284 if (method.equals("get")) { 285 _method = Request.HTTP_METHOD_GET; 286 } else if (method.equals("post")) { 287 _method = Request.HTTP_METHOD_POST; 288 } else if (method.equals("head")) { 289 _method = Request.HTTP_METHOD_HEAD; 290 } else { 291 throw new UnsupportedOperationException("Unkonwn HTTP method: " + method); 292 } 293 } 294 295 /** 296 * Sets the path of the document on the server, combined 297 * with the host and port 298 * 299 * @param path Path to the document on the server 300 */ 301 public void setPath(String path) { 302 _path = path; 303 } 304 305 /** 306 * Sets whether or not to transmit the request over 307 * SSL. 308 * 309 * @param secure whether or not this request is SSL 310 */ 311 public void setSecure(String secure) { 312 _secure = Boolean.valueOf(secure).booleanValue(); 313 } 314 315 316 /** 317 * Sets whether or not to transmit the request over 318 * SSL. 319 * 320 * @param secure whether or not this request is SSL 321 */ 322 public void setFollowRedirects(String followRedirects) { 323 _followRedirects = Boolean.valueOf(followRedirects).booleanValue(); 324 } 325 326 /** 327 * HTTP version to use. Legal values are 1.0 and 1.1. 328 * 1.1 is the default. 329 * 330 * @param version HTTP specification version 331 */ 332 public void setVersion(String version) { 333 _httpVersion = version; 334 } 335 336 }