View Javadoc

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 }