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.internal.util;
22  
23  import java.net.URL;
24  import java.util.Vector;
25  
26  import org.apache.cactus.Cookie;
27  import org.apache.cactus.ServletURL;
28  import org.apache.cactus.WebRequest;
29  import org.apache.cactus.internal.client.ClientException;
30  import org.apache.commons.httpclient.Header;
31  import org.apache.commons.httpclient.cookie.CookiePolicy;
32  import org.apache.commons.httpclient.cookie.CookieSpec;
33  import org.apache.commons.logging.Log;
34  import org.apache.commons.logging.LogFactory;
35  
36  /**
37   * Utility methods to manipulate cookies and transform Cactus cookie objects 
38   * to HttpClient cookie objects.
39   *
40   * @version $Id: CookieUtil.java 238991 2004-05-22 11:34:50Z vmassol $
41   * @since 1.5
42   */
43  public class CookieUtil
44  {
45      /**
46       * The logger.
47       */
48      private static final Log LOGGER = LogFactory.getLog(CookieUtil.class);
49  
50      /**
51       * Returns the domain that will be used to send the cookies. If a host
52       * was specified using <code>setURL()</code> then the domain will be
53       * this host. Otherwise it will be the real redirector host.
54       *
55       * @param theRequest the request containing all data to pass to the server
56       *        redirector.
57       * @param theRealHost the real host to which we are connecting to. We will
58       *        use it if no simulation host has been specified.
59       * @return the cookie domain to use
60       */
61      public static String getCookieDomain(WebRequest theRequest, 
62          String theRealHost)
63      {
64          String domain;
65          ServletURL url = theRequest.getURL();
66  
67          if ((url != null) && (url.getHost() != null))
68          {
69              domain = url.getHost();
70          }
71          else
72          {
73              domain = theRealHost;
74          }
75  
76          LOGGER.debug("Cookie validation domain = [" + domain + "]");
77  
78          return domain;
79      }
80  
81      /**
82       * Returns the port that will be used to send the cookies. If a port
83       * was specified using <code>setURL()</code> then the port sent will be
84       * this port. Otherwise it will be the real redirector port.
85       *
86       * @param theRequest the request containing all data to pass to the server
87       *        redirector.
88       * @param theRealPort the real port to which we are connecting to. We will
89       *        use it if no simulation port has been specified.
90       * @return the cookie domain to use
91       */
92      public static int getCookiePort(WebRequest theRequest, int theRealPort)
93      {
94          int port;
95          ServletURL url = theRequest.getURL();
96  
97          if ((url != null) && (url.getHost() != null))
98          {
99              port = url.getPort();
100         }
101         else
102         {
103             port = theRealPort;
104         }
105 
106         LOGGER.debug("Cookie validation port = [" + port + "]");
107 
108         return port;
109     }
110 
111     /**
112      * Returns the path that will be used to validate if a cookie will be
113      * sent or not. The algorithm is as follows : if the cookie path is not
114      * set (i.e. null) then the cookie is always sent (provided the domain
115      * is right). If the cookie path is set, the cookie is sent only if
116      * the request path starts with the same string as the cookie path. If
117      * <code>setURL()</code> has been called, return the path it has been
118      * set to (context + servletPath + pathInfo). Otherwise return the
119      * real redirector path.
120      *
121      * @param theRequest the request containing all data to pass to the server
122      *        redirector.
123      * @param theRealPath the real path to which we are connecting to. We will
124      *        use it if no simulation path has been specified.
125      * @return the path to use to decide if a cookie will get sent
126      */
127     public static String getCookiePath(WebRequest theRequest, 
128         String theRealPath)
129     {
130         String path;
131         ServletURL url = theRequest.getURL();
132 
133         if ((url != null) && (url.getPath() != null))
134         {
135             path = url.getPath();
136         }
137         else
138         {
139             String file = theRealPath;
140 
141             if (file != null)
142             {
143                 int q = file.lastIndexOf('?');
144 
145                 if (q != -1)
146                 {
147                     path = file.substring(0, q);
148                 }
149                 else
150                 {
151                     path = file;
152                 }
153             }
154             else
155             {
156                 path = null;
157             }
158         }
159 
160         LOGGER.debug("Cookie validation path = [" + path + "]");
161 
162         return path;
163     }
164 
165     /**
166      * Create a Commons-HttpClient cookie from a Cactus cookie, with information
167      * from the web request and the URL.
168      * 
169      * @param theRequest The request
170      * @param theUrl The URL
171      * @param theCactusCookie The Cactus Cookie object
172      * @return The HttpClient cookie
173      */
174     public static org.apache.commons.httpclient.Cookie createHttpClientCookie(
175         WebRequest theRequest, URL theUrl, Cookie theCactusCookie)
176     {
177         // If no domain has been specified, use a default one
178         String domain;
179         if (theCactusCookie.getDomain() == null)
180         {
181             domain = CookieUtil.getCookieDomain(theRequest, theUrl.getHost());
182         }
183         else
184         {
185             domain = theCactusCookie.getDomain();
186         }
187 
188         // If not path has been specified , use a default one
189         String path;
190         if (theCactusCookie.getPath() == null)
191         {
192             path = CookieUtil.getCookiePath(theRequest, theUrl.getFile());
193         }
194         else
195         {
196             path = theCactusCookie.getPath();
197         }
198 
199         // Assemble the HttpClient cookie
200         org.apache.commons.httpclient.Cookie httpclientCookie =
201             new org.apache.commons.httpclient.Cookie(domain,
202                 theCactusCookie.getName(), theCactusCookie.getValue());
203         httpclientCookie.setComment(theCactusCookie.getComment());
204         httpclientCookie.setExpiryDate(
205             theCactusCookie.getExpiryDate());
206         httpclientCookie.setPath(path);
207         httpclientCookie.setSecure(theCactusCookie.isSecure());
208         
209         return httpclientCookie;
210     }
211 
212     /**
213      * Transforms an array of Cactus cookies into an array of Commons-HttpClient
214      * cookies, using information from the request and URL.
215      * 
216      * @param theRequest The request
217      * @param theUrl The URL
218      * @return The array of HttpClient cookies
219      */
220     public static org.apache.commons.httpclient.Cookie[] 
221         createHttpClientCookies(WebRequest theRequest, URL theUrl)
222     {
223         Vector cactusCookies = theRequest.getCookies();
224         
225         // transform the Cactus cookies into HttpClient cookies
226         org.apache.commons.httpclient.Cookie[] httpclientCookies = 
227             new org.apache.commons.httpclient.Cookie[cactusCookies.size()];
228 
229         for (int i = 0; i < cactusCookies.size(); i++)
230         {
231             Cookie cactusCookie = (Cookie) cactusCookies.elementAt(i);
232             httpclientCookies[i] = CookieUtil.createHttpClientCookie(
233                 theRequest, theUrl, cactusCookie);
234         }
235 
236         return httpclientCookies;
237     }
238 
239     /**
240      * Create a HttpClient {@link Header} for cookies that matches
241      * the domain and path.
242      * 
243      * @param theDomain the cookie domain to match
244      * @param thePath the cookie path to match
245      * @param theCookies the list of potential cookies
246      * @return the HttpClient {@link Header} containing the matching 
247      *         cookies
248      * @throws ClientException if no cookie was matching the domain
249      *         and path
250      */
251     public static Header createCookieHeader(String theDomain, String thePath,
252         org.apache.commons.httpclient.Cookie[] theCookies)
253         throws ClientException
254     {
255         Header cookieHeader = null;
256         
257         // separate domain into host and port
258         int port = 80;
259         String host = theDomain;
260         int portIndex = theDomain.indexOf(":");
261         if (portIndex != -1)
262         {
263             host = host.substring(0, portIndex);
264             port = Integer.parseInt(theDomain.substring(portIndex + 1));
265         }
266 
267         CookieSpec matcher = CookiePolicy.getDefaultSpec();
268         org.apache.commons.httpclient.Cookie[] cookies =
269             matcher.match(host, port, thePath, false, theCookies);
270         if ((cookies != null) && (cookies.length > 0))
271         {
272             cookieHeader = matcher.formatCookieHeader(cookies);
273         }
274         
275         if (cookieHeader == null)
276         {
277             throw new ClientException("Failed to create Cookie header for ["
278                 + "domain = [" + theDomain + ", path = [" + thePath
279                 + ", cookies = [" + theCookies + "]]. Turn on HttpClient "
280                 + "logging for more information about the error"); 
281         }
282         
283         return cookieHeader;
284     }
285 
286     /**
287      * @return the cookie string which will be added as a HTTP "Cookie" header
288      *         or null if no cookie has been set
289      * @param theRequest the request containing all data to pass to the server
290      *        redirector.
291      * @param theUrl the URL to connect to
292      * @throws ClientException if an error occurred when creating the cookie
293      *         string
294      */
295     public static String getCookieString(WebRequest theRequest, URL theUrl)
296         throws ClientException
297     {
298         // If no Cookies, then exit
299         Vector cookies = theRequest.getCookies();
300 
301         if (!cookies.isEmpty())
302         {
303             // transform the Cactus cookies into HttpClient cookies
304             org.apache.commons.httpclient.Cookie[] httpclientCookies = 
305                 CookieUtil.createHttpClientCookies(theRequest, theUrl);
306 
307             // and create the cookie header to send
308             Header cookieHeader = createCookieHeader(
309                 CookieUtil.getCookieDomain(theRequest, theUrl.getHost()), 
310                 CookieUtil.getCookiePath(theRequest, theUrl.getFile()), 
311                 httpclientCookies);
312 
313             return cookieHeader.getValue();
314         }
315 
316         return null;
317     }
318 }