001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    
020    import java.io.FileInputStream;
021    import java.io.FileOutputStream;
022    import java.io.IOException;
023    import java.io.InputStream;
024    import java.io.OutputStream;
025    
026    import java.nio.channels.Channel;
027    import java.nio.channels.FileChannel;
028    
029    /**
030     * @author Brian Wing Shun Chan
031     * @author Raymond Augé
032     */
033    public class StreamUtil {
034    
035            public static final int BUFFER_SIZE = GetterUtil.getInteger(
036                    System.getProperty(StreamUtil.class.getName() + ".buffer.size"),
037                    8192);
038    
039            public static final boolean FORCE_TIO = GetterUtil.getBoolean(
040                    System.getProperty(StreamUtil.class.getName() + ".force.tio"));
041    
042            public static void cleanUp(Channel channel) {
043                    try {
044                            if (channel != null) {
045                                    channel.close();
046                            }
047                    }
048                    catch (Exception e) {
049                            if (_log.isWarnEnabled()) {
050                                    _log.warn(e, e);
051                            }
052                    }
053            }
054    
055            public static void cleanUp(Channel inputChannel, Channel outputChannel) {
056                    cleanUp(inputChannel);
057                    cleanUp(outputChannel);
058            }
059    
060            public static void cleanUp(InputStream inputStream) {
061                    try {
062                            if (inputStream != null) {
063                                    inputStream.close();
064                            }
065                    }
066                    catch (Exception e) {
067                            if (_log.isWarnEnabled()) {
068                                    _log.warn(e, e);
069                            }
070                    }
071            }
072    
073            public static void cleanUp(
074                    InputStream inputStream, OutputStream outputStream) {
075    
076                    cleanUp(outputStream);
077                    cleanUp(inputStream);
078            }
079    
080            public static void cleanUp(OutputStream outputStream) {
081                    try {
082                            if (outputStream != null) {
083                                    outputStream.flush();
084                            }
085                    }
086                    catch (Exception e) {
087                            if (_log.isWarnEnabled()) {
088                                    _log.warn(e, e);
089                            }
090                    }
091    
092                    try {
093                            if (outputStream != null) {
094                                    outputStream.close();
095                            }
096                    }
097                    catch (Exception e) {
098                            if (_log.isWarnEnabled()) {
099                                    _log.warn(e, e);
100                            }
101                    }
102            }
103    
104            public static void transfer(
105                            InputStream inputStream, OutputStream outputStream)
106                    throws IOException {
107    
108                    transfer(inputStream, outputStream, BUFFER_SIZE, true);
109            }
110    
111            public static void transfer(
112                            InputStream inputStream, OutputStream outputStream, boolean cleanUp)
113                    throws IOException {
114    
115                    transfer(inputStream, outputStream, BUFFER_SIZE, cleanUp);
116            }
117    
118            public static void transfer(
119                            InputStream inputStream, OutputStream outputStream, int bufferSize)
120                    throws IOException {
121    
122                    transfer(inputStream, outputStream, bufferSize, true);
123            }
124    
125            public static void transfer(
126                            InputStream inputStream, OutputStream outputStream, int bufferSize,
127                            boolean cleanUp)
128                    throws IOException {
129    
130                    transfer(inputStream, outputStream, bufferSize, cleanUp, 0);
131            }
132    
133            public static void transfer(
134                            InputStream inputStream, OutputStream outputStream, int bufferSize,
135                            boolean cleanUp, long length)
136                    throws IOException {
137    
138                    if (inputStream == null) {
139                            throw new IllegalArgumentException("Input stream cannot be null");
140                    }
141    
142                    if (outputStream == null) {
143                            throw new IllegalArgumentException("Output stream cannot be null");
144                    }
145    
146                    if (bufferSize <= 0) {
147                            bufferSize = BUFFER_SIZE;
148                    }
149    
150                    try {
151                            if (!FORCE_TIO && (inputStream instanceof FileInputStream) &&
152                                    (outputStream instanceof FileOutputStream)) {
153    
154                                    FileInputStream fileInputStream = (FileInputStream)inputStream;
155                                    FileOutputStream fileOutputStream =
156                                            (FileOutputStream)outputStream;
157    
158                                    transferFileChannel(
159                                            fileInputStream.getChannel(), fileOutputStream.getChannel(),
160                                            length);
161                            }
162                            else {
163                                    transferByteArray(
164                                            inputStream, outputStream, bufferSize, length);
165                            }
166                    }
167                    finally {
168                            if (cleanUp) {
169                                    cleanUp(inputStream, outputStream);
170                            }
171                    }
172            }
173    
174            public static void transfer(
175                            InputStream inputStream, OutputStream outputStream, long length)
176                    throws IOException {
177    
178                    transfer(inputStream, outputStream, BUFFER_SIZE, true, length);
179            }
180    
181            protected static void transferByteArray(
182                            InputStream inputStream, OutputStream outputStream, int bufferSize,
183                            long length)
184                    throws IOException {
185    
186                    byte[] bytes = new byte[bufferSize];
187    
188                    long remainingLength = length;
189    
190                    if (remainingLength > 0) {
191                            while (remainingLength > 0) {
192                                    int readBytes = inputStream.read(
193                                            bytes, 0, (int)Math.min(remainingLength, bufferSize));
194    
195                                    if (readBytes == -1) {
196                                            break;
197                                    }
198    
199                                    outputStream.write(bytes, 0, readBytes);
200    
201                                    remainingLength -= readBytes;
202                            }
203                    }
204                    else {
205                            int value = -1;
206    
207                            while ((value = inputStream.read(bytes)) != -1) {
208                                    outputStream.write(bytes, 0, value);
209                            }
210                    }
211            }
212    
213            protected static void transferFileChannel(
214                            FileChannel inputFileChannel, FileChannel outputFileChannel,
215                            long length)
216                    throws IOException {
217    
218                    long size = 0;
219    
220                    if (length > 0) {
221                            size = length;
222                    }
223                    else {
224                            size = inputFileChannel.size();
225                    }
226    
227                    long position = 0;
228    
229                    while (position < size) {
230                            position += inputFileChannel.transferTo(
231                                    position, size - position, outputFileChannel);
232                    }
233            }
234    
235            private static Log _log = LogFactoryUtil.getLog(StreamUtil.class);
236    
237    }