001/*
002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Anahide Tchertchian
018 */
019package org.nuxeo.ecm.web.resources.wro.factory;
020
021import static org.apache.commons.lang3.Validate.notNull;
022
023import java.util.Map;
024
025import javax.servlet.http.HttpServletRequest;
026
027import org.apache.commons.io.FilenameUtils;
028import org.apache.commons.lang3.StringUtils;
029import org.apache.commons.lang3.Validate;
030import org.apache.commons.logging.Log;
031import org.apache.commons.logging.LogFactory;
032import org.nuxeo.common.utils.URIUtils;
033
034import ro.isdc.wro.cache.CacheKey;
035import ro.isdc.wro.cache.factory.DefaultCacheKeyFactory;
036import ro.isdc.wro.config.ReadOnlyContext;
037import ro.isdc.wro.model.group.DefaultGroupExtractor;
038import ro.isdc.wro.model.group.GroupExtractor;
039import ro.isdc.wro.model.group.Inject;
040import ro.isdc.wro.model.resource.ResourceType;
041
042/**
043 * Cache key extractor generating a key depending on all request parameters, and accepting slash character for page
044 * names.
045 *
046 * @since 7.10
047 */
048public class NuxeoWroPageCacheKeyFactory extends DefaultCacheKeyFactory {
049
050    private static final Log log = LogFactory.getLog(NuxeoWroPageCacheKeyFactory.class);
051
052    protected static final String URI_MARKER = "/resource/page/";
053
054    @Inject
055    private GroupExtractor groupExtractor;
056
057    @Inject
058    private ReadOnlyContext context;
059
060    @Override
061    public CacheKey create(HttpServletRequest request) {
062        notNull(request);
063        CacheKey key = null;
064
065        GroupExtractor ext = new DefaultGroupExtractor() {
066
067            @Override
068            public String getGroupName(HttpServletRequest request) {
069                Validate.notNull(request);
070                String uri = request.getRequestURI();
071                // check if include or uri path are present and use one of these as request uri.
072                final String includeUriPath = (String) request.getAttribute(ATTR_INCLUDE_PATH);
073                uri = includeUriPath != null ? includeUriPath : uri;
074                final String groupName = FilenameUtils.removeExtension(getPageName(stripSessionID(uri)));
075                return StringUtils.isEmpty(groupName) ? null : groupName;
076            }
077
078            private String stripSessionID(final String uri) { // NOSONAR
079                if (uri == null) {
080                    return null;
081                }
082                return uri.replaceFirst("(?i)(;jsessionid.*)", "");
083            }
084
085            protected String getPageName(String filename) {
086                if (filename == null) {
087                    return null;
088                }
089                int index = filename.indexOf(URI_MARKER);
090                if (index != -1) {
091                    return filename.substring(index + URI_MARKER.length());
092                }
093                return null;
094            }
095
096        };
097
098        final String groupName = ext.getGroupName(request);
099        final ResourceType resourceType = groupExtractor.getResourceType(request);
100        final boolean minimize = isMinimized(request);
101        if (groupName != null && resourceType != null) {
102            key = new CacheKey(groupName, resourceType, minimize);
103        }
104
105        if (key != null) {
106            // add additional attributes for request-related info
107            Map<String, String> params = URIUtils.getRequestParameters(request.getQueryString());
108            if (params != null) {
109                for (Map.Entry<String, String> entry : params.entrySet()) {
110                    key.addAttribute(entry.getKey(), entry.getValue());
111                }
112            }
113        }
114        if (log.isDebugEnabled()) {
115            log.debug(String.format("Cache key for request '%s' '%s': %s", request.getRequestURL(),
116                    request.getQueryString(), key));
117        }
118        return key;
119    }
120
121    /**
122     * Uses isMinimizeEnabled configuration to compute minimize value.
123     */
124    private boolean isMinimized(final HttpServletRequest request) { // NOSONAR
125        return context.getConfig().isMinimizeEnabled() ? groupExtractor.isMinimized(request) : false;
126    }
127
128}