1 /* 2 * $HeadURL: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha2/src/java/org/apache/http/io/ContentLengthOutputStream.java $ 3 * $Revision: 390883 $ 4 * $Date: 2006-04-02 20:39:50 +0200 (Sun, 02 Apr 2006) $ 5 * 6 * ==================================================================== 7 * 8 * Copyright 1999-2006 The Apache Software Foundation 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * ==================================================================== 22 * 23 * This software consists of voluntary contributions made by many 24 * individuals on behalf of the Apache Software Foundation. For more 25 * information on the Apache Software Foundation, please see 26 * <http://www.apache.org/>. 27 * 28 */ 29 30 package org.apache.http.io; 31 32 import java.io.IOException; 33 import java.io.OutputStream; 34 35 /** 36 * A stream wrapper that closes itself after a defined number of bytes. 37 * 38 * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a> 39 * 40 * @version $Revision: 390883 $ 41 * 42 * @since 4.0 43 */ 44 public class ContentLengthOutputStream extends OutputStream { 45 46 /** 47 * Wrapped data transmitter that all calls are delegated to. 48 */ 49 private final HttpDataTransmitter out; 50 51 /** 52 * The maximum number of bytes that can be written the stream. Subsequent 53 * write operations will be ignored. 54 */ 55 private final long contentLength; 56 57 /** Total bytes written */ 58 private long total = 0; 59 60 /** True if the stream is closed. */ 61 private boolean closed = false; 62 63 /** 64 * Creates a new length limited stream 65 * 66 * @param out The data transmitter to wrap 67 * @param contentLength The maximum number of bytes that can be written to 68 * the stream. Subsequent write operations will be ignored. 69 * 70 * @since 4.0 71 */ 72 public ContentLengthOutputStream(final HttpDataTransmitter out, long contentLength) { 73 super(); 74 if (out == null) { 75 throw new IllegalArgumentException("HTTP data transmitter may not be null"); 76 } 77 if (contentLength < 0) { 78 throw new IllegalArgumentException("Content length may not be negative"); 79 } 80 this.out = out; 81 this.contentLength = contentLength; 82 } 83 84 /** 85 * <p>Does not close the underlying socket output.</p> 86 * 87 * @throws IOException If an I/O problem occurs. 88 */ 89 public void close() throws IOException { 90 if (!this.closed) { 91 this.closed = true; 92 this.out.flush(); 93 } 94 } 95 96 public void flush() throws IOException { 97 this.out.flush(); 98 } 99 100 public void write(byte[] b, int off, int len) throws IOException { 101 if (this.closed) { 102 throw new IOException("Attempted write to closed stream."); 103 } 104 if (this.total < this.contentLength) { 105 long max = this.contentLength - this.total; 106 if (len > max) { 107 len = (int) max; 108 } 109 this.out.write(b, off, len); 110 this.total += len; 111 } 112 } 113 114 public void write(byte[] b) throws IOException { 115 write(b, 0, b.length); 116 } 117 118 public void write(int b) throws IOException { 119 if (this.closed) { 120 throw new IOException("Attempted write to closed stream."); 121 } 122 if (this.total < this.contentLength) { 123 this.out.write(b); 124 this.total++; 125 } 126 } 127 128 }