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.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.kfs.coa.businessobject.Account;
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.BatchInputFileType;
040    import org.kuali.kfs.sys.batch.BatchSpringContext;
041    import org.kuali.kfs.sys.batch.service.BatchInputFileService;
042    import org.kuali.kfs.sys.businessobject.BatchUpload;
043    import org.kuali.kfs.sys.context.SpringContext;
044    import org.kuali.kfs.sys.exception.FileStorageException;
045    import org.kuali.kfs.sys.exception.ParseException;
046    import org.kuali.rice.kim.bo.Person;
047    import org.kuali.rice.kim.bo.impl.KimAttributes;
048    import org.kuali.rice.kim.bo.types.dto.AttributeSet;
049    import org.kuali.rice.kim.service.IdentityManagementService;
050    import org.kuali.rice.kim.util.KimCommonUtils;
051    import org.kuali.rice.kim.util.KimConstants;
052    import org.kuali.rice.kns.exception.AuthorizationException;
053    import org.kuali.rice.kns.service.ParameterEvaluator;
054    import org.kuali.rice.kns.service.ParameterService;
055    import org.kuali.rice.kns.util.GlobalVariables;
056    import org.kuali.rice.kns.util.KNSConstants;
057    import org.kuali.rice.kns.util.WebUtils;
058    import org.kuali.rice.kns.web.struts.action.KualiAction;
059    import org.kuali.rice.core.util.KeyLabelPair;
060    
061    /**
062     * Handles actions from the batch upload screen.
063     */
064    public class KualiBatchInputFileAction extends KualiAction {
065        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiBatchInputFileAction.class);
066        private static IdentityManagementService identityManagementService;
067        private IdentityManagementService getIdentityManagementService() {
068            if (identityManagementService == null) {
069                identityManagementService = SpringContext.getBean(IdentityManagementService.class);
070            }
071            return identityManagementService;
072        }
073    
074        /**
075         * @see org.kuali.rice.kns.web.struts.action.KualiAction#execute(org.apache.struts.action.ActionMapping,
076         *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
077         */
078        @Override
079        public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
080            ActionForward forward = super.execute(mapping, form, request, response);
081            setupForm((KualiBatchInputFileForm) form);
082            return forward;
083        }
084    
085        @Override
086        protected void checkAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
087            BatchUpload batchUpload = ((KualiBatchInputFileForm) form).getBatchUpload();
088            BatchInputFileType batchInputFileType = retrieveBatchInputFileTypeImpl(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            return mapping.findForward(KFSConstants.MAPPING_BASIC);
102        }
103    
104        /**
105         * Sends the uploaded file contents, requested file name, and batch type to the BatchInputTypeService for storage. If errors
106         * were encountered, messages will be in GlobalVariables.errorMap, which is checked and set for display by the request
107         * processor.
108         */
109        public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
110            BatchUpload batchUpload = ((KualiBatchInputFileForm) form).getBatchUpload();
111            BatchInputFileType batchType = retrieveBatchInputFileTypeImpl(batchUpload.getBatchInputTypeName());
112    
113            BatchInputFileService batchInputFileService = SpringContext.getBean(BatchInputFileService.class);
114            FormFile uploadedFile = ((KualiBatchInputFileForm) form).getUploadFile();
115    
116            if (uploadedFile == null || uploadedFile.getInputStream() == null || uploadedFile.getInputStream().available() == 0) {
117                GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, KFSKeyConstants.ERROR_BATCH_UPLOAD_NO_FILE_SELECTED_SAVE, new String[] {});
118                return mapping.findForward(KFSConstants.MAPPING_BASIC);
119            }
120    
121            if (!batchInputFileService.isFileUserIdentifierProperlyFormatted(batchUpload.getFileUserIdentifer())) {
122                GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, KFSKeyConstants.ERROR_BATCH_UPLOAD_FILE_USER_IDENTIFIER_BAD_FORMAT, new String[] {});
123                return mapping.findForward(KFSConstants.MAPPING_BASIC);
124            }
125    
126            InputStream fileContents = ((KualiBatchInputFileForm) form).getUploadFile().getInputStream();
127            byte[] fileByteContent = IOUtils.toByteArray(fileContents);
128            
129            Object parsedObject = null;
130            try {
131                parsedObject = batchInputFileService.parse(batchType, fileByteContent);
132            }
133            catch (ParseException e) {
134                LOG.error("errors parsing xml " + e.getMessage(), e);
135                GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, KFSKeyConstants.ERROR_BATCH_UPLOAD_PARSING_XML, new String[] { e.getMessage() });
136            }
137    
138            if (parsedObject != null && GlobalVariables.getMessageMap().isEmpty()) {
139                boolean validateSuccessful = batchInputFileService.validate(batchType, parsedObject);
140    
141                if (validateSuccessful && GlobalVariables.getMessageMap().isEmpty()) {
142                    try {
143                        InputStream saveStream = new ByteArrayInputStream(fileByteContent);
144    
145                        String savedFileName = batchInputFileService.save(GlobalVariables.getUserSession().getPerson(), batchType, batchUpload.getFileUserIdentifer(), saveStream, parsedObject);
146                        GlobalVariables.getMessageList().add(KFSKeyConstants.MESSAGE_BATCH_UPLOAD_SAVE_SUCCESSFUL);
147                    }
148                    catch (FileStorageException e1) {
149                        LOG.error("errors saving xml " + e1.getMessage(), e1);
150                        GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, KFSKeyConstants.ERROR_BATCH_UPLOAD_SAVE, new String[] { e1.getMessage() });
151                    }
152                }
153            }
154    
155            return mapping.findForward(KFSConstants.MAPPING_BASIC);
156        }
157    
158        /**
159         * Retrieves a BatchInputFileType implementation from Spring based on the given name.
160         */
161        private BatchInputFileType retrieveBatchInputFileTypeImpl(String batchInputTypeName) {
162            BatchInputFileType batchInputType = BatchSpringContext.getBatchInputFileType(batchInputTypeName);
163            if (batchInputType == null) {
164                LOG.error("Batch input type implementation not found for id " + batchInputTypeName);
165                throw new RuntimeException(("Batch input type implementation not found for id " + batchInputTypeName));
166            }
167    
168            return batchInputType;
169        }
170    
171        /**
172         * Builds list of filenames that the user has permission to manage, and populates the form member. Sets the title key from the
173         * batch input type.
174         */
175        private void setupForm(KualiBatchInputFileForm form) {
176            BatchInputFileType batchInputFileType = retrieveBatchInputFileTypeImpl(form.getBatchUpload().getBatchInputTypeName());
177    
178            if (batchInputFileType == null) {
179                LOG.error("Batch input type implementation not found for id " + form.getBatchUpload().getBatchInputTypeName());
180                throw new RuntimeException(("Batch input type implementation not found for id " + form.getBatchUpload().getBatchInputTypeName()));
181            }
182            ParameterService parmeterService =  SpringContext.getBean(ParameterService.class);
183            String url = parmeterService.getParameterValue(BatchUpload.class,KFSConstants.BATCH_UPLOAD_HELP_SYS_PARAM_NAME, batchInputFileType.getFileTypeIdentifer());
184            form.setUrl(url);
185              // set title key
186            form.setTitleKey(batchInputFileType.getTitleKey());
187        }
188    
189    }
190