001    /**
002     * Copyright 2005-2012 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.rice.kns.web.struts.action;
017    
018    import org.apache.log4j.Logger;
019    import org.apache.struts.Globals;
020    import org.apache.struts.action.Action;
021    import org.apache.struts.action.ActionForm;
022    import org.apache.struts.action.ActionForward;
023    import org.apache.struts.action.ActionMapping;
024    import org.kuali.rice.core.api.util.RiceConstants;
025    import org.kuali.rice.kns.util.IncidentReportUtils;
026    import org.kuali.rice.kns.web.struts.form.KualiExceptionIncidentForm;
027    import org.kuali.rice.krad.exception.KualiExceptionIncident;
028    import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
029    import org.kuali.rice.krad.service.KualiExceptionIncidentService;
030    import org.kuali.rice.krad.util.KRADConstants;
031    
032    import javax.servlet.http.HttpServletRequest;
033    import javax.servlet.http.HttpServletResponse;
034    import java.util.Enumeration;
035    import java.util.HashMap;
036    import java.util.Map;
037    
038    /**
039     * This is the struts action class for handling the exception for Kuali
040     * applications.
041     * 
042     */
043    public class KualiExceptionHandlerAction extends Action {
044            private static final Logger LOG = Logger
045                            .getLogger(KualiExceptionHandlerAction.class);
046    
047            /**
048             * This overridden method dispatches action to be taken based on
049             * "methodToCall" parameter. The exception is processed when there is no
050             * "methodToCall" specified.
051             * 
052             * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping,
053             *      org.apache.struts.action.ActionForm,
054             *      javax.servlet.http.HttpServletRequest,
055             *      javax.servlet.http.HttpServletResponse)
056             */
057            public ActionForward execute(ActionMapping mapping, ActionForm form,
058                            HttpServletRequest request, HttpServletResponse response)
059                            throws Exception {
060                    return executeException(mapping, form, request, response);
061            }
062    
063            /**
064             * This overridden method processes the exception and post exception (when
065             * user either submit/cancel the exception JSP page).
066             * <ul>
067             * <li>ProcessDefinition application Exception - Exception is stored in Http Request</li>
068             * <li>ProcessDefinition exception incident reporting - No exception, only form data</li>
069             * </ul>
070             * 
071             * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping,
072             *      org.apache.struts.action.ActionForm,
073             *      javax.servlet.http.HttpServletRequest,
074             *      javax.servlet.http.HttpServletResponse)
075             */
076            public ActionForward executeException(ActionMapping mapping,
077                            ActionForm form, HttpServletRequest request,
078                            HttpServletResponse response) throws Exception {
079    
080                    if (LOG.isDebugEnabled()) {
081                            String lm = String.format("ENTRY %s%n%s", form.getClass()
082                                            .getSimpleName(), request.getRequestURI());
083                            LOG.debug(lm);
084                    }
085    
086                    // Get exception thrown
087                    Exception e = (Exception) request.getAttribute(Globals.EXCEPTION_KEY);
088    
089                    // Initialize defined action mapping from struts-config
090                    ActionForward returnForward = null;
091    
092                    // In case there is no exception, either a post back after page was
093                    // filled in
094                    // or just an error from directly accessing this struts action
095                    if (e == null) {
096                            if (form instanceof KualiExceptionIncidentForm) {
097                                    KualiExceptionIncidentForm formObject = (KualiExceptionIncidentForm) form;
098                                    // Manage conditions: submit or cancel
099                                    if (!formObject.isCancel()) {
100                                            // Locate the post exception handler service. The service id
101                                            // is
102                                            // defined in the application properties
103                                            // Only process the post exception handling when the
104                                            // service
105                                            // is specified
106                                            KualiExceptionIncidentService reporterService = KRADServiceLocatorWeb
107                                                            .getKualiExceptionIncidentService();
108                                            // An instance of the ExceptionIncident is created by
109                                            // the
110                                            // ExceptionIncidentService
111                                            Map reducedMap = new HashMap();
112                                            Enumeration<String> names = request.getParameterNames();
113                                            while (names.hasMoreElements()) {
114                                                    String name = names.nextElement();
115                                                    reducedMap.put(name, request.getParameter(name));
116                                            }
117                                            KualiExceptionIncident exceptionIncident = reporterService
118                                                            .getExceptionIncident(reducedMap);
119                                            // Report the incident
120                                            reporterService.report(exceptionIncident);
121                                    } else {
122                                            // Set return after canceling
123                                            ActionForward cancelForward = mapping
124                                                            .findForward(KRADConstants.MAPPING_CANCEL);
125                                            if (cancelForward == null) {
126                                                    cancelForward = returnForward;
127                                            } else {
128                                                    returnForward = cancelForward;
129                                            }
130                                    }
131                            }
132                    } else {
133                            // ProcessDefinition the received exception from HTTP request
134                            returnForward = processException(mapping, form, request, e);
135                    }
136    
137                    // Not specified, return
138                    if (returnForward == null) {
139                            returnForward = mapping.findForward(KRADConstants.MAPPING_CLOSE);
140                    }
141    
142                    if (LOG.isDebugEnabled()) {
143                            String lm = String.format("EXIT %s",
144                                            (returnForward == null) ? "null" : returnForward.getPath());
145                            LOG.debug(lm);
146                    }
147    
148                    return returnForward;
149            }
150    
151            /**
152             * This method process the caught exception by creating an exception
153             * information properties list and forward these properties to the exception
154             * incident handler JSP.
155             * 
156             * @param exception
157             * @param mapping
158             * @param request
159             * @param documentId
160             *            Id of the document that Struts threw exception during its
161             *            processing. null if not the document processing that caused
162             *            the exception
163             * @return
164             * @throws Exception
165             */
166            @SuppressWarnings("unchecked")
167            protected ActionForward processException(ActionMapping mapping,
168                            ActionForm form, HttpServletRequest request, Exception exception)
169                            throws Exception {
170                    // Only process the exception handling when the service
171                    // is specified
172                    KualiExceptionIncidentService reporterService = KRADServiceLocatorWeb
173                                    .getKualiExceptionIncidentService();
174                    // Get exception properties from the Http Request
175                    Map<String, String> properties = (Map<String, String>) request
176                                    .getAttribute(IncidentReportUtils.EXCEPTION_PROPERTIES);
177                    // Construct the exception incident object
178                    KualiExceptionIncident ei = reporterService.getExceptionIncident(
179                                    exception, properties);
180                    // Set full exception properties in Http Request and forward to JSP
181                    request.setAttribute(KualiExceptionHandlerAction.class
182                                    .getSimpleName(), ei.toProperties());
183                    return mapping.findForward(RiceConstants.MAPPING_BASIC);
184            }
185    }