/*
 * This file is part of Nuts Framework.
 * Copyright(C) 2009-2012 Nuts Develop Team.
 *
 * Nuts Framework is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License any later version.
 * 
 * Nuts Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
package nuts.core.servlet;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;



import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * SessionRecoverFilter
 * 
 * <pre>
 * Set cookie [CSESSIONID=JSESSIONID; path=request.getContextPath(); expires=session.getMaxInactiveInterval()].
 * if request.getSession(false) is null and cookie.JSESSION is null and cookie.CSESSIONID exists,
 * set response cookie [JSESSIONID=CSESSION], 
 * and redirect to the request URL with query string build by request.parameters. 
 * </pre>
 */
public class SessionRecoverFilter implements Filter {
	/**
	 * log
	 */
	protected static Log log = LogFactory.getLog(SessionRecoverFilter.class);

	/**
	 * JSESSIONID = "JSESSIONID";
	 */
	public final static String JSESSIONID = "JSESSIONID";
	
	/**
	 * CSESSIONID = "CSESSIONID";
	 */
	public final static String CSESSIONID = "CSESSIONID";
	
	/**
	 * Constructor.
	 */
	public SessionRecoverFilter() {
	}

	/**
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
	 */
	public void init(FilterConfig config) throws ServletException {
	}

	/**
	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
	 */
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
		throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest)req; 
		HttpServletResponse response = (HttpServletResponse)res; 

		HttpSession session = request.getSession(false);

		if (log.isDebugEnabled()) {
			log.debug("filter - " + request.getRequestURI() + " [" + (session == null ? "null" : session.getId()) + "]");
		}
		
		String csessionId = null;
		String jsessionId = null;
		
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (Cookie c : cookies) {
				if (c.getName().equalsIgnoreCase(CSESSIONID)) {
					csessionId = c.getValue();
				}
				else if (c.getName().equalsIgnoreCase(JSESSIONID)) {
					jsessionId = c.getValue();
				}
			}
		}

		if (session == null) {
			if (csessionId != null && !csessionId.equals(jsessionId)) {
				Cookie c = new Cookie(JSESSIONID, csessionId);
				c.setPath("/");
				response.addCookie(c);

				String url = URLHelper.buildURL(request);
				if (log.isDebugEnabled()) {
					log.debug("Redirect - " + url + " [" + JSESSIONID + "=" + c.getValue() + "]");
				}
				response.sendRedirect(url);

				return;
			}
		}
		else {
			if (jsessionId != null && !jsessionId.equals(csessionId)) {
				Cookie c = new Cookie(CSESSIONID, jsessionId);
				c.setPath(request.getContextPath());
				c.setMaxAge(session.getMaxInactiveInterval());

				if (log.isDebugEnabled()) {
					log.debug("Set cookie - [" + CSESSIONID + "=" + c.getValue() + "; path=" + c.getPath() + "; expires=" + c.getMaxAge() + ";]");
				}
				response.addCookie(c);
			}
		}
		
		chain.doFilter(req, res);
	}

	/**
	 * @see javax.servlet.Filter#destroy()
	 */
	public void destroy() {
	}

}
