001    /**
002     * Copyright (c) 2000-2013 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.upload;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.ProgressTracker;
020    
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.io.OutputStream;
024    
025    import javax.portlet.PortletRequest;
026    import javax.portlet.PortletSession;
027    
028    /**
029     * @author Jorge Ferrer
030     * @author Brian Wing Shun Chan
031     * @author Minhchau Dang
032     */
033    public class ProgressInputStream extends InputStream {
034    
035            public ProgressInputStream(
036                    PortletRequest portletRequest, InputStream inputStream, long totalSize,
037                    String progressId) {
038    
039                    _portletSession = portletRequest.getPortletSession();
040                    _inputStream = inputStream;
041                    _totalSize = totalSize;
042                    _progressId = progressId;
043    
044                    initProgress();
045            }
046    
047            @Override
048            public int available() throws IOException {
049                    return _inputStream.available();
050            }
051    
052            public void clearProgress() {
053                    _portletSession.removeAttribute(_getPercentAttributeName());
054            }
055    
056            @Override
057            public void close() throws IOException {
058                    _inputStream.close();
059            }
060    
061            public long getTotalRead() {
062                    return _totalRead;
063            }
064    
065            public void initProgress() {
066                    ProgressTracker progressTracker = new ProgressTracker(_progressId);
067    
068                    progressTracker.initialize(_portletSession);
069            }
070    
071            @Override
072            public void mark(int readlimit) {
073                    _inputStream.mark(readlimit);
074            }
075    
076            @Override
077            public boolean markSupported() {
078                    return _inputStream.markSupported();
079            }
080    
081            @Override
082            public int read() throws IOException {
083                    return _inputStream.read();
084            }
085    
086            @Override
087            public int read(byte[] b) throws IOException {
088                    return read(b, 0, b.length);
089            }
090    
091            @Override
092            public int read(byte[] b, int off, int len) throws IOException {
093                    int bytesRead = super.read(b, off, len);
094    
095                    _updateProgress(bytesRead);
096    
097                    return bytesRead;
098            }
099    
100            public void readAll(OutputStream outputStream) throws IOException {
101                    byte[] buffer = new byte[_DEFAULT_INITIAL_BUFFER_SIZE];
102    
103                    int len = 0;
104    
105                    while ((len = read(buffer)) > 0) {
106                            outputStream.write(buffer, 0, len);
107                    }
108    
109                    outputStream.close();
110            }
111    
112            @Override
113            public void reset() throws IOException {
114                    _inputStream.reset();
115            }
116    
117            @Override
118            public long skip(long n) throws IOException {
119                    long result = _inputStream.skip(n);
120    
121                    _updateProgress(result);
122    
123                    return result;
124            }
125    
126            private String _getPercentAttributeName() {
127                    return ProgressTracker.PERCENT + _progressId;
128            }
129    
130            private void _updateProgress(long bytesRead) {
131                    if (bytesRead > 0) {
132                            _totalRead += bytesRead;
133                    }
134                    else if (_totalSize > 0) {
135                            _totalRead = _totalSize;
136                    }
137    
138                    int percent = 0;
139    
140                    if (_totalSize > 0) {
141                            percent = (int)((_totalRead * 100) / _totalSize);
142                    }
143    
144                    if (_log.isDebugEnabled()) {
145                            _log.debug(_totalRead + "/" + _totalSize + "=" + percent);
146                    }
147    
148                    ProgressTracker progressTracker =
149                            (ProgressTracker)_portletSession.getAttribute(
150                                    _getPercentAttributeName(), PortletSession.APPLICATION_SCOPE);
151    
152                    Integer curPercent = null;
153    
154                    if (progressTracker != null) {
155                            curPercent = progressTracker.getPercent();
156                    }
157    
158                    if ((curPercent == null) || ((percent - curPercent.intValue()) >= 1)) {
159                            if (progressTracker == null) {
160                                    progressTracker = new ProgressTracker(_progressId);
161    
162                                    progressTracker.initialize(_portletSession);
163                            }
164    
165                            progressTracker.setPercent(percent);
166                    }
167            }
168    
169            private static final int _DEFAULT_INITIAL_BUFFER_SIZE = 4 * 1024;
170    
171            private static Log _log = LogFactoryUtil.getLog(ProgressInputStream.class);
172    
173            private InputStream _inputStream;
174            private PortletSession _portletSession;
175            private String _progressId;
176            private long _totalRead;
177            private long _totalSize;
178    
179    }