001/** 002 * Copyright 2005-2018 The Kuali Foundation 003 * 004 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php 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.kuali.rice.krad.web.service.impl; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.krad.file.FileMeta; 020import org.kuali.rice.krad.uif.UifConstants; 021import org.kuali.rice.krad.uif.UifParameters; 022import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle; 023import org.kuali.rice.krad.uif.util.ObjectPropertyUtils; 024import org.kuali.rice.krad.util.KRADUtils; 025import org.kuali.rice.krad.web.form.DialogResponse; 026import org.kuali.rice.krad.web.form.UifFormBase; 027import org.kuali.rice.krad.web.service.CollectionControllerService; 028import org.kuali.rice.krad.web.service.FileControllerService; 029import org.kuali.rice.krad.web.service.ModelAndViewService; 030import org.springframework.web.multipart.MultipartFile; 031import org.springframework.web.multipart.MultipartHttpServletRequest; 032import org.springframework.web.servlet.ModelAndView; 033 034import javax.servlet.http.HttpServletRequest; 035import javax.servlet.http.HttpServletResponse; 036import java.util.Collection; 037import java.util.Date; 038import java.util.Iterator; 039import java.util.List; 040import java.util.UUID; 041 042/** 043 * Default implementation of the file controller service. 044 * 045 * @author Kuali Rice Team (rice.collab@kuali.org) 046 */ 047public class FileControllerServiceImpl implements FileControllerService { 048 049 protected static final String DELETE_FILE_UPLOAD_LINE_DIALOG = "DialogGroup-DeleteFileUploadLine"; 050 051 private CollectionControllerService collectionControllerService; 052 private ModelAndViewService modelAndViewService; 053 054 /** 055 * {@inheritDoc} 056 */ 057 @Override 058 public ModelAndView addFileUploadLine(final UifFormBase form) { 059 form.setAjaxReturnType(UifConstants.AjaxReturnTypes.UPDATECOMPONENT.getKey()); 060 form.setAjaxRequest(true); 061 062 MultipartHttpServletRequest request = (MultipartHttpServletRequest) form.getRequest(); 063 064 final String collectionId = request.getParameter(UifParameters.UPDATE_COMPONENT_ID); 065 final String bindingPath = request.getParameter(UifConstants.PostMetadata.BINDING_PATH); 066 067 Class<?> collectionObjectClass = (Class<?>) form.getViewPostMetadata().getComponentPostData(collectionId, 068 UifConstants.PostMetadata.COLL_OBJECT_CLASS); 069 070 Iterator<String> fileNamesItr = request.getFileNames(); 071 072 while (fileNamesItr.hasNext()) { 073 String propertyPath = fileNamesItr.next(); 074 075 MultipartFile uploadedFile = request.getFile(propertyPath); 076 077 final FileMeta fileObject = (FileMeta) KRADUtils.createNewObjectFromClass(collectionObjectClass); 078 try { 079 fileObject.init(uploadedFile); 080 } catch (Exception e) { 081 throw new RuntimeException("Unable to initialize new file object", e); 082 } 083 084 String id = UUID.randomUUID().toString() + "_" + uploadedFile.getName(); 085 fileObject.setId(id); 086 087 fileObject.setDateUploaded(new Date()); 088 089 fileObject.setUrl("?methodToCall=getFileFromLine&formKey=" 090 + form.getFormKey() 091 + "&fileName=" 092 + fileObject.getName() 093 + "&propertyPath=" 094 + propertyPath); 095 096 ViewLifecycle.encapsulateLifecycle(form.getView(), form, form.getViewPostMetadata(), null, request, 097 new Runnable() { 098 @Override 099 public void run() { 100 ViewLifecycle.getHelper().processAndAddLineObject(form, fileObject, collectionId, 101 bindingPath); 102 } 103 }); 104 } 105 106 return getModelAndViewService().getModelAndView(form); 107 } 108 109 /** 110 * {@inheritDoc} 111 */ 112 @Override 113 public ModelAndView deleteFileUploadLine(UifFormBase form) { 114 DialogResponse deleteFileUploadLineDialogResponse = form.getDialogResponse(DELETE_FILE_UPLOAD_LINE_DIALOG); 115 116 if (deleteFileUploadLineDialogResponse == null) { 117 // no confirmation dialog found, so create one on the form and return it 118 return getModelAndViewService().showDialog(DELETE_FILE_UPLOAD_LINE_DIALOG, true, form); 119 } 120 121 return getCollectionControllerService().deleteLine(form); 122 } 123 124 /** 125 * {@inheritDoc} 126 */ 127 @Override 128 public void getFileFromLine(UifFormBase form, HttpServletResponse response) { 129 HttpServletRequest request = form.getRequest(); 130 131 String selectedCollectionPath = request.getParameter("propertyPath"); 132 133 if (StringUtils.isBlank(selectedCollectionPath)) { 134 throw new RuntimeException("Selected collection was not set for delete line action, cannot delete line"); 135 } 136 137 String selectedLine = request.getParameter(UifParameters.SELECTED_LINE_INDEX); 138 int selectedLineIndex; 139 if (StringUtils.isNotBlank(selectedLine)) { 140 selectedLineIndex = Integer.parseInt(selectedLine); 141 } else { 142 selectedLineIndex = -1; 143 } 144 145 if (selectedLineIndex == -1) { 146 throw new RuntimeException("Selected line index was not set for delete line action, cannot delete line"); 147 } 148 149 Collection<FileMeta> collection = ObjectPropertyUtils.getPropertyValue(form, selectedCollectionPath); 150 151 if (collection instanceof List) { 152 FileMeta fileLine = ((List<FileMeta>) collection).get(selectedLineIndex); 153 sendFileFromLineResponse(form, response, (List<FileMeta>) collection, fileLine); 154 } 155 } 156 157 /** 158 * Hook controller method to send a response back by using response.flushBuffer() using request/collection/fileLine 159 * information provided. 160 * 161 * <p>A sample implementation may look like: 162 * <code> <pre> 163 * if (fileLine instanceof FileMetaBlob) { 164 * InputStream is = ((FileMetaBlob) fileLine).getBlob().getBinaryStream(); 165 * response.setContentType("application/force-download"); 166 * response.setHeader("Content-Disposition", "attachment; filename=" + fileLine.getName()); 167 * 168 * // copy it to response's OutputStream 169 * FileCopyUtils.copy(is, response.getOutputStream()); 170 * 171 * response.flushBuffer(); 172 * } 173 * </pre></code></p> 174 * 175 * @param form form instance containing the file request data 176 * @param response Http response object for streaming back the file contents 177 * @param collection collection the file object belongs to 178 * @param fileLine the particular file line instance the contents should be sent back for 179 */ 180 protected void sendFileFromLineResponse(UifFormBase form, HttpServletResponse response, List<FileMeta> collection, 181 FileMeta fileLine) { 182 // empty method for overrides 183 } 184 185 protected CollectionControllerService getCollectionControllerService() { 186 return collectionControllerService; 187 } 188 189 public void setCollectionControllerService(CollectionControllerService collectionControllerService) { 190 this.collectionControllerService = collectionControllerService; 191 } 192 193 protected ModelAndViewService getModelAndViewService() { 194 return modelAndViewService; 195 } 196 197 public void setModelAndViewService(ModelAndViewService modelAndViewService) { 198 this.modelAndViewService = modelAndViewService; 199 } 200}