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.inquiry;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.core.api.exception.RiceRuntimeException;
020import org.kuali.rice.krad.bo.PersistableAttachment;
021import org.kuali.rice.krad.bo.PersistableAttachmentList;
022import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
023import org.kuali.rice.krad.service.ModuleService;
024import org.kuali.rice.krad.uif.UifParameters;
025import org.kuali.rice.krad.util.GlobalVariables;
026import org.kuali.rice.krad.util.KRADConstants;
027import org.kuali.rice.krad.util.KRADUtils;
028import org.kuali.rice.krad.web.form.InquiryForm;
029import org.kuali.rice.krad.web.form.UifFormBase;
030import org.kuali.rice.krad.web.service.impl.ControllerServiceImpl;
031import org.springframework.web.servlet.ModelAndView;
032
033import javax.servlet.http.HttpServletRequest;
034import javax.servlet.http.HttpServletResponse;
035import java.io.ByteArrayInputStream;
036import java.io.IOException;
037import java.lang.reflect.Method;
038import java.util.Properties;
039
040/**
041 * Override of navigation controller service to check if the initial inquiry needs redirected and also to
042 * retrieve the inquiry data object on the initial call.
043 *
044 * @author Kuali Rice Team (rice.collab@kuali.org)
045 */
046public class InquiryControllerServiceImpl extends ControllerServiceImpl implements InquiryControllerService {
047
048    /**
049     * Determines if the inquiry request needs to be redirected based on the module service, if not retrieves
050     * the inquiry data object and sets the instance onto the form for display.
051     *
052     * <p>Note the inquiry data object is retrieved based on the key values passed by the request.</p>
053     *
054     * {@inheritDoc}
055     */
056    @Override
057    public ModelAndView start(UifFormBase form) {
058        InquiryForm inquiryForm = (InquiryForm) form;
059        HttpServletRequest request = form.getRequest();
060
061        Boolean hasRedirectedInquiryParameter = (request.getParameter(UifParameters.REDIRECTED_INQUIRY) != null
062                                         && request.getParameter(UifParameters.REDIRECTED_INQUIRY).contains("true"));
063
064        if (!inquiryForm.isRedirectedInquiry() && !hasRedirectedInquiryParameter) {
065            ModelAndView redirectModelAndView = checkForModuleInquiryRedirect(inquiryForm, request);
066            if (redirectModelAndView != null) {
067                return redirectModelAndView;
068            }
069        }
070
071        // invoke inquirable to retrieve inquiry data object
072        Object dataObject = inquiryForm.getInquirable().retrieveDataObject(KRADUtils.translateRequestParameterMap(
073                request.getParameterMap()));
074
075        inquiryForm.setDataObject(dataObject);
076
077        return super.start(inquiryForm);
078    }
079
080    /**
081     * Checks for a module service that claims the inquiry class as an EBO, and if found redirects to the URL
082     * given by the module service.
083     *
084     * @param inquiryForm form instance containing the inquiry data
085     * @param request http request being handled
086     * @return ModelAndView instance for redirecting to the inquiry, or null if a redirect is not needed
087     */
088    protected ModelAndView checkForModuleInquiryRedirect(InquiryForm inquiryForm, HttpServletRequest request) {
089        Class<?> inquiryObjectClass;
090        try {
091            inquiryObjectClass = Class.forName(inquiryForm.getDataObjectClassName());
092        } catch (ClassNotFoundException e) {
093            throw new RiceRuntimeException("Unable to get class for name: " + inquiryForm.getDataObjectClassName(), e);
094        }
095
096        ModuleService responsibleModuleService =
097                KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(inquiryObjectClass);
098        if (responsibleModuleService != null && responsibleModuleService.isExternalizable(inquiryObjectClass)) {
099            String inquiryUrl = responsibleModuleService.getExternalizableDataObjectInquiryUrl(inquiryObjectClass,
100                    KRADUtils.convertRequestMapToProperties(request.getParameterMap()));
101
102            Properties redirectUrlProps = new Properties();
103            redirectUrlProps.put(UifParameters.REDIRECTED_INQUIRY, "true");
104
105            GlobalVariables.getUifFormManager().removeSessionForm(inquiryForm);
106
107            return getModelAndViewService().performRedirect(inquiryForm, inquiryUrl, redirectUrlProps);
108        }
109
110        return null;
111    }
112
113    /**
114     * {@inheritDoc}
115     */
116    @Override
117    public void downloadDataObjectAttachment(InquiryForm form, HttpServletResponse response) {
118        Object dataObject = form.getDataObject();
119
120        if (dataObject instanceof PersistableAttachment) {
121            PersistableAttachment attachment = (PersistableAttachment) dataObject;
122            byte[] attachmentContent = attachment.getAttachmentContent();
123
124            addAttachmentToResponse(response, attachmentContent, attachment.getContentType(), attachment.getFileName());
125        } else if (dataObject instanceof PersistableAttachmentList) {
126            PersistableAttachmentList<PersistableAttachment> attachmentListBo =
127                    (PersistableAttachmentList<PersistableAttachment>) dataObject;
128            PersistableAttachment attachment = attachmentListBo.getAttachments().get(Integer.parseInt(
129                    form.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX)));
130            byte[] attachmentContent = attachment.getAttachmentContent();
131
132            addAttachmentToResponse(response, attachmentContent, attachment.getContentType(), attachment.getFileName());
133        }
134    }
135
136    /**
137     * {@inheritDoc}
138     */
139    @Override
140    public void downloadCustomDataObjectAttachment(InquiryForm form, HttpServletRequest request,
141            HttpServletResponse response) throws Exception {
142        String fileName = request.getParameter(KRADConstants.DATA_OBJECT_ATTACHMENT_FILE_NAME);
143        String contentType = request.getParameter(KRADConstants.DATA_OBJECT_ATTACHMENT_FILE_CONTENT_TYPE);
144        String fileContentDataObjField = request.getParameter(KRADConstants.DATA_OBJECT_ATTACHMENT_FILE_CONTENT_FIELD);
145
146        if (fileName == null) {
147            throw new RuntimeException("Request Parameter "
148                    + KRADConstants.DATA_OBJECT_ATTACHMENT_FILE_NAME + " must be provided");
149        }
150
151        if (contentType == null) {
152            throw new RuntimeException("Request Parameter "
153                    + KRADConstants.DATA_OBJECT_ATTACHMENT_FILE_CONTENT_TYPE + " must be provided");
154        }
155
156        if (fileContentDataObjField == null) {
157            throw new RuntimeException("Request Parameter "
158                    + KRADConstants.DATA_OBJECT_ATTACHMENT_FILE_CONTENT_FIELD + " must be provided");
159        }
160
161        checkViewAuthorization(form);
162
163        Object dataObject = form.getDataObject();
164
165        if (dataObject == null && GlobalVariables.getMessageMap().hasNoMessages()) {
166            throw new UnsupportedOperationException("The record you have inquired on does not exist.");
167        }
168
169        Method method = dataObject.getClass().getMethod("get" + StringUtils.capitalize(fileContentDataObjField));
170        byte[] attachmentContent = (byte[]) method.invoke(dataObject);
171
172        addAttachmentToResponse(response, attachmentContent, contentType, fileName);
173    }
174
175    /**
176     * Adds the header and content of an attachment to the response.
177     *
178     * @param response HttpServletResponse instance
179     * @param attachmentContent the attachment contents
180     * @param contentType the content type of the attachment
181     * @param fileName the file name of the attachment
182     * @throws RuntimeException if unable to retrieve the attachment contents.
183     */
184    private void addAttachmentToResponse(HttpServletResponse response, byte[] attachmentContent,
185            String contentType, String fileName) {
186        ByteArrayInputStream inputStream = null;
187        int attachmentContentLength;
188
189        if (attachmentContent != null) {
190            inputStream = new ByteArrayInputStream(attachmentContent);
191            attachmentContentLength = attachmentContent.length;
192        } else {
193            attachmentContentLength = 0;
194        }
195
196        try {
197            KRADUtils.addAttachmentToResponse(response, inputStream, contentType, fileName, attachmentContentLength);
198        } catch (IOException e) {
199            throw new RuntimeException("Unable to retrieve attachment contents", e);
200        }
201    }
202}