001/* 002 * Copyright 2012 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.core.upload; 017 018import java.io.IOException; 019import java.io.InputStream; 020import java.util.HashMap; 021import java.util.LinkedHashMap; 022import java.util.Map; 023 024import org.apache.avalon.framework.parameters.Parameters; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.cocoon.acting.Action; 027import org.apache.cocoon.environment.ObjectModelHelper; 028import org.apache.cocoon.environment.Redirector; 029import org.apache.cocoon.environment.Request; 030import org.apache.cocoon.environment.SourceResolver; 031import org.apache.cocoon.servlet.multipart.Part; 032import org.apache.commons.lang.exception.ExceptionUtils; 033 034import org.ametys.core.cocoon.JSonReader; 035import org.ametys.core.upload.Upload; 036import org.ametys.core.upload.UploadManager; 037import org.ametys.core.util.cocoon.AbstractCurrentUserProviderServiceableAction; 038 039/** 040 * {@link Action} for uploading a file and store it using the {@link UploadManager}. 041 */ 042public class UploadAction extends AbstractCurrentUserProviderServiceableAction 043{ 044 /** The Upload Manager */ 045 protected UploadManager _uploadManager; 046 047 @Override 048 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 049 { 050 Request request = ObjectModelHelper.getRequest(objectModel); 051 052 _lookupComponents(); 053 054 Map<String, Object> result = new LinkedHashMap<>(); 055 _doUpload(request, parameters, result); 056 request.setAttribute(JSonReader.OBJECT_TO_READ, result); 057 058 return EMPTY_MAP; 059 } 060 061 /** 062 * Lookup components (lazy initialize) 063 * @throws ServiceException If some components cannot be looked up 064 */ 065 protected void _lookupComponents() throws ServiceException 066 { 067 // Lazy initialize the upload manager because it cannot be found if the config is not complete 068 if (_uploadManager == null) 069 { 070 _uploadManager = (UploadManager) manager.lookup(UploadManager.ROLE); 071 } 072 } 073 074 /** 075 * Do upload the file and fill the result map. 076 * @param request The request 077 * @param parameters The parameters 078 * @param result The result map to fill 079 * @throws Exception if an error occurs. 080 */ 081 protected void _doUpload(Request request, Parameters parameters, Map<String, Object> result) throws Exception 082 { 083 Part partUploaded = _getPart(request); 084 085 if (partUploaded.isRejected()) 086 { 087 result.put("success", false); 088 result.put("error", "rejected"); 089 } 090 else 091 { 092 try (InputStream is = partUploaded.getInputStream()) 093 { 094 _storeUpload(is, partUploaded.getFileName(), result); 095 } 096 catch (IOException e) 097 { 098 _handleStoreUploadException(e, partUploaded, result); 099 } 100 } 101 } 102 103 /** 104 * Gets the {@link Part} object which is trying to be uploaded 105 * @param request The request 106 * @return The {@link Part} object which is trying to be uploaded 107 * @throws Exception if an error occurs. 108 */ 109 protected Part _getPart(Request request) throws Exception 110 { 111 Part partUploaded = (Part) request.get("file"); 112 113 if (partUploaded == null) 114 { 115 throw new Exception("Missing request parameter file"); 116 } 117 118 return partUploaded; 119 } 120 121 /** 122 * Stores the given upload data (as an {@link InputStream}) into the {@link UploadManager} system and fill the result map. 123 * @param is The upload data 124 * @param filename The file name 125 * @param result The result map to fill 126 * @throws IOException if an I/O error occurs 127 */ 128 protected void _storeUpload(InputStream is, String filename, Map<String, Object> result) throws IOException 129 { 130 Upload upload = _uploadManager.storeUpload(_getCurrentUser(), filename, is); 131 _fillSuccess(upload, result); 132 } 133 134 /** 135 * Fill the result map. 136 * @param upload The upload 137 * @param result The result map to fill 138 */ 139 protected void _fillSuccess(Upload upload, Map<String, Object> result) 140 { 141 result.put("success", true); 142 result.put("id", upload.getId()); 143 result.put("filename", upload.getFilename()); 144 result.put("size", upload.getLength()); 145 result.put("viewHref", _getUrlForView(upload)); 146 result.put("downloadHref", _getUrlForDownload(upload)); 147 } 148 149 /** 150 * Handles a store upload exception by filling the result map with information about the exception. 151 * @param e The exception 152 * @param obj The object representing the upload data (for logging purpose) 153 * @param result The result map to fill 154 */ 155 protected void _handleStoreUploadException(IOException e, Object obj, Map<String, Object> result) 156 { 157 getLogger().error("Unable to store uploaded file: " + obj, e); 158 159 result.put("success", false); 160 161 Map<String, String> ex = new HashMap<>(); 162 ex.put("message", e.getMessage()); 163 ex.put("stacktrace", ExceptionUtils.getFullStackTrace(e)); 164 165 result.put("error", ex); 166 } 167 168 /** 169 * Get the url for view the uploaded file 170 * @param upload The file uploaded 171 * @return The url for view 172 */ 173 protected String _getUrlForView(Upload upload) 174 { 175 return "/plugins/core/upload/file?id=" + upload.getId(); 176 } 177 178 /** 179 * Get the url for download the uploaded file 180 * @param upload The file uploaded 181 * @return The url for view 182 */ 183 protected String _getUrlForDownload(Upload upload) 184 { 185 return "/plugins/core/upload/file?id=" + upload.getId() + "&download=true"; 186 } 187}