001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.ade.upload; 029 030import org.opencms.gwt.shared.CmsUploadProgessInfo; 031import org.opencms.gwt.shared.CmsUploadProgessInfo.UPLOAD_STATE; 032import org.opencms.main.CmsLog; 033import org.opencms.util.CmsUUID; 034 035import java.io.Serializable; 036 037import org.apache.commons.fileupload.ProgressListener; 038import org.apache.commons.logging.Log; 039 040/** 041 * Provides the upload listener for the upload widget.<p> 042 * 043 * @since 8.0.0 044 */ 045public class CmsUploadListener implements ProgressListener, Serializable { 046 047 /** The log object for this class. */ 048 private static final Log LOG = CmsLog.getLog(CmsUploadListener.class); 049 050 /** The serial version id. */ 051 private static final long serialVersionUID = -6431275569719042836L; 052 053 /** The content length of the request (larger than the sum of file sizes). */ 054 protected long m_contentLength; 055 056 /** Stores the exception if one has been occurred. */ 057 protected RuntimeException m_exception; 058 059 /** Signals that there occurred an exception before. */ 060 protected boolean m_exceptionTrhown; 061 062 /** The bytes read so far. */ 063 private long m_bytesRead; 064 065 /** The upload delay. */ 066 private int m_delay; 067 068 /** A flag that signals if the upload is finished. */ 069 private boolean m_finished; 070 071 /** The UUID for this listener. */ 072 private CmsUUID m_id; 073 074 /** Stores the current item. */ 075 private int m_item; 076 077 /** The timeout watch dog for this listener. */ 078 private CmsUploadTimeoutWatcher m_watcher; 079 080 /** 081 * The public constructor for the listener.<p> 082 * 083 * @param requestSize content length of the request (larger than the sum of file sizes) 084 */ 085 public CmsUploadListener(int requestSize) { 086 087 m_id = new CmsUUID(); 088 m_contentLength = Long.valueOf(requestSize).longValue(); 089 startWatcher(); 090 } 091 092 /** 093 * Sets the exception that should cancel the upload on the next update.<p> 094 * 095 * @param e the exception 096 */ 097 public void cancelUpload(CmsUploadException e) { 098 099 m_exception = e; 100 } 101 102 /** 103 * Returns the bytes transfered so far.<p> 104 * 105 * @return the bytes transfered so far 106 */ 107 public long getBytesRead() { 108 109 return m_bytesRead; 110 } 111 112 /** 113 * Returns the content length of the request (larger than the sum of file sizes).<p> 114 * 115 * @return the content length of the request (larger than the sum of file sizes) 116 */ 117 public long getContentLength() { 118 119 return m_contentLength; 120 } 121 122 /** 123 * Returns the exception.<p> 124 * 125 * @return the exception 126 */ 127 public RuntimeException getException() { 128 129 return m_exception; 130 } 131 132 /** 133 * Returns the listeners UUID.<p> 134 * 135 * @return the listeners UUID 136 */ 137 public CmsUUID getId() { 138 139 return m_id; 140 } 141 142 /** 143 * Returns the current progress info of the upload.<p> 144 * 145 * @return the progress info 146 */ 147 public CmsUploadProgessInfo getInfo() { 148 149 if (m_finished) { 150 return new CmsUploadProgessInfo( 151 getItem(), 152 (int)getPercent(), 153 UPLOAD_STATE.finished, 154 getContentLength(), 155 getBytesRead()); 156 } 157 return new CmsUploadProgessInfo( 158 getItem(), 159 (int)getPercent(), 160 UPLOAD_STATE.running, 161 getContentLength(), 162 getBytesRead()); 163 } 164 165 /** 166 * Returns the number of the field, which is currently being read.<p> 167 * <ul> 168 * <li>0 = no item so far 169 * <li>1 = first item is being read, ... 170 * </ul> 171 172 * @return the number of the field, which is currently being read. 173 */ 174 public int getItem() { 175 176 return m_item; 177 } 178 179 /** 180 * Returns the percent done of the current upload.<p> 181 * 182 * @return the percent done of the current upload 183 */ 184 public long getPercent() { 185 186 return m_contentLength != 0 ? (m_bytesRead * 100) / m_contentLength : 0; 187 } 188 189 /** 190 * Returns <code>true</code> if the process has been canceled due to an error or by the user.<p> 191 * 192 * @return boolean<code>true</code> if the process has been canceled due to an error or by the user 193 */ 194 public boolean isCanceled() { 195 196 return m_exception != null; 197 } 198 199 /** 200 * Returns the finished.<p> 201 * 202 * @return the finished 203 */ 204 public boolean isFinished() { 205 206 return m_finished; 207 } 208 209 /** 210 * Sets the delay.<p> 211 * 212 * @param delay the delay to set 213 */ 214 public void setDelay(int delay) { 215 216 m_delay = delay; 217 } 218 219 /** 220 * Sets the finished.<p> 221 * 222 * @param finished the finished to set 223 */ 224 public void setFinished(boolean finished) { 225 226 m_finished = finished; 227 } 228 229 /** 230 * @see java.lang.Object#toString() 231 */ 232 @Override 233 public String toString() { 234 235 return "UUID=" 236 + getId() 237 + " total=" 238 + getContentLength() 239 + " done=" 240 + getBytesRead() 241 + " cancelled=" 242 + isCanceled(); 243 } 244 245 /** 246 * Updates the listeners status information and does the following steps: 247 * <ul> 248 * <li> returns if there was already thrown an exception before 249 * <li> sets the local variables to the current upload state 250 * <li> throws an RuntimeException if it was set in the meanwhile (by another request e.g. user has canceled) 251 * <li> slows down the upload process if it's configured 252 * <li> stops the watcher if the upload has reached more than 100 percent 253 * </ul> 254 * 255 * @see org.apache.commons.fileupload.ProgressListener#update(long, long, int) 256 */ 257 public void update(long done, long total, int item) { 258 259 if (m_exceptionTrhown) { 260 return; 261 } 262 263 m_bytesRead = done; 264 m_contentLength = total; 265 m_item = item; 266 267 // If an other request has set an exception, it is thrown so the commons-fileupload's 268 // parser stops and the connection is closed. 269 if (isCanceled()) { 270 m_exceptionTrhown = true; 271 throw m_exception; 272 } 273 274 // Just a way to slow down the upload process and see the progress bar in fast networks. 275 if ((m_delay > 0) && (done < total)) { 276 try { 277 Thread.sleep(m_delay); 278 } catch (Exception e) { 279 m_exception = new RuntimeException(e); 280 } 281 } 282 if (getPercent() >= 100) { 283 stopWatcher(); 284 } 285 } 286 287 /** 288 * Starts the watcher.<p> 289 */ 290 private void startWatcher() { 291 292 if (m_watcher == null) { 293 try { 294 m_watcher = new CmsUploadTimeoutWatcher(this); 295 m_watcher.start(); 296 } catch (Exception e) { 297 LOG.info( 298 Messages.get().getBundle().key(Messages.LOG_UPLOAD_CREATE_WATCH_DOG_2, getId(), e.getMessage())); 299 } 300 } 301 } 302 303 /** 304 * Stops the watcher.<p> 305 */ 306 private void stopWatcher() { 307 308 if (m_watcher != null) { 309 m_watcher.cancel(); 310 } 311 } 312}