    1   /*
    2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/HttpState.java,v 1.38 2004/12/20 11:50:54 olegk Exp $
    3    * $Revision: 5562 $
    4    * $Date: 2007-11-16 00:53:10 +0000 (Fri, 16 Nov 2007) $
    5    *
    6    * ====================================================================
    7    *
    8    *  Copyright 1999-2004 The Apache Software Foundation
    9    *
    10   *  Licensed under the Apache License, Version 2.0 (the "License");
    11   *  you may not use this file except in compliance with the License.
    12   *  You may obtain a copy of the License at
    13   *
    14   *      http://www.apache.org/licenses/LICENSE-2.0
    15   *
    16   *  Unless required by applicable law or agreed to in writing, software
    17   *  distributed under the License is distributed on an "AS IS" BASIS,
    18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    19   *  See the License for the specific language governing permissions and
    20   *  limitations under the License.
    21   * ====================================================================
    22   *
    23   * This software consists of voluntary contributions made by many
    24   * individuals on behalf of the Apache Software Foundation.  For more
    25   * information on the Apache Software Foundation, please see
    26   * <http://www.apache.org/>.
    27   *
    28   */
    29
    30  package org.apache.commons.httpclient;
    31
    32  import java.util.ArrayList;
    33  import java.util.Collection; // <- IA/HERITRIX CHANGE
    34  import java.util.Date;
    35  import java.util.HashMap;
    36  import java.util.Map;
    37  import java.util.List;
    38  import java.util.Iterator;
    39  import java.util.SortedMap; // <- IA/HERITRIX CHANGE
    40  import java.util.TreeMap;   // <- IA/HERITRIX CHANGE
    41
    42  import org.apache.commons.httpclient.cookie.CookieSpec;
    43  import org.apache.commons.httpclient.cookie.CookiePolicy;
    44  import org.apache.commons.httpclient.auth.AuthScope;
    45  import org.apache.commons.logging.Log;
    46  import org.apache.commons.logging.LogFactory;
    47
    48  import com.sleepycat.collections.StoredIterator; // <- IA/HERITRIX CHANGE
    49
    50  /***
    51   * <p>
    52   * A container for HTTP attributes that may persist from request
    53   * to request, such as {@link Cookie cookies} and authentication
    54   * {@link Credentials credentials}.
    55   * </p>
    56   *
    57   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
    58   * @author Rodney Waldhoff
    59   * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
    60   * @author Sean C. Sullivan
    61   * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
    62   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
    63   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
    64   * @author <a href="mailto:adrian@intencha.com">Adrian Sutton</a>
    65   *
    66   * @version $Revision: 5562 $ $Date: 2007-11-16 00:53:10 +0000 (Fri, 16 Nov 2007) $
    67   *
    68   */
    69  @SuppressWarnings("unchecked") // <- IA/HERITRIX CHANGE
    70  public class HttpState {
    71
    72      // ----------------------------------------------------- Instance Variables
    73
    74      /***
    75       * Map of {@link Credentials credentials} by realm that this
    76       * HTTP state contains.
    77       */
    78      private HashMap credMap = new HashMap();
    79
    80      /***
    81       * Map of {@link Credentials proxy credentials} by realm that this
    82       * HTTP state contains
    83       */
    84      private HashMap proxyCred = new HashMap();
    85
    86  // BEGIN IA/HERITRIX CHANGES
    87  //    /***
    88  //     * Array of {@link Cookie cookies} that this HTTP state contains.
    89  //     */
    90  //    private ArrayList cookiesArrayList = new ArrayList();
    91      /***
    92       * SortedMap of {@link Cookie cookies} that this HTTP state contains.
    93       */
    94      private SortedMap cookiesMap = new TreeMap();
    95  // END IA/HERITRIX CHANGES
    96
    97      private boolean preemptive = false;
    98
    99      private int cookiePolicy = -1;
    100         // -------------------------------------------------------- Class Variables
    101
    102     /***
    103      * The boolean system property name to turn on preemptive authentication.
    104      * @deprecated This field and feature will be removed following HttpClient 3.0.
    105      */
    106     public static final String PREEMPTIVE_PROPERTY = "httpclient.authentication.preemptive";
    107
    108     /***
    109      * The default value for {@link #PREEMPTIVE_PROPERTY}.
    110      * @deprecated This field and feature will be removed following HttpClient 3.0.
    111      */
    112     public static final String PREEMPTIVE_DEFAULT = "false";
    113
    114     /*** Log object for this class. */
    115     private static final Log LOG = LogFactory.getLog(HttpState.class);
    116
    117     /***
    118      * Default constructor.
    119      */
    120     public HttpState() {
    121         super();
    122     }
    123
    124     // ------------------------------------------------------------- Properties
    125
    126     /***
    127      * Adds an {@link Cookie HTTP cookie}, replacing any existing equivalent cookies.
    128      * If the given cookie has already expired it will not be added, but existing
    129      * values will still be removed.
    130      *
    131      * @param cookie the {@link Cookie cookie} to be added
    132      *
    133      * @see #addCookies(Cookie[])
    134      *
    135      */
    136     public synchronized void addCookie(Cookie cookie) {
    137         LOG.trace("enter HttpState.addCookie(Cookie)");
    138
    139 // BEGIN IA/HERITRIX CHANGES
    140 // PRIOR IMPL & COMPARISON HARNESS LEFT COMMENTED OUT FOR TEMPORARY REFERENCE
    141 //        Cookie removed1 = null;
    142 //        Cookie removed2 = null;
    143         if (cookie != null) {
    144             // first remove any old cookie that is equivalent
    145 //            for (Iterator it = cookiesArrayList.iterator(); it.hasNext();) {
    146 //                Cookie tmp = (Cookie) it.next();
    147 //                if (cookie.equals(tmp)) {
    148 //                    it.remove();
    149 //                    removed1 = tmp;
    150 //                    break;
    151 //                }
    152 //            }
    153             if (!cookie.isExpired()) {
    154 //                cookiesArrayList.add(cookie);
    155                 cookiesMap.put(cookie.getSortKey(),cookie);
    156             } else {
    157                 cookiesMap.remove(cookie.getSortKey());
    158             }
    159         }
    160 //        if(removed1!=null && !removed1.equals(removed2)) {
    161 //            System.out.println("addCookie discrepancy");
    162 //        }
    163 // END IA/HERITRIX CHANGES
    164     }
    165
    166     /***
    167      * Adds an array of {@link Cookie HTTP cookies}. Cookies are added individually and
    168      * in the given array order. If any of the given cookies has already expired it will
    169      * not be added, but existing values will still be removed.
    170      *
    171      * @param cookies the {@link Cookie cookies} to be added
    172      *
    173      * @see #addCookie(Cookie)
    174      *
    175      *
    176      */
    177     public synchronized void addCookies(Cookie[] cookies) {
    178         LOG.trace("enter HttpState.addCookies(Cookie[])");
    179
    180         if (cookies != null) {
    181             for (int i = 0; i < cookies.length; i++) {
    182                 this.addCookie(cookies[i]);
    183             }
    184         }
    185     }
    186
    187     /***
    188      * Returns an array of {@link Cookie cookies} that this HTTP
    189      * state currently contains.
    190      *
    191      * @return an array of {@link Cookie cookies}.
    192      *
    193      * @see #getCookies(String, int, String, boolean)
    194      *
    195      * @deprecated use getCookiesMap() // <- IA/HERITRIX CHANGE
    196      */
    197     public synchronized Cookie[] getCookies() {
    198         LOG.trace("enter HttpState.getCookies()");
    199 // BEGIN IA/HERITRIX CHANGES
    200 //      PRIOR IMPL & COMPARISON HARNESS LEFT COMMENTED OUT FOR TEMPORARY REFERENCE
    201 //        Cookie[] arrayListAnswer = (Cookie[]) (cookiesArrayList.toArray(new Cookie[cookiesArrayList.size()]));
    202         ArrayList arrayableCookies = new ArrayList();
    203         Iterator iter = cookiesMap.values().iterator();
    204         while(iter.hasNext()) {
    205             arrayableCookies.add(iter.next());
    206     }
    207         StoredIterator.close(iter);
    208         Cookie[] mapAnswer =
    209             (Cookie[]) arrayableCookies.toArray(new Cookie[arrayableCookies.size()]);
    210
    211 //        if(cookiesArrayList.size()!=arrayableCookies.size()) {
    212 //            System.out.println("discrepancy");
    213 //        }
    214         return mapAnswer;
    215 // END IA/HERITRIX CHANGES
    216     }
    217
    218 // START IA/HERITRIX ADDITIONS
    219     /***
    220      * Returns a sorted map of {@link Cookie cookies} that this HTTP
    221      * state currently contains.
    222      *
    223      * Any operations on this map should be synchronized with respect
    224      * to this HttpState instance.
    225      *
    226      * @return sorter map of {@link Cookie cookies}
    227      */
    228     public synchronized SortedMap getCookiesMap() {
    229         return cookiesMap;
    230     }
    231
    232     /***
    233      * Replace the standard sorted map with an external implemenations
    234      * (such as one backed by persistent store, like BDB's StoredSortedMap.)
    235      *
    236      * @param map alternate sorted map to use to store cookies
    237      */
    238     public synchronized void setCookiesMap(SortedMap map) {
    239         this.cookiesMap = map;
    240     }
    241 // END IA/HERITRIX ADDITIONS
    242
    243     /***
    244      * Returns an array of {@link Cookie cookies} in this HTTP
    245      * state that match the given request parameters.
    246      *
    247      * @param domain the request domain
    248      * @param port the request port
    249      * @param path the request path
    250      * @param secure <code>true</code> when using HTTPS
    251      *
    252      * @return an array of {@link Cookie cookies}.
    253      *
    254      * @see #getCookies()
    255      *
    256      * @deprecated use CookieSpec#match(String, int, String, boolean, Cookie)
    257      */
    258     public synchronized Cookie[] getCookies(
    259         String domain,
    260         int port,
    261         String path,
    262         boolean secure
    263     ) {
    264         LOG.trace("enter HttpState.getCookies(String, int, String, boolean)");
    265
    266         CookieSpec matcher = CookiePolicy.getDefaultSpec();
    267 // BEGIN IA/HERITRIX CHANGES
    268 //      PRIOR IMPL & COMPARISON HARNESS LEFT COMMENTED OUT FOR TEMPORARY REFERENCE
    269 //        ArrayList list = new ArrayList(cookiesArrayList.size());
    270 //        for (int i = 0, m = cookiesArrayList.size(); i < m; i++) {
    271 //            Cookie cookie = (Cookie) (cookiesArrayList.get(i));
    272 //            if (matcher.match(domain, port, path, secure, cookie)) {
    273 //                list.add(cookie);
    274 //            }
    275 //        }
    276 //        Cookie[] arrayListAnswer = (Cookie[]) (list.toArray(new Cookie[list.size()]));
    277         Cookie[] mapAnswer = matcher.match(domain,port,path,secure,cookiesMap);
    278
    279 //        if(! (new HashSet(list).equals(new HashSet(Arrays.asList(mapAnswer))))) {
    280 //            System.out.println("discrepancy");
    281 //        }
    282         return mapAnswer;
    283 // END IA/HERITRIX CHANGES
    284     }
    285
    286     /***
    287      * Removes all of {@link Cookie cookies} in this HTTP state
    288      * that have expired according to the current system time.
    289      *
    290      * @see #purgeExpiredCookies(java.util.Date)
    291      *
    292      */
    293     public synchronized boolean purgeExpiredCookies() {
    294         LOG.trace("enter HttpState.purgeExpiredCookies()");
    295         return purgeExpiredCookies(new Date());
    296     }
    297
    298     /***
    299      * Removes all of {@link Cookie cookies} in this HTTP state
    300      * that have expired by the specified {@link java.util.Date date}.
    301      *
    302      * @param date The {@link java.util.Date date} to compare against.
    303      *
    304      * @return true if any cookies were purged.
    305      *
    306      * @see Cookie#isExpired(java.util.Date)
    307      *
    308      * @see #purgeExpiredCookies()
    309      */
    310     public synchronized boolean purgeExpiredCookies(Date date) {
    311         LOG.trace("enter HttpState.purgeExpiredCookies(Date)");
    312 // BEGIN IA/HERITRIX CHANGES
    313 //      PRIOR IMPL & COMPARISON HARNESS LEFT COMMENTED OUT FOR TEMPORARY REFERENCE
    314 //        boolean arrayRemoved = false;
    315 //        Iterator ita = cookiesArrayList.iterator();
    316 //        while (ita.hasNext()) {
    317 //            if (((Cookie) (ita.next())).isExpired(date)) {
    318 //                ita.remove();
    319 //                arrayRemoved = true;
    320 //            }
    321 //        }
    322         boolean removed = false;
    323         Iterator it = cookiesMap.values().iterator();
    324         while (it.hasNext()) {
    325             if (((Cookie) (it.next())).isExpired(date)) {
    326                 it.remove();
    327                 removed = true;
    328             }
    329         }
    330         StoredIterator.close(it);
    331 //        assert removed == arrayRemoved : "discrepancy"
    332 // END IA/HERITRIX CHANGES
    333         return removed;
    334     }
    335
    336
    337     /***
    338      * Returns the current {@link CookiePolicy cookie policy} for this
    339      * HTTP state.
    340      *
    341      * @return The {@link CookiePolicy cookie policy}.
    342      *
    343      * @deprecated Use
    344      *  {@link org.apache.commons.httpclient.params.HttpMethodParams#getCookiePolicy()},
    345      *  {@link HttpMethod#getParams()}.
    346      */
    347
    348     public int getCookiePolicy() {
    349         return this.cookiePolicy;
    350     }
    351
    352
    353     /***
    354      * Defines whether preemptive authentication should be
    355      * attempted.
    356      *
    357      * @param value <tt>true</tt> if preemptive authentication should be
    358      * attempted, <tt>false</tt> otherwise.
    359      *
    360      * @deprecated Use
    361      * {@link org.apache.commons.httpclient.params.HttpClientParams#setAuthenticationPreemptive(boolean)},
    362      * {@link HttpClient#getParams()}.
    363      */
    364
    365     public void setAuthenticationPreemptive(boolean value) {
    366         this.preemptive = value;
    367     }
    368
    369
    370     /***
    371      * Returns <tt>true</tt> if preemptive authentication should be
    372      * attempted, <tt>false</tt> otherwise.
    373      *
    374      * @return boolean flag.
    375      *
    376      * @deprecated Use
    377      * {@link org.apache.commons.httpclient.params.HttpClientParams#isAuthenticationPreemptive()},
    378      * {@link HttpClient#getParams()}.
    379      */
    380
    381     public boolean isAuthenticationPreemptive() {
    382         return this.preemptive;
    383     }
    384
    385
    386     /***
    387      * Sets the current {@link CookiePolicy cookie policy} for this HTTP
    388      * state to one of the following supported policies:
    389      * {@link CookiePolicy#COMPATIBILITY},
    390      * {@link CookiePolicy#NETSCAPE_DRAFT} or
    391      * {@link CookiePolicy#RFC2109}.
    392      *
    393      * @param policy new {@link CookiePolicy cookie policy}
    394      *
    395      * @deprecated
    396      *  Use {@link org.apache.commons.httpclient.params.HttpMethodParams#setCookiePolicy(String)},
    397      *  {@link HttpMethod#getParams()}.
    398      */
    399
    400     public void setCookiePolicy(int policy) {
    401         this.cookiePolicy = policy;
    402     }
    403
    404     /***
    405      * Sets the {@link Credentials credentials} for the given authentication
    406      * realm on the given host. The <code>null</code> realm signifies default
    407      * credentials for the given host, which should be used when no
    408      * {@link Credentials credentials} have been explictly supplied for the
    409      * challenging realm. The <code>null</code> host signifies default
    410      * credentials, which should be used when no {@link Credentials credentials}
    411      * have been explictly supplied for the challenging host. Any previous
    412      * credentials for the given realm on the given host will be overwritten.
    413      *
    414      * @param realm the authentication realm
    415      * @param host the host the realm belongs to
    416      * @param credentials the authentication {@link Credentials credentials}
    417      * for the given realm.
    418      *
    419      * @see #getCredentials(String, String)
    420      * @see #setProxyCredentials(String, String, Credentials)
    421      *
    422      * @deprecated use #setCredentials(AuthScope, Credentials)
    423      */
    424
    425     public synchronized void setCredentials(String realm, String host, Credentials credentials) {
    426         LOG.trace("enter HttpState.setCredentials(String, String, Credentials)");
    427         credMap.put(new AuthScope(host, AuthScope.ANY_PORT, realm, AuthScope.ANY_SCHEME), credentials);
    428     }
    429
    430     /***
    431      * Sets the {@link Credentials credentials} for the given authentication
    432      * scope. Any previous credentials for the given scope will be overwritten.
    433      *
    434      * @param authscope the {@link AuthScope authentication scope}
    435      * @param credentials the authentication {@link Credentials credentials}
    436      * for the given scope.
    437      *
    438      * @see #getCredentials(AuthScope)
    439      * @see #setProxyCredentials(AuthScope, Credentials)
    440      *
    441      * @since 3.0
    442      */
    443     public synchronized void setCredentials(final AuthScope authscope, final Credentials credentials) {
    444         if (authscope == null) {
    445             throw new IllegalArgumentException("Authentication scope may not be null");
    446         }
    447         LOG.trace("enter HttpState.setCredentials(AuthScope, Credentials)");
    448         credMap.put(authscope, credentials);
    449     }
    450
    451     /***
    452      * Find matching {@link Credentials credentials} for the given authentication scope.
    453      *
    454      * @param map the credentials hash map
    455      * @param token the {@link AuthScope authentication scope}
    456      * @return the credentials
    457      *
    458      */
    459     private static Credentials matchCredentials(final HashMap map, final AuthScope authscope) {
    460         // see if we get a direct hit
    461         Credentials creds = (Credentials)map.get(authscope);
    462         if (creds == null) {
    463             // Nope.
    464             // Do a full scan
    465             int bestMatchFactor  = -1;
    466             AuthScope bestMatch  = null;
    467             Iterator items = map.keySet().iterator();
    468             while (items.hasNext()) {
    469                 AuthScope current = (AuthScope)items.next();
    470                 int factor = authscope.match(current);
    471                 if (factor > bestMatchFactor) {
    472                     bestMatchFactor = factor;
    473                     bestMatch = current;
    474                 }
    475             }
    476             if (bestMatch != null) {
    477                 creds = (Credentials)map.get(bestMatch);
    478             }
    479         }
    480         return creds;
    481     }
    482
    483     /***
    484      * Get the {@link Credentials credentials} for the given authentication scope on the
    485      * given host.
    486      *
    487      * If the <i>realm</i> exists on <i>host</i>, return the coresponding credentials.
    488      * If the <i>host</i> exists with a <tt>null</tt> <i>realm</i>, return the corresponding
    489      * credentials.
    490      * If the <i>realm</i> exists with a <tt>null</tt> <i>host</i>, return the
    491      * corresponding credentials.  If the <i>realm</i> does not exist, return
    492      * the default Credentials.  If there are no default credentials, return
    493      * <code>null</code>.
    494      *
    495      * @param realm the authentication realm
    496      * @param host the host the realm is on
    497      * @return the credentials
    498      *
    499      * @see #setCredentials(String, String, Credentials)
    500      *
    501      * @deprecated use #getCredentials(AuthScope)
    502      */
    503
    504     public synchronized Credentials getCredentials(String realm, String host) {
    505         LOG.trace("enter HttpState.getCredentials(String, String");
    506         return matchCredentials(this.credMap,
    507             new AuthScope(host, AuthScope.ANY_PORT, realm, AuthScope.ANY_SCHEME));
    508     }
    509
    510     /***
    511      * Get the {@link Credentials credentials} for the given authentication scope.
    512      *
    513      * @param authscope the {@link AuthScope authentication scope}
    514      * @return the credentials
    515      *
    516      * @see #setCredentials(AuthScope, Credentials)
    517      *
    518      * @since 3.0
    519      */
    520     public synchronized Credentials getCredentials(final AuthScope authscope) {
    521         if (authscope == null) {
    522             throw new IllegalArgumentException("Authentication scope may not be null");
    523         }
    524         LOG.trace("enter HttpState.getCredentials(AuthScope)");
    525         return matchCredentials(this.credMap, authscope);
    526     }
    527
    528     /***
    529      * Sets the {@link Credentials credentials} for the given proxy authentication
    530      * realm on the given proxy host. The <code>null</code> proxy realm signifies
    531      * default credentials for the given proxy host, which should be used when no
    532      * {@link Credentials credentials} have been explictly supplied for the
    533      * challenging proxy realm. The <code>null</code> proxy host signifies default
    534      * credentials, which should be used when no {@link Credentials credentials}
    535      * have been explictly supplied for the challenging proxy host. Any previous
    536      * credentials for the given proxy realm on the given proxy host will be
    537      * overwritten.
    538      *
    539      * @param realm the authentication realm
    540      * @param proxyHost the proxy host
    541      * @param credentials the authentication credentials for the given realm
    542      *
    543      * @see #getProxyCredentials(AuthScope)
    544      * @see #setCredentials(AuthScope, Credentials)
    545      *
    546      * @deprecated use #setProxyCredentials(AuthScope, Credentials)
    547      */
    548     public synchronized void setProxyCredentials(
    549         String realm,
    550         String proxyHost,
    551         Credentials credentials
    552     ) {
    553         LOG.trace("enter HttpState.setProxyCredentials(String, String, Credentials");
    554         proxyCred.put(new AuthScope(proxyHost, AuthScope.ANY_PORT, realm, AuthScope.ANY_SCHEME), credentials);
    555     }
    556
    557     /***
    558      * Sets the {@link Credentials proxy credentials} for the given authentication
    559      * realm. Any previous credentials for the given realm will be overwritten.
    560      *
    561      * @param authscope the {@link AuthScope authentication scope}
    562      * @param credentials the authentication {@link Credentials credentials}
    563      * for the given realm.
    564      *
    565      * @see #getProxyCredentials(AuthScope)
    566      * @see #setCredentials(AuthScope, Credentials)
    567      *
    568      * @since 3.0
    569      */
    570     public synchronized void setProxyCredentials(final AuthScope authscope,
    571         final Credentials credentials)
    572     {
    573         if (authscope == null) {
    574             throw new IllegalArgumentException("Authentication scope may not be null");
    575         }
    576         LOG.trace("enter HttpState.setProxyCredentials(AuthScope, Credentials)");
    577         proxyCred.put(authscope, credentials);
    578     }
    579
    580     /***
    581      * Get the {@link Credentials credentials} for the proxy host with the given
    582      * authentication scope.
    583      *
    584      * If the <i>realm</i> exists on <i>host</i>, return the coresponding credentials.
    585      * If the <i>host</i> exists with a <tt>null</tt> <i>realm</i>, return the corresponding
    586      * credentials.
    587      * If the <i>realm</i> exists with a <tt>null</tt> <i>host</i>, return the
    588      * corresponding credentials.  If the <i>realm</i> does not exist, return
    589      * the default Credentials.  If there are no default credentials, return
    590      * <code>null</code>.
    591      *
    592      * @param realm the authentication realm
    593      * @param proxyHost the proxy host the realm is on
    594      * @return the credentials
    595      * @see #setProxyCredentials(String, String, Credentials)
    596      *
    597      * @deprecated use #getProxyCredentials(AuthScope)
    598      */
    599     public synchronized Credentials getProxyCredentials(String realm, String proxyHost) {
    600        LOG.trace("enter HttpState.getCredentials(String, String");
    601         return matchCredentials(this.proxyCred,
    602             new AuthScope(proxyHost, AuthScope.ANY_PORT, realm, AuthScope.ANY_SCHEME));
    603     }
    604
    605     /***
    606      * Get the {@link Credentials proxy credentials} for the given authentication scope.
    607      *
    608      * @param authscope the {@link AuthScope authentication scope}
    609      * @return the credentials
    610      *
    611      * @see #setProxyCredentials(AuthScope, Credentials)
    612      *
    613      * @since 3.0
    614      */
    615     public synchronized Credentials getProxyCredentials(final AuthScope authscope) {
    616         if (authscope == null) {
    617             throw new IllegalArgumentException("Authentication scope may not be null");
    618         }
    619         LOG.trace("enter HttpState.getProxyCredentials(AuthScope)");
    620         return matchCredentials(this.proxyCred, authscope);
    621     }
    622
    623     /***
    624      * Returns a string representation of this HTTP state.
    625      *
    626      * @return The string representation of the HTTP state.
    627      *
    628      * @see java.lang.Object#toString()
    629      */
    630     public synchronized String toString() {
    631         StringBuffer sbResult = new StringBuffer();
    632
    633         sbResult.append("[");
    634         sbResult.append(getCredentialsStringRepresentation(proxyCred));
    635         sbResult.append(" | ");
    636         sbResult.append(getCredentialsStringRepresentation(credMap));
    637         sbResult.append(" | ");
    638         sbResult.append(getCookiesStringRepresentation(cookiesMap.values())); // <- IA/HERITRIX CHANGE
    639         sbResult.append("]");
    640
    641         String strResult = sbResult.toString();
    642
    643         return strResult;
    644     }
    645
    646     /***
    647      * Returns a string representation of the credentials.
    648      * @param credMap The credentials.
    649      * @return The string representation.
    650      */
    651     private static String getCredentialsStringRepresentation(final Map credMap) {
    652         StringBuffer sbResult = new StringBuffer();
    653         Iterator iter = credMap.keySet().iterator();
    654         while (iter.hasNext()) {
    655             Object key = iter.next();
    656             Credentials cred = (Credentials) credMap.get(key);
    657             if (sbResult.length() > 0) {
    658                 sbResult.append(", ");
    659             }
    660             sbResult.append(key);
    661             sbResult.append("#");
    662             sbResult.append(cred.toString());
    663         }
    664         return sbResult.toString();
    665     }
    666
    667     /***
    668      * Returns a string representation of the cookies.
    669      * @param cookies The cookies
    670      * @return The string representation.
    671      */
    672     private static String getCookiesStringRepresentation(final Collection cookies) { // <- IA/HERITRIX CHANGE
    673         StringBuffer sbResult = new StringBuffer();
    674         Iterator iter = cookies.iterator();
    675         while (iter.hasNext()) {
    676             Cookie ck = (Cookie) iter.next();
    677             if (sbResult.length() > 0) {
    678                 sbResult.append("#");
    679             }
    680             sbResult.append(ck.toExternalForm());
    681         }
    682         return sbResult.toString();
    683     }
    684
    685     /***
    686      * Clears all credentials.
    687      */
    688     public void clearCredentials() {
    689         this.credMap.clear();
    690     }
    691
    692     /***
    693      * Clears all proxy credentials.
    694      */
    695     public void clearProxyCredentials() {
    696         this.proxyCred.clear();
    697     }
    698
    699     /***
    700      * Clears all cookies.
    701      */
    702     public void clearCookies() {
    703 // BEGIN IA/HERITRIX CHANGES
    704 //        this.cookiesArrayList.clear();
    705         this.cookiesMap.clear();
    706 // END IA/HERITRIX CHANGES
    707     }
    708
    709     /***
    710      * Clears the state information (all cookies, credentials and proxy credentials).
    711      */
    712     public void clear() {
    713         clearCookies();
    714         clearCredentials();
    715         clearProxyCredentials();
    716     }
    717 }