001/* 002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 016 * 017 * $Id: InputFileSizeValidator.java 28460 2008-01-03 15:34:05Z sfermigier $ 018 */ 019 020package org.nuxeo.ecm.platform.ui.web.component.file; 021 022import javax.faces.component.StateHolder; 023import javax.faces.component.UIComponent; 024import javax.faces.context.FacesContext; 025import javax.faces.validator.Validator; 026import javax.faces.validator.ValidatorException; 027 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030import org.nuxeo.ecm.core.api.Blob; 031 032import com.sun.faces.util.MessageFactory; 033 034/** 035 * Input file size validator. 036 * <p> 037 * Validates an {@link InputFileInfo} blob value in case it's been uploaded. Value is set using the "maxSize" attribute 038 * and setting it to (for instance) "10Ko", "10Mo" or "10Go". 039 * 040 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 041 */ 042public class InputFileSizeValidator implements Validator, StateHolder { 043 044 public static final String VALIDATOR_ID = "InputFileSizeValidator"; 045 046 private static final Log log = LogFactory.getLog(InputFileSizeValidator.class); 047 048 private String maxSize = null; 049 050 private boolean maximumSet = false; 051 052 private boolean transientValue = false; 053 054 /** 055 * The message identifier of the {@link javax.faces.application.FacesMessage} to be created if the maximum size 056 * check fails. The message format string for this message may optionally include the following placeholders: 057 * <ul> 058 * <li><code>{0}</code> replaced by the configured maximum length.</li> 059 * </ul> 060 */ 061 public static final String MAXIMUM_MESSAGE_ID = "error.inputFile.maxSize"; 062 063 @Override 064 public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { 065 if (!maximumSet) { 066 return; 067 } 068 if (context == null || component == null) { 069 throw new IllegalArgumentException(); 070 } 071 if (value != null) { 072 if (value instanceof InputFileInfo) { 073 InputFileInfo info = (InputFileInfo) value; 074 String choice = info.getConvertedChoice(); 075 if (!(InputFileChoice.isUploadOrKeepTemp(choice))) { 076 return; 077 } 078 Blob blob = info.getConvertedBlob(); 079 long finalMaxSize = 0L; 080 String maxString = null; 081 if (maxSize != null) { 082 finalMaxSize = getMaxSizeBytes(); 083 maxString = maxSize; 084 } 085 if (finalMaxSize != 0L && blob.getLength() > finalMaxSize) { 086 throw new ValidatorException(MessageFactory.getMessage(context, MAXIMUM_MESSAGE_ID, maxString)); 087 } 088 } 089 } 090 } 091 092 private static long parseMaxSizeString(String maxSize) { 093 long res = 0L; 094 if (maxSize != null) { 095 maxSize = maxSize.trim(); 096 if (maxSize.length() < 2) { 097 log.error("Invalid maximum size " + maxSize); 098 return res; 099 } 100 Integer maxSizeInt; 101 String suffix = maxSize.substring(maxSize.length() - 2); 102 String maxSizeIntStr = maxSize.substring(0, maxSize.length() - 2).trim(); 103 try { 104 maxSizeInt = Integer.valueOf(maxSizeIntStr); 105 } catch (NumberFormatException e) { 106 log.error("Invalid maximum size " + maxSize); 107 return res; 108 } 109 // Using IS units 110 if ("Ko".equals(suffix)) { 111 res = maxSizeInt * 1000; 112 } else if ("Mo".equals(suffix)) { 113 res = maxSizeInt * 1000 * 1000; 114 } else if (maxSize.endsWith("Go")) { 115 res = maxSizeInt * 1000 * 1000 * 1000; 116 } else { 117 log.error("Invalid maximum size " + maxSize); 118 } 119 } 120 return res; 121 } 122 123 public String getMaxSize() { 124 return maxSize; 125 } 126 127 public long getMaxSizeBytes() { 128 return parseMaxSizeString(maxSize); 129 } 130 131 public void setMaxSize(String maxSizeString) { 132 maxSize = maxSizeString; 133 maximumSet = true; 134 } 135 136 @Override 137 public boolean isTransient() { 138 return transientValue; 139 } 140 141 @Override 142 public void setTransient(boolean newTransientValue) { 143 transientValue = newTransientValue; 144 } 145 146 @Override 147 public Object saveState(FacesContext context) { 148 Object[] values = new Object[2]; 149 values[0] = maxSize; 150 values[1] = maximumSet ? Boolean.TRUE : Boolean.FALSE; 151 return values; 152 } 153 154 @Override 155 public void restoreState(FacesContext context, Object state) { 156 Object[] values = (Object[]) state; 157 maxSize = (String) values[0]; 158 maximumSet = (Boolean) values[1]; 159 } 160 161}