/**
* Copyright (C) 2012 BonitaSoft S.A.
* BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This library 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
* version 2.1 of the License.
* This library 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 this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
**/
package org.bonitasoft.forms.server;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.bonitasoft.console.common.server.auth.AuthenticationManagerProperties;
import org.bonitasoft.console.common.server.login.HttpServletRequestAccessor;
import org.bonitasoft.console.common.server.sso.InternalSSOManager;
import org.bonitasoft.console.common.server.utils.SessionUtil;
import org.bonitasoft.engine.session.APISession;
import org.bonitasoft.forms.client.model.ApplicationConfig;
import org.bonitasoft.forms.client.model.Expression;
import org.bonitasoft.forms.client.model.FormAction;
import org.bonitasoft.forms.client.model.FormFieldValue;
import org.bonitasoft.forms.client.model.FormPage;
import org.bonitasoft.forms.client.model.FormURLComponents;
import org.bonitasoft.forms.client.model.FormValidator;
import org.bonitasoft.forms.client.model.FormWidget;
import org.bonitasoft.forms.client.model.HtmlTemplate;
import org.bonitasoft.forms.client.model.ReducedApplicationConfig;
import org.bonitasoft.forms.client.model.ReducedFormFieldAvailableValue;
import org.bonitasoft.forms.client.model.ReducedFormPage;
import org.bonitasoft.forms.client.model.ReducedFormValidator;
import org.bonitasoft.forms.client.model.ReducedFormWidget;
import org.bonitasoft.forms.client.model.ReducedHtmlTemplate;
import org.bonitasoft.forms.client.model.TransientData;
import org.bonitasoft.forms.client.model.exception.AbortedFormException;
import org.bonitasoft.forms.client.model.exception.CanceledFormException;
import org.bonitasoft.forms.client.model.exception.FileTooBigException;
import org.bonitasoft.forms.client.model.exception.ForbiddenApplicationAccessException;
import org.bonitasoft.forms.client.model.exception.ForbiddenFormAccessException;
import org.bonitasoft.forms.client.model.exception.FormAlreadySubmittedException;
import org.bonitasoft.forms.client.model.exception.FormInErrorException;
import org.bonitasoft.forms.client.model.exception.IllegalActivityTypeException;
import org.bonitasoft.forms.client.model.exception.MigrationProductVersionNotIdenticalException;
import org.bonitasoft.forms.client.model.exception.RPCException;
import org.bonitasoft.forms.client.model.exception.SessionTimeoutException;
import org.bonitasoft.forms.client.model.exception.SkippedFormException;
import org.bonitasoft.forms.client.model.exception.SuspendedFormException;
import org.bonitasoft.forms.client.rpc.FormsService;
import org.bonitasoft.forms.server.accessor.impl.util.FormCacheUtil;
import org.bonitasoft.forms.server.accessor.impl.util.FormCacheUtilFactory;
import org.bonitasoft.forms.server.api.FormAPIFactory;
import org.bonitasoft.forms.server.api.IFormDefinitionAPI;
import org.bonitasoft.forms.server.api.impl.util.FormFieldValuesUtil;
import org.bonitasoft.forms.server.exception.ApplicationFormDefinitionNotFoundException;
import org.bonitasoft.forms.server.exception.FormInitializationException;
import org.bonitasoft.forms.server.exception.FormNotFoundException;
import org.bonitasoft.forms.server.exception.NoCredentialsInSessionException;
import org.bonitasoft.forms.server.provider.FormServiceProvider;
import org.bonitasoft.forms.server.provider.impl.util.FormServiceProviderFactory;
import org.bonitasoft.forms.server.provider.impl.util.FormServiceProviderUtil;
import org.bonitasoft.forms.server.util.LocaleUtil;
import org.bonitasoft.web.rest.model.user.User;
import org.w3c.dom.Document;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
/**
* Servlet implementing the Forms service for async calls
*
* @author Anthony Birembaut, Qixiang Zhang, Vincent Elcrin
*/
public class FormsServlet extends RemoteServiceServlet implements FormsService {
/**
* UID
*/
private static final long serialVersionUID = -638652293467914223L;
/**
* page flow transient data param key inside the session
*/
public static final String TRANSIENT_DATA_SESSION_PARAM_KEY_PREFIX = "transientData-";
/**
* Logger
*/
private static Logger LOGGER = Logger.getLogger(FormsServlet.class.getName());
/**
* FormFieldValuesUtil
*/
private final FormFieldValuesUtil formFieldValuesUtil = new FormFieldValuesUtil();
/**
* locale Util
*/
protected final LocaleUtil localeUtil = new LocaleUtil();
/**
* {@inheritDoc}
*/
@Override
public String processCall(final String payload) throws SerializationException {
try {
return super.processCall(payload);
} catch (final SerializationException e) {
LOGGER.log(
Level.SEVERE,
"The Object returned by the RPC call is not supported by the client. Complex java types and XML types are not supported as data field's inputs.",
e);
throw e;
}
}
/**
* {@inheritDoc}
*/
@Override
public ReducedApplicationConfig getApplicationConfig(final String formID, final Map<String, Object> urlContext, final boolean includeApplicationTemplate)
throws RPCException, SessionTimeoutException, ForbiddenApplicationAccessException, MigrationProductVersionNotIdenticalException {
final HttpServletRequest request = getThreadLocalRequest();
final String localeStr = localeUtil.getLocale(request);
final Map<String, Object> context = initContext(urlContext, localeUtil.resolveLocale(localeStr));
try {
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
final Document document = formServiceProvider.getFormDefinitionDocument(context);
final Date deployementDate = formServiceProvider.getDeployementDate(context);
final IFormDefinitionAPI definitionAPI = FormAPIFactory.getFormDefinitionAPI(tenantID, document, deployementDate, localeStr);
final String permissions = definitionAPI.getApplicationPermissions(formID, context);
final String productVersion = definitionAPI.getProductVersion(context);
final String migrationProductVersion = definitionAPI.getMigrationProductVersion(formID, context);
formServiceProvider.isAllowed(formID, permissions, productVersion, migrationProductVersion, context, false);
final ApplicationConfig applicationConfig = definitionAPI.getApplicationConfig(context, formID, includeApplicationTemplate);
return resolveApplicationConfigExpressions(formServiceProvider, context, applicationConfig).getReducedApplicationConfig();
} catch (final ForbiddenApplicationAccessException e) {
throw new ForbiddenApplicationAccessException(e);
} catch (final MigrationProductVersionNotIdenticalException e) {
throw new MigrationProductVersionNotIdenticalException(e);
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Session timeout");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while getting the Process Config from a process instance", e);
}
throw new RPCException(e.getMessage(), e);
}
}
/**
* {@inheritDoc}
*/
@Override
public ReducedFormPage getFormFirstPage(final String formID, final Map<String, Object> urlContext) throws SessionTimeoutException, RPCException,
SuspendedFormException, CanceledFormException, FormAlreadySubmittedException, ForbiddenFormAccessException, FormInErrorException,
MigrationProductVersionNotIdenticalException, SkippedFormException, AbortedFormException {
final HttpServletRequest request = getThreadLocalRequest();
final String localeStr = localeUtil.getLocale(request);
final Locale userLocale = localeUtil.resolveLocale(localeStr);
final Map<String, Object> context = initContext(urlContext, userLocale);
final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
final Document document = formServiceProvider.getFormDefinitionDocument(context);
final Date deployementDate = formServiceProvider.getDeployementDate(context);
final boolean isEditMode = formServiceProvider.isEditMode(formID, context);
context.put(FormServiceProviderUtil.IS_EDIT_MODE, isEditMode);
final boolean isCurrentValue = formServiceProvider.isCurrentValue(context);
context.put(FormServiceProviderUtil.IS_CURRENT_VALUE, isCurrentValue);
final IFormDefinitionAPI definitionAPI = FormAPIFactory.getFormDefinitionAPI(tenantID, document, deployementDate, localeStr);
final String permissions = definitionAPI.getFormPermissions(formID, context);
final String productVersion = definitionAPI.getProductVersion(context);
final String migrationProductVersion = definitionAPI.getMigrationProductVersion(formID, context);
formServiceProvider.isAllowed(formID, permissions, productVersion, migrationProductVersion, context, true);
final Expression pageIdExpression = definitionAPI.getFormFirstPage(formID, context);
FormPage formPage = null;
if (pageIdExpression != null) {
setClassloader(formServiceProvider, context);
final List<TransientData> transientData = definitionAPI.getFormTransientData(formID, context);
final Map<String, Serializable> transientDataContext = definitionAPI.getTransientDataContext(transientData, userLocale, context);
setFormTransientDataContext(formServiceProvider, formID, transientDataContext, context);
context.put(FormServiceProviderUtil.TRANSIENT_DATA_CONTEXT, transientDataContext);
context.put(FormServiceProviderUtil.FIELD_VALUES, new HashMap<String, FormFieldValue>());
final String pageId = (String) formServiceProvider.resolveExpression(pageIdExpression, context);
if (pageId != null) {
formPage = definitionAPI.getFormPage(formID, pageId, context);
if (formPage != null) {
formPage.setPageLabel((String) formServiceProvider.resolveExpression(formPage.getPageLabelExpression(), context));
formFieldValuesUtil.setFormWidgetsValues(tenantID, formPage.getFormWidgets(), context);
formFieldValuesUtil.storeWidgetsInCacheAndSetCacheID(tenantID, formID, pageId, localeStr, deployementDate, formPage.getFormWidgets());
}
} else {
throw new IllegalStateException("The first Form page cannot be calculated for " + formID
+ ". This is more likely to be a design issue of conditional pageflow.");
}
}
if (formPage == null) {
return null;
} else {
return formPage.getReducedFormPage();
}
} catch (final ApplicationFormDefinitionNotFoundException e) {
throw new ForbiddenFormAccessException(e);
} catch (final ForbiddenFormAccessException e) {
throw e;
} catch (final MigrationProductVersionNotIdenticalException e) {
throw new MigrationProductVersionNotIdenticalException(e);
} catch (final CanceledFormException e) {
throw new CanceledFormException(e);
} catch (final SuspendedFormException e) {
throw new SuspendedFormException(e);
} catch (final FormInErrorException e) {
throw new FormInErrorException(e);
} catch (final SkippedFormException e) {
throw new SkippedFormException(e);
} catch (final AbortedFormException e) {
throw new AbortedFormException(e);
} catch (final FormAlreadySubmittedException e) {
throw new FormAlreadySubmittedException(e);
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Session timeout");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while getting the first page for application " + formID, e);
}
throw new RPCException(e.getMessage(), e);
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
/**
* Set the classloader matching the given context
*
* @param formServiceProvider
* the form service provider
* @param context
* the context (including URL parameters)
* @throws SessionTimeoutException
* @throws FormNotFoundException
*/
protected void setClassloader(final FormServiceProvider formServiceProvider, final Map<String, Object> context) throws SessionTimeoutException,
FormNotFoundException {
final ClassLoader classloader = formServiceProvider.getClassloader(context);
if (classloader != null) {
Thread.currentThread().setContextClassLoader(classloader);
}
}
/**
* Initialize the context map
*
* @param urlContext
* the map of URL parameters
* @param locale
* the user locale
* @return the context map
*/
protected Map<String, Object> initContext(final Map<String, Object> urlContext, final Locale locale) {
final HttpServletRequest request = getThreadLocalRequest();
final HttpSession httpSession = request.getSession();
final APISession aAPISession = (APISession) httpSession.getAttribute(SessionUtil.API_SESSION_PARAM_KEY);
final Map<String, Object> context = new HashMap<>();
context.put(FormServiceProviderUtil.URL_CONTEXT, urlContext);
context.put(FormServiceProviderUtil.LOCALE, locale);
context.put(FormServiceProviderUtil.API_SESSION, aAPISession);
return context;
}
/**
* {@inheritDoc}
*/
@Override
public ReducedFormPage getFormNextPage(final String formID, final Map<String, Object> urlContext, final String nextPageExpressionId,
final Map<String, FormFieldValue> fieldValues) throws RPCException, SessionTimeoutException, FormAlreadySubmittedException, SuspendedFormException,
CanceledFormException, ForbiddenFormAccessException, FormInErrorException, SkippedFormException, AbortedFormException {
final HttpServletRequest request = getThreadLocalRequest();
final String localeStr = localeUtil.getLocale(request);
final Locale userLocale = localeUtil.resolveLocale(localeStr);
final Map<String, Object> context = initContext(urlContext, userLocale);
final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
final Date deployementDate = formServiceProvider.getDeployementDate(context);
final Document document = formServiceProvider.getFormDefinitionDocument(context);
final boolean isEditMode = formServiceProvider.isEditMode(formID, context);
context.put(FormServiceProviderUtil.IS_EDIT_MODE, isEditMode);
final boolean isCurrentValue = formServiceProvider.isCurrentValue(context);
context.put(FormServiceProviderUtil.IS_CURRENT_VALUE, isCurrentValue);
final IFormDefinitionAPI definitionAPI = FormAPIFactory.getFormDefinitionAPI(tenantID, document, deployementDate, localeStr);
final String permissions = definitionAPI.getFormPermissions(formID, context);
final String productVersion = definitionAPI.getProductVersion(context);
final String migrationProductVersion = definitionAPI.getMigrationProductVersion(formID, context);
formServiceProvider.isAllowed(formID, permissions, productVersion, migrationProductVersion, context, true);
setClassloader(formServiceProvider, context);
final Map<String, Serializable> transientDataContext = getFormTransientDataContext(formServiceProvider, formID, context);
context.put(FormServiceProviderUtil.TRANSIENT_DATA_CONTEXT, transientDataContext);
context.put(FormServiceProviderUtil.FIELD_VALUES, fieldValues);
final FormCacheUtil formCacheUtil = FormCacheUtilFactory.getTenantFormCacheUtil(tenantID);
final Expression nextPageIdExpression = formCacheUtil.getNextPageIdExpression(nextPageExpressionId);
final String pageId = (String) formServiceProvider.resolveExpression(nextPageIdExpression, context);
if (pageId != null) {
final FormPage formPage = definitionAPI.getFormPage(formID, pageId, context);
formPage.setPageLabel((String) formServiceProvider.resolveExpression(formPage.getPageLabelExpression(), context));
formFieldValuesUtil.setFormWidgetsValues(tenantID, formPage.getFormWidgets(), context);
formFieldValuesUtil.storeWidgetsInCacheAndSetCacheID(tenantID, formID, pageId, localeStr, deployementDate, formPage.getFormWidgets());
return formPage.getReducedFormPage();
} else {
throw new IllegalStateException("The next Form page cannot be calculated for " + formID
+ ". This is more likely to be a design issue of conditional pageflow.");
}
} catch (final ForbiddenFormAccessException e) {
throw e;
} catch (final CanceledFormException e) {
throw new CanceledFormException(e);
} catch (final SuspendedFormException e) {
throw new SuspendedFormException(e);
} catch (final FormInErrorException e) {
throw new FormInErrorException(e);
} catch (final SkippedFormException e) {
throw new SkippedFormException(e);
} catch (final AbortedFormException e) {
throw new AbortedFormException(e);
} catch (final FormAlreadySubmittedException e) {
throw new FormAlreadySubmittedException(e);
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Session timeout");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while getting the process instance next form page " + nextPageExpressionId, e);
}
throw new RPCException(e.getMessage(), e);
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
/**
* {@inheritDoc}
*/
@Override
public Map<String, Object> skipForm(final String formID, final Map<String, Object> urlContext) throws RPCException, SessionTimeoutException,
FormAlreadySubmittedException, IllegalActivityTypeException {
final HttpServletRequest request = getThreadLocalRequest();
final Map<String, Object> context = initContext(urlContext, localeUtil.resolveLocale(localeUtil.getLocale(request)));
try {
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
return formServiceProvider.skipForm(formID, context);
} catch (final FormAlreadySubmittedException e) {
throw new FormAlreadySubmittedException(e.getMessage(), e);
} catch (final IllegalActivityTypeException e) {
throw new IllegalActivityTypeException(e);
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Session timeout");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while terminating task", e);
}
throw new RPCException(e.getMessage(), e);
}
}
/**
* {@inheritDoc}
*/
@Override
public Map<String, List<ReducedFormValidator>> validateFormFields(final String formID, final Map<String, Object> urlContext,
final Map<String, String> validatorsMap, final Map<String, FormFieldValue> widgetValues, final String submitButtonId) throws RPCException,
SessionTimeoutException {
final HttpServletRequest request = getThreadLocalRequest();
final Map<String, Object> context = initContext(urlContext, localeUtil.resolveLocale(localeUtil.getLocale(request)));
final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
setClassloader(formServiceProvider, context);
final Map<String, List<ReducedFormValidator>> nonCompliantValidators = new HashMap<>();
final Map<String, Serializable> transientDataContext = getFormTransientDataContext(formServiceProvider, formID, context);
context.put(FormServiceProviderUtil.TRANSIENT_DATA_CONTEXT, transientDataContext);
for (final Entry<String, String> validatorsEntry : validatorsMap.entrySet()) {
final String fieldId = getFieldId(validatorsEntry.getKey());
final String fieldValidatorsId = validatorsEntry.getValue();
final FormFieldValue fieldValue = getFieldValue(validatorsEntry.getKey(), widgetValues);
final FormCacheUtil formCacheUtil = FormCacheUtilFactory.getTenantFormCacheUtil(tenantID);
final List<FormValidator> fieldValidators = formCacheUtil.getFieldValidators(fieldValidatorsId);
final List<FormValidator> nonCompliantFieldValidators = formServiceProvider.validateField(fieldValidators, fieldId, fieldValue, submitButtonId,
context);
if (!nonCompliantFieldValidators.isEmpty()) {
final List<ReducedFormValidator> reducedValidators = new ArrayList<>();
for (final FormValidator formValidator : nonCompliantFieldValidators) {
reducedValidators.add(formValidator.getReducedFormValidator());
}
nonCompliantValidators.put(validatorsEntry.getKey(), reducedValidators);
}
}
return nonCompliantValidators;
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while validating Field", e);
}
throw new RPCException(e.getMessage(), e);
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
/**
* {@inheritDoc}
*/
@Override
public List<ReducedFormValidator> validateFormPage(final String formID, final Map<String, Object> urlContext, final String pageValidatorsId,
final Map<String, FormFieldValue> fields, final String submitButtonId) throws RPCException, SessionTimeoutException {
final HttpServletRequest request = getThreadLocalRequest();
final Map<String, Object> context = initContext(urlContext, localeUtil.resolveLocale(localeUtil.getLocale(request)));
final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
setClassloader(formServiceProvider, context);
final Map<String, Serializable> transientDataContext = getFormTransientDataContext(formServiceProvider, formID, context);
context.put(FormServiceProviderUtil.TRANSIENT_DATA_CONTEXT, transientDataContext);
final FormCacheUtil formCacheUtil = FormCacheUtilFactory.getTenantFormCacheUtil(tenantID);
final List<FormValidator> pageValidators = formCacheUtil.getPageValidators(pageValidatorsId);
final List<FormValidator> nonCompliantFieldValidators = formServiceProvider.validatePage(pageValidators, fields, submitButtonId, context);
final List<ReducedFormValidator> reducedValidators = new ArrayList<>();
for (final FormValidator formValidator : nonCompliantFieldValidators) {
reducedValidators.add(formValidator.getReducedFormValidator());
}
return reducedValidators;
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
throw new SessionTimeoutException();
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while validating Page", e);
}
throw new RPCException(e.getMessage(), e);
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
/**
* Retrieve the true ID of the field with the given client ID
*
* @param key
* the ID returned by the client part
* @return the true ID
*/
protected String getFieldId(final String key) {
return key;
}
/**
* Retrieve the value of the field with the given ID
*
* @param fieldId
* the field ID
* @param widgetValues
* the values of the fields
* @return a {@link FormFieldValue}
*/
protected FormFieldValue getFieldValue(final String fieldId, final Map<String, FormFieldValue> widgetValues) {
return widgetValues.get(fieldId);
}
/**
* {@inheritDoc}
*/
@Override
public ReducedHtmlTemplate getFormConfirmationTemplate(final String formID, final Map<String, Object> urlContext,
final Map<String, FormFieldValue> fieldValues)
throws RPCException,
SessionTimeoutException {
final HttpServletRequest request = getThreadLocalRequest();
final String localeStr = localeUtil.getLocale(request);
final Map<String, Object> context = initContext(urlContext, localeUtil.resolveLocale(localeStr));
final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
final Date deployementDate = formServiceProvider.getDeployementDate(context);
final boolean isEditMode = formServiceProvider.isEditMode(formID, context);
context.put(FormServiceProviderUtil.IS_EDIT_MODE, isEditMode);
// Set the current value to false in order to evaluate the confirmation message on archived objects
context.put(FormServiceProviderUtil.IS_CURRENT_VALUE, Boolean.FALSE);
context.put(FormServiceProviderUtil.IS_CONFIRMATION_PAGE, Boolean.TRUE);
final Document document = formServiceProvider.getFormDefinitionDocument(context);
final IFormDefinitionAPI definitionAPI = FormAPIFactory.getFormDefinitionAPI(tenantID, document, deployementDate, localeStr);
final HtmlTemplate htmlTemplate = definitionAPI.getFormConfirmationLayout(formID, context);
setClassloader(formServiceProvider, context);
final Map<String, Serializable> transientDataContext = getFormTransientDataContext(formServiceProvider, formID, context);
context.put(FormServiceProviderUtil.TRANSIENT_DATA_CONTEXT, transientDataContext);
context.put(FormServiceProviderUtil.FIELD_VALUES, fieldValues);
htmlTemplate.setDynamicMessage((String) formServiceProvider.resolveExpression(htmlTemplate.getDynamicMessageExpression(), context));
return htmlTemplate.getReducedHtmlTemplate();
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Session timeout");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while getting the Process Confirmation Template", e);
}
throw new RPCException(e.getMessage(), e);
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
/**
* {@inheritDoc}
*/
@Override
public ReducedHtmlTemplate getApplicationErrorTemplate(final String formID, final Map<String, Object> urlContext) throws RPCException,
SessionTimeoutException {
final HttpServletRequest request = getThreadLocalRequest();
final String localeStr = localeUtil.getLocale(request);
final Map<String, Object> context = initContext(urlContext, localeUtil.resolveLocale(localeStr));
try {
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
final Date deployementDate = formServiceProvider.getDeployementDate(context);
final Document document = formServiceProvider.getFormDefinitionDocument(context);
final IFormDefinitionAPI definitionAPI = FormAPIFactory.getFormDefinitionAPI(tenantID, document, deployementDate, localeStr);
final HtmlTemplate htmlTemplate = definitionAPI.getApplicationErrorLayout(context);
return htmlTemplate.getReducedHtmlTemplate();
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Session timeout");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while getting the Process Error Template", e);
}
throw new RPCException(e.getMessage(), e);
}
}
/**
* {@inheritDoc}
*/
@Override
public FormURLComponents getNextFormURL(final String formID, final Map<String, Object> urlContext) throws RPCException, SessionTimeoutException {
final HttpServletRequest request = getThreadLocalRequest();
final Map<String, Object> context = initContext(urlContext, localeUtil.resolveLocale(localeUtil.getLocale(request)));
try {
context.put(FormServiceProviderUtil.REQUEST, request);
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
removeFormTransientDataContext(formServiceProvider, formID, context);
return formServiceProvider.getNextFormURLParameters(formID, context);
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Session timeout");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while getting the next task", e);
}
throw new RPCException(e.getMessage(), e);
}
}
@Override
public void assignForm(final String formID, final Map<String, Object> urlContext) throws RPCException, SessionTimeoutException,
ForbiddenFormAccessException {
final HttpServletRequest request = getThreadLocalRequest();
final Map<String, Object> context = initContext(urlContext, localeUtil.resolveLocale(localeUtil.getLocale(request)));
try {
context.put(FormServiceProviderUtil.REQUEST, request);
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
formServiceProvider.assignForm(formID, context);
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Session timeout");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final ForbiddenFormAccessException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, e.getMessage(), e);
}
throw e;
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Invalid Session");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while getting the next task", e);
}
throw new RPCException(e.getMessage(), e);
}
}
/**
* store the transient data context for the current page flow displayed in the session
*
* @param formServiceProvider
* @param formID
* the form ID
* @param transientDataContext
* the transient data context
* @param context
*/
protected void setFormTransientDataContext(final FormServiceProvider formServiceProvider, final String formID,
final Map<String, Serializable> transientDataContext, final Map<String, Object> context) {
formServiceProvider.storeFormTransientDataContext(getSession(), TRANSIENT_DATA_SESSION_PARAM_KEY_PREFIX + formID, transientDataContext, context);
}
/*
* Code smell. Shouldn't be protected but avoid npe during tests.
*/
protected HttpSession getSession() {
return getThreadLocalRequest().getSession();
}
/**
* Get the transient data context for the current page flow displayed from the session
*
* @param formServiceProvider
* @param formID
* the form ID
* @param context
* @return a Map<String, Object> containing the context of transient data
*/
protected Map<String, Serializable> getFormTransientDataContext(final FormServiceProvider formServiceProvider, final String formID,
final Map<String, Object> context) {
final HttpServletRequest request = getThreadLocalRequest();
final HttpSession session = request.getSession();
return formServiceProvider.retrieveFormTransientDataContext(session, TRANSIENT_DATA_SESSION_PARAM_KEY_PREFIX + formID, context);
}
/**
* Get the transient data context for the current page flow displayed from the session
*
* @param formServiceProvider
* @param formID
* the form ID
* @param context
*/
protected void removeFormTransientDataContext(final FormServiceProvider formServiceProvider, final String formID, final Map<String, Object> context) {
final HttpServletRequest request = getThreadLocalRequest();
final HttpSession session = request.getSession();
formServiceProvider.removeFormTransientDataContext(session, TRANSIENT_DATA_SESSION_PARAM_KEY_PREFIX + formID, context);
}
/**
* {@inheritDoc}
*/
@Override
public List<ReducedFormFieldAvailableValue> getFormAsyncAvailableValues(final String formID, final Map<String, Object> urlContext,
final ReducedFormWidget formWidget, final FormFieldValue currentFieldValue) throws RPCException, SessionTimeoutException {
final HttpServletRequest request = getThreadLocalRequest();
final Map<String, Object> context = initContext(urlContext, localeUtil.resolveLocale(localeUtil.getLocale(request)));
final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
setClassloader(formServiceProvider, context);
final Map<String, Serializable> transientDataContext = getFormTransientDataContext(formServiceProvider, formID, context);
context.put(FormServiceProviderUtil.TRANSIENT_DATA_CONTEXT, transientDataContext);
// put the current value of the field in the field context
final Map<String, FormFieldValue> fieldContext = new HashMap<>();
fieldContext.put(formWidget.getId(), currentFieldValue);
context.put(FormServiceProviderUtil.FIELD_VALUES, fieldContext);
Object availableValuesObject = null;
if (formWidget.getFormWidgetCacheId() != null) {
// evaluate the available values expression
final FormCacheUtil formCacheUtil = FormCacheUtilFactory.getTenantFormCacheUtil(tenantID);
final FormWidget cachedFormWidget = formCacheUtil.getFormWidget(formWidget.getFormWidgetCacheId());
availableValuesObject = formServiceProvider.resolveExpression(cachedFormWidget.getAvailableValuesExpression(), context);
}
return formFieldValuesUtil.getAvailableValues(availableValuesObject, formWidget.getId());
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Session timeout");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while getting activity async available values of the widget " + formWidget.getId(), e);
}
throw new RPCException(e.getMessage(), e);
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
/**
* {@inheritDoc}
*/
@Override
public Map<String, Object> executeActions(final String formID, final Map<String, Object> urlContext, final Map<String, FormFieldValue> fieldValues,
final List<String> pageIds, final String submitButtonId) throws RPCException, SessionTimeoutException, FileTooBigException,
FormAlreadySubmittedException {
final HttpServletRequest request = getThreadLocalRequest();
final String localeStr = localeUtil.getLocale(request);
final Map<String, Object> context = initContext(urlContext, localeUtil.resolveLocale(localeStr));
final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
context.put(FormServiceProviderUtil.FIELD_VALUES, fieldValues);
context.put(FormServiceProviderUtil.SUBMIT_BUTTON_ID, submitButtonId);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
final Date deployementDate = formServiceProvider.getDeployementDate(context);
final Document document = formServiceProvider.getFormDefinitionDocument(context);
final IFormDefinitionAPI definitionAPI = FormAPIFactory.getFormDefinitionAPI(tenantID, document, deployementDate, localeStr);
final List<FormAction> actions = definitionAPI.getFormActions(formID, pageIds, context);
setClassloader(formServiceProvider, context);
final Map<String, Serializable> transientDataContext = getFormTransientDataContext(formServiceProvider, formID, context);
context.put(FormServiceProviderUtil.TRANSIENT_DATA_CONTEXT, transientDataContext);
return formServiceProvider.executeActions(actions, context);
} catch (final FormAlreadySubmittedException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "The form with ID " + formID + " has already been submitted by someone else.", e);
}
throw e;
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Session timeout");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final org.bonitasoft.forms.server.exception.FileTooBigException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, e.getMessage(), e);
}
throw new FileTooBigException(e.getMessage(), e.getFileName(), e.getMaxSize());
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
} catch (final Throwable e) {
throw new RPCException(e.getMessage(), e);
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
}
/**
* {@inheritDoc}
*/
@Override
public FormURLComponents getAnyTodoListForm(final Map<String, Object> urlContext) throws RPCException, SessionTimeoutException {
final HttpServletRequest request = getThreadLocalRequest();
final Map<String, Object> context = initContext(urlContext, localeUtil.resolveLocale(localeUtil.getLocale(request)));
try {
final long tenantID = retrieveCredentialAndReturnTenantID(request, context);
final FormServiceProvider formServiceProvider = FormServiceProviderFactory.getFormServiceProvider(tenantID);
return formServiceProvider.getAnyTodoListForm(context);
} catch (final FormNotFoundException e) {
throw new RPCException(e.getMessage(), e);
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Session timeout");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while getting any todolist form", e);
}
throw new RPCException(e.getMessage(), e);
}
}
/**
* {@inheritDoc}
*/
@Override
public User getLoggedInUser() throws RPCException, SessionTimeoutException {
try {
final HttpServletRequest request = getThreadLocalRequest();
final HttpSession session = request.getSession();
final User user = (User) session.getAttribute(SessionUtil.USER_SESSION_PARAM_KEY);
if (user == null) {
final String errorMessage = "There is no user in the HTTP session.";
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, errorMessage);
}
throw new NoCredentialsInSessionException(errorMessage);
}
final APISession apiSession = (APISession) session.getAttribute(SessionUtil.API_SESSION_PARAM_KEY);
long tenantId = 0L;
if (apiSession != null) {
tenantId = apiSession.getTenantId();
}
manageLogoutDisplay(user, tenantId);
return user;
} catch (final NoCredentialsInSessionException e) {
if (LOGGER.isLoggable(Level.INFO)) {
LOGGER.log(Level.INFO, "Session timeout");
}
throw new SessionTimeoutException(e.getMessage(), e);
} catch (final Throwable e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, "Error while getting any todolist form", e);
}
throw new RPCException(e.getMessage(), e);
}
}
/**
* @param user
*/
private void manageLogoutDisplay(final User user, final long tenantId) {
final List<String> features = user.getFeatures();
if (features != null
&& (!features.contains(AuthenticationManagerProperties.LOGOUT_ENABLED)
|| !features.contains(AuthenticationManagerProperties.LOGOUT_DISABLED))) {
if (AuthenticationManagerProperties.getProperties(tenantId).isLogoutDisabled()) {
features.add(AuthenticationManagerProperties.LOGOUT_DISABLED);
} else {
features.add(AuthenticationManagerProperties.LOGOUT_ENABLED);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public String generateTemporaryToken() throws RPCException, SessionTimeoutException {
final HttpServletRequest request = getThreadLocalRequest();
final HttpSession httpSession = request.getSession();
final APISession aAPISession = (APISession) httpSession.getAttribute(SessionUtil.API_SESSION_PARAM_KEY);
String userToken = null;
if (aAPISession != null) {
userToken = InternalSSOManager.getInstance().add(aAPISession);
}
return userToken;
}
/**
* {@inheritDoc}
*/
@Override
public void logout() throws RPCException, SessionTimeoutException {
final HttpServletRequest request = getThreadLocalRequest();
final HttpSession session = request.getSession();
session.removeAttribute(SessionUtil.USER_SESSION_PARAM_KEY);
session.removeAttribute(SessionUtil.API_SESSION_PARAM_KEY);
}
/**
* Retrieve the API session from the HTTP session and return it
*
* @param request
* the HTTP request
* @return the API session
* @throws NoCredentialsInSessionException
*/
protected APISession getAPISession(final HttpServletRequest request) throws NoCredentialsInSessionException {
final HttpSession session = request.getSession();
final APISession apiSession = (APISession) session.getAttribute(SessionUtil.API_SESSION_PARAM_KEY);
if (apiSession == null) {
final String errorMessage = "There is no engine API session in the HTTP session.";
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, errorMessage);
}
throw new NoCredentialsInSessionException(errorMessage);
}
return apiSession;
}
/**
* Retrieve the API session and the user from the HTTP session and add them in the context
*
* @param request
* the HTTP request
* @param context
* the context
* @return the tenant ID
* @throws NoCredentialsInSessionException
*/
protected long retrieveCredentialAndReturnTenantID(final HttpServletRequest request, final Map<String, Object> context)
throws NoCredentialsInSessionException {
final HttpSession session = request.getSession();
final User user = (User) session.getAttribute(SessionUtil.USER_SESSION_PARAM_KEY);
if (user == null) {
final String errorMessage = "There is no user in the HTTP session.";
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, errorMessage);
}
throw new NoCredentialsInSessionException(errorMessage);
}
// The API session is not mandatory (it is when using the default form service provider)
final APISession apiSession = (APISession) session.getAttribute(SessionUtil.API_SESSION_PARAM_KEY);
context.put(FormServiceProviderUtil.API_SESSION, apiSession);
context.put(FormServiceProviderUtil.USER, user);
return apiSession.getTenantId();
}
/**
* Resolve expression from ApplicationConfig and set result into the reduced application config.
*
* @param formServiceProvider
* is used to resolve the expressions
* @param context
* needed by applicationConfig
* @param applicationConfig
* contains expressions to resolve as well as the application config reduced
* @return applicationConfig
* @throws FormNotFoundException
* @throws SessionTimeoutException
* @throws IOException
* @throws org.bonitasoft.forms.server.exception.FileTooBigException
* @throws FormInitializationException
*/
private ApplicationConfig resolveApplicationConfigExpressions(final FormServiceProvider formServiceProvider, final Map<String, Object> context,
final ApplicationConfig applicationConfig) throws FormNotFoundException, SessionTimeoutException,
org.bonitasoft.forms.server.exception.FileTooBigException, IOException, FormInitializationException {
try {
context.put(FormServiceProviderUtil.IS_CONFIG_CONTEXT, true);
String resolvedExpression = (String) formServiceProvider.resolveExpression(applicationConfig.getApplicationLabelExpression(), context);
applicationConfig.setApplicationLabel(resolvedExpression);
resolvedExpression = (String) formServiceProvider.resolveExpression(applicationConfig.getMandatoryLabelExpression(), context);
applicationConfig.setMandatoryLabel(resolvedExpression);
resolvedExpression = (String) formServiceProvider.resolveExpression(applicationConfig.getMandatorySymbolExpression(), context);
applicationConfig.setMandatorySymbol(resolvedExpression);
} catch (final FormNotFoundException e) {
throw new FormNotFoundException(e);
} catch (final SessionTimeoutException e) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.INFO, "Invalid Session");
}
final HttpServletRequestAccessor httpServletRequestAccessor = new HttpServletRequestAccessor(getThreadLocalRequest());
SessionUtil.sessionLogout(httpServletRequestAccessor.getHttpSession());
throw new SessionTimeoutException();
}
return applicationConfig;
}
}