/*
 * This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
 *
 * Copyright 2008-2011 Geosparc nv, http://www.geosparc.com/, Belgium.
 *
 * The program is available in open source according to the GNU Affero
 * General Public License. All contributions in this program are covered
 * by the Geomajas Contributors License Agreement. For full licensing
 * details, see LICENSE.txt in the project root.
 */

package org.geomajas.servlet;

import javax.servlet.http.HttpServletRequest;

import org.geomajas.service.DispatcherUrlService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * {@link org.geomajas.service.DispatcherUrlService} which tries to automatically detect the dispatcher server address.
 *
 * @author Joachim Van der Auwera
 * @author Oliver May
 */
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AutomaticDispatcherUrlService implements DispatcherUrlService {

	private static final String X_FORWARD_HOST_HEADER = "X-Forwarded-Host";
	private static final String X_GWT_MODULE_HEADER = "X-GWT-Module-Base";
	
	private Logger log = LoggerFactory.getLogger(AutomaticDispatcherUrlService.class);

	/** {@inheritDoc} */
	public String getDispatcherUrl() {
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		if (null == requestAttributes || !(requestAttributes instanceof ServletRequestAttributes)) {
			log.warn("Trying to automatically get the dispatcher URL, but not running inside a servlet request. " +
					"You are recommended to use StaticDispatcherUrlService");
			return "./d/"; // use relative URL as back-up, will fail in many cases
		}

		HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();

		String serverName = request.getServerName();
		
		// X-Forwarded-Host if behind a reverse proxy, fallback to general method.
		// Alternative we could use the gwt module url to guess the real URL.
		if (null != request.getHeader(X_FORWARD_HOST_HEADER)) {
			log.warn("AutomaticDispatcherService detected a X-Forwarded-Host header which means the server is " +
					"accessed using a reverse proxy server. This might cause problems in some cases. You are " +
					"recommended to configure your tomcat connector to be aware of the original url. " +
					"(see http://tomcat.apache.org/tomcat-6.0-doc/proxy-howto.html )");
			String gwtModuleBase = request.getHeader(X_GWT_MODULE_HEADER);
			if (null != gwtModuleBase) {
				// Get last slash in the gwtModuleBase, ignoring the trailing slash.
				int contextEndIndex = gwtModuleBase.lastIndexOf("/", gwtModuleBase.length() - 2);
				if (contextEndIndex > -1) {
					return gwtModuleBase.substring(0, contextEndIndex) + "/d/";
				}
			} else {
				// else get the information from the X-forwarded-host header and default to the standard behaviour 
				serverName = request.getHeader(X_FORWARD_HOST_HEADER);
			}
		}
		
		String url = request.getScheme() + "://" + serverName;
		if (80 != request.getServerPort()) {
			url += ":" + request.getServerPort();
		}
		String cp = request.getContextPath();
		if (null != cp && cp.length() > 0) {
			url += request.getContextPath();
		}
		url += "/d/";
		return url;
	}
}

@@ -448,55 +448,8 @@
 t;%0A%0A
-import javax.servlet.http.HttpServletRequest;%0A%0A
 impo
@@ -925,16 +925,63 @@
 butes;%0A%0A
+import javax.servlet.http.HttpServletRequest;%0A%0A
 /**%0A * %7B
@@ -1461,17 +1461,16 @@
 -Base%22;%0A
-%09
 %0A%09privat
@@ -2174,18 +2174,16 @@
 Name();%0A
-%09%09
 %0A%09%09// X-
@@ -3292,18 +3292,16 @@
 %09%09%7D%0A%09%09%7D%0A
-%09%09
 %0A%09%09Strin
@@ -3305,45 +3305,112 @@
 ring
- url = request.getScheme() + %22://%22 + 
+Builder url = new StringBuilder();%0A%09%09url.append(request.getScheme());%0A%09%09url.append(%22://%22);%0A%09%09url.append(
 serv
@@ -3415,16 +3415,17 @@
 rverName
+)
 ;%0A%09%09if (
@@ -3467,18 +3467,53 @@
 %09url
- += %22:%22 + 
+.append(%22:%22);%0A%09%09%09url.append(Integer.toString(
 requ
@@ -3531,16 +3531,18 @@
 erPort()
+))
 ;%0A%09%09%7D%0A%09%09
@@ -3624,20 +3624,24 @@
 %7B%0A%09%09%09url
- += 
+.append(
 request.
@@ -3652,24 +3652,25 @@
 ontextPath()
+)
 ;%0A%09%09%7D%0A%09%09url 
@@ -3672,17 +3672,22 @@
 %09url
- += 
+.append(
 %22/d/%22
+)
 ;%0A%09%09
@@ -3696,15 +3696,26 @@
 turn url
+.toString()
 ;%0A%09%7D%0A%7D%0A

use StringBuilder instead of string concatenation