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 package org.apache.commons.fileupload.util;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23
24 import org.apache.commons.fileupload.InvalidFileNameException;
25 import org.apache.commons.io.IOUtils;
26 import org.apache.commons.io.output.NullOutputStream;
27
28 /**
29 * Utility class for working with streams.
30 */
31 public final class Streams {
32
33 /**
34 * Default buffer size for use in
35 * {@link #copy(InputStream, OutputStream, boolean)}.
36 */
37 public static final int DEFAULT_BUFFER_SIZE = 8192;
38
39 /**
40 * This convenience method allows to read a
41 * {@link org.apache.commons.fileupload.FileItemStream}'s
42 * content into a string. The platform's default character encoding
43 * is used for converting bytes into characters.
44 *
45 * @param inputStream The input stream to read.
46 * @see #asString(InputStream, String)
47 * @return The streams contents, as a string.
48 * @throws IOException An I/O error occurred.
49 */
50 public static String asString(final InputStream inputStream) throws IOException {
51 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
52 copy(inputStream, baos, true);
53 return baos.toString();
54 }
55
56 /**
57 * This convenience method allows to read a
58 * {@link org.apache.commons.fileupload.FileItemStream}'s
59 * content into a string, using the given character encoding.
60 *
61 * @param inputStream The input stream to read.
62 * @param encoding The character encoding, typically "UTF-8".
63 * @see #asString(InputStream)
64 * @return The streams contents, as a string.
65 * @throws IOException An I/O error occurred.
66 */
67 public static String asString(final InputStream inputStream, final String encoding) throws IOException {
68 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
69 copy(inputStream, baos, true);
70 return baos.toString(encoding);
71 }
72
73 /**
74 * Checks, whether the given file name is valid in the sense,
75 * that it doesn't contain any NUL characters. If the file name
76 * is valid, it will be returned without any modifications. Otherwise,
77 * an {@link InvalidFileNameException} is raised.
78 *
79 * @param fileName The file name to check
80 * @return Unmodified file name, if valid.
81 * @throws InvalidFileNameException The file name was found to be invalid.
82 */
83 public static String checkFileName(final String fileName) {
84 if (fileName != null && fileName.indexOf('\u0000') != -1) {
85 // fileName.replace("\u0000", "\\0")
86 final StringBuilder sb = new StringBuilder();
87 for (int i = 0; i < fileName.length(); i++) {
88 final char c = fileName.charAt(i);
89 switch (c) {
90 case 0:
91 sb.append("\\0");
92 break;
93 default:
94 sb.append(c);
95 break;
96 }
97 }
98 throw new InvalidFileNameException(fileName,
99 "Invalid file name: " + sb);
100 }
101 return fileName;
102 }
103
104 /**
105 * Copies the contents of the given {@link InputStream}
106 * to the given {@link OutputStream}. Shortcut for
107 * <pre>
108 * copy(pInputStream, outputStream, new byte[8192]);
109 * </pre>
110 *
111 * @param inputStream The input stream, which is being read.
112 * It is guaranteed, that {@link InputStream#close()} is called
113 * on the stream.
114 * @param outputStream The output stream, to which data should
115 * be written. May be null, in which case the input streams
116 * contents are simply discarded.
117 * @param closeOutputStream True guarantees, that {@link OutputStream#close()}
118 * is called on the stream. False indicates, that only
119 * {@link OutputStream#flush()} should be called finally.
120 *
121 * @return Number of bytes, which have been copied.
122 * @throws IOException An I/O error occurred.
123 */
124 public static long copy(final InputStream inputStream, final OutputStream outputStream,
125 final boolean closeOutputStream)
126 throws IOException {
127 return copy(inputStream, outputStream, closeOutputStream, new byte[DEFAULT_BUFFER_SIZE]);
128 }
129
130 /**
131 * Copies the contents of the given {@link InputStream}
132 * to the given {@link OutputStream}.
133 *
134 * @param inputStream The input stream, which is being read.
135 * It is guaranteed, that {@link InputStream#close()} is called
136 * on the stream.
137 * @param outputStream The output stream, to which data should
138 * be written. May be null, in which case the input streams
139 * contents are simply discarded.
140 * @param closeOutputStream True guarantees, that {@link OutputStream#close()}
141 * is called on the stream. False indicates, that only
142 * {@link OutputStream#flush()} should be called finally.
143 * @param buffer Temporary buffer, which is to be used for
144 * copying data.
145 * @return Number of bytes, which have been copied.
146 * @throws IOException An I/O error occurred.
147 */
148 public static long copy(final InputStream inputStream, final OutputStream outputStream, final boolean closeOutputStream, final byte[] buffer)
149 throws IOException {
150 try {
151 return IOUtils.copyLarge(inputStream, outputStream != null ? outputStream : NullOutputStream.INSTANCE, buffer);
152 } finally {
153 IOUtils.closeQuietly(inputStream);
154 if (closeOutputStream) {
155 IOUtils.closeQuietly(outputStream);
156 }
157 }
158 }
159
160 /**
161 * Private constructor, to prevent instantiation.
162 * This class has only static methods.
163 */
164 private Streams() {
165 // Does nothing
166 }
167
168 }