1/*
2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/impl/io/AbstractSessionOutputBuffer.java $
3 * $Revision: 652091 $
4 * $Date: 2008-04-29 13:41:07 -0700 (Tue, 29 Apr 2008) $
5 *
6 * ====================================================================
7 * Licensed to the Apache Software Foundation (ASF) under one
8 * or more contributor license agreements.  See the NOTICE file
9 * distributed with this work for additional information
10 * regarding copyright ownership.  The ASF licenses this file
11 * to you under the Apache License, Version 2.0 (the
12 * "License"); you may not use this file except in compliance
13 * with the License.  You may obtain a copy of the License at
14 *
15 *   http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing,
18 * software distributed under the License is distributed on an
19 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20 * KIND, either express or implied.  See the License for the
21 * specific language governing permissions and limitations
22 * under the License.
23 * ====================================================================
24 *
25 * This software consists of voluntary contributions made by many
26 * individuals on behalf of the Apache Software Foundation.  For more
27 * information on the Apache Software Foundation, please see
28 * <http://www.apache.org/>.
29 *
30 */
31
32package org.apache.http.impl.io;
33
34import java.io.IOException;
35import java.io.OutputStream;
36
37import org.apache.http.io.SessionOutputBuffer;
38import org.apache.http.io.HttpTransportMetrics;
39import org.apache.http.params.HttpParams;
40import org.apache.http.params.HttpProtocolParams;
41import org.apache.http.protocol.HTTP;
42import org.apache.http.util.ByteArrayBuffer;
43import org.apache.http.util.CharArrayBuffer;
44
45/**
46 * Abstract base class for session output buffers that stream data
47 * to an {@link OutputStream}.
48 *
49 * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
50 *
51 *
52 * @deprecated Please use {@link java.net.URL#openConnection} instead.
53 *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
54 *     for further details.
55 */
56@Deprecated
57public abstract class AbstractSessionOutputBuffer implements SessionOutputBuffer {
58
59    private static final byte[] CRLF = new byte[] {HTTP.CR, HTTP.LF};
60
61    private static final int MAX_CHUNK = 256;
62
63    private OutputStream outstream;
64    private ByteArrayBuffer buffer;
65
66    private String charset = HTTP.US_ASCII;
67    private boolean ascii = true;
68
69    private HttpTransportMetricsImpl metrics;
70
71    protected void init(final OutputStream outstream, int buffersize, final HttpParams params) {
72        if (outstream == null) {
73            throw new IllegalArgumentException("Input stream may not be null");
74        }
75        if (buffersize <= 0) {
76            throw new IllegalArgumentException("Buffer size may not be negative or zero");
77        }
78        if (params == null) {
79            throw new IllegalArgumentException("HTTP parameters may not be null");
80        }
81        this.outstream = outstream;
82        this.buffer = new ByteArrayBuffer(buffersize);
83        this.charset = HttpProtocolParams.getHttpElementCharset(params);
84        this.ascii = this.charset.equalsIgnoreCase(HTTP.US_ASCII)
85                     || this.charset.equalsIgnoreCase(HTTP.ASCII);
86        this.metrics = new HttpTransportMetricsImpl();
87    }
88
89    protected void flushBuffer() throws IOException {
90        int len = this.buffer.length();
91        if (len > 0) {
92            this.outstream.write(this.buffer.buffer(), 0, len);
93            this.buffer.clear();
94            this.metrics.incrementBytesTransferred(len);
95        }
96    }
97
98    public void flush() throws IOException {
99        flushBuffer();
100        this.outstream.flush();
101    }
102
103    public void write(final byte[] b, int off, int len) throws IOException {
104        if (b == null) {
105            return;
106        }
107        // Do not want to buffer largish chunks
108        // if the byte array is larger then MAX_CHUNK
109        // write it directly to the output stream
110        if (len > MAX_CHUNK || len > this.buffer.capacity()) {
111            // flush the buffer
112            flushBuffer();
113            // write directly to the out stream
114            this.outstream.write(b, off, len);
115            this.metrics.incrementBytesTransferred(len);
116        } else {
117            // Do not let the buffer grow unnecessarily
118            int freecapacity = this.buffer.capacity() - this.buffer.length();
119            if (len > freecapacity) {
120                // flush the buffer
121                flushBuffer();
122            }
123            // buffer
124            this.buffer.append(b, off, len);
125        }
126    }
127
128    public void write(final byte[] b) throws IOException {
129        if (b == null) {
130            return;
131        }
132        write(b, 0, b.length);
133    }
134
135    public void write(int b) throws IOException {
136        if (this.buffer.isFull()) {
137            flushBuffer();
138        }
139        this.buffer.append(b);
140    }
141
142    public void writeLine(final String s) throws IOException {
143        if (s == null) {
144            return;
145        }
146        if (s.length() > 0) {
147            write(s.getBytes(this.charset));
148        }
149        write(CRLF);
150    }
151
152    public void writeLine(final CharArrayBuffer s) throws IOException {
153        if (s == null) {
154            return;
155        }
156        if (this.ascii) {
157            int off = 0;
158            int remaining = s.length();
159            while (remaining > 0) {
160                int chunk = this.buffer.capacity() - this.buffer.length();
161                chunk = Math.min(chunk, remaining);
162                if (chunk > 0) {
163                    this.buffer.append(s, off, chunk);
164                }
165                if (this.buffer.isFull()) {
166                    flushBuffer();
167                }
168                off += chunk;
169                remaining -= chunk;
170            }
171        } else {
172            // This is VERY memory inefficient, BUT since non-ASCII charsets are
173            // NOT meant to be used anyway, there's no point optimizing it
174            byte[] tmp = s.toString().getBytes(this.charset);
175            write(tmp);
176        }
177        write(CRLF);
178    }
179
180    public HttpTransportMetrics getMetrics() {
181        return this.metrics;
182    }
183
184}
185