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;
22  
23  import java.io.BufferedReader;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.StringReader;
27  
28  import java.net.HttpURLConnection;
29  
30  import java.util.Vector;
31  
32  import org.apache.cactus.internal.util.CookieUtil;
33  import org.apache.cactus.internal.util.IoUtil;
34  import org.apache.cactus.util.ChainedRuntimeException;
35  import org.apache.commons.httpclient.Header;
36  import org.apache.commons.httpclient.HttpException;
37  import org.apache.commons.httpclient.cookie.CookiePolicy;
38  import org.apache.commons.httpclient.cookie.CookieSpec;
39  import org.apache.commons.logging.Log;
40  import org.apache.commons.logging.LogFactory;
41  
42  /**
43   * Default web response implementation that provides a minimal
44   * API for asserting returned output stream from the server side. For more
45   * complex assertions, use an <code>com.meterware.httpunit.WebResponse</code>
46   * instead as parameter of your <code>endXXX()</code> methods.
47   *
48   * @version $Id: WebResponse.java 238991 2004-05-22 11:34:50Z vmassol $
49   */
50  public class WebResponse
51  {
52      /**
53       * The logger.
54       */
55      private static final Log LOGGER = LogFactory.getLog(WebResponse.class);
56  
57      /**
58       * The connection object that was used to call the URL.
59       */
60      private HttpURLConnection connection;
61  
62      /**
63       * The request data that were used to open the connection to the server.
64       */
65      private WebRequest request;
66  
67      /**
68       * Save the response content for repeatable reads.
69       */
70      private String content;
71  
72      /**
73       * @param theRequest the request data that were used to open the
74       *        connection to the server.
75       * @param theConnection the original <code>HttpURLConnection</code> used
76       *        to call the URL
77       */
78      public WebResponse(WebRequest theRequest, HttpURLConnection theConnection)
79      {
80          this.request = theRequest;
81          this.connection = theConnection;
82      }
83  
84      /**
85       * @return the original <code>HttpURLConnection</code> used to call the
86       *         URL
87       */
88      public HttpURLConnection getConnection()
89      {
90          return this.connection;
91      }
92  
93      /**
94       * @return the request data the were used to open the connection to the
95       *         server
96       */
97      public WebRequest getWebRequest()
98      {
99          return this.request;
100     }
101 
102     /**
103      * @return the text of the response (excluding headers) as a string.
104      */
105     public String getText()
106     {
107         // Get the text from the save content if content has already been
108         // read.
109         if (this.content == null)
110         {
111             try
112             {
113                 this.content = IoUtil.getText(this.connection.getInputStream());
114             }
115             catch (IOException e)
116             {
117                 throw new ChainedRuntimeException(e);
118             }
119         }
120 
121         return this.content;
122     }
123 
124     /**
125      * @return the text of the response (excluding headers) as an array of
126      *         strings (each string is a separate line from the output stream).
127      */
128     public String[] getTextAsArray()
129     {
130         Vector lines = new Vector();
131 
132         try
133         {
134             // Read content first
135             if (this.content == null)
136             {
137                 getText();
138             }
139 
140             BufferedReader input = new BufferedReader(
141                 new StringReader(this.content));
142             String str;
143 
144             while (null != (str = input.readLine()))
145             {
146                 lines.addElement(str);
147             }
148 
149             input.close();
150         }
151         catch (IOException e)
152         {
153             throw new ChainedRuntimeException(e);
154         }
155 
156         // Dummy variable to explicitely tell the object type to copy.
157         String[] dummy = new String[lines.size()];
158 
159         return (String[]) (lines.toArray(dummy));
160     }
161 
162     /**
163      * @return a buffered input stream for reading the response data.
164      **/
165     public InputStream getInputStream()
166     {
167         try
168         {
169             return this.connection.getInputStream();
170         }
171         catch (IOException e)
172         {
173             throw new ChainedRuntimeException(e);
174         }
175     }
176 
177     /**
178      * Return the first cookie found that has the specified name or null
179      * if not found.
180      *
181      * @param theName the cookie name to find
182      * @return the cookie or null if not found
183      */
184     public Cookie getCookie(String theName)
185     {
186         Cookie result = null;
187 
188         Cookie[] cookies = getCookies();
189 
190         for (int i = 0; i < cookies.length; i++)
191         {
192             if (cookies[i].getName().equals(theName))
193             {
194                 result = cookies[i];
195 
196                 break;
197             }
198         }
199 
200         return result;
201     }
202 
203     /**
204      * Return the first cookie found that has the specified name or null
205      * if not found. The name is case-insensitive.
206      *
207      * @param theName the cookie name to find (case-insensitive)
208      * @return the cookie or null if not found
209      * @since 1.5
210      */
211     public Cookie getCookieIgnoreCase(String theName)
212     {
213         Cookie result = null;
214 
215         Cookie[] cookies = getCookies();
216 
217         for (int i = 0; i < cookies.length; i++)
218         {
219             if (cookies[i].getName().equalsIgnoreCase(theName))
220             {
221                 result = cookies[i];
222 
223                 break;
224             }
225         }
226 
227         return result;
228     }
229 
230     /**
231      * @return the cookies returned by the server
232      */
233     public Cookie[] getCookies()
234     {
235         Cookie[] returnCookies = null;
236 
237         // There can be several headers named "Set-Cookie", so loop through
238         // all the headers, looking for cookies
239         String headerName = this.connection.getHeaderFieldKey(0);
240         String headerValue = this.connection.getHeaderField(0);
241 
242         Vector cookieVector = new Vector();
243         CookieSpec cookieSpec = CookiePolicy.getDefaultSpec();
244 
245         for (int i = 1; (headerName != null) || (headerValue != null); i++)
246         {
247             LOGGER.debug("Header name  = [" + headerName + "]");
248             LOGGER.debug("Header value = [" + headerValue + "]");
249 
250             if ((headerName != null)
251                 && (headerName.toLowerCase().equals("set-cookie") 
252                 || headerName.toLowerCase().equals("set-cookie2")))
253             {
254                 // Parse the cookie definition
255                 org.apache.commons.httpclient.Cookie[] cookies;
256                 try
257                 {
258                     cookies = cookieSpec.parse(
259                         CookieUtil.getCookieDomain(getWebRequest(), 
260                             getConnection().getURL().getHost()), 
261                         CookieUtil.getCookiePort(getWebRequest(), 
262                             getConnection().getURL().getPort()), 
263                         CookieUtil.getCookiePath(getWebRequest(), 
264                             getConnection().getURL().getFile()),
265                         false, new Header(headerName, headerValue));
266                 }
267                 catch (HttpException e)
268                 {
269                     throw new ChainedRuntimeException(
270                         "Error parsing cookies", e);
271                 }
272 
273                 // Transform the HttpClient cookies into Cactus cookies and
274                 // add them to the cookieVector vector
275                 for (int j = 0; j < cookies.length; j++)
276                 {
277                     Cookie cookie = new Cookie(cookies[j].getDomain(), 
278                         cookies[j].getName(), cookies[j].getValue());
279 
280                     cookie.setComment(cookies[j].getComment());
281                     cookie.setExpiryDate(cookies[j].getExpiryDate());
282                     cookie.setPath(cookies[j].getPath());
283                     cookie.setSecure(cookies[j].getSecure());
284 
285                     cookieVector.addElement(cookie);
286                 }
287             }
288 
289             headerName = this.connection.getHeaderFieldKey(i);
290             headerValue = this.connection.getHeaderField(i);
291         }
292 
293         returnCookies = new Cookie[cookieVector.size()];
294         cookieVector.copyInto(returnCookies);
295 
296         return returnCookies;
297     }
298 
299     /**
300      * Returns the status code returned by the server.
301      * 
302      * @return The status code
303      * @since 1.5
304      */
305     public int getStatusCode()
306     {
307         try
308         {
309             return this.connection.getResponseCode();
310         }
311         catch (IOException e)
312         {
313             throw new ChainedRuntimeException(e);
314         }
315     }
316 
317 }