001: /*
002: * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/httpcore/tags/4.0-beta1/module-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionOutputBufferImpl.java $
003: * $Revision: 594116 $
004: * $Date: 2007-11-12 14:35:43 +0100 (Mon, 12 Nov 2007) $
005: *
006: * ====================================================================
007: * Licensed to the Apache Software Foundation (ASF) under one
008: * or more contributor license agreements. See the NOTICE file
009: * distributed with this work for additional information
010: * regarding copyright ownership. The ASF licenses this file
011: * to you under the Apache License, Version 2.0 (the
012: * "License"); you may not use this file except in compliance
013: * with the License. You may obtain a copy of the License at
014: *
015: * http://www.apache.org/licenses/LICENSE-2.0
016: *
017: * Unless required by applicable law or agreed to in writing,
018: * software distributed under the License is distributed on an
019: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
020: * KIND, either express or implied. See the License for the
021: * specific language governing permissions and limitations
022: * under the License.
023: * ====================================================================
024: *
025: * This software consists of voluntary contributions made by many
026: * individuals on behalf of the Apache Software Foundation. For more
027: * information on the Apache Software Foundation, please see
028: * <http://www.apache.org/>.
029: *
030: */
031:
032: package org.apache.http.impl.nio.reactor;
033:
034: import java.io.IOException;
035: import java.nio.ByteBuffer;
036: import java.nio.CharBuffer;
037: import java.nio.channels.ReadableByteChannel;
038: import java.nio.channels.WritableByteChannel;
039: import java.nio.charset.CharacterCodingException;
040: import java.nio.charset.Charset;
041: import java.nio.charset.CharsetEncoder;
042: import java.nio.charset.CoderResult;
043:
044: import org.apache.http.nio.reactor.SessionOutputBuffer;
045: import org.apache.http.nio.util.ByteBufferAllocator;
046: import org.apache.http.nio.util.ExpandableBuffer;
047: import org.apache.http.nio.util.HeapByteBufferAllocator;
048: import org.apache.http.params.HttpParams;
049: import org.apache.http.params.HttpProtocolParams;
050: import org.apache.http.protocol.HTTP;
051: import org.apache.http.util.CharArrayBuffer;
052:
053: public class SessionOutputBufferImpl extends ExpandableBuffer implements
054: SessionOutputBuffer {
055:
056: private static final byte[] CRLF = new byte[] { HTTP.CR, HTTP.LF };
057:
058: private CharBuffer charbuffer = null;
059: private Charset charset = null;
060: private CharsetEncoder charencoder = null;
061:
062: public SessionOutputBufferImpl(int buffersize, int linebuffersize,
063: final ByteBufferAllocator allocator, final HttpParams params) {
064: super (buffersize, allocator);
065: this .charbuffer = CharBuffer.allocate(linebuffersize);
066: this .charset = Charset.forName(HttpProtocolParams
067: .getHttpElementCharset(params));
068: this .charencoder = this .charset.newEncoder();
069: }
070:
071: public SessionOutputBufferImpl(int buffersize, int linebuffersize,
072: final HttpParams params) {
073: this (buffersize, linebuffersize, new HeapByteBufferAllocator(),
074: params);
075: }
076:
077: public void reset(final HttpParams params) {
078: clear();
079: }
080:
081: public int flush(final WritableByteChannel channel)
082: throws IOException {
083: if (channel == null) {
084: throw new IllegalArgumentException(
085: "Channel may not be null");
086: }
087: setOutputMode();
088: int noWritten = channel.write(this .buffer);
089: return noWritten;
090: }
091:
092: public void write(final ByteBuffer src) {
093: if (src == null) {
094: return;
095: }
096: setInputMode();
097: int requiredCapacity = this .buffer.position() + src.remaining();
098: ensureCapacity(requiredCapacity);
099: this .buffer.put(src);
100: }
101:
102: public void write(final ReadableByteChannel src) throws IOException {
103: if (src == null) {
104: return;
105: }
106: setInputMode();
107: src.read(this .buffer);
108: }
109:
110: private void write(final byte[] b) {
111: if (b == null) {
112: return;
113: }
114: setInputMode();
115: int off = 0;
116: int len = b.length;
117: int requiredCapacity = this .buffer.position() + len;
118: ensureCapacity(requiredCapacity);
119: this .buffer.put(b, off, len);
120: }
121:
122: private void writeCRLF() {
123: write(CRLF);
124: }
125:
126: public void writeLine(final CharArrayBuffer linebuffer)
127: throws CharacterCodingException {
128: if (linebuffer == null) {
129: return;
130: }
131: // Do not bother if the buffer is empty
132: if (linebuffer.length() > 0) {
133: setInputMode();
134: this .charencoder.reset();
135: // transfer the string in small chunks
136: int remaining = linebuffer.length();
137: int offset = 0;
138: while (remaining > 0) {
139: int l = this .charbuffer.remaining();
140: boolean eol = false;
141: if (remaining <= l) {
142: l = remaining;
143: // terminate the encoding process
144: eol = true;
145: }
146: this .charbuffer.put(linebuffer.buffer(), offset, l);
147: this .charbuffer.flip();
148:
149: boolean retry = true;
150: while (retry) {
151: CoderResult result = this .charencoder.encode(
152: this .charbuffer, this .buffer, eol);
153: if (result.isError()) {
154: result.throwException();
155: }
156: if (result.isOverflow()) {
157: expand();
158: }
159: retry = !result.isUnderflow();
160: }
161: this .charbuffer.compact();
162: offset += l;
163: remaining -= l;
164: }
165: // flush the encoder
166: boolean retry = true;
167: while (retry) {
168: CoderResult result = this .charencoder
169: .flush(this .buffer);
170: if (result.isError()) {
171: result.throwException();
172: }
173: if (result.isOverflow()) {
174: expand();
175: }
176: retry = !result.isUnderflow();
177: }
178: }
179: writeCRLF();
180: }
181:
182: public void writeLine(final String s) throws IOException {
183: if (s == null) {
184: return;
185: }
186: if (s.length() > 0) {
187: CharArrayBuffer tmp = new CharArrayBuffer(s.length());
188: tmp.append(s);
189: writeLine(tmp);
190: } else {
191: write(CRLF);
192: }
193: }
194:
195: }
|