/*
 * $Id$ $Revision$
 * $Date$
 * 
 * ==============================================================================
 * 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 wicket.protocol.http;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Locale;

import javax.servlet.http.HttpServletResponse;

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

import wicket.Response;
import wicket.WicketRuntimeException;
import wicket.util.time.Time;

/**
 * Implements responses over the HTTP protocol by holding an underlying
 * HttpServletResponse object and providing convenience methods for using that
 * object. Convenience methods include methods which: add a cookie, close the
 * stream, encode a URL, redirect a request to another resource, determine if a
 * redirect has been issued, set the content type, set the locale and, most
 * importantly, write a String to the response output.
 * 
 * @author Jonathan Locke
 */
public class WebResponse extends Response
{
	/** Log. */
	private static final Log log = LogFactory.getLog(WebResponse.class);

	/** True if response is a redirect. */
	protected boolean redirect;

	/** The underlying response object. */
	private final HttpServletResponse httpServletResponse;

	/**
	 * Constructor for testing harness.
	 */
	WebResponse()
	{
		this.httpServletResponse = null;
	}

	/**
	 * Package private constructor.
	 * 
	 * @param httpServletResponse
	 *            The servlet response object
	 * @throws IOException
	 */
	WebResponse(final HttpServletResponse httpServletResponse) throws IOException
	{
		this.httpServletResponse = httpServletResponse;
	}

	/**
	 * Closes response output.
	 */
	public void close()
	{
		// NOTE: Servlet container will close the response output stream
		// automatically, so we do nothing here.
	}

	/**
	 * Returns the given url encoded.
	 * 
	 * @param url
	 *            The URL to encode
	 * @return The encoded url
	 */
	public final String encodeURL(final String url)
	{
		if (httpServletResponse != null)
		{
			return httpServletResponse.encodeURL(url);
		}
		return url;
	}

	/**
	 * Gets the wrapped http servlet response object.
	 * 
	 * @return The wrapped http servlet response object
	 */
	public final HttpServletResponse getHttpServletResponse()
	{
		return httpServletResponse;
	}

	/**
	 * @see wicket.Response#getOutputStream()
	 */
	public OutputStream getOutputStream()
	{
		try
		{
			return httpServletResponse.getOutputStream();
		}
		catch (IOException e)
		{
			throw new WicketRuntimeException("Error while getting output stream.", e);
		}
	}

	/**
	 * Whether this response is going to redirect the user agent.
	 * 
	 * @return True if this response is going to redirect the user agent
	 */
	public final boolean isRedirect()
	{
		return redirect;
	}

	/**
	 * Redirects to the given url.
	 * 
	 * @param url
	 *            The URL to redirect to
	 */
	public void redirect(final String url)
	{
		if (httpServletResponse != null)
		{
			try
			{
				if (httpServletResponse.isCommitted())
				{
					log.error("Unable to redirect. HTTP Response has already been committed.");
				}

				if (log.isDebugEnabled())
				{
					log.debug("Redirecting to " + url);
				}

				httpServletResponse.sendRedirect(url);
				redirect = true;
			}
			catch (IOException e)
			{
				throw new WicketRuntimeException("Redirect failed", e);
			}
		}
	}

	/**
	 * Set the content type on the response.
	 * 
	 * @param mimeType
	 *            The mime type
	 */
	public final void setContentType(final String mimeType)
	{
		httpServletResponse.setContentType(mimeType);
	}

	/**
	 * @see wicket.Response#setContentLength(long)
	 */
	public void setContentLength(long length)
	{
		httpServletResponse.setContentLength((int)length);
	}

	/**
	 * @see wicket.Response#setLastModifiedTime(wicket.util.time.Time)
	 */
	public void setLastModifiedTime(Time time)
	{
		if (time != null)
		{
			// If time is set also set cache headers.
			httpServletResponse.setDateHeader("Expires", time.getMilliseconds() * 1000 + 3600);
			httpServletResponse.setHeader("Cache-Control", "max-age=" + 3600);
			httpServletResponse.setDateHeader("Last-Modified", time.getMilliseconds());
		}
	}

	/**
	 * Output stream encoding. If the deployment descriptor contains a
	 * locale-encoding-mapping-list element, and that element provides a mapping
	 * for the given locale, that mapping is used. Otherwise, the mapping from
	 * locale to character encoding is container dependent. Default is
	 * ISO-8859-1.
	 * 
	 * @see javax.servlet.ServletResponse#setLocale(java.util.Locale)
	 * 
	 * @param locale
	 *            The locale use for mapping the character encoding
	 */
	public final void setLocale(final Locale locale)
	{
		httpServletResponse.setLocale(locale);
	}

	/**
	 * Writes string to response output.
	 * 
	 * @param string
	 *            The string to write
	 */
	public void write(final String string)
	{
		try
		{
			httpServletResponse.getWriter().write(string);
		}
		catch (IOException e)
		{
			throw new WicketRuntimeException("Error while writing to servlet output writer.", e);
		}
	}
}

@@ -4560,22 +4560,24 @@
 s() 
-* 1000 + 36
++ (3600 * 10
 00)
+)
 ;%0A%09%09

fix for the Expires header