All Downloads are FREE. Search and download functionalities are using the official Maven repository.

no.digipost.io.LimitedInputStream Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) Posten Norge AS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package no.digipost.io;

import java.io.Closeable;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.function.Supplier;

import static no.digipost.DiggExceptions.asUnchecked;

/**
 * An {@link InputStream} which limits how many bytes which can be read.
 * 

* This class is based on the * LimitedInputStream from Apache Commons Fileupload (v1.3.2), * which has the license as the Digg library, Apache License 2.0, but also supports * to {@link #SILENTLY_EOF_ON_REACHING_LIMIT silently treat the limit as EOF} without any signal to distinguish between the EOF of the wrapped stream and * the limited stream. */ public final class LimitedInputStream extends FilterInputStream implements Closeable { private static final class SilentlyEofWhenReachingLimit implements Supplier { @Override public Exception get() { throw new UnsupportedOperationException("Should not call get() on instance of " + SilentlyEofWhenReachingLimit.class.getSimpleName() + ", this indicates a bug."); } private SilentlyEofWhenReachingLimit() {} } /** * Supply this instead of an {@link Supplier exception supplier} as parameter when contructing * a new {@code LimitedInputStream} to instruct it to * treat the limit as an ordinary EOF, and not throw any exception to signal that the * limit was reached during consumption of the stream. *

* Invoking {@link Supplier#get() get()} on this will throw an exception. */ public static final Supplier SILENTLY_EOF_ON_REACHING_LIMIT = new SilentlyEofWhenReachingLimit(); private final DataSize limit; private final Supplier throwIfTooManyBytes; private long count; /** * @see no.digipost.DiggIO#limit(InputStream, DataSize, Supplier) */ public LimitedInputStream(InputStream inputStream, DataSize maxDataToRead, Supplier throwIfTooManyBytes) { super(inputStream); this.limit = maxDataToRead; this.throwIfTooManyBytes = throwIfTooManyBytes; } /** * Reads the next byte of data from this input stream. The value * byte is returned as an int in the range * 0 to 255. If no byte is available * because the end of the stream has been reached, the value * -1 is returned. This method blocks until input data * is available, the end of the stream is detected, or an exception * is thrown. *

* This method * simply performs in.read() and returns the result. * * @return the next byte of data, or -1 if the end of the * stream is reached. * @exception IOException if an I/O error occurs. * @see java.io.FilterInputStream#in */ @Override public int read() throws IOException { int res = super.read(); if (res != -1) { count++; if (hasReachedLimit()) { return -1; } } return res; } /** * Reads up to len bytes of data from this input stream * into an array of bytes. If len is not zero, the method * blocks until some input is available; otherwise, no * bytes are read and 0 is returned. *

* This method simply performs in.read(b, off, len) * and returns the result. * * @param b the buffer into which the data is read. * @param off The start offset in the destination array * b. * @param len the maximum number of bytes read. * @return the total number of bytes read into the buffer, or * -1 if there is no more data because the end of * the stream has been reached. * @exception NullPointerException If b is null. * @exception IndexOutOfBoundsException If off is negative, * len is negative, or len is greater than * b.length - off * @exception IOException if an I/O error occurs. * @see java.io.FilterInputStream#in */ @Override public int read(byte[] b, int off, int len) throws IOException { int res = super.read(b, off, len); if (res > 0) { count += res; if (hasReachedLimit()) { return -1; } } return res; } private boolean hasReachedLimit() throws IOException { if (count > limit.toBytes()) { if (throwIfTooManyBytes == SILENTLY_EOF_ON_REACHING_LIMIT) { return true; } Exception tooManyBytes = throwIfTooManyBytes.get(); if (tooManyBytes instanceof IOException) { throw (IOException) tooManyBytes; } else { throw asUnchecked(tooManyBytes); } } else { return false; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy