Source Code Cross Referenced for HttpMethodBase.java in  » Net » Apache-common-HttpClient » org » apache » commons » httpclient » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » Apache common HttpClient » org.apache.commons.httpclient 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v 1.222 2005/01/14 21:16:40 olegk Exp $
0003:         * $Revision: 539441 $
0004:         * $Date: 2007-05-18 14:56:55 +0200 (Fri, 18 May 2007) $
0005:         *
0006:         * ====================================================================
0007:         *
0008:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0009:         *  contributor license agreements.  See the NOTICE file distributed with
0010:         *  this work for additional information regarding copyright ownership.
0011:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0012:         *  (the "License"); you may not use this file except in compliance with
0013:         *  the License.  You may obtain a copy of the License at
0014:         *
0015:         *      http://www.apache.org/licenses/LICENSE-2.0
0016:         *
0017:         *  Unless required by applicable law or agreed to in writing, software
0018:         *  distributed under the License is distributed on an "AS IS" BASIS,
0019:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0020:         *  See the License for the specific language governing permissions and
0021:         *  limitations under the License.
0022:         * ====================================================================
0023:         *
0024:         * This software consists of voluntary contributions made by many
0025:         * individuals on behalf of the Apache Software Foundation.  For more
0026:         * information on the Apache Software Foundation, please see
0027:         * <http://www.apache.org/>.
0028:         *
0029:         */
0030:
0031:        package org.apache.commons.httpclient;
0032:
0033:        import java.io.ByteArrayInputStream;
0034:        import java.io.ByteArrayOutputStream;
0035:        import java.io.IOException;
0036:        import java.io.InputStream;
0037:        import java.io.InterruptedIOException;
0038:        import java.util.Collection;
0039:
0040:        import org.apache.commons.httpclient.auth.AuthState;
0041:        import org.apache.commons.httpclient.cookie.CookiePolicy;
0042:        import org.apache.commons.httpclient.cookie.CookieSpec;
0043:        import org.apache.commons.httpclient.cookie.CookieVersionSupport;
0044:        import org.apache.commons.httpclient.cookie.MalformedCookieException;
0045:        import org.apache.commons.httpclient.params.HttpMethodParams;
0046:        import org.apache.commons.httpclient.protocol.Protocol;
0047:        import org.apache.commons.httpclient.util.EncodingUtil;
0048:        import org.apache.commons.httpclient.util.ExceptionUtil;
0049:        import org.apache.commons.logging.Log;
0050:        import org.apache.commons.logging.LogFactory;
0051:
0052:        /**
0053:         * An abstract base implementation of HttpMethod.
0054:         * <p>
0055:         * At minimum, subclasses will need to override:
0056:         * <ul>
0057:         *   <li>{@link #getName} to return the approriate name for this method
0058:         *   </li>
0059:         * </ul>
0060:         * </p>
0061:         *
0062:         * <p>
0063:         * When a method requires additional request headers, subclasses will typically
0064:         * want to override:
0065:         * <ul>
0066:         *   <li>{@link #addRequestHeaders addRequestHeaders(HttpState,HttpConnection)}
0067:         *      to write those headers
0068:         *   </li>
0069:         * </ul>
0070:         * </p>
0071:         *
0072:         * <p>
0073:         * When a method expects specific response headers, subclasses may want to
0074:         * override:
0075:         * <ul>
0076:         *   <li>{@link #processResponseHeaders processResponseHeaders(HttpState,HttpConnection)}
0077:         *     to handle those headers
0078:         *   </li>
0079:         * </ul>
0080:         * </p>
0081:         *
0082:         *
0083:         * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
0084:         * @author Rodney Waldhoff
0085:         * @author Sean C. Sullivan
0086:         * @author <a href="mailto:dion@apache.org">dIon Gillard</a>
0087:         * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
0088:         * @author <a href="mailto:dims@apache.org">Davanum Srinivas</a>
0089:         * @author Ortwin Glueck
0090:         * @author Eric Johnson
0091:         * @author Michael Becke
0092:         * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
0093:         * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
0094:         * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
0095:         * @author Christian Kohlschuetter
0096:         *
0097:         * @version $Revision: 539441 $ $Date: 2007-05-18 14:56:55 +0200 (Fri, 18 May 2007) $
0098:         */
0099:        public abstract class HttpMethodBase implements  HttpMethod {
0100:
0101:            // -------------------------------------------------------------- Constants
0102:
0103:            /** Log object for this class. */
0104:            private static final Log LOG = LogFactory
0105:                    .getLog(HttpMethodBase.class);
0106:
0107:            // ----------------------------------------------------- Instance variables 
0108:
0109:            /** Request headers, if any. */
0110:            private HeaderGroup requestHeaders = new HeaderGroup();
0111:
0112:            /** The Status-Line from the response. */
0113:            protected StatusLine statusLine = null;
0114:
0115:            /** Response headers, if any. */
0116:            private HeaderGroup responseHeaders = new HeaderGroup();
0117:
0118:            /** Response trailer headers, if any. */
0119:            private HeaderGroup responseTrailerHeaders = new HeaderGroup();
0120:
0121:            /** Path of the HTTP method. */
0122:            private String path = null;
0123:
0124:            /** Query string of the HTTP method, if any. */
0125:            private String queryString = null;
0126:
0127:            /** The response body of the HTTP method, assuming it has not be 
0128:             * intercepted by a sub-class. */
0129:            private InputStream responseStream = null;
0130:
0131:            /** The connection that the response stream was read from. */
0132:            private HttpConnection responseConnection = null;
0133:
0134:            /** Buffer for the response */
0135:            private byte[] responseBody = null;
0136:
0137:            /** True if the HTTP method should automatically follow HTTP redirects.*/
0138:            private boolean followRedirects = false;
0139:
0140:            /** True if the HTTP method should automatically handle
0141:             *  HTTP authentication challenges. */
0142:            private boolean doAuthentication = true;
0143:
0144:            /** HTTP protocol parameters. */
0145:            private HttpMethodParams params = new HttpMethodParams();
0146:
0147:            /** Host authentication state */
0148:            private AuthState hostAuthState = new AuthState();
0149:
0150:            /** Proxy authentication state */
0151:            private AuthState proxyAuthState = new AuthState();
0152:
0153:            /** True if this method has already been executed. */
0154:            private boolean used = false;
0155:
0156:            /** Count of how many times did this HTTP method transparently handle 
0157:             * a recoverable exception. */
0158:            private int recoverableExceptionCount = 0;
0159:
0160:            /** the host for this HTTP method, can be null */
0161:            private HttpHost httphost = null;
0162:
0163:            /**
0164:             * Handles method retries
0165:             * 
0166:             * @deprecated no loner used
0167:             */
0168:            private MethodRetryHandler methodRetryHandler;
0169:
0170:            /** True if the connection must be closed when no longer needed */
0171:            private boolean connectionCloseForced = false;
0172:
0173:            /** Number of milliseconds to wait for 100-contunue response. */
0174:            private static final int RESPONSE_WAIT_TIME_MS = 3000;
0175:
0176:            /** HTTP protocol version used for execution of this method. */
0177:            protected HttpVersion effectiveVersion = null;
0178:
0179:            /** Whether the execution of this method has been aborted */
0180:            private volatile boolean aborted = false;
0181:
0182:            /** Whether the HTTP request has been transmitted to the target
0183:             * server it its entirety */
0184:            private boolean requestSent = false;
0185:
0186:            /** Actual cookie policy */
0187:            private CookieSpec cookiespec = null;
0188:
0189:            /** Default initial size of the response buffer if content length is unknown. */
0190:            private static final int DEFAULT_INITIAL_BUFFER_SIZE = 4 * 1024; // 4 kB
0191:
0192:            // ----------------------------------------------------------- Constructors
0193:
0194:            /**
0195:             * No-arg constructor.
0196:             */
0197:            public HttpMethodBase() {
0198:            }
0199:
0200:            /**
0201:             * Constructor specifying a URI.
0202:             * It is responsibility of the caller to ensure that URI elements
0203:             * (path & query parameters) are properly encoded (URL safe).
0204:             *
0205:             * @param uri either an absolute or relative URI. The URI is expected
0206:             *            to be URL-encoded
0207:             * 
0208:             * @throws IllegalArgumentException when URI is invalid
0209:             * @throws IllegalStateException when protocol of the absolute URI is not recognised
0210:             */
0211:            public HttpMethodBase(String uri) throws IllegalArgumentException,
0212:                    IllegalStateException {
0213:
0214:                try {
0215:
0216:                    // create a URI and allow for null/empty uri values
0217:                    if (uri == null || uri.equals("")) {
0218:                        uri = "/";
0219:                    }
0220:                    String charset = getParams().getUriCharset();
0221:                    setURI(new URI(uri, true, charset));
0222:                } catch (URIException e) {
0223:                    throw new IllegalArgumentException("Invalid uri '" + uri
0224:                            + "': " + e.getMessage());
0225:                }
0226:            }
0227:
0228:            // ------------------------------------------- Property Setters and Getters
0229:
0230:            /**
0231:             * Obtains the name of the HTTP method as used in the HTTP request line,
0232:             * for example <tt>"GET"</tt> or <tt>"POST"</tt>.
0233:             * 
0234:             * @return the name of this method
0235:             */
0236:            public abstract String getName();
0237:
0238:            /**
0239:             * Returns the URI of the HTTP method
0240:             * 
0241:             * @return The URI
0242:             * 
0243:             * @throws URIException If the URI cannot be created.
0244:             * 
0245:             * @see org.apache.commons.httpclient.HttpMethod#getURI()
0246:             */
0247:            public URI getURI() throws URIException {
0248:                StringBuffer buffer = new StringBuffer();
0249:                if (this .httphost != null) {
0250:                    buffer.append(this .httphost.getProtocol().getScheme());
0251:                    buffer.append("://");
0252:                    buffer.append(this .httphost.getHostName());
0253:                    int port = this .httphost.getPort();
0254:                    if (port != -1
0255:                            && port != this .httphost.getProtocol()
0256:                                    .getDefaultPort()) {
0257:                        buffer.append(":");
0258:                        buffer.append(port);
0259:                    }
0260:                }
0261:                buffer.append(this .path);
0262:                if (this .queryString != null) {
0263:                    buffer.append('?');
0264:                    buffer.append(this .queryString);
0265:                }
0266:                String charset = getParams().getUriCharset();
0267:                return new URI(buffer.toString(), true, charset);
0268:            }
0269:
0270:            /**
0271:             * Sets the URI for this method. 
0272:             * 
0273:             * @param uri URI to be set 
0274:             * 
0275:             * @throws URIException if a URI cannot be set
0276:             * 
0277:             * @since 3.0
0278:             */
0279:            public void setURI(URI uri) throws URIException {
0280:                // only set the host if specified by the URI
0281:                if (uri.isAbsoluteURI()) {
0282:                    this .httphost = new HttpHost(uri);
0283:                }
0284:                // set the path, defaulting to root
0285:                setPath(uri.getPath() == null ? "/" : uri.getEscapedPath());
0286:                setQueryString(uri.getEscapedQuery());
0287:            }
0288:
0289:            /**
0290:             * Sets whether or not the HTTP method should automatically follow HTTP redirects 
0291:             * (status code 302, etc.)
0292:             * 
0293:             * @param followRedirects <tt>true</tt> if the method will automatically follow redirects,
0294:             * <tt>false</tt> otherwise.
0295:             */
0296:            public void setFollowRedirects(boolean followRedirects) {
0297:                this .followRedirects = followRedirects;
0298:            }
0299:
0300:            /**
0301:             * Returns <tt>true</tt> if the HTTP method should automatically follow HTTP redirects 
0302:             * (status code 302, etc.), <tt>false</tt> otherwise.
0303:             * 
0304:             * @return <tt>true</tt> if the method will automatically follow HTTP redirects, 
0305:             * <tt>false</tt> otherwise.
0306:             */
0307:            public boolean getFollowRedirects() {
0308:                return this .followRedirects;
0309:            }
0310:
0311:            /** Sets whether version 1.1 of the HTTP protocol should be used per default.
0312:             *
0313:             * @param http11 <tt>true</tt> to use HTTP/1.1, <tt>false</tt> to use 1.0
0314:             * 
0315:             * @deprecated Use {@link HttpMethodParams#setVersion(HttpVersion)}
0316:             */
0317:            public void setHttp11(boolean http11) {
0318:                if (http11) {
0319:                    this .params.setVersion(HttpVersion.HTTP_1_1);
0320:                } else {
0321:                    this .params.setVersion(HttpVersion.HTTP_1_0);
0322:                }
0323:            }
0324:
0325:            /**
0326:             * Returns <tt>true</tt> if the HTTP method should automatically handle HTTP 
0327:             * authentication challenges (status code 401, etc.), <tt>false</tt> otherwise
0328:             *
0329:             * @return <tt>true</tt> if authentication challenges will be processed 
0330:             * automatically, <tt>false</tt> otherwise.
0331:             * 
0332:             * @since 2.0
0333:             */
0334:            public boolean getDoAuthentication() {
0335:                return doAuthentication;
0336:            }
0337:
0338:            /**
0339:             * Sets whether or not the HTTP method should automatically handle HTTP 
0340:             * authentication challenges (status code 401, etc.)
0341:             *
0342:             * @param doAuthentication <tt>true</tt> to process authentication challenges
0343:             * authomatically, <tt>false</tt> otherwise.
0344:             * 
0345:             * @since 2.0
0346:             */
0347:            public void setDoAuthentication(boolean doAuthentication) {
0348:                this .doAuthentication = doAuthentication;
0349:            }
0350:
0351:            // ---------------------------------------------- Protected Utility Methods
0352:
0353:            /**
0354:             * Returns <tt>true</tt> if version 1.1 of the HTTP protocol should be 
0355:             * used per default, <tt>false</tt> if version 1.0 should be used.
0356:             *
0357:             * @return <tt>true</tt> to use HTTP/1.1, <tt>false</tt> to use 1.0
0358:             * 
0359:             * @deprecated Use {@link HttpMethodParams#getVersion()}
0360:             */
0361:            public boolean isHttp11() {
0362:                return this .params.getVersion().equals(HttpVersion.HTTP_1_1);
0363:            }
0364:
0365:            /**
0366:             * Sets the path of the HTTP method.
0367:             * It is responsibility of the caller to ensure that the path is
0368:             * properly encoded (URL safe).
0369:             *
0370:             * @param path the path of the HTTP method. The path is expected
0371:             *        to be URL-encoded
0372:             */
0373:            public void setPath(String path) {
0374:                this .path = path;
0375:            }
0376:
0377:            /**
0378:             * Adds the specified request header, NOT overwriting any previous value.
0379:             * Note that header-name matching is case insensitive.
0380:             *
0381:             * @param header the header to add to the request
0382:             */
0383:            public void addRequestHeader(Header header) {
0384:                LOG.trace("HttpMethodBase.addRequestHeader(Header)");
0385:
0386:                if (header == null) {
0387:                    LOG.debug("null header value ignored");
0388:                } else {
0389:                    getRequestHeaderGroup().addHeader(header);
0390:                }
0391:            }
0392:
0393:            /**
0394:             * Use this method internally to add footers.
0395:             * 
0396:             * @param footer The footer to add.
0397:             */
0398:            public void addResponseFooter(Header footer) {
0399:                getResponseTrailerHeaderGroup().addHeader(footer);
0400:            }
0401:
0402:            /**
0403:             * Gets the path of this HTTP method.
0404:             * Calling this method <em>after</em> the request has been executed will 
0405:             * return the <em>actual</em> path, following any redirects automatically
0406:             * handled by this HTTP method.
0407:             *
0408:             * @return the path to request or "/" if the path is blank.
0409:             */
0410:            public String getPath() {
0411:                return (path == null || path.equals("")) ? "/" : path;
0412:            }
0413:
0414:            /**
0415:             * Sets the query string of this HTTP method. The caller must ensure that the string 
0416:             * is properly URL encoded. The query string should not start with the question 
0417:             * mark character.
0418:             *
0419:             * @param queryString the query string
0420:             * 
0421:             * @see EncodingUtil#formUrlEncode(NameValuePair[], String)
0422:             */
0423:            public void setQueryString(String queryString) {
0424:                this .queryString = queryString;
0425:            }
0426:
0427:            /**
0428:             * Sets the query string of this HTTP method.  The pairs are encoded as UTF-8 characters.  
0429:             * To use a different charset the parameters can be encoded manually using EncodingUtil 
0430:             * and set as a single String.
0431:             *
0432:             * @param params an array of {@link NameValuePair}s to add as query string
0433:             *        parameters. The name/value pairs will be automcatically 
0434:             *        URL encoded
0435:             * 
0436:             * @see EncodingUtil#formUrlEncode(NameValuePair[], String)
0437:             * @see #setQueryString(String)
0438:             */
0439:            public void setQueryString(NameValuePair[] params) {
0440:                LOG
0441:                        .trace("enter HttpMethodBase.setQueryString(NameValuePair[])");
0442:                queryString = EncodingUtil.formUrlEncode(params, "UTF-8");
0443:            }
0444:
0445:            /**
0446:             * Gets the query string of this HTTP method.
0447:             *
0448:             * @return The query string
0449:             */
0450:            public String getQueryString() {
0451:                return queryString;
0452:            }
0453:
0454:            /**
0455:             * Set the specified request header, overwriting any previous value. Note
0456:             * that header-name matching is case-insensitive.
0457:             *
0458:             * @param headerName the header's name
0459:             * @param headerValue the header's value
0460:             */
0461:            public void setRequestHeader(String headerName, String headerValue) {
0462:                Header header = new Header(headerName, headerValue);
0463:                setRequestHeader(header);
0464:            }
0465:
0466:            /**
0467:             * Sets the specified request header, overwriting any previous value.
0468:             * Note that header-name matching is case insensitive.
0469:             * 
0470:             * @param header the header
0471:             */
0472:            public void setRequestHeader(Header header) {
0473:
0474:                Header[] headers = getRequestHeaderGroup().getHeaders(
0475:                        header.getName());
0476:
0477:                for (int i = 0; i < headers.length; i++) {
0478:                    getRequestHeaderGroup().removeHeader(headers[i]);
0479:                }
0480:
0481:                getRequestHeaderGroup().addHeader(header);
0482:
0483:            }
0484:
0485:            /**
0486:             * Returns the specified request header. Note that header-name matching is
0487:             * case insensitive. <tt>null</tt> will be returned if either
0488:             * <i>headerName</i> is <tt>null</tt> or there is no matching header for
0489:             * <i>headerName</i>.
0490:             * 
0491:             * @param headerName The name of the header to be returned.
0492:             *
0493:             * @return The specified request header.
0494:             * 
0495:             * @since 3.0
0496:             */
0497:            public Header getRequestHeader(String headerName) {
0498:                if (headerName == null) {
0499:                    return null;
0500:                } else {
0501:                    return getRequestHeaderGroup().getCondensedHeader(
0502:                            headerName);
0503:                }
0504:            }
0505:
0506:            /**
0507:             * Returns an array of the requests headers that the HTTP method currently has
0508:             *
0509:             * @return an array of my request headers.
0510:             */
0511:            public Header[] getRequestHeaders() {
0512:                return getRequestHeaderGroup().getAllHeaders();
0513:            }
0514:
0515:            /**
0516:             * @see org.apache.commons.httpclient.HttpMethod#getRequestHeaders(java.lang.String)
0517:             */
0518:            public Header[] getRequestHeaders(String headerName) {
0519:                return getRequestHeaderGroup().getHeaders(headerName);
0520:            }
0521:
0522:            /**
0523:             * Gets the {@link HeaderGroup header group} storing the request headers.
0524:             * 
0525:             * @return a HeaderGroup
0526:             * 
0527:             * @since 2.0beta1
0528:             */
0529:            protected HeaderGroup getRequestHeaderGroup() {
0530:                return requestHeaders;
0531:            }
0532:
0533:            /**
0534:             * Gets the {@link HeaderGroup header group} storing the response trailer headers 
0535:             * as per RFC 2616 section 3.6.1.
0536:             * 
0537:             * @return a HeaderGroup
0538:             * 
0539:             * @since 2.0beta1
0540:             */
0541:            protected HeaderGroup getResponseTrailerHeaderGroup() {
0542:                return responseTrailerHeaders;
0543:            }
0544:
0545:            /**
0546:             * Gets the {@link HeaderGroup header group} storing the response headers.
0547:             * 
0548:             * @return a HeaderGroup
0549:             * 
0550:             * @since 2.0beta1
0551:             */
0552:            protected HeaderGroup getResponseHeaderGroup() {
0553:                return responseHeaders;
0554:            }
0555:
0556:            /**
0557:             * @see org.apache.commons.httpclient.HttpMethod#getResponseHeaders(java.lang.String)
0558:             * 
0559:             * @since 3.0
0560:             */
0561:            public Header[] getResponseHeaders(String headerName) {
0562:                return getResponseHeaderGroup().getHeaders(headerName);
0563:            }
0564:
0565:            /**
0566:             * Returns the response status code.
0567:             *
0568:             * @return the status code associated with the latest response.
0569:             */
0570:            public int getStatusCode() {
0571:                return statusLine.getStatusCode();
0572:            }
0573:
0574:            /**
0575:             * Provides access to the response status line.
0576:             *
0577:             * @return the status line object from the latest response.
0578:             * @since 2.0
0579:             */
0580:            public StatusLine getStatusLine() {
0581:                return statusLine;
0582:            }
0583:
0584:            /**
0585:             * Checks if response data is available.
0586:             * @return <tt>true</tt> if response data is available, <tt>false</tt> otherwise.
0587:             */
0588:            private boolean responseAvailable() {
0589:                return (responseBody != null) || (responseStream != null);
0590:            }
0591:
0592:            /**
0593:             * Returns an array of the response headers that the HTTP method currently has
0594:             * in the order in which they were read.
0595:             *
0596:             * @return an array of response headers.
0597:             */
0598:            public Header[] getResponseHeaders() {
0599:                return getResponseHeaderGroup().getAllHeaders();
0600:            }
0601:
0602:            /**
0603:             * Gets the response header associated with the given name. Header name
0604:             * matching is case insensitive. <tt>null</tt> will be returned if either
0605:             * <i>headerName</i> is <tt>null</tt> or there is no matching header for
0606:             * <i>headerName</i>.
0607:             *
0608:             * @param headerName the header name to match
0609:             *
0610:             * @return the matching header
0611:             */
0612:            public Header getResponseHeader(String headerName) {
0613:                if (headerName == null) {
0614:                    return null;
0615:                } else {
0616:                    return getResponseHeaderGroup().getCondensedHeader(
0617:                            headerName);
0618:                }
0619:            }
0620:
0621:            /**
0622:             * Return the length (in bytes) of the response body, as specified in a
0623:             * <tt>Content-Length</tt> header.
0624:             *
0625:             * <p>
0626:             * Return <tt>-1</tt> when the content-length is unknown.
0627:             * </p>
0628:             *
0629:             * @return content length, if <tt>Content-Length</tt> header is available. 
0630:             *          <tt>0</tt> indicates that the request has no body.
0631:             *          If <tt>Content-Length</tt> header is not present, the method 
0632:             *          returns  <tt>-1</tt>.
0633:             */
0634:            public long getResponseContentLength() {
0635:                Header[] headers = getResponseHeaderGroup().getHeaders(
0636:                        "Content-Length");
0637:                if (headers.length == 0) {
0638:                    return -1;
0639:                }
0640:                if (headers.length > 1) {
0641:                    LOG.warn("Multiple content-length headers detected");
0642:                }
0643:                for (int i = headers.length - 1; i >= 0; i--) {
0644:                    Header header = headers[i];
0645:                    try {
0646:                        return Long.parseLong(header.getValue());
0647:                    } catch (NumberFormatException e) {
0648:                        if (LOG.isWarnEnabled()) {
0649:                            LOG.warn("Invalid content-length value: "
0650:                                    + e.getMessage());
0651:                        }
0652:                    }
0653:                    // See if we can have better luck with another header, if present
0654:                }
0655:                return -1;
0656:            }
0657:
0658:            /**
0659:             * Returns the response body of the HTTP method, if any, as an array of bytes.
0660:             * If response body is not available or cannot be read, returns <tt>null</tt>.
0661:             * Buffers the response and this method can be called several times yielding
0662:             * the same result each time.
0663:             * 
0664:             * Note: This will cause the entire response body to be buffered in memory. A
0665:             * malicious server may easily exhaust all the VM memory. It is strongly
0666:             * recommended, to use getResponseAsStream if the content length of the response
0667:             * is unknown or resonably large.
0668:             *  
0669:             * @return The response body.
0670:             * 
0671:             * @throws IOException If an I/O (transport) problem occurs while obtaining the 
0672:             * response body.
0673:             */
0674:            public byte[] getResponseBody() throws IOException {
0675:                if (this .responseBody == null) {
0676:                    InputStream instream = getResponseBodyAsStream();
0677:                    if (instream != null) {
0678:                        long contentLength = getResponseContentLength();
0679:                        if (contentLength > Integer.MAX_VALUE) { //guard below cast from overflow
0680:                            throw new IOException(
0681:                                    "Content too large to be buffered: "
0682:                                            + contentLength + " bytes");
0683:                        }
0684:                        int limit = getParams().getIntParameter(
0685:                                HttpMethodParams.BUFFER_WARN_TRIGGER_LIMIT,
0686:                                1024 * 1024);
0687:                        if ((contentLength == -1) || (contentLength > limit)) {
0688:                            LOG
0689:                                    .warn("Going to buffer response body of large or unknown size. "
0690:                                            + "Using getResponseBodyAsStream instead is recommended.");
0691:                        }
0692:                        LOG.debug("Buffering response body");
0693:                        ByteArrayOutputStream outstream = new ByteArrayOutputStream(
0694:                                contentLength > 0 ? (int) contentLength
0695:                                        : DEFAULT_INITIAL_BUFFER_SIZE);
0696:                        byte[] buffer = new byte[4096];
0697:                        int len;
0698:                        while ((len = instream.read(buffer)) > 0) {
0699:                            outstream.write(buffer, 0, len);
0700:                        }
0701:                        outstream.close();
0702:                        setResponseStream(null);
0703:                        this .responseBody = outstream.toByteArray();
0704:                    }
0705:                }
0706:                return this .responseBody;
0707:            }
0708:
0709:            /**
0710:             * Returns the response body of the HTTP method, if any, as an array of bytes.
0711:             * If response body is not available or cannot be read, returns <tt>null</tt>.
0712:             * Buffers the response and this method can be called several times yielding
0713:             * the same result each time.
0714:             * 
0715:             * Note: This will cause the entire response body to be buffered in memory. This method is
0716:             * safe if the content length of the response is unknown, because the amount of memory used
0717:             * is limited.<p>
0718:             * 
0719:             * If the response is large this method involves lots of array copying and many object 
0720:             * allocations, which makes it unsuitable for high-performance / low-footprint applications.
0721:             * Those applications should use {@link #getResponseBodyAsStream()}.
0722:             * 
0723:             * @param maxlen the maximum content length to accept (number of bytes). 
0724:             * @return The response body.
0725:             * 
0726:             * @throws IOException If an I/O (transport) problem occurs while obtaining the 
0727:             * response body.
0728:             */
0729:            public byte[] getResponseBody(int maxlen) throws IOException {
0730:                if (maxlen < 0)
0731:                    throw new IllegalArgumentException(
0732:                            "maxlen must be positive");
0733:                if (this .responseBody == null) {
0734:                    InputStream instream = getResponseBodyAsStream();
0735:                    if (instream != null) {
0736:                        // we might already know that the content is larger
0737:                        long contentLength = getResponseContentLength();
0738:                        if ((contentLength != -1) && (contentLength > maxlen)) {
0739:                            throw new HttpContentTooLargeException(
0740:                                    "Content-Length is " + contentLength,
0741:                                    maxlen);
0742:                        }
0743:
0744:                        LOG.debug("Buffering response body");
0745:                        ByteArrayOutputStream rawdata = new ByteArrayOutputStream(
0746:                                contentLength > 0 ? (int) contentLength
0747:                                        : DEFAULT_INITIAL_BUFFER_SIZE);
0748:                        byte[] buffer = new byte[2048];
0749:                        int pos = 0;
0750:                        int len;
0751:                        do {
0752:                            len = instream.read(buffer, 0, Math.min(
0753:                                    buffer.length, maxlen - pos));
0754:                            if (len == -1)
0755:                                break;
0756:                            rawdata.write(buffer, 0, len);
0757:                            pos += len;
0758:                        } while (pos < maxlen);
0759:
0760:                        setResponseStream(null);
0761:                        // check if there is even more data
0762:                        if (pos == maxlen) {
0763:                            if (instream.read() != -1)
0764:                                throw new HttpContentTooLargeException(
0765:                                        "Content-Length not known but larger than "
0766:                                                + maxlen, maxlen);
0767:                        }
0768:                        this .responseBody = rawdata.toByteArray();
0769:                    }
0770:                }
0771:                return this .responseBody;
0772:            }
0773:
0774:            /**
0775:             * Returns the response body of the HTTP method, if any, as an {@link InputStream}. 
0776:             * If response body is not available, returns <tt>null</tt>. If the response has been
0777:             * buffered this method returns a new stream object on every call. If the response
0778:             * has not been buffered the returned stream can only be read once.
0779:             * 
0780:             * @return The response body or <code>null</code>.
0781:             * 
0782:             * @throws IOException If an I/O (transport) problem occurs while obtaining the 
0783:             * response body.
0784:             */
0785:            public InputStream getResponseBodyAsStream() throws IOException {
0786:                if (responseStream != null) {
0787:                    return responseStream;
0788:                }
0789:                if (responseBody != null) {
0790:                    InputStream byteResponseStream = new ByteArrayInputStream(
0791:                            responseBody);
0792:                    LOG.debug("re-creating response stream from byte array");
0793:                    return byteResponseStream;
0794:                }
0795:                return null;
0796:            }
0797:
0798:            /**
0799:             * Returns the response body of the HTTP method, if any, as a {@link String}. 
0800:             * If response body is not available or cannot be read, returns <tt>null</tt>
0801:             * The string conversion on the data is done using the character encoding specified
0802:             * in <tt>Content-Type</tt> header. Buffers the response and this method can be 
0803:             * called several times yielding the same result each time.
0804:             * 
0805:             * Note: This will cause the entire response body to be buffered in memory. A
0806:             * malicious server may easily exhaust all the VM memory. It is strongly
0807:             * recommended, to use getResponseAsStream if the content length of the response
0808:             * is unknown or resonably large.
0809:             * 
0810:             * @return The response body or <code>null</code>.
0811:             * 
0812:             * @throws IOException If an I/O (transport) problem occurs while obtaining the 
0813:             * response body.
0814:             */
0815:            public String getResponseBodyAsString() throws IOException {
0816:                byte[] rawdata = null;
0817:                if (responseAvailable()) {
0818:                    rawdata = getResponseBody();
0819:                }
0820:                if (rawdata != null) {
0821:                    return EncodingUtil
0822:                            .getString(rawdata, getResponseCharSet());
0823:                } else {
0824:                    return null;
0825:                }
0826:            }
0827:
0828:            /**
0829:             * Returns the response body of the HTTP method, if any, as a {@link String}. 
0830:             * If response body is not available or cannot be read, returns <tt>null</tt>
0831:             * The string conversion on the data is done using the character encoding specified
0832:             * in <tt>Content-Type</tt> header. Buffers the response and this method can be 
0833:             * called several times yielding the same result each time.</p>
0834:             * 
0835:             * Note: This will cause the entire response body to be buffered in memory. This method is
0836:             * safe if the content length of the response is unknown, because the amount of memory used
0837:             * is limited.<p>
0838:             * 
0839:             * If the response is large this method involves lots of array copying and many object 
0840:             * allocations, which makes it unsuitable for high-performance / low-footprint applications.
0841:             * Those applications should use {@link #getResponseBodyAsStream()}.
0842:             * 
0843:             * @param maxlen the maximum content length to accept (number of bytes). Note that,
0844:             * depending on the encoding, this is not equal to the number of characters.
0845:             * @return The response body or <code>null</code>.
0846:             * 
0847:             * @throws IOException If an I/O (transport) problem occurs while obtaining the 
0848:             * response body.
0849:             */
0850:            public String getResponseBodyAsString(int maxlen)
0851:                    throws IOException {
0852:                if (maxlen < 0)
0853:                    throw new IllegalArgumentException(
0854:                            "maxlen must be positive");
0855:                byte[] rawdata = null;
0856:                if (responseAvailable()) {
0857:                    rawdata = getResponseBody(maxlen);
0858:                }
0859:                if (rawdata != null) {
0860:                    return EncodingUtil
0861:                            .getString(rawdata, getResponseCharSet());
0862:                } else {
0863:                    return null;
0864:                }
0865:            }
0866:
0867:            /**
0868:             * Returns an array of the response footers that the HTTP method currently has
0869:             * in the order in which they were read.
0870:             *
0871:             * @return an array of footers
0872:             */
0873:            public Header[] getResponseFooters() {
0874:                return getResponseTrailerHeaderGroup().getAllHeaders();
0875:            }
0876:
0877:            /**
0878:             * Gets the response footer associated with the given name.
0879:             * Footer name matching is case insensitive.
0880:             * <tt>null</tt> will be returned if either <i>footerName</i> is
0881:             * <tt>null</tt> or there is no matching footer for <i>footerName</i>
0882:             * or there are no footers available.  If there are multiple footers
0883:             * with the same name, there values will be combined with the ',' separator
0884:             * as specified by RFC2616.
0885:             * 
0886:             * @param footerName the footer name to match
0887:             * @return the matching footer
0888:             */
0889:            public Header getResponseFooter(String footerName) {
0890:                if (footerName == null) {
0891:                    return null;
0892:                } else {
0893:                    return getResponseTrailerHeaderGroup().getCondensedHeader(
0894:                            footerName);
0895:                }
0896:            }
0897:
0898:            /**
0899:             * Sets the response stream.
0900:             * @param responseStream The new response stream.
0901:             */
0902:            protected void setResponseStream(InputStream responseStream) {
0903:                this .responseStream = responseStream;
0904:            }
0905:
0906:            /**
0907:             * Returns a stream from which the body of the current response may be read.
0908:             * If the method has not yet been executed, if <code>responseBodyConsumed</code>
0909:             * has been called, or if the stream returned by a previous call has been closed,
0910:             * <code>null</code> will be returned.
0911:             *
0912:             * @return the current response stream
0913:             */
0914:            protected InputStream getResponseStream() {
0915:                return responseStream;
0916:            }
0917:
0918:            /**
0919:             * Returns the status text (or "reason phrase") associated with the latest
0920:             * response.
0921:             * 
0922:             * @return The status text.
0923:             */
0924:            public String getStatusText() {
0925:                return statusLine.getReasonPhrase();
0926:            }
0927:
0928:            /**
0929:             * Defines how strictly HttpClient follows the HTTP protocol specification  
0930:             * (RFC 2616 and other relevant RFCs). In the strict mode HttpClient precisely
0931:             * implements the requirements of the specification, whereas in non-strict mode 
0932:             * it attempts to mimic the exact behaviour of commonly used HTTP agents, 
0933:             * which many HTTP servers expect.
0934:             * 
0935:             * @param strictMode <tt>true</tt> for strict mode, <tt>false</tt> otherwise
0936:             * 
0937:             * @deprecated Use {@link org.apache.commons.httpclient.params.HttpParams#setParameter(String, Object)}
0938:             * to exercise a more granular control over HTTP protocol strictness.
0939:             */
0940:            public void setStrictMode(boolean strictMode) {
0941:                if (strictMode) {
0942:                    this .params.makeStrict();
0943:                } else {
0944:                    this .params.makeLenient();
0945:                }
0946:            }
0947:
0948:            /**
0949:             * @deprecated Use {@link org.apache.commons.httpclient.params.HttpParams#setParameter(String, Object)}
0950:             * to exercise a more granular control over HTTP protocol strictness.
0951:             *
0952:             * @return <tt>false</tt>
0953:             */
0954:            public boolean isStrictMode() {
0955:                return false;
0956:            }
0957:
0958:            /**
0959:             * Adds the specified request header, NOT overwriting any previous value.
0960:             * Note that header-name matching is case insensitive.
0961:             *
0962:             * @param headerName the header's name
0963:             * @param headerValue the header's value
0964:             */
0965:            public void addRequestHeader(String headerName, String headerValue) {
0966:                addRequestHeader(new Header(headerName, headerValue));
0967:            }
0968:
0969:            /**
0970:             * Tests if the connection should be force-closed when no longer needed.
0971:             * 
0972:             * @return <code>true</code> if the connection must be closed
0973:             */
0974:            protected boolean isConnectionCloseForced() {
0975:                return this .connectionCloseForced;
0976:            }
0977:
0978:            /**
0979:             * Sets whether or not the connection should be force-closed when no longer 
0980:             * needed. This value should only be set to <code>true</code> in abnormal 
0981:             * circumstances, such as HTTP protocol violations. 
0982:             * 
0983:             * @param b <code>true</code> if the connection must be closed, <code>false</code>
0984:             * otherwise.
0985:             */
0986:            protected void setConnectionCloseForced(boolean b) {
0987:                if (LOG.isDebugEnabled()) {
0988:                    LOG.debug("Force-close connection: " + b);
0989:                }
0990:                this .connectionCloseForced = b;
0991:            }
0992:
0993:            /**
0994:             * Tests if the connection should be closed after the method has been executed.
0995:             * The connection will be left open when using HTTP/1.1 or if <tt>Connection: 
0996:             * keep-alive</tt> header was sent.
0997:             * 
0998:             * @param conn the connection in question
0999:             * 
1000:             * @return boolean true if we should close the connection.
1001:             */
1002:            protected boolean shouldCloseConnection(HttpConnection conn) {
1003:                // Connection must be closed due to an abnormal circumstance 
1004:                if (isConnectionCloseForced()) {
1005:                    LOG.debug("Should force-close connection.");
1006:                    return true;
1007:                }
1008:
1009:                Header connectionHeader = null;
1010:                // In case being connected via a proxy server
1011:                if (!conn.isTransparent()) {
1012:                    // Check for 'proxy-connection' directive
1013:                    connectionHeader = responseHeaders
1014:                            .getFirstHeader("proxy-connection");
1015:                }
1016:                // In all cases Check for 'connection' directive
1017:                // some non-complaint proxy servers send it instread of
1018:                // expected 'proxy-connection' directive
1019:                if (connectionHeader == null) {
1020:                    connectionHeader = responseHeaders
1021:                            .getFirstHeader("connection");
1022:                }
1023:                // In case the response does not contain any explict connection
1024:                // directives, check whether the request does
1025:                if (connectionHeader == null) {
1026:                    connectionHeader = requestHeaders
1027:                            .getFirstHeader("connection");
1028:                }
1029:                if (connectionHeader != null) {
1030:                    if (connectionHeader.getValue().equalsIgnoreCase("close")) {
1031:                        if (LOG.isDebugEnabled()) {
1032:                            LOG
1033:                                    .debug("Should close connection in response to directive: "
1034:                                            + connectionHeader.getValue());
1035:                        }
1036:                        return true;
1037:                    } else if (connectionHeader.getValue().equalsIgnoreCase(
1038:                            "keep-alive")) {
1039:                        if (LOG.isDebugEnabled()) {
1040:                            LOG
1041:                                    .debug("Should NOT close connection in response to directive: "
1042:                                            + connectionHeader.getValue());
1043:                        }
1044:                        return false;
1045:                    } else {
1046:                        if (LOG.isDebugEnabled()) {
1047:                            LOG.debug("Unknown directive: "
1048:                                    + connectionHeader.toExternalForm());
1049:                        }
1050:                    }
1051:                }
1052:                LOG
1053:                        .debug("Resorting to protocol version default close connection policy");
1054:                // missing or invalid connection header, do the default
1055:                if (this .effectiveVersion.greaterEquals(HttpVersion.HTTP_1_1)) {
1056:                    if (LOG.isDebugEnabled()) {
1057:                        LOG.debug("Should NOT close connection, using "
1058:                                + this .effectiveVersion.toString());
1059:                    }
1060:                } else {
1061:                    if (LOG.isDebugEnabled()) {
1062:                        LOG.debug("Should close connection, using "
1063:                                + this .effectiveVersion.toString());
1064:                    }
1065:                }
1066:                return this .effectiveVersion.lessEquals(HttpVersion.HTTP_1_0);
1067:            }
1068:
1069:            /**
1070:             * Tests if the this method is ready to be executed.
1071:             * 
1072:             * @param state the {@link HttpState state} information associated with this method
1073:             * @param conn the {@link HttpConnection connection} to be used
1074:             * @throws HttpException If the method is in invalid state.
1075:             */
1076:            private void checkExecuteConditions(HttpState state,
1077:                    HttpConnection conn) throws HttpException {
1078:
1079:                if (state == null) {
1080:                    throw new IllegalArgumentException(
1081:                            "HttpState parameter may not be null");
1082:                }
1083:                if (conn == null) {
1084:                    throw new IllegalArgumentException(
1085:                            "HttpConnection parameter may not be null");
1086:                }
1087:                if (this .aborted) {
1088:                    throw new IllegalStateException("Method has been aborted");
1089:                }
1090:                if (!validate()) {
1091:                    throw new ProtocolException(
1092:                            "HttpMethodBase object not valid");
1093:                }
1094:            }
1095:
1096:            /**
1097:             * Executes this method using the specified <code>HttpConnection</code> and
1098:             * <code>HttpState</code>. 
1099:             *
1100:             * @param state {@link HttpState state} information to associate with this
1101:             *        request. Must be non-null.
1102:             * @param conn the {@link HttpConnection connection} to used to execute
1103:             *        this HTTP method. Must be non-null.
1104:             *
1105:             * @return the integer status code if one was obtained, or <tt>-1</tt>
1106:             *
1107:             * @throws IOException if an I/O (transport) error occurs
1108:             * @throws HttpException  if a protocol exception occurs.
1109:             */
1110:            public int execute(HttpState state, HttpConnection conn)
1111:                    throws HttpException, IOException {
1112:
1113:                LOG
1114:                        .trace("enter HttpMethodBase.execute(HttpState, HttpConnection)");
1115:
1116:                // this is our connection now, assign it to a local variable so 
1117:                // that it can be released later
1118:                this .responseConnection = conn;
1119:
1120:                checkExecuteConditions(state, conn);
1121:                this .statusLine = null;
1122:                this .connectionCloseForced = false;
1123:
1124:                conn.setLastResponseInputStream(null);
1125:
1126:                // determine the effective protocol version
1127:                if (this .effectiveVersion == null) {
1128:                    this .effectiveVersion = this .params.getVersion();
1129:                }
1130:
1131:                writeRequest(state, conn);
1132:                this .requestSent = true;
1133:                readResponse(state, conn);
1134:                // the method has successfully executed
1135:                used = true;
1136:
1137:                return statusLine.getStatusCode();
1138:            }
1139:
1140:            /**
1141:             * Aborts the execution of this method.
1142:             * 
1143:             * @since 3.0
1144:             */
1145:            public void abort() {
1146:                if (this .aborted) {
1147:                    return;
1148:                }
1149:                this .aborted = true;
1150:                HttpConnection conn = this .responseConnection;
1151:                if (conn != null) {
1152:                    conn.close();
1153:                }
1154:            }
1155:
1156:            /**
1157:             * Returns <tt>true</tt> if the HTTP method has been already {@link #execute executed},
1158:             * but not {@link #recycle recycled}.
1159:             * 
1160:             * @return <tt>true</tt> if the method has been executed, <tt>false</tt> otherwise
1161:             */
1162:            public boolean hasBeenUsed() {
1163:                return used;
1164:            }
1165:
1166:            /**
1167:             * Recycles the HTTP method so that it can be used again.
1168:             * Note that all of the instance variables will be reset
1169:             * once this method has been called. This method will also
1170:             * release the connection being used by this HTTP method.
1171:             * 
1172:             * @see #releaseConnection()
1173:             * 
1174:             * @deprecated no longer supported and will be removed in the future
1175:             *             version of HttpClient
1176:             */
1177:            public void recycle() {
1178:                LOG.trace("enter HttpMethodBase.recycle()");
1179:
1180:                releaseConnection();
1181:
1182:                path = null;
1183:                followRedirects = false;
1184:                doAuthentication = true;
1185:                queryString = null;
1186:                getRequestHeaderGroup().clear();
1187:                getResponseHeaderGroup().clear();
1188:                getResponseTrailerHeaderGroup().clear();
1189:                statusLine = null;
1190:                effectiveVersion = null;
1191:                aborted = false;
1192:                used = false;
1193:                params = new HttpMethodParams();
1194:                responseBody = null;
1195:                recoverableExceptionCount = 0;
1196:                connectionCloseForced = false;
1197:                hostAuthState.invalidate();
1198:                proxyAuthState.invalidate();
1199:                cookiespec = null;
1200:                requestSent = false;
1201:            }
1202:
1203:            /**
1204:             * Releases the connection being used by this HTTP method. In particular the
1205:             * connection is used to read the response(if there is one) and will be held
1206:             * until the response has been read. If the connection can be reused by other 
1207:             * HTTP methods it is NOT closed at this point.
1208:             *
1209:             * @since 2.0
1210:             */
1211:            public void releaseConnection() {
1212:                try {
1213:                    if (this .responseStream != null) {
1214:                        try {
1215:                            // FYI - this may indirectly invoke responseBodyConsumed.
1216:                            this .responseStream.close();
1217:                        } catch (IOException ignore) {
1218:                        }
1219:                    }
1220:                } finally {
1221:                    ensureConnectionRelease();
1222:                }
1223:            }
1224:
1225:            /**
1226:             * Remove the request header associated with the given name. Note that
1227:             * header-name matching is case insensitive.
1228:             *
1229:             * @param headerName the header name
1230:             */
1231:            public void removeRequestHeader(String headerName) {
1232:
1233:                Header[] headers = getRequestHeaderGroup().getHeaders(
1234:                        headerName);
1235:                for (int i = 0; i < headers.length; i++) {
1236:                    getRequestHeaderGroup().removeHeader(headers[i]);
1237:                }
1238:
1239:            }
1240:
1241:            /**
1242:             * Removes the given request header.
1243:             * 
1244:             * @param header the header
1245:             */
1246:            public void removeRequestHeader(final Header header) {
1247:                if (header == null) {
1248:                    return;
1249:                }
1250:                getRequestHeaderGroup().removeHeader(header);
1251:            }
1252:
1253:            // ---------------------------------------------------------------- Queries
1254:
1255:            /**
1256:             * Returns <tt>true</tt> the method is ready to execute, <tt>false</tt> otherwise.
1257:             * 
1258:             * @return This implementation always returns <tt>true</tt>.
1259:             */
1260:            public boolean validate() {
1261:                return true;
1262:            }
1263:
1264:            /** 
1265:             * Returns the actual cookie policy
1266:             * 
1267:             * @param state HTTP state. TODO: to be removed in the future
1268:             * 
1269:             * @return cookie spec
1270:             */
1271:            private CookieSpec getCookieSpec(final HttpState state) {
1272:                if (this .cookiespec == null) {
1273:                    int i = state.getCookiePolicy();
1274:                    if (i == -1) {
1275:                        this .cookiespec = CookiePolicy
1276:                                .getCookieSpec(this .params.getCookiePolicy());
1277:                    } else {
1278:                        this .cookiespec = CookiePolicy.getSpecByPolicy(i);
1279:                    }
1280:                    this .cookiespec
1281:                            .setValidDateFormats((Collection) this .params
1282:                                    .getParameter(HttpMethodParams.DATE_PATTERNS));
1283:                }
1284:                return this .cookiespec;
1285:            }
1286:
1287:            /**
1288:             * Generates <tt>Cookie</tt> request headers for those {@link Cookie cookie}s
1289:             * that match the given host, port and path.
1290:             *
1291:             * @param state the {@link HttpState state} information associated with this method
1292:             * @param conn the {@link HttpConnection connection} used to execute
1293:             *        this HTTP method
1294:             *
1295:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
1296:             *                     can be recovered from.
1297:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
1298:             *                    cannot be recovered from.
1299:             */
1300:            protected void addCookieRequestHeader(HttpState state,
1301:                    HttpConnection conn) throws IOException, HttpException {
1302:
1303:                LOG
1304:                        .trace("enter HttpMethodBase.addCookieRequestHeader(HttpState, "
1305:                                + "HttpConnection)");
1306:
1307:                Header[] cookieheaders = getRequestHeaderGroup().getHeaders(
1308:                        "Cookie");
1309:                for (int i = 0; i < cookieheaders.length; i++) {
1310:                    Header cookieheader = cookieheaders[i];
1311:                    if (cookieheader.isAutogenerated()) {
1312:                        getRequestHeaderGroup().removeHeader(cookieheader);
1313:                    }
1314:                }
1315:
1316:                CookieSpec matcher = getCookieSpec(state);
1317:                String host = this .params.getVirtualHost();
1318:                if (host == null) {
1319:                    host = conn.getHost();
1320:                }
1321:                Cookie[] cookies = matcher.match(host, conn.getPort(),
1322:                        getPath(), conn.isSecure(), state.getCookies());
1323:                if ((cookies != null) && (cookies.length > 0)) {
1324:                    if (getParams().isParameterTrue(
1325:                            HttpMethodParams.SINGLE_COOKIE_HEADER)) {
1326:                        // In strict mode put all cookies on the same header
1327:                        String s = matcher.formatCookies(cookies);
1328:                        getRequestHeaderGroup().addHeader(
1329:                                new Header("Cookie", s, true));
1330:                    } else {
1331:                        // In non-strict mode put each cookie on a separate header
1332:                        for (int i = 0; i < cookies.length; i++) {
1333:                            String s = matcher.formatCookie(cookies[i]);
1334:                            getRequestHeaderGroup().addHeader(
1335:                                    new Header("Cookie", s, true));
1336:                        }
1337:                    }
1338:                    if (matcher instanceof  CookieVersionSupport) {
1339:                        CookieVersionSupport versupport = (CookieVersionSupport) matcher;
1340:                        int ver = versupport.getVersion();
1341:                        boolean needVersionHeader = false;
1342:                        for (int i = 0; i < cookies.length; i++) {
1343:                            if (ver != cookies[i].getVersion()) {
1344:                                needVersionHeader = true;
1345:                            }
1346:                        }
1347:                        if (needVersionHeader) {
1348:                            // Advertise cookie version support
1349:                            getRequestHeaderGroup().addHeader(
1350:                                    versupport.getVersionHeader());
1351:                        }
1352:                    }
1353:                }
1354:            }
1355:
1356:            /**
1357:             * Generates <tt>Host</tt> request header, as long as no <tt>Host</tt> request
1358:             * header already exists.
1359:             *
1360:             * @param state the {@link HttpState state} information associated with this method
1361:             * @param conn the {@link HttpConnection connection} used to execute
1362:             *        this HTTP method
1363:             *
1364:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
1365:             *                     can be recovered from.
1366:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
1367:             *                    cannot be recovered from.
1368:             */
1369:            protected void addHostRequestHeader(HttpState state,
1370:                    HttpConnection conn) throws IOException, HttpException {
1371:                LOG
1372:                        .trace("enter HttpMethodBase.addHostRequestHeader(HttpState, "
1373:                                + "HttpConnection)");
1374:
1375:                // Per 19.6.1.1 of RFC 2616, it is legal for HTTP/1.0 based
1376:                // applications to send the Host request-header.
1377:                // TODO: Add the ability to disable the sending of this header for
1378:                //       HTTP/1.0 requests.
1379:                String host = this .params.getVirtualHost();
1380:                if (host != null) {
1381:                    LOG.debug("Using virtual host name: " + host);
1382:                } else {
1383:                    host = conn.getHost();
1384:                }
1385:                int port = conn.getPort();
1386:
1387:                // Note: RFC 2616 uses the term "internet host name" for what goes on the
1388:                // host line.  It would seem to imply that host should be blank if the
1389:                // host is a number instead of an name.  Based on the behavior of web
1390:                // browsers, and the fact that RFC 2616 never defines the phrase "internet
1391:                // host name", and the bad behavior of HttpClient that follows if we
1392:                // send blank, I interpret this as a small misstatement in the RFC, where
1393:                // they meant to say "internet host".  So IP numbers get sent as host
1394:                // entries too. -- Eric Johnson 12/13/2002
1395:                if (LOG.isDebugEnabled()) {
1396:                    LOG.debug("Adding Host request header");
1397:                }
1398:
1399:                //appends the port only if not using the default port for the protocol
1400:                if (conn.getProtocol().getDefaultPort() != port) {
1401:                    host += (":" + port);
1402:                }
1403:
1404:                setRequestHeader("Host", host);
1405:            }
1406:
1407:            /**
1408:             * Generates <tt>Proxy-Connection: Keep-Alive</tt> request header when 
1409:             * communicating via a proxy server.
1410:             *
1411:             * @param state the {@link HttpState state} information associated with this method
1412:             * @param conn the {@link HttpConnection connection} used to execute
1413:             *        this HTTP method
1414:             *
1415:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
1416:             *                     can be recovered from.
1417:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
1418:             *                    cannot be recovered from.
1419:             */
1420:            protected void addProxyConnectionHeader(HttpState state,
1421:                    HttpConnection conn) throws IOException, HttpException {
1422:                LOG.trace("enter HttpMethodBase.addProxyConnectionHeader("
1423:                        + "HttpState, HttpConnection)");
1424:                if (!conn.isTransparent()) {
1425:                    if (getRequestHeader("Proxy-Connection") == null) {
1426:                        addRequestHeader("Proxy-Connection", "Keep-Alive");
1427:                    }
1428:                }
1429:            }
1430:
1431:            /**
1432:             * Generates all the required request {@link Header header}s 
1433:             * to be submitted via the given {@link HttpConnection connection}.
1434:             *
1435:             * <p>
1436:             * This implementation adds <tt>User-Agent</tt>, <tt>Host</tt>,
1437:             * <tt>Cookie</tt>, <tt>Authorization</tt>, <tt>Proxy-Authorization</tt>
1438:             * and <tt>Proxy-Connection</tt> headers, when appropriate.
1439:             * </p>
1440:             *
1441:             * <p>
1442:             * Subclasses may want to override this method to to add additional
1443:             * headers, and may choose to invoke this implementation (via
1444:             * <tt>super</tt>) to add the "standard" headers.
1445:             * </p>
1446:             *
1447:             * @param state the {@link HttpState state} information associated with this method
1448:             * @param conn the {@link HttpConnection connection} used to execute
1449:             *        this HTTP method
1450:             *
1451:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
1452:             *                     can be recovered from.
1453:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
1454:             *                    cannot be recovered from.
1455:             *
1456:             * @see #writeRequestHeaders
1457:             */
1458:            protected void addRequestHeaders(HttpState state,
1459:                    HttpConnection conn) throws IOException, HttpException {
1460:                LOG.trace("enter HttpMethodBase.addRequestHeaders(HttpState, "
1461:                        + "HttpConnection)");
1462:
1463:                addUserAgentRequestHeader(state, conn);
1464:                addHostRequestHeader(state, conn);
1465:                addCookieRequestHeader(state, conn);
1466:                addProxyConnectionHeader(state, conn);
1467:            }
1468:
1469:            /**
1470:             * Generates default <tt>User-Agent</tt> request header, as long as no
1471:             * <tt>User-Agent</tt> request header already exists.
1472:             *
1473:             * @param state the {@link HttpState state} information associated with this method
1474:             * @param conn the {@link HttpConnection connection} used to execute
1475:             *        this HTTP method
1476:             *
1477:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
1478:             *                     can be recovered from.
1479:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
1480:             *                    cannot be recovered from.
1481:             */
1482:            protected void addUserAgentRequestHeader(HttpState state,
1483:                    HttpConnection conn) throws IOException, HttpException {
1484:                LOG
1485:                        .trace("enter HttpMethodBase.addUserAgentRequestHeaders(HttpState, "
1486:                                + "HttpConnection)");
1487:
1488:                if (getRequestHeader("User-Agent") == null) {
1489:                    String agent = (String) getParams().getParameter(
1490:                            HttpMethodParams.USER_AGENT);
1491:                    if (agent == null) {
1492:                        agent = "Jakarta Commons-HttpClient";
1493:                    }
1494:                    setRequestHeader("User-Agent", agent);
1495:                }
1496:            }
1497:
1498:            /**
1499:             * Throws an {@link IllegalStateException} if the HTTP method has been already
1500:             * {@link #execute executed}, but not {@link #recycle recycled}.
1501:             *
1502:             * @throws IllegalStateException if the method has been used and not
1503:             *      recycled
1504:             */
1505:            protected void checkNotUsed() throws IllegalStateException {
1506:                if (used) {
1507:                    throw new IllegalStateException("Already used.");
1508:                }
1509:            }
1510:
1511:            /**
1512:             * Throws an {@link IllegalStateException} if the HTTP method has not been
1513:             * {@link #execute executed} since last {@link #recycle recycle}.
1514:             *
1515:             *
1516:             * @throws IllegalStateException if not used
1517:             */
1518:            protected void checkUsed() throws IllegalStateException {
1519:                if (!used) {
1520:                    throw new IllegalStateException("Not Used.");
1521:                }
1522:            }
1523:
1524:            // ------------------------------------------------- Static Utility Methods
1525:
1526:            /**
1527:             * Generates HTTP request line according to the specified attributes.
1528:             *
1529:             * @param connection the {@link HttpConnection connection} used to execute
1530:             *        this HTTP method
1531:             * @param name the method name generate a request for
1532:             * @param requestPath the path string for the request
1533:             * @param query the query string for the request
1534:             * @param version the protocol version to use (e.g. HTTP/1.0)
1535:             *
1536:             * @return HTTP request line
1537:             */
1538:            protected static String generateRequestLine(
1539:                    HttpConnection connection, String name, String requestPath,
1540:                    String query, String version) {
1541:                LOG
1542:                        .trace("enter HttpMethodBase.generateRequestLine(HttpConnection, "
1543:                                + "String, String, String, String)");
1544:
1545:                StringBuffer buf = new StringBuffer();
1546:                // Append method name
1547:                buf.append(name);
1548:                buf.append(" ");
1549:                // Absolute or relative URL?
1550:                if (!connection.isTransparent()) {
1551:                    Protocol protocol = connection.getProtocol();
1552:                    buf.append(protocol.getScheme().toLowerCase());
1553:                    buf.append("://");
1554:                    buf.append(connection.getHost());
1555:                    if ((connection.getPort() != -1)
1556:                            && (connection.getPort() != protocol
1557:                                    .getDefaultPort())) {
1558:                        buf.append(":");
1559:                        buf.append(connection.getPort());
1560:                    }
1561:                }
1562:                // Append path, if any
1563:                if (requestPath == null) {
1564:                    buf.append("/");
1565:                } else {
1566:                    if (!connection.isTransparent()
1567:                            && !requestPath.startsWith("/")) {
1568:                        buf.append("/");
1569:                    }
1570:                    buf.append(requestPath);
1571:                }
1572:                // Append query, if any
1573:                if (query != null) {
1574:                    if (query.indexOf("?") != 0) {
1575:                        buf.append("?");
1576:                    }
1577:                    buf.append(query);
1578:                }
1579:                // Append protocol
1580:                buf.append(" ");
1581:                buf.append(version);
1582:                buf.append("\r\n");
1583:
1584:                return buf.toString();
1585:            }
1586:
1587:            /**
1588:             * This method is invoked immediately after 
1589:             * {@link #readResponseBody(HttpState,HttpConnection)} and can be overridden by
1590:             * sub-classes in order to provide custom body processing.
1591:             *
1592:             * <p>
1593:             * This implementation does nothing.
1594:             * </p>
1595:             *
1596:             * @param state the {@link HttpState state} information associated with this method
1597:             * @param conn the {@link HttpConnection connection} used to execute
1598:             *        this HTTP method
1599:             *
1600:             * @see #readResponse
1601:             * @see #readResponseBody
1602:             */
1603:            protected void processResponseBody(HttpState state,
1604:                    HttpConnection conn) {
1605:            }
1606:
1607:            /**
1608:             * This method is invoked immediately after 
1609:             * {@link #readResponseHeaders(HttpState,HttpConnection)} and can be overridden by
1610:             * sub-classes in order to provide custom response headers processing.
1611:
1612:             * <p>
1613:             * This implementation will handle the <tt>Set-Cookie</tt> and
1614:             * <tt>Set-Cookie2</tt> headers, if any, adding the relevant cookies to
1615:             * the given {@link HttpState}.
1616:             * </p>
1617:             *
1618:             * @param state the {@link HttpState state} information associated with this method
1619:             * @param conn the {@link HttpConnection connection} used to execute
1620:             *        this HTTP method
1621:             *
1622:             * @see #readResponse
1623:             * @see #readResponseHeaders
1624:             */
1625:            protected void processResponseHeaders(HttpState state,
1626:                    HttpConnection conn) {
1627:                LOG
1628:                        .trace("enter HttpMethodBase.processResponseHeaders(HttpState, "
1629:                                + "HttpConnection)");
1630:
1631:                CookieSpec parser = getCookieSpec(state);
1632:
1633:                // process set-cookie headers
1634:                Header[] headers = getResponseHeaderGroup().getHeaders(
1635:                        "set-cookie");
1636:                processCookieHeaders(parser, headers, state, conn);
1637:
1638:                // see if the cookie spec supports cookie versioning.
1639:                if (parser instanceof  CookieVersionSupport) {
1640:                    CookieVersionSupport versupport = (CookieVersionSupport) parser;
1641:                    if (versupport.getVersion() > 0) {
1642:                        // process set-cookie2 headers.
1643:                        // Cookie2 will replace equivalent Cookie instances
1644:                        headers = getResponseHeaderGroup().getHeaders(
1645:                                "set-cookie2");
1646:                        processCookieHeaders(parser, headers, state, conn);
1647:                    }
1648:                }
1649:            }
1650:
1651:            /**
1652:             * This method processes the specified cookie headers. It is invoked from
1653:             * within {@link #processResponseHeaders(HttpState,HttpConnection)}
1654:             *
1655:             * @param headers cookie {@link Header}s to be processed
1656:             * @param state the {@link HttpState state} information associated with
1657:             *        this HTTP method
1658:             * @param conn the {@link HttpConnection connection} used to execute
1659:             *        this HTTP method
1660:             */
1661:            protected void processCookieHeaders(final CookieSpec parser,
1662:                    final Header[] headers, final HttpState state,
1663:                    final HttpConnection conn) {
1664:                LOG
1665:                        .trace("enter HttpMethodBase.processCookieHeaders(Header[], HttpState, "
1666:                                + "HttpConnection)");
1667:
1668:                String host = this .params.getVirtualHost();
1669:                if (host == null) {
1670:                    host = conn.getHost();
1671:                }
1672:                for (int i = 0; i < headers.length; i++) {
1673:                    Header header = headers[i];
1674:                    Cookie[] cookies = null;
1675:                    try {
1676:                        cookies = parser.parse(host, conn.getPort(), getPath(),
1677:                                conn.isSecure(), header);
1678:                    } catch (MalformedCookieException e) {
1679:                        if (LOG.isWarnEnabled()) {
1680:                            LOG.warn("Invalid cookie header: \""
1681:                                    + header.getValue() + "\". "
1682:                                    + e.getMessage());
1683:                        }
1684:                    }
1685:                    if (cookies != null) {
1686:                        for (int j = 0; j < cookies.length; j++) {
1687:                            Cookie cookie = cookies[j];
1688:                            try {
1689:                                parser.validate(host, conn.getPort(),
1690:                                        getPath(), conn.isSecure(), cookie);
1691:                                state.addCookie(cookie);
1692:                                if (LOG.isDebugEnabled()) {
1693:                                    LOG.debug("Cookie accepted: \""
1694:                                            + parser.formatCookie(cookie)
1695:                                            + "\"");
1696:                                }
1697:                            } catch (MalformedCookieException e) {
1698:                                if (LOG.isWarnEnabled()) {
1699:                                    LOG.warn("Cookie rejected: \""
1700:                                            + parser.formatCookie(cookie)
1701:                                            + "\". " + e.getMessage());
1702:                                }
1703:                            }
1704:                        }
1705:                    }
1706:                }
1707:            }
1708:
1709:            /**
1710:             * This method is invoked immediately after 
1711:             * {@link #readStatusLine(HttpState,HttpConnection)} and can be overridden by
1712:             * sub-classes in order to provide custom response status line processing.
1713:             *
1714:             * @param state the {@link HttpState state} information associated with this method
1715:             * @param conn the {@link HttpConnection connection} used to execute
1716:             *        this HTTP method
1717:             *
1718:             * @see #readResponse
1719:             * @see #readStatusLine
1720:             */
1721:            protected void processStatusLine(HttpState state,
1722:                    HttpConnection conn) {
1723:            }
1724:
1725:            /**
1726:             * Reads the response from the given {@link HttpConnection connection}.
1727:             *
1728:             * <p>
1729:             * The response is processed as the following sequence of actions:
1730:             *
1731:             * <ol>
1732:             * <li>
1733:             * {@link #readStatusLine(HttpState,HttpConnection)} is
1734:             * invoked to read the request line.
1735:             * </li>
1736:             * <li>
1737:             * {@link #processStatusLine(HttpState,HttpConnection)}
1738:             * is invoked, allowing the method to process the status line if
1739:             * desired.
1740:             * </li>
1741:             * <li>
1742:             * {@link #readResponseHeaders(HttpState,HttpConnection)} is invoked to read
1743:             * the associated headers.
1744:             * </li>
1745:             * <li>
1746:             * {@link #processResponseHeaders(HttpState,HttpConnection)} is invoked, allowing
1747:             * the method to process the headers if desired.
1748:             * </li>
1749:             * <li>
1750:             * {@link #readResponseBody(HttpState,HttpConnection)} is
1751:             * invoked to read the associated body (if any).
1752:             * </li>
1753:             * <li>
1754:             * {@link #processResponseBody(HttpState,HttpConnection)} is invoked, allowing the
1755:             * method to process the response body if desired.
1756:             * </li>
1757:             * </ol>
1758:             *
1759:             * Subclasses may want to override one or more of the above methods to to
1760:             * customize the processing. (Or they may choose to override this method
1761:             * if dramatically different processing is required.)
1762:             * </p>
1763:             *
1764:             * @param state the {@link HttpState state} information associated with this method
1765:             * @param conn the {@link HttpConnection connection} used to execute
1766:             *        this HTTP method
1767:             *
1768:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
1769:             *                     can be recovered from.
1770:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
1771:             *                    cannot be recovered from.
1772:             */
1773:            protected void readResponse(HttpState state, HttpConnection conn)
1774:                    throws IOException, HttpException {
1775:                LOG
1776:                        .trace("enter HttpMethodBase.readResponse(HttpState, HttpConnection)");
1777:                // Status line & line may have already been received
1778:                // if 'expect - continue' handshake has been used
1779:                while (this .statusLine == null) {
1780:                    readStatusLine(state, conn);
1781:                    processStatusLine(state, conn);
1782:                    readResponseHeaders(state, conn);
1783:                    processResponseHeaders(state, conn);
1784:
1785:                    int status = this .statusLine.getStatusCode();
1786:                    if ((status >= 100) && (status < 200)) {
1787:                        if (LOG.isInfoEnabled()) {
1788:                            LOG.info("Discarding unexpected response: "
1789:                                    + this .statusLine.toString());
1790:                        }
1791:                        this .statusLine = null;
1792:                    }
1793:                }
1794:                readResponseBody(state, conn);
1795:                processResponseBody(state, conn);
1796:            }
1797:
1798:            /**
1799:             * Read the response body from the given {@link HttpConnection}.
1800:             *
1801:             * <p>
1802:             * The current implementation wraps the socket level stream with
1803:             * an appropriate stream for the type of response (chunked, content-length,
1804:             * or auto-close).  If there is no response body, the connection associated
1805:             * with the request will be returned to the connection manager.
1806:             * </p>
1807:             *
1808:             * <p>
1809:             * Subclasses may want to override this method to to customize the
1810:             * processing.
1811:             * </p>
1812:             *
1813:             * @param state the {@link HttpState state} information associated with this method
1814:             * @param conn the {@link HttpConnection connection} used to execute
1815:             *        this HTTP method
1816:             *
1817:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
1818:             *                     can be recovered from.
1819:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
1820:             *                    cannot be recovered from.
1821:             *
1822:             * @see #readResponse
1823:             * @see #processResponseBody
1824:             */
1825:            protected void readResponseBody(HttpState state, HttpConnection conn)
1826:                    throws IOException, HttpException {
1827:                LOG
1828:                        .trace("enter HttpMethodBase.readResponseBody(HttpState, HttpConnection)");
1829:
1830:                // assume we are not done with the connection if we get a stream
1831:                InputStream stream = readResponseBody(conn);
1832:                if (stream == null) {
1833:                    // done using the connection!
1834:                    responseBodyConsumed();
1835:                } else {
1836:                    conn.setLastResponseInputStream(stream);
1837:                    setResponseStream(stream);
1838:                }
1839:            }
1840:
1841:            /**
1842:             * Returns the response body as an {@link InputStream input stream}
1843:             * corresponding to the values of the <tt>Content-Length</tt> and 
1844:             * <tt>Transfer-Encoding</tt> headers. If no response body is available
1845:             * returns <tt>null</tt>.
1846:             * <p>
1847:             *
1848:             * @see #readResponse
1849:             * @see #processResponseBody
1850:             *
1851:             * @param conn the {@link HttpConnection connection} used to execute
1852:             *        this HTTP method
1853:             *
1854:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
1855:             *                     can be recovered from.
1856:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
1857:             *                    cannot be recovered from.
1858:             */
1859:            private InputStream readResponseBody(HttpConnection conn)
1860:                    throws HttpException, IOException {
1861:
1862:                LOG
1863:                        .trace("enter HttpMethodBase.readResponseBody(HttpConnection)");
1864:
1865:                responseBody = null;
1866:                InputStream is = conn.getResponseInputStream();
1867:                if (Wire.CONTENT_WIRE.enabled()) {
1868:                    is = new WireLogInputStream(is, Wire.CONTENT_WIRE);
1869:                }
1870:                boolean canHaveBody = canResponseHaveBody(statusLine
1871:                        .getStatusCode());
1872:                InputStream result = null;
1873:                Header transferEncodingHeader = responseHeaders
1874:                        .getFirstHeader("Transfer-Encoding");
1875:                // We use Transfer-Encoding if present and ignore Content-Length.
1876:                // RFC2616, 4.4 item number 3
1877:                if (transferEncodingHeader != null) {
1878:
1879:                    String transferEncoding = transferEncodingHeader.getValue();
1880:                    if (!"chunked".equalsIgnoreCase(transferEncoding)
1881:                            && !"identity".equalsIgnoreCase(transferEncoding)) {
1882:                        if (LOG.isWarnEnabled()) {
1883:                            LOG.warn("Unsupported transfer encoding: "
1884:                                    + transferEncoding);
1885:                        }
1886:                    }
1887:                    HeaderElement[] encodings = transferEncodingHeader
1888:                            .getElements();
1889:                    // The chunked encoding must be the last one applied
1890:                    // RFC2616, 14.41
1891:                    int len = encodings.length;
1892:                    if ((len > 0)
1893:                            && ("chunked".equalsIgnoreCase(encodings[len - 1]
1894:                                    .getName()))) {
1895:                        // if response body is empty
1896:                        if (conn.isResponseAvailable(conn.getParams()
1897:                                .getSoTimeout())) {
1898:                            result = new ChunkedInputStream(is, this );
1899:                        } else {
1900:                            if (getParams().isParameterTrue(
1901:                                    HttpMethodParams.STRICT_TRANSFER_ENCODING)) {
1902:                                throw new ProtocolException(
1903:                                        "Chunk-encoded body declared but not sent");
1904:                            } else {
1905:                                LOG.warn("Chunk-encoded body missing");
1906:                            }
1907:                        }
1908:                    } else {
1909:                        LOG.info("Response content is not chunk-encoded");
1910:                        // The connection must be terminated by closing 
1911:                        // the socket as per RFC 2616, 3.6
1912:                        setConnectionCloseForced(true);
1913:                        result = is;
1914:                    }
1915:                } else {
1916:                    long expectedLength = getResponseContentLength();
1917:                    if (expectedLength == -1) {
1918:                        if (canHaveBody
1919:                                && this .effectiveVersion
1920:                                        .greaterEquals(HttpVersion.HTTP_1_1)) {
1921:                            Header connectionHeader = responseHeaders
1922:                                    .getFirstHeader("Connection");
1923:                            String connectionDirective = null;
1924:                            if (connectionHeader != null) {
1925:                                connectionDirective = connectionHeader
1926:                                        .getValue();
1927:                            }
1928:                            if (!"close".equalsIgnoreCase(connectionDirective)) {
1929:                                LOG
1930:                                        .info("Response content length is not known");
1931:                                setConnectionCloseForced(true);
1932:                            }
1933:                        }
1934:                        result = is;
1935:                    } else {
1936:                        result = new ContentLengthInputStream(is,
1937:                                expectedLength);
1938:                    }
1939:                }
1940:
1941:                // See if the response is supposed to have a response body
1942:                if (!canHaveBody) {
1943:                    result = null;
1944:                }
1945:                // if there is a result - ALWAYS wrap it in an observer which will
1946:                // close the underlying stream as soon as it is consumed, and notify
1947:                // the watcher that the stream has been consumed.
1948:                if (result != null) {
1949:
1950:                    result = new AutoCloseInputStream(result,
1951:                            new ResponseConsumedWatcher() {
1952:                                public void responseConsumed() {
1953:                                    responseBodyConsumed();
1954:                                }
1955:                            });
1956:                }
1957:
1958:                return result;
1959:            }
1960:
1961:            /**
1962:             * Reads the response headers from the given {@link HttpConnection connection}.
1963:             *
1964:             * <p>
1965:             * Subclasses may want to override this method to to customize the
1966:             * processing.
1967:             * </p>
1968:             *
1969:             * <p>
1970:             * "It must be possible to combine the multiple header fields into one
1971:             * "field-name: field-value" pair, without changing the semantics of the
1972:             * message, by appending each subsequent field-value to the first, each
1973:             * separated by a comma." - HTTP/1.0 (4.3)
1974:             * </p>
1975:             *
1976:             * @param state the {@link HttpState state} information associated with this method
1977:             * @param conn the {@link HttpConnection connection} used to execute
1978:             *        this HTTP method
1979:             *
1980:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
1981:             *                     can be recovered from.
1982:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
1983:             *                    cannot be recovered from.
1984:             *
1985:             * @see #readResponse
1986:             * @see #processResponseHeaders
1987:             */
1988:            protected void readResponseHeaders(HttpState state,
1989:                    HttpConnection conn) throws IOException, HttpException {
1990:                LOG.trace("enter HttpMethodBase.readResponseHeaders(HttpState,"
1991:                        + "HttpConnection)");
1992:
1993:                getResponseHeaderGroup().clear();
1994:
1995:                Header[] headers = HttpParser.parseHeaders(conn
1996:                        .getResponseInputStream(), getParams()
1997:                        .getHttpElementCharset());
1998:                // Wire logging moved to HttpParser
1999:                getResponseHeaderGroup().setHeaders(headers);
2000:            }
2001:
2002:            /**
2003:             * Read the status line from the given {@link HttpConnection}, setting my
2004:             * {@link #getStatusCode status code} and {@link #getStatusText status
2005:             * text}.
2006:             *
2007:             * <p>
2008:             * Subclasses may want to override this method to to customize the
2009:             * processing.
2010:             * </p>
2011:             *
2012:             * @param state the {@link HttpState state} information associated with this method
2013:             * @param conn the {@link HttpConnection connection} used to execute
2014:             *        this HTTP method
2015:             *
2016:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
2017:             *                     can be recovered from.
2018:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
2019:             *                    cannot be recovered from.
2020:             *
2021:             * @see StatusLine
2022:             */
2023:            protected void readStatusLine(HttpState state, HttpConnection conn)
2024:                    throws IOException, HttpException {
2025:                LOG
2026:                        .trace("enter HttpMethodBase.readStatusLine(HttpState, HttpConnection)");
2027:
2028:                final int maxGarbageLines = getParams().getIntParameter(
2029:                        HttpMethodParams.STATUS_LINE_GARBAGE_LIMIT,
2030:                        Integer.MAX_VALUE);
2031:
2032:                //read out the HTTP status string
2033:                int count = 0;
2034:                String s;
2035:                do {
2036:                    s = conn.readLine(getParams().getHttpElementCharset());
2037:                    if (s == null && count == 0) {
2038:                        // The server just dropped connection on us
2039:                        throw new NoHttpResponseException("The server "
2040:                                + conn.getHost() + " failed to respond");
2041:                    }
2042:                    if (Wire.HEADER_WIRE.enabled()) {
2043:                        Wire.HEADER_WIRE.input(s + "\r\n");
2044:                    }
2045:                    if (s != null && StatusLine.startsWithHTTP(s)) {
2046:                        // Got one
2047:                        break;
2048:                    } else if (s == null || count >= maxGarbageLines) {
2049:                        // Giving up
2050:                        throw new ProtocolException(
2051:                                "The server "
2052:                                        + conn.getHost()
2053:                                        + " failed to respond with a valid HTTP response");
2054:                    }
2055:                    count++;
2056:                } while (true);
2057:
2058:                //create the status line from the status string
2059:                statusLine = new StatusLine(s);
2060:
2061:                //check for a valid HTTP-Version
2062:                String versionStr = statusLine.getHttpVersion();
2063:                if (getParams().isParameterFalse(
2064:                        HttpMethodParams.UNAMBIGUOUS_STATUS_LINE)
2065:                        && versionStr.equals("HTTP")) {
2066:                    getParams().setVersion(HttpVersion.HTTP_1_0);
2067:                    if (LOG.isWarnEnabled()) {
2068:                        LOG
2069:                                .warn("Ambiguous status line (HTTP protocol version missing):"
2070:                                        + statusLine.toString());
2071:                    }
2072:                } else {
2073:                    this .effectiveVersion = HttpVersion.parse(versionStr);
2074:                }
2075:
2076:            }
2077:
2078:            // ------------------------------------------------------ Protected Methods
2079:
2080:            /**
2081:             * <p>
2082:             * Sends the request via the given {@link HttpConnection connection}.
2083:             * </p>
2084:             *
2085:             * <p>
2086:             * The request is written as the following sequence of actions:
2087:             * </p>
2088:             *
2089:             * <ol>
2090:             * <li>
2091:             * {@link #writeRequestLine(HttpState, HttpConnection)} is invoked to 
2092:             * write the request line.
2093:             * </li>
2094:             * <li>
2095:             * {@link #writeRequestHeaders(HttpState, HttpConnection)} is invoked 
2096:             * to write the associated headers.
2097:             * </li>
2098:             * <li>
2099:             * <tt>\r\n</tt> is sent to close the head part of the request.
2100:             * </li>
2101:             * <li>
2102:             * {@link #writeRequestBody(HttpState, HttpConnection)} is invoked to 
2103:             * write the body part of the request.
2104:             * </li>
2105:             * </ol>
2106:             *
2107:             * <p>
2108:             * Subclasses may want to override one or more of the above methods to to
2109:             * customize the processing. (Or they may choose to override this method
2110:             * if dramatically different processing is required.)
2111:             * </p>
2112:             *
2113:             * @param state the {@link HttpState state} information associated with this method
2114:             * @param conn the {@link HttpConnection connection} used to execute
2115:             *        this HTTP method
2116:             *
2117:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
2118:             *                     can be recovered from.
2119:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
2120:             *                    cannot be recovered from.
2121:             */
2122:            protected void writeRequest(HttpState state, HttpConnection conn)
2123:                    throws IOException, HttpException {
2124:                LOG
2125:                        .trace("enter HttpMethodBase.writeRequest(HttpState, HttpConnection)");
2126:                writeRequestLine(state, conn);
2127:                writeRequestHeaders(state, conn);
2128:                conn.writeLine(); // close head
2129:                if (Wire.HEADER_WIRE.enabled()) {
2130:                    Wire.HEADER_WIRE.output("\r\n");
2131:                }
2132:
2133:                HttpVersion ver = getParams().getVersion();
2134:                Header expectheader = getRequestHeader("Expect");
2135:                String expectvalue = null;
2136:                if (expectheader != null) {
2137:                    expectvalue = expectheader.getValue();
2138:                }
2139:                if ((expectvalue != null)
2140:                        && (expectvalue.compareToIgnoreCase("100-continue") == 0)) {
2141:                    if (ver.greaterEquals(HttpVersion.HTTP_1_1)) {
2142:
2143:                        // make sure the status line and headers have been sent
2144:                        conn.flushRequestOutputStream();
2145:
2146:                        int readTimeout = conn.getParams().getSoTimeout();
2147:                        try {
2148:                            conn.setSocketTimeout(RESPONSE_WAIT_TIME_MS);
2149:                            readStatusLine(state, conn);
2150:                            processStatusLine(state, conn);
2151:                            readResponseHeaders(state, conn);
2152:                            processResponseHeaders(state, conn);
2153:
2154:                            if (this .statusLine.getStatusCode() == HttpStatus.SC_CONTINUE) {
2155:                                // Discard status line
2156:                                this .statusLine = null;
2157:                                LOG.debug("OK to continue received");
2158:                            } else {
2159:                                return;
2160:                            }
2161:                        } catch (InterruptedIOException e) {
2162:                            if (!ExceptionUtil.isSocketTimeoutException(e)) {
2163:                                throw e;
2164:                            }
2165:                            // Most probably Expect header is not recongnized
2166:                            // Remove the header to signal the method 
2167:                            // that it's okay to go ahead with sending data
2168:                            removeRequestHeader("Expect");
2169:                            LOG
2170:                                    .info("100 (continue) read timeout. Resume sending the request");
2171:                        } finally {
2172:                            conn.setSocketTimeout(readTimeout);
2173:                        }
2174:
2175:                    } else {
2176:                        removeRequestHeader("Expect");
2177:                        LOG
2178:                                .info("'Expect: 100-continue' handshake is only supported by "
2179:                                        + "HTTP/1.1 or higher");
2180:                    }
2181:                }
2182:
2183:                writeRequestBody(state, conn);
2184:                // make sure the entire request body has been sent
2185:                conn.flushRequestOutputStream();
2186:            }
2187:
2188:            /**
2189:             * Writes the request body to the given {@link HttpConnection connection}.
2190:             *
2191:             * <p>
2192:             * This method should return <tt>true</tt> if the request body was actually
2193:             * sent (or is empty), or <tt>false</tt> if it could not be sent for some
2194:             * reason.
2195:             * </p>
2196:             *
2197:             * <p>
2198:             * This implementation writes nothing and returns <tt>true</tt>.
2199:             * </p>
2200:             *
2201:             * @param state the {@link HttpState state} information associated with this method
2202:             * @param conn the {@link HttpConnection connection} used to execute
2203:             *        this HTTP method
2204:             *
2205:             * @return <tt>true</tt>
2206:             *
2207:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
2208:             *                     can be recovered from.
2209:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
2210:             *                    cannot be recovered from.
2211:             */
2212:            protected boolean writeRequestBody(HttpState state,
2213:                    HttpConnection conn) throws IOException, HttpException {
2214:                return true;
2215:            }
2216:
2217:            /**
2218:             * Writes the request headers to the given {@link HttpConnection connection}.
2219:             *
2220:             * <p>
2221:             * This implementation invokes {@link #addRequestHeaders(HttpState,HttpConnection)},
2222:             * and then writes each header to the request stream.
2223:             * </p>
2224:             *
2225:             * <p>
2226:             * Subclasses may want to override this method to to customize the
2227:             * processing.
2228:             * </p>
2229:             *
2230:             * @param state the {@link HttpState state} information associated with this method
2231:             * @param conn the {@link HttpConnection connection} used to execute
2232:             *        this HTTP method
2233:             *
2234:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
2235:             *                     can be recovered from.
2236:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
2237:             *                    cannot be recovered from.
2238:             *
2239:             * @see #addRequestHeaders
2240:             * @see #getRequestHeaders
2241:             */
2242:            protected void writeRequestHeaders(HttpState state,
2243:                    HttpConnection conn) throws IOException, HttpException {
2244:                LOG.trace("enter HttpMethodBase.writeRequestHeaders(HttpState,"
2245:                        + "HttpConnection)");
2246:                addRequestHeaders(state, conn);
2247:
2248:                String charset = getParams().getHttpElementCharset();
2249:
2250:                Header[] headers = getRequestHeaders();
2251:                for (int i = 0; i < headers.length; i++) {
2252:                    String s = headers[i].toExternalForm();
2253:                    if (Wire.HEADER_WIRE.enabled()) {
2254:                        Wire.HEADER_WIRE.output(s);
2255:                    }
2256:                    conn.print(s, charset);
2257:                }
2258:            }
2259:
2260:            /**
2261:             * Writes the request line to the given {@link HttpConnection connection}.
2262:             *
2263:             * <p>
2264:             * Subclasses may want to override this method to to customize the
2265:             * processing.
2266:             * </p>
2267:             *
2268:             * @param state the {@link HttpState state} information associated with this method
2269:             * @param conn the {@link HttpConnection connection} used to execute
2270:             *        this HTTP method
2271:             *
2272:             * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
2273:             *                     can be recovered from.
2274:             * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
2275:             *                    cannot be recovered from.
2276:             *
2277:             * @see #generateRequestLine
2278:             */
2279:            protected void writeRequestLine(HttpState state, HttpConnection conn)
2280:                    throws IOException, HttpException {
2281:                LOG
2282:                        .trace("enter HttpMethodBase.writeRequestLine(HttpState, HttpConnection)");
2283:                String requestLine = getRequestLine(conn);
2284:                if (Wire.HEADER_WIRE.enabled()) {
2285:                    Wire.HEADER_WIRE.output(requestLine);
2286:                }
2287:                conn.print(requestLine, getParams().getHttpElementCharset());
2288:            }
2289:
2290:            /**
2291:             * Returns the request line.
2292:             * 
2293:             * @param conn the {@link HttpConnection connection} used to execute
2294:             *        this HTTP method
2295:             * 
2296:             * @return The request line.
2297:             */
2298:            private String getRequestLine(HttpConnection conn) {
2299:                return HttpMethodBase.generateRequestLine(conn, getName(),
2300:                        getPath(), getQueryString(), this .effectiveVersion
2301:                                .toString());
2302:            }
2303:
2304:            /**
2305:             * Returns {@link HttpMethodParams HTTP protocol parameters} associated with this method.
2306:             *
2307:             * @return HTTP parameters.
2308:             *
2309:             * @since 3.0
2310:             */
2311:            public HttpMethodParams getParams() {
2312:                return this .params;
2313:            }
2314:
2315:            /**
2316:             * Assigns {@link HttpMethodParams HTTP protocol parameters} for this method.
2317:             * 
2318:             * @since 3.0
2319:             * 
2320:             * @see HttpMethodParams
2321:             */
2322:            public void setParams(final HttpMethodParams params) {
2323:                if (params == null) {
2324:                    throw new IllegalArgumentException(
2325:                            "Parameters may not be null");
2326:                }
2327:                this .params = params;
2328:            }
2329:
2330:            /**
2331:             * Returns the HTTP version used with this method (may be <tt>null</tt>
2332:             * if undefined, that is, the method has not been executed)
2333:             *
2334:             * @return HTTP version.
2335:             *
2336:             * @since 3.0
2337:             */
2338:            public HttpVersion getEffectiveVersion() {
2339:                return this .effectiveVersion;
2340:            }
2341:
2342:            /**
2343:             * Per RFC 2616 section 4.3, some response can never contain a message
2344:             * body.
2345:             *
2346:             * @param status - the HTTP status code
2347:             *
2348:             * @return <tt>true</tt> if the message may contain a body, <tt>false</tt> if it can not
2349:             *         contain a message body
2350:             */
2351:            private static boolean canResponseHaveBody(int status) {
2352:                LOG.trace("enter HttpMethodBase.canResponseHaveBody(int)");
2353:
2354:                boolean result = true;
2355:
2356:                if ((status >= 100 && status <= 199) || (status == 204)
2357:                        || (status == 304)) { // NOT MODIFIED
2358:                    result = false;
2359:                }
2360:
2361:                return result;
2362:            }
2363:
2364:            /**
2365:             * Returns proxy authentication realm, if it has been used during authentication process. 
2366:             * Otherwise returns <tt>null</tt>.
2367:             * 
2368:             * @return proxy authentication realm
2369:             * 
2370:             * @deprecated use #getProxyAuthState()
2371:             */
2372:            public String getProxyAuthenticationRealm() {
2373:                return this .proxyAuthState.getRealm();
2374:            }
2375:
2376:            /**
2377:             * Returns authentication realm, if it has been used during authentication process. 
2378:             * Otherwise returns <tt>null</tt>.
2379:             * 
2380:             * @return authentication realm
2381:             * 
2382:             * @deprecated use #getHostAuthState()
2383:             */
2384:            public String getAuthenticationRealm() {
2385:                return this .hostAuthState.getRealm();
2386:            }
2387:
2388:            /**
2389:             * Returns the character set from the <tt>Content-Type</tt> header.
2390:             * 
2391:             * @param contentheader The content header.
2392:             * @return String The character set.
2393:             */
2394:            protected String getContentCharSet(Header contentheader) {
2395:                LOG.trace("enter getContentCharSet( Header contentheader )");
2396:                String charset = null;
2397:                if (contentheader != null) {
2398:                    HeaderElement values[] = contentheader.getElements();
2399:                    // I expect only one header element to be there
2400:                    // No more. no less
2401:                    if (values.length == 1) {
2402:                        NameValuePair param = values[0]
2403:                                .getParameterByName("charset");
2404:                        if (param != null) {
2405:                            // If I get anything "funny" 
2406:                            // UnsupportedEncondingException will result
2407:                            charset = param.getValue();
2408:                        }
2409:                    }
2410:                }
2411:                if (charset == null) {
2412:                    charset = getParams().getContentCharset();
2413:                    if (LOG.isDebugEnabled()) {
2414:                        LOG.debug("Default charset used: " + charset);
2415:                    }
2416:                }
2417:                return charset;
2418:            }
2419:
2420:            /**
2421:             * Returns the character encoding of the request from the <tt>Content-Type</tt> header.
2422:             * 
2423:             * @return String The character set.
2424:             */
2425:            public String getRequestCharSet() {
2426:                return getContentCharSet(getRequestHeader("Content-Type"));
2427:            }
2428:
2429:            /**  
2430:             * Returns the character encoding of the response from the <tt>Content-Type</tt> header.
2431:             * 
2432:             * @return String The character set.
2433:             */
2434:            public String getResponseCharSet() {
2435:                return getContentCharSet(getResponseHeader("Content-Type"));
2436:            }
2437:
2438:            /**
2439:             * @deprecated no longer used
2440:             * 
2441:             * Returns the number of "recoverable" exceptions thrown and handled, to
2442:             * allow for monitoring the quality of the connection.
2443:             *
2444:             * @return The number of recoverable exceptions handled by the method.
2445:             */
2446:            public int getRecoverableExceptionCount() {
2447:                return recoverableExceptionCount;
2448:            }
2449:
2450:            /**
2451:             * A response has been consumed.
2452:             *
2453:             * <p>The default behavior for this class is to check to see if the connection
2454:             * should be closed, and close if need be, and to ensure that the connection
2455:             * is returned to the connection manager - if and only if we are not still
2456:             * inside the execute call.</p>
2457:             *
2458:             */
2459:            protected void responseBodyConsumed() {
2460:
2461:                // make sure this is the initial invocation of the notification,
2462:                // ignore subsequent ones.
2463:                responseStream = null;
2464:                if (responseConnection != null) {
2465:                    responseConnection.setLastResponseInputStream(null);
2466:
2467:                    // At this point, no response data should be available.
2468:                    // If there is data available, regard the connection as being
2469:                    // unreliable and close it.
2470:
2471:                    if (shouldCloseConnection(responseConnection)) {
2472:                        responseConnection.close();
2473:                    } else {
2474:                        try {
2475:                            if (responseConnection.isResponseAvailable()) {
2476:                                boolean logExtraInput = getParams()
2477:                                        .isParameterTrue(
2478:                                                HttpMethodParams.WARN_EXTRA_INPUT);
2479:
2480:                                if (logExtraInput) {
2481:                                    LOG
2482:                                            .warn("Extra response data detected - closing connection");
2483:                                }
2484:                                responseConnection.close();
2485:                            }
2486:                        } catch (IOException e) {
2487:                            LOG.warn(e.getMessage());
2488:                            responseConnection.close();
2489:                        }
2490:                    }
2491:                }
2492:                this .connectionCloseForced = false;
2493:                ensureConnectionRelease();
2494:            }
2495:
2496:            /**
2497:             * Insure that the connection is released back to the pool.
2498:             */
2499:            private void ensureConnectionRelease() {
2500:                if (responseConnection != null) {
2501:                    responseConnection.releaseConnection();
2502:                    responseConnection = null;
2503:                }
2504:            }
2505:
2506:            /**
2507:             * Returns the {@link HostConfiguration host configuration}.
2508:             * 
2509:             * @return the host configuration
2510:             * 
2511:             * @deprecated no longer applicable
2512:             */
2513:            public HostConfiguration getHostConfiguration() {
2514:                HostConfiguration hostconfig = new HostConfiguration();
2515:                hostconfig.setHost(this .httphost);
2516:                return hostconfig;
2517:            }
2518:
2519:            /**
2520:             * Sets the {@link HostConfiguration host configuration}.
2521:             * 
2522:             * @param hostconfig The hostConfiguration to set
2523:             * 
2524:             * @deprecated no longer applicable
2525:             */
2526:            public void setHostConfiguration(final HostConfiguration hostconfig) {
2527:                if (hostconfig != null) {
2528:                    this .httphost = new HttpHost(hostconfig.getHost(),
2529:                            hostconfig.getPort(), hostconfig.getProtocol());
2530:                } else {
2531:                    this .httphost = null;
2532:                }
2533:            }
2534:
2535:            /**
2536:             * Returns the {@link MethodRetryHandler retry handler} for this HTTP method
2537:             * 
2538:             * @return the methodRetryHandler
2539:             * 
2540:             * @deprecated use {@link HttpMethodParams}
2541:             */
2542:            public MethodRetryHandler getMethodRetryHandler() {
2543:                return methodRetryHandler;
2544:            }
2545:
2546:            /**
2547:             * Sets the {@link MethodRetryHandler retry handler} for this HTTP method
2548:             * 
2549:             * @param handler the methodRetryHandler to use when this method executed
2550:             * 
2551:             * @deprecated use {@link HttpMethodParams}
2552:             */
2553:            public void setMethodRetryHandler(MethodRetryHandler handler) {
2554:                methodRetryHandler = handler;
2555:            }
2556:
2557:            /**
2558:             * This method is a dirty hack intended to work around 
2559:             * current (2.0) design flaw that prevents the user from
2560:             * obtaining correct status code, headers and response body from the 
2561:             * preceding HTTP CONNECT method.
2562:             * 
2563:             * TODO: Remove this crap as soon as possible
2564:             */
2565:            void fakeResponse(StatusLine statusline,
2566:                    HeaderGroup responseheaders, InputStream responseStream) {
2567:                // set used so that the response can be read
2568:                this .used = true;
2569:                this .statusLine = statusline;
2570:                this .responseHeaders = responseheaders;
2571:                this .responseBody = null;
2572:                this .responseStream = responseStream;
2573:            }
2574:
2575:            /**
2576:             * Returns the target host {@link AuthState authentication state}
2577:             * 
2578:             * @return host authentication state
2579:             * 
2580:             * @since 3.0
2581:             */
2582:            public AuthState getHostAuthState() {
2583:                return this .hostAuthState;
2584:            }
2585:
2586:            /**
2587:             * Returns the proxy {@link AuthState authentication state}
2588:             * 
2589:             * @return host authentication state
2590:             * 
2591:             * @since 3.0
2592:             */
2593:            public AuthState getProxyAuthState() {
2594:                return this .proxyAuthState;
2595:            }
2596:
2597:            /**
2598:             * Tests whether the execution of this method has been aborted
2599:             * 
2600:             * @return <tt>true</tt> if the execution of this method has been aborted,
2601:             *  <tt>false</tt> otherwise
2602:             * 
2603:             * @since 3.0
2604:             */
2605:            public boolean isAborted() {
2606:                return this .aborted;
2607:            }
2608:
2609:            /**
2610:             * Returns <tt>true</tt> if the HTTP has been transmitted to the target
2611:             * server in its entirety, <tt>false</tt> otherwise. This flag can be useful 
2612:             * for recovery logic. If the request has not been transmitted in its entirety,
2613:             * it is safe to retry the failed method.
2614:             * 
2615:             * @return <tt>true</tt> if the request has been sent, <tt>false</tt> otherwise
2616:             */
2617:            public boolean isRequestSent() {
2618:                return this.requestSent;
2619:            }
2620:
2621:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.