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