LocaleWrappedServletResponse.java

/*
 * Copyright 2018 Global Crop Diversity Trust
 *
 * 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.genesys.server.servlet.filter;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LocaleWrappedServletResponse extends HttpServletResponseWrapper {
	private static final Logger LOG = LoggerFactory.getLogger(LocaleWrappedServletResponse.class);

	private String prefix;
	private LocaleURLMatcher localeUrlMatcher;
	private String defaultLanguagePrefix;

	public LocaleWrappedServletResponse(HttpServletResponse response, LocaleURLMatcher localeUrlMatcher, String urlLanguage, String defaultLanguage) {
		super(response);
		this.localeUrlMatcher = localeUrlMatcher;
		this.prefix = updatePrefix(urlLanguage);
		LOG.debug("Response prefix={} lang={}", prefix, urlLanguage);
		this.defaultLanguagePrefix = "/" + defaultLanguage + "/";
	}

	private boolean isExcluded(String url) {
		// Exclude querystring-only urls, URLs starting with //, http:// or https:// and anything excluded by
		// the matcher
		boolean excluded = url.startsWith("?") || url.startsWith("//") || url.startsWith("http://") || url.startsWith("https://") || localeUrlMatcher.isExcluded(url);
		LOG.trace("isExcluded? {} --> {}", url, excluded);
		return excluded;
	}

	@Override
	public String encodeURL(String url) {
		if (isExcluded(url)) {
			if (url.startsWith(defaultLanguagePrefix)) {
				LOG.debug("URL starts with defaultLanguagePrefix={} trimming down", defaultLanguagePrefix);
				return super.encodeURL(url.substring(defaultLanguagePrefix.length() - 1));
			}
			return super.encodeURL(url);
		} else {
			String encodedURL = prefix + super.encodeURL(url);
			LOG.debug("encodeURL {} to {}", url, encodedURL);
			return encodedURL;
		}
	}

	@Override
	@Deprecated
	public String encodeUrl(String url) {
		if (isExcluded(url)) {
			return super.encodeUrl(url);
		} else {
			String encodedURL = prefix + super.encodeUrl(url);
			LOG.debug("encodeUrl {} to {}", url, encodedURL);
			return encodedURL;
		}
	}

	@Override
	public String encodeRedirectURL(String url) {
		if (isExcluded(url)) {
			return super.encodeRedirectURL(url);
		} else {
			String encodedURL = prefix + super.encodeRedirectURL(url);
			LOG.debug("encodeRedirectURL {} to {}", url, encodedURL);
			return encodedURL;
		}
	}

	@Override
	@Deprecated
	public String encodeRedirectUrl(String url) {
		if (isExcluded(url)) {
			return super.encodeRedirectUrl(url);
		} else {
			String encodedURL = prefix + super.encodeRedirectUrl(url);
			LOG.debug("encodeRedirectUrl {} to {}", url, encodedURL);
			return encodedURL;
		}
	}

	@Override
	public void sendRedirect(String location) throws IOException {
		if (isExcluded(location)) {
			super.sendRedirect(location);
		} else {
			String prefixedUrl = prefix + location;
			LOG.debug("sendRedirect {} to {}", location, prefixedUrl);
			super.sendRedirect(prefixedUrl);
		}
	}

	@Override
	public void setHeader(String name, String value) {
		LOG.debug("setHeader {}: {}", name, value);
		if ("Location".equalsIgnoreCase(name)) {
			if (isExcluded(value)) {
				super.setHeader(name, value);
			} else {
				String prefixedUrl = prefix + value;
				LOG.debug("Rewrote redirect header {}: {} -> {}", name, value, prefixedUrl);
				super.setHeader(name, prefixedUrl);
			}
		} else {
			super.setHeader(name, value);
		}
	}

	private String updatePrefix(String language) {
		if (StringUtils.isBlank(language)) {
			return "";
		} else {
			return "/" + language;
		}
	}
}