001/*
002 * ====================================================================
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements.  See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership.  The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License.  You may obtain a copy of the License at
010 *
011 *   http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied.  See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 * ====================================================================
020 *
021 * This software consists of voluntary contributions made by many
022 * individuals on behalf of the Apache Software Foundation.  For more
023 * information on the Apache Software Foundation, please see
024 * <http://www.apache.org/>.
025 *
026 */
027
028package org.apache.http.impl.io;
029
030import java.io.IOException;
031import java.io.OutputStream;
032
033import org.apache.http.io.SessionOutputBuffer;
034import org.apache.http.util.Args;
035
036/**
037 * Output stream that writes data without any transformation. The end of
038 * the content entity is demarcated by closing the underlying connection
039 * (EOF condition). Entities transferred using this input stream can be of
040 * unlimited length.
041 * <p>
042 * Note that this class NEVER closes the underlying stream, even when close
043 * gets called.  Instead, the stream will be marked as closed and no further
044 * output will be permitted.
045 *
046 * @since 4.0
047 */
048public class IdentityOutputStream extends OutputStream {
049
050    /**
051     * Wrapped session output buffer.
052     */
053    private final SessionOutputBuffer out;
054
055    /** True if the stream is closed. */
056    private boolean closed = false;
057
058    public IdentityOutputStream(final SessionOutputBuffer out) {
059        super();
060        this.out = Args.notNull(out, "Session output buffer");
061    }
062
063    /**
064     * <p>Does not close the underlying socket output.</p>
065     *
066     * @throws IOException If an I/O problem occurs.
067     */
068    @Override
069    public void close() throws IOException {
070        if (!this.closed) {
071            this.closed = true;
072            this.out.flush();
073        }
074    }
075
076    @Override
077    public void flush() throws IOException {
078        this.out.flush();
079    }
080
081    @Override
082    public void write(final byte[] b, final int off, final int len) throws IOException {
083        if (this.closed) {
084            throw new IOException("Attempted write to closed stream.");
085        }
086        this.out.write(b, off, len);
087    }
088
089    @Override
090    public void write(final byte[] b) throws IOException {
091        write(b, 0, b.length);
092    }
093
094    @Override
095    public void write(final int b) throws IOException {
096        if (this.closed) {
097            throw new IOException("Attempted write to closed stream.");
098        }
099        this.out.write(b);
100    }
101
102}