/** * Copyright 2005-2016 hdiv.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hdiv.dataComposer; import java.util.Arrays; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.hdiv.config.HDIVConfig; import org.hdiv.context.RequestContextHolder; import org.hdiv.idGenerator.UidGenerator; import org.hdiv.session.ISession; import org.hdiv.state.IPage; import org.hdiv.state.IState; import org.hdiv.state.StateUtil; import org.hdiv.state.scope.StateScopeManager; import org.hdiv.state.scope.StateScopeType; import org.hdiv.util.HDIVUtil; /** * DataComposer object factory, more efficient than to use the Spring factory. * * @author Gotzon Illarramendi * @since HDIV 2.1.0 */ public class DataComposerFactory { private static final int DEFAULT_ALLOWED_LENGTH = 4000; /** * HDIV configuration object. */ protected HDIVConfig config; /** * Http session wrapper */ protected ISession session; /** * Unique Id generator */ protected UidGenerator uidGenerator; /** * Maximum size allowed to represent page state */ protected int allowedLength = DEFAULT_ALLOWED_LENGTH; /** * State management utility */ protected StateUtil stateUtil; /** * State scope manager. */ protected StateScopeManager stateScopeManager; /** * HTTP headers to exclude page reuse in Ajax requests. */ protected List<String> excludePageReuseHeaders = Arrays.asList("X-PJAX", "X-HDIV-EXCLUDE-PAGE-REUSE"); @Deprecated public final IDataComposer newInstance(final HttpServletRequest request) { return newInstance(HDIVUtil.getRequestContext(request)); } /** * Creates a new instance of DataComposer based on the defined strategy. * * @param context Request context * * @return IDataComposer instance */ public IDataComposer newInstance(final RequestContextHolder context) { DataComposerMemory composer = new DataComposerMemory(context); composer.setHdivConfig(config); composer.setSession(session); composer.setUidGenerator(uidGenerator); composer.setStateScopeManager(stateScopeManager); composer.init(); initDataComposer(composer, context); return composer; } /** * Initialize IDataComposer instance. * * @param dataComposer IDataComposer instance * @param context current request context */ protected void initDataComposer(final IDataComposer dataComposer, final RequestContextHolder context) { String hdivState = context.getHdivState(); String preState = getModifyStateParameterValue(context); if (preState != null && preState.length() > 0) { // We are modifying an existing state, preload dataComposer with it int pageId = stateUtil.getPageId(preState); IState state = stateUtil.restoreState(context, preState); if (pageId > 0) { IPage page = state.getPage(); if (page == null) { page = session.getPage(context, pageId); } if (page != null) { dataComposer.startPage(page); } } if (state != null) { dataComposer.beginRequest(state); } } else if (reuseExistingPage(context)) { if (hdivState != null && hdivState.length() > 0) { int pageId = stateUtil.getPageId(hdivState); if (pageId > 0) { IPage page = session.getPage(context, pageId); dataComposer.startPage(page); } else { dataComposer.startPage(hdivState); } } else { dataComposer.startPage(hdivState); } } else { dataComposer.startPage(hdivState); } // Detect if request url is configured as a long living page String url = context.getUrlWithoutContextPath(); StateScopeType scope = config.isLongLivingPages(url); if (scope != null) { dataComposer.startScope(scope); } } /** * Get _MODIFY_HDIV_STATE_ parameter value. * * @param context request context * @return parameter value. */ protected String getModifyStateParameterValue(final RequestContextHolder context) { String paramName = context.getHdivModifyParameterName(); return paramName != null ? context.getParameter(paramName) : null; } /** * Is it necessary to create a new Page or reuse existing Page adding the created states to it? * * @param context request context * @return reuse or not */ protected boolean reuseExistingPage(final RequestContextHolder context) { return config.isReuseExistingPageInAjaxRequest() && context.isAjax() && !excludePageReuseInAjax(context); } protected final boolean excludePageReuseInAjax(final RequestContextHolder request) { for (String header : excludePageReuseHeaders) { String headerValue = request.getHeader(header); if (headerValue != null) { return true; } } return false; } /** * @param config the hdivConfig to set */ public void setConfig(final HDIVConfig config) { this.config = config; } /** * @param session the session to set */ public void setSession(final ISession session) { this.session = session; } /** * @param uidGenerator the uidGenerator to set */ public void setUidGenerator(final UidGenerator uidGenerator) { this.uidGenerator = uidGenerator; } /** * @param allowedLength the allowedLength to set */ public void setAllowedLength(final int allowedLength) { this.allowedLength = allowedLength; } /** * @param stateUtil the stateUtil to set */ public void setStateUtil(final StateUtil stateUtil) { this.stateUtil = stateUtil; } /** * @param stateScopeManager the stateScopeManager to set */ public void setStateScopeManager(final StateScopeManager stateScopeManager) { this.stateScopeManager = stateScopeManager; } /** * @param excludePageReuseHeaders the excludePageReuseHeaders to set */ public void setExcludePageReuseHeaders(final List<String> excludePageReuseHeaders) { this.excludePageReuseHeaders = excludePageReuseHeaders; } }