16906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson/* 26906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * Copyright (C) 2010 The Android Open Source Project 36906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * 46906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 56906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * you may not use this file except in compliance with the License. 66906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * You may obtain a copy of the License at 76906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * 86906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 96906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * 106906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * Unless required by applicable law or agreed to in writing, software 116906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 126906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * See the License for the specific language governing permissions and 146906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * limitations under the License. 156906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson */ 166906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 175aafac4db69e6d087c512cdfa5c7c0e2f1611681Jesse Wilsonpackage libcore.net.http; 186906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 196906b0c12dcf3216883d0373973a252812a20d32Jesse Wilsonimport java.io.IOException; 206906b0c12dcf3216883d0373973a252812a20d32Jesse Wilsonimport java.io.InputStream; 216906b0c12dcf3216883d0373973a252812a20d32Jesse Wilsonimport java.io.OutputStream; 226906b0c12dcf3216883d0373973a252812a20d32Jesse Wilsonimport java.net.CacheRequest; 23ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughesimport libcore.io.Streams; 246906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 256906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson/** 26ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson * An input stream for the body of an HTTP response. 276906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * 28da289bcd0a9e207cc03c752f7c21c9004056e179Jesse Wilson * <p>Since a single socket's input stream may be used to read multiple HTTP 29da289bcd0a9e207cc03c752f7c21c9004056e179Jesse Wilson * responses from the same server, subclasses shouldn't close the socket stream. 306906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * 316906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * <p>A side effect of reading an HTTP response is that the response cache 326906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * is populated. If the stream is closed early, that cache entry will be 336906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * invalidated. 346906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson */ 356906b0c12dcf3216883d0373973a252812a20d32Jesse Wilsonabstract class AbstractHttpInputStream extends InputStream { 366906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson protected final InputStream in; 37953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson protected final HttpEngine httpEngine; 38afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson private final CacheRequest cacheRequest; 39afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson private final OutputStream cacheBody; 406906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson protected boolean closed; 416906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 42953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson AbstractHttpInputStream(InputStream in, HttpEngine httpEngine, 436906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson CacheRequest cacheRequest) throws IOException { 446906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson this.in = in; 45953df613522e12a418cb7cb73248594d6c9f53d4Jesse Wilson this.httpEngine = httpEngine; 46afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson 47afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson OutputStream cacheBody = cacheRequest != null ? cacheRequest.getBody() : null; 48afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson 49afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson // some apps return a null body; for compatibility we treat that like a null cache request 50afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson if (cacheBody == null) { 51afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson cacheRequest = null; 52afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson } 53afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson 54afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson this.cacheBody = cacheBody; 556906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson this.cacheRequest = cacheRequest; 566906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 576906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 586906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson /** 596906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * read() is implemented using read(byte[], int, int) so subclasses only 606906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * need to override the latter. 616906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson */ 626906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson @Override public final int read() throws IOException { 63ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes return Streams.readSingleByte(this); 646906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 656906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 666906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson protected final void checkNotClosed() throws IOException { 676906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson if (closed) { 686906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson throw new IOException("stream closed"); 696906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 706906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 716906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 726906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson protected final void cacheWrite(byte[] buffer, int offset, int count) throws IOException { 73afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson if (cacheBody != null) { 74afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson cacheBody.write(buffer, offset, count); 756906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 766906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 776906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 786906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson /** 796906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * Closes the cache entry and makes the socket available for reuse. This 80ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson * should be invoked when the end of the body has been reached. 816906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson */ 82c0372d90016d241ac979faa6fa1731f30b6f2a03Jesse Wilson protected final void endOfInput(boolean reuseSocket) throws IOException { 836906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson if (cacheRequest != null) { 84afd9b157f467b7c4f2f0b5592dca72f18d844602Jesse Wilson cacheBody.close(); 856906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 86757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson httpEngine.release(reuseSocket); 876906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 886906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 896906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson /** 906906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * Calls abort on the cache entry and disconnects the socket. This 916906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * should be invoked when the connection is closed unexpectedly to 926906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * invalidate the cache entry and to prevent the HTTP connection from 936906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * being reused. HTTP messages are sent in serial so whenever a message 946906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * cannot be read to completion, subsequent messages cannot be read 956906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * either and the connection must be discarded. 966906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * 976906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * <p>An earlier implementation skipped the remaining bytes, but this 986906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * requires that the entire transfer be completed. If the intention was 996906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson * to cancel the transfer, closing the connection is the only solution. 1006906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson */ 1016906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson protected final void unexpectedEndOfInput() { 1026906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson if (cacheRequest != null) { 1036906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson cacheRequest.abort(); 1046906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 105757afaa7afe96791a3cc612c9e3c4597a7321c7eJesse Wilson httpEngine.release(false); 1066906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 1076906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson} 108