Package org.gjt.bugrat.servlet

Source Code of org.gjt.bugrat.servlet.BugRatServlet$RequiredException

package org.gjt.bugrat.servlet;

import java.io.*;
import java.util.*;
import java.text.FieldPosition;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.AddressException;

import org.gjt.bugrat.db.*;
import org.gjt.bugrat.dbi.*;
import org.gjt.bugrat.mail.StringDataSource;
import org.gjt.bugrat.text.BugFormatter;
import org.gjt.bugrat.text.ReportFormatter;
import org.gjt.bugrat.util.BugRatLogger;


public
class    BugRatServlet
extends    HttpServlet
implements  BugRatConstants, BugRatLogger, DBConfigChangeListener
  {
  private static final String    VERSION_STRING = "2.5.3";

  protected boolean        debug = false;

  protected String        jdbcUrl = null;
  protected Properties      jdbcProps = null;
  protected String        jdbcDriverClassName = null;

  protected ServletConfig      config = null;
  protected ServletContext    context = null;
  protected DBConfig        dbConfig = null;

  protected BugRatHTML      output = null;
  protected MailQueueThread    mailQueue = null;

  protected String        adminServlet = null;
  protected String        reportServlet = null;
  protected String        viewerServlet = null;

  protected boolean        allowsBugComments = true;
  protected boolean        allowsRepComments = true;
  protected boolean        commentReqsAdmin = false;
  protected boolean        newUserReqsAdmin = false;

  protected SimpleDateFormat    dateFmt = null;
  protected BugFormatter      bugFmt = null;
  protected ReportFormatter    reportFmt = null;


  protected String
  getVersionStr()
    {
    return VERSION_STRING;
    }

  protected ServletConfig
  getConfig()
    {
    return this.config;
    }

  protected ServletContext
  getContext()
    {
    return this.context;
    }

  protected DBConfig
  getDBConfig()
    {
    return this.dbConfig;
    }

  protected String
  getAdminServletName()
    {
    return this.adminServlet;
    }

  protected String
  getReportServletName()
    {
    return this.reportServlet;
    }

  protected String
  getViewerServletName()
    {
    return this.viewerServlet;
    }

  protected BugRatHTML
  getOutput()
    {
    return this.output;
    }

  protected int
  getUserId( BugRatRequest bReq )
    throws DBIException
    {
    int result = 0;

    HttpServletRequest req = bReq.getRequest();

    String userName = req.getRemoteUser();
    if ( userName != null )
      {
      Person p = Person.getLoginPerson( userName );
      if ( p != null )
        {
        result = p.getId();
        }
      }

    return result;
    }

  /**
   * Returns whether or not this servlet has admin authority.
   * Subclasses must override in order to set admin to true.
   */

  public boolean
  isAdmin()
    {
    return false;
    }

  /**
   * Returns whether or not this servlet allows comments to be
   * added to reports.
   */

  public boolean
  allowsReportComments()
    {
    return this.allowsRepComments;
    }

  /**
   * Returns whether or not this servlet allows comments to be
   * added to bugs.
   */

  public boolean
  allowsBugComments()
    {
    return this.allowsBugComments;
    }

  /**
   * Returns whether or not the addition of comments to reports
   * requires admin authority or not. This applies only to reports,
   * since all Bug edits require admin by default.
   */

  public boolean
  getCommentsRequireAdmin()
    {
    return this.commentReqsAdmin;
    }

  /**
   * Returns whether or not the creation of new users
   * requires admin authority or not.
   */

  public boolean
  getNewUserRequiresAdmin()
    {
    return this.newUserReqsAdmin;
    }


  public void
  sendCommonHeader( BugRatRequest req, PrintWriter cW )
    {
    this.output.sendCommonHeader( req, cW, "BugRat Servlet" );
    }

  public void
  sendCommonHeader( BugRatRequest req, PrintWriter cW, String title )
    {
    this.output.sendCommonHeader( req, cW, title );
    }

  public void
  sendCommonTrailer( BugRatRequest req, PrintWriter cW )
    {
    this.output.sendCommonTrailer( req, cW );
    }

  /**
   * This is to process GET requests that are common to all of
   * the BugRat servlets.
   *
   * @return True of the request was processed, otherwise false.
   *
   */

  public boolean
  commonGet( BugRatRequest bReq )
    throws ServletException, IOException
    {
    boolean result = true;

    String pathInfo = bReq.getPathInfo();

    if ( pathInfo == null || pathInfo.length() == 0 )
      {
      // Leave the default page to the specific servlet...
      result = false;
      }
    else if ( pathInfo.equalsIgnoreCase( "/ListCategories" ) )
      {
      this.getOutput().listCategories( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/about" ) )
      {
      this.sendAboutPage( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ListPeople" ) )
      {
      this.getOutput().listPeople( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ChooseBug" ) )
      {
      this.getOutput().sendBugIDForm( bReq, "/ChooseBug" );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ChooseReport" ) )
      {
      this.getOutput().sendReportIDForm( bReq, "/ChooseReport" );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ShowProjectAllReports" ) )
      {
      this.getOutput().showAllProjectReports( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ShowProjectAllBugs" ) )
      {
      this.getOutput().showAllProjectBugs( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ShowAllReports" ) )
      {
      this.getOutput().showAllReports( bReq, null );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ShowAllLinkedReports" ) )
      {
      this.getOutput().showAllReports( bReq, "linked" );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ShowUnLinkedReports" ) )
      {
      this.getOutput().showAllReports( bReq, "unlinked" );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ShowAllBugs" ) )
      {
      this.getOutput().showAllBugs( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ReloadConfig" ) )
      {
      this.reloadDBConfiguration( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ShowStatistics" ) )
      {
      this.getOutput().showAllStatistics( bReq );
      }
    else if ( pathInfo.startsWith( "/images/" ) )
      {
      this.getOutput().sendImage( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/SelectAllReports" ) )
      {
      this.getOutput().sendSelectAll( bReq, "ShowReports" );
      }
    else if ( pathInfo.equalsIgnoreCase( "/SelectBugsByResponsible" ) )
      {
      this.selectByResponsible( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/SelectReportsBySubmitter" ) )
      {
      this.selectBySubmitter( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/BrowseBugs" ) )
      {
      this.browseBugs( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/SearchBugs" ) )
      {
      this.searchBugs( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/BrowseReports" ) )
      {
      this.browseReports( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/SearchReports" ) )
      {
      this.searchReports( bReq );
      }
    else if ( pathInfo.startsWith( "/AddBugComment/" ) )
      {
      String idStr =
        pathInfo.substring
          ( "/AddBugComment/".length() );

      if ( ! this.isAdmin() )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat - Requires Admin" );
        this.reportError
          ( bReq, cW,
            "You must use the Admin servlet to add "
            + "comments to bugs." );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      else if ( ! this.allowsBugComments() )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat - Not Allowed" );
        this.reportError
          ( bReq, cW,
            "BugRat is configured to not allow comments on bugs." );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      else try
        {
        int id = Integer.parseInt( idStr );
        this.getOutput().sendCommentForm( bReq, "Bug", id );
        }
      catch ( NumberFormatException ex )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat - Error Parsing ID" );
        this.reportError
          ( bReq, cW,
            "Could not parse Bug ID '" +idStr+ "'" );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      }
    else if ( pathInfo.startsWith( "/AddReportComment/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/AddReportComment/".length() );

      if ( ! this.allowsReportComments() )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat - No Comments" );
        this.reportError
          ( bReq, cW,
            "BugRat is configured to not allow comments on reports." );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      else if ( this.getCommentsRequireAdmin() && ! this.isAdmin() )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat - Requires Admin" );
        this.reportError
          ( bReq, cW,
            "BugRat is configured to only allow the admin "
            + "servlet to add comments to reports." );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      else try
        {
        id = Integer.parseInt( idStr );
        this.getOutput().sendCommentForm( bReq, "Report", id );
        }
      catch ( NumberFormatException ex )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat - Error Parsing ID" );
        this.reportError
          ( bReq, cW,
            "Could not parse Report ID '" +idStr+ "'" );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      }
    else if ( pathInfo.equals( "/SelectReports" )
          || pathInfo.startsWith( "/SelectReports/" ) )
      {
      String selStr =
        pathInfo.equals( "/SelectReports" )
        ? ""
        : pathInfo.substring( "/SelectReports/".length() );

      String[] selArgs = this.splitString( selStr, "/" );

      if ( selArgs == null || selArgs.length == 0 )
        {
        this.getOutput().sendSelectProject( bReq, "ShowReports" );
        }
      else if ( selArgs.length == 1 )
        {
        this.getOutput().sendSelectCategory
          ( bReq, selArgs[0], "ShowReports" );
        }
      else if ( selArgs.length == 2 )
        {
        this.getOutput().sendSelectSubCategory
          ( bReq, selArgs[0], selArgs[1], "ShowReports" );
        }
      else
        {
        // UNDONE
        }
      }
    else if ( pathInfo.startsWith( "/ShowReports/" ) )
      {
      String title = null;
      String matchString = null;

      String selStr =
        pathInfo.substring( "/ShowReports/".length() );

      String[] selArgs = this.splitString( selStr, "/" );

      PrintWriter cW = bReq.getHTMLWriter();
      this.sendCommonHeader( bReq, cW, "BugRat - Show Reports" );

      if ( selArgs != null && selArgs.length == 1 )
        {
        title =
          "Reports For " +
          this.getDBConfig().getProjectName( selArgs[0] );

        matchString =
          "SELECT * from report " +
          "WHERE project = '" + selArgs[0] + "'";
        }
      else if ( selArgs != null && selArgs.length == 2 )
        {
        title =
          "Reports For " +
          this.getDBConfig().getProjectName( selArgs[0] ) +
          " / " +
          this.getDBConfig().getCategoryName( selArgs[0], selArgs[1] );

        matchString =
          "SELECT * from report " +
          "WHERE project = '" + selArgs[0] + "'" +
          "  AND category = '" + selArgs[1] + "'";
        }
      else if ( selArgs != null && selArgs.length == 3 )
        {
        title =
          "Reports For " +
          this.getDBConfig().getProjectName( selArgs[0] ) +
          " / " +
          this.getDBConfig().getCategoryName( selArgs[0], selArgs[1] ) +
          " / " +
          this.getDBConfig().getSubCategoryName
            ( selArgs[0], selArgs[1], selArgs[2] );

        matchString =
          "SELECT * from report " +
          "WHERE project = '" + selArgs[0] + "'" +
          "  AND category = '" + selArgs[1] + "'" +
          "  AND subcat = '" + selArgs[2] + "'";
        }
      else
        {
        this.reportError( bReq, cW,
          "Error, wrong number of arguments for ShowReports." );
        }

      if ( matchString != null )
        {
        try {
          Vector repV = Report.matchReports( matchString );

          if ( repV.size() > 0 )
            {
            this.getOutput().showReports
              ( bReq, cW, title, repV, "ShowReport" );
            }
          else
            {
            // UNDONE - Need common method for this!!!!!
            cW.println
              ( "<h2>No Reports</h2> "
                + "There were no matching bug reports." );
            }
          }
        catch ( DBIException ex )
          {
          this.log( "/SelectReports/ MATCH CALL", ex );
          this.reportError( bReq, cW,
            "Error, exception trying to match in SelectReports: "
              + ex.getMessage() );
          }
        }

      this.sendCommonTrailer( bReq, cW );
      cW.close();
      }
    else if ( pathInfo.startsWith( "/ShowReport/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/ShowReport/".length() );

      PrintWriter cW = bReq.getHTMLWriter();
      this.sendCommonHeader( bReq, cW, "BugRat - Show Report #" + idStr );

      try {
        id = Integer.parseInt( idStr );
        this.getOutput().showReport( bReq, cW, id );
        }
      catch ( NumberFormatException ex )
        {
        this.reportError
          ( bReq, cW,
            "Could not parse Report ID '" + idStr + "'" );
        }

      this.sendCommonTrailer( bReq, cW );
      cW.close();
      }
    else if ( pathInfo.startsWith( "/ShowBug/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/ShowBug/".length() );

      PrintWriter cW = bReq.getHTMLWriter();
      this.sendCommonHeader( bReq, cW, "BugRat - Show Bug #" + idStr );

      try {
        id = Integer.parseInt( idStr );
        this.getOutput().showBug( bReq, cW, id );
        }
      catch ( NumberFormatException ex )
        {
        this.reportError
          ( bReq, cW,
            "Could not parse Bug ID '" + idStr + "'" );
        }

      this.sendCommonTrailer( bReq, cW );
      cW.close();
      }
    else if ( pathInfo.startsWith( "/ShowComment/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/ShowComment/".length() );

      PrintWriter cW = bReq.getHTMLWriter();
      this.sendCommonHeader( bReq, cW, "BugRat - Show Comment #" + idStr );

      try {
        id = Integer.parseInt( idStr );
        this.getOutput().showComment( bReq, cW, id );
        }
      catch ( NumberFormatException ex )
        {
        this.reportError
          ( bReq, cW,
            "Could not parse Comment ID '" + idStr + "'" );
        }

      this.sendCommonTrailer( bReq, cW );
      cW.close();
      }
    else if ( pathInfo.startsWith( "/ShowReportComments/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/ShowReportComments/".length() );

      try {
        id = Integer.parseInt( idStr );

        this.getOutput().showComments( bReq, "Report", id );
        }
      catch ( NumberFormatException ex )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat - Show Report Comments" );
        this.reportError
          ( bReq, cW,
            "Could not parse Report ID '" + idStr + "'" );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      }
    else if ( pathInfo.startsWith( "/ShowBugComments/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/ShowBugComments/".length() );

      try {
        id = Integer.parseInt( idStr );

        this.getOutput().showComments( bReq, "Bug", id );
        }
      catch ( NumberFormatException ex )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat - Error Parsing ID" );
        this.reportError
          ( bReq, cW,
            "Could not parse Bug ID '" + idStr + "'" );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      }
    else if ( pathInfo.startsWith( "/ShowBugActions/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/ShowBugActions/".length() );

      try {
        id = Integer.parseInt( idStr );
        this.getOutput().showActions( bReq, "Bug", id );
        }
      catch ( NumberFormatException ex )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat - Error Parsing ID" );
        this.reportError
          ( bReq, cW,
            "Could not parse Bug ID '" + idStr + "'" );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      }
    else if ( pathInfo.startsWith( "/ShowReportActions/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/ShowReportActions/".length() );

      try {
        id = Integer.parseInt( idStr );
        this.getOutput().showActions( bReq, "Report", id );
        }
      catch ( NumberFormatException ex )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat - Error Parsing ID" );
        this.reportError
          ( bReq, cW,
            "Could not parse Report ID '" + idStr + "'" );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      }
    else if ( pathInfo.startsWith( "/ShowEmail/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/ShowEmail/".length() );

      PrintWriter cW = bReq.getHTMLWriter();
      this.sendCommonHeader( bReq, cW, "BugRat - Show Email #" + idStr );

      try {
        id = Integer.parseInt( idStr );
        this.getOutput().showEmailMessage( bReq, cW, id );
        }
      catch ( NumberFormatException ex )
        {
        this.reportError
          ( bReq, cW,
            "Could not parse Email ID '" + idStr + "'" );
        }

      this.sendCommonTrailer( bReq, cW );
      cW.close();
      }
    else if ( pathInfo.equalsIgnoreCase( "/EditPerson" ) )
      {
      this.getOutput().sendSelectPersonPage( bReq );
      }
    else if ( pathInfo.startsWith( "/EditPerson/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/EditPerson/".length() );

      PrintWriter cW = bReq.getHTMLWriter();

      try {
        id = Integer.parseInt( idStr );
        this.sendCommonHeader( bReq, cW, "BugRat - Edit Person" );
        this.getOutput().sendEditPersonForm( bReq, cW, id, false );
        }
      catch ( NumberFormatException ex )
        {  
        this.sendCommonHeader( bReq, cW, "BugRat Error" );
        this.reportError
          ( bReq, cW,
            "Could not parse Person ID '" + idStr + "'" );
        }

      this.sendCommonTrailer( bReq, cW );
      cW.close();
      }
    else if ( pathInfo.startsWith( "/MailBug/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/MailBug/".length() );

      try {
        id = Integer.parseInt( idStr );
        this.sendMailItemForm( bReq, "B", id );
        }
      catch ( NumberFormatException ex )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat Error" );
        this.reportError
          ( bReq, cW,
            "Could not parse Bug ID '" +idStr+ "'" );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      }
    else if ( pathInfo.startsWith( "/MailReport/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/MailReport/".length() );

      try {
        id = Integer.parseInt( idStr );
        this.sendMailItemForm( bReq, "R", id );
        }
      catch ( NumberFormatException ex )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat Error" );
        this.reportError
          ( bReq, cW,
            "Could not parse Report ID '" +idStr+ "'" );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      }
    else
      {
      result = false;
      }

    return result;
    }

  /**
   * This is to process POST requests that are common to all of
   * the BugRat servlets.
   *
   * @return True of the request was processed, otherwise false.
   *
   */

  public boolean
  commonPost( BugRatRequest bReq )
    throws ServletException, IOException
    {
    boolean result = true;

    String pathInfo = bReq.getPathInfo();

    if ( pathInfo.equalsIgnoreCase( "/ChooseBug" ) )
      {
      this.getOutput().processChooseBug( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ChooseReport" ) )
      {
      this.getOutput().processChooseReport( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/AddComment" ) )
      {
      this.processAddComment( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/CommitPerson" ) )
      {
      this.processCommitPerson( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/SelectBugsByResponsible" ) )
      {
      this.selectBugsByResponsible( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/SelectReportsBySubmitter" ) )
      {
      this.selectReportsBySubmitter( bReq );
      }
    else if ( pathInfo.endsWith( "/BrowseForBugs" ) )
      {
      this.processBrowseForBugs( bReq );
      }
    else if ( pathInfo.endsWith( "/SearchForBugs" ) )
      {
      this.processSearchForBugs( bReq );
      }
    else if ( pathInfo.endsWith( "/BrowseForReports" ) )
      {
      this.processBrowseForReports( bReq );
      }
    else if ( pathInfo.endsWith( "/SearchForReports" ) )
      {
      this.processSearchForReports( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ShowReports" ) )
      {
      this.processShowReports( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ShowBugs" ) )
      {
      this.processShowBugs( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/MailItem" ) )
      {
      this.processMailItem( bReq );
      }
    else
      {
      result = false;
      }

    return result;
    }

  private void
  sendAboutPage( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - About" );

    this.sendPropertyHTML( bReq, cW, "commonServlet.aboutHtml" );

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  sendPropertyHTML( BugRatRequest bReq, PrintWriter cW, String propName )
    throws IOException
    {
    String htmlText =
      this.getDBConfig().getProperty( propName );

    if ( htmlText == null )
      {
      this.reportError( bReq, cW,
        "Could not load the property '" + propName
          + "' from the BugRat database 'property' table." );
      }
    else
      {
      Object[] fmtArgs =
        {
        bReq.getServletContext(),
        this.adminServlet,
        this.reportServlet,
        this.viewerServlet
        };

      htmlText = this.format( htmlText, fmtArgs );

      cW.println( htmlText );
      }
    }

  protected void
  reportError( BugRatRequest bReq, PrintWriter cW, String errorHtml )
    throws IOException
    {
    this.output.reportError( bReq, cW, errorHtml );
    }

  //
  // DBConfigChangeListener interface
  //
  public void
  dbConfigHasChanged()
    {
    this.log( "dbConfigHasChanged() The DB config has changed." );
    this.initializeConfiguration();
    this.logConfigParameters( this.getServletInfo() );
    }

  public void
  reloadDBConfiguration( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Reload Configuration" );

    try {
      this.getDBConfig().retrieveConfiguration();

      cW.println( "<h2>Configuration Reloaded</h2>" );
      cW.println( "The BugRat configuration has been " );
      cW.println( "successfully reloaded from the database." );
      cW.println( "<BR><BR><BR>" );
      cW.println( "<a href=\"" + bReq.getServletPath() + "/\">");
      cW.println( "Back to the main page...</a>" );
      }
    catch ( DBIException ex )
      {
      this.reportError
        ( bReq, cW,
          "<h2>ERROR Reloading Configuration</h2>" +
          "Reloading the configuration from the " +
          "database failed.<p><strong>" + ex.getMessage() +
          "</strong>" );
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  /**
   *
     * processAddComment - process the posting of an edited bug
     *
     *
     */
    protected void
    processAddComment( BugRatRequest bReq )
    throws IOException
    {
    DBConfig config = this.getDBConfig();
            
    String bgColor = config.getProperty( "reportServlet.bgColor" );
    String okColor = config.getProperty( "reportServlet.okColor" );
    String errColor = config.getProperty( "reportServlet.errColor" );
            
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Add Comment" );

    cW.println( "<h2>Adding Comment</h2>" );

    try {
      String value;
      String[] valAry;

      valAry = bReq.getParameterValues( "target" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "target" );
      String target = valAry[0];

      valAry = bReq.getParameterValues( "id" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "id" );
      String idStr = valAry[0];

      valAry = bReq.getParameterValues( "commentor" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "commentor" );
      String commentorIdStr = valAry[0];

      int commentorId = -1;
      try { commentorId = Integer.parseInt( commentorIdStr ); }
      catch ( NumberFormatException ex )
        { commentorId = -1; }

      if ( commentorId == -1 )
        {
        throw this.new RequiredException
          ( "commentor" );
        }
    /*
      valAry = bReq.getParameterValues( "email" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "email" );
      String emailStr = valAry[0];

      valAry = bReq.getParameterValues( "name" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "name" );
      String nameStr = valAry[0];
    */
      valAry = bReq.getParameterValues( "synopsis" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "synopsis" );
      String synopsis = valAry[0];

      valAry = bReq.getParameterValues( "comment" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "comment" );
      String comment = valAry[0];

      int id = -1;
      try { id = Integer.parseInt( idStr ); }
      catch ( NumberFormatException ex )
        { id = -1; }

      if ( id == -1 )
        {
        this.reportError( bReq, cW,
          "Bad " + target + " id: '" + idStr + "'" );
        }
      else
        {
        Comment cmt = Description.getNewComment();

        Description desc = cmt.getDescription();

        desc.setSynopsis( synopsis );
        desc.setDescription( comment );
        desc.setURL( null );
        desc.setEmailId( 0 );
        desc.setMimeType(
          ( config.isTextHTML( comment ) )
            ? "text/html" : "text/plain" );

        cmt.setTargetId( id );
        cmt.setTarget
          ( target.equalsIgnoreCase( "Report" )
            ? "R" : "B" );
      /*
        Person person = Person.getPerson( emailStr );
        if ( person == null )
          {
          person =
            Person.getNewPerson
              ( PERSON_ANON, emailStr, nameStr );
          }
        cmt.setCommentorId( person.getId() );
      */
        cmt.setCommentorId( commentorId );
        cmt.setCommentTime( new java.util.Date() );

        cmt.commit();

        cW.println( "Successfully added comment to " );
        cW.println( target );
        cW.println( " # " + id + ".<p>" );
        cW.print  ( "<A HREF=\"" );
        cW.print  ( bReq.getServletPath() );
        cW.print  ( "/Show" );
        cW.print  ( target );
        cW.print  ( "/" + id );
        cW.println( "\">" );
        cW.println( "Show " + target + " #" + id + "." );
        cW.println( "</A>" );
        }
      }
    catch ( RequiredException ex )
      {
      this.reportError( bReq, cW,
        "Required field '" + ex.getMessage() + "' is missing!" );
      }
    catch ( DBIException ex )
      {
      this.reportError( bReq, cW,
        "Error committing comment to database, "
        + ex.getMessage() );
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  sendMailItemForm( BugRatRequest bReq, String selector, int id )
    throws IOException
    {
    String itemName =
      selector.equals( "B" ) ? "Bug" : "Report";

    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader
      ( bReq, cW, "BugRat - Mail " + itemName + " #" + id );

    cW.println( "<H2>Mail " + itemName + " #" + id + "</H2>" );

    cW.println( "Use this form to mail a bug or report to someone." );
    cW.println( "The email will be sent to everyone you list in the " );
    cW.println( "fields below. " );

    try {
      Object item =
        selector.equals( "B" )
          ? (Object)Bug.getBug( id )
          : (Object)Report.getReport( id );

      if ( item == null )
        throw new DBIException
          ( itemName + " ID=" + id + " does not exist" );

      int respId =
        selector.equals( "B" )
          ? ((Bug) item).getResponsible()
          : ((Report) item).getResponsible();

      Person p = Person.getPerson( respId );

      cW.print  ( "<FORM method=\"POST\" action=\"" );
      cW.print  ( bReq.getServletPath() );
      cW.print  ( "/MailItem\">" );

      cW.print  ( "<INPUT type=\"hidden\" name=\"id\"" );
      cW.println( "       value=\"" + id + "\">" );

      cW.print  ( "<INPUT type=\"hidden\" name=\"selector\"" );
      cW.println( "       value=\"" + selector + "\">" );

      cW.println( "Email the " + itemName + " with ID " );
      cW.println( id );
      cW.println( " to:<p> " );

      cW.println( "<strong>BugRat User:</strong><br>" );

      this.getOutput().sendPersonSelector
        ( bReq, cW, -1,
          ( (p == null) ? -1 : p.getId() ),
            "user", null, null );

      cW.println( "<P>" );

      cW.println( "<strong>Others:</strong>" );
      cW.println( "(separate email addresses with commas)" );
      cW.println( "<br>" );

      cW.println( "<TEXTAREA name=\"other\" rows=\"3\" cols=\"64\">" );
      cW.println( "</TEXTAREA>" );

      cW.println( "<P>" );

      cW.println( "<strong>Comment:</strong>" );
      cW.println( "(may be empty)" );
      cW.println( "<br>" );

      cW.println( "<TEXTAREA name=\"comment\" rows=\"8\" cols=\"64\">" );
      cW.println( "</TEXTAREA>" );

      cW.println( "<P>" );

      cW.print  ( "<INPUT type=\"submit\"" );
      cW.println( "       name=\"submit\" value=\"Send Email\">" );

      cW.println( "</FORM>" );
      }
    catch ( DBIException ex )
      {
      cW.println( "<hr>" );
      this.getOutput().reportError( bReq, cW,
        "Error getting bug #" + id
        + " to email, " + ex.getMessage() );
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  /**
   *
     * processEmailBug - email a bug to someone
     *
     */
    protected void
    processMailItem( BugRatRequest bReq )
    throws IOException
    {
    DBConfig config = this.getDBConfig();

    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader
      ( bReq, cW, "BugRat - Emailed Item" );

    try {
      String value;
      String[] valAry;

      valAry = bReq.getParameterValues( "selector" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "item selector" );
      String itemSel = valAry[0];

      boolean isBug = itemSel.equals( "B" );
      String itemName = isBug ? "Bug" : "Report";

      valAry = bReq.getParameterValues( "id" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "ID" );
      String idStr = valAry[0];

      int id = Integer.parseInt( idStr );

      String userIdStr = null;
      valAry = bReq.getParameterValues( "user" );
      if ( this.isEmptyParameter( valAry ) )
        userIdStr = null;
      else
        userIdStr = valAry[0];

      String otherStr = null;
      valAry = bReq.getParameterValues( "other" );
      if ( this.isEmptyParameter( valAry ) )
        otherStr = null;
      else
        otherStr = valAry[0];

      String commentStr = null;
      valAry = bReq.getParameterValues( "comment" );
      if ( this.isEmptyParameter( valAry ) )
        commentStr = null;
      else
        commentStr = valAry[0];

      try {
        Object item = isBug
          ? (Object)Bug.getBug( id )
          : (Object)Report.getReport( id );

        if ( item == null )
          {
          cW.print  ( "<h2>Emailing " );
          cW.print  ( itemName );
          cW.println( " #" + id + "</h2>" );

          this.reportError( bReq, cW,
            "Could not retrieve " +itemName+ " #" + id );
          }
        else
          {
          InternetAddress addr = null;
          Vector vAddr = new Vector(2);

          int userId = 0;
          Person p = null;
          if ( userIdStr != null )
            {
            userId = Integer.parseInt( userIdStr );
            }

          if ( userId != 0 )
            {
            p = Person.getPerson( userId );
            if ( p == null )
              {
              throw new DBIException
                ( "Could not find email user #"
                  + userId );
              }
            }

          if ( p != null )
            {
            vAddr.addElement
              ( new InternetAddress
                ( p.getEmail(), p.getName() ) );
            }

          if ( otherStr != null && otherStr.length() > 0 )
            {
            InternetAddress[] oa =
              InternetAddress.parse( otherStr );

            if ( oa != null && oa.length > 0 )
              {
              for ( int i = 0 ; i < oa.length ; ++i )
                {
                vAddr.addElement( oa[i] );
                }
              }
            }

          InternetAddress fromAddr = null;
          int senderId = this.getUserId( bReq );
          if ( senderId != 0 )
            {
            p = Person.getPerson( senderId );
            if ( p != null )
              {
              fromAddr = new InternetAddress
                ( p.getEmail(), p.getName() );
              }
            }

          Description desc = isBug
            ? ((Bug) item).getDescription()
            : ((Report) item).getDescription();

          String subject =
              "BugRat " +itemName+ " #" + id
              + " - " + desc.getSynopsis();

          StringBuffer body = new StringBuffer();

          if ( commentStr != null )
            {
            body.append( "----- Sender's Comment -----" );
            body.append( "\n" );
            body.append( commentStr );
            body.append( "\n" );
            body.append( "----- End Of Sender's Comment ---------------------------" );

            body.append( "\n" +itemName+ " URL: <" );
            body.append( bReq.getServletUrlPrefix() );
            body.append( bReq.getViewerServletPath() );
            body.append( isBug ? "/ShowBug/" : "/ShowReport/" );
            body.append( id );
            body.append( ">" );
            body.append( "\n\n" );
            }

          StringWriter sW = new StringWriter();
          PrintWriter pW = new PrintWriter( sW );

          if ( isBug )
            {
            this.bugFmt.format
              ( (Bug)item, bReq, pW, "text/plain", true );
            }
          else
            {
            this.reportFmt.format
              ( (Report)item, bReq, pW, "text/plain", true );
            }

          body.append( itemName );
          body.append( " #" );
          body.append( id );
          body.append( " Details\n\n" );

          body.append( sW.toString() );

          //
          // ATTACHMENT
          //
          Vector attach = null;
          sW = new StringWriter();
          pW = new PrintWriter( sW );

          pW.println( "<html>" );
          pW.println( "<head>" );
          pW.println( "<title>" );
          pW.println( "BugRat " + itemName + " #" );
          pW.println( id );
          pW.println( "</title>" );
          pW.println( "</head>" );
          pW.println( "<body>" );

          pW.println( "<h2>" );
          pW.println( "BugRat " + itemName + " #" );
          pW.println( id );
          pW.println( "</h2>" );

          if ( isBug )
            {
            this.bugFmt.format
              ( (Bug)item, bReq, pW, "text/html", true );
            }
          else
            {
            this.reportFmt.format
              ( (Report)item, bReq, pW, "text/html", true );
            }

          pW.print  ( "<p>" );
          pW.println( "<center>" );
          pW.print  ( "<a href=\"" );
          pW.print  ( bReq.getServletUrlPrefix() );
          pW.print  ( bReq.getViewerServletPath() );
          pW.print  ( isBug ? "/ShowBug/" : "/ShowReport/" );
          pW.print  ( id );
          pW.println( "\">" );
          pW.println( "View this " + itemName + " online..." );  
          pW.println( "</a>" );
          pW.println( "</center>" );
          pW.print  ( "</p>" );

          pW.println( "</body>" );
          pW.println( "</html>" );

          attach = new Vector();

          StringDataSource ds =
            new StringDataSource
              ( sW.getBuffer().toString(),
                ( itemName + "-" + id + ".html" ),
                  "text/html" );

          attach.addElement( ds );

          InternetAddress[] toAddrs =
            new InternetAddress[ vAddr.size() ];

          vAddr.copyInto( toAddrs );

          this.mailQueue.addMailJob
            ( subject, body.toString(),
              fromAddr, toAddrs, null, attach );

          if ( isBug )
            this.getOutput().showBug( bReq, cW, id );
          else
            this.getOutput().showReport( bReq, cW, id );
          }
        }
      catch ( NumberFormatException ex )
        {
        cW.println( "<h2>Mailing " +itemName+ "</h2>" );
        throw this.new RequiredException
          ( "could not parse '"
            + ( (id == -1) ? "bug" : "person" )
            + "' id, " + ex.getMessage() );
        }
      catch ( AddressException ex )
        {
        cW.println( "<h2>Mailing " +itemName+ "</h2>" );
        this.reportError( bReq, cW,
          "Error parsing email address '"
          + otherStr + "', " + ex.getMessage() );
        }
      catch ( DBIException ex )
        {
        cW.println( "<h2>Mailing " +itemName+ "</h2>" );
        this.reportError( bReq, cW,
          "Error committing reassignment of bug #"
          + id + ", " + ex.getMessage() );
        }
      }
    catch ( RequiredException ex )
      {
      cW.println( "<h2>Required Field Missing</h2>" );
      this.reportError( bReq, cW,
        "The required field '" + ex.getMessage() + "' is missing!" );
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  browseBugs( BugRatRequest bReq )
    throws IOException
    {
    Vector lpV = null;
    DBConfig config = this.getDBConfig();

    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Browse Bugs" );

    cW.println( "<H2>Browse Bugs</h2>" );
    cW.println( "Browse bugs in database by choosing from among the " );
    cW.println( "following choices. Choose as many as you wish." );
    cW.println( "<BR><BR>" );
    cW.print  ( "<FORM method=\"POST\" action=\"" );
    cW.print  ( bReq.getServletPath() );
    cW.println( "/BrowseForBugs\">" );

    cW.println( "<TABLE width=\"100%\" border=\"1\" cellpadding=\"2\">" );

    cW.println( "<TR bgcolor=\"#F0F0FF\">" );
    cW.println( "<TH align=\"left\" colspan=\"2\">" );
    cW.println( "Project:" );
    cW.println( "</TH>" );
    cW.println( "</TR>" );

    cW.println( "<TR>" );
    cW.println( "<TD width=\"100%\" align=\"top\" colspan=\"2\">" );

    cW.println( "<TABLE width=\"100%\" border=\"0\">" );

    cW.println( "<TR>" );
    cW.println( "<TD>" );

    Vector projects = config.getProjects();
    for ( int i = 0, sz = projects.size() ; i < sz ; ++i )
      {
      Category pc = (Category) projects.elementAt(i);
      String projStr = pc.getProject();
      String projectName = pc.getName();
      cW.print  ( "<INPUT type=\"radio\" name=\"project\"" );
      cW.print  ( " value = \"" + projStr + "\">" );
      cW.println( "&nbsp;" + projectName + "<BR>" );
      cW.println( "</INPUT>" );
      if ( i > 10 && ( i == ( sz / 2 ) ) )
        cW.println( "</TD><TD>" );
      }
    cW.println( "</TR>" );

    cW.println( "</TABLE>" );

    cW.println( "</TR>" );

    cW.println( "<TR bgcolor=\"#F0F0FF\">" );
    cW.println( "<TH align=\"left\">Status of Bug:</TH>" );
    cW.println( "<TH align=\"left\">Priority of Bug:</TH>" );
    cW.println( "</TR>" );

    cW.println( "<TR>" );
    cW.println( "<TD align=\"left\" valign=\"top\">" );
    lpV = config.getStates();
    for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
      {
      LevelParam lp = (LevelParam) lpV.elementAt(i);

      cW.print  ( "<INPUT type=\"checkbox\" name=\"status\"" );
      cW.println( " value = \"" + lp.getId() + "\">" );
      cW.println( lp.getName() + "<BR>" );
      }
    cW.println( "</TD>" );

    cW.println( "<TD align=\"left\" valign=\"top\">" );
    lpV = config.getPriorities();
    for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
      {
      LevelParam lp = (LevelParam) lpV.elementAt(i);

      cW.print  ( "<INPUT type=\"checkbox\" name=\"priority\"" );
      cW.println( " value = \"" + lp.getId() + "\">" );
      cW.println( lp.getName() + "<BR>" );
      }
    cW.println( "</TD>" );

    cW.println( "</TR>" );

    cW.println( "<TR bgcolor=\"#F0F0FF\">" );

    cW.println( "<TH align=\"left\">Severity of Bug:</TH>" );
    cW.println( "<TH align=\"left\">Class of Bug:</TH>" );

    cW.println( "</TR>" );

    cW.println( "<TR>" );
    cW.println( "<TD align=\"left\" valign=\"top\">" );
    lpV = config.getSeverities();
    for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
      {
      LevelParam lp = (LevelParam) lpV.elementAt(i);

      cW.print  ( "<INPUT type=\"checkbox\" name=\"severity\"" );
      cW.println( " value = \"" + lp.getId() + "\">" );
      cW.println( lp.getName() + "<BR>" );
      }
    cW.println( "</TD>" );

    cW.println( "<TD align=\"left\" valign=\"top\">" );
    lpV = config.getClasses();
    for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
      {
      LevelParam lp = (LevelParam) lpV.elementAt(i);

      cW.print  ( "<INPUT type=\"checkbox\" name=\"class\"" );
      cW.println( " value = \"" + lp.getId() + "\">" );
      cW.println( lp.getName() + "<BR>" );
      }
    cW.println( "</TD>" );
    cW.println( "</TR>" );

    cW.println( "<TR bgcolor=\"#F0F0FF\">" );
    cW.println( "<TD width=\"100%\" align=\"center\" colspan=\"2\">" );

    cW.println( "<TABLE border=\"0\" cellpadding=\"0\" cellspacing=\"0\">" );
    cW.println( "<TR>" );
    cW.println( "<TD align=\"right\">" );
    cW.println( "<B>The&nbsp;opened&nbsp;date&nbsp;is:</B>&nbsp;" );
    cW.println( "</TD>" );
    cW.println( "<TD align=\"left\">" );
    cW.println( "<INPUT type=\"radio\" name=\"bydate\" value=\"olderThan\">" );
    cW.println( "&nbsp;Older&nbsp;Than&nbsp;" );
    cW.println( "<INPUT type=\"radio\" name=\"bydate\" value=\"newerThan\">" );
    cW.println( "Newer&nbsp;Than&nbsp;" );
    cW.print  ( "<INPUT type=\"textfield\" name=\"days\">" );
    cW.println( "&nbsp;Days&nbsp;Old&nbsp;" );
    cW.println( "</TD>" );
    cW.println( "</TR>" );
    cW.println( "</TABLE>" );

    cW.println( "</TD>" );
    cW.println( "</TR>" );

    cW.println( "<TR>" );
    cW.println( "<TD align=\"center\" colspan=\"2\">" );

    cW.print  ( "<INPUT type=\"submit\" name=\"submit\"" );
    cW.print  ( " value=\"Show Bugs\">&nbsp;&nbsp;&nbsp;" );

    cW.print  ( "<INPUT type=\"reset\" name=\"reset\"" );
    cW.println( " value=\"Clear\">" );

    cW.println( "</TD>" );
    cW.println( "</TR>" );

    cW.println( "</TABLE>" );

    cW.println( "</FORM>" );

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  processBrowseForBugs( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Browse Bugs" );

    String statusStr = null;
    String priorityStr = null;
    String severityStr = null;
    String classStr = null;
    String dateStr = null;
    String dateCompareType = null;
    String projectStr = null;

    String[] vals = bReq.getParameterValues( "project" );
    if ( vals != null )
      {
      projectStr = vals[0];
      if ( this.debug )
        this.log( "projectStr = " + projectStr );
      }

    vals = bReq.getParameterValues( "status" );
    if ( vals != null )
      {
      int num_checked = vals.length;
      for ( int i = 0 ; i < num_checked ; i++ )
        {
        if ( i == 0 )
          statusStr = vals[0];
        else
          statusStr = statusStr + vals[i];
        }
      if ( this.debug )
        this.log( "StatusStr = " + statusStr );
      }

    vals = bReq.getParameterValues( "priority" );
    if ( vals != null )
      {
      int num_checked = vals.length;
      for ( int i = 0 ; i < num_checked ; i++ )
        {
        if ( i == 0 )
          priorityStr = vals[0];
        else
          priorityStr = priorityStr + vals[i];
        }
      if ( this.debug )
        this.log( "PriorityStr = " + priorityStr );
      }

    vals = bReq.getParameterValues( "severity" );
    if ( vals != null )
      {
      int num_checked = vals.length;
      for ( int i = 0 ; i < num_checked ; i++ )
        {
        if ( i == 0 )
          severityStr = vals[0];
        else
          severityStr = severityStr + vals[i];
        }
      if ( this.debug )
        this.log( "SeverityStr = " + severityStr );
      }

    vals = bReq.getParameterValues( "class" );
    if ( vals != null )
      {
      int num_checked = vals.length;
      for ( int i = 0 ; i < num_checked ; i++ )
        {
        if ( i == 0 )
          classStr = vals[0];
        else
          classStr = classStr + vals[i];
        }
      if ( this.debug )
        this.log( "ClassStr = " + classStr );
      }

    vals = bReq.getParameterValues( "bydate" );
    if ( vals != null )
      {
      if (vals.length != 0)
        {
        dateCompareType =  vals[0];
        vals = bReq.getParameterValues( "days" );
        if ( vals != null )
          {
          dateStr = vals[0];
          if ( dateStr.length() == 0 )
            dateStr = null;
          if ( this.debug )
            this.log( "dateStr = " + dateStr );
          }
        }
      }

    try {
      String matchString = null;
      Vector projects = this.getDBConfig().getProjects();
      boolean hits = false;
      for ( int i = 0, sz = projects.size() ; i < sz ; ++i )
        {
        Category pc = (Category) projects.elementAt(i);
        String projStr = pc.getProject(); // ---- this is it
        String projectName = pc.getName();

        if ( projectStr == null || projectStr.equals( projStr ) )
          {
          matchString = "SELECT bug.id from bug WHERE ";
          if ( statusStr != null )
            {
            matchString = matchString + "LOCATE(bug.state,'" +
                statusStr + "') <> 0 ";
            matchString = matchString + " AND ";
            }
          if ( priorityStr != null )
            {
            matchString = matchString + "LOCATE(bug.priority,'" +
                priorityStr + "') <> 0 ";
            matchString = matchString + " AND ";
            }
          if ( severityStr != null )
            {
            matchString = matchString + "LOCATE(bug.severity,'" +
                severityStr + "') <> 0 ";
            matchString = matchString + " AND ";
            }
          if ( classStr != null )
            {
            matchString = matchString + "LOCATE(bug.class,'" +
                classStr + "') <> 0 ";
            matchString = matchString + " AND ";
            }
          if ( dateStr != null )
            {
            if ( dateCompareType.equals( "olderThan" ) )
              matchString = matchString +
                "bug.opened < (CURDATE() - " +
                dateStr + ") AND " ;
            else if ( dateCompareType.equals( "newerThan" ) )
              matchString = matchString +
                "bug.opened > (CURDATE() - " +
                dateStr + ") AND " ;
            }

          matchString = matchString + " project = '" + projStr + "'";

          Vector repV = Bug.matchBugs( matchString );

          String title = "Bugs Selected: Project " + projectName;

          if ( repV.size() != 0 )
            {
            this.getOutput().showBugs
              ( bReq, cW, title, repV, "ShowBug" );
            hits = true;
            }
          }
        }

      if ( ! hits )
        {
        cW.println( "<H2>No Matches</H2>" );
        cW.println( "There were no matches!<br>" );
        cW.println( "The match string was:<p><code>" );
        cW.println( matchString );
        cW.println( "</code>" );
        }
      }
    catch ( DBIException ex )
      {
      cW.println( "<h2>Error Browsing bugs</h2>" );
      cW.println( "An error occurred trying to get the" );
      cW.println( "bugs you requested." );
      cW.println( "The message was:<br>" );
      cW.println( ex.getMessage() );
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  browseReports( BugRatRequest bReq )
    throws IOException
    {
    Vector lpV = null;
    DBConfig config = this.getDBConfig();
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Browse Reports" );

    cW.println( "<H2>Browse Reports</h2>" );
    cW.println( "Browse reports in database by choosing from among the " );
    cW.println( "following choices. Choose as many as you wish." );
    cW.println( "<BR><BR>" );
    cW.print  ( "<FORM method=\"POST\" action=\"" );
    cW.print  ( bReq.getServletPath() );
    cW.println( "/BrowseForReports\">" );

    cW.println( "<TABLE width=\"100%\" border=\"1\" cellpadding=\"3\">" );

    cW.println( "<TR bgcolor=\"#F0F0FF\">" );
    cW.println( "<TH align=\"left\" colspan=\"2\">" );
    cW.println( "Project:" );
    cW.println( "</TH>" );
    cW.println( "</TR>" );

    cW.println( "<TR>" );
    cW.println( "<TD width=\"100%\" align=\"top\" colspan=\"2\">" );

    cW.println( "<TABLE width=\"100%\" border=\"0\">" );

    cW.println( "<TR>" );
    cW.println( "<TD align=\"left\" valign=\"top\">" );
    Vector projects = config.getProjects();
    for ( int i = 0, sz = projects.size() ; i < sz ; ++i )
      {       
      Category pc = (Category) projects.elementAt(i);
      String projStr = pc.getProject();
      String projectName = pc.getName();
      cW.print  ( "<INPUT type=\"radio\" name=\"project\"" );
      cW.println( " value = \"" + projStr + "\">" );
      cW.println( "&nbsp;" + projectName + "<BR>" );
      cW.println( "</INPUT>" );
      if ( i>10 && ( i == ( sz / 2 ) ) )
        cW.println( "</TD><TD>" );
      }
    cW.println( "</TD>" );
    cW.println( "</TR>" );

    cW.println( "</TABLE>" );

    cW.println( "</TR>" );

    cW.println( "<TR bgcolor=\"#F0F0FF\">" );
    cW.println( "<TH align=\"left\">Status of Report:</TH>" );
    cW.println( "<TH align=\"left\">Priority Of Report:</TH>" );
    cW.println( "</TR>" );

    cW.println( "<TR>" );
    cW.println( "<TD align=\"left\" valign=\"top\">");
    lpV = config.getStates();
    for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
      {
      LevelParam lp = (LevelParam) lpV.elementAt(i);
      cW.print  ( "<INPUT type=\"checkbox\" name=\"status\"" );
      cW.println( " value = \"" + lp.getId() + "\">" );
      cW.println( lp.getName() + "<BR>" );
      cW.println( "</INPUT>" );
      }
    cW.println( "</TD>" );
    cW.println( "<TD align=\"left\" valign=\"top\">");
    lpV = config.getPriorities();
    for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
      {
      LevelParam lp = (LevelParam) lpV.elementAt(i);
      cW.print  ( "<INPUT type=\"checkbox\" name=\"priority\"" );
      cW.println( " value = \"" + lp.getId() + "\">" );
      cW.println( lp.getName() + "<BR>" );
      cW.println( "</INPUT>" );
      }
    cW.println( "</TD>" );
    cW.println( "</TR>" );

    cW.println( "<TR bgcolor=\"#F0F0FF\">" );
    cW.println( "<TH align=\"left\">Severity of Report:</TH>" );
    cW.println( "<TH align=\"left\">Class of Report:</TH>" );
    cW.println( "</TR>" );

    cW.println( "<TR>" );
    cW.println( "<TD align=\"left\" valign=\"top\">");
    lpV = config.getSeverities();
    for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
      {
      LevelParam lp = (LevelParam) lpV.elementAt(i);
      cW.print  ( "<INPUT type=\"checkbox\" name=\"severity\"" );
      cW.println( " value = \"" + lp.getId() + "\">" );
      cW.println( lp.getName() + "<BR>" );
      cW.println( "</INPUT>" );
      }
    cW.println( "</TD>" );
    cW.println( "<TD align=\"left\" valign=\"top\">");
    lpV = config.getClasses();
    for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
      {
      LevelParam lp = (LevelParam) lpV.elementAt(i);
      cW.print  ( "<INPUT type=\"checkbox\" name=\"class\"" );
      cW.println( " value = \"" + lp.getId() + "\">" );
      cW.println( lp.getName() + "<BR>" );
      cW.println( "</INPUT>" );
      }
    cW.println( "</TD>" );
    cW.println( "</TR>" );

    cW.println( "<TR bgcolor=\"#F0F0FF\">" );
    cW.println( "<TD width=\"100%\" align=\"center\" colspan=\"2\">" );

    cW.println( "<B>Submit&nbsp;Date&nbsp;is:</B>&nbsp; " );  
    cW.print  ( "<INPUT type=\"radio\" name=\"bydate\" value=\"olderThan\">" );
    cW.println( "Older&nbsp;Than&nbsp;" );
    cW.print  ( "<INPUT type=\"radio\" name=\"bydate\" value=\"newerThan\">" );
    cW.println( "&nbsp;Newer&nbsp;Than " );
    cW.print  ( "<INPUT type=\"textfield\" name=\"days\">" );
    cW.println( "&nbsp;Days&nbsp;Old" );

    cW.println( "</TD>" );
    cW.println( "</TR>" );

    cW.println( "<TR>" );
    cW.println( "<TD align=\"center\" colspan=\"2\">" );

    cW.print  ( "<INPUT type=\"submit\" name=\"submit\"" );
    cW.print  ( " value=\"Show Reports\">&nbsp;&nbsp;&nbsp;" );

    cW.print  ( "<INPUT type=\"reset\" name=\"reset\"" );
    cW.println( " value=\"Clear\">" );

    cW.println( "</TD>" );
    cW.println( "</TR>" );

    cW.println( "</TABLE>" );

    cW.println( "</FORM>" );

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  processBrowseForReports( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Browse Reports" );

    String statusStr = null;
    String priorityStr = null;
    String severityStr = null;
    String classStr = null;
    String dateStr = null;
    String dateCompareType = null;
    String projectStr = null;

    String[] vals = bReq.getParameterValues( "project" );
    if ( vals != null )
      {
      projectStr = vals[0];
      if ( this.debug )
        this.log( "projectStr = " + projectStr );
      }

    vals = bReq.getParameterValues( "status" );
    if ( vals != null )
      {
      int num_checked = vals.length;
      for ( int i = 0 ; i < num_checked ; i++ )
        {
        if ( i == 0 )
          statusStr = vals[0];
        else
          statusStr = statusStr + vals[i];
        }
      if ( this.debug )
        this.log( "StatusStr = " + statusStr );
      }

    vals = bReq.getParameterValues( "priority" );
    if ( vals != null )
      {
      int num_checked = vals.length;
      for ( int i = 0 ; i < num_checked ; i++ )
        {
        if ( i == 0 )
          priorityStr = vals[0];
        else
          priorityStr = priorityStr + vals[i];
        }
      if ( this.debug )
        this.log( "PriorityStr = " + priorityStr );
      }

    vals = bReq.getParameterValues( "severity" );
    if ( vals != null )
      {
      int num_checked = vals.length;
      for ( int i = 0 ; i < num_checked ; i++ )
        {
        if ( i == 0 )
          severityStr = vals[0];
        else
          severityStr = severityStr + vals[i];
        }
      if ( this.debug )
        this.log( "SeverityStr = " + severityStr );
      }

    vals = bReq.getParameterValues( "class" );
    if ( vals != null )
      {
      int num_checked = vals.length;
      for ( int i = 0 ; i < num_checked ; i++ )
        {
        if ( i == 0 )
          classStr = vals[0];
        else
          classStr = classStr + vals[i];
        }
      if ( this.debug )
        this.log( "ClassStr = " + classStr );
      }

    vals = bReq.getParameterValues( "bydate" );
    if ( vals != null )
      {
      if (vals.length != 0)
        {
        dateCompareType =  vals[0];
        if ( this.debug )
          this.log( "dateCompareType = " + dateCompareType );
        vals = bReq.getParameterValues( "days" );
        if ( vals != null )
          {
          dateStr = vals[0];
          if ( dateStr.length() == 0 )
            dateStr = null;
          if ( this.debug )
            this.log( "dateStr = " + dateStr );
          }
        }
      }

    StringBuffer mBuf = new StringBuffer( 1024 );

    try {
      boolean hits = false;
      Vector projects = this.getDBConfig().getProjects();

      for ( int i = 0, sz = projects.size() ; i < sz ; ++i )
        {
        Category pc = (Category) projects.elementAt(i);
        String projStr = pc.getProject(); // ---- this is it
        String projectName = pc.getName();

        if ( projectStr == null || projectStr.equals( projStr ) )
          {
          mBuf.append( "SELECT report.id from report WHERE " );

          if ( statusStr != null )
            {
            mBuf.append( "LOCATE(report.state,'" );
            mBuf.append( statusStr );
            mBuf.append( "') <> 0 AND " );
            }

          if ( priorityStr != null )
            {
            mBuf.append( "LOCATE(report.priority,'" );
            mBuf.append( priorityStr );
            mBuf.append( "') <> 0 AND " );
            }

          if ( severityStr != null )
            {
            mBuf.append( "LOCATE(report.severity,'" );
            mBuf.append( severityStr );
            mBuf.append( "') <> 0 AND " );
            }

          if ( classStr != null )
            {
            mBuf.append( "LOCATE(report.class,'" );
            mBuf.append( classStr );
            mBuf.append( "') <> 0 AND " );
            }

          if ( dateStr != null )
            {
            if ( dateCompareType.equals( "olderThan" ) )
              {
              mBuf.append( "report.submitted < (CURDATE() - " );
              mBuf.append( dateStr );
              mBuf.append( ") AND " );
              }
            else if ( dateCompareType.equals( "newerThan" ) )
              {
              mBuf.append( "report.submitted > (CURDATE() - " );
              mBuf.append( dateStr );
              mBuf.append( ") AND " );
              }
            }

          mBuf.append( " project = '" );
          mBuf.append( projStr );
          mBuf.append( "'" );

          Vector repV = Report.matchReports( mBuf.toString() );

          String title =
            "Reports Selected: Project " + projectName;

          if ( repV.size() != 0 )
            {
            this.getOutput().showReports
              ( bReq, cW, title, repV, "ShowReport" );
            hits = true;
            }
          }
        }

      if ( ! hits )
        {
        cW.println( "<H2>No Matches</H2>" );
        cW.println( "There were no matches!<br>" );
        cW.println( "<hr>" );
        cW.println( "The match SQL was:<p><code>" );
        cW.println( mBuf.toString() );
        cW.println( "</code></p>" );
        }
      }
    catch ( DBIException ex )
      {
      cW.println( "<h2>Error Browsing reports</h2>" );
      cW.println( "An error occurred trying to get the" );
      cW.println( "reports you requested." );
      cW.println( "The message was:<br>" );
      cW.println( ex.getMessage() );
      cW.println( "<hr>" );
      cW.println( "The match SQL was:<p><code>" );
      cW.println( mBuf.toString() );
      cW.println( "</code></p>" );
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  searchBugs( BugRatRequest bReq )
    throws IOException
    {
    Vector lpV = null;
    DBConfig config = this.getDBConfig();
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Search Bugs" );

    cW.println( "<H2>Search Bugs</h2>" );

    cW.println( "Enter text and select which of the text fields you " );
    cW.println( "would like to search." );
    cW.println( "<P>" );

    cW.print  ( "<FORM method=\"POST\" action=\"" );
    cW.print  ( bReq.getServletPath() );
    cW.println( "/SearchForBugs\">" );
    cW.println( "Search Text:" );
    cW.println( "<INPUT name=\"searchtext\">" );

    cW.println( "<P>" );
    cW.println( "<INPUT type=\"checkbox\" name=\"fieldstosearch\" value=\"S\">" );
    cW.println( "Synopsis" );
    cW.println( "<BR>" );
    cW.println( "<INPUT type=\"checkbox\" name=\"fieldstosearch\" value=\"D\">" );
    cW.println( "Description" );
    cW.println( "<BR>" );
    cW.println( "<INPUT type=\"checkbox\" name=\"fieldstosearch\" value=\"E\">" );
    cW.println( "Environment Description" );
    cW.println( "<BR>" );
    cW.println( "<INPUT type=\"checkbox\" name=\"fieldstosearch\" value=\"R\">" );
    cW.println( "How To Reproduce" );
    cW.println( "<BR>" );
    cW.println( "<INPUT type=\"checkbox\" name=\"fieldstosearch\" value=\"W\">" );
    cW.println( "Known Workarounds" );

    cW.println( "<P>" );
    cW.println( "<INPUT type=\"submit\" name=\"submit\"" );
    cW.println( " value=\"Show Bugs\">" );

    cW.println( "</FORM>" );

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  /**
   * Please see the NOTE for method processSearchForReports() below.
   *
   * This method's SQL was optimized by Nicolaus Bauman.
   */

  protected void
  processSearchForBugs( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Search Bugs" );

    String fieldsChosen = null;
    String searchText = null;

    StringBuffer mBuf = new StringBuffer( 1024 );

    String[] vals = bReq.getParameterValues( "searchtext" );
    if ( vals != null )
      {
      searchText = vals[0];
      if ( this.debug )
        this.log( "Looking for " + searchText );
      }

    vals = bReq.getParameterValues( "fieldstosearch" );
    if ( vals == null )
      {
      vals = new String[5];
      vals[0] = new String ("S");
      vals[1] = new String ("D");
      vals[2] = new String ("E");
      vals[3] = new String ("R");
      vals[4] = new String ("W");
      }
 
    try {
      boolean hits = false;
      String matchString = null;
      Vector projects = this.getDBConfig().getProjects();

      for ( int i = 0, sz = projects.size() ; i < sz ; ++i )
        {
        Category pc = (Category) projects.elementAt(i);
        String projStr = pc.getProject();
        String projectName = pc.getName();

        mBuf.setLength( 0 );

        mBuf.append( "SELECT DISTINCT bug.id " );
        mBuf.append( "FROM bug " );

        for( int vi = 0, vsz = vals.length ; vi < vsz ; vi++ )
          {
          if ( vals[vi].equals( "S" ) )
            mBuf.append( ", description d1 " );
          else if ( vals[vi].equals( "D" ) )
            mBuf.append( ", description d2 " );
          else if ( vals[vi].equals( "E" ) )
            mBuf.append( ", envdesc " );
          else if ( vals[vi].equals( "R" ) )
            mBuf.append( ", description d4 " );
          else if ( vals[vi].equals( "W" ) )
            mBuf.append( ", description d5 " );
          }

        mBuf.append( "WHERE ( " );

        for ( int vi = 0, vsz = vals.length ; vi < vsz ; vi++ )
          {
          if ( vals[vi].equals( "S" ) )
            {
            mBuf.append( "d1.synopsis LIKE \"%" );
            mBuf.append( searchText );
            mBuf.append( "%\" OR " );
            }
          else if ( vals[vi].equals( "D" ) )
            {
            mBuf.append( "d2.desctext LIKE \"%" );
            mBuf.append( searchText );
            mBuf.append( "%\" OR " );
            }
          else if ( vals[vi].equals( "E" ) )
            {
            mBuf.append( "envdesc.envdesc LIKE \"%" );
            mBuf.append( searchText );
            mBuf.append( "%\" OR " );
            }
          else if ( vals[vi].equals( "R" ) )
            {
            mBuf.append( "d3.synopsis LIKE \"%" );
            mBuf.append( searchText );
            mBuf.append( "%\" OR " );
            }
          else if ( vals[vi].equals( "W" ) )
            {
            mBuf.append( "d4.synopsis LIKE \"%" );
            mBuf.append( searchText );
            mBuf.append( "%\" OR " );
            }
          }

        mBuf.append( " bug.id <> bug.id )" );

        for( int vi = 0, vsz = vals.length ; vi < vsz ; vi++ )
          {
          if ( vals[vi].equals( "S" ) )
            mBuf.append( " AND bug.bugdesc = d1.id" );
          else if ( vals[vi].equals( "D" ) )
            mBuf.append( " AND bug.bugdesc = d2.id" );
          else if ( vals[vi].equals( "E" ) )
            mBuf.append( " AND bug.envdesc = envdesc.id" );
          else if ( vals[vi].equals( "R" ) )
            mBuf.append( " AND bug.repro = d3.id" );
          else if ( vals[vi].equals( "W" ) )
            mBuf.append( " AND bug.around = d4.id" );
          }

        mBuf.append( " AND project = '" );
        mBuf.append( projStr );
        mBuf.append( "'" );

        if ( this.debug )
          {
          this.log( "SQL for processSearchForBugs()" );
          this.log( mBuf.toString() );
          }

        Vector bugV = Bug.matchBugs( mBuf.toString() );

        String title = "Bugs Found: Project " + projectName;

        if ( bugV.size() != 0 )
          {
          this.getOutput().showBugs
            ( bReq, cW, title, bugV, "ShowBug" );
          hits = true;
          }
        }

      if ( ! hits )
        {
        cW.println( "<H2>No Matches</H2>" );
        cW.println( "There were no matches!<br>" );
        cW.println( "<hr>" );
        cW.println( "The match SQL was:<p><code>" );
        cW.println( mBuf.toString() );
        cW.println( "</code></p>" );
        }
      }
    catch ( DBIException ex )
      {
      cW.println( "<h2>Error Browsing bugs</h2>" );
      cW.println( "An error occurred trying to get the" );
      cW.println( "bugs you requested." );
      cW.println( "The message was:<br><code>" );
      cW.println( ex.getMessage() );
      cW.println( "</code><hr>" );
      cW.println( "The match SQL was:<p><code>" );
      cW.println( mBuf.toString() );
      cW.println( "</code></p>" );
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  searchReports( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Search Reports" );

    cW.println( "<H2>Search Reports</h2>" );

    cW.println( "Enter text and select which of the text fields you " );
    cW.println( "would like to search." );

    cW.println( "<P>" );
    cW.print  ( "<FORM method=\"POST\" action=\"" );
    cW.print  ( bReq.getServletPath() );
    cW.println( "/SearchForReports\">" );
    cW.println( "Search Text:" );
    cW.println( "<INPUT name=\"searchtext\">" );

    cW.println( "<P>" );
    cW.println( "<INPUT type=\"checkbox\" name=\"fieldstosearch\" value=\"S\">" );
    cW.println( "Synopsis" );
    cW.println( "<BR>" );
    cW.println( "<INPUT type=\"checkbox\" name=\"fieldstosearch\" value=\"D\">" );
    cW.println( "Description" );
    cW.println( "<BR>" );
    cW.println( "<INPUT type=\"checkbox\" name=\"fieldstosearch\" value=\"E\">" );
    cW.println( "Environment" );
    cW.println( "<BR>" );
    cW.println( "<INPUT type=\"checkbox\" name=\"fieldstosearch\" value=\"R\">" );
    cW.println( "How To Reproduce" );
    cW.println( "<BR>" );
    cW.println( "<INPUT type=\"checkbox\" name=\"fieldstosearch\" value=\"W\">" );
    cW.println( "Known Workarounds" );
    cW.println( "<BR>" );

    cW.println( "<P>" );
    cW.println( "<INPUT type=\"submit\" name=\"submit\"" );
    cW.println( " value=\"Show Reports\">" );

    cW.println( "</FORM>" );

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  /**
   * NOTE
   * We used to use a select statement that looked like this: <pre>

    SELECT DISTINCT report.id
    FROM
      report, description, envdesc
    WHERE ( description.synopsis LIKE '%bugarbugar%'
          AND report.repdesc = description.id
        OR description.desctext LIKE '%bugarbugar%'
          AND report.repdesc = description.id
        OR envdesc.envdesc LIKE '%bugarbugar%'
          AND report.envdesc = envdesc.id
        OR description.synopsis LIKE '%bugarbugar%'
          AND report.repro = description.id
        OR description.synopsis LIKE '%bugarbugar%'
          AND report.around = description.id
        OR report.id <> report.id
        )
      AND project = 'schmearmeer';

    </pre>
   * However, that was an extremely slow search. Fortunately,
   * Nicolaus Bauman, who is running BugRat for Apache, provided
   * us with the following SQL: <pre>

    SELECT DISTINCT report.id
    FROM
      envdesc,
      description d1,
      description d2,
      description d3,
      description d4,
      report
    WHERE ( d1.synopsis like '%bugarbugar%'
        OR d2.desctext like '%bugarbugar%'
        OR envdesc.envdesc like '%bugarbugar%'
        OR d3.synopsis like '%bugarbugar%'
        OR d4.synopsis like '%bugarbugar%'
        OR report.id <> report.id
        )
      AND report.repdesc = d1.id
      AND report.repdesc = d2.id
      AND report.envdesc = envdesc.id
      AND report.repro = d3.id
      AND report.around = d4.id
      AND project = 'schmearmeer'

    </pre>
   * which runs 150 times faster than the previous SQL!!!
   *
   * Thank you Nick!
   */

  protected void
  processSearchForReports( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Search Reports" );

    String fieldsChosen = null;
    String searchText = null;

    StringBuffer mBuf = new StringBuffer( 1024 );

    String[] vals = bReq.getParameterValues( "searchtext" );
    if ( vals != null )
      {
      searchText = vals[0];
      if ( this.debug )
        this.log( "Looking for " + searchText );
      }

    vals = bReq.getParameterValues( "fieldstosearch" );
    if ( vals == null )
      {
      vals = new String[5];
      vals[0] = new String ("S");
      vals[1] = new String ("D");
      vals[2] = new String ("E");
      vals[3] = new String ("R");
      vals[4] = new String ("W");
      }
 
    try {
      boolean hits = false;
      Vector projects = this.getDBConfig().getProjects();

      for ( int i = 0, sz = projects.size() ; i < sz ; ++i )
        {
        Category pc = (Category) projects.elementAt(i);
        String projStr = pc.getProject(); // ---- this is it
        String projectName = pc.getName();

        mBuf.setLength( 0 );

        mBuf.append( "SELECT DISTINCT report.id " );
        mBuf.append( "FROM report " );

        for( int vi = 0, vsz = vals.length ; vi < vsz ; vi++ )
          {
          if ( vals[vi].equals( "S" ) )
            mBuf.append( ", description d1 " );
          else if ( vals[vi].equals( "D" ) )
            mBuf.append( ", description d2 " );
          else if ( vals[vi].equals( "E" ) )
            mBuf.append( ", envdesc " );
          else if ( vals[vi].equals( "R" ) )
            mBuf.append( ", description d4 " );
          else if ( vals[vi].equals( "W" ) )
            mBuf.append( ", description d5 " );
          }

        mBuf.append( "WHERE ( " );

        for ( int vi = 0, vsz = vals.length ; vi < vsz ; vi++ )
          {
          if ( vals[vi].equals( "S" ) )
            {
            mBuf.append( "d1.synopsis LIKE \"%" );
            mBuf.append( searchText );
            mBuf.append( "%\" OR " );
            }
          else if ( vals[vi].equals( "D" ) )
            {
            mBuf.append( "d2.desctext LIKE \"%" );
            mBuf.append( searchText );
            mBuf.append( "%\" OR " );
            }
          else if ( vals[vi].equals( "E" ) )
            {
            mBuf.append( "envdesc.envdesc LIKE \"%" );
            mBuf.append( searchText );
            mBuf.append( "%\" OR " );
            }
          else if ( vals[vi].equals( "R" ) )
            {
            mBuf.append( "d3.synopsis LIKE \"%" );
            mBuf.append( searchText );
            mBuf.append( "%\" OR " );
            }
          else if ( vals[vi].equals( "W" ) )
            {
            mBuf.append( "d4.synopsis LIKE \"%" );
            mBuf.append( searchText );
            mBuf.append( "%\" OR " );
            }
          }

        mBuf.append( " report.id <> report.id )" );

        for( int vi = 0, vsz = vals.length ; vi < vsz ; vi++ )
          {
          if ( vals[vi].equals( "S" ) )
            mBuf.append( " AND report.repdesc = d1.id" );
          else if ( vals[vi].equals( "D" ) )
            mBuf.append( " AND report.repdesc = d2.id" );
          else if ( vals[vi].equals( "E" ) )
            mBuf.append( " AND report.envdesc = envdesc.id" );
          else if ( vals[vi].equals( "R" ) )
            mBuf.append( " AND report.repro = d3.id" );
          else if ( vals[vi].equals( "W" ) )
            mBuf.append( " AND report.around = d4.id" );
          }

        mBuf.append( " AND project = '" );
        mBuf.append( projStr );
        mBuf.append( "'" );

        if ( this.debug )
          {
          this.log( "SQL for processSearchForReports()" );
          this.log( mBuf.toString() );
          }

        Vector repV = Report.matchReports( mBuf.toString() );

        String title = "Reports Found: Project " + projectName;

        if ( repV.size() != 0 )
          {
          this.getOutput().showReports
            ( bReq, cW, title, repV, "ShowReport" );
          hits = true;
          }
        }

      if ( ! hits )
        {
        cW.println( "<H2>No Matches</H2>" );
        cW.println( "There were no matches!<br>" );
        cW.println( "<hr>" );
        cW.println( "The match SQL was:<p><code>" );
        cW.println( mBuf.toString() );
        cW.println( "</code></p>" );
        }
      }
    catch ( DBIException ex )
      {
      cW.println( "<h2>Error Searching Reports</h2>" );
      cW.println( "An error occurred trying to get the" );
      cW.println( "reports you requested." );
      cW.println( "The message was:<br><code>" );
      cW.println( ex.getMessage() );
      cW.println( "</code><hr>" );
      cW.println( "The match SQL was:<p><code>" );
      cW.println( mBuf.toString() );
      cW.println( "</code></p>" );
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  processShowReports( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Show Reports" );

    DBConfig config = this.getDBConfig();
    String scope = bReq.getParameterValues( "scope" )[0];

    String optionChosen = null;

    if ( scope.equals( "project" ) )
      {
      String[] vals = bReq.getParameterValues( "project" );
      if ( vals == null || vals.length == 0 )
        {
        this.reportError
          ( bReq, cW,
            "You must select a project from the list." );
        }
      else
        {
        String project = vals[0];

        try {
          String niceProject =
            config.getProjectName( project );

          Vector repV =
            Report.matchReports
              ( "SELECT report.id from report "
                + "WHERE project = '" + project + "'" );

          // FORM to narrow to categories
          if ( repV.size() > 0 )
            {
            cW.print  ( "<FORM method=\"POST\" action=\"" );
            cW.print  ( bReq.getServletPath() );
            cW.println( "/ShowReports\">" );
            cW.print  ( "<INPUT type=\"hidden\"" );
            cW.println( "       name=\"scope\" value=\"category\">" );
            cW.print  ( "<INPUT type=\"hidden\"" );
            cW.println( "       name=\"project\" value=\"" +
                  project + "\">");

            cW.println( "<SELECT name=\"category\" size=\"1\">" );

            Vector categories = config.getProjectCategories( project );
            for ( int i = 0, sz = categories.size() ; i < sz ; ++i )
              {
              Category cat = (Category) categories.elementAt(i);
              String catStr = cat.getCategory();
              String catName = cat.getName();
              cW.print  ( "<OPTION value=\"" + catStr + "\">" );
              cW.println( catName );
              cW.println( "</OPTION>" );
              }

            cW.print  ( "</SELECT>&nbsp;" );

            cW.print  ( "<INPUT type=\"submit\" name=\"submit\"" );
            cW.println( " value=\"Narrow Reports To Category\">" );

            cW.println( "</FORM>" );
            }

          if ( repV.size() == 0 )
            {
            optionChosen = niceProject;
            }
          else
            {
            String title = "Reports for " + niceProject;
            this.getOutput().showReports
              ( bReq, cW, title, repV, "ShowReport" );
            }
          }
        catch ( DBIException ex )
          {
          cW.println( "<h2>Error Getting Reports</h2>" );
          cW.println( "An error occurred trying to get the" );
          cW.println( "reports for project '" + project + "'." );
          cW.println( "The message was:<br>" );
          cW.println( ex.getMessage() );
          }
        }
      }
    else if ( scope.equals( "category" ) )
      {
      String[] vals = bReq.getParameterValues( "category" );
      if ( this.isEmptyParameter( vals ) )
        {
        cW.println( "<H2>No Category Specified</H2>" );
        cW.println( "No category was chosen, please go back and " );
        cW.println( " choose a category. " );
        }
      else
        {
        String category = vals[0];
        String project = null;

        vals = bReq.getParameterValues( "project" );
        if ( this.isEmptyParameter( vals ) )
          {
          this.reportError
            ( bReq, cW,
              "Error, category project is empty." );
          }
        else
          {
          project = vals[0];
          }

        if ( project != null )
        try {
          String niceProject =
            config.getProjectName( project );
          String niceCategory =
            config.getCategoryName( project, category );

          Vector repV =
            Report.matchReports
              ( "SELECT report.id from report "
                + "WHERE project = '" + project + "'"
                + "AND category = '" + category + "'" );

          // FORM to narrow to subcategories
          if ( repV.size() > 0 )
            {
            cW.print  ( "<FORM method=\"POST\" action=\"" );
            cW.print  ( bReq.getServletPath() );
            cW.println( "/ShowReports\">" );
            cW.print  ( "<INPUT type=\"hidden\"" );
            cW.println( "       name=\"scope\" value=\"subcat\">" );
            cW.print  ( "<INPUT type=\"hidden\"" );
            cW.println( "       name=\"project\" value=\"" +
                project + "\">");
            cW.print  ( "<INPUT type=\"hidden\"" );
            cW.println( "       name=\"category\" value=\"" +
                category + "\">");

            cW.println( "<SELECT name=\"subcat\" size=\"1\">" );

            Vector subcat =
              config.getCategorySubCats( project, category );

            for ( int i = 0, sz = subcat.size() ; i < sz ; ++i )
              {
              Category sub = (Category) subcat.elementAt(i);
              String subStr = sub.getSubCategory();
              String subName = sub.getName();
              cW.print  ( "<OPTION value=\"" + subStr + "\">" );
              cW.println( subName );
              cW.println( "</OPTION>" );
              }

            cW.print  ( "</SELECT>&nbsp;" );

            cW.print  ( "<INPUT type=\"submit\" name=\"submit\"" );
            cW.println( " value=\"Narrow Reports To Subcategory\">" );

            cW.println( "</FORM>" );
            }

          if ( repV.size() == 0 )
            {
            optionChosen = config.getProjectName( project)
              + " / " +
              config.getCategoryName( project,
              category );
            }
          else
            {
            String title =
              "Reports For "
              + niceProject
              + " / "
              + niceCategory;

            this.getOutput().showReports
              ( bReq, cW, title, repV, "ShowReport" );
            }
          }
        catch ( DBIException ex )
          {
          cW.println( "<h2>Error Getting Reports</h2>" );
          cW.println( "An error occurred trying to get the" );
          cW.println( "reports for project '" + project + "'" );
          cW.println( " and category '" + category + "'." );
          cW.println( "The message was:<br>" );
          cW.println( ex.getMessage() );
          }
        }
      }
    else if ( scope.equals( "subcat" ) )
      {
      String[] vals = bReq.getParameterValues( "subcat" );
      if ( this.isEmptyParameter( vals ) )
        {
        cW.println( "<H2>Subcategory Not Selected</H2>" );
        cW.println( "No subcategory was chosen, please go back and " );
        cW.println( " choose a subcategory. " );
        }
      else
        {
        String subcat = vals[0];
        String category = null;
        String project = null;

        vals = bReq.getParameterValues( "project" );
        if ( this.isEmptyParameter( vals ) )
          {
          this.reportError
            ( bReq, cW,
              "Error, subcategory project is empty." );
          }
        else
          {
          project = vals[0];
          vals = bReq.getParameterValues( "category" );
          if ( this.isEmptyParameter( vals ) )
            {
            this.reportError
              ( bReq, cW,
                "Error, subcategory category is empty." );
            }
          else
            {
            category = vals[0];
            }
          }

        if ( project != null && category != null )
        try {
          String niceProject =
            config.getProjectName( project );
          String niceCategory =
            config.getCategoryName( project, category );
          String niceSubcategory =
            config.getSubCategoryName( project, category, subcat );

          Vector repV =
            Report.matchReports
              ( "SELECT report.id from report "
                + "WHERE project = '" + project + "'"
                + "AND category = '" + category + "'"
                + "AND subcat = '" + subcat + "'" );

          if ( repV.size() == 0 )
            {
            optionChosen =
              niceProject
              + " / "
              + niceCategory
              + " / "
              + niceSubcategory;
            }
          else
            {
            String title =
              "Bug Reports for "
              + niceProject
              + " / "
              + niceCategory
              + " / "
              + niceSubcategory;

            this.getOutput().showReports
              ( bReq, cW, title, repV, "ShowReport" );
            }
          }
        catch ( DBIException ex )
          {
          cW.println( "<h2>Error Retrieving Bug Reports</h2>" );
          cW.println( "An error occurred trying to retrieve the" );
          cW.println( " bug reports for project '" + project + "'" );
          cW.println( " and category '" + category + "'" );
          cW.println( " and subcategory '" + subcat + "'." );
          cW.println( " The message was:<br>" );
          cW.println( "&nbsp;&nbsp;&nbsp;" + ex.getMessage() );
          }
        }
      }
    else if ( scope.equals( "ID" ) )
      {
      String[] vals = bReq.getParameterValues( "reportId" );
      if ( this.isEmptyParameter( vals ) )
        {
        cW.println( "<H2>No Bug Report</H2>" );
        cW.println( "No bug report ID was specified, please " );
        cW.println( "go back and choose a subcategory. " );
        }
      else
        {
        String idStr = vals[0];
        try {
          int id = Integer.parseInt( idStr );
          this.getOutput().showReport( bReq, cW, id );
          }
        catch ( NumberFormatException ex )
          {
          this.reportError( bReq, cW,
            "bad report id '" + idStr + "'" );
          }
        }
      }
    else
      {
      cW.println( "<H2>Internal Error: Invalid Scope</H2>" );
      cW.println( "The scope, '" + scope + "', is not valid." );
      }

    if ( optionChosen != null )
      {
      cW.println( "<H2>No Matches</H2>" );
      cW.println( "There were no reports found for '" );
      cW.println( optionChosen );
      cW.println( "' in the scope '" );
      cW.println( scope.trim() );
      cW.println( "'." );
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  processShowBugs( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Show Bugs" );

    DBConfig config = this.getDBConfig();
    String optionChosen = null;
    String scope = bReq.getParameterValues( "scope" )[0];

    if ( scope.equals( "project" ) )
      {
      String[] vals = bReq.getParameterValues( "project" );
      if ( vals == null )
        {
        this.reportError
          ( bReq, cW,
            "You must select a project from the list" );
        }
      else
        {
        String project = vals[0];

        try {
          // Add menu at top to narrow down categories
          cW.print  ( "<FORM method=\"POST\" action=\"" );
          cW.print  ( bReq.getServletPath() );
          cW.println( "/ShowBugs\">" );
          cW.println
            ( "<H3>Bugs in Project '" +
              config.getProjectName( project ) +
               "':</H3>" );
          cW.print  ( "<INPUT type=\"hidden\"" );
          cW.println( "       name=\"scope\" value=\"category\">" );
          cW.print  ( "<INPUT type=\"hidden\"" );
          cW.println( "       name=\"project\" value=\"" +
              project + "\">");
          cW.println( "<SELECT name=\"category\" size=\"1\">" );

          Vector categories = config.getProjectCategories( project );
          for ( int i = 0, sz = categories.size() ; i < sz ; ++i )
            {
            Category cat = (Category) categories.elementAt(i);
            String catStr = cat.getCategory();
            String catName = cat.getName();
            cW.print  ( "<OPTION value=\"" + catStr + "\">" );
            cW.println( catName );
            cW.print  ( "</OPTION>" );
            }

          cW.println( "</SELECT>&nbsp;" );
          cW.println( "<INPUT type=\"submit\" name=\"submit\"" );
          cW.println( " value=\"Narrow Reports To Categories\">" );

          Vector bugV =
            Bug.matchBugs
              ( "SELECT bug.id from bug "
                + "WHERE project = '" + project + "'" );

          String title =
            "Bugs For Project '" + project + "'";

          if ( bugV.size() == 0 )
            {
            optionChosen = config.getProjectName( project );
            }
          else
            {
            this.getOutput().showBugs
              ( bReq, cW, title, bugV, "ShowBug" );
            }
          }
        catch ( DBIException ex )
          {
          cW.println( "<h2>Error Getting Bugs</h2>" );
          cW.println( "An error occurred trying to get the" );
          cW.println( "bugs for project '" + project + "'." );
          cW.println( "The message was:<br>" );
          cW.println( ex.getMessage() );
          }
        }
      }
    else if ( scope.equals( "category" ) )
      {
      String[] vals = bReq.getParameterValues( "category" );
      if ( this.isEmptyParameter( vals ) )
        {
        cW.println( "<H2>No Category</H2>" );
        cW.println( "No category was chosen. ");
        cW.println( "Please go back and choose a category." );
        }
      else
        {
        String project = null;
        String category = vals[0];
        vals = bReq.getParameterValues( "project" );
        if ( this.isEmptyParameter( vals ) )
          {
          this.reportError
            ( bReq, cW,
              "Error narrowing category, "
              + "project is not specified." );
          }
        else
        try {
          project = vals[0];
          // Add menu at top to narrow down to subcategories
          cW.print  ( "<FORM method=\"POST\" action=\"" );
          cW.print  ( bReq.getServletPath() );
          cW.println( "/ShowBugs\">" );
          cW.println( "<H3>Bug in Project '" + project +
              "', Category '" + category + "':</H3>" );
          cW.print  ( "<INPUT type=\"hidden\"" );
          cW.println( "       name=\"scope\" value=\"subcat\">" );
          cW.print  ( "<INPUT type=\"hidden\"" );
          cW.println( "       name=\"project\" value=\"" +
              project + "\">");
          cW.print  ( "<INPUT type=\"hidden\"" );
          cW.println( "       name=\"category\" value=\"" +
              category + "\">");

          cW.println( "<SELECT name=\"subcat\" size=\"1\">" );

          Vector subcats =
            config.getCategorySubCats( project, category );

          for ( int i = 0, sz = subcats.size() ; i < sz ; ++i )
            {
            Category sub = (Category) subcats.elementAt(i);
            String subStr = sub.getSubCategory();
            String subName = sub.getName();
            cW.print  ( "<OPTION value=\"" + subStr + "\">" );
            cW.print  ( subName );
            cW.println( "</OPTION>" );
            }

          cW.println( "</SELECT>&nbsp;" );

          cW.println( "<INPUT type=\"submit\" name=\"submit\"" );
          cW.println( " value=\"Narrow Reports To Subcategory\">" );

          String matchStr =
            "SELECT bug.id " +
            "FROM bug " +
            "WHERE bug.project = '" + project + "' " +
            "  AND bug.category = '" + category + "'";

          Vector bugV = Bug.matchBugs( matchStr );

          String title =
            "Bugs For Project '" + project + ", " + category + "'";

          if ( bugV.size() == 0 )
            {
            optionChosen =
              config.getProjectName( project )
              + "/"
              + config.getCategoryName( project, category );
            }
          else
            {
            this.getOutput().showBugs
              ( bReq, cW, title, bugV, "ShowBug" );
            }
          }
        catch ( DBIException ex )
          {
          cW.println( "<h2>Error Getting Bugs</h2>" );
          cW.println( "An error occurred trying to get the" );
          cW.println( "bugs for project '" + project + "'" );
          cW.println( " and category '" + category + "'." );
          cW.println( "The message was:<br>" );
          cW.println( ex.getMessage() );
          }
        }
      }
    else if ( scope.equals( "subcat" ) )
      {
      String[] vals = bReq.getParameterValues( "subcat" );
      if ( vals == null )
        {
        cW.println( "<H2>No Subcategory</H2>" );
        cW.println( "No subcategory was chosen. ");
        cW.println( "Please go back and choose a subcategory." );
        }
      else
        {
        String subcat = vals[0];
        vals = bReq.getParameterValues( "project" );
        if ( vals == null )
          {
          this.reportError
            ( bReq, cW,
              "Error when narrowing category." );
          }

        String project = vals[0];
        vals = bReq.getParameterValues( "category" );
        if ( vals == null )
          {
          this.reportError
            ( bReq, cW,
              "Error when narrowing category." );
          }
        String category = vals[0];
        try {
          Vector repV =
            Bug.matchBugs
              ( "SELECT bug.id from bug "
                + "WHERE project = '" + project
                + "' AND category = '" + category
                + "' AND subcat = '" + subcat + "'" );

          String title =
            "Bugs For Project '" + project
            + ", " + category + ", " + subcat + "'";

          if ( repV.size() == 0 )
            {
            optionChosen =
              config.getProjectName( project )
              + "/"
              + config.getCategoryName( project, category )
              + "/"
              + config.getSubCategoryName
                ( project, category, subcat );
            }
          else
            {
            this.getOutput().showBugs
              ( bReq, cW, title, repV, "ShowBug" );
            }
          }
        catch ( DBIException ex )
          {
          cW.println( "<h2>Error Getting Bugs</h2>" );
          cW.println( "An error occurred trying to get the" );
          cW.println( "bugs for project '" + project + "'" );
          cW.println( " and category '" + category + "'" );
          cW.println( " and subcat '" + subcat + "'." );
          cW.println( "The message was:<br>" );
          cW.println( ex.getMessage() );
          }
        }
      }
    else if ( scope.equals( "ID" ) )
      {
      String[] vals = bReq.getParameterValues( "bugId" );
      if ( this.isEmptyParameter( vals ) )
        {
        cW.println( "<H2>Error!</H2>" );
        cW.println( "No bug ID was specified, please " );
        cW.println( "go back and enter a valid bug ID. " );
        }
      else
        {
        String idStr = vals[0];
        try {
          int id = Integer.parseInt( idStr );
          this.getOutput().showBug( bReq, cW, id );
          }
        catch ( NumberFormatException ex )
          {
          this.reportError( bReq, cW,
            "bad bug id '" + idStr + "'" );
          }
        }
      }
    else
      {
      // UNDONE
      }

    if ( optionChosen != null )
      {
      cW.println( "<H2>No Matches</H2>" );
      cW.println( "There were no bugs found ");
      cW.println( " in " + scope + " '" + optionChosen + "'.");
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  selectBugsByResponsible( BugRatRequest bReq )
    throws IOException
    {                      
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Select Bug By Responsible" );

    String[] valAry = bReq.getParameterValues( "type" );
    String type = valAry[0];

    valAry = bReq.getParameterValues( "person" );
    if ( valAry == null || valAry.length == 0 )
      {
      cW.println( "<h2>No Person Chosen</h2>" );
      cW.println( "You must choose a person from the list.<br>" );
      cW.println( "Use your browser to go back and choose again." );
      }
    else
      {
      try
        {
        // Get All Bugs By Responsible
        boolean gotSome = false;
        String personIdStr = valAry[0];
        Vector projects = this.getDBConfig().getProjects();
        for ( int i = 0, sz = projects.size() ; i < sz ; ++i )
          {
          Category pc = (Category) projects.elementAt(i);
          String projStr = pc.getProject();
          String projectName = pc.getName();

          Vector bugV = Bug.matchBugs
            (
            "SELECT" +
            "  bug.id " +
            "FROM" +
            "  bug " +
            "WHERE" +
            "  bug.project = '" + projStr + "' " +
            "AND " + type + " = '" + personIdStr + "'"
            );

      /*    if ( bugV.size() == 1 )
            {
            int bugId = ((Bug) bugV.elementAt(0)).getId();
            this.getOutput().showBug( bReq, cW, bugId );
            }
          else
      */
          if ( bugV.size() > 0 )
            {
            gotSome = true;
            String title =  
              "Bugs For Project " + projectName;
            this.getOutput().showBugs
              ( bReq, cW, title, bugV, "ShowBug" );
            }
          }

        if ( ! gotSome )
          {
          int personId = 0;
          try { personId = Integer.parseInt( personIdStr ); }
          catch ( NumberFormatException ex )
            { personId = 0; }

          Person p = Person.getPerson( personId );

          cW.println( "<h2>No Matches</h2>" );
          cW.print  ( "There are no bugs assigned to '" );
          cW.print  ( (p == null) ? "-Unassigned-" : p.getName() );
          cW.println( "'." );
          }
        }
      catch ( DBIException ex )
        {
        cW.println( "<h2>Error Getting Bugs By Responsible</h2>" );
        cW.println( "An error occurred trying to get the" );
        cW.println( "bugs for all projects." );
        cW.println( "The message was:<br>" );
        cW.println( ex.getMessage() );
        }
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  selectReportsBySubmitter( BugRatRequest bReq )
    throws IOException
    {                      
    String[] valAry = bReq.getParameterValues( "type" );
    String type = valAry[0];

    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Select Report By Submitter" );

    valAry = bReq.getParameterValues( "person" );
    if ( valAry == null || valAry.length == 0 )
      {
      cW.println( "<h2>No Person Chosen</h2>" );
      cW.println( "Please choose a person from the list.<br>" );
      cW.println( "Use your browser to go back and choose again." );
      }
    else
      {
      try {
        // Get All Reports By Submitter
        boolean gotSome = false;
        String personIdStr = valAry[0];
        Vector projects = this.getDBConfig().getProjects();
        for ( int i = 0, sz = projects.size() ; i < sz ; ++i )
          {
          Category pc = (Category) projects.elementAt(i);
          String projStr = pc.getProject(); // ---- this is it
          String projectName = pc.getName();

          Vector repV = Report.matchReports
            (
            "SELECT" +
            "  report.id " +
            "FROM" +
            "  report " +
            "WHERE" +
            "  report.project = '" + projStr + "' " +
            "AND " + type + " = '" + personIdStr + "'"
            );

        /*  if ( repV.size() == 1 )
            {
            int repId = ((Report)repV.elementAt(0)).getId();
            this.getOutput().showReport( bReq, cW, repId );
            }
          else
        */
          if ( repV.size() > 0 )
            {
            gotSome = true;
            String title =
              "Reports For Project " + projectName;
            this.getOutput().showReports
              ( bReq, cW, title, repV, "ShowReport" );
            }
          }

        if ( ! gotSome )
          {
          int personId = 0;
          try { personId = Integer.parseInt( personIdStr ); }
          catch ( NumberFormatException ex )
            { personId = 0; }

          Person p = Person.getPerson( personId );

          cW.println( "<h2>No Matches</h2>" );
          cW.print  ( "There are no reports submitted by '" );
          cW.print  ( (p == null) ? "-Unknown-" : p.getName() );
          cW.println( "'." );
          }
        }
      catch ( DBIException ex )
        {
        cW.println( "<h2>Error Getting Reports By Submitter</h2>" );
        cW.println( "An error occurred trying to get the" );
        cW.println( "reports for all projects." );
        cW.println( "The message was:<br>" );
        cW.println( ex.getMessage() );
        }
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  selectByResponsible( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Select Bugs By Responsible" );

    cW.println( "<H2>Choose Bug By Person Responsible</h2>" );
    cW.println( "Please choose a person from the list below to" +
      " display all bugs that person is responsible for." );

    cW.println
      ( "<FORM method=\"POST\" action=\""
        + bReq.getServletPath()
        + "/SelectBugsByResponsible\">" );

    cW.println( "<INPUT type=\"hidden\" name=\"type\" value=\"responsible\">" );

    String notAssgnOption =
      "<OPTION VALUE=\"0\"> Not Assigned </OPTION>";

    this.getOutput().sendPersonSelector
      ( bReq, cW, -1, -1, "person", notAssgnOption, null );

    cW.println( "&nbsp;" );
    cW.println( "<INPUT type=\"submit\" name=\"submit\"" );
    cW.println( " value=\"Show Bugs\">" );

    cW.println( "</FORM>" );

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  selectBySubmitter( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Select Report By Submitter" );

    cW.println( "<H2>Choose Report By Person Submitting</h2>" );
    cW.println( "Please choose a person from the list below to" +
      " display all reports that person has submitted." );

    cW.println
      ( "<FORM method=\"POST\" action=\""
        + bReq.getServletPath()
        + "/SelectReportsBySubmitter\">" );

    cW.println( "<INPUT type=\"hidden\" name=\"type\" value=\"submitter\">" );

    this.getOutput().sendPersonSelector
      ( bReq, cW, -1, -1, "person", null, null );

    cW.println( "&nbsp;" );
    cW.println( "<INPUT type=\"submit\" name=\"submit\"" );
    cW.println( " value=\"Show Reports\">" );

    cW.println( "</FORM>" );

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  chooseBug( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Choose Bug By ID" );

    String action = bReq.getServletPath() + "/ChooseBug";

    cW.println( "<H2>Choose Bug By BugID</H2>" );
    cW.println( "Please type in the ID of the bug you would like to view." );
    cW.println( "<BR>" );

    cW.println( "<FORM method=\"POST\" action=\"" + action + "\">" );
    cW.println( "<INPUT type=\"text\" name=\"bugId\" > ");
    cW.println( "<INPUT type=\"submit\" name=\"submit\"" );
    cW.println( " value=\"Find Bug\">" );

    cW.println( "</FORM>" );

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected void
  chooseReport( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Choose Report By ID" );

    String action = bReq.getServletPath() + "/ChooseReport";

    cW.println( "<H2>Choose Report By ReportID</H2>" );
    cW.println( "Please type in the ID of the report you would like to view." );
    cW.println( "<BR>" );

    cW.println( "<FORM method=\"POST\" action=\"" + action + "\">" );
    cW.println( "<INPUT type=\"text\" name=\"reportId\" > ");
    cW.println( "<INPUT type=\"submit\" name=\"submit\"" );
    cW.println( " value=\"Find Report\">" );

    cW.println( "</FORM>" );

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  /**
   *
     * processCommitPerson - process the posting of an edited bug
     *
     *
     */
    private void
    processCommitPerson( BugRatRequest bReq )
    throws IOException
    {
    DBConfig config = this.getDBConfig();

    boolean okToContionue = true;
    boolean newAccountRequiresAdmin = bReq.getNewUserRequiresAdmin();

    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader
      ( bReq, cW, "BugRat - Commit Person" );

    if ( newAccountRequiresAdmin )
      {
      if ( ! this.isAdmin() )
        {
        okToContionue = false;
        }
      }

    if ( okToContionue )
      {
      try {
        String[] valAry;

        valAry = bReq.getParameterValues( "id" );
        if ( this.isEmptyParameter( valAry ) )
          throw this.new RequiredException( "id" );
        String idStr = valAry[0];

        valAry = bReq.getParameterValues( "type" );
        if ( this.isEmptyParameter( valAry ) )
          throw this.new RequiredException( "type" );
        String personType = valAry[0];

        valAry = bReq.getParameterValues( "name" );
        if ( this.isEmptyParameter( valAry ) )
          throw this.new RequiredException( "name" );
        String personName = valAry[0];

        valAry = bReq.getParameterValues( "email" );
        if ( this.isEmptyParameter( valAry ) )
          throw this.new RequiredException( "email" );
        String personEmail = valAry[0];

        valAry = bReq.getParameterValues( "org" );
        String personOrg =
          this.isEmptyParameter( valAry ) ? null : valAry[0];

        valAry = bReq.getParameterValues( "phone" );
        String personPhone =
          this.isEmptyParameter( valAry ) ? null : valAry[0];

        valAry = bReq.getParameterValues( "fax" );
        String personFAX =
          this.isEmptyParameter( valAry ) ? null : valAry[0];

        valAry = bReq.getParameterValues( "url" );
        String personURL =
          this.isEmptyParameter( valAry ) ? null : valAry[0];

        try {
          int personId = Integer.parseInt( idStr );

          Person pers = null;
          if ( personId != 0 )
            {
            pers = Person.getPerson( personId );
            }

          if ( pers == null )
            {
            pers =
              Person.getNewPerson
                ( personType, personEmail, personName );

            personId = pers.getId();
            pers.setOrganization( personOrg );
            pers.setPhone( personPhone );
            pers.setFAX( personFAX );
            pers.setURL( personURL );
            }
          else
            {
            pers.setType( personType );
            pers.setEmail( personEmail );
            pers.setName( personName );
            pers.setOrganization( personOrg );
            pers.setPhone( personPhone );
            pers.setFAX( personFAX );
            pers.setURL( personURL );
            }

          pers.commit();

          this.dbConfig.retrievePersons();

          this.getOutput().sendEditPersonForm
            ( bReq, cW, personId, true );

          cW.println( "<p>" );
          cW.println( "<a href=\"" );
          cW.print  ( bReq.getServletPath() );
          cW.print  ( "/EditPerson" );
          cW.println( "\">" );
          cW.println( "Select another person to edit." );
          cW.println( "</a>" );
          }
        catch ( NumberFormatException ex )
          {
          cW.println( "<h2>Error Committing Person</h2>" );
          this.reportError( bReq, cW,
            "Error parsing person ID '" + idStr + "', "
            + ex.getMessage() );
          }
        catch ( DBIException ex )
          {
          cW.println( "<h2>Error Committing Person</h2>" );
          this.reportError( bReq, cW,
            "Error committing person ID '" + idStr + "' to database, "
            + ex.getMessage() );
          }
        }
      catch ( RequiredException ex )
        {
        this.reportError( bReq, cW,
          "Required field '" + ex.getMessage() + "' is missing" );
        }
      }
    else
      {
      cW.println( "<h2>Not Authorized</h2>" );
      cW.println( "This BugRat installation requires you to use the" );
      cW.println( "Admin servlet to commit changes to users. Please" );
      cW.println( "use the Admin servlet to commit changes to users." );
      }

    this.sendCommonTrailer( bReq, cW );
    cW.close();
    }

  protected boolean
  isEmptyParameter( String[] parm )
    {
    return
      ( parm == null
        || parm.length == 0
        || parm[0].length() == 0 );
    }

  public void
  destroy()
    {
    if ( this.mailQueue != null )
      {
      this.mailQueue.shutdown();
      this.mailQueue = null;
      }

    super.destroy();
    }

  public void
  init( ServletConfig config )
    throws ServletException
    {
    super.init( config );

    this.config = config;
    this.context = config.getServletContext();

    this.log( this.getServletName() + " ------" );

    this.adminServlet =
      this.config.getInitParameter( "adminServlet" );
    if ( this.adminServlet == null )
      {
      this.adminServlet = "admin";
      }

    String dbgStr = this.config.getInitParameter( "debug" );
    if ( dbgStr != null &&
        ( dbgStr.equalsIgnoreCase( "on" )
          || dbgStr.equalsIgnoreCase( "true" )
          || dbgStr.equalsIgnoreCase( "yes" ) ) )
      {
      this.debug = true;
      }

    this.reportServlet =
      this.config.getInitParameter( "reportServlet" );
    if ( this.reportServlet == null )
      {
      this.reportServlet = "report";
      }

    this.viewerServlet =
      this.config.getInitParameter( "viewerServlet" );
    if ( this.viewerServlet == null )
      {
      this.viewerServlet = "view";
      }

    this.log( "  Servlet Names:" );
    this.log( "    Admin   = '" + this.adminServlet + "'" );
    this.log( "    Report  = '" + this.reportServlet + "'" );
    this.log( "    View    = '" + this.viewerServlet + "'" );

    String val;
    val = config.getInitParameter( "jdbcUrl" );
    if ( val != null )
      this.jdbcUrl = val;

    this.log( "  JDBC URL:" );
    this.log( "    Url = '" + this.jdbcUrl + "'" );

    this.jdbcProps = new Properties();
    for ( int i = 1 ; ; ++i )
      {
      val = config.getInitParameter( "jdbcProp_" + i );
      if ( val == null )
        break;

      int index = val.indexOf( "=" );
      if ( index > 0 )
        {
        String propKey = val.substring( 0, index );
        String propVal = val.substring( index + 1);
        this.log( "    Props '" + propKey + "=" + propVal + "'" );
        this.jdbcProps.put( propKey, propVal );
        }
      }

    val = config.getInitParameter( "jdbcDriverClassName" );
    if ( val != null )
      this.jdbcDriverClassName = val;

    this.log( "  JDBC Driver:" );
    this.log( "    Driver  = '" + this.jdbcDriverClassName + "'" );

    try {
      //
      // NOTE You MUST call the JDBC Parameters and Driver
      //      methods BEFORE calling setCurrentDBIManager().
      //
      DBIManager dbiMgr = DBIManager.getInstance();

      dbiMgr.setJDBCParameters
        ( this.jdbcUrl, this.jdbcDriverClassName,
          this.jdbcProps, this );

      dbiMgr.setCurrentDBIManager( DBIManager.JDBC );

      this.dbConfig = DBConfig.getInstance();

      this.dbConfig.addConfigChangeListener( this );

      this.initializeConfiguration();

      this.logConfigParameters( this.getServletInfo() );

      this.output = new DefaultBugRatHTML( this, this.dbConfig );
      }
    catch ( DBIException ex )
      {
      this.log( "Initializing DBI", ex );
      throw new ServletException
        ( "could not set DBIManager to JDBC: "
          + ex.getMessage() );
      }

    String dateFormatStr =
      this.dbConfig.getProperty
        ( "commonServlet.dateFormat", "MMM d yyyy, hh:mm:ss z" );

    this.dateFmt =
      new SimpleDateFormat( dateFormatStr );

    this.bugFmt = new BugFormatter( this.dbConfig, this.dateFmt );
    this.reportFmt = new ReportFormatter( this.dbConfig, this.dateFmt );

    String transportProtocol =
      this.dbConfig.getProperty
        ( "commonServlet.mailTransport", "smtp" );

    String mailServerHostname =
      this.dbConfig.getProperty
        ( "commonServlet.mailServerName", "localhost" );

    String adminAddress = this.dbConfig.getAdminEmailAddress();

    this.log( "  Mail Queue:" );
    this.log( "    Transport    = '" + transportProtocol + "'" );
    this.log( "    Server       = '" + mailServerHostname + "'" );
    this.log( "    AdminAddress = '" + adminAddress + "'" );

    this.mailQueue =
      MailQueueThread.establishMailQueue
        ( transportProtocol, mailServerHostname, adminAddress, this );

    String userDir = System.getProperty( "user.dir" );

    this.log( "  System Properties:" );
    this.log( "    user.dir  = '" + userDir + "'" );
    }

  protected void
  initializeConfiguration()
    {
    this.allowsBugComments =
      this.dbConfig.getBoolean
        ( "commonServlet.allowsBugComments", true );

    this.allowsRepComments =
      this.dbConfig.getBoolean
        ( "commonServlet.allowsReportComments", true );

    this.commentReqsAdmin =
      this.dbConfig.getBoolean
        ( "commonServlet.commentRequiresAdmin", false );

    this.newUserReqsAdmin =
      this.dbConfig.getBoolean
        ( "commonServlet.newPersonRequiresAdmin", false );
    }

  protected void
  logConfigParameters( String servletName )
    {
    this.log( servletName );

    this.log( "  Configuration:" );
    this.log( "    allowsBugComments     = '"
      + this.allowsBugComments + "'" );
    this.log( "    allowsReportComments  = '"
      + this.allowsRepComments + "'" );
    this.log( "    commentRequiresAdmin  = '"
      + this.commentReqsAdmin + "'" );
    this.log( "    newUserReqsAdmin      = '"
      + this.newUserReqsAdmin + "'" );
    }

  /**
   * Split a string into a string array containing the substrings
   * between the delimiters.
   *
   * NOTE This method WILL <strong>NOT</strong> return an empty
   * token at the end of the array that is returned, if the string
   * ends with the delimiter. You will need to check for this in
   * the calling code.
   *
   * This was stolen from com.ice.util.StringUtilities, simply to
   * eliminate this single method dependency, which simpifies pkging.
   *
   */

  public String[]
  splitString( String splitStr, String delim )
    {
    int        i, count;
    String[]    result;
    StringTokenizer toker;

    toker = new StringTokenizer( splitStr, delim );

    count = toker.countTokens();

    result = new String[ count ];

    for ( i = 0 ; i < count ; ++i )
      {
      try { result[i] = toker.nextToken(); }
      catch ( NoSuchElementException ex )
        {
        result = null;
        break;
        }
      }

    return result;
    }

  /**
   * This is a HORRIBLE HACK that is necessitated because of the
   * terribly lazing programming displayed by the author of the
   * core Java class 'java.text.MessageFormat'. The sloppy coding
   * hard codes a limit of ten items that may be replaced by the
   * MessageFormat.format() method. Incredible.
   *
   * Thus, we need a method to allow more general formatting. The
   * simplest thing I could come up with was to parse up the format
   * text so that we MessageFormat.format() each item one at a time.
   * I am not happy with this code, but am not up to a more general
   * solution at this time. This is depressing...
   *
   */

  public static String
  filterQuotes( String str )
    {
    StringBuffer buf = new StringBuffer();

    for ( ; ; )
      {
      int idx = str.indexOf( "''" );
      if ( idx == -1 )
        {
        buf.append( str );
        break;
        }

      buf.append( str.substring( 0, idx ) );
      buf.append( "'" );
      str = str.substring( idx + 2 );
      }

    return buf.toString();
    }

  public static String
  format( String formatStr, Object[] fmtArgs )
    {
    StringBuffer result =
      new StringBuffer( formatStr.length() + 256 );

    String workStr = formatStr;

    for ( ; ; )
      {
      int lcbIdx = workStr.indexOf( "{" );
      if ( lcbIdx == -1 )
        {
        break;
        }
     
      if ( lcbIdx > 0 )
        {
        char lqt = workStr.charAt(lcbIdx-1);
        char num = workStr.charAt(lcbIdx+1);
        char rcb = workStr.charAt(lcbIdx+2);

        String leftStr = workStr.substring( 0, lcbIdx );

        if ( lqt == '\'' && num == '\'' )
          {
          // This is a quoted brace, put it...
          result.append
            ( BugRatServlet.filterQuotes
              ( workStr.substring( 0, lcbIdx - 1 ) ) );

          result.append( "{" );
          workStr = workStr.substring( lcbIdx + 1 );
          }
        else if ( (num >= '0' && num <= '9') && rcb == '}' )
          {
          // This is a valid format item, to be replaced...
          result.append( BugRatServlet.filterQuotes( leftStr ) );
          String fmtStr = "{" + num + "}";
          result.append( MessageFormat.format( fmtStr, fmtArgs ) );
          workStr = workStr.substring( lcbIdx + 3 );
          }
        else
          {
          // This is an error, I believe!
          result.append( BugRatServlet.filterQuotes( leftStr ) );
          result.append( "ERR{ERR" );
          workStr = workStr.substring( lcbIdx + 1 );
          }
        }
      else
        {
        char num = workStr.charAt(1);
        char rcb = workStr.charAt(2);
        if ( rcb == '}' && num >= '0' && num <= '9' )
          {
          String fmtStr = "{" + num + "}";
          result.append
            ( MessageFormat.format( fmtStr, fmtArgs ) );
          workStr = workStr.substring( 3 );
          }
        else
          {
          result.append( "{" );
          workStr = workStr.substring( 1 );
          }
        }
      }

    if ( workStr.length() > 0 )
      {
      result.append( BugRatServlet.filterQuotes( workStr ) );
      }

    return result.toString();
    }

  protected class
  RequiredException extends Exception
    {
    public
    RequiredException( String msg )
      {
      super( msg );
      }
    }

  }

TOP

Related Classes of org.gjt.bugrat.servlet.BugRatServlet$RequiredException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.