/*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (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.mozilla.org/MPL/>.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 * language governing rights and limitations under the License.
 * 
 * The Original Code is the Venice Web Communities System.
 * 
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.dynamo.servlet;

import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.log4j.Logger;
import com.silverwrist.dynamo.WebConstants;
import com.silverwrist.dynamo.iface.*;

class ServletHeaderOutput implements HeaderOutput, WebConstants
{
  /*--------------------------------------------------------------------------------
   * Internal class which holds headers until the response is prepared
   *--------------------------------------------------------------------------------
   */

  private static class HeaderHolder
  {
    /*====================================================================
     * Attributes
     *====================================================================
     */

    private HashMap m_headers = new HashMap();

    /*====================================================================
     * Constructor
     *====================================================================
     */

    HeaderHolder()
    { // do nothing
    } // end constructor

    /*====================================================================
     * External operations
     *====================================================================
     */

    synchronized void saveHeader(String name, Object value, boolean append)
    {
      ArrayList l = (ArrayList)(m_headers.get(name));
      if (l==null)
      { // create the arraylist and save it off
	l = new ArrayList();
	m_headers.put(name,l);

      } // end if

      if (!append)
	l.clear();  // clear previous values first
      l.add(value);

    } // end saveHeader

    boolean containsHeader(String name)
    {
      return m_headers.containsKey(name);

    } // end containsHeader

    synchronized void flushHeaders(HttpServletResponse resp)
    {
      Iterator it = m_headers.keySet().iterator();
      while (it.hasNext())
      { // get the key and the list of values
	String name = (String)(it.next());
	ArrayList l = (ArrayList)(m_headers.get(name));
	Iterator it2 = l.iterator();
	while (it2.hasNext())
	{ // add the values in in turn
	  Object val = it.next();
	  if (val instanceof Integer)
	    resp.addIntHeader(name,((Integer)val).intValue());
	  else if (val instanceof java.util.Date)
	    resp.addDateHeader(name,((java.util.Date)val).getTime());
	  else
	    resp.addHeader(name,val.toString());

	} // end while

      } // end while

    } // end flushHeaders

  } // end class HeaderHolder

  /*--------------------------------------------------------------------------------
   * Static data members
   *--------------------------------------------------------------------------------
   */

  private static Logger logger = Logger.getLogger(ServletHeaderOutput.class);

  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private HttpServletRequest m_req;
  private HttpServletResponse m_resp;
  private HeaderHolder m_holder = null;

  /*--------------------------------------------------------------------------------
   * Constructors
   *--------------------------------------------------------------------------------
   */

  ServletHeaderOutput(HttpServletRequest req)
  {
    m_req = req;
    m_resp = null;

  } // end constructor

  ServletHeaderOutput(HttpServletRequest req, HttpServletResponse resp)
  {
    m_req = req;
    m_resp = resp;

  } // end constructor

  /*--------------------------------------------------------------------------------
   * Internal operations
   *--------------------------------------------------------------------------------
   */

  private synchronized final HeaderHolder getHeaderHolder()
  {
    if (m_holder==null)
    { // look for the headers object in request attributes
      m_holder = (HeaderHolder)(m_req.getAttribute(REQUEST_NEWHEADERHOLDER_ATTR));
      if (m_holder==null)
      { // create the object and save off a reference
	m_holder = new HeaderHolder();
	m_req.setAttribute(REQUEST_NEWHEADERHOLDER_ATTR,m_holder);

      } // end if

    } // end if

    return m_holder;

  } // end getHeaderHolder

  /*--------------------------------------------------------------------------------
   * Implementations from class HeaderOutput
   *--------------------------------------------------------------------------------
   */

  public void setHeader(String name, String value, boolean append)
  {
    if (m_resp!=null)
    { // set the header directly
      if (append)
	m_resp.addHeader(name,value);
      else
	m_resp.setHeader(name,value);

    } // end if
    else
      getHeaderHolder().saveHeader(name,value,append);

  } // end setHeader

  public void setHeader(String name, int value, boolean append)
  {
    if (m_resp!=null)
    { // set the header directly
      if (append)
	m_resp.addIntHeader(name,value);
      else
	m_resp.setIntHeader(name,value);

    } // end if
    else
      this.setHeader(name,new Integer(value),append);

  } // end setIntHeader

  public void setHeader(String name, Integer value, boolean append)
  {
    if (m_resp!=null)
      this.setHeader(name,value.intValue(),append);
    else
      getHeaderHolder().saveHeader(name,value,append);

  } // end setHeader

  public void setHeader(String name, java.util.Date value, boolean append)
  {
    if (m_resp!=null)
    { // set the header directly
      long tmp = value.getTime();
      if (append)
	m_resp.addDateHeader(name,tmp);
      else
	m_resp.setDateHeader(name,tmp);

    } // end if
    else
      getHeaderHolder().saveHeader(name,value,append);

  } // end setHeader

  public boolean containsHeader(String name)
  {
    if (m_resp!=null)
      return m_resp.containsHeader(name);
    else
      return getHeaderHolder().containsHeader(name);

  } // end containsHeader

  /*--------------------------------------------------------------------------------
   * External operations
   *--------------------------------------------------------------------------------
   */

  static void flushHeaders(HttpServletRequest req, HttpServletResponse resp)
  {
    HeaderHolder hh = (HeaderHolder)(req.getAttribute(REQUEST_NEWHEADERHOLDER_ATTR));
    if (hh!=null)
    { // flush headers
      req.removeAttribute(REQUEST_NEWHEADERHOLDER_ATTR);
      hh.flushHeaders(resp);

    } // end if

  } // end flushHeaders

} // end class ServletHeaderOutput
