Index: httpcore/module-main/src/test/java/org/apache/http/protocol/TestStandardInterceptors.java =================================================================== --- httpcore/module-main/src/test/java/org/apache/http/protocol/TestStandardInterceptors.java (revision 505702) +++ httpcore/module-main/src/test/java/org/apache/http/protocol/TestStandardInterceptors.java (working copy) @@ -444,7 +444,7 @@ public void testResponseConnControlNoEntity() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); ResponseConnControl interceptor = new ResponseConnControl(); interceptor.process(response, context); Header header = response.getFirstHeader(HTTP.CONN_DIRECTIVE); @@ -453,7 +453,7 @@ public void testResponseConnControlEntityContentLength() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); StringEntity entity = new StringEntity("whatever"); response.setEntity(entity); ResponseConnControl interceptor = new ResponseConnControl(); @@ -467,7 +467,7 @@ BasicHttpRequest request = new BasicHttpRequest("GET", "/"); request.addHeader(new BasicHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE)); context.setAttribute(HttpExecutionContext.HTTP_REQUEST, request); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); BasicHttpEntity entity = new BasicHttpEntity(); response.setEntity(entity); ResponseConnControl interceptor = new ResponseConnControl(); @@ -479,7 +479,7 @@ public void testResponseConnControlEntityChunked() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); BasicHttpEntity entity = new BasicHttpEntity(); entity.setChunked(true); response.setEntity(entity); @@ -496,7 +496,7 @@ context.setAttribute(HttpExecutionContext.HTTP_REQUEST, request); BasicHttpResponse response = new BasicHttpResponse( - HttpVersion.HTTP_1_0, HttpStatus.SC_OK); + HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); BasicHttpEntity entity = new BasicHttpEntity(); response.setEntity(entity); ResponseConnControl interceptor = new ResponseConnControl(); @@ -512,7 +512,7 @@ request.addHeader(new BasicHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE)); context.setAttribute(HttpExecutionContext.HTTP_REQUEST, request); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); StringEntity entity = new StringEntity("whatever"); response.setEntity(entity); ResponseConnControl interceptor = new ResponseConnControl(); @@ -527,7 +527,7 @@ BasicHttpRequest request = new BasicHttpRequest("GET", "/"); context.setAttribute(HttpExecutionContext.HTTP_REQUEST, request); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); StringEntity entity = new StringEntity("whatever"); response.setEntity(entity); ResponseConnControl interceptor = new ResponseConnControl(); @@ -556,7 +556,7 @@ for (int i = 0; i < statusCodes.length; i++) { BasicHttpResponse response = new BasicHttpResponse( - HttpVersion.HTTP_1_1, statusCodes[i]); + HttpVersion.HTTP_1_1, statusCodes[i], "Unreasonable"); interceptor.process(response, context); Header header = response.getFirstHeader(HTTP.CONN_DIRECTIVE); assertNotNull(header); @@ -574,7 +574,7 @@ // expected } try { - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); interceptor.process(response, null); fail("IllegalArgumentException should have been thrown"); } catch (IllegalArgumentException ex) { @@ -584,7 +584,7 @@ public void testResponseContentNoEntity() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); ResponseContent interceptor = new ResponseContent(); interceptor.process(response, context); Header header = response.getFirstHeader(HTTP.CONTENT_LEN); @@ -594,7 +594,7 @@ public void testResponseContentStatusNoContent() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); response.setStatusCode(HttpStatus.SC_NO_CONTENT); ResponseContent interceptor = new ResponseContent(); interceptor.process(response, context); @@ -604,7 +604,7 @@ public void testResponseContentStatusResetContent() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); response.setStatusCode(HttpStatus.SC_RESET_CONTENT); ResponseContent interceptor = new ResponseContent(); interceptor.process(response, context); @@ -614,7 +614,7 @@ public void testResponseContentStatusNotModified() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); response.setStatusCode(HttpStatus.SC_NOT_MODIFIED); ResponseContent interceptor = new ResponseContent(); interceptor.process(response, context); @@ -624,7 +624,7 @@ public void testResponseContentEntityChunked() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); BasicHttpEntity entity = new BasicHttpEntity(); entity.setChunked(true); response.setEntity(entity); @@ -639,7 +639,7 @@ public void testResponseContentEntityContentLenghtDelimited() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); BasicHttpEntity entity = new BasicHttpEntity(); entity.setContentLength (10); response.setEntity(entity); @@ -654,7 +654,7 @@ public void testResponseContentEntityUnknownContentLength() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); BasicHttpEntity entity = new BasicHttpEntity(); response.setEntity(entity); ResponseContent interceptor = new ResponseContent(); @@ -667,7 +667,7 @@ public void testResponseContentEntityChunkedHTTP10() throws Exception { HttpContext context = new HttpExecutionContext(null); - BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK); + BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_OK, "OK"); BasicHttpEntity entity = new BasicHttpEntity(); entity.setChunked(true); response.setEntity(entity); @@ -681,7 +681,7 @@ public void testResponseContentEntityNoContentTypeAndEncoding() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); BasicHttpEntity entity = new BasicHttpEntity(); response.setEntity(entity); ResponseContent interceptor = new ResponseContent(); @@ -694,7 +694,7 @@ public void testResponseContentEntityContentTypeAndEncoding() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); BasicHttpEntity entity = new BasicHttpEntity(); entity.setContentEncoding("whatever"); entity.setContentType("whatever"); @@ -723,7 +723,7 @@ ResponseContent interceptor = new ResponseContent(); HttpContext context = new HttpExecutionContext(null); try { - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); response.addHeader(new BasicHeader(HTTP.CONTENT_LEN, "10")); interceptor.process(response, context); fail("ProtocolException should have been thrown"); @@ -731,7 +731,7 @@ // expected } try { - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); response.addHeader(new BasicHeader(HTTP.TRANSFER_ENCODING, "stuff")); interceptor.process(response, context); fail("ProtocolException should have been thrown"); @@ -742,7 +742,7 @@ public void testResponseDateGenerated() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); ResponseDate interceptor = new ResponseDate(); interceptor.process(response, context); Header h1 = response.getFirstHeader(HTTP.DATE_DIRECTIVE); @@ -754,7 +754,7 @@ public void testResponseDateNotGenerated() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); response.setStatusCode(199); ResponseDate interceptor = new ResponseDate(); interceptor.process(response, context); @@ -774,7 +774,7 @@ public void testResponseServerGenerated() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); response.getParams().setParameter(HttpProtocolParams.ORIGIN_SERVER, "some server"); ResponseServer interceptor = new ResponseServer(); interceptor.process(response, context); @@ -785,7 +785,7 @@ public void testResponseServerNotGenerated() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); response.getParams().setParameter(HttpProtocolParams.ORIGIN_SERVER, "some server"); response.addHeader(new BasicHeader(HTTP.SERVER_DIRECTIVE, "whatever")); ResponseServer interceptor = new ResponseServer(); @@ -797,7 +797,7 @@ public void testResponseServerMissing() throws Exception { HttpContext context = new HttpExecutionContext(null); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); ResponseServer interceptor = new ResponseServer(); interceptor.process(response, context); Header h1 = response.getFirstHeader(HTTP.SERVER_DIRECTIVE); Index: httpcore/module-main/src/test/java/org/apache/http/message/TestBasicMessages.java =================================================================== --- httpcore/module-main/src/test/java/org/apache/http/message/TestBasicMessages.java (revision 505702) +++ httpcore/module-main/src/test/java/org/apache/http/message/TestBasicMessages.java (working copy) @@ -66,7 +66,7 @@ } public void testDefaultResponseConstructors() { - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_BAD_REQUEST); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_BAD_REQUEST, "Bad Request"); assertNotNull(response.getHttpVersion()); assertEquals(HttpVersion.HTTP_1_0, response.getHttpVersion()); assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusLine().getStatusCode()); @@ -80,12 +80,12 @@ } public void testSetResponseStatus() { - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK"); assertNotNull(response.getHttpVersion()); assertNotNull(response.getStatusLine()); assertEquals(200, response.getStatusLine().getStatusCode()); - response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_BAD_REQUEST); + response = new BasicHttpResponse(HttpVersion.HTTP_1_0, HttpStatus.SC_BAD_REQUEST, "Bad Request"); assertNotNull(response.getHttpVersion()); assertEquals(HttpVersion.HTTP_1_0, response.getHttpVersion()); assertEquals(HttpStatus.SC_BAD_REQUEST, response.getStatusLine().getStatusCode()); @@ -97,21 +97,21 @@ assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatusLine().getStatusCode()); assertEquals("whatever", response.getStatusLine().getReasonPhrase()); - response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); try { response.setStatusCode(-23); fail("IllegalArgumentException should have been thrown"); } catch (IllegalArgumentException ex) { // expected } - response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); try { response.setStatusLine(null, 200); fail("IllegalArgumentException should have been thrown"); } catch (IllegalArgumentException ex) { // expected } - response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); try { response.setStatusLine(null); fail("IllegalArgumentException should have been thrown"); @@ -121,7 +121,7 @@ } public void testSetResponseEntity() { - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK"); assertNull(response.getEntity()); HttpEntity entity = new BasicHttpEntity(); Index: httpcore/module-main/src/test/java/org/apache/http/message/TestStatusLine.java =================================================================== --- httpcore/module-main/src/test/java/org/apache/http/message/TestStatusLine.java (revision 505702) +++ httpcore/module-main/src/test/java/org/apache/http/message/TestStatusLine.java (working copy) @@ -75,11 +75,6 @@ assertEquals(HttpVersion.HTTP_1_1, statusline.getHttpVersion()); assertEquals(HttpStatus.SC_OK, statusline.getStatusCode()); assertEquals("OK", statusline.getReasonPhrase()); - - statusline = new BasicStatusLine(HttpVersion.HTTP_1_1, HttpStatus.SC_OK); - assertEquals(HttpVersion.HTTP_1_1, statusline.getHttpVersion()); - assertEquals(HttpStatus.SC_OK, statusline.getStatusCode()); - assertEquals("OK", statusline.getReasonPhrase()); } public void testConstructorInvalidInput() { @@ -211,7 +206,8 @@ assertEquals("HTTP/1.1 200 OK", s); statusline = new BasicStatusLine(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, null); s = BasicStatusLine.format(statusline); - assertEquals("HTTP/1.1 200", s); + assertEquals("HTTP/1.1 200 ", s); + // compare with "testParseSuccess" above: trailing space is correct } public void testFormattingInvalidInput() throws Exception { Index: httpcore/module-main/src/main/java/org/apache/http/message/BasicHttpResponse.java =================================================================== --- httpcore/module-main/src/main/java/org/apache/http/message/BasicHttpResponse.java (revision 505702) +++ httpcore/module-main/src/main/java/org/apache/http/message/BasicHttpResponse.java (working copy) @@ -31,13 +31,18 @@ package org.apache.http.message; +import java.util.Locale; + import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; import org.apache.http.StatusLine; +import org.apache.http.ReasonPhraseCatalog; + /** * Basic implementation of an HTTP response that can be modified. + * This implementation makes sure that there always is a status line. * * @author Oleg Kalnichevski * @@ -45,60 +50,155 @@ * * @since 4.0 */ -public class BasicHttpResponse extends AbstractHttpMessage implements HttpResponse { - - private StatusLine statusline = null; - private HttpEntity entity = null; - - public BasicHttpResponse(final StatusLine statusline) { +public class BasicHttpResponse extends AbstractHttpMessage + implements HttpResponse { + + private StatusLine statusline; + private HttpEntity entity; + private ReasonPhraseCatalog reasonCatalog; + private Locale locale; + + + /** + * Creates a new response. + * This is the constructor to which all others map. + * + * @param statusline the status line + * @param catalog the reason phrase catalog, or + * null to disable automatic + * reason phrase lookup + * @param locale the locale for looking up reason phrases, or + * null for the system locale + */ + public BasicHttpResponse(final StatusLine statusline, + final ReasonPhraseCatalog catalog, + final Locale locale) { super(); if (statusline == null) { - throw new IllegalArgumentException("Status line may not be null"); + throw new IllegalArgumentException("Status line may not be null."); } - this.statusline = statusline; + this.statusline = statusline; + this.reasonCatalog = catalog; + this.locale = (locale != null) ? locale : Locale.getDefault(); } - public BasicHttpResponse(final HttpVersion ver, final int code) { - super(); - this.statusline = new BasicStatusLine(ver, code); + /** + * Creates a response from a status line. + * The response will not have a reason phrase catalog and + * use the system default locale. + * + * @param statusline the status line + */ + public BasicHttpResponse(final StatusLine statusline) { + this(statusline, null, null); } + /** + * Creates a response from elements of a status line. + * The response will not have a reason phrase catalog and + * use the system default locale. + * + * @param ver the HTTP version of the response + * @param code the status code of the response + * @param reason the reason phrase to the status code, or + * null + */ + public BasicHttpResponse(final HttpVersion ver, + final int code, + final String reason) { + this(new BasicStatusLine(ver, code, reason), null, null); + } + + + // non-javadoc, see interface HttpResponse public HttpVersion getHttpVersion() { return this.statusline.getHttpVersion(); } - + + // non-javadoc, see interface HttpResponse public StatusLine getStatusLine() { return this.statusline; } + // non-javadoc, see interface HttpResponse public HttpEntity getEntity() { return this.entity; } + // non-javadoc, see interface HttpResponse + public Locale getLocale() { + return this.locale; + } + + // non-javadoc, see interface HttpResponse public void setStatusLine(final StatusLine statusline) { if (statusline == null) { throw new IllegalArgumentException("Status line may not be null"); } this.statusline = statusline; } - + + // non-javadoc, see interface HttpResponse public void setStatusLine(final HttpVersion ver, final int code) { - if (ver == null) { - throw new IllegalArgumentException("HTTP version may not be null"); - } - this.statusline = new BasicStatusLine(ver, code); + // arguments checked in BasicStatusLine constructor + this.statusline = new BasicStatusLine(ver, code, getReason(code)); } - + + // non-javadoc, see interface HttpResponse + public void setStatusLine(final HttpVersion ver, final int code, + final String reason) { + // arguments checked in BasicStatusLine constructor + this.statusline = new BasicStatusLine(ver, code, reason); + } + + // non-javadoc, see interface HttpResponse public void setStatusCode(int code) { - if (code < 0) { - throw new IllegalArgumentException("Status line may not be null"); - } + // argument checked in BasicStatusLine constructor HttpVersion ver = this.statusline.getHttpVersion(); - this.statusline = new BasicStatusLine(ver, code); + this.statusline = new BasicStatusLine(ver, code, getReason(code)); } - + + // non-javadoc, see interface HttpResponse + public void setReasonPhrase(String reason) { + + if ((reason != null) && ((reason.indexOf('\n') >= 0) || + (reason.indexOf('\r') >= 0)) + ) { + throw new IllegalArgumentException("Line break in reason phrase."); + } + this.statusline = new BasicStatusLine(this.statusline.getHttpVersion(), + this.statusline.getStatusCode(), + reason); + } + + // non-javadoc, see interface HttpResponse public void setEntity(final HttpEntity entity) { this.entity = entity; } - + + // non-javadoc, see interface HttpResponse + public void setLocale(Locale loc) { + if (loc == null) { + throw new IllegalArgumentException("Locale may not be null."); + } + this.locale = loc; + final int code = this.statusline.getStatusCode(); + this.statusline = new BasicStatusLine + (this.statusline.getHttpVersion(), code, getReason(code)); + } + + /** + * Looks up a reason phrase. + * This method evaluates the currently set catalog and locale. + * It also handles a missing catalog. + * + * @param code the status code for which to look up the reason + * + * @return the reason phrase, or null if there is none + */ + protected String getReason(int code) { + return (this.reasonCatalog == null) ? + null : this.reasonCatalog.getReason(code, this.locale); + } + } Index: httpcore/module-main/src/main/java/org/apache/http/message/BasicStatusLine.java =================================================================== --- httpcore/module-main/src/main/java/org/apache/http/message/BasicStatusLine.java (revision 505702) +++ httpcore/module-main/src/main/java/org/apache/http/message/BasicStatusLine.java (working copy) @@ -37,7 +37,7 @@ import org.apache.http.StatusLine; import org.apache.http.protocol.HTTP; import org.apache.http.util.CharArrayBuffer; -import org.apache.http.impl.EnglishReasonPhraseCatalog; +//import org.apache.http.impl.EnglishReasonPhraseCatalog; /** @@ -69,14 +69,22 @@ // ----------------------------------------------------------- Constructors /** * Creates a new status line with the given version, status, and reason. + * + * @param httpVersion the HTTP version of the response + * @param statusCode the status code of the response + * @param reasonPhrase the reason phrase to the status code, or + * null */ - public BasicStatusLine(final HttpVersion httpVersion, int statusCode, final String reasonPhrase) { + public BasicStatusLine(final HttpVersion httpVersion, int statusCode, + final String reasonPhrase) { super(); if (httpVersion == null) { - throw new IllegalArgumentException("HTTP version may not be null"); + throw new IllegalArgumentException + ("HTTP version may not be null."); } if (statusCode < 0) { - throw new IllegalArgumentException("Status code may not be negative"); + throw new IllegalArgumentException + ("Status code may not be negative."); } this.httpVersion = httpVersion; this.statusCode = statusCode; @@ -84,15 +92,6 @@ } /** - * Creates a new status line with the given version and status. - */ - public BasicStatusLine(final HttpVersion httpVersion, int statusCode) { - this(httpVersion, statusCode, - //@@@ TODO: reason null instead of English? - EnglishReasonPhraseCatalog.INSTANCE.getReason(statusCode, null)); - } - - /** * Parses the status line returned from the HTTP server. * * @param buffer the buffer from which to parse @@ -219,8 +218,8 @@ BasicHttpVersionFormat.format(buffer, statusline.getHttpVersion()); buffer.append(' '); buffer.append(Integer.toString(statusline.getStatusCode())); + buffer.append(' '); // keep whitespace even if reason phrase is empty if (statusline.getReasonPhrase() != null) { - buffer.append(' '); buffer.append(statusline.getReasonPhrase()); } } Index: httpcore/module-main/src/main/java/org/apache/http/impl/EnglishReasonPhraseCatalog.java =================================================================== --- httpcore/module-main/src/main/java/org/apache/http/impl/EnglishReasonPhraseCatalog.java (revision 505702) +++ httpcore/module-main/src/main/java/org/apache/http/impl/EnglishReasonPhraseCatalog.java (working copy) @@ -31,9 +31,10 @@ package org.apache.http.impl; +import java.util.Locale; + import org.apache.http.HttpStatus; import org.apache.http.ReasonPhraseCatalog; -import org.apache.http.protocol.HttpContext; /** @@ -74,11 +75,11 @@ * Obtains the reason phrase for a status code. * * @param status the status code, in the range 100-599 - * @param context ignored + * @param loc ignored * * @return the reason phrase, or null */ - public String getReason(int status, HttpContext context) { + public String getReason(int status, Locale loc) { if ((status < 100) || (status >= 600)) { throw new IllegalArgumentException ("Unknown category for status code " + status + "."); Index: httpcore/module-main/src/main/java/org/apache/http/impl/AbstractHttpClientConnection.java =================================================================== --- httpcore/module-main/src/main/java/org/apache/http/impl/AbstractHttpClientConnection.java (revision 505702) +++ httpcore/module-main/src/main/java/org/apache/http/impl/AbstractHttpClientConnection.java (working copy) @@ -253,7 +253,7 @@ } while(true); //create the status line from the status string StatusLine statusline = BasicStatusLine.parse(this.buffer, 0, this.buffer.length()); - HttpResponse response = this.responsefactory.newHttpResponse(statusline); + HttpResponse response = this.responsefactory.newHttpResponse(statusline, null); response.getParams().setDefaults(params); return response; } Index: httpcore/module-main/src/main/java/org/apache/http/impl/DefaultHttpResponseFactory.java =================================================================== --- httpcore/module-main/src/main/java/org/apache/http/impl/DefaultHttpResponseFactory.java (revision 505702) +++ httpcore/module-main/src/main/java/org/apache/http/impl/DefaultHttpResponseFactory.java (working copy) @@ -31,6 +31,8 @@ package org.apache.http.impl; +import java.util.Locale; + import org.apache.http.HttpResponse; import org.apache.http.HttpResponseFactory; import org.apache.http.HttpVersion; @@ -86,17 +88,34 @@ if (ver == null) { throw new IllegalArgumentException("HTTP version may not be null"); } - final String reason = reasonCatalog.getReason(status, context); + final Locale loc = determineLocale(context); + final String reason = reasonCatalog.getReason(status, loc); StatusLine statusline = new BasicStatusLine(ver, status, reason); - return new BasicHttpResponse(statusline); + return new BasicHttpResponse(statusline, reasonCatalog, loc); } // non-javadoc, see interface HttpResponseFactory - public HttpResponse newHttpResponse(final StatusLine statusline) { + public HttpResponse newHttpResponse(final StatusLine statusline, + HttpContext context) { if (statusline == null) { throw new IllegalArgumentException("Status line may not be null"); } - return new BasicHttpResponse(statusline); + final Locale loc = determineLocale(context); + return new BasicHttpResponse(statusline, reasonCatalog, loc); } + + + /** + * Determines the locale of the response. + * The implementation in this class always returns the default locale. + * + * @param context the context from which to determine the locale, or + * null to use the default locale + * + * @return the locale for the response, never null + */ + protected Locale determineLocale(HttpContext context) { + return Locale.getDefault(); + } } Index: httpcore/module-main/src/main/java/org/apache/http/HttpResponseFactory.java =================================================================== --- httpcore/module-main/src/main/java/org/apache/http/HttpResponseFactory.java (revision 505702) +++ httpcore/module-main/src/main/java/org/apache/http/HttpResponseFactory.java (working copy) @@ -44,10 +44,33 @@ * @since 4.0 */ public interface HttpResponseFactory { - + + /** + * Creates a new response from status line elements. + * + * @param ver the HTTP version + * @param status the status code + * @param context the context from which to determine the locale + * for looking up a reason phrase to the status code, or + * null to use the default locale + * + * @return the new response with an initialized status line + */ HttpResponse newHttpResponse(HttpVersion ver, int status, HttpContext context); - HttpResponse newHttpResponse(StatusLine statusline); + /** + * Creates a new response from a status line. + * + * @param statusline the status line + * @param context the context from which to determine the locale + * for looking up a reason phrase if the status code + * is updated, or + * null to use the default locale + * + * @return the new response with the argument status line + */ + HttpResponse newHttpResponse(StatusLine statusline, + HttpContext context); } Index: httpcore/module-main/src/main/java/org/apache/http/ReasonPhraseCatalog.java =================================================================== --- httpcore/module-main/src/main/java/org/apache/http/ReasonPhraseCatalog.java (revision 505702) +++ httpcore/module-main/src/main/java/org/apache/http/ReasonPhraseCatalog.java (working copy) @@ -31,8 +31,9 @@ package org.apache.http; -import org.apache.http.protocol.HttpContext; +import java.util.Locale; + /** * Interface for obtaining reason phrases for HTTP status codes. * @@ -52,12 +53,11 @@ * the language for the reason phrase. * * @param status the status code, in the range 100-599 - * @param context the context for the response being generated, or - * null if not available + * @param loc the preferred locale for the reason phrase * * @return the reason phrase, or null if unknown */ - public String getReason(int status, HttpContext context) + public String getReason(int status, Locale loc) ; } Index: httpcore/module-main/src/main/java/org/apache/http/HttpResponse.java =================================================================== --- httpcore/module-main/src/main/java/org/apache/http/HttpResponse.java (revision 505702) +++ httpcore/module-main/src/main/java/org/apache/http/HttpResponse.java (working copy) @@ -31,6 +31,10 @@ package org.apache.http; + +import java.util.Locale; + + /** * An HTTP response. * @@ -43,44 +47,115 @@ public interface HttpResponse extends HttpMessage { /** - * Returns the status line that belongs to this response as set by - * @link #setStatusLine(StatusLine). + * Obtains the status line of this response. + * The status line can be set using on of the + * {@link #setStatusLine setStatusLine} methods, + * or it can be initialized in a constructor. + * + * @return the status line, or null if not yet set */ StatusLine getStatusLine(); /** - * Sets the status line that belongs to this response. - * @param statusline the status line of this response. + * Sets the status line of this response. + * + * @param statusline the status line of this response */ void setStatusLine(StatusLine statusline); - + /** - * Sets the status line that belongs to this response. - * @param ver the HTTP version. - * @param code the HTTP status code. + * Sets the status line of this response. + * The reason phrase will be determined based on the current + * {@link #getLocale locale}. + * + * @param ver the HTTP version + * @param code the status code */ void setStatusLine(HttpVersion ver, int code); + + /** + * Sets the status line of this response with a reason phrase. + * + * @param ver the HTTP version + * @param code the status code + * @param reason the reason phrase, or null to omit + */ + void setStatusLine(HttpVersion ver, int code, String reason); /** - * Convenience method that creates and sets a new status line of this - * response that is initialized with the specified status code. + * Updates the status line of this response with a new status code. + * The status line can only be updated if it is available. It must + * have been set either explicitly or in a constructor. + *
+ * The reason phrase will be updated according to the new status code, + * based on the current {@link #getLocale locale}. It can be set + * explicitly using {@link #setReasonPhrase setReasonPhrase}. * * @param code the HTTP status code. + * + * @throws IllegalStateException + * if the status line has not be set + * * @see HttpStatus + * @see #setStatusLine(StatusLine) + * @see #setStatusLine(HttpVersion,int) */ - void setStatusCode(int code); - + void setStatusCode(int code) + throws IllegalStateException; + /** - * Returns the response entity of this response as set by - * @link #setEntity(HttpEntity). - * @return the response entity or null if there is none. + * Updates the status line of this response with a new reason phrase. + * The status line can only be updated if it is available. It must + * have been set either explicitly or in a constructor. + * + * @param reason the new reason phrase as a single-line string, or + * null to unset the reason phrase + * + * @throws IllegalStateException + * if the status line has not be set + * + * @see #setStatusLine(StatusLine) + * @see #setStatusLine(HttpVersion,int) */ + void setReasonPhrase(String reason) + throws IllegalStateException; + + /** + * Obtains the message entity of this response, if any. + * The entity is provided by calling {@link #setEntity setEntity}. + * + * @return the response entity, or + * null if there is none + */ HttpEntity getEntity(); /** * Associates a response entity with this response. - * @param entity the entity to associate with this response. + * + * @param entity the entity to associate with this response, or + * null to unset */ void setEntity(HttpEntity entity); - + + /** + * Obtains the locale of this response. + * The locale is used to determine the reason phrase + * for the {@link #setStatusCode status code}. + * It can be changed using {@link #setLocale setLocale}. + * + * @return the locale of this response, never null + */ + Locale getLocale(); + + /** + * Changes the locale of this response. + * If there is a status line, it's reason phrase will be updated + * according to the status code and new locale. + * + * @param loc the new locale + * + * @see #getLocale getLocale + * @see #setStatusCode setStatusCode + */ + void setLocale(Locale loc); } Index: httpcore/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpResponseParser.java =================================================================== --- httpcore/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpResponseParser.java (revision 505702) +++ httpcore/module-nio/src/main/java/org/apache/http/impl/nio/codecs/HttpResponseParser.java (working copy) @@ -56,7 +56,7 @@ protected HttpMessage createMessage(final CharArrayBuffer buffer) throws HttpException { StatusLine statusline = BasicStatusLine.parse(buffer, 0, buffer.length()); - return this.responseFactory.newHttpResponse(statusline); + return this.responseFactory.newHttpResponse(statusline, null); } } Index: httpclient/src/test/org/apache/http/impl/client/TestDefaultResponseConsumedWatcher.java =================================================================== --- httpclient/src/test/org/apache/http/impl/client/TestDefaultResponseConsumedWatcher.java (revision 505344) +++ httpclient/src/test/org/apache/http/impl/client/TestDefaultResponseConsumedWatcher.java (working copy) @@ -90,7 +90,7 @@ entity.setContentLength(data.length); entity.setContent(new ByteArrayInputStream(data)); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, 200); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, 200, "OK"); response.addHeader("Connection", "Close"); response.setParams(new DefaultHttpParams(null)); response.setEntity(entity); @@ -113,7 +113,7 @@ entity.setContentLength(data.length); entity.setContent(new ByteArrayInputStream(data)); - HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200); + HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK"); response.addHeader("Connection", "Keep-alive"); response.setParams(new DefaultHttpParams(null)); response.setEntity(entity); Index: httpasync/src/test/java/org/apache/http/async/TestAbstractHttpHandle.java =================================================================== --- httpasync/src/test/java/org/apache/http/async/TestAbstractHttpHandle.java (revision 505650) +++ httpasync/src/test/java/org/apache/http/async/TestAbstractHttpHandle.java (working copy) @@ -247,7 +247,8 @@ MockHttpDispatcher mhd = new MockHttpDispatcher(null); MockHttpHandle mhh = createHandle(mhd); - HttpResponse rsp = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200); + HttpResponse rsp = new BasicHttpResponse + (HttpVersion.HTTP_1_1, 200, "OK"); mhh.dispatcherPostprocess(rsp); assertEquals("not postprocessed", mhd.count_postprocess, 1); assertSame("wrong handle", mhh, mhd.last_handle); Index: httpasync/src/java/org/apache/http/async/impl/NotificationResponseWrapper.java =================================================================== --- httpasync/src/java/org/apache/http/async/impl/NotificationResponseWrapper.java (revision 505650) +++ httpasync/src/java/org/apache/http/async/impl/NotificationResponseWrapper.java (working copy) @@ -32,6 +32,7 @@ package org.apache.http.async.impl; +import java.util.Locale; import java.util.Iterator; import org.apache.http.HttpResponse; @@ -127,12 +128,33 @@ } // non-javadoc, see interface HttpResponse + public void setStatusLine(HttpVersion ver, int code, String reason) { + wrapped_response.setStatusLine(ver, code, reason); + } + + // non-javadoc, see interface HttpResponse public void setStatusCode(int code) { wrapped_response.setStatusCode(code); } + // non-javadoc, see interface HttpResponse + public void setReasonPhrase(String reason) { + wrapped_response.setReasonPhrase(reason); + } + // non-javadoc, see interface HttpResponse + public Locale getLocale() { + return wrapped_response.getLocale(); + } + // non-javadoc, see interface HttpResponse + public void setLocale(Locale loc) { + wrapped_response.setLocale(loc); + } + + + + // non-javadoc, see interface HttpMessage public HttpVersion getHttpVersion() { return wrapped_response.getHttpVersion();