package org.joget.commons.util; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.joget.commons.spring.model.Setting; import org.springframework.web.multipart.MultipartFile; /** * Utility class to act as a temporary holder to manage the files posted in a HTTP request * */ public class FileStore { private static Integer fileSizeLimit; /** * Get the file size limit of the system in byte * @return */ public static long getFileSizeLimitLong() { if (fileSizeLimit != -1) { return fileSizeLimit * 1024 * 1024L; } return -1L; } /** * Method call to refresh the file size limit based on system setting */ public static void updateFileSizeLimit() { fileSizeLimit = -1; SetupManager setupManager = (SetupManager) SecurityUtil.getApplicationContext().getBean("setupManager"); Setting setting = setupManager.getSettingByProperty("fileSizeLimit"); if (setting != null && setting.getValue() != null && !setting.getValue().isEmpty()) { try { fileSizeLimit = Integer.parseInt(setting.getValue()); } catch (Exception e) { LogUtil.debug(FileStore.class.getName(), "System Setting for File Size limit is not a valid number"); } } } /** * Get the file size limit of the system in MB * @return */ public static int getFileSizeLimit() { if (fileSizeLimit == null) { updateFileSizeLimit(); } return fileSizeLimit; } private static ThreadLocal fileStore = new ThreadLocal() { @Override protected synchronized Object initialValue() { return new HashMap<String, MultipartFile[]>(); } }; private static ThreadLocal filesExceedLimit = new ThreadLocal() { @Override protected synchronized Object initialValue() { return new ArrayList<String>(); } }; /** * Sets the posted files in a HTTP request to a ThreadLocal object for * temporary storing * @param fileMap a map of field name & its files */ public static void setFileMap(Map<String, MultipartFile[]> fileMap) { Collection<String> exceedLimitList = new ArrayList<String> (); Map<String, MultipartFile[]> files = new HashMap<String, MultipartFile[]>(); if (getFileSizeLimit() > 0) { for (String key : fileMap.keySet()) { MultipartFile[] tempFiles = fileMap.get(key); boolean exceedLimit = false; for (MultipartFile file : tempFiles) { if (file.getSize() > getFileSizeLimitLong()) { exceedLimit = true; exceedLimitList.add(key); } } if (!exceedLimit) { files.put(key, tempFiles); } } } else { files = fileMap; } fileStore.set(files); filesExceedLimit.set(exceedLimitList); } /** * Gets all the posted files of the current HTTP request * @return a map of field name & its files */ public static Map<String, MultipartFile[]> getFileMap() { return (Map<String, MultipartFile[]>) fileStore.get(); } /** * Gets a list of the field name which has file exceed the file limit * in the current HTTP request * @return */ public static Collection<String> getFileErrorList() { return (Collection<String>) filesExceedLimit.get(); } /** * Gets the Iterator of all upload field name of the current HTTP request * @return */ public static Iterator<String> getFileNames() { return ((Map<String, MultipartFile[]>) fileStore.get()).keySet().iterator(); } /** * Convenient method to retrieves the posted file in current HTTP request * based on field name * @return */ public static MultipartFile getFile(String name) throws FileLimitException { Collection<String> exceedLimitList = (ArrayList<String>) filesExceedLimit.get(); if (exceedLimitList.contains(name)) { LogUtil.info(FileStore.class.getName(), name + " - File size exceed limit."); throw new FileLimitException("File size exceed limit."); } MultipartFile[] files = ((Map<String, MultipartFile[]>) fileStore.get()).get(name); if (files != null && files.length > 0) { return files[0]; } else { return null; } } /** * Method to retrieves the posted files in current HTTP request based on * field name * @return */ public static MultipartFile[] getFiles(String name) throws FileLimitException { Collection<String> exceedLimitList = (ArrayList<String>) filesExceedLimit.get(); if (exceedLimitList.contains(name)) { LogUtil.info(FileStore.class.getName(), name + " - File size exceed limit."); throw new FileLimitException("File size exceed limit."); } return ((Map<String, MultipartFile[]>) fileStore.get()).get(name); } /** * Method used by the system to clear the ThreadLocal object after a HTTP * request is finish processing */ public static void clear() { fileStore.set(new HashMap<String, MultipartFile>()); filesExceedLimit.set(new ArrayList<String>()); } }