ResponseHeaderService.java

package sk.iway.iwcm.components.response_header.rest;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Service;

import sk.iway.iwcm.Cache;
import sk.iway.iwcm.Constants;
import sk.iway.iwcm.Logger;
import sk.iway.iwcm.RequestBean;
import sk.iway.iwcm.SetCharacterEncodingFilter;
import sk.iway.iwcm.Tools;
import sk.iway.iwcm.common.CloudToolsForCore;
import sk.iway.iwcm.components.response_header.jpa.ResponseHeaderEntity;
import sk.iway.iwcm.components.response_header.jpa.ResponseHeaderRepository;

@Service
public class ResponseHeaderService {

    private static final String CACHE_KEY = "apps.response-header.headersList-";
    private static final Integer cacheInMinutes = 1440; //24 hours

    public Map<String, ResponseHeaderEntity> getResponseHeaders(String url) {
        int domainId = CloudToolsForCore.getDomainId();

        //FIRST step, check Cache for values, in specific domain
        @SuppressWarnings("unchecked")
        List<ResponseHeaderEntity> headersList = (List<ResponseHeaderEntity>)Cache.getInstance().getObject(CACHE_KEY + domainId);

        if(headersList == null) {

            //Cache is empty for this domain, lets fill it up with values from DB
            //For that we need get Repository
            //!! Bug fix, @Autowired does not work so we must get repostiry using "getSpringBean"
            RequestBean requestBean = SetCharacterEncodingFilter.getCurrentRequestBean();
            if (requestBean != null) {
                ResponseHeaderRepository rhr = requestBean.getSpringBean("responseHeaderRepository", ResponseHeaderRepository.class);

                //Get DB data
                headersList = rhr.findByDomainId(domainId);
            }
            if(headersList == null) headersList = new ArrayList<>();

            //Set new object to Cache, reasponse headers value from DB
            Cache.getInstance().setObject(CACHE_KEY + domainId, headersList, cacheInMinutes);
        }

        return  this.filterRequestHeadersByUrl(headersList, url);
    }

    private Map<String, ResponseHeaderEntity> filterRequestHeadersByUrl(List<ResponseHeaderEntity> headersInput, String url) {
        //Empty list
        if(headersInput.size() < 1) return null;

        //Prepare output map
        Map<String, ResponseHeaderEntity> headersMap = new HashMap<>();

        //Now filter headers using path
        for(ResponseHeaderEntity header : headersInput) {
            if(isPathCorrect(header.getUrl(), url)) {
                //be smart, try to find headers with best match (longest) URL address
                String key = header.getHeaderName();
                ResponseHeaderEntity current = headersMap.get(key);
                if (current == null) {
                    headersMap.put(key, header);
                } else {
                    if (current.getUrl().length()<header.getUrl().length()) {
                        headersMap.put(key, header);
                    }
                }
            }
        }

        //return filtred values
        return headersMap;
    }

    public static void deleteDomainCache() {
        int domainId = CloudToolsForCore.getDomainId();
        Cache.getInstance().removeObject(CACHE_KEY + domainId, true);
    }

    /**
     * Set HTTP headers for path
     */
    public static void setResponseHeaders(String path, HttpServletRequest request, HttpServletResponse response) {
        try {
            ResponseHeaderService pes = new ResponseHeaderService();
            Map<String, ResponseHeaderEntity> headersMap = pes.getResponseHeaders(path);
            if (headersMap!=null) {
                for(ResponseHeaderEntity header : headersMap.values()) {
                    String name = Constants.executeMacro(header.getHeaderName());
                    String value = Constants.executeMacro(header.getHeaderValue());

                    if (name.equalsIgnoreCase("content-language")) {
                        setContentLanguageHeader(value, true, request, response);
                    } else {
                        response.setHeader(name, value);
                    }
                }
            }
        } catch (Exception ex) {
            Logger.error(ResponseHeaderService.class, ex);
        }
    }

    /**
     * Set Content-Language header, also set response.setLocale
     * @param lngContryPair - pair eg sk-SK, cs-CZ, en-GB
     * @param forceSet - set to true to owerwrite previously set value
     * @param request
     * @param response
     */
    public static void setContentLanguageHeader(String lngContryPair, boolean forceSet, HttpServletRequest request, HttpServletResponse response) {
        if (request.getAttribute("contentLanguageHeaderSet")==null || forceSet) {
            response.setHeader("Content-Language", lngContryPair);
            response.setLocale(org.springframework.util.StringUtils.parseLocaleString(lngContryPair.replaceAll("-", "_")));
            request.setAttribute("contentLanguageHeaderSet", Boolean.TRUE);
        }
    }

    /**
     * Check if path is correct for URL, it accepts path in format
     * - /path/subpath/ - use startsWith
     * - /path/subpath/*.pdf - use startsWith for /path/subpath/ and endsWith for *.pdf
     * - /path/subpath/*.pdf,*.jpg - use startsWith for /path/subpath/ and endsWith for *.pdf or *.jpg
     * - ^/path/subpath/$ - use equals
     * @param path - path to test
     * @param url - URL address to test
     * @return
     */
    public static boolean isPathCorrect(String path, String url) {

        // check if path is null
        if (path == null || url == null) {
            return false;
        }

        // check if path is in format ^/path/subpath/$
        if (path.startsWith("^") && path.endsWith("$") && path.length() > 2) {
            return path.substring(1, path.length() - 1).equals(url);
        }
        int pos = path.indexOf("*");
        if (pos == -1) {
            // check if path is in format /path/subpath/
            return url.startsWith(path);
        } else if (pos == path.length()-1) {
            // check if path is in format /path/subpath/*
            return url.startsWith(path.substring(0, pos));
        } else {
            // check if path is in format /path/subpath/*.pdf
            String pathStart = path.substring(0, pos);
            String pathEnd = path.substring(pos);
            if (pathEnd.indexOf(",") == -1 && pathEnd.length() > 1) {
                // check if path is in format /path/subpath/*.pdf
                return url.startsWith(pathStart) && url.endsWith(pathEnd.substring(1));
            } else {
                // check if path is in format /path/subpath/*.pdf,*.jpg
                String[] pathEnds = Tools.getTokens(pathEnd, ",", true);
                for (String pathEndItem : pathEnds) {
                    if (url.startsWith(pathStart) && pathEndItem.length()>1 && url.endsWith(pathEndItem.substring(1))) {
                        return true;
                    }
                }
            }
        }

        return false;
    }
}