KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > gargoylesoftware > htmlunit > WebClient


1 /*
2  * Copyright (c) 2002, 2005 Gargoyle Software Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12  * 3. The end-user documentation included with the redistribution, if any, must
13  * include the following acknowledgment:
14  *
15  * "This product includes software developed by Gargoyle Software Inc.
16  * (http://www.GargoyleSoftware.com/)."
17  *
18  * Alternately, this acknowledgment may appear in the software itself, if
19  * and wherever such third-party acknowledgments normally appear.
20  * 4. The name "Gargoyle Software" must not be used to endorse or promote
21  * products derived from this software without prior written permission.
22  * For written permission, please contact info@GargoyleSoftware.com.
23  * 5. Products derived from this software may not be called "HtmlUnit", nor may
24  * "HtmlUnit" appear in their name, without prior written permission of
25  * Gargoyle Software Inc.
26  *
27  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
28  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
29  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
30  * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
33  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
36  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  */

38 package com.gargoylesoftware.htmlunit;
39
40 import java.io.BufferedInputStream JavaDoc;
41 import java.io.ByteArrayOutputStream JavaDoc;
42 import java.io.File JavaDoc;
43 import java.io.FileInputStream JavaDoc;
44 import java.io.IOException JavaDoc;
45 import java.io.InputStream JavaDoc;
46 import java.io.OutputStreamWriter JavaDoc;
47 import java.lang.reflect.Constructor JavaDoc;
48 import java.net.MalformedURLException JavaDoc;
49 import java.net.URL JavaDoc;
50 import java.net.URLConnection JavaDoc;
51 import java.net.URLStreamHandler JavaDoc;
52 import java.util.ArrayList JavaDoc;
53 import java.util.BitSet JavaDoc;
54 import java.util.Collections JavaDoc;
55 import java.util.HashMap JavaDoc;
56 import java.util.HashSet JavaDoc;
57 import java.util.Iterator JavaDoc;
58 import java.util.List JavaDoc;
59 import java.util.Map JavaDoc;
60 import java.util.Set JavaDoc;
61 import java.util.Stack JavaDoc;
62 import java.util.StringTokenizer JavaDoc;
63
64 import org.org.apache.commons.httpclient.URI;
65 import org.org.apache.commons.httpclient.URIException;
66 import org.org.apache.commons.httpclient.auth.CredentialsProvider;
67 import org.org.apache.commons.httpclient.util.URIUtil;
68 import org.apache.commons.io.FileUtils;
69 import org.apache.commons.io.IOUtils;
70 import org.apache.commons.logging.Log;
71 import org.apache.commons.logging.LogFactory;
72
73 import com.gargoylesoftware.htmlunit.html.BaseFrame;
74 import com.gargoylesoftware.htmlunit.html.FocusableElement;
75 import com.gargoylesoftware.htmlunit.html.HTMLParser;
76 import com.gargoylesoftware.htmlunit.html.HTMLParserListener;
77 import com.gargoylesoftware.htmlunit.html.HtmlPage;
78 import com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine;
79
80 /**
81  * An object that represents a web browser
82  *
83  * @version $Revision: 100 $
84  * @author <a HREF="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
85  * @author <a HREF="mailto:gudujarlson@sf.net">Mike J. Bresnahan</a>
86  * @author Dominique Broeglin
87  * @author Noboru Sinohara
88  * @author <a HREF="mailto:chen_jun@users.sourceforge.net"> Chen Jun</a>
89  * @author David K. Taylor
90  * @author <a HREF="mailto:cse@dynabean.de">Christian Sell</a>
91  * @author <a HREF="mailto:bcurren@esomnie.com">Ben Curren</a>
92  * @author Marc Guillemot
93  * @author Chris Erskine
94  * @author Daniel Gredler
95  * @author Sergey Gorelkin
96  * @author Hans Donner
97  */

98 public class WebClient {
99
100     private WebConnection webConnection_;
101     private boolean printContentOnFailingStatusCode_ = true;
102     private boolean throwExceptionOnFailingStatusCode_ = true;
103     private CredentialsProvider credentialsProvider_ = new DefaultCredentialsProvider();
104     private final String JavaDoc proxyHost_;
105     private final int proxyPort_;
106     private ScriptEngine scriptEngine_;
107     private boolean javaScriptEnabled_ = true;
108     private String JavaDoc homePage_;
109     private FocusableElement elementWithFocus_;
110     private final Map JavaDoc requestHeaders_ = Collections.synchronizedMap(new HashMap JavaDoc(89));
111
112     private AlertHandler alertHandler_;
113     private ConfirmHandler confirmHandler_;
114     private PromptHandler promptHandler_;
115     private StatusHandler statusHandler_;
116
117     private BrowserVersion browserVersion_ = BrowserVersion.getDefault();
118     private boolean isRedirectEnabled_ = true;
119     private PageCreator pageCreator_ = new DefaultPageCreator();
120
121     private final Set JavaDoc webWindowListeners_ = new HashSet JavaDoc(5);
122     private final List JavaDoc webWindows_ = Collections.synchronizedList(new ArrayList JavaDoc());
123
124     private WebWindow currentWindow_ = new TopLevelWindow("", this);
125     private Stack JavaDoc firstWindowStack_ = new Stack JavaDoc();
126     private int timeout_ = 0;
127     private HTMLParserListener htmlParserListener_;
128
129     private static URLStreamHandler JavaDoc JavaScriptUrlStreamHandler_
130         = new com.gargoylesoftware.htmlunit.protocol.javascript.Handler();
131     private static URLStreamHandler JavaDoc AboutUrlStreamHandler_
132         = new com.gargoylesoftware.htmlunit.protocol.about.Handler();
133
134     /**
135      * URL for "about:blank"
136      */

137     public static final URL JavaDoc URL_ABOUT_BLANK;
138     static {
139         URL JavaDoc tmpUrl = null;
140         try {
141             tmpUrl = new URL JavaDoc(null, "about:blank", AboutUrlStreamHandler_);
142         }
143         catch (final MalformedURLException JavaDoc e) {
144             // impossible
145
e.printStackTrace();
146         }
147         URL_ABOUT_BLANK = tmpUrl;
148     }
149
150     //singleton WebResponse for "about:blank"
151
private static final WebResponse WEB_RESPONSE_FOR_ABOUT_BLANK = new WebResponse() {
152         public int getStatusCode() {
153             return 200;
154         }
155         public String JavaDoc getStatusMessage() {
156             return "OK";
157         }
158         public String JavaDoc getContentType() {
159             return "text/html";
160         }
161         public String JavaDoc getContentAsString() {
162             return "";
163         }
164         public InputStream JavaDoc getContentAsStream() {
165             return TextUtil.toInputStream("");
166         }
167         public URL JavaDoc getUrl() {
168             return URL_ABOUT_BLANK;
169         }
170         public List JavaDoc getResponseHeaders() {
171             return Collections.EMPTY_LIST;
172         }
173         public String JavaDoc getResponseHeaderValue(final String JavaDoc key) {
174             return "";
175         }
176         public long getLoadTimeInMilliSeconds() {
177             return 0;
178         }
179         public byte[] getResponseBody() {
180             return "".getBytes();
181         }
182         public String JavaDoc getContentCharSet() {
183             return "ISO-8859-1";
184         }
185     };
186
187     private ScriptPreProcessor scriptPreProcessor_;
188     private Map JavaDoc activeXObjectMap_ = Collections.EMPTY_MAP;
189     private RefreshHandler refreshHandler_ = new ImmediateRefreshHandler();
190     private boolean throwExceptionOnScriptError_ = true;
191
192
193     /**
194      * Create an instance using {@link BrowserVersion#FULL_FEATURED_BROWSER}
195      */

196     public WebClient() {
197         this( BrowserVersion.FULL_FEATURED_BROWSER );
198     }
199
200
201     /**
202      * Create an instance using the specified {@link BrowserVersion}
203      * @param browserVersion The browser version to simulate
204      */

205     public WebClient( final BrowserVersion browserVersion ) {
206         Assert.notNull("browserVersion", browserVersion);
207
208         homePage_ = "http://www.gargoylesoftware.com/";
209         browserVersion_ = browserVersion;
210         proxyHost_ = null;
211         proxyPort_ = 0;
212         try {
213             scriptEngine_ = createJavaScriptEngineIfPossible( this );
214         }
215         catch( final NoClassDefFoundError JavaDoc e ) {
216             scriptEngine_ = null;
217         }
218     }
219
220
221     /**
222      * Create an instance that will use the specified {@link BrowserVersion} and proxy server
223      * @param browserVersion The browser version to simulate
224      * @param proxyHost The server that will act as proxy
225      * @param proxyPort The port to use on the proxy server
226      */

227     public WebClient( final BrowserVersion browserVersion, final String JavaDoc proxyHost, final int proxyPort ) {
228         Assert.notNull("browserVersion", browserVersion);
229         Assert.notNull( "proxyHost", proxyHost );
230
231         homePage_ = "http://www.gargoylesoftware.com/";
232         browserVersion_ = browserVersion;
233         proxyHost_ = proxyHost;
234         proxyPort_ = proxyPort;
235         try {
236             scriptEngine_ = createJavaScriptEngineIfPossible( this );
237         }
238         catch( final NoClassDefFoundError JavaDoc e ) {
239             scriptEngine_ = null;
240         }
241     }
242
243
244     /**
245      * Create a javascript engine if possible.
246      *
247      * @param webClient The webclient that we are creating the script engine for.
248      * @return A javascript engine or null if one could not be created.
249      */

250     public static JavaScriptEngine createJavaScriptEngineIfPossible( final WebClient webClient ) {
251         try {
252             Class.forName( "org.mozilla.javascript.Context" );
253             return new JavaScriptEngine( webClient );
254         }
255         catch( final ClassNotFoundException JavaDoc e ) {
256             return null;
257         }
258         catch( final NoClassDefFoundError JavaDoc e ) {
259             return null;
260         }
261     }
262
263
264     /**
265      * <p>Return the object that will resolve all url requests<p>
266      * <p>INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK</p>
267      * @return The connection that will be used.
268      */

269     public synchronized WebConnection getWebConnection() {
270         if( webConnection_ == null ) {
271             if( proxyHost_ == null ) {
272                 webConnection_ = new HttpWebConnection( this );
273             }
274             else {
275                 webConnection_ = new HttpWebConnection( this, proxyHost_, proxyPort_ );
276             }
277         }
278
279         return webConnection_;
280     }
281
282
283     /**
284      * Set the object that will resolve all url requests <p />
285      *
286      * This method is intended for unit testing HtmlUnit itself. It is not expected
287      * to change but you shouldn't need to call it during normal use of HtmlUnit.
288      *
289      * @param webConnection The new web connection
290      */

291     public void setWebConnection( final WebConnection webConnection ) {
292         Assert.notNull( "webConnection", webConnection );
293         webConnection_ = webConnection;
294     }
295
296     /**
297      * Send a request to a server and return a Page that represents the
298      * response from the server. This page will be used to populate this frame.<p>
299      *
300      * The type of Page will depend on the content type of the http response. <p />
301      *
302      * <table>
303      * <tr>
304      * <th>Content type</th>
305      * <th>Type of page</th>
306      * </tr>
307      * <tr>
308      * <td>"text/html"</td>
309      * <td>{@link com.gargoylesoftware.htmlunit.html.HtmlPage}</td>
310      * </tr>
311      * <tr>
312      * <td>"text/xhtml"</td>
313      * <td>{@link com.gargoylesoftware.htmlunit.html.HtmlPage}</td>
314      * </tr>
315      * <tr>
316      * <td>"application/xhtml+xml"</td>
317      * <td>{@link com.gargoylesoftware.htmlunit.html.HtmlPage} for now, in the
318      * future it will be XML validated as well
319      * </td>
320      * </tr>
321      * <tr>
322      * <td>"text/*"</td>
323      * <td>{@link com.gargoylesoftware.htmlunit.TextPage}</td>
324      * </tr>
325      * <tr>
326      * <td>Anything else</td>
327      * <td>{@link com.gargoylesoftware.htmlunit.UnexpectedPage}</td>
328      * </tr>
329      * </table>
330      *
331      *
332      * @param webWindow The WebWindow to load this request into
333      * @param parameters Parameter object for the web request
334      * @return See above
335      * @exception IOException If an IO error occurs
336      * @exception FailingHttpStatusCodeException If the server returns a
337      * failing status code AND the property
338      * {@link #setThrowExceptionOnFailingStatusCode(boolean)} is set to true
339      *
340      * @see WebRequestSettings
341      */

342     public Page getPage( final WebWindow webWindow, final WebRequestSettings parameters )
343         throws IOException JavaDoc, FailingHttpStatusCodeException {
344
345         getLog().debug("Get page for window named '" + webWindow.getName() + "', using " + parameters);
346
347         final String JavaDoc protocol = parameters.getURL().getProtocol();
348         final WebResponse webResponse;
349         if( protocol.equals("javascript") ) {
350             webResponse = makeWebResponseForJavaScriptUrl(webWindow, parameters.getURL());
351         }
352         else if (protocol.equals("about")) {
353             webResponse = makeWebResponseForAboutUrl(parameters.getURL());
354         }
355         else if (protocol.equals("file")) {
356             webResponse = makeWebResponseForFileUrl(parameters.getURL());
357         }
358         else {
359             webResponse = loadWebResponse(
360                     parameters.getURL(),
361                     parameters.getEncodingType(),
362                     parameters.getSubmitMethod(),
363                     parameters.getRequestParameters());
364         }
365         final String JavaDoc contentType = webResponse.getContentType();
366         final int statusCode = webResponse.getStatusCode();
367
368         final boolean wasResponseSuccessful = ( statusCode >= 200 && statusCode < 300 );
369
370         if( printContentOnFailingStatusCode_ && !wasResponseSuccessful) {
371             getLog().info( "statusCode=[" + statusCode
372                 + "] contentType=[" + contentType + "]" );
373             getLog().info( webResponse.getContentAsString() );
374         }
375
376         loadWebResponseInto(webResponse, webWindow);
377
378         if( getThrowExceptionOnFailingStatusCode() && !wasResponseSuccessful) {
379             throw new FailingHttpStatusCodeException( statusCode, webResponse.getStatusMessage() );
380         }
381
382         return webWindow.getEnclosedPage();
383     }
384
385     /**
386      * <p>For internal use only</p>
387      * <p>Open a new web window and populate it with a page loaded by
388      * {@link #getPage(WebWindow,WebRequestSettings)}</p>
389      *
390      * @param opener The web window that initiated the request.
391      * @param target The name of the window to be opened. This is the name that would
392      * be passed into the javascript open() method.
393      * @param params Any parameters
394      * @return The new page.
395      * @exception FailingHttpStatusCodeException If the server returns a
396      * failing status code AND the property
397      * {@link #setThrowExceptionOnFailingStatusCode(boolean)} is set to true.
398      * @exception IOException If an IO problem occurs.
399      */

400     public Page getPage(final WebWindow opener, final String JavaDoc target, final WebRequestSettings params)
401         throws FailingHttpStatusCodeException, IOException JavaDoc {
402         return getPage(openTargetWindow(opener, target, "_self"), params);
403     }
404
405     /**
406      * Convenience method to load a URL into the current WebWindow
407      * @param url The url of the new content.
408      * @return The new page.
409      * @throws FailingHttpStatusCodeException If the server returns a
410      * failing status code AND the property
411      * {@link #setThrowExceptionOnFailingStatusCode(boolean)} is set to true.
412      * @throws IOException If an IO problem occurs.
413      */

414     public Page getPage(final URL JavaDoc url) throws IOException JavaDoc, FailingHttpStatusCodeException {
415         return getPage(getCurrentWindow(), new WebRequestSettings(url));
416     }
417
418     /**
419      * Convenience method to load a web request into the current WebWindow
420      * @param request The request parameters
421      * @return The new page.
422      * @exception FailingHttpStatusCodeException If the server returns a
423      * failing status code AND the property
424      * {@link #setThrowExceptionOnFailingStatusCode(boolean)} is set to true.
425      * @exception IOException If an IO problem occurs.
426      * @see #getPage(WebWindow,WebRequestSettings)
427      */

428     public Page getPage(final WebRequestSettings request) throws IOException JavaDoc,
429             FailingHttpStatusCodeException {
430         return getPage(getCurrentWindow(), request);
431     }
432
433
434     /**
435      * Send a request to a server and return a Page that represents the
436      * response from the server. This is the same as calling {@link
437      * #getPage(WebWindow,URL,SubmitMethod,List)} with the current window.
438      *
439      * @param url The url of the server
440      * @param method The submit method to use when sending the request to the server
441      * @param parameters A list of {@link KeyValuePair}'s that are the parameters
442      * to the request
443      * @return See above
444      * @exception IOException If an IO error occurs
445      * @exception FailingHttpStatusCodeException If the server returns a
446      * failing status code AND the property
447      * "throwExceptionOnFailingStatusCode" is set to true (see {@link
448      * #setThrowExceptionOnFailingStatusCode(boolean)})
449      * @deprecated Use {@link #getPage(WebRequestSettings)}
450      */

451     public Page getPage(
452             final URL JavaDoc url,
453             final SubmitMethod method,
454             final List JavaDoc parameters )
455         throws
456             IOException JavaDoc,
457             FailingHttpStatusCodeException {
458
459         return getPage( getCurrentWindow(), url, method, parameters );
460     }
461
462
463     /**
464      * Return a page.
465      *
466      * @param webWindow The window that the new page will be loaded into.
467      * @param url The url of the server
468      * @param method The submit method. Ie Submit.GET or SubmitMethod.POST
469      * @param parameters A list of {@link
470      * com.gargoylesoftware.htmlunit.KeyValuePair KeyValuePair}'s that
471      * contain the parameters to send to the server
472      * @return The page that was loaded.
473      * @exception IOException If an IO error occurs
474      * @exception FailingHttpStatusCodeException If the server returns a
475      * failing status code
476      * @see #setThrowExceptionOnFailingStatusCode(boolean)
477      * @see FailingHttpStatusCodeException
478      * @deprecated Use {@link #getPage(WebWindow, WebRequestSettings)}
479      */

480     public Page getPage(
481             final WebWindow webWindow,
482             final URL JavaDoc url,
483             final SubmitMethod method,
484             final List JavaDoc parameters )
485         throws
486             IOException JavaDoc,
487             FailingHttpStatusCodeException {
488         final WebRequestSettings settings = new WebRequestSettings(url, method);
489         settings.setRequestParameters(parameters);
490         return getPage(webWindow, settings);
491     }
492
493
494     /**
495      * Return a page.
496      *
497      * @param webWindow The window from which the load is initiated. If target
498      * is not specified then this will also be the window into which the new page
499      * is loaded.
500      * @param url The url of the server
501      * @param target The name of the window where the page will be loaded.
502      * @param method The submit method. Ie Submit.GET or SubmitMethod.POST
503      * @param parameters A list of {@link
504      * com.gargoylesoftware.htmlunit.KeyValuePair KeyValuePair}'s that
505      * contain the parameters to send to the server
506      * @return The page that was loaded.
507      * @exception IOException If an IO error occurs
508      * @exception FailingHttpStatusCodeException If the server returns a
509      * failing status code
510      * @see #setThrowExceptionOnFailingStatusCode(boolean)
511      * @see FailingHttpStatusCodeException
512      * @deprecated Use {@link #getPage(WebWindow, WebRequestSettings)}
513      */

514     public Page getPage(
515             final WebWindow webWindow,
516             final URL JavaDoc url,
517             final String JavaDoc target,
518             final SubmitMethod method,
519             final List JavaDoc parameters )
520         throws
521             IOException JavaDoc,
522             FailingHttpStatusCodeException {
523         return getPage(openTargetWindow( webWindow, target, "_self" ), url,
524             method, parameters, getThrowExceptionOnFailingStatusCode());
525     }
526
527
528     /**
529      * Return a page.
530      *
531      * @param webWindow The window that the new page will be loaded into.
532      * @param url The url of the server
533      * @param encType Encoding type of the form when done as a POST
534      * @param method The submit method. Ie Submit.GET or SubmitMethod.POST
535      * @param parameters A list of {@link
536      * com.gargoylesoftware.htmlunit.KeyValuePair KeyValuePair}'s that
537      * contain the parameters to send to the server
538      * @return The page that was loaded.
539      * @exception IOException If an IO error occurs
540      * @exception FailingHttpStatusCodeException If the server returns a
541      * failing status code AND the property
542      * "throwExceptionOnFailingStatusCode" is set to true (see {@link
543      * #setThrowExceptionOnFailingStatusCode(boolean)})
544      * @deprecated Use {@link #getPage(WebWindow, WebRequestSettings)}
545      */

546     public Page getPage(
547             final WebWindow webWindow,
548             final URL JavaDoc url,
549             final FormEncodingType encType,
550             final SubmitMethod method,
551             final List JavaDoc parameters )
552         throws
553             IOException JavaDoc,
554             FailingHttpStatusCodeException {
555         return getPage(webWindow, url, encType, method, parameters, getThrowExceptionOnFailingStatusCode());
556     }
557
558
559     /**
560      * Return a page.
561      *
562      * @param webWindow The window that the new page will be loaded into.
563      * @param url The url of the server
564      * @param target The name of the window where the page will be loaded.
565      * @param encType Encoding type of the form when done as a POST
566      * @param method The submit method. Ie Submit.GET or SubmitMethod.POST
567      * @param parameters A list of {@link
568      * com.gargoylesoftware.htmlunit.KeyValuePair KeyValuePair}'s that
569      * contain the parameters to send to the server
570      * @return The page that was loaded.
571      * @exception IOException If an IO error occurs
572      * @exception FailingHttpStatusCodeException If the server returns a
573      * failing status code
574      * @see #setThrowExceptionOnFailingStatusCode(boolean)
575      * @see FailingHttpStatusCodeException
576      * @deprecated Use {@link #getPage(WebWindow, WebRequestSettings)}
577      */

578     public Page getPage(
579             final WebWindow webWindow,
580             final URL JavaDoc url,
581             final String JavaDoc target,
582             final FormEncodingType encType,
583             final SubmitMethod method,
584             final List JavaDoc parameters )
585         throws
586             IOException JavaDoc,
587             FailingHttpStatusCodeException {
588         return getPage(openTargetWindow( webWindow, target, "_self" ),
589             url, encType, method, parameters,
590             getThrowExceptionOnFailingStatusCode());
591     }
592
593
594     /**
595      * Return a page.
596      *
597      * @param webWindow The window that the new page will be loaded into.
598      * @param url The url of the server
599      * @param method The submit method. Ie Submit.GET or SubmitMethod.POST
600      * @param parameters A list of {@link
601      * com.gargoylesoftware.htmlunit.KeyValuePair KeyValuePair}'s that
602      * contain the parameters to send to the server
603      * @param throwExceptionOnFailingStatusCode true if this method should throw
604      * an exception whenever a failing status code is received.
605      * @return The page that was loaded.
606      * @exception IOException If an IO error occurs
607      * @exception FailingHttpStatusCodeException If the server returns a
608      * failing status code AND the variable
609      * "throwExceptionOnFailingStatusCode" is set to true
610      * @see #setThrowExceptionOnFailingStatusCode(boolean)
611      * @see FailingHttpStatusCodeException
612      * @deprecated Use {@link #getPage(WebWindow, WebRequestSettings)}
613      */

614     public Page getPage(
615             final WebWindow webWindow,
616             final URL JavaDoc url,
617             final SubmitMethod method,
618             final List JavaDoc parameters,
619             final boolean throwExceptionOnFailingStatusCode )
620         throws
621             IOException JavaDoc,
622             FailingHttpStatusCodeException {
623         final WebRequestSettings settings = new WebRequestSettings(url);
624         settings.setSubmitMethod(method);
625         settings.setRequestParameters(parameters);
626         try {
627             return getPage(webWindow, settings);
628         }
629         catch (final FailingHttpStatusCodeException e) {
630             if (throwExceptionOnFailingStatusCode) {
631                 throw e;
632             }
633             else {
634                 return webWindow.getEnclosedPage();
635             }
636         }
637     }
638
639     /**
640      * @param webWindow The window that the new page will be loaded into.
641      * @param url The url of the server
642      * @param encType Encoding type of the form when done as a POST
643      * @param method The submit method. Ie Submit.GET or SubmitMethod.POST
644      * @param parameters A list of {@link
645      * com.gargoylesoftware.htmlunit.KeyValuePair KeyValuePair}'s that
646      * contain the parameters to send to the server
647      * @param throwExceptionOnFailingStatusCode true if this method should throw
648      * an exception whenever a failing status code is received.
649      * @return The page that was loaded.
650      * @exception IOException If an IO error occurs
651      * @exception FailingHttpStatusCodeException If the server returns a
652      * failing status code AND the variable
653      * "throwExceptionOnFailingStatusCode" is set to true
654      * @see #setThrowExceptionOnFailingStatusCode(boolean)
655      * @see FailingHttpStatusCodeException
656      * @deprecated Use {@link #getPage(WebWindow, WebRequestSettings)}
657      */

658     public Page getPage(
659             final WebWindow webWindow,
660             final URL JavaDoc url,
661             final FormEncodingType encType,
662             final SubmitMethod method,
663             final List JavaDoc parameters,
664             final boolean throwExceptionOnFailingStatusCode )
665         throws
666             IOException JavaDoc,
667             FailingHttpStatusCodeException {
668         final WebRequestSettings params = new WebRequestSettings(url, method);
669         params.setEncodingType(encType);
670         params.setRequestParameters(parameters);
671
672         try {
673             return getPage(webWindow, params);
674         }
675         catch (final FailingHttpStatusCodeException e){
676             if (throwExceptionOnFailingStatusCode){
677                 throw e;
678             }
679             else {
680                 return webWindow.getEnclosedPage();
681             }
682         }
683     }
684
685     /**
686      * Use the specified WebResponse to create a Page object which will then
687      * get inserted into the WebWindow. All initialization and event notification
688      * will be handled here.
689      *
690      * @param webResponse The response that will be used to create the new page.
691      * @param webWindow The window that the new page will be placed within.
692      * @throws IOException If an IO error occurs.
693      * @return The newly created page.
694      */

695     public Page loadWebResponseInto(
696             final WebResponse webResponse, final WebWindow webWindow )
697         throws
698             IOException JavaDoc {
699
700         Assert.notNull("webResponse", webResponse);
701         Assert.notNull("webWindow", webWindow);
702
703         final Page oldPage = webWindow.getEnclosedPage();
704         if (oldPage != null) {
705             // Remove the old windows before create new ones.
706
oldPage.cleanUp();
707         }
708
709         final Page newPage = pageCreator_.createPage( webResponse, webWindow );
710
711         if (! firstWindowStack_.empty() && firstWindowStack_.peek() == null) {
712             firstWindowStack_.pop();
713             firstWindowStack_.push(webWindow);
714         }
715
716         newPage.initialize();
717
718         fireWindowContentChanged( new WebWindowEvent(webWindow, WebWindowEvent.CHANGE, oldPage, newPage) );
719         return newPage;
720     }
721
722
723     /**
724      * Specify whether or not the content of the resulting document will be
725      * printed to the console in the event of a failing response code.
726      * Successful response codes are in the range 200-299. The default is true.
727      *
728      * @param enabled True to enable this feature
729      */

730     public void setPrintContentOnFailingStatusCode( final boolean enabled ) {
731         printContentOnFailingStatusCode_ = enabled;
732     }
733
734
735     /**
736      * Return true if the content of the resulting document will be printed to
737      * the console in the event of a failing response code.
738      *
739      * @return See above
740      * @see #setPrintContentOnFailingStatusCode
741      */

742     public boolean getPrintContentOnFailingStatusCode() {
743         return printContentOnFailingStatusCode_;
744     }
745
746
747     /**
748      * Specify whether or not an exception will be thrown in the event of a
749      * failing status code. Successful status codes are in the range 200-299.
750      * The default is true.
751      *
752      * @param enabled True to enable this feature
753      */

754     public void setThrowExceptionOnFailingStatusCode( final boolean enabled ) {
755         throwExceptionOnFailingStatusCode_ = enabled;
756     }
757
758
759     /**
760      * Return true if an exception will be thrown in the event of a failing
761      * response code.
762      *
763      * @return See above
764      * @see #setThrowExceptionOnFailingStatusCode
765      */

766     public boolean getThrowExceptionOnFailingStatusCode() {
767         return throwExceptionOnFailingStatusCode_;
768     }
769
770
771     /**
772      * Set a header which will be sent up on EVERY request from this client.
773      *
774      * @param name The name of the header
775      * @param value The value of the header
776      */

777     public void addRequestHeader( final String JavaDoc name, final String JavaDoc value ) {
778         requestHeaders_.put( name, value );
779     }
780
781
782     /**
783      * Remove a header
784      *
785      * @param name Name of the header
786      * @see #addRequestHeader
787      */

788     public void removeRequestHeader( final String JavaDoc name ) {
789         requestHeaders_.remove( name );
790     }
791
792
793     /**
794      * Sets the credentials provider that will provide authentication information when
795      * trying to access protected information on a web server. This information is
796      * required when the server is using Basic HTTP authentication, NTLM authentication,
797      * or Digest authentication.
798      * @param credentialsProvider The new credentials provider to use to authenticate.
799      */

800     public void setCredentialsProvider( final CredentialsProvider credentialsProvider ) {
801         Assert.notNull( "credentialsProvider", credentialsProvider );
802         credentialsProvider_ = credentialsProvider;
803     }
804
805
806     /**
807      * Returns the credentials provider for this client instance. By default, this
808      * method returns an instance of {@link DefaultCredentialsProvider}.
809      * @return The credentials provider for this client instance.
810      */

811     public CredentialsProvider getCredentialsProvider() {
812         return credentialsProvider_;
813     }
814
815
816     /**
817      * Throw an exception with the specified message. If junit is found in the
818      * classpath then a junit.framework.AssertionFailedError will be thrown
819      * (the same behaviour as calling fail() in junit). If junit is not found
820      * then an IllegalStateException will be thrown instead of the
821      * AssertionFailedError. <p>
822      *
823      * Override this to provide custom behaviour.
824      *
825      * @param message The failure message
826      */

827     public void assertionFailed( final String JavaDoc message ) {
828         try {
829             final Class JavaDoc clazz = junit.framework.AssertionFailedError.class;
830             final Constructor JavaDoc constructor = clazz.getConstructor( new Class JavaDoc[]{String JavaDoc.class} );
831             final Error JavaDoc error = ( Error JavaDoc )constructor.newInstance( new Object JavaDoc[]{message} );
832             throw error;
833         }
834         catch( final Exception JavaDoc e ) {
835             throw new IllegalStateException JavaDoc( message );
836         }
837 <