001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.io.output;
019
020import java.io.IOException;
021import java.io.OutputStream;
022
023import org.apache.commons.io.IOUtils;
024
025/**
026 * Throws an IOException on all attempts to write to the stream.
027 * <p>
028 * Typically uses of this class include testing for corner cases in methods that accept an output stream and acting as a sentinel value instead of a
029 * {@code null} output stream.
030 * </p>
031 *
032 * @since 1.4
033 */
034public class ClosedOutputStream extends OutputStream {
035
036    /**
037     * The singleton instance.
038     *
039     * @since 2.12.0
040     */
041    public static final ClosedOutputStream INSTANCE = new ClosedOutputStream();
042
043    /**
044     * The singleton instance.
045     *
046     * @deprecated Use {@link #INSTANCE}.
047     */
048    @Deprecated
049    public static final ClosedOutputStream CLOSED_OUTPUT_STREAM = INSTANCE;
050
051    /**
052     * Construct a new instance.
053     */
054    public ClosedOutputStream() {
055        // empty
056    }
057
058    /**
059     * Throws an {@link IOException} to indicate that the stream is closed.
060     *
061     * @throws IOException always thrown
062     */
063    @Override
064    public void flush() throws IOException {
065        throw new IOException("flush() failed: stream is closed");
066    }
067
068    /**
069     * Throws an {@link IOException} to indicate that the stream is closed.
070     *
071     * @param b   Byte array, never {@code null}.
072     * @param off The start offset in the byte array.
073     * @param len The number of bytes to write.
074     * @throws NullPointerException if the byte array is {@code null}.
075     * @throws IndexOutOfBoundsException if {@code off} or {@code len} are negative, or if {@code off + len} is greater than {@code b.length}.
076     * @throws IOException always thrown.
077     */
078    @Override
079    public void write(final byte b[], final int off, final int len) throws IOException {
080        IOUtils.checkFromIndexSize(b, off, len);
081        throw new IOException("write(byte[], int, int) failed: stream is closed");
082    }
083
084    /**
085     * Throws an {@link IOException} to indicate that the stream is closed.
086     *
087     * @param b ignored.
088     * @throws IOException always thrown.
089     */
090    @Override
091    public void write(final int b) throws IOException {
092        throw new IOException("write(int) failed: stream is closed");
093    }
094}