/*
 * 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) 2002 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.venice.servlet;

import java.io.*;
import java.util.*;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.HttpStatusCode;
import com.silverwrist.dynamo.Namespaces;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.servlet.ServletBase;
import com.silverwrist.dynamo.util.*;

public class FrameServlet extends ServletBase
{
  /*--------------------------------------------------------------------------------
   * Static data members
   *--------------------------------------------------------------------------------
   */

  private static final int DEFAULT_HARD_LIMIT = 5;
  private static final int DEFAULT_SOFT_LIMIT = 10;

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

  private File m_base_directory;         // base directory from where we get static pages
  private HardSoftCache m_cache;         // cache for static page information

  /*--------------------------------------------------------------------------------
   * Abstract implementations from class ServletBase
   *--------------------------------------------------------------------------------
   */

  protected Object process(Request r, Application app) throws Exception
  {
    String page_name = r.getExtraPath().substring(1);
    PageData pd = (PageData)(m_cache.get(page_name));
    if (pd!=null)
    { // found page data - test to see if it's been modified
      if (pd.isModified())
      { // data is modified - kick it out of the cache
	m_cache.remove(page_name);
	pd = null;

      } // end if

    } // end if

    if (pd==null)
    { // Start by getting the File associated with this page name.
      File page_file = new File(m_base_directory,page_name);
      if (!(page_file.canRead()))  // can't read the farking file!
	return new HttpErrorMessage(HttpStatusCode.E_NOTFOUND);

      // Figure out whether this is actually "frameable" content.
      MIMETypeMapper mapper = (MIMETypeMapper)(r.queryService(MIMETypeMapper.class));
      String type = mapper.getMIMEType(page_name);
      boolean is_text = type.startsWith("text/html");

      try
      { // Create the page data and cache it.
	if (is_text)
	{ // only cache the text pages
	  pd = new TextPageData(page_file,r.getRequestPath() + r.getExtraPath());
	  m_cache.put(page_name,pd);

	} // end if
	else  // just output binary data
	  pd = new BinaryPageData(page_file,type);

      } // end try
      catch (IOException e)
      { // if there's an error reading the page data, send back a 500 Internal Server Error
	return new HttpErrorMessage(HttpStatusCode.E_INTERNAL,e.getMessage());

      } // end catch

    } // end if

    return pd;  // return the PageData to be rendered

  } // end process

  /*--------------------------------------------------------------------------------
   * Overrides from class ServletBase
   *--------------------------------------------------------------------------------
   */

  protected void initServlet(ServiceProvider services) throws DynamoException
  {
    // Start by getting the base directory.
    ObjectProvider oprov = (ObjectProvider)(services.queryService(ObjectProvider.class));
    String base_dir = (String)(oprov.getObject(Namespaces.SUBSTRATE_NAMESPACE,
					       ApplicationSubstrate.OBJ_BASE_PATH));

    // Now try and get the content prefix and append it to that base path.
    try
    { // retrieve the prefix for the frame servlet
      String pfx = (String)(oprov.getObject(Namespaces.SERVLET_INIT_NAMESPACE,"content.prefix"));
      if (!(pfx.startsWith("/")))
	base_dir += "/";
      base_dir += pfx;

    } // end try
    catch (NoSuchObjectException e)
    { // leave the base path as it is
    } // end catch

    m_base_directory = new File(base_dir);
    if (!(m_base_directory.isDirectory()))
    { // it's not a directory - throw an exception!
      ConfigException ce = new ConfigException(FrameServlet.class,"FrameServletMessages",
					       "basepath.notDirectory");
      ce.setParameter(0,m_base_directory.getAbsolutePath());
      throw ce;

    } // end if

    int hard_limit = DEFAULT_HARD_LIMIT;
    try
    { // get the hard limit from the configuration and parse it
      String s = (String)(oprov.getObject(Namespaces.SERVLET_INIT_NAMESPACE,"cache.hard.limit"));
      hard_limit = Integer.parseInt(s);

    } // end try
    catch (NoSuchObjectException e)
    { // if the hard limit is not present, default it
      hard_limit = DEFAULT_HARD_LIMIT;

    } // end catch
    catch (NumberFormatException e)
    { // if it's not an integer, that's an error
      throw new ConfigException(FrameServlet.class,"FrameServletMessages","hardlimit.notInteger");

    } // end catch

    int soft_limit = DEFAULT_SOFT_LIMIT;
    try
    { // get the soft limit from the configuration and parse it
      String s = (String)(oprov.getObject(Namespaces.SERVLET_INIT_NAMESPACE,"cache.soft.limit"));
      soft_limit = Integer.parseInt(s);

    } // end try
    catch (NoSuchObjectException e)
    { // if the soft limit is not present, default it
      soft_limit = DEFAULT_SOFT_LIMIT;

    } // end catch
    catch (NumberFormatException e)
    { // if it's not an integer, that's an error
      throw new ConfigException(FrameServlet.class,"FrameServletMessages","softlimit.notInteger");

    } // end catch

    // Create the cache.
    m_cache = new HardSoftCache(hard_limit,soft_limit);

  } // end initServlet

} // end class FrameServlet
