Coverage Report - org.mule.transport.http.CookieHelper
 
Classes in this File Line Coverage Branch Coverage Complexity
CookieHelper
0%
0/60
0%
0/28
0
CookieStorageType
0%
0/9
0%
0/6
0
CookieStorageType$1
0%
0/60
0%
0/34
0
CookieStorageType$2
0%
0/40
0%
0/14
0
 
 1  
 /*
 2  
  * $Id: CookieHelper.java 19552 2010-09-10 13:08:00Z epere4 $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.transport.http;
 12  
 
 13  
 import org.mule.api.MuleEvent;
 14  
 import org.mule.api.MuleMessage;
 15  
 import org.mule.api.expression.ExpressionManager;
 16  
 
 17  
 import java.net.URI;
 18  
 import java.net.URISyntaxException;
 19  
 import java.util.ArrayList;
 20  
 import java.util.Collection;
 21  
 import java.util.Iterator;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 import java.util.Map.Entry;
 25  
 
 26  
 import org.apache.commons.httpclient.Cookie;
 27  
 import org.apache.commons.httpclient.Header;
 28  
 import org.apache.commons.httpclient.HttpClient;
 29  
 import org.apache.commons.httpclient.cookie.CookiePolicy;
 30  
 import org.apache.commons.httpclient.cookie.CookieSpec;
 31  
 import org.apache.commons.httpclient.cookie.MalformedCookieException;
 32  
 import org.apache.commons.httpclient.cookie.NetscapeDraftSpec;
 33  
 import org.apache.commons.httpclient.cookie.RFC2109Spec;
 34  
 import org.apache.commons.logging.Log;
 35  
 import org.apache.commons.logging.LogFactory;
 36  
 import org.apache.tomcat.util.http.Cookies;
 37  
 import org.apache.tomcat.util.http.MimeHeaders;
 38  
 import org.apache.tomcat.util.http.ServerCookie;
 39  
 
 40  
 /**
 41  
  * Helper functions for parsing, formatting, storing and retrieving cookie headers.
 42  
  * <p>
 43  
  * It is important that all access to Cookie data is done using this class. This will
 44  
  * help to prevent ClassCastExceptions and data corruption.
 45  
  * <p>
 46  
  * The reasons for such a very complex {@link CookieHelper} class are historical and
 47  
  * are related to the fact that cookies are a multivalued property and we store them
 48  
  * as a single message property under the name
 49  
  * {@link HttpConnector#HTTP_COOKIES_PROPERTY "cookies"}.
 50  
  * <p>
 51  
  * In an HTTP message going from client to server the cookies come on their own
 52  
  * {@link HttpConstants#HEADER_COOKIE "Cookie"} header. The HTTP message can have
 53  
  * several of these Cookie headers and each of them can store 1 or more cookies. One
 54  
  * problem with this is that in Mule we use {@link Map Maps} to store the HTTP
 55  
  * headers and this means that we can only have one object with the key
 56  
  * {@link HttpConnector#HTTP_COOKIES_PROPERTY "cookies"} (yes, we use that constant
 57  
  * instead of {@link HttpConstants#HEADER_COOKIE "Cookie"} when we store the cookies
 58  
  * inside a {@link MuleMessage}).
 59  
  * <p>
 60  
  * In an HTTP message going from server to client the Cookies go in their own
 61  
  * {@link HttpConstants#HEADER_COOKIE_SET "Set-Cookie"} header. But, again,
 62  
  * internally we store all the HTTP headers inside a {@link Map} that maps each HTTP
 63  
  * header with a single value. For Cookies it is a special case so have to be able to
 64  
  * store many cookies in the value from that map.
 65  
  * <p>
 66  
  * With all these layed out one could say that we could just have a
 67  
  * {@link Collection} of {@link Cookie Cookies}. But this is not that simple. In some
 68  
  * parts of the code the cookies are stored as an array of Cookies ({@link Cookie
 69  
  * Cookie[]}) and in some others it is stored as a {@link Map} where each entry
 70  
  * corresponds to a cookie's name/value pair (which is not strictly a cookie).
 71  
  * Specifically, when parsing cookies from the client (ie, acting as a server), the
 72  
  * code stores it as an array of cookies. When the cookies are specified as a
 73  
  * property in the endpoint (like <a href=
 74  
  * "http://www.mulesoft.org/documentation/display/MULE2USER/HTTP+Transport#HTTPTransport-Cookies"
 75  
  * >explained in the docs</a>), they are stored as a {@link Map}.
 76  
  * <p>
 77  
  * This class has helper methods that helps making code that is independent of the
 78  
  * way the cookies are stored and still keep backward compatibility. It is very
 79  
  * hacky, but I think it is better than what we had before.
 80  
  * <p>
 81  
  * <b>Know Limitation:</b> because of how cookies are handled in Mule, we don't
 82  
  * handle well the host, port and path of a Cookie. We just handle Cookies as if they
 83  
  * were only name/value pairs. This means that, for example, if a message with
 84  
  * cookies is received on an endpoint called http://localhost:4020/hello (1) and that
 85  
  * message goes to http://www.mulesoft.org/jira/ (2), then service (2) will receive
 86  
  * all the cookies that were sent to service (1) as if they were their own.
 87  
  * Furthermore, the same thing will happend on the response: all the returned cookies
 88  
  * from service (2) will reach service (1) and then the client will receive them as
 89  
  * if they were from service (1).
 90  
  */
 91  
 public class CookieHelper
 92  
 {
 93  
 
 94  
     /**
 95  
      * This is used as the default {@link URI} for
 96  
      * {@link #parseCookiesAsAClient(String, String, URI)} and overloading methods
 97  
      * for when the {@link URI} supplied is null.
 98  
      */
 99  
     private static final String DEFAULT_URI_STRING = "http://localhost:80/";
 100  
     /**
 101  
      * logger used by this class
 102  
      */
 103  0
     protected static final Log logger = LogFactory.getLog(CookieHelper.class);
 104  
 
 105  
     /**
 106  
      * Do not instantiate.
 107  
      */
 108  
     private CookieHelper()
 109  0
     {
 110  
         // no op
 111  0
     }
 112  
 
 113  
     /**
 114  
      * @param spec
 115  
      * @return the {@link CookieSpec} (defaults to {@link RFC2109Spec} when spec is
 116  
      *         null)
 117  
      */
 118  
     public static CookieSpec getCookieSpec(String spec)
 119  
     {
 120  0
         if (spec != null && spec.equalsIgnoreCase(HttpConnector.COOKIE_SPEC_NETSCAPE))
 121  
         {
 122  0
             return new NetscapeDraftSpec();
 123  
         }
 124  
         else
 125  
         {
 126  0
             return new RFC2109Spec();
 127  
         }
 128  
     }
 129  
 
 130  
     /**
 131  
      * @param spec
 132  
      * @return the cookie policy (defaults to {@link CookiePolicy#RFC_2109} when spec
 133  
      *         is null).
 134  
      */
 135  
     public static String getCookiePolicy(String spec)
 136  
     {
 137  0
         if (spec != null && spec.equalsIgnoreCase(HttpConnector.COOKIE_SPEC_NETSCAPE))
 138  
         {
 139  0
             return CookiePolicy.NETSCAPE;
 140  
         }
 141  
         else
 142  
         {
 143  0
             return CookiePolicy.RFC_2109;
 144  
         }
 145  
     }
 146  
 
 147  
     /**
 148  
      * @see #parseCookiesAsAClient(String, String, URI)
 149  
      */
 150  
     public static Cookie[] parseCookiesAsAClient(Header cookieHeader, String spec)
 151  
         throws MalformedCookieException
 152  
     {
 153  0
         return parseCookiesAsAClient(cookieHeader.getValue(), spec, null);
 154  
     }
 155  
 
 156  
     /**
 157  
      * @see #parseCookiesAsAClient(String, String, URI)
 158  
      */
 159  
     public static Cookie[] parseCookiesAsAClient(String cookieHeaderValue, String spec)
 160  
         throws MalformedCookieException
 161  
     {
 162  0
         return parseCookiesAsAClient(cookieHeaderValue, spec, null);
 163  
     }
 164  
 
 165  
     /**
 166  
      * @see #parseCookiesAsAClient(String, String, URI)
 167  
      */
 168  
     public static Cookie[] parseCookiesAsAClient(Header cookieHeader, String spec, URI uri)
 169  
         throws MalformedCookieException
 170  
     {
 171  0
         return parseCookiesAsAClient(cookieHeader.getValue(), spec, uri);
 172  
     }
 173  
 
 174  
     /**
 175  
      * This method parses the value of {@link HttpConstants#HEADER_COOKIE_SET
 176  
      * "Set-Cookie"} HTTP header, returning an array with all the {@link Cookie}
 177  
      * found. This method is intended to be used from the client side of the HTTP
 178  
      * connection.
 179  
      * 
 180  
      * @param cookieHeaderValue the value with the cookie/s to parse.
 181  
      * @param spec the spec according to {@link #getCookieSpec(String)} (can be null)
 182  
      * @param uri the uri information that will be use to complete Cookie information
 183  
      *            (host, port and path). If null then the default
 184  
      *            {@value #DEFAULT_URI_STRING} will be used.
 185  
      * @return
 186  
      * @throws MalformedCookieException
 187  
      */
 188  
     public static Cookie[] parseCookiesAsAClient(String cookieHeaderValue, String spec, URI uri)
 189  
         throws MalformedCookieException
 190  
     {
 191  0
         if (uri == null)
 192  
         {
 193  
             try
 194  
             {
 195  0
                 uri = new URI(DEFAULT_URI_STRING);
 196  
             }
 197  0
             catch (URISyntaxException e)
 198  
             {
 199  0
                 throw new RuntimeException("This should have not happened", e);
 200  0
             }
 201  
         }
 202  0
         CookieSpec cookieSpec = getCookieSpec(spec);
 203  0
         boolean secure = uri.getScheme() != null && uri.getScheme().equalsIgnoreCase("https");
 204  0
         String host = uri.getHost();
 205  0
         int port = getPortFromURI(uri);
 206  0
         String path = uri.getPath();
 207  
 
 208  0
         return cookieSpec.parse(host, port, path, secure, cookieHeaderValue);
 209  
     }
 210  
 
 211  
     private static int getPortFromURI(URI uri) throws MalformedCookieException
 212  
     {
 213  0
         int port = uri.getPort();
 214  0
         if (port < 0)
 215  
         {
 216  0
             String scheme = uri.getScheme();
 217  0
             if (scheme.equalsIgnoreCase("https"))
 218  
             {
 219  0
                 port = 443;
 220  
             }
 221  0
             else if (scheme.equalsIgnoreCase("http"))
 222  
             {
 223  0
                 port = 80;
 224  
             }
 225  
             else
 226  
             {
 227  0
                 throw new MalformedCookieException(
 228  
                     "The uri ("
 229  
                                     + uri
 230  
                                     + ") does not specify a port and no default is available for its scheme ("
 231  
                                     + scheme + ").");
 232  
             }
 233  
         }
 234  0
         return port;
 235  
     }
 236  
 
 237  
     /**
 238  
      * This method parses the value of an HTTP {@link HttpConstants#HEADER_COOKIE
 239  
      * "Cookie"} header that comes from a client to a server. It returns all the
 240  
      * Cookies present in the header.
 241  
      * 
 242  
      * @param header the header from which the cookie will be parsed. Please not that
 243  
      *            only the {@link Header#getValue() value} of this header will be
 244  
      *            used. No validation will be made to make sure that the
 245  
      *            {@link Header#getName() headerName} is actually a
 246  
      *            {@link HttpConstants#HEADER_COOKIE}.
 247  
      * @return
 248  
      */
 249  
     public static Cookie[] parseCookiesAsAServer(Header header, URI uri)
 250  
     {
 251  0
         return parseCookiesAsAServer(header.getValue(), uri);
 252  
     }
 253  
 
 254  
     /**
 255  
      * This method parses the value of an HTTP {@link HttpConstants#HEADER_COOKIE
 256  
      * "Cookie"} header that comes from a client to a server. It returns all the
 257  
      * Cookies present in the header.
 258  
      * 
 259  
      * @param headerValue the value of the header from which the cookie will be
 260  
      *            parsed.
 261  
      * @param uri
 262  
      * @return
 263  
      */
 264  
     public static Cookie[] parseCookiesAsAServer(String headerValue, URI uri)
 265  
     {
 266  0
         MimeHeaders mimeHeaders = new MimeHeaders();
 267  0
         mimeHeaders.addValue(HttpConstants.HEADER_COOKIE).setBytes(headerValue.getBytes(), 0,
 268  
             headerValue.length());
 269  
 
 270  0
         Cookies cs = new Cookies(mimeHeaders);
 271  0
         Cookie[] cookies = new Cookie[cs.getCookieCount()];
 272  0
         for (int i = 0; i < cs.getCookieCount(); i++)
 273  
         {
 274  0
             ServerCookie serverCookie = cs.getCookie(i);
 275  0
             cookies[i] = transformServerCookieToClientCookie(serverCookie);
 276  0
             if (uri != null)
 277  
             {
 278  0
                 cookies[i].setSecure(uri.getScheme() != null && uri.getScheme().equalsIgnoreCase("https"));
 279  0
                 cookies[i].setDomain(uri.getHost());
 280  0
                 cookies[i].setPath(uri.getPath());
 281  
             }
 282  
         }
 283  0
         return cookies;
 284  
     }
 285  
 
 286  
     /**
 287  
      * Transforms a {@link ServerCookie} (from apache tomcat) into a {@link Cookie}
 288  
      * (from commons httpclient). Both types of Cookie hold the same data but the
 289  
      * {@link ServerCookie} is the type that you get when parsing cookies as a
 290  
      * Server.
 291  
      * 
 292  
      * @param serverCookie
 293  
      * @return
 294  
      */
 295  
     protected static Cookie transformServerCookieToClientCookie(ServerCookie serverCookie)
 296  
     {
 297  0
         Cookie clientCookie = new Cookie(serverCookie.getDomain().toString(), serverCookie.getName()
 298  
             .toString(), serverCookie.getValue().toString(), serverCookie.getPath().toString(),
 299  
             serverCookie.getMaxAge(), serverCookie.getSecure());
 300  0
         clientCookie.setComment(serverCookie.getComment().toString());
 301  0
         clientCookie.setVersion(serverCookie.getVersion());
 302  0
         return clientCookie;
 303  
     }
 304  
 
 305  
     /**
 306  
      * This method formats the cookie so it can be send from server to client in a
 307  
      * {@link HttpConstants#HEADER_COOKIE_SET "Set-Cookie"} header.
 308  
      * 
 309  
      * @param cookie
 310  
      * @return
 311  
      */
 312  
     public static String formatCookieForASetCookieHeader(Cookie cookie)
 313  
     {
 314  0
         StringBuffer sb = new StringBuffer();
 315  0
         ServerCookie.appendCookieValue(sb, cookie.getVersion(), cookie.getName(), cookie.getValue(),
 316  
             cookie.getPath(), cookie.getDomain(), cookie.getComment(), -1, cookie.getSecure());
 317  0
         String cookieForASetCookieHeader = sb.toString();
 318  0
         return cookieForASetCookieHeader;
 319  
     }
 320  
 
 321  
     /**
 322  
      * Adds to the client all the cookies present in the cookiesObject.
 323  
      * 
 324  
      * @param client
 325  
      * @param cookiesObject this must be either a {@link Map Map&lt;String,
 326  
      *            String&gt;} or a {@link Cookie Cookie[]}. It can be null.
 327  
      * @param policy
 328  
      * @param event this one is used only if the cookies are stored in a {@link Map}
 329  
      *            in order to resolve expressions with the {@link ExpressionManager}.
 330  
      * @param destinationUri the host, port and path of this {@link URI} will be used
 331  
      *            as the data of the cookies that are added.
 332  
      */
 333  
     public static void addCookiesToClient(HttpClient client,
 334  
                                           Object cookiesObject,
 335  
                                              String policy,
 336  
                                              MuleEvent event,
 337  
                                              URI destinationUri)
 338  
     {
 339  0
         CookieStorageType.resolveCookieStorageType(cookiesObject).addCookiesToClient(client, cookiesObject,
 340  
             policy, event, destinationUri);
 341  0
     }
 342  
 
 343  
     /**
 344  
      * This method merges a new Cookie (or override the previous one if it exists) to
 345  
      * the preExistentCookies. The result (the old cookies with the new one added) is
 346  
      * returned. If a cookie with the same name already exists, then it will be
 347  
      * overridden.
 348  
      * <p>
 349  
      * It is <b>important</b> that you use the returned value of this method because
 350  
      * for some implementations of preExistentCookies it is not possible to add new
 351  
      * Cookies (for example, on {@link Cookie Cookie[]}).
 352  
      * 
 353  
      * @param preExistentCookies this must be either a {@link Map Map&lt;String,
 354  
      *            String&gt;} or a {@link Cookie Cookie[]}. It can be null.
 355  
      * @param cookieName the new cookie name to be added.
 356  
      * @param cookieValue the new cookie value to be added.
 357  
      * @return
 358  
      */
 359  
     public static Object putAndMergeCookie(Object preExistentCookies, String cookieName, String cookieValue)
 360  
     {
 361  0
         return CookieStorageType.resolveCookieStorageType(preExistentCookies).putAndMergeCookie(
 362  
             preExistentCookies, cookieName, cookieValue);
 363  
     }
 364  
 
 365  
     /**
 366  
      * Merges all the Cookies in newCookiesArray with the preExistentCookies, adding
 367  
      * the new ones and overwriting the existing ones (existing means same cookie
 368  
      * name).
 369  
      * <p>
 370  
      * It is <b>important</b> that you use the returned value of this method because
 371  
      * for some implementations of preExistentCookies it is not possible to add new
 372  
      * Cookies (for example, on {@link Cookie Cookie[]}).
 373  
      * 
 374  
      * @param preExistentCookies
 375  
      * @param newCookiesArray
 376  
      * @return
 377  
      */
 378  
     public static Object putAndMergeCookie(Object preExistentCookies, Cookie[] newCookiesArray)
 379  
     {
 380  0
         return CookieStorageType.resolveCookieStorageType(preExistentCookies).putAndMergeCookie(
 381  
             preExistentCookies, newCookiesArray);
 382  
     }
 383  
 
 384  
     /**
 385  
      * Merges all the Cookies in newCookiesMap with the preExistentCookies, adding
 386  
      * the new ones and overwriting the existing ones (existing means same cookie
 387  
      * name).
 388  
      * <p>
 389  
      * It is <b>important</b> that you use the returned value of this method because
 390  
      * for some implementations of preExistentCookies it is not possible to add new
 391  
      * Cookies (for example, on {@link Cookie Cookie[]}).
 392  
      * 
 393  
      * @param preExistentCookies
 394  
      * @param newCookiesMap
 395  
      * @return
 396  
      */
 397  
     public static Object putAndMergeCookie(Object preExistentCookies, Map<String, String> newCookiesMap)
 398  
     {
 399  0
         return CookieStorageType.resolveCookieStorageType(preExistentCookies).putAndMergeCookie(
 400  
             preExistentCookies, newCookiesMap);
 401  
     }
 402  
 
 403  
     /**
 404  
      * Searches and return the cookie with the cookieName in the cookiesObject. It
 405  
      * returns null if the cookie is not present.
 406  
      * 
 407  
      * @param cookiesObject
 408  
      * @param cookieName
 409  
      * @return
 410  
      */
 411  
     public static String getCookieValueFromCookies(Object cookiesObject, String cookieName)
 412  
     {
 413  0
         return CookieStorageType.resolveCookieStorageType(cookiesObject).getCookieValueFromCookies(
 414  
             cookiesObject, cookieName);
 415  
     }
 416  
 
 417  
     /**
 418  
      * Returns an array view of the cookiesObject.
 419  
      * 
 420  
      * @param cookiesObject
 421  
      * @return
 422  
      */
 423  
     public static Cookie[] asArrayOfCookies(Object cookiesObject)
 424  
     {
 425  0
         return CookieStorageType.resolveCookieStorageType(cookiesObject).asArrayOfCookies(cookiesObject);
 426  
     }
 427  
 
 428  
 }
 429  
 
 430  
 /**
 431  
  * This enum type is here to distinguish and handle the two type of cookie storage
 432  
  * that we have. The method
 433  
  * {@link CookieStorageType#resolveCookieStorageType(Object)} allows you to select
 434  
  * the appropriate {@link CookieStorageType} for the cookiesObject that you have.
 435  
  */
 436  0
 enum CookieStorageType
 437  
 {
 438  
     /**
 439  
      * This corresponds to the storage of cookies as a {@link Cookie Cookie[]}.
 440  
      * <p>
 441  
      * All the parameters of type {@link Object} in the method of this object are
 442  
      * assumed to be of type {@link Cookie Cookie[]} and won't be checked. They will
 443  
      * be cast to {@link Cookie Cookie[]}.
 444  
      */
 445  0
     ARRAY_OF_COOKIES
 446  
     {
 447  
         @Override
 448  
         public Object putAndMergeCookie(Object preExistentCookies, String cookieName, String cookieValue)
 449  
         {
 450  0
             final Cookie[] preExistentCookiesArray = (Cookie[]) preExistentCookies;
 451  
 
 452  0
             final int sessionIndex = getCookieIndexFromCookiesArray(cookieName, preExistentCookiesArray);
 453  
 
 454  
             // domain, path, secure (https) and expiry are handled in method
 455  
             // CookieHelper.addCookiesToClient()
 456  0
             final Cookie newSessionCookie = new Cookie(null, cookieName, cookieValue);
 457  
             final Cookie[] mergedCookiesArray;
 458  0
             if (sessionIndex >= 0)
 459  
             {
 460  0
                 preExistentCookiesArray[sessionIndex] = newSessionCookie;
 461  0
                 mergedCookiesArray = preExistentCookiesArray;
 462  
             }
 463  
             else
 464  
             {
 465  0
                 Cookie[] newSessionCookieArray = new Cookie[]{newSessionCookie};
 466  0
                 mergedCookiesArray = concatenateCookies(preExistentCookiesArray, newSessionCookieArray);
 467  
             }
 468  0
             return mergedCookiesArray;
 469  
         }
 470  
 
 471  
         protected Cookie[] concatenateCookies(Cookie[] cookies1, Cookie[] cookies2)
 472  
         {
 473  0
             if (cookies1 == null)
 474  
             {
 475  0
                 return cookies2;
 476  
             }
 477  0
             else if (cookies2 == null)
 478  
             {
 479  0
                 return null;
 480  
             }
 481  
             else
 482  
             {
 483  0
                 Cookie[] mergedCookies = new Cookie[cookies1.length + cookies2.length];
 484  0
                 System.arraycopy(cookies1, 0, mergedCookies, 0, cookies1.length);
 485  0
                 System.arraycopy(cookies2, 0, mergedCookies, cookies1.length, cookies2.length);
 486  0
                 return mergedCookies;
 487  
             }
 488  
         }
 489  
 
 490  
         protected int getCookieIndexFromCookiesArray(String cookieName, Cookie[] preExistentCookies)
 491  
         {
 492  0
             if (preExistentCookies != null && cookieName != null)
 493  
             {
 494  0
                 for (int i = 0; i < preExistentCookies.length; i++)
 495  
                 {
 496  0
                     if (cookieName.equals(preExistentCookies[i].getName()))
 497  
                     {
 498  0
                         return i;
 499  
                     }
 500  
                 }
 501  
             }
 502  0
             return -1;
 503  
         }
 504  
 
 505  
         @Override
 506  
         public String getCookieValueFromCookies(Object cookiesObject, String cookieName)
 507  
         {
 508  0
             Cookie[] cookies = (Cookie[]) cookiesObject;
 509  
 
 510  0
             int sessionIndex = getCookieIndexFromCookiesArray(cookieName, cookies);
 511  0
             if (sessionIndex >= 0)
 512  
             {
 513  0
                 return cookies[sessionIndex].getValue();
 514  
             }
 515  
             else
 516  
             {
 517  0
                 return null;
 518  
             }
 519  
         }
 520  
 
 521  
         @Override
 522  
         public void addCookiesToClient(HttpClient client,
 523  
                                        Object cookiesObject,
 524  
                                        String policy,
 525  
                                        MuleEvent event,
 526  
                                        URI destinationUri)
 527  
         {
 528  0
             Cookie[] cookies = (Cookie[]) cookiesObject;
 529  
 
 530  0
             if (cookies != null && cookies.length > 0)
 531  
             {
 532  0
                 String host = destinationUri.getHost();
 533  0
                 String path = destinationUri.getPath();
 534  0
                 for (Cookie cookie : cookies)
 535  
                 {
 536  0
                     client.getState().addCookie(
 537  
                         new Cookie(host, cookie.getName(), cookie.getValue(), path, cookie.getExpiryDate(),
 538  
                             cookie.getSecure()));
 539  
                 }
 540  0
                 client.getParams().setCookiePolicy(CookieHelper.getCookiePolicy(policy));
 541  
             }
 542  0
         }
 543  
 
 544  
         @Override
 545  
         public Object putAndMergeCookie(Object preExistentCookies, Cookie[] newCookiesArray)
 546  
         {
 547  0
             if (newCookiesArray == null)
 548  
             {
 549  0
                 return preExistentCookies;
 550  
             }
 551  0
             final List<Cookie> cookiesThatAreReallyNew = new ArrayList<Cookie>(newCookiesArray.length);
 552  0
             final Cookie[] preExistentCookiesArray = (Cookie[]) preExistentCookies;
 553  0
             for (Cookie newCookie : newCookiesArray)
 554  
             {
 555  0
                 int newCookieInPreExistentArrayIndex = getCookieIndexFromCookiesArray(newCookie.getName(),
 556  
                     preExistentCookiesArray);
 557  0
                 if (newCookieInPreExistentArrayIndex >= 0)
 558  
                 {
 559  
                     // overwrite the old one
 560  0
                     preExistentCookiesArray[newCookieInPreExistentArrayIndex] = newCookie;
 561  
                 }
 562  
                 else
 563  
                 {
 564  
                     // needs to add it at the end
 565  0
                     cookiesThatAreReallyNew.add(newCookie);
 566  
                 }
 567  
             }
 568  
 
 569  0
             return concatenateCookies(preExistentCookiesArray,
 570  
                 cookiesThatAreReallyNew.toArray(new Cookie[cookiesThatAreReallyNew.size()]));
 571  
         }
 572  
 
 573  
         @Override
 574  
         public Object putAndMergeCookie(Object preExistentCookies, Map<String, String> newCookiesMap)
 575  
         {
 576  0
             if (newCookiesMap == null)
 577  
             {
 578  0
                 return putAndMergeCookie(preExistentCookies, (Cookie[]) null);
 579  
             }
 580  
             else
 581  
             {
 582  0
                 Cookie[] cookiesArray = new Cookie[newCookiesMap.size()];
 583  0
                 int i = 0;
 584  0
                 for (Entry<String, String> cookieEntry : newCookiesMap.entrySet())
 585  
                 {
 586  0
                     Cookie cookie = new Cookie();
 587  0
                     cookie.setName(cookieEntry.getKey());
 588  0
                     cookie.setValue(cookieEntry.getValue());
 589  0
                     cookiesArray[i++] = cookie;
 590  0
                 }
 591  0
                 return putAndMergeCookie(preExistentCookies, cookiesArray);
 592  
             }
 593  
         }
 594  
 
 595  
         @Override
 596  
         public Cookie[] asArrayOfCookies(Object cookiesObject)
 597  
         {
 598  0
             if (cookiesObject == null)
 599  
             {
 600  0
                 return ZERO_COOKIES;
 601  
             }
 602  
             else
 603  
             {
 604  0
                 return (Cookie[]) cookiesObject;
 605  
             }
 606  
         }
 607  
 
 608  
     },
 609  
     /**
 610  
      * This corresponds to the storage of cookies as {@link Map Map<String,String>},
 611  
      * where the keys are the cookie names and the values are the cookie values.
 612  
      * <p>
 613  
      * All the parameters of type {@link Object} in the method of this object are
 614  
      * assumed to be of type {@link Map Map&lt;String, String&gt;} and won't be
 615  
      * checked. They will be cast to {@link Map} and used as if all the keys and
 616  
      * values are of type {@link String}.
 617  
      */
 618  0
     MAP_STRING_STRING
 619  
     {
 620  
         @Override
 621  
         public Object putAndMergeCookie(Object preExistentCookies, String cookieName, String cookieValue)
 622  
         {
 623  0
             final Map<String, String> cookieMap = (Map<String, String>) preExistentCookies;
 624  
 
 625  0
             cookieMap.put(cookieName, cookieValue);
 626  0
             return cookieMap;
 627  
         }
 628  
 
 629  
         @Override
 630  
         public String getCookieValueFromCookies(Object cookiesObject, String cookieName)
 631  
         {
 632  0
             return ((Map<String, String>) cookiesObject).get(cookieName);
 633  
         }
 634  
 
 635  
         @Override
 636  
         public void addCookiesToClient(HttpClient client,
 637  
                                        Object cookiesObject,
 638  
                                        String policy,
 639  
                                        MuleEvent event,
 640  
                                        URI destinationUri)
 641  
         {
 642  0
             Map<String, String> cookieMap = (Map<String, String>) cookiesObject;
 643  
 
 644  0
             client.getParams().setCookiePolicy(CookieHelper.getCookiePolicy(policy));
 645  
 
 646  0
             String host = destinationUri.getHost();
 647  0
             String path = destinationUri.getPath();
 648  0
             Iterator<String> keyIter = cookieMap.keySet().iterator();
 649  0
             while (keyIter.hasNext())
 650  
             {
 651  0
                 String key = keyIter.next();
 652  0
                 String cookieValue = cookieMap.get(key);
 653  
 
 654  
                 final String value;
 655  0
                 if (event != null)
 656  
                 {
 657  0
                     value = event.getMuleContext()
 658  
                         .getExpressionManager()
 659  
                         .parse(cookieValue, event.getMessage());
 660  
                 }
 661  
                 else
 662  
                 {
 663  0
                     value = cookieValue;
 664  
                 }
 665  
 
 666  0
                 Cookie cookie = new Cookie(host, key, value, path, null, false);
 667  0
                 client.getState().addCookie(cookie);
 668  0
             }
 669  
 
 670  0
         }
 671  
 
 672  
         @Override
 673  
         public Object putAndMergeCookie(Object preExistentCookies, Cookie[] newCookiesArray)
 674  
         {
 675  0
             if (newCookiesArray == null)
 676  
             {
 677  0
                 return preExistentCookies;
 678  
             }
 679  0
             for (Cookie cookie : newCookiesArray)
 680  
             {
 681  0
                 preExistentCookies = putAndMergeCookie(preExistentCookies, cookie.getName(),
 682  
                     cookie.getValue());
 683  
             }
 684  0
             return preExistentCookies;
 685  
         }
 686  
 
 687  
         @Override
 688  
         public Object putAndMergeCookie(Object preExistentCookies, Map<String, String> newCookiesMap)
 689  
         {
 690  0
             if (newCookiesMap == null)
 691  
             {
 692  0
                 return preExistentCookies;
 693  
             }
 694  0
             for (Entry<String, String> cookieEntry : newCookiesMap.entrySet())
 695  
             {
 696  0
                 preExistentCookies = putAndMergeCookie(preExistentCookies, cookieEntry.getKey(),
 697  
                     cookieEntry.getValue());
 698  
             }
 699  0
             return preExistentCookies;
 700  
         }
 701  
 
 702  
         @Override
 703  
         public Cookie[] asArrayOfCookies(Object cookiesObject)
 704  
         {
 705  0
             Map<String, String> cookieMap = (Map<String, String>) cookiesObject;
 706  0
             Cookie[] arrayOfCookies = new Cookie[cookieMap.size()];
 707  0
             int i = 0;
 708  0
             for (Entry<String, String> cookieEntry : cookieMap.entrySet())
 709  
             {
 710  0
                 Cookie cookie = new Cookie();
 711  0
                 cookie.setName(cookieEntry.getKey());
 712  0
                 cookie.setValue(cookieEntry.getValue());
 713  0
                 arrayOfCookies[i++] = cookie;
 714  0
             }
 715  0
             return arrayOfCookies;
 716  
         }
 717  
 
 718  
     };
 719  
 
 720  0
     private static final Cookie[] ZERO_COOKIES = new Cookie[0];
 721  
 
 722  
     /**
 723  
      * Resolves the cookiesObject to the appropriate {@link CookieStorageType}.
 724  
      * 
 725  
      * @param cookiesObject
 726  
      * @return
 727  
      */
 728  
     public static CookieStorageType resolveCookieStorageType(Object cookiesObject)
 729  
     {
 730  0
         if (cookiesObject == null || cookiesObject instanceof Cookie[])
 731  
         {
 732  0
             return CookieStorageType.ARRAY_OF_COOKIES;
 733  
         }
 734  0
         else if (cookiesObject instanceof Map)
 735  
         {
 736  0
             return CookieStorageType.MAP_STRING_STRING;
 737  
         }
 738  
         else
 739  
         {
 740  0
             throw new IllegalArgumentException("Invalid cookiesObject. Only " + Cookie.class + "[] and "
 741  
                                                + Map.class + " are supported: " + cookiesObject);
 742  
         }
 743  
     }
 744  
 
 745  
     /**
 746  
      * @see CookieHelper#putAndMergeCookie(Object, String, String)
 747  
      */
 748  
     public abstract Object putAndMergeCookie(Object preExistentCookies, String cookieName, String cookieValue);
 749  
 
 750  
     /**
 751  
      * @see CookieHelper#putAndMergeCookie(Object, Cookie[])
 752  
      */
 753  
     public abstract Object putAndMergeCookie(Object preExistentCookies, Cookie[] newCookiesArray);
 754  
 
 755  
     /**
 756  
      * @see CookieHelper#putAndMergeCookie(Object, Map)
 757  
      */
 758  
     public abstract Object putAndMergeCookie(Object preExistentCookies, Map<String, String> newCookiesMap);
 759  
 
 760  
     /**
 761  
      * @see CookieHelper#getCookieValueFromCookies(Object, String)
 762  
      */
 763  
     public abstract String getCookieValueFromCookies(Object cookiesObject, String cookieName);
 764  
 
 765  
     /**
 766  
      * @see CookieHelper#addCookiesToClient(HttpClient, Object, String, MuleEvent,
 767  
      *      URI)
 768  
      */
 769  
     public abstract void addCookiesToClient(HttpClient client,
 770  
                                             Object cookiesObject,
 771  
                                             String policy,
 772  
                                             MuleEvent event,
 773  
                                             URI destinationUri);
 774  
 
 775  
     /**
 776  
      * @see CookieHelper#asArrayOfCookies(Object)
 777  
      */
 778  
     public abstract Cookie[] asArrayOfCookies(Object cookiesObject);
 779  
 }