1919import java .io .IOException ;
2020import java .io .OutputStream ;
2121
22+ import org .apache .commons .io .function .IOConsumer ;
23+ import org .apache .commons .io .function .IOFunction ;
24+
2225/**
2326 * An output stream which triggers an event when a specified number of bytes of data have been written to it. The event
2427 * can be used, for example, to throw an exception if a maximum has been reached, or to switch the underlying stream
3235 * when a pending write operation would cause the threshold to be exceeded.
3336 * </p>
3437 */
35- public abstract class ThresholdingOutputStream extends OutputStream {
38+ public class ThresholdingOutputStream extends OutputStream {
39+
40+ /**
41+ * Noop output stream getter function.
42+ */
43+ private static IOFunction <ThresholdingOutputStream , OutputStream > NOOP_OS_GETTER = os -> NullOutputStream .NULL_OUTPUT_STREAM ;
3644
3745 /**
3846 * The threshold at which the event will be triggered.
3947 */
4048 private final int threshold ;
4149
50+ /**
51+ * Accepts reaching the threshold.
52+ */
53+ private final IOConsumer <ThresholdingOutputStream > thresholdConsumer ;
54+
55+ /**
56+ * Gets the output stream.
57+ */
58+ private final IOFunction <ThresholdingOutputStream , OutputStream > outputStreamGetter ;
59+
4260 /**
4361 * The number of bytes written to the output stream.
4462 */
@@ -55,7 +73,22 @@ public abstract class ThresholdingOutputStream extends OutputStream {
5573 * @param threshold The number of bytes at which to trigger an event.
5674 */
5775 public ThresholdingOutputStream (final int threshold ) {
76+ this (threshold , IOConsumer .noop (), NOOP_OS_GETTER );
77+ }
78+
79+ /**
80+ * Constructs an instance of this class which will trigger an event at the specified threshold.
81+ *
82+ * @param threshold The number of bytes at which to trigger an event.
83+ * @param thresholdConsumer Accepts reaching the threshold.
84+ * @param outputStreamGetter Gets the output stream.
85+ * @since 2.9.0
86+ */
87+ public ThresholdingOutputStream (final int threshold , final IOConsumer <ThresholdingOutputStream > thresholdConsumer ,
88+ final IOFunction <ThresholdingOutputStream , OutputStream > outputStreamGetter ) {
5889 this .threshold = threshold ;
90+ this .thresholdConsumer = thresholdConsumer == null ? IOConsumer .noop () : thresholdConsumer ;
91+ this .outputStreamGetter = outputStreamGetter == null ? NOOP_OS_GETTER : outputStreamGetter ;
5992 }
6093
6194 /**
@@ -116,7 +149,9 @@ public long getByteCount() {
116149 *
117150 * @throws IOException if an error occurs.
118151 */
119- protected abstract OutputStream getStream () throws IOException ;
152+ protected OutputStream getStream () throws IOException {
153+ return outputStreamGetter .apply (this );
154+ }
120155
121156 /**
122157 * Returns the threshold, in bytes, at which an event will be triggered.
@@ -162,7 +197,9 @@ protected void setByteCount(final long count) {
162197 *
163198 * @throws IOException if an error occurs.
164199 */
165- protected abstract void thresholdReached () throws IOException ;
200+ protected void thresholdReached () throws IOException {
201+ thresholdConsumer .accept (this );
202+ }
166203
167204 /**
168205 * Writes {@code b.length} bytes from the specified byte array to this output stream.
0 commit comments