001/* 002 * ==================================================================== 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 * ==================================================================== 020 * 021 * This software consists of voluntary contributions made by many 022 * individuals on behalf of the Apache Software Foundation. For more 023 * information on the Apache Software Foundation, please see 024 * <http://www.apache.org/>. 025 * 026 */ 027 028package org.apache.http.impl; 029 030import java.io.IOException; 031import java.io.OutputStream; 032import java.net.Socket; 033import java.net.SocketTimeoutException; 034import java.nio.charset.CharsetDecoder; 035import java.nio.charset.CharsetEncoder; 036 037import org.apache.http.HttpClientConnection; 038import org.apache.http.HttpEntity; 039import org.apache.http.HttpEntityEnclosingRequest; 040import org.apache.http.HttpException; 041import org.apache.http.HttpRequest; 042import org.apache.http.HttpResponse; 043import org.apache.http.HttpStatus; 044import org.apache.http.config.MessageConstraints; 045import org.apache.http.entity.ContentLengthStrategy; 046import org.apache.http.impl.io.DefaultHttpRequestWriterFactory; 047import org.apache.http.impl.io.DefaultHttpResponseParserFactory; 048import org.apache.http.io.HttpMessageParser; 049import org.apache.http.io.HttpMessageParserFactory; 050import org.apache.http.io.HttpMessageWriter; 051import org.apache.http.io.HttpMessageWriterFactory; 052import org.apache.http.util.Args; 053 054/** 055 * Default implementation of {@link HttpClientConnection}. 056 * 057 * @since 4.3 058 */ 059public class DefaultBHttpClientConnection extends BHttpConnectionBase 060 implements HttpClientConnection { 061 062 private final HttpMessageParser<HttpResponse> responseParser; 063 private final HttpMessageWriter<HttpRequest> requestWriter; 064 065 /** 066 * Creates new instance of DefaultBHttpClientConnection. 067 * 068 * @param buffersize buffer size. Must be a positive number. 069 * @param fragmentSizeHint fragment size hint. 070 * @param chardecoder decoder to be used for decoding HTTP protocol elements. 071 * If {@code null} simple type cast will be used for byte to char conversion. 072 * @param charencoder encoder to be used for encoding HTTP protocol elements. 073 * If {@code null} simple type cast will be used for char to byte conversion. 074 * @param constraints Message constraints. If {@code null} 075 * {@link MessageConstraints#DEFAULT} will be used. 076 * @param incomingContentStrategy incoming content length strategy. If {@code null} 077 * {@link org.apache.http.impl.entity.LaxContentLengthStrategy#INSTANCE} will be used. 078 * @param outgoingContentStrategy outgoing content length strategy. If {@code null} 079 * {@link org.apache.http.impl.entity.StrictContentLengthStrategy#INSTANCE} will be used. 080 * @param requestWriterFactory request writer factory. If {@code null} 081 * {@link DefaultHttpRequestWriterFactory#INSTANCE} will be used. 082 * @param responseParserFactory response parser factory. If {@code null} 083 * {@link DefaultHttpResponseParserFactory#INSTANCE} will be used. 084 */ 085 public DefaultBHttpClientConnection( 086 final int buffersize, 087 final int fragmentSizeHint, 088 final CharsetDecoder chardecoder, 089 final CharsetEncoder charencoder, 090 final MessageConstraints constraints, 091 final ContentLengthStrategy incomingContentStrategy, 092 final ContentLengthStrategy outgoingContentStrategy, 093 final HttpMessageWriterFactory<HttpRequest> requestWriterFactory, 094 final HttpMessageParserFactory<HttpResponse> responseParserFactory) { 095 super(buffersize, fragmentSizeHint, chardecoder, charencoder, 096 constraints, incomingContentStrategy, outgoingContentStrategy); 097 this.requestWriter = (requestWriterFactory != null ? requestWriterFactory : 098 DefaultHttpRequestWriterFactory.INSTANCE).create(getSessionOutputBuffer()); 099 this.responseParser = (responseParserFactory != null ? responseParserFactory : 100 DefaultHttpResponseParserFactory.INSTANCE).create(getSessionInputBuffer(), constraints); 101 } 102 103 public DefaultBHttpClientConnection( 104 final int buffersize, 105 final CharsetDecoder chardecoder, 106 final CharsetEncoder charencoder, 107 final MessageConstraints constraints) { 108 this(buffersize, buffersize, chardecoder, charencoder, constraints, null, null, null, null); 109 } 110 111 public DefaultBHttpClientConnection(final int buffersize) { 112 this(buffersize, buffersize, null, null, null, null, null, null, null); 113 } 114 115 protected void onResponseReceived(final HttpResponse response) { 116 } 117 118 protected void onRequestSubmitted(final HttpRequest request) { 119 } 120 121 @Override 122 public void bind(final Socket socket) throws IOException { 123 super.bind(socket); 124 } 125 126 @Override 127 public boolean isResponseAvailable(final int timeout) throws IOException { 128 ensureOpen(); 129 try { 130 return awaitInput(timeout); 131 } catch (final SocketTimeoutException ex) { 132 return false; 133 } 134 } 135 136 @Override 137 public void sendRequestHeader(final HttpRequest request) 138 throws HttpException, IOException { 139 Args.notNull(request, "HTTP request"); 140 ensureOpen(); 141 this.requestWriter.write(request); 142 onRequestSubmitted(request); 143 incrementRequestCount(); 144 } 145 146 @Override 147 public void sendRequestEntity(final HttpEntityEnclosingRequest request) 148 throws HttpException, IOException { 149 Args.notNull(request, "HTTP request"); 150 ensureOpen(); 151 final HttpEntity entity = request.getEntity(); 152 if (entity == null) { 153 return; 154 } 155 final OutputStream outstream = prepareOutput(request); 156 entity.writeTo(outstream); 157 outstream.close(); 158 } 159 160 @Override 161 public HttpResponse receiveResponseHeader() throws HttpException, IOException { 162 ensureOpen(); 163 final HttpResponse response = this.responseParser.parse(); 164 onResponseReceived(response); 165 if (response.getStatusLine().getStatusCode() >= HttpStatus.SC_OK) { 166 incrementResponseCount(); 167 } 168 return response; 169 } 170 171 @Override 172 public void receiveResponseEntity( 173 final HttpResponse response) throws HttpException, IOException { 174 Args.notNull(response, "HTTP response"); 175 ensureOpen(); 176 final HttpEntity entity = prepareInput(response); 177 response.setEntity(entity); 178 } 179 180 @Override 181 public void flush() throws IOException { 182 ensureOpen(); 183 doFlush(); 184 } 185 186}