• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package org.apache.commons.io.build;
19 
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.io.Writer;
24 import java.nio.charset.Charset;
25 import java.nio.file.OpenOption;
26 import java.nio.file.Path;
27 import java.util.function.IntUnaryOperator;
28 
29 import org.apache.commons.io.Charsets;
30 import org.apache.commons.io.IOUtils;
31 import org.apache.commons.io.file.PathUtils;
32 
33 /**
34  * Abstracts building a typed instance of {@code T}.
35  *
36  * @param <T> the type of instances to build.
37  * @param <B> the type of builder subclass.
38  * @since 2.12.0
39  */
40 public abstract class AbstractStreamBuilder<T, B extends AbstractStreamBuilder<T, B>> extends AbstractOriginSupplier<T, B> {
41 
42     private static final int DEFAULT_MAX_VALUE = Integer.MAX_VALUE;
43 
44     private static final OpenOption[] DEFAULT_OPEN_OPTIONS = PathUtils.EMPTY_OPEN_OPTION_ARRAY;
45 
46     /**
47      * The buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
48      */
49     private int bufferSize = IOUtils.DEFAULT_BUFFER_SIZE;
50 
51     /**
52      * The buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
53      */
54     private int bufferSizeDefault = IOUtils.DEFAULT_BUFFER_SIZE;
55 
56     /**
57      * The maximum buffer size.
58      */
59     private int bufferSizeMax = DEFAULT_MAX_VALUE;
60 
61     /**
62      * The Charset, defaults to {@link Charset#defaultCharset()}.
63      */
64     private Charset charset = Charset.defaultCharset();
65 
66     /**
67      * The Charset, defaults to {@link Charset#defaultCharset()}.
68      */
69     private Charset charsetDefault = Charset.defaultCharset();
70 
71     private OpenOption[] openOptions = DEFAULT_OPEN_OPTIONS;
72 
73     /**
74      * The default checking behavior for a buffer size request. Throws a {@link IllegalArgumentException} by default.
75      */
76     private final IntUnaryOperator defaultSizeChecker = size -> size > bufferSizeMax ? throwIae(size, bufferSizeMax) : size;
77 
78     /**
79      * The checking behavior for a buffer size request.
80      */
81     private IntUnaryOperator bufferSizeChecker = defaultSizeChecker;
82 
83     /**
84      * Applies the buffer size request.
85      *
86      * @param size the size request.
87      * @return the size to use, usually the input, or can throw an unchecked exception, like {@link IllegalArgumentException}.
88      */
checkBufferSize(final int size)89     private int checkBufferSize(final int size) {
90         return bufferSizeChecker.applyAsInt(size);
91     }
92 
93     /**
94      * Gets the buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
95      *
96      * @return the buffer size, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
97      */
getBufferSize()98     protected int getBufferSize() {
99         return bufferSize;
100     }
101 
102     /**
103      * Gets the buffer size default, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
104      *
105      * @return the buffer size default, defaults to {@link IOUtils#DEFAULT_BUFFER_SIZE} ({@value IOUtils#DEFAULT_BUFFER_SIZE}).
106      */
getBufferSizeDefault()107     protected int getBufferSizeDefault() {
108         return bufferSizeDefault;
109     }
110 
111     /**
112      * Gets a CharSequence from the origin with a Charset.
113      *
114      * @return An input stream
115      * @throws IOException                   if an I/O error occurs.
116      * @throws UnsupportedOperationException if the origin cannot be converted to a CharSequence.
117      * @throws IllegalStateException         if the {@code origin} is {@code null}.
118      * @see AbstractOrigin#getCharSequence(Charset)
119      * @since 2.13.0
120      */
getCharSequence()121     protected CharSequence getCharSequence() throws IOException {
122         return checkOrigin().getCharSequence(getCharset());
123     }
124 
125     /**
126      * Gets the Charset, defaults to {@link Charset#defaultCharset()}.
127      *
128      * @return the Charset, defaults to {@link Charset#defaultCharset()}.
129      */
getCharset()130     public Charset getCharset() {
131         return charset;
132     }
133 
134     /**
135      * Gets the Charset default, defaults to {@link Charset#defaultCharset()}.
136      *
137      * @return the Charset default, defaults to {@link Charset#defaultCharset()}.
138      */
getCharsetDefault()139     protected Charset getCharsetDefault() {
140         return charsetDefault;
141     }
142 
143     /**
144      * Gets an input stream from the origin with open options.
145      *
146      * @return An input stream
147      * @throws IOException                   if an I/O error occurs.
148      * @throws UnsupportedOperationException if the origin cannot be converted to an InputStream.
149      * @see AbstractOrigin#getInputStream(OpenOption...)
150      * @throws IllegalStateException if the {@code origin} is {@code null}.
151      * @since 2.13.0
152      */
getInputStream()153     protected InputStream getInputStream() throws IOException {
154         return checkOrigin().getInputStream(getOpenOptions());
155     }
156 
157     /**
158      * Gets the OpenOption.
159      *
160      * @return the OpenOption.
161      */
getOpenOptions()162     protected OpenOption[] getOpenOptions() {
163         return openOptions;
164     }
165 
166     /**
167      * Gets an OutputStream from the origin with open options.
168      *
169      * @return An OutputStream
170      * @throws IOException                   if an I/O error occurs.
171      * @throws UnsupportedOperationException if the origin cannot be converted to an OutputStream.
172      * @throws IllegalStateException         if the {@code origin} is {@code null}.
173      * @see AbstractOrigin#getOutputStream(OpenOption...)
174      * @since 2.13.0
175      */
getOutputStream()176     protected OutputStream getOutputStream() throws IOException {
177         return checkOrigin().getOutputStream(getOpenOptions());
178     }
179 
180     /**
181      * Gets a Path from the origin.
182      *
183      * @return A Path
184      * @throws UnsupportedOperationException if the origin cannot be converted to a Path.
185      * @throws IllegalStateException         if the {@code origin} is {@code null}.
186      * @see AbstractOrigin#getPath()
187      * @since 2.13.0
188      */
getPath()189     protected Path getPath() {
190         return checkOrigin().getPath();
191     }
192 
193     /**
194      * Gets an writer from the origin with open options.
195      *
196      * @return An writer.
197      * @throws IOException                   if an I/O error occurs.
198      * @throws UnsupportedOperationException if the origin cannot be converted to a Writer.
199      * @throws IllegalStateException         if the {@code origin} is {@code null}.
200      * @see AbstractOrigin#getOutputStream(OpenOption...)
201      * @since 2.13.0
202      */
getWriter()203     protected Writer getWriter() throws IOException {
204         return checkOrigin().getWriter(getCharset(), getOpenOptions());
205     }
206 
207     /**
208      * Sets the buffer size. Invalid input (bufferSize &lt;= 0) resets the value to its default.
209      * <p>
210      * Subclasses may ignore this setting.
211      * </p>
212      *
213      * @param bufferSize the buffer size.
214      * @return this.
215      */
setBufferSize(final int bufferSize)216     public B setBufferSize(final int bufferSize) {
217         this.bufferSize = checkBufferSize(bufferSize > 0 ? bufferSize : bufferSizeDefault);
218         return asThis();
219     }
220 
221     /**
222      * Sets the buffer size.
223      * <p>
224      * Subclasses may ignore this setting.
225      * </p>
226      *
227      * @param bufferSize the buffer size, null resets to the default.
228      * @return this.
229      */
setBufferSize(final Integer bufferSize)230     public B setBufferSize(final Integer bufferSize) {
231         setBufferSize(bufferSize != null ? bufferSize : bufferSizeDefault);
232         return asThis();
233     }
234 
235     /**
236      * Sets the buffer size checker function. Throws a {@link IllegalArgumentException} by default.
237      *
238      * @param bufferSizeChecker the buffer size checker function. null resets to the default behavior.
239      * @return this
240      * @since 2.14.0
241      */
setBufferSizeChecker(final IntUnaryOperator bufferSizeChecker)242     public B setBufferSizeChecker(final IntUnaryOperator bufferSizeChecker) {
243         this.bufferSizeChecker = bufferSizeChecker != null ? bufferSizeChecker : defaultSizeChecker;
244         return asThis();
245     }
246 
247     /**
248      * Sets the buffer size for subclasses to initialize.
249      * <p>
250      * Subclasses may ignore this setting.
251      * </p>
252      *
253      * @param bufferSizeDefault the buffer size, null resets to the default.
254      * @return this.
255      */
setBufferSizeDefault(final int bufferSizeDefault)256     protected B setBufferSizeDefault(final int bufferSizeDefault) {
257         this.bufferSizeDefault = bufferSizeDefault;
258         return asThis();
259     }
260 
261     /**
262      * The maximum buffer size checked by the buffer size checker. Values less or equal to 0, resets to the int max value. By default, if this value is
263      * exceeded, this methods throws an {@link IllegalArgumentException}.
264      *
265      * @param bufferSizeMax maximum buffer size checked by the buffer size checker.
266      * @return this.
267      * @since 2.14.0
268      */
setBufferSizeMax(final int bufferSizeMax)269     public B setBufferSizeMax(final int bufferSizeMax) {
270         this.bufferSizeMax = bufferSizeMax > 0 ? bufferSizeMax : DEFAULT_MAX_VALUE;
271         return asThis();
272     }
273 
274     /**
275      * Sets the Charset.
276      * <p>
277      * Subclasses may ignore this setting.
278      * </p>
279      *
280      * @param charset the Charset, null resets to the default.
281      * @return this.
282      */
setCharset(final Charset charset)283     public B setCharset(final Charset charset) {
284         this.charset = Charsets.toCharset(charset, charsetDefault);
285         return asThis();
286     }
287 
288     /**
289      * Sets the Charset.
290      * <p>
291      * Subclasses may ignore this setting.
292      * </p>
293      *
294      * @param charset the Charset name, null resets to the default.
295      * @return this.
296      */
setCharset(final String charset)297     public B setCharset(final String charset) {
298         return setCharset(Charsets.toCharset(charset, charsetDefault));
299     }
300 
301     /**
302      * Sets the Charset default for subclasses to initialize.
303      * <p>
304      * Subclasses may ignore this setting.
305      * </p>
306      *
307      * @param defaultCharset the Charset name, null resets to the default.
308      * @return this.
309      */
setCharsetDefault(final Charset defaultCharset)310     protected B setCharsetDefault(final Charset defaultCharset) {
311         this.charsetDefault = defaultCharset;
312         return asThis();
313     }
314 
315     /**
316      * Sets the OpenOption[].
317      * <p>
318      * Normally used with InputStream, OutputStream, and Writer.
319      * </p>
320      * <p>
321      * Subclasses may ignore this setting.
322      * </p>
323      *
324      * @param openOptions the OpenOption[] name, null resets to the default.
325      * @return this.
326      * @since 2.13.0
327      * @see #setInputStream(InputStream)
328      * @see #setOutputStream(OutputStream)
329      * @see #setWriter(Writer)
330      */
setOpenOptions(final OpenOption... openOptions)331     public B setOpenOptions(final OpenOption... openOptions) {
332         this.openOptions = openOptions != null ? openOptions : DEFAULT_OPEN_OPTIONS;
333         return asThis();
334     }
335 
throwIae(final int size, final int max)336     private int throwIae(final int size, final int max) {
337         throw new IllegalArgumentException(String.format("Request %,d exceeds maximum %,d", size, max));
338     }
339 }
340