001 /*
002 * Copyright 2011 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 */
016 package org.kuali.kfs.sys.web.struts;
017
018 import java.io.File;
019 import java.io.FileInputStream;
020 import java.io.FileNotFoundException;
021 import java.io.InputStream;
022 import java.util.ArrayList;
023 import java.util.HashMap;
024 import java.util.List;
025 import java.util.Map;
026 import java.util.Set;
027
028 import javax.servlet.http.HttpServletRequest;
029 import javax.servlet.http.HttpServletResponse;
030
031 import org.apache.commons.lang.StringUtils;
032 import org.apache.struts.action.ActionForm;
033 import org.apache.struts.action.ActionForward;
034 import org.apache.struts.action.ActionMapping;
035 import org.apache.struts.upload.FormFile;
036 import org.kuali.kfs.sys.KFSConstants;
037 import org.kuali.kfs.sys.KFSKeyConstants;
038 import org.kuali.kfs.sys.batch.BatchInputFileSetType;
039 import org.kuali.kfs.sys.batch.BatchSpringContext;
040 import org.kuali.kfs.sys.batch.service.BatchInputFileSetService;
041 import org.kuali.kfs.sys.businessobject.BatchUpload;
042 import org.kuali.kfs.sys.context.SpringContext;
043 import org.kuali.kfs.sys.exception.FileStorageException;
044 import org.kuali.rice.kim.bo.Person;
045 import org.kuali.rice.kim.bo.impl.KimAttributes;
046 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
047 import org.kuali.rice.kim.service.IdentityManagementService;
048 import org.kuali.rice.kim.util.KimCommonUtils;
049 import org.kuali.rice.kim.util.KimConstants;
050 import org.kuali.rice.kns.exception.AuthorizationException;
051 import org.kuali.rice.kns.exception.ValidationException;
052 import org.kuali.rice.kns.util.GlobalVariables;
053 import org.kuali.rice.kns.util.KNSConstants;
054 import org.kuali.rice.kns.util.WebUtils;
055 import org.kuali.rice.kns.web.struts.action.KualiAction;
056 import org.kuali.rice.core.util.KeyLabelPair;
057
058 /**
059 * This class is the struts action for the batch upload screen that supports file sets
060 */
061 public class KualiBatchInputFileSetAction extends KualiAction {
062 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiBatchInputFileSetAction.class);
063 private static IdentityManagementService identityManagementService;
064 private IdentityManagementService getIdentityManagementService() {
065 if (identityManagementService == null) {
066 identityManagementService = SpringContext.getBean(IdentityManagementService.class);
067 }
068 return identityManagementService;
069 }
070
071 /**
072 * @see org.kuali.rice.kns.web.struts.action.KualiAction#execute(org.apache.struts.action.ActionMapping,
073 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
074 */
075 @Override
076 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
077 ActionForward forward = super.execute(mapping, form, request, response);
078 setupForm((KualiBatchInputFileSetForm) form);
079 return forward;
080 }
081
082 /**
083 * @see org.kuali.rice.kns.web.struts.action.KualiAction#checkAuthorization(org.apache.struts.action.ActionForm, java.lang.String)
084 */
085 @Override
086 protected void checkAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
087 BatchUpload batchUpload = ((KualiBatchInputFileSetForm) form).getBatchUpload();
088 BatchInputFileSetType batchInputFileType = retrieveBatchInputFileSetTypeImpl(batchUpload.getBatchInputTypeName());
089 AttributeSet permissionDetails = new AttributeSet();
090 permissionDetails.put(KimAttributes.NAMESPACE_CODE, KimCommonUtils.getNamespaceCode(batchInputFileType.getClass()));
091 permissionDetails.put(KimAttributes.BEAN_NAME, batchUpload.getBatchInputTypeName());
092 if (!getIdentityManagementService().isAuthorizedByTemplateName(GlobalVariables.getUserSession().getPrincipalId(), KNSConstants.KNS_NAMESPACE, KFSConstants.PermissionTemplate.UPLOAD_BATCH_INPUT_FILES.name, permissionDetails, null)) {
093 throw new AuthorizationException(GlobalVariables.getUserSession().getPrincipalName(), methodToCall, batchUpload.getBatchInputTypeName());
094 }
095 }
096
097 /**
098 * Forwards to the batch upload JSP. Initial request.
099 */
100 public ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
101 BatchUpload batchUpload = ((KualiBatchInputFileSetForm) form).getBatchUpload();
102 BatchInputFileSetType batchType = retrieveBatchInputFileSetTypeImpl(batchUpload.getBatchInputTypeName());
103 return mapping.findForward(KFSConstants.MAPPING_BASIC);
104 }
105
106 /**
107 * Sends the uploaded file contents, requested file name, and batch type to the BatchInputTypeService for storage. If errors
108 * were encountered, messages will be in GlobalVariables.errorMap, which is checked and set for display by the request
109 * processor.
110 */
111 public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
112 BatchUpload batchUpload = ((KualiBatchInputFileSetForm) form).getBatchUpload();
113 BatchInputFileSetType batchType = retrieveBatchInputFileSetTypeImpl(batchUpload.getBatchInputTypeName());
114
115 boolean requiredValuesForFilesMissing = false;
116 if (StringUtils.isBlank(batchUpload.getFileUserIdentifer())) {
117 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, KFSKeyConstants.ERROR_BATCH_UPLOAD_NO_FILE_SET_IDENTIFIER_SELECTED, new String[] {});
118 requiredValuesForFilesMissing = true;
119 }
120
121 BatchInputFileSetService batchInputFileSetService = SpringContext.getBean(BatchInputFileSetService.class);
122 if (!batchInputFileSetService.isFileUserIdentifierProperlyFormatted(batchUpload.getFileUserIdentifer())) {
123 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, KFSKeyConstants.ERROR_BATCH_UPLOAD_FILE_SET_IDENTIFIER_BAD_FORMAT);
124 requiredValuesForFilesMissing = true;
125 }
126
127 Map<String, FormFile> uploadedFiles = ((KualiBatchInputFileSetForm) form).getUploadedFiles();
128 Map<String, InputStream> typeToStreamMap = new HashMap<String, InputStream>();
129
130 for (String fileType : uploadedFiles.keySet()) {
131 FormFile uploadedFile = uploadedFiles.get(fileType);
132 if (uploadedFile == null || uploadedFile.getInputStream() == null || uploadedFile.getInputStream().available() == 0) {
133 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, KFSKeyConstants.ERROR_BATCH_UPLOAD_NO_FILE_SELECTED_SAVE_FOR_FILE_TYPE, new String[] { batchType.getFileTypeDescription().get(fileType) });
134 requiredValuesForFilesMissing = true;
135 }
136 else {
137 typeToStreamMap.put(fileType, uploadedFile.getInputStream());
138 }
139 }
140
141 if (requiredValuesForFilesMissing) {
142 return mapping.findForward(KFSConstants.MAPPING_BASIC);
143 }
144
145 try {
146 Map<String, String> typeToSavedFileNames = batchInputFileSetService.save(GlobalVariables.getUserSession().getPerson(), batchType, batchUpload.getFileUserIdentifer(), typeToStreamMap);
147 }
148 catch (FileStorageException e) {
149 LOG.error("Error occured while trying to save file set (probably tried to save a file that already exists).", e);
150 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, KFSKeyConstants.ERROR_BATCH_UPLOAD_FILE_SAVE_ERROR, new String[] { e.getMessage() });
151 return mapping.findForward(KFSConstants.MAPPING_BASIC);
152 }
153 catch (ValidationException e) {
154 LOG.error("Error occured while trying to validate file set.", e);
155 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, KFSKeyConstants.ERROR_BATCH_UPLOAD_FILE_VALIDATION_ERROR);
156 return mapping.findForward(KFSConstants.MAPPING_BASIC);
157 }
158 GlobalVariables.getMessageList().add(KFSKeyConstants.MESSAGE_BATCH_UPLOAD_SAVE_SUCCESSFUL);
159
160 return mapping.findForward(KFSConstants.MAPPING_BASIC);
161 }
162
163 /**
164 * Retrieves a BatchInputFileType implementation from Spring based on the given name.
165 */
166 public BatchInputFileSetType retrieveBatchInputFileSetTypeImpl(String batchInputTypeName) {
167 BatchInputFileSetType batchInputType = BatchSpringContext.getBatchInputFileSetType(batchInputTypeName);
168 if (batchInputType == null) {
169 LOG.error("Batch input type implementation not found for id " + batchInputTypeName);
170 throw new RuntimeException(("Batch input type implementation not found for id " + batchInputTypeName));
171 }
172
173 return batchInputType;
174 }
175
176 /**
177 * Builds list of filenames that the user has permission to manage, and populates the form member. Throws an exception if the
178 * batch file set type is not active. Sets the title key from the batch input type. This method must be called before the action
179 * handler to ensure proper authorization.
180 */
181 public void setupForm(KualiBatchInputFileSetForm form) {
182 BatchInputFileSetType batchInputFileSetType = retrieveBatchInputFileSetTypeImpl(form.getBatchUpload().getBatchInputTypeName());
183
184 if (batchInputFileSetType == null) {
185 LOG.error("Batch input type implementation not found for id " + form.getBatchUpload().getBatchInputTypeName());
186 throw new RuntimeException("Batch input type implementation not found for id " + form.getBatchUpload().getBatchInputTypeName());
187 }
188
189 if (!SpringContext.getBean(BatchInputFileSetService.class).isBatchInputTypeActive(batchInputFileSetType)) {
190 throw new RuntimeException("Batch input file set type is not active.");
191 }
192 form.setBatchInputFileSetType(batchInputFileSetType);
193
194 // set title key
195 form.setTitleKey(batchInputFileSetType.getTitleKey());
196 }
197
198 }
199