ulrich
2024-02-26 85c480d3d8f2c7214b6d8311ed232f7b385f012e
commit | author | age
85c480 1 /*
U 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 de.uhilger.neon.up;
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
27 /**
28  * Der Lowlevel MultipartParser aus dem Projekt Apache Commons Fileupload 
29  * ohne Abhaengigkeiten zum Rest von Commons Fileupload und Commons IO.
30  * 
31  * Utility class for working with streams.
32  */
33 public final class Streams {
34   
35     /**
36      * Private constructor, to prevent instantiation.
37      * This class has only static methods.
38      */
39     private Streams() {
40         // Does nothing
41     }
42
43     /**
44      * Default buffer size for use in
45      * {@link #copy(InputStream, OutputStream, boolean)}.
46      */
47     private static final int DEFAULT_BUFFER_SIZE = 8192;
48
49     /**
50      * Copies the contents of the given {@link InputStream}
51      * to the given {@link OutputStream}. Shortcut for
52      * <pre>
53      *   copy(pInputStream, pOutputStream, new byte[8192]);
54      * </pre>
55      *
56      * @param inputStream The input stream, which is being read.
57      * It is guaranteed, that {@link InputStream#close()} is called
58      * on the stream.
59      * @param outputStream The output stream, to which data should
60      * be written. May be null, in which case the input streams
61      * contents are simply discarded.
62      * @param closeOutputStream True guarantees, that {@link OutputStream#close()}
63      * is called on the stream. False indicates, that only
64      * {@link OutputStream#flush()} should be called finally.
65      *
66      * @return Number of bytes, which have been copied.
67      * @throws IOException An I/O error occurred.
68      */
69     public static long copy(InputStream inputStream, OutputStream outputStream, boolean closeOutputStream)
70             throws IOException {
71         return copy(inputStream, outputStream, closeOutputStream, new byte[DEFAULT_BUFFER_SIZE]);
72     }
73
74     /**
75      * Copies the contents of the given {@link InputStream}
76      * to the given {@link OutputStream}.
77      *
78      * @param inputStream The input stream, which is being read.
79      *   It is guaranteed, that {@link InputStream#close()} is called
80      *   on the stream.
81      * @param outputStream The output stream, to which data should
82      *   be written. May be null, in which case the input streams
83      *   contents are simply discarded.
84      * @param closeOutputStream True guarantees, that {@link OutputStream#close()}
85      *   is called on the stream. False indicates, that only
86      *   {@link OutputStream#flush()} should be called finally.
87      * @param buffer Temporary buffer, which is to be used for
88      *   copying data.
89      * @return Number of bytes, which have been copied.
90      * @throws IOException An I/O error occurred.
91      */
92     public static long copy(InputStream inputStream,
93             OutputStream outputStream, boolean closeOutputStream,
94             byte[] buffer)
95     throws IOException {
96         OutputStream out = outputStream;
97         InputStream in = inputStream;
98         try {
99             long total = 0;
100             for (;;) {
101                 int res = in.read(buffer);
102                 if (res == -1) {
103                     break;
104                 }
105                 if (res > 0) {
106                     total += res;
107                     if (out != null) {
108                         out.write(buffer, 0, res);
109                     }
110                 }
111             }
112             if (out != null) {
113                 if (closeOutputStream) {
114                     out.close();
115                 } else {
116                     out.flush();
117                 }
118                 out = null;
119             }
120             in.close();
121             in = null;
122             return total;
123         } finally {
124             closeAlmostQuietly((Closeable) in);
125             if (closeOutputStream) {
126                 closeAlmostQuietly((Closeable) out);
127             }
128         }
129     }
130
131     public static void closeAlmostQuietly(Closeable closeable) {
132         if (closeable != null) {
133             try {
134                 closeable.close();
135             } catch (final IOException e) {
136                 //logger.log(Level.SEVERE, e.getLocalizedMessage(), e);
137                 e.printStackTrace();
138             }
139         }
140     }
141     
142     /**
143      * This convenience method allows to read a
144      * org.apache.commons.fileupload.FileItemStream's
145      * content into a string. The platform's default character encoding
146      * is used for converting bytes into characters.
147      *
148      * @param inputStream The input stream to read.
149      * @see #asString(InputStream, String)
150      * @return The streams contents, as a string.
151      * @throws IOException An I/O error occurred.
152      */
153     public static String asString(InputStream inputStream) throws IOException {
154         ByteArrayOutputStream baos = new ByteArrayOutputStream();
155         copy(inputStream, baos, true);
156         return baos.toString();
157     }
158
159     /**
160      * This convenience method allows to read a
161      * org.apache.commons.fileupload.FileItemStream's
162      * content into a string, using the given character encoding.
163      *
164      * @param inputStream The input stream to read.
165      * @param encoding The character encoding, typically "UTF-8".
166      * @see #asString(InputStream)
167      * @return The streams contents, as a string.
168      * @throws IOException An I/O error occurred.
169      */
170     public static String asString(InputStream inputStream, String encoding) throws IOException {
171         ByteArrayOutputStream baos = new ByteArrayOutputStream();
172         copy(inputStream, baos, true);
173         return baos.toString(encoding);
174     }
175
176     /**
177      * Checks, whether the given file name is valid in the sense,
178      * that it doesn't contain any NUL characters. If the file name
179      * is valid, it will be returned without any modifications. Otherwise,
180      * an InvalidFileNameException is raised.
181      *
182      * @param fileName The file name to check
183      * @return Unmodified file name, if valid.
184      * @throws Exception The file name was found to be invalid.
185      */
186     public static String checkFileName(String fileName) throws Exception {
187         if (fileName != null  &&  fileName.indexOf('\u0000') != -1) {
188             // pFileName.replace("\u0000", "\\0")
189             final StringBuilder sb = new StringBuilder();
190             for (int i = 0;  i < fileName.length();  i++) {
191                 char c = fileName.charAt(i);
192                 switch (c) {
193                     case 0:
194                         sb.append("\\0");
195                         break;
196                     default:
197                         sb.append(c);
198                         break;
199                 }
200             }
201             throw new Exception(fileName + ", Invalid file name: " + sb.toString());
202         }
203         return fileName;
204     }
205
206 }