1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/*
2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java $
3069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Revision: 652091 $
4069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Date: 2008-04-29 13:41:07 -0700 (Tue, 29 Apr 2008) $
5069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
6069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
7069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one
8069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * or more contributor license agreements.  See the NOTICE file
9069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * distributed with this work for additional information
10069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * regarding copyright ownership.  The ASF licenses this file
11069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to you under the Apache License, Version 2.0 (the
12069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "License"); you may not use this file except in compliance
13069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * with the License.  You may obtain a copy of the License at
14069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
15069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *   http://www.apache.org/licenses/LICENSE-2.0
16069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
17069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Unless required by applicable law or agreed to in writing,
18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * software distributed under the License is distributed on an
19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * KIND, either express or implied.  See the License for the
21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * specific language governing permissions and limitations
22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * under the License.
23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This software consists of voluntary contributions made by many
26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * individuals on behalf of the Apache Software Foundation.  For more
27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * information on the Apache Software Foundation, please see
28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <http://www.apache.org/>.
29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpackage org.apache.http.impl.io;
33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.IOException;
35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.OutputStream;
36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.io.SessionOutputBuffer;
38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.io.HttpTransportMetrics;
39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.params.HttpParams;
40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.params.HttpProtocolParams;
41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.protocol.HTTP;
42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.util.ByteArrayBuffer;
43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.util.CharArrayBuffer;
44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/**
46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Abstract base class for session output buffers that stream data
47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to an {@link OutputStream}.
48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
51d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *
52d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * @deprecated Please use {@link java.net.URL#openConnection} instead.
53d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
54d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *     for further details.
55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
56d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath@Deprecated
57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic abstract class AbstractSessionOutputBuffer implements SessionOutputBuffer {
58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final byte[] CRLF = new byte[] {HTTP.CR, HTTP.LF};
60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final int MAX_CHUNK = 256;
62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private OutputStream outstream;
64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private ByteArrayBuffer buffer;
65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private String charset = HTTP.US_ASCII;
67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean ascii = true;
68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private HttpTransportMetricsImpl metrics;
70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected void init(final OutputStream outstream, int buffersize, final HttpParams params) {
72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (outstream == null) {
73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Input stream may not be null");
74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (buffersize <= 0) {
76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Buffer size may not be negative or zero");
77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (params == null) {
79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("HTTP parameters may not be null");
80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.outstream = outstream;
82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.buffer = new ByteArrayBuffer(buffersize);
83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.charset = HttpProtocolParams.getHttpElementCharset(params);
84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.ascii = this.charset.equalsIgnoreCase(HTTP.US_ASCII)
85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                     || this.charset.equalsIgnoreCase(HTTP.ASCII);
86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.metrics = new HttpTransportMetricsImpl();
87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected void flushBuffer() throws IOException {
90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int len = this.buffer.length();
91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (len > 0) {
92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.outstream.write(this.buffer.buffer(), 0, len);
93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.buffer.clear();
94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.metrics.incrementBytesTransferred(len);
95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void flush() throws IOException {
99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        flushBuffer();
100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.outstream.flush();
101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void write(final byte[] b, int off, int len) throws IOException {
104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (b == null) {
105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return;
106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Do not want to buffer largish chunks
108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // if the byte array is larger then MAX_CHUNK
109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // write it directly to the output stream
110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (len > MAX_CHUNK || len > this.buffer.capacity()) {
111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // flush the buffer
112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            flushBuffer();
113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // write directly to the out stream
114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.outstream.write(b, off, len);
115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.metrics.incrementBytesTransferred(len);
116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // Do not let the buffer grow unnecessarily
118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            int freecapacity = this.buffer.capacity() - this.buffer.length();
119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (len > freecapacity) {
120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // flush the buffer
121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                flushBuffer();
122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // buffer
124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.buffer.append(b, off, len);
125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void write(final byte[] b) throws IOException {
129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (b == null) {
130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return;
131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        write(b, 0, b.length);
133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void write(int b) throws IOException {
136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.buffer.isFull()) {
137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            flushBuffer();
138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.buffer.append(b);
140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void writeLine(final String s) throws IOException {
143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (s == null) {
144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return;
145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (s.length() > 0) {
147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            write(s.getBytes(this.charset));
148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        write(CRLF);
150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void writeLine(final CharArrayBuffer s) throws IOException {
153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (s == null) {
154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return;
155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.ascii) {
157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            int off = 0;
158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            int remaining = s.length();
159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            while (remaining > 0) {
160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                int chunk = this.buffer.capacity() - this.buffer.length();
161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                chunk = Math.min(chunk, remaining);
162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (chunk > 0) {
163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    this.buffer.append(s, off, chunk);
164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (this.buffer.isFull()) {
166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    flushBuffer();
167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                off += chunk;
169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                remaining -= chunk;
170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // This is VERY memory inefficient, BUT since non-ASCII charsets are
173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // NOT meant to be used anyway, there's no point optimizing it
174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            byte[] tmp = s.toString().getBytes(this.charset);
175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            write(tmp);
176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        write(CRLF);
178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public HttpTransportMetrics getMetrics() {
181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return this.metrics;
182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project}
185