Package org.broadleafcommerce.cms.web

Source Code of org.broadleafcommerce.cms.web.BroadleafProcessURLFilter

/*
* #%L
* BroadleafCommerce CMS Module
* %%
* Copyright (C) 2009 - 2013 Broadleaf Commerce
* %%
* 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.
* #L%
*/
package org.broadleafcommerce.cms.web;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.broadleafcommerce.common.RequestDTOImpl;
import org.broadleafcommerce.common.locale.domain.Locale;
import org.broadleafcommerce.common.locale.service.LocaleService;
import org.broadleafcommerce.common.sandbox.domain.SandBox;
import org.broadleafcommerce.common.sandbox.domain.SandBoxType;
import org.broadleafcommerce.common.sandbox.service.SandBoxService;
import org.broadleafcommerce.common.site.domain.Site;
import org.broadleafcommerce.common.time.FixedTimeSource;
import org.broadleafcommerce.common.time.SystemTime;
import org.broadleafcommerce.common.web.BroadleafRequestContext;
import org.broadleafcommerce.common.web.util.StatusExposingServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
* @deprecated In favor of org.broadleafcommerce.common.web.BroadleafRequestFilter.
* formally component name "blProcessURLFilter"
*
* This filter sets up the CMS system by setting the current sandbox, locale, time of day, and languageCode
* that used by content items.
* <p/>
* After setting up content variables, it checks to see if a request can be processed by an instance of
* URLProcessor and if so, delegates the request to that processor.
*
* This filter creates an internal cache to quickly determine if the request should be processed
* by an instance of URLProcessor or be passed to the next filter in the filter chain.    The
* cache settings (including expiration seconds, maximum elements, and concurrency) can be
* configured via Spring at startup.   See {@code com.google.common.cache.CacheBuilder} for more information
* on these parameters.
*
* @author bpolster
*/
@Deprecated
public class BroadleafProcessURLFilter extends OncePerRequestFilter {
    private final Log LOG = LogFactory.getLog(BroadleafProcessURLFilter.class);

    // List of URLProcessors
    private List<URLProcessor> urlProcessorList = new ArrayList<URLProcessor>();

    // Cache-settings
    //   by default, expire cache every four hours (4 hours * 60 minutes * 60 seconds)
    private int cacheExpirationSeconds = 4 * 60 * 60;
    private int maxCacheElements = 10000;
    private int maxCacheConcurrency = 3;
    private Cache<String, URLProcessor> urlCache;


    @Resource(name = "blSandBoxService")
    private SandBoxService sandBoxService;

    @Resource(name = "blLocaleService")
    private LocaleService localeService;

    protected Boolean sandBoxPreviewEnabled = true;

    /**
     * Parameter/Attribute name for the current language
     */
    public static String LOCALE_VAR = "blLocale";

    /**
     * Parameter/Attribute name for the current language
     */
    public static String LOCALE_CODE_PARAM = "blLocaleCode";

    /**
     * Parameter/Attribute name for the current language
     */
    public static String REQUEST_DTO = "blRequestDTO";

    /**
     * Request attribute to store the current sandbox
     */
    public static String SANDBOX_VAR = "blSandbox";

    // Properties to manage URLs that will not be processed by this filter.
    private static final String BLC_ADMIN_GWT = "org.broadleafcommerce.admin";
    private static final String BLC_ADMIN_PREFIX = "blcadmin";
    private static final String BLC_ADMIN_SERVICE = ".service";
    private HashSet<String> ignoreSuffixes;

    // Request Parameters and Attributes for Sandbox Mode properties - mostly date values.
    private static String SANDBOX_ID_VAR = "blSandboxId";
    private static String SANDBOX_DATE_TIME_VAR = "blSandboxDateTime";
    private static final SimpleDateFormat CONTENT_DATE_FORMATTER = new SimpleDateFormat("yyyyMMddHHmm");
    private static final SimpleDateFormat CONTENT_DATE_DISPLAY_FORMATTER = new SimpleDateFormat("MM/dd/yyyy");
    private static final SimpleDateFormat CONTENT_DATE_DISPLAY_HOURS_FORMATTER = new SimpleDateFormat("h");
    private static final SimpleDateFormat CONTENT_DATE_DISPLAY_MINUTES_FORMATTER = new SimpleDateFormat("mm");
    private static final SimpleDateFormat CONTENT_DATE_PARSE_FORMAT = new SimpleDateFormat("MM/dd/yyyy hh:mm aa");
    private static String SANDBOX_DATE_TIME_RIBBON_OVERRIDE_PARAM = "blSandboxDateTimeRibbonOverride";
    private static final String SANDBOX_DISPLAY_DATE_TIME_DATE_PARAM = "blSandboxDisplayDateTimeDate";
    private static final String SANDBOX_DISPLAY_DATE_TIME_HOURS_PARAM = "blSandboxDisplayDateTimeHours";
    private static final String SANDBOX_DISPLAY_DATE_TIME_MINUTES_PARAM = "blSandboxDisplayDateTimeMinutes";
    private static final String SANDBOX_DISPLAY_DATE_TIME_AMPM_PARAM = "blSandboxDisplayDateTimeAMPM";


    /**
     * (non-Javadoc)
     *
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    @Override
    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {

        if (!shouldProcessURL(request, request.getRequestURI())) {
            if (LOG.isTraceEnabled()) {
                LOG.trace("Process URL not processing URL " + request.getRequestURI());
            }
            filterChain.doFilter(request, response);
            return;
        }

        final String requestURIWithoutContext;

        if (request.getContextPath() != null) {
            requestURIWithoutContext = request.getRequestURI().substring(request.getContextPath().length());
        } else {
            requestURIWithoutContext = request.getRequestURI();
        }


        if (LOG.isTraceEnabled()) {
            LOG.trace("Process URL Filter Begin " + requestURIWithoutContext);
        }

        if (request.getAttribute(REQUEST_DTO) == null) {
            request.setAttribute(REQUEST_DTO, new RequestDTOImpl(request));
        }

        Site site = determineSite(request);
        SandBox currentSandbox = determineSandbox(request, site);

        BroadleafRequestContext brc = new BroadleafRequestContext();
        brc.setLocale(determineLocale(request, site));
        brc.setSandBox(currentSandbox);
        brc.setRequest(request);
        brc.setResponse(response);
        BroadleafRequestContext.setBroadleafRequestContext(brc);

        try {
            URLProcessor urlProcessor = null;

            if (isProduction(currentSandbox)) {
                try {
                    urlProcessor = lookupProcessorFromCache(requestURIWithoutContext);
                } catch (ExecutionException e) {
                    LOG.error(e);
                }
            }

            if (urlProcessor == null) {
                urlProcessor = determineURLProcessor(requestURIWithoutContext);
            }

            if (urlProcessor instanceof NullURLProcessor) {
                // Pass request down the filter chain
                if (LOG.isTraceEnabled()) {
                    LOG.trace("URL not being processed by a Broadleaf URLProcessor " + requestURIWithoutContext);
                }
                StatusExposingServletResponse sesResponse = new StatusExposingServletResponse(response);
                filterChain.doFilter(request, sesResponse);
                if (sesResponse.getStatus() == sesResponse.SC_NOT_FOUND) {
                    if (LOG.isWarnEnabled()) {
                        LOG.warn("Page not found.  Unable to render " + requestURIWithoutContext);
                    }
                    urlCache.invalidate(requestURIWithoutContext);
                }
            } else {
                if (LOG.isTraceEnabled()) {
                    LOG.trace("URL about to be processed by a Broadleaf URLProcessor " + requestURIWithoutContext);
                }               
                urlProcessor.processURL(requestURIWithoutContext);
            }
        } finally {
            // If the system-time was overridden, set it back to normal
            SystemTime.resetLocalTimeSource();
        }

    }


    /**
     * Returns true if the passed in sandbox is null or is of type SandBoxType.PRODUCTION.
     *
     * @param sandbox
     * @return
     */
    private boolean isProduction(SandBox sandbox) {
        return (sandbox == null) || (SandBoxType.PRODUCTION.equals(sandbox));
    }


    /**
     * Builds a cache for each URL that determines how it should be processed.
     *
     * @return
     */
    private URLProcessor lookupProcessorFromCache(String requestURIWithoutContextPath) throws ExecutionException {
        if (urlCache == null) {
            urlCache = CacheBuilder.newBuilder()
                   .maximumSize(maxCacheElements)
                   .concurrencyLevel(maxCacheConcurrency)
                   .expireAfterWrite(cacheExpirationSeconds, TimeUnit.SECONDS)
                   .build(new CacheLoader<String,URLProcessor>() {
                        @Override
                        public URLProcessor load(String key) throws IOException, ServletException {
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("Loading URL processor into Cache");
                            }
                            return determineURLProcessor(key);
                        }
                   });
        }
        return urlCache.getIfPresent(requestURIWithoutContextPath);
    }

    private URLProcessor determineURLProcessor(String requestURI) {
         for (URLProcessor processor: getUrlProcessorList()) {
            if (processor.canProcessURL(requestURI)) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("URLProcessor found for URI " + requestURI + " - " + processor.getClass().getName());
                }
                return processor;
            }
        }
        // Indicates that this URL is not handled by a URLProcessor
        return NullURLProcessor.getInstance();
    }

    /**
     * Determines if the passed in URL should be processed by the content management system.
     * <p/>
     * By default, this method returns false for any BLC-Admin URLs and service calls and for all
     * common image/digital mime-types (as determined by an internal call to {@code getIgnoreSuffixes}.
     * <p/>
     * This check is called with the {@code doFilterInternal} method to short-circuit the content
     * processing which can be expensive for requests that do not require it.
     *
     * @param requestURI - the HttpServletRequest.getRequestURI
     * @return true if the {@code HttpServletRequest} should be processed
     */
    protected boolean shouldProcessURL(HttpServletRequest request, String requestURI) {
        if (requestURI.contains(BLC_ADMIN_GWT) ||
            requestURI.endsWith(BLC_ADMIN_SERVICE) ||
            requestURI.contains(BLC_ADMIN_PREFIX)) {
            if (LOG.isTraceEnabled()) {
                LOG.trace("BroadleafProcessURLFilter ignoring admin request URI " + requestURI);
            }
            return false;
        } else {
            int pos = requestURI.lastIndexOf(".");
            if (pos > 0) {
                String suffix = requestURI.substring(pos);
                if (getIgnoreSuffixes().contains(suffix.toLowerCase())) {
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("BroadleafProcessURLFilter ignoring request due to suffix " + requestURI);
                    }
                    return false;
                }
            }
        }
        return true;
    }


    private SandBox determineSandbox(HttpServletRequest request, Site site) {
        SandBox currentSandbox = null;
        if (!sandBoxPreviewEnabled) {
            if (LOG.isTraceEnabled()) {
                LOG.trace("Sandbox preview disabled. Setting sandbox to production");
            }
            request.setAttribute(SANDBOX_VAR, currentSandbox);
        } else {
            Long sandboxId = null;
            if (request.getParameter("blSandboxDateTimeRibbonProduction") == null) {
                sandboxId = lookupSandboxId(request);
            } else {
                request.getSession().removeAttribute(SANDBOX_DATE_TIME_VAR);
                request.getSession().removeAttribute(SANDBOX_ID_VAR);
            }
            if (sandboxId != null) {
                currentSandbox = sandBoxService.retrieveSandBoxById(sandboxId);
                request.setAttribute(SANDBOX_VAR, currentSandbox);
                if (currentSandbox != null && !SandBoxType.PRODUCTION.equals(currentSandbox.getSandBoxType())) {
                    setContentTime(request);
                }
            }

//            if (currentSandbox == null && site != null) {
//                currentSandbox = site.getProductionSandbox();
//            }
        }

        if (LOG.isTraceEnabled()) {
            LOG.trace("Serving request using sandbox: " + currentSandbox);
        }

        Date currentSystemDateTime = SystemTime.asDate(true);
        Calendar sandboxDateTimeCalendar = Calendar.getInstance();
        sandboxDateTimeCalendar.setTime(currentSystemDateTime);
        request.setAttribute(SANDBOX_DISPLAY_DATE_TIME_DATE_PARAM, CONTENT_DATE_DISPLAY_FORMATTER.format(currentSystemDateTime));
        request.setAttribute(SANDBOX_DISPLAY_DATE_TIME_HOURS_PARAM, CONTENT_DATE_DISPLAY_HOURS_FORMATTER.format(currentSystemDateTime));
        request.setAttribute(SANDBOX_DISPLAY_DATE_TIME_MINUTES_PARAM, CONTENT_DATE_DISPLAY_MINUTES_FORMATTER.format(currentSystemDateTime));
        request.setAttribute(SANDBOX_DISPLAY_DATE_TIME_AMPM_PARAM, sandboxDateTimeCalendar.get(Calendar.AM_PM));
        return currentSandbox;
    }

    /**
     * If another filter has already set the language as a request attribute, that will be honored.
     * Otherwise, the request parameter is checked followed by the session attribute.
     *
     * @param request
     * @param site
     * @return
     */
    private Locale determineLocale(HttpServletRequest request, Site site) {

        Locale locale = null;

        // First check for request attribute
        locale = (Locale) request.getAttribute(LOCALE_VAR);

        // Second, check for a request parameter
        if (locale == null && request.getParameter(LOCALE_CODE_PARAM) != null) {
            String localeCode = request.getParameter(LOCALE_CODE_PARAM);
            locale = localeService.findLocaleByCode(localeCode);
            if (LOG.isTraceEnabled()) {
                LOG.trace("Attempt to find locale by param " + localeCode + " resulted in " + locale);
            }
        }

        // Third, check the session
        if (locale == null) {
            HttpSession session = request.getSession(true);
            if (session != null) {
                locale = (Locale) session.getAttribute(LOCALE_VAR);
            }
            if (LOG.isTraceEnabled()) {
                LOG.trace("Attempt to find locale from session resulted in " + locale);
            }
        }

        // Finally, use the default
        if (locale == null) {
            locale = localeService.findDefaultLocale();
            if (LOG.isTraceEnabled()) {
                LOG.trace("Locale set to default locale " + locale);
            }
        }

        request.setAttribute(LOCALE_VAR, locale);
        request.getSession().setAttribute(LOCALE_VAR, locale);

        Map<String, Object> ruleMap = (Map<String, Object>) request.getAttribute("blRuleMap");
        if (ruleMap == null) {
            ruleMap = new HashMap<String, Object>();
            request.setAttribute("blRuleMap", ruleMap);
        }
        ruleMap.put("locale", locale);
        return locale;
    }


    private Long lookupSandboxId(HttpServletRequest request) {
        String sandboxIdStr = request.getParameter(SANDBOX_ID_VAR);
        Long sandboxId = null;

        if (sandboxIdStr != null) {
            try {
                sandboxId = Long.valueOf(sandboxIdStr);
                if (LOG.isTraceEnabled()) {
                    LOG.trace("SandboxId found on request " + sandboxId);
                }
            } catch (NumberFormatException nfe) {
                LOG.warn("blcSandboxId parameter could not be converted into a Long", nfe);
            }
        }

        if (sandboxId == null) {
            // check the session
            HttpSession session = request.getSession(false);
            if (session != null) {
                sandboxId = (Long) session.getAttribute(SANDBOX_ID_VAR);
                if (LOG.isTraceEnabled()) {
                    if (sandboxId != null) {
                        LOG.trace("SandboxId found in session " + sandboxId);
                    }
                }
            }
        } else {
            HttpSession session = request.getSession();
            session.setAttribute(SANDBOX_ID_VAR, sandboxId);
        }
        return sandboxId;
    }

    private void setContentTime(HttpServletRequest request) {
        String sandboxDateTimeParam = request.getParameter(SANDBOX_DATE_TIME_VAR);
        if (sandBoxPreviewEnabled) {
            sandboxDateTimeParam = null;
        }
        Date overrideTime = null;

        try {
            if (request.getParameter(SANDBOX_DATE_TIME_RIBBON_OVERRIDE_PARAM) != null) {
                overrideTime = readDateFromRequest(request);
            } else if (sandboxDateTimeParam != null) {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Setting date/time using " + sandboxDateTimeParam);
                }
                overrideTime = CONTENT_DATE_FORMATTER.parse(sandboxDateTimeParam);
            }
        } catch (ParseException e) {
            LOG.debug(e);
        }

        if (overrideTime == null) {
            HttpSession session = request.getSession(false);
            if (session != null) {
                overrideTime = (Date) session.getAttribute(SANDBOX_DATE_TIME_VAR);
            }
        } else {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Setting date-time for sandbox mode to " + overrideTime + " for sandboxDateTimeParam = " + sandboxDateTimeParam);
            }
            HttpSession session = request.getSession();
            session.setAttribute(SANDBOX_DATE_TIME_VAR, overrideTime);
        }


        if (overrideTime != null) {
            FixedTimeSource ft = new FixedTimeSource(overrideTime.getTime());
            SystemTime.setLocalTimeSource(ft);
        } else {
            SystemTime.resetLocalTimeSource();
        }
    }

    private Date readDateFromRequest(HttpServletRequest request) throws ParseException {
        String date = request.getParameter(SANDBOX_DISPLAY_DATE_TIME_DATE_PARAM);
        String minutes = request.getParameter(SANDBOX_DISPLAY_DATE_TIME_MINUTES_PARAM);
        String hours = request.getParameter(SANDBOX_DISPLAY_DATE_TIME_HOURS_PARAM);
        String ampm = request.getParameter(SANDBOX_DISPLAY_DATE_TIME_AMPM_PARAM);

        if (StringUtils.isEmpty(minutes)) {
            minutes = Integer.toString(SystemTime.asCalendar().get(Calendar.MINUTE));
        }

        if (StringUtils.isEmpty(hours)) {
            hours = Integer.toString(SystemTime.asCalendar().get(Calendar.HOUR_OF_DAY));
        }

        String dateString = date + " " + hours + ":" + minutes + " " + ampm;

        if (LOG.isDebugEnabled()) {
            LOG.debug("Setting date/time using " + dateString);
        }

        Date parsedDate = CONTENT_DATE_PARSE_FORMAT.parse(dateString);
        return parsedDate;
    }

    private Site determineSite(ServletRequest request) {
        /* TODO:  Multi-tennant:  Need to add code that determines the site to support
         SiteService.retrieveAllSites();
         For each site, check the identifier type (e.g. hostname, url, param)
         to determine the current site.
         */
        return null;
    }

    /**
     * Returns a set of suffixes that can be ignored by content processing.   The following
     * are returned:
     * <p/>
     * <B>List of suffixes ignored:</B>
     *
     * ".aif", ".aiff", ".asf", ".avi", ".bin", ".bmp", ".doc", ".eps", ".gif", ".hqx", ".jpg", ".jpeg", ".mid", ".midi", ".mov", ".mp3", ".mpg", ".mpeg", ".p65", ".pdf", ".pic", ".pict", ".png", ".ppt", ".psd", ".qxd", ".ram", ".ra", ".rm", ".sea", ".sit", ".stk", ".swf", ".tif", ".tiff", ".txt", ".rtf", ".vob", ".wav", ".wmf", ".xls", ".zip";
     *
     * @return set of suffixes to ignore.
     */
    protected Set getIgnoreSuffixes() {
        if (ignoreSuffixes == null || ignoreSuffixes.isEmpty()) {
            String[] ignoreSuffixList = {".aif", ".aiff", ".asf", ".avi", ".bin", ".bmp", ".css", ".doc", ".eps", ".gif", ".hqx", ".js", ".jpg", ".jpeg", ".mid", ".midi", ".mov", ".mp3", ".mpg", ".mpeg", ".p65", ".pdf", ".pic", ".pict", ".png", ".ppt", ".psd", ".qxd", ".ram", ".ra", ".rm", ".sea", ".sit", ".stk", ".swf", ".tif", ".tiff", ".txt", ".rtf", ".vob", ".wav", ".wmf", ".xls", ".zip"};
            ignoreSuffixes = new HashSet<String>(Arrays.asList(ignoreSuffixList));
        }
        return ignoreSuffixes;
    }

    public int getMaxCacheElements() {
        return maxCacheElements;
    }

    public void setMaxCacheElements(int maxCacheElements) {
        this.maxCacheElements = maxCacheElements;
    }

    public int getCacheExpirationSeconds() {
        return cacheExpirationSeconds;
    }

    public void setCacheExpirationSeconds(int cacheExpirationSeconds) {
        this.cacheExpirationSeconds = cacheExpirationSeconds;
    }

    public int getMaxCacheConcurrency() {
        return maxCacheConcurrency;
    }

    public void setMaxCacheConcurrency(int maxCacheConcurrency) {
        this.maxCacheConcurrency = maxCacheConcurrency;
    }

    public List<URLProcessor> getUrlProcessorList() {
        return urlProcessorList;
    }

    public void setUrlProcessorList(List<URLProcessor> urlProcessorList) {
        this.urlProcessorList = urlProcessorList;
    }

    public Boolean getSandBoxPreviewEnabled() {
        return sandBoxPreviewEnabled;
    }

    public void setSandBoxPreviewEnabled(Boolean sandBoxPreviewEnabled) {
        this.sandBoxPreviewEnabled = sandBoxPreviewEnabled;
    }
}
TOP

Related Classes of org.broadleafcommerce.cms.web.BroadleafProcessURLFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.