001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.fileupload.util; 018 019 import java.io.ByteArrayOutputStream; 020 import java.io.IOException; 021 import java.io.InputStream; 022 import java.io.OutputStream; 023 024 import org.apache.commons.fileupload.InvalidFileNameException; 025 026 027 /** Utility class for working with streams. 028 */ 029 public final class Streams { 030 /** 031 * Private constructor, to prevent instantiation. 032 * This class has only static methods. 033 */ 034 private Streams() { 035 // Does nothing 036 } 037 038 /** 039 * Default buffer size for use in 040 * {@link #copy(InputStream, OutputStream, boolean)}. 041 */ 042 private static final int DEFAULT_BUFFER_SIZE = 8192; 043 044 /** 045 * Copies the contents of the given {@link InputStream} 046 * to the given {@link OutputStream}. Shortcut for 047 * <pre> 048 * copy(pInputStream, pOutputStream, new byte[8192]); 049 * </pre> 050 * @param pInputStream The input stream, which is being read. 051 * It is guaranteed, that {@link InputStream#close()} is called 052 * on the stream. 053 * @param pOutputStream The output stream, to which data should 054 * be written. May be null, in which case the input streams 055 * contents are simply discarded. 056 * @param pClose True guarantees, that {@link OutputStream#close()} 057 * is called on the stream. False indicates, that only 058 * {@link OutputStream#flush()} should be called finally. 059 * 060 * @return Number of bytes, which have been copied. 061 * @throws IOException An I/O error occurred. 062 */ 063 public static long copy(InputStream pInputStream, 064 OutputStream pOutputStream, boolean pClose) 065 throws IOException { 066 return copy(pInputStream, pOutputStream, pClose, 067 new byte[DEFAULT_BUFFER_SIZE]); 068 } 069 070 /** 071 * Copies the contents of the given {@link InputStream} 072 * to the given {@link OutputStream}. 073 * @param pIn The input stream, which is being read. 074 * It is guaranteed, that {@link InputStream#close()} is called 075 * on the stream. 076 * @param pOut The output stream, to which data should 077 * be written. May be null, in which case the input streams 078 * contents are simply discarded. 079 * @param pClose True guarantees, that {@link OutputStream#close()} 080 * is called on the stream. False indicates, that only 081 * {@link OutputStream#flush()} should be called finally. 082 * @param pBuffer Temporary buffer, which is to be used for 083 * copying data. 084 * @return Number of bytes, which have been copied. 085 * @throws IOException An I/O error occurred. 086 */ 087 public static long copy(InputStream pIn, 088 OutputStream pOut, boolean pClose, 089 byte[] pBuffer) 090 throws IOException { 091 OutputStream out = pOut; 092 InputStream in = pIn; 093 try { 094 long total = 0; 095 for (;;) { 096 int res = in.read(pBuffer); 097 if (res == -1) { 098 break; 099 } 100 if (res > 0) { 101 total += res; 102 if (out != null) { 103 out.write(pBuffer, 0, res); 104 } 105 } 106 } 107 if (out != null) { 108 if (pClose) { 109 out.close(); 110 } else { 111 out.flush(); 112 } 113 out = null; 114 } 115 in.close(); 116 in = null; 117 return total; 118 } finally { 119 if (in != null) { 120 try { 121 in.close(); 122 } catch (Throwable t) { 123 /* Ignore me */ 124 } 125 } 126 if (pClose && out != null) { 127 try { 128 out.close(); 129 } catch (Throwable t) { 130 /* Ignore me */ 131 } 132 } 133 } 134 } 135 136 /** 137 * This convenience method allows to read a 138 * {@link org.apache.commons.fileupload.FileItemStream}'s 139 * content into a string. The platform's default character encoding 140 * is used for converting bytes into characters. 141 * @param pStream The input stream to read. 142 * @see #asString(InputStream, String) 143 * @return The streams contents, as a string. 144 * @throws IOException An I/O error occurred. 145 */ 146 public static String asString(InputStream pStream) throws IOException { 147 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 148 copy(pStream, baos, true); 149 return baos.toString(); 150 } 151 152 /** 153 * This convenience method allows to read a 154 * {@link org.apache.commons.fileupload.FileItemStream}'s 155 * content into a string, using the given character encoding. 156 * @param pStream The input stream to read. 157 * @param pEncoding The character encoding, typically "UTF-8". 158 * @see #asString(InputStream) 159 * @return The streams contents, as a string. 160 * @throws IOException An I/O error occurred. 161 */ 162 public static String asString(InputStream pStream, String pEncoding) 163 throws IOException { 164 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 165 copy(pStream, baos, true); 166 return baos.toString(pEncoding); 167 } 168 169 /** 170 * Checks, whether the given file name is valid in the sense, 171 * that it doesn't contain any NUL characters. If the file name 172 * is valid, it will be returned without any modifications. Otherwise, 173 * an {@link InvalidFileNameException} is raised. 174 * @param pFileName The file name to check 175 * @return Unmodified file name, if valid. 176 * @throws InvalidFileNameException The file name was found to be invalid. 177 */ 178 public static String checkFileName(String pFileName) { 179 if (pFileName != null && pFileName.indexOf('\u0000') != -1) { 180 // pFileName.replace("\u0000", "\\0") 181 final StringBuffer sb = new StringBuffer(); 182 for (int i = 0; i < pFileName.length(); i++) { 183 char c = pFileName.charAt(i); 184 switch (c) { 185 case 0: 186 sb.append("\\0"); 187 break; 188 default: 189 sb.append(c); 190 break; 191 } 192 } 193 throw new InvalidFileNameException(pFileName, 194 "Invalid file name: " + sb); 195 } 196 return pFileName; 197 } 198 }