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