/** * Copyright © 2002 Instituto Superior Técnico * * This file is part of FenixEdu Academic. * * FenixEdu Academic is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * FenixEdu Academic is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with FenixEdu Academic. If not, see <http://www.gnu.org/licenses/>. */ package org.fenixedu.academic.ui.struts.action.base; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; import org.apache.struts.action.DynaActionForm; import org.apache.struts.actions.DispatchAction; import org.apache.struts.validator.DynaValidatorForm; import org.fenixedu.academic.domain.Person; import org.fenixedu.academic.domain.curricularRules.executors.RuleResult; import org.fenixedu.academic.domain.curricularRules.executors.RuleResultMessage; import org.fenixedu.academic.domain.exceptions.DomainException; import org.fenixedu.academic.service.services.commons.ExecuteFactoryMethod; import org.fenixedu.academic.service.services.commons.FactoryExecutor; import org.fenixedu.academic.service.services.exceptions.FenixServiceException; import org.fenixedu.academic.ui.struts.action.commons.FenixActionForward; import org.fenixedu.academic.util.LabelFormatter; import org.fenixedu.bennu.core.domain.Bennu; import org.fenixedu.bennu.core.domain.User; import org.fenixedu.bennu.core.security.Authenticate; import org.fenixedu.bennu.core.util.CoreConfiguration; import org.fenixedu.bennu.struts.base.ExceptionHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pt.ist.fenixWebFramework.renderers.components.state.IViewState; import pt.ist.fenixWebFramework.renderers.components.state.LifeCycleConstants; import pt.ist.fenixWebFramework.renderers.components.state.ViewDestination; import pt.ist.fenixWebFramework.renderers.model.MetaObject; import pt.ist.fenixWebFramework.renderers.plugin.RenderersRequestProcessorImpl; import pt.ist.fenixWebFramework.renderers.utils.RenderUtils; import pt.ist.fenixframework.DomainObject; import pt.ist.fenixframework.FenixFramework; public abstract class FenixDispatchAction extends DispatchAction implements ExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(FenixDispatchAction.class); protected static final Bennu rootDomainObject = Bennu.getInstance(); protected static final String ACTION_MESSAGES_REQUEST_KEY = "FENIX_ACTION_MESSAGES"; @Override public ActionForward execute(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception { final ActionMessages actionMessages = new ActionMessages(); request.setAttribute(ACTION_MESSAGES_REQUEST_KEY, actionMessages); final ActionForward actionForward = super.execute(mapping, actionForm, request, response); if (!actionMessages.isEmpty()) { saveMessages(request, actionMessages); } if (CoreConfiguration.getConfiguration().developmentMode()) { logger.info("CLASS: " + this.getClass().getName() + ", method: " + getFromRequest(request, "method")); } return actionForward; } protected static User getUserView(HttpServletRequest request) { return Authenticate.getUser(); } protected Person getLoggedPerson(HttpServletRequest request) { final User userView = getUserView(request); return (userView == null) ? null : userView.getPerson(); } /* * Sets an error to display later in the Browser and sets the mapping * forward. */ protected ActionForward setError(HttpServletRequest request, ActionMapping mapping, String errorMessage, String forwardPage, Object actionArg) { addErrorMessage(request, errorMessage, errorMessage, actionArg); if (forwardPage != null) { return mapping.findForward(forwardPage); } return mapping.getInputForward(); } /* * Verifies if a property of type String in a FormBean is not empty. Returns * true if the field is present and not empty. False otherwhise. */ protected boolean verifyStringParameterInForm(DynaValidatorForm dynaForm, String field) { if (dynaForm.get(field) != null && !dynaForm.get(field).equals("")) { return true; } return false; } /* * Verifies if a parameter in a Http Request is not empty. Return true if * the field is not empty. False otherwise. */ protected boolean verifyParameterInRequest(HttpServletRequest request, String field) { if (request.getParameter(field) != null && !request.getParameter(field).equals("")) { return true; } return false; } protected Integer getInteger(final DynaActionForm dynaActionForm, final String string) { final String value = dynaActionForm.getString(string); return value == null || value.length() == 0 ? null : Integer.valueOf(value); } protected String getRequestParameterAsString(HttpServletRequest request, String parameterName) { final String requestParameter = request.getParameter(parameterName); if (!StringUtils.isEmpty(requestParameter)) { return requestParameter; } else { return null; } } protected Integer getIntegerFromRequestOrForm(final HttpServletRequest request, final DynaActionForm form, final String name) { final Integer value = getIntegerFromRequest(request, name); return (value != null) ? value : getInteger(form, name); } protected Object getFromRequestOrForm(final HttpServletRequest request, final DynaActionForm form, final String name) { final Object value = getFromRequest(request, name); return (value != null) ? value : form.get(name); } /** * Searches in request parameters first and next in request attributed * * @param request * @param name * @return */ protected Object getFromRequest(HttpServletRequest request, String name) { final String requestParameter = request.getParameter(name); return (requestParameter != null) ? requestParameter : request.getAttribute(name); } protected String getStringFromRequest(HttpServletRequest request, String name) { final String requestParameter = request.getParameter(name); return (requestParameter != null) ? requestParameter : (String) request.getAttribute(name); } protected Integer getIntegerFromRequest(HttpServletRequest request, String name) { final String requestParameter = request.getParameter(name); return (!StringUtils.isEmpty(requestParameter) ? Integer.valueOf(requestParameter) : (Integer) request.getAttribute(name)); } protected Long getLongFromRequest(HttpServletRequest request, String name) { final String requestParameter = request.getParameter(name); return (!StringUtils.isEmpty(requestParameter) ? Long.valueOf(requestParameter) : (Long) request.getAttribute(name)); } @Override public ActionForward processException(HttpServletRequest request, ActionMapping mapping, ActionForward input, Exception e) { if (!(e instanceof DomainException)) { return null; } DomainException domainException = (DomainException) e; ActionMessages messages = getMessages(request); if (messages == null) { messages = new ActionMessages(); } messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(domainException.getKey(), domainException.getArgs())); saveMessages(request, messages); IViewState viewState = RenderUtils.getViewState(); if (viewState != null) { ViewDestination destination = viewState.getDestination("exception"); if (destination != null) { return forwardForDestination(destination); } } // show exception in output to ease finding the problem when // messages are not shown in page logger.error(e.getMessage(), e); return input; } private ActionForward forwardForDestination(ViewDestination destination) { ActionForward forward = new ActionForward(); forward.setModule(destination.getModule()); forward.setPath(destination.getPath()); forward.setRedirect(destination.getRedirect()); return forward; } protected Object executeFactoryMethod() throws FenixServiceException { return executeFactoryMethod(getFactoryObject()); } protected Object executeFactoryMethod(FactoryExecutor executor) throws FenixServiceException { return ExecuteFactoryMethod.run(executor); } protected FactoryExecutor getFactoryObject() { return getRenderedObject(); } protected <RenderedObjectType> RenderedObjectType getRenderedObject() { return (RenderedObjectType) getRenderedObjectFromViewState(RenderUtils.getViewState()); } protected <RenderedObjectType> RenderedObjectType getRenderedObject(String id) { return (RenderedObjectType) getRenderedObjectFromViewState(RenderUtils.getViewState(id)); } private Object getRenderedObjectFromViewState(IViewState viewState) { if (viewState != null) { MetaObject metaObject = viewState.getMetaObject(); if (metaObject != null) { return metaObject.getObject(); } } return null; } protected ActionMessages getActionMessages(HttpServletRequest request) { return (ActionMessages) request.getAttribute(ACTION_MESSAGES_REQUEST_KEY); } protected boolean hasActionMessage(HttpServletRequest request) { return !this.getActionMessages(request).isEmpty(); } protected void addActionMessage(HttpServletRequest request, String key, String... args) { this.addActionMessage(ActionMessages.GLOBAL_MESSAGE, request, key, args); } protected void addActionMessageLiteral(HttpServletRequest request, String message) { this.getActionMessages(request).add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(message, false)); } protected void addActionMessageLiteral(String propertyName, HttpServletRequest request, String message) { this.getActionMessages(request).add(propertyName, new ActionMessage(message, false)); } protected void addActionMessage(HttpServletRequest request, String key) { this.addActionMessage(ActionMessages.GLOBAL_MESSAGE, request, key); } protected void addActionMessage(HttpServletRequest request, String key, boolean resource) { this.addActionMessage(ActionMessages.GLOBAL_MESSAGE, request, key, resource); } protected void addActionMessage(String propertyName, HttpServletRequest request, String key, boolean resource) { this.getActionMessages(request).add(propertyName, new ActionMessage(key, resource)); } protected void addActionMessage(String propertyName, HttpServletRequest request, String key) { this.getActionMessages(request).add(propertyName, new ActionMessage(key)); } protected void addActionMessage(String propertyName, HttpServletRequest request, String key, String... args) { this.getActionMessages(request).add(propertyName, new ActionMessage(key, args)); } protected String[] solveLabelFormatterArgs(HttpServletRequest request, LabelFormatter[] labelFormatterArgs) { final String[] args = new String[labelFormatterArgs.length]; int i = 0; for (final LabelFormatter labelFormatter : labelFormatterArgs) { args[i++] = labelFormatter.toString(); } return args; } protected Object getObjectFromViewState(final String viewStateId) { IViewState viewState = RenderUtils.getViewState(viewStateId); return viewState == null ? null : viewState.getMetaObject().getObject(); } protected void addRuleResultMessagesToActionMessages(final String propertyName, final HttpServletRequest request, final RuleResult... ruleResults) { for (final RuleResult ruleResult : ruleResults) { for (final RuleResultMessage message : ruleResult.getMessages()) { if (message.isToTranslate()) { addActionMessage(propertyName, request, message.getMessage(), message.getArgs()); } else { addActionMessageLiteral(propertyName, request, message.getMessage()); } } } } protected void addActionMessages(final HttpServletRequest request, final Collection<LabelFormatter> messages) { addActionMessages(ActionMessages.GLOBAL_MESSAGE, request, messages); } protected void addActionMessages(final String propertyName, final HttpServletRequest request, final Collection<LabelFormatter> messages) { for (final LabelFormatter each : messages) { addActionMessageLiteral(propertyName, request, each.toString()); } } protected void addErrorMessage(HttpServletRequest request, String property, String key, Object... args) { final ActionMessages messages = getErrors(request); messages.add(property, new ActionMessage(key, args)); saveErrors(request, messages); } @SuppressWarnings("unchecked") protected <T extends DomainObject> T getDomainObject(final HttpServletRequest request, final String name) { final String parameter = request.getParameter(name); return (T) FenixFramework.getDomainObject(parameter != null ? parameter : (String) request.getAttribute(name)); } /** * Obtains a domain object whose ExternalId is present in the given form. * * The reason for this method to exist is that in Struts's forms, the default * value of a String is an empty string, and not null. * * This method should be avoided, as Struts forms are not to be used. * * @param form * The {@link DynaActionForm} to extract the id from * @param name * The name of the parameter. Must be of type {@link String} * @return * The {@link DomainObject} */ protected <T extends DomainObject> T getDomainObject(final DynaActionForm form, final String name) { final String parameter = (String) form.get(name); if (StringUtils.isEmpty(parameter) || parameter.startsWith("-")) { return null; } else { return FenixFramework.getDomainObject(parameter); } } public ActionForward redirect(String url, HttpServletRequest request) { return new FenixActionForward(request, new ActionForward(url, true)); } public List<IViewState> getViewStatesWithPrefixId(final String prefixId) { final List<IViewState> viewStates = (List<IViewState>) RenderersRequestProcessorImpl.getCurrentRequest().getAttribute( LifeCycleConstants.VIEWSTATE_PARAM_NAME); final List<IViewState> result = new ArrayList<IViewState>(); if (viewStates != null) { for (final IViewState state : viewStates) { if (state.getId().startsWith(prefixId)) { result.add(state); } } } return result; } protected void writeFile(final HttpServletResponse response, final String filename, final String contentType, final byte[] content) throws IOException { response.setContentLength(content.length); response.setContentType(contentType); response.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\""); try (ServletOutputStream outputStream = response.getOutputStream()) { outputStream.write(content); outputStream.flush(); response.flushBuffer(); } } public <T> T keepInRequest(HttpServletRequest request, String name) { T fromRequest = (T) getFromRequest(request, name); request.setAttribute(name, fromRequest); return fromRequest; } protected void atomic(Runnable runnable) { FenixFramework.atomic(runnable); } }