001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.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.web.struts.action;
017:
018: import java.io.ByteArrayInputStream;
019: import java.io.File;
020: import java.io.FileInputStream;
021: import java.io.FileNotFoundException;
022: import java.io.InputStream;
023: import java.util.ArrayList;
024: import java.util.List;
025:
026: import javax.servlet.http.HttpServletRequest;
027: import javax.servlet.http.HttpServletResponse;
028:
029: import org.apache.commons.io.IOUtils;
030: import org.apache.commons.lang.StringUtils;
031: import org.apache.struts.action.ActionForm;
032: import org.apache.struts.action.ActionForward;
033: import org.apache.struts.action.ActionMapping;
034: import org.apache.struts.upload.FormFile;
035: import org.kuali.core.authorization.AuthorizationType;
036: import org.kuali.core.bo.user.UniversalUser;
037: import org.kuali.core.exceptions.AuthorizationException;
038: import org.kuali.core.exceptions.ModuleAuthorizationException;
039: import org.kuali.core.util.GlobalVariables;
040: import org.kuali.core.util.WebUtils;
041: import org.kuali.core.web.struts.action.KualiAction;
042: import org.kuali.core.web.ui.KeyLabelPair;
043: import org.kuali.kfs.KFSConstants;
044: import org.kuali.kfs.KFSKeyConstants;
045: import org.kuali.kfs.batch.BatchInputFileType;
046: import org.kuali.kfs.batch.BatchSpringContext;
047: import org.kuali.kfs.bo.BatchUpload;
048: import org.kuali.kfs.context.SpringContext;
049: import org.kuali.kfs.exceptions.FileStorageException;
050: import org.kuali.kfs.exceptions.XMLParseException;
051: import org.kuali.kfs.service.BatchInputFileService;
052: import org.kuali.kfs.web.struts.form.KualiBatchInputFileForm;
053:
054: /**
055: * Handles actions from the batch upload screen.
056: */
057: public class KualiBatchInputFileAction extends KualiAction {
058: private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
059: .getLogger(KualiBatchInputFileAction.class);
060:
061: /**
062: * @see org.kuali.core.web.struts.action.KualiAction#execute(org.apache.struts.action.ActionMapping,
063: * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
064: */
065: @Override
066: public ActionForward execute(ActionMapping mapping,
067: ActionForm form, HttpServletRequest request,
068: HttpServletResponse response) throws Exception {
069: ActionForward forward = super .execute(mapping, form, request,
070: response);
071: setupForm((KualiBatchInputFileForm) form);
072: return forward;
073: }
074:
075: /**
076: * First verifies the user is active for the module in which the batch input type is in, then calls batch input service to
077: * authorize the user for the specific batch input type.
078: *
079: * @see org.kuali.core.web.struts.action.KualiAction#checkAuthorization(org.apache.struts.action.ActionForm, java.lang.String)
080: */
081: @Override
082: protected void checkAuthorization(ActionForm form,
083: String methodToCall) throws AuthorizationException {
084: BatchUpload batchUpload = ((KualiBatchInputFileForm) form)
085: .getBatchUpload();
086: BatchInputFileType batchInputFileType = retrieveBatchInputFileTypeImpl(batchUpload
087: .getBatchInputTypeName());
088:
089: AuthorizationType defaultAuthorizationType = new AuthorizationType.Default(
090: batchInputFileType.getClass());
091: if (!getKualiModuleService().isAuthorized(
092: GlobalVariables.getUserSession().getUniversalUser(),
093: defaultAuthorizationType)) {
094: LOG
095: .error("User not authorized for lookup action for this object: "
096: + batchInputFileType.getClass().getName());
097: throw new ModuleAuthorizationException(GlobalVariables
098: .getUserSession().getUniversalUser()
099: .getPersonUserIdentifier(),
100: defaultAuthorizationType, getKualiModuleService()
101: .getResponsibleModule(
102: batchInputFileType.getClass()));
103: }
104:
105: boolean isAuthorizedForType = SpringContext.getBean(
106: BatchInputFileService.class)
107: .isUserAuthorizedForBatchType(
108: batchInputFileType,
109: GlobalVariables.getUserSession()
110: .getUniversalUser());
111: if (!isAuthorizedForType) {
112: LOG.error("User "
113: + GlobalVariables.getUserSession()
114: .getUniversalUser()
115: .getPersonUserIdentifier()
116: + " is not authorized for batch type "
117: + batchInputFileType.getFileTypeIdentifer());
118: throw new AuthorizationException(GlobalVariables
119: .getUserSession().getUniversalUser()
120: .getPersonUserIdentifier(), "upload",
121: batchInputFileType.getFileTypeIdentifer());
122: }
123: }
124:
125: /**
126: * Forwards to the batch upload JSP. Initial request.
127: */
128: public ActionForward start(ActionMapping mapping, ActionForm form,
129: HttpServletRequest request, HttpServletResponse response)
130: throws Exception {
131: return mapping.findForward(KFSConstants.MAPPING_BASIC);
132: }
133:
134: /**
135: * Sends the uploaded file contents, requested file name, and batch type to the BatchInputTypeService for storage. If errors
136: * were encountered, messages will be in GlobalVariables.errorMap, which is checked and set for display by the request
137: * processor.
138: */
139: public ActionForward save(ActionMapping mapping, ActionForm form,
140: HttpServletRequest request, HttpServletResponse response)
141: throws Exception {
142: BatchUpload batchUpload = ((KualiBatchInputFileForm) form)
143: .getBatchUpload();
144: BatchInputFileType batchType = retrieveBatchInputFileTypeImpl(batchUpload
145: .getBatchInputTypeName());
146:
147: BatchInputFileService batchInputFileService = SpringContext
148: .getBean(BatchInputFileService.class);
149: FormFile uploadedFile = ((KualiBatchInputFileForm) form)
150: .getUploadFile();
151:
152: if (uploadedFile == null
153: || uploadedFile.getInputStream() == null
154: || uploadedFile.getInputStream().available() == 0) {
155: GlobalVariables
156: .getErrorMap()
157: .putError(
158: KFSConstants.GLOBAL_ERRORS,
159: KFSKeyConstants.ERROR_BATCH_UPLOAD_NO_FILE_SELECTED_SAVE,
160: new String[] {});
161: return mapping.findForward(KFSConstants.MAPPING_BASIC);
162: }
163:
164: if (!batchInputFileService
165: .isFileUserIdentifierProperlyFormatted(batchUpload
166: .getFileUserIdentifer())) {
167: GlobalVariables
168: .getErrorMap()
169: .putError(
170: KFSConstants.GLOBAL_ERRORS,
171: KFSKeyConstants.ERROR_BATCH_UPLOAD_FILE_USER_IDENTIFIER_BAD_FORMAT,
172: new String[] {});
173: return mapping.findForward(KFSConstants.MAPPING_BASIC);
174: }
175:
176: InputStream fileContents = ((KualiBatchInputFileForm) form)
177: .getUploadFile().getInputStream();
178: byte[] fileByteContent = IOUtils.toByteArray(fileContents);
179:
180: Object parsedObject = null;
181: try {
182: parsedObject = batchInputFileService.parse(batchType,
183: fileByteContent);
184: } catch (XMLParseException e) {
185: LOG.error("errors parsing xml " + e.getMessage(), e);
186: GlobalVariables.getErrorMap().putError(
187: KFSConstants.GLOBAL_ERRORS,
188: KFSKeyConstants.ERROR_BATCH_UPLOAD_PARSING_XML,
189: new String[] { e.getMessage() });
190: }
191:
192: if (parsedObject != null
193: && GlobalVariables.getErrorMap().isEmpty()) {
194: boolean validateSuccessful = batchInputFileService
195: .validate(batchType, parsedObject);
196:
197: if (validateSuccessful
198: && GlobalVariables.getErrorMap().isEmpty()) {
199: try {
200: InputStream saveStream = new ByteArrayInputStream(
201: fileByteContent);
202:
203: String savedFileName = batchInputFileService.save(
204: GlobalVariables.getUserSession()
205: .getUniversalUser(), batchType,
206: batchUpload.getFileUserIdentifer(),
207: saveStream, parsedObject);
208: GlobalVariables
209: .getMessageList()
210: .add(
211: KFSKeyConstants.MESSAGE_BATCH_UPLOAD_SAVE_SUCCESSFUL);
212: } catch (FileStorageException e1) {
213: LOG.error("errors saving xml " + e1.getMessage(),
214: e1);
215: GlobalVariables.getErrorMap().putError(
216: KFSConstants.GLOBAL_ERRORS,
217: KFSKeyConstants.ERROR_BATCH_UPLOAD_SAVE,
218: new String[] { e1.getMessage() });
219: }
220: }
221: }
222:
223: return mapping.findForward(KFSConstants.MAPPING_BASIC);
224: }
225:
226: /**
227: * Deletes an existing batch file. If errors were encountered, messages will be in GlobalVariables.errorMap, which is checked
228: * and set for display by the request processor.
229: */
230: public ActionForward delete(ActionMapping mapping, ActionForm form,
231: HttpServletRequest request, HttpServletResponse response)
232: throws Exception {
233: KualiBatchInputFileForm kualiBatchInputFileForm = (KualiBatchInputFileForm) form;
234: BatchUpload batchUpload = kualiBatchInputFileForm
235: .getBatchUpload();
236:
237: if (StringUtils.isBlank(batchUpload.getExistingFileName())) {
238: GlobalVariables
239: .getErrorMap()
240: .putError(
241: KFSConstants.GLOBAL_ERRORS,
242: KFSKeyConstants.ERROR_BATCH_UPLOAD_NO_FILE_SELECTED_DELETE,
243: new String[] {});
244: return mapping.findForward(KFSConstants.MAPPING_BASIC);
245: }
246:
247: BatchInputFileType batchType = retrieveBatchInputFileTypeImpl(batchUpload
248: .getBatchInputTypeName());
249: try {
250: boolean deleteSuccessful = SpringContext.getBean(
251: BatchInputFileService.class)
252: .delete(
253: GlobalVariables.getUserSession()
254: .getUniversalUser(), batchType,
255: batchUpload.getExistingFileName());
256:
257: if (deleteSuccessful) {
258: GlobalVariables
259: .getMessageList()
260: .add(
261: KFSKeyConstants.MESSAGE_BATCH_UPLOAD_DELETE_SUCCESSFUL);
262: }
263: // if not successful, the delete method is responsible for populating the error map with the reason why deletion failed
264: } catch (FileNotFoundException e1) {
265: LOG.error("errors deleting file " + e1.getMessage(), e1);
266: GlobalVariables.getErrorMap().putError(
267: KFSConstants.GLOBAL_ERRORS,
268: KFSKeyConstants.ERROR_BATCH_UPLOAD_DELETE,
269: new String[] { e1.getMessage() });
270: }
271:
272: return mapping.findForward(KFSConstants.MAPPING_BASIC);
273: }
274:
275: /**
276: * Retrieves the contents of an uploaded batch file. If errors were encountered, messages will be in GlobalVariables.errorMap,
277: * which is checked and set for display by the request processor.
278: */
279: public ActionForward download(ActionMapping mapping,
280: ActionForm form, HttpServletRequest request,
281: HttpServletResponse response) throws Exception {
282: KualiBatchInputFileForm kualiBatchInputFileForm = (KualiBatchInputFileForm) form;
283: BatchUpload batchUpload = kualiBatchInputFileForm
284: .getBatchUpload();
285:
286: if (StringUtils.isBlank(batchUpload.getExistingFileName())) {
287: GlobalVariables
288: .getErrorMap()
289: .putError(
290: KFSConstants.GLOBAL_ERRORS,
291: KFSKeyConstants.ERROR_BATCH_UPLOAD_NO_FILE_SELECTED_DOWNLOAD,
292: new String[] {});
293: return mapping.findForward(KFSConstants.MAPPING_BASIC);
294: }
295:
296: BatchInputFileType batchType = retrieveBatchInputFileTypeImpl(batchUpload
297: .getBatchInputTypeName());
298: File batchInputFile = null;
299: try {
300: batchInputFile = SpringContext.getBean(
301: BatchInputFileService.class)
302: .download(
303: GlobalVariables.getUserSession()
304: .getUniversalUser(), batchType,
305: batchUpload.getExistingFileName());
306: } catch (FileNotFoundException e1) {
307: LOG.error("errors downloading file " + e1.getMessage(), e1);
308: GlobalVariables.getErrorMap().putError(
309: KFSConstants.GLOBAL_ERRORS,
310: KFSKeyConstants.ERROR_BATCH_UPLOAD_DOWNLOAD,
311: new String[] { e1.getMessage() });
312:
313: return mapping.findForward(KFSConstants.MAPPING_BASIC);
314: }
315:
316: WebUtils.saveMimeInputStreamAsFile(response, "text/plain",
317: new FileInputStream(batchInputFile), batchInputFile
318: .getName(), new Long(batchInputFile.length())
319: .intValue());
320:
321: return null;
322: }
323:
324: /**
325: * Retrieves a BatchInputFileType implementation from Spring based on the given name.
326: */
327: private BatchInputFileType retrieveBatchInputFileTypeImpl(
328: String batchInputTypeName) {
329: BatchInputFileType batchInputType = BatchSpringContext
330: .getBatchInputFileType(batchInputTypeName);
331: if (batchInputType == null) {
332: LOG
333: .error("Batch input type implementation not found for id "
334: + batchInputTypeName);
335: throw new RuntimeException(
336: ("Batch input type implementation not found for id " + batchInputTypeName));
337: }
338:
339: return batchInputType;
340: }
341:
342: /**
343: * Builds list of filenames that the user has permission to manage, and populates the form member. Sets the title key from the
344: * batch input type.
345: */
346: private void setupForm(KualiBatchInputFileForm form) {
347: List<KeyLabelPair> userFiles = new ArrayList();
348:
349: UniversalUser user = GlobalVariables.getUserSession()
350: .getUniversalUser();
351: BatchInputFileType batchInputFileType = retrieveBatchInputFileTypeImpl(form
352: .getBatchUpload().getBatchInputTypeName());
353:
354: if (batchInputFileType == null) {
355: LOG
356: .error("Batch input type implementation not found for id "
357: + form.getBatchUpload()
358: .getBatchInputTypeName());
359: throw new RuntimeException(
360: ("Batch input type implementation not found for id " + form
361: .getBatchUpload().getBatchInputTypeName()));
362: }
363:
364: BatchInputFileService batchInputFileService = SpringContext
365: .getBean(BatchInputFileService.class);
366: List<String> userFileNames = batchInputFileService
367: .listBatchTypeFilesForUser(batchInputFileType, user);
368:
369: userFiles.add(new KeyLabelPair("", ""));
370: for (int i = 0; i < userFileNames.size(); i++) {
371: String fileName = userFileNames.get(i);
372: // do NOT expose the full path name to the browser
373: String key = fileName;
374: String label = fileName;
375: if (batchInputFileService.hasBeenProcessed(
376: batchInputFileType, fileName)) {
377: label = label + " (processed)";
378: } else {
379: label = label + " (ready to process)";
380: }
381: userFiles.add(new KeyLabelPair(key, label));
382: }
383:
384: form.setUserFiles(userFiles);
385:
386: // set title key
387: form.setTitleKey(batchInputFileType.getTitleKey());
388: }
389:
390: }
|