/** * Copyright (C) 2015 BonitaSoft S.A. * BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2.0 of the License, or * (at your option) any later version. * This program 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 General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.bonitasoft.console.common.server.form; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.bonitasoft.console.common.server.login.localization.UrlBuilder; import org.bonitasoft.console.common.server.page.CustomPageRequestModifier; import org.bonitasoft.console.common.server.page.PageRenderer; import org.bonitasoft.console.common.server.page.PageServlet; import org.bonitasoft.console.common.server.page.ResourceRenderer; import org.bonitasoft.console.common.server.utils.SessionUtil; import org.bonitasoft.engine.bpm.flownode.ActivityInstanceNotFoundException; import org.bonitasoft.engine.bpm.process.ArchivedProcessInstanceNotFoundException; import org.bonitasoft.engine.bpm.process.ProcessDefinitionNotFoundException; import org.bonitasoft.engine.exception.BonitaException; import org.bonitasoft.engine.session.APISession; /** * Servlet allowing to display a form for a process or a task * The servlet only redirect to the generic Page servlet with the right URL * * @author Anthony Birembaut */ public class ProcessFormServlet extends HttpServlet { /** * UUID */ private static final long serialVersionUID = -6397856355139281873L; /** * Logger */ private static Logger LOGGER = Logger.getLogger(ProcessFormServlet.class.getName()); private static final String PAGE_SERVLET_MAPPING = "/portal/resource/"; private static final String PROCESS_PATH_SEGMENT = "process"; private static final String PROCESS_INSTANCE_PATH_SEGMENT = "processInstance"; private static final String TASK_INSTANCE_PATH_SEGMENT = "taskInstance"; private static final String TASK_PATH_SEGMENT = "task"; private static final String USER_ID_PARAM = "user"; private static final String ID_PARAM = "id"; protected ProcessFormService processFormService = new ProcessFormService(); private final ResourceRenderer resourceRenderer = new ResourceRenderer(); protected PageRenderer pageRenderer = new PageRenderer(resourceRenderer); protected CustomPageRequestModifier customPageRequestModifier = new CustomPageRequestModifier(); @Override protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { long processDefinitionId = -1L; long processInstanceId = -1L; long taskInstanceId = -1L; String taskName = null; final List<String> pathSegments = resourceRenderer.getPathSegments(request.getPathInfo()); final String user = request.getParameter(USER_ID_PARAM); final long userId = convertToLong(USER_ID_PARAM, user); final HttpSession session = request.getSession(); final APISession apiSession = (APISession) session.getAttribute(SessionUtil.API_SESSION_PARAM_KEY); try { if (pathSegments.size() > 1) { taskInstanceId = getTaskInstanceId(apiSession, pathSegments, userId); processInstanceId = getProcessInstanceId(pathSegments); processDefinitionId = getProcessDefinitionId(apiSession, pathSegments); } if (processDefinitionId == -1L && processInstanceId == -1L && taskInstanceId == -1L) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Either process name and version are required or process instance Id (with or without task name) or task instance Id."); return; } processDefinitionId = processFormService.ensureProcessDefinitionId(apiSession, processDefinitionId, processInstanceId, taskInstanceId); taskName = processFormService.getTaskName(apiSession, taskInstanceId); redirectToPageServlet(request, response, apiSession, processDefinitionId, processInstanceId, taskInstanceId, taskName); } catch (final Exception e) { handleException(response, processDefinitionId, taskName, processInstanceId != -1L, e); } } @SuppressWarnings("unchecked") protected void redirectToPageServlet(final HttpServletRequest request, final HttpServletResponse response, final APISession apiSession, final long processDefinitionId, final long processInstanceId, final long taskInstanceId, final String taskName) throws BonitaException, IOException { final String pageServletURL = buildPageServletURL(request, apiSession, processDefinitionId, processInstanceId, taskInstanceId, taskName); final UrlBuilder urlBuilder = new UrlBuilder(pageServletURL); urlBuilder.appendParameters(request.getParameterMap()); response.sendRedirect(response.encodeRedirectURL(urlBuilder.build())); } protected String buildPageServletURL(final HttpServletRequest request, final APISession apiSession, final long processDefinitionId, final long processInstanceId, final long taskInstanceId, final String taskName) throws BonitaException, IOException { final StringBuilder pageServletURL = new StringBuilder(request.getContextPath()); pageServletURL.append(PAGE_SERVLET_MAPPING); if (taskInstanceId != -1L) { pageServletURL.append(TASK_INSTANCE_PATH_SEGMENT) .append("/") .append(processFormService.getProcessPath(apiSession, processDefinitionId)) .append("/") .append(processFormService.encodePathSegment(taskName)) .append(PageServlet.RESOURCE_PATH_SEPARATOR) .append("/?") .append(ID_PARAM) .append("=") .append(taskInstanceId); } else if (processInstanceId != -1L) { pageServletURL.append(PROCESS_INSTANCE_PATH_SEGMENT) .append("/") .append(processFormService.getProcessPath(apiSession, processDefinitionId)) .append(PageServlet.RESOURCE_PATH_SEPARATOR) .append("/?") .append(ID_PARAM) .append("=") .append(processInstanceId); } else { pageServletURL.append(PROCESS_PATH_SEGMENT) .append("/") .append(processFormService.getProcessPath(apiSession, processDefinitionId)) .append(PageServlet.RESOURCE_PATH_SEPARATOR) .append("/?") .append(ID_PARAM) .append("=") .append(processDefinitionId); } return pageServletURL.toString(); } protected long getProcessInstanceId(final List<String> pathSegments) { long processInstanceId = -1L; if (PROCESS_INSTANCE_PATH_SEGMENT.equals(pathSegments.get(0))) { final String processInstance = pathSegments.get(1); processInstanceId = convertToLong(PROCESS_INSTANCE_PATH_SEGMENT, processInstance); } return processInstanceId; } protected long getTaskInstanceId(final APISession apiSession, final List<String> pathSegments, final long userId) throws BonitaException, UnsupportedEncodingException { if (TASK_INSTANCE_PATH_SEGMENT.equals(pathSegments.get(0))) { final String taskInstance = pathSegments.get(1); return convertToLong(TASK_INSTANCE_PATH_SEGMENT, taskInstance); } else if (PROCESS_INSTANCE_PATH_SEGMENT.equals(pathSegments.get(0))) { final String processInstance = pathSegments.get(1); final long processInstanceId = convertToLong(PROCESS_INSTANCE_PATH_SEGMENT, processInstance); if (pathSegments.size() > 2 && TASK_PATH_SEGMENT.equals(pathSegments.get(2))) { final String taskName = URLDecoder.decode(pathSegments.get(3), "UTF-8"); return processFormService.getTaskInstanceId(apiSession, processInstanceId, taskName, userId); } } return -1L; } protected long getProcessDefinitionId(final APISession apiSession, final List<String> pathSegments) throws BonitaException { long processDefinitionId = -1L; if (PROCESS_PATH_SEGMENT.equals(pathSegments.get(0))) { if (pathSegments.size() > 2) { final String processName = pathSegments.get(1); final String processVersion = pathSegments.get(2); processDefinitionId = processFormService.getProcessDefinitionId(apiSession, processName, processVersion); } } return processDefinitionId; } protected long convertToLong(final String parameterName, final String idAsString) { if (idAsString != null) { try { return Long.parseLong(idAsString); } catch (final NumberFormatException e) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.log(Level.INFO, "Wrong value for " + parameterName + " expecting a number (long value)"); } } } return -1; } protected void handleException(final HttpServletResponse response, final long processDefinitionId, final String taskName, final boolean hasProcessInstanceId, final Exception e) throws ServletException { try { if (e instanceof ProcessDefinitionNotFoundException) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "Cannot find the process"); } else if (e instanceof ArchivedProcessInstanceNotFoundException) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "Cannot find the process instance"); } else if (e instanceof ActivityInstanceNotFoundException) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "Cannot find the task instance"); } else { if (LOGGER.isLoggable(Level.WARNING)) { String message = "Error while trying to display a form"; if (processDefinitionId != -1) { message = message + " for process " + processDefinitionId; } if (taskName != null) { message = message + " for task " + taskName; } else if (hasProcessInstanceId) { message = message + " ( instance overview)"; } LOGGER.log(Level.WARNING, message, e); } response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); } } catch (final IOException ioe) { throw new ServletException(ioe); } } }