import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.sql.*;

import ConnectionPool.*;

/*
    This servlet acts as a cache for domain values.  In our
    Catalog Example it caches the Category Names and Codes.
    Preventing excessive database queries.
*/
public class CatalogDomainServlet extends HttpServlet {

  // Method Name: init()
  // Purpose: This is the default init() method.
  public void init(ServletConfig config)
    throws ServletException {

    super.init(config);

    initializeDomains();
  }

  // Method Name: initializeDomains()
  // Purpose: This method gets a reference to the database
  // ConnectionPool from the ServletContext.  It then performs
  // a query getting all of the Category values in the
  // database.  These values are then stored in a Vector and
  // placed in the ServletContext keyed by the string
  // DOMAIN_LIST.
  private void initializeDomains() throws ServletException {

    Connection con = null;
    ConnectionPool pool = null;
    Vector categories = new Vector(8);
    Category category = null;

    try {

      // Get a reference to the ConnectionPool from the Global
      // ServletContext
      ServletContext context = getServletContext();
      // Get a connection from the ConnectionPool
      if ( context == null ) {

        throw new ServletException("Could not get a reference" +
          " to the ServletContext");
      }
      pool =(ConnectionPool)
        context.getAttribute("CONNECTION_POOL");

      // Get a connection from the ConnectionPool
      if ( pool == null ) {

        // Sleep for 5 seconds and try again
        try {

          Thread.sleep(5000);
          pool =(ConnectionPool)
            context.getAttribute("CONNECTION_POOL");
        }
        catch (Exception e) {

          throw new ServletException(e.getMessage());
        }
        if ( pool == null ) {

          // Still could not get reference
          throw new ServletException("Could not get reference" +
            " to the CONNECTION_POOL");
        }
      }
      con = pool.getConnection();
      // Get a connection from the ConnectionPool
      if ( con == null ) {

        throw new ServletException("Could not get reference" +
          " Connection.");
      }
      if ( con != null ) {

        // Create the statement
        Statement statement = con.createStatement();

        // Use the created statement to SELECT the DATA
        // FROM the Titles Table.
        ResultSet rs = statement.executeQuery("SELECT * " +
         "FROM Categories");

        // Iterate over the ResultSet
        while ( rs.next() ) {

          category = new Category();

          category.setId(rs.getInt("category_id"));

          // get the name, which is a String
          category.setName(rs.getString("category_name"));

          // add the resulting category to the Vector
          categories.addElement(category);
        }
        // Close the ResultSet
        rs.close();

        // Once the domain list is Initailized, add it to the
        // Global ServletContext.  This makes it available
        // To other servlets using the same ServletContext.
        context.setAttribute("DOMAIN_LIST", categories);
      }
    }
    catch (SQLException sqle) {

      System.err.println(sqle.getMessage());
    }
    catch (Exception e) {

      System.err.println(e.getMessage());
    }
    finally {

      // Release the connection
      pool.releaseConnection(con);
    }
  }

  // Method Name: doGet()
  // Purpose: This method services GET requests.  Its only
  // purpose is to prove that the domain values are loading
  // properly.
  public void doGet(HttpServletRequest request,
    HttpServletResponse response)
    throws ServletException, IOException {

    response.setContentType("text/html");
    PrintWriter out = new PrintWriter (response.getOutputStream());
    out.println("<html>");
    out.println("<head><title>CatalogServlet</title></head>");
    out.println("<body>");

    // Get reference to ServletContext
    ServletContext context = getServletContext();
    // Get reference to the DOMAIN_LIST Vector
    Vector categories = (Vector)context.getAttribute("DOMAIN_LIST");

    // Itereate over the list of categories
    for (int x = 0; x < categories.size(); x++ ) {

      Category category = (Category)categories.elementAt(x);

      out.println(category.getId() + "-->" + category.getName() + "<BR>");
    }
    out.println("</body></html>");
    out.close();
  }

  // Method Name: destroy()
  // Purpose: This method performs cleanup on the Vector
  // and the ServletContext.
  public void destroy() {

    // Access the ServletContext using the getAttribute()
    // method, which returns a reference to the Categoies.
    ServletContext context = getServletContext();
    Vector categories =
      (Vector)context.getAttribute("DOMAIN_LIST");

    if ( categories != null ) {

      // Empty List
      categories.removeAllElements();
      // Remove the Attribute from the ServletContext
      context.removeAttribute("DOMAIN_LIST");
    }
    else {

      System.err.println("Could not get a reference to DOMAIN_LIST!");
    }
  }

  //Get Servlet information
  public String getServletInfo() {

    return "CatalogDomainServlet Information";
  }
}
