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/codecs/LengthDelimitedEncoder.java $
003: * $Revision: 613298 $
004: * $Date: 2008-01-18 23:09:22 +0100 (Fri, 18 Jan 2008) $
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.codecs;
033:
034: import java.io.IOException;
035: import java.nio.ByteBuffer;
036: import java.nio.channels.FileChannel;
037: import java.nio.channels.WritableByteChannel;
038:
039: import org.apache.http.impl.io.HttpTransportMetricsImpl;
040: import org.apache.http.nio.FileContentEncoder;
041: import org.apache.http.nio.reactor.SessionOutputBuffer;
042:
043: /**
044: * Content-Length delimited encoder implementation.
045: *
046: * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
047: * @author Andrea Selva
048: *
049: * @version $Revision: 613298 $
050: *
051: * @since 4.0
052: */
053: public class LengthDelimitedEncoder extends AbstractContentEncoder
054: implements FileContentEncoder {
055:
056: private final long contentLength;
057:
058: private long len;
059:
060: public LengthDelimitedEncoder(final WritableByteChannel channel,
061: final SessionOutputBuffer buffer,
062: final HttpTransportMetricsImpl metrics, long contentLength) {
063: super (channel, buffer, metrics);
064: if (contentLength < 0) {
065: throw new IllegalArgumentException(
066: "Content length may not be negative");
067: }
068: this .contentLength = contentLength;
069: this .len = 0;
070: }
071:
072: public int write(final ByteBuffer src) throws IOException {
073: if (src == null) {
074: return 0;
075: }
076: assertNotCompleted();
077: int lenRemaining = (int) (this .contentLength - this .len);
078:
079: int bytesWritten;
080: if (src.remaining() > lenRemaining) {
081: int oldLimit = src.limit();
082: int newLimit = oldLimit - (src.remaining() - lenRemaining);
083: src.limit(newLimit);
084: bytesWritten = this .channel.write(src);
085: src.limit(oldLimit);
086: } else {
087: bytesWritten = this .channel.write(src);
088: }
089: if (bytesWritten > 0) {
090: this .metrics.incrementBytesTransferred(bytesWritten);
091: }
092: this .len += bytesWritten;
093: if (this .len >= this .contentLength) {
094: this .completed = true;
095: }
096: return bytesWritten;
097: }
098:
099: public long transfer(final FileChannel src, long position,
100: long count) throws IOException {
101:
102: if (src == null) {
103: return 0;
104: }
105: assertNotCompleted();
106: int lenRemaining = (int) (this .contentLength - this .len);
107:
108: long bytesWritten;
109: if (count > lenRemaining) {
110: count = lenRemaining;
111: }
112: bytesWritten = src.transferTo(position, count, this .channel);
113: if (bytesWritten > 0) {
114: this .metrics.incrementBytesTransferred(bytesWritten);
115: }
116: this .len += bytesWritten;
117: if (this .len >= this .contentLength) {
118: this .completed = true;
119: }
120: return bytesWritten;
121: }
122:
123: @Override
124: public String toString() {
125: StringBuffer buffer = new StringBuffer();
126: buffer.append("[content length: ");
127: buffer.append(this .contentLength);
128: buffer.append("; pos: ");
129: buffer.append(this .len);
130: buffer.append("; completed: ");
131: buffer.append(this .completed);
132: buffer.append("]");
133: return buffer.toString();
134: }
135:
136: }
|