Package org.gjt.bugrat.servlet

Source Code of org.gjt.bugrat.servlet.BugRatAdmin

package org.gjt.bugrat.servlet;

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

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

import org.gjt.bugrat.db.*;
import org.gjt.bugrat.dbi.*;


public
class    BugRatAdmin
extends    BugRatServlet
  {
  public String
  getServletInfo()
    {
    return "BugRat - Admin servlet, version "
        + this.getVersionStr() + " by Tim Endres.";
    }

  /**
   * Override isAdmin() to return true, since we ARE da man!
   */

  public boolean
  isAdmin()
    {
    return true;
    }

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

  public void
  doGet( HttpServletRequest req, HttpServletResponse res )
    throws ServletException, IOException
    {
    BugRatRequest bReq = new BugRatRequest( req, res, this );

    String pathInfo = bReq.getPathInfo();

    if ( this.commonGet( bReq ) )
      {
      // Handled by the common GET code...
      }
    else if ( pathInfo == null || pathInfo.equals( "/" ) )
      {
      // UNDONE - Main Menu ?
      this.sendIndexPage( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/index" ) ||
        pathInfo.equalsIgnoreCase( "/index.html" ) )
      {
      this.sendIndexPage( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/MailQueueInfo" ) )
      {
      this.sendMailQueueInfoPage( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ShowIdInfo" ) )
      {
      this.sendNextIdInfoPage( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/AdjustAllIds" ) )
      {
      this.adjustAllNextIds( bReq );
      this.sendNextIdInfoPage( bReq );
      }
    else if ( pathInfo.startsWith( "/EditPrefs/" ) )
      {
      String prefSelector =
        pathInfo.substring( "/EditPrefs/".length() );

      this.sendEditPreferencesForm( bReq, prefSelector );
      }
    else if ( pathInfo.equalsIgnoreCase( "/LinkReport" ) )
      {
      this.chooseReportToLink( bReq );
      }
    else if ( pathInfo.startsWith( "/LinkReport/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/LinkReport/".length() );

      try {
        id = Integer.parseInt( idStr );
        this.linkReport( bReq, 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();
        }
      catch ( DBIException ex )
        {
        PrintWriter cW = bReq.getHTMLWriter();
        this.sendCommonHeader( bReq, cW, "BugRat Error" );
        this.reportError
          ( bReq, cW,
            "Error linking Report ID '" +idStr+ "'" );
        this.sendCommonTrailer( bReq, cW );
        cW.close();
        }
      }
    else if ( pathInfo.equalsIgnoreCase( "/EditBug" ) )
      {
      this.chooseBugToEdit( bReq );
      }
    else if ( pathInfo.startsWith( "/EditBug/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/EditBug/".length() );

      try {
        id = Integer.parseInt( idStr );
        this.editBug( bReq, 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( "/ReassignBug/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/ReassignBug/".length() );

      try {
        id = Integer.parseInt( idStr );
        this.sendReassignForm( bReq, id, "Bug" );
        }
      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( "/ReassignReport/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring
          ( "/ReassignReport/".length() );

      try {
        id = Integer.parseInt( idStr );
        this.sendReassignForm( bReq, id, "Report" );
        }
      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( "/CloseBug/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring( "/CloseBug/".length() );

      try {
        id = Integer.parseInt( idStr );
        this.processClose( bReq, id, "Bug" );
        }
      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( "/CloseReport/" ) )
      {
      int id = -1;
      String idStr =
        pathInfo.substring( "/CloseReport/".length() );

      try {
        id = Integer.parseInt( idStr );
        this.processClose( bReq, id, "Report" );
        }
      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 if ( pathInfo.equalsIgnoreCase( "/EditProperty" ) )
      {
      this.sendPropertyListPage( bReq );
      }
    else if ( pathInfo.startsWith( "/EditProperty/" ) )
      {
      String propKey =
        pathInfo.substring
          ( "/EditProperty/".length() );

      this.sendEditPropertyForm( bReq, propKey );
      }
    else if ( pathInfo.equalsIgnoreCase( "/EditCategory" ) )
      {
    //  this.sendEditCategoryPage( bReq, null );
      }
    else if ( pathInfo.startsWith( "/EditCategory/" ) )
      {
      String catStr =
        pathInfo.substring
          ( "/EditCategory/".length() );

      String[] catArgs = this.splitString( catStr , "/" );

      this.sendEditCategoryPage( bReq, catArgs );
      }
    else
      {
      PrintWriter cW = bReq.getHTMLWriter();
      this.sendCommonHeader( bReq, cW, "BugRat Error" );
      this.reportError( bReq, cW,
        "Servlet request (via pathinfo) not recognized." );
      this.sendCommonTrailer( bReq, cW );
      cW.close();
      }
    }

  /**
   * Write survey results to output file in response to the POSTed
   * form.  Write a "thank you" to the client.    
   */
  public void
  doPost( HttpServletRequest req, HttpServletResponse res )
    throws ServletException, IOException
    {
    BugRatRequest bReq = new BugRatRequest( req, res, this );

    String pathInfo = bReq.getPathInfo();

    if ( this.commonPost( bReq ) )
      {
      // Handled by the common GET code...
      }
    else if ( pathInfo == null )
      {
      // REVIEW
      this.processShowReports( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/SetProperty" ) )
      {
      this.processSetProperty( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/SetCategory" ) )
      {
      this.processSetCategory( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ReassignBug" ) )
      {
      this.processReassign( bReq, "Bug" );
      }
    else if ( pathInfo.equalsIgnoreCase( "/ReassignReport" ) )
      {
      this.processReassign( bReq, "Report" );
      }
    else if ( pathInfo.equalsIgnoreCase( "/LinkReportPost" ) )
      {
      this.processLinkReportPost( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/PostEditBug" ) )
      {
      this.processEditBug( bReq );
      }
    else if ( pathInfo.equalsIgnoreCase( "/SavePrefs" ) )
      {
      this.processSavePrefs( bReq );
      }
    else
      {
      PrintWriter cW = bReq.getHTMLWriter();
      this.sendCommonHeader
        ( bReq, cW, "BugRat - Error Unknown Command" );
      this.reportError( bReq, cW,
        "Servlet request (via pathinfo) not recognized." );
      this.sendCommonTrailer( bReq, cW );
      cW.close();
      }
    }

  private void
  sendReassignForm( BugRatRequest bReq, int id, String target )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader
      ( bReq, cW, "BugRat - Reassign " + target + " # '" + id + "'" );

    cW.println( "<H2>Reassign " + target + " # '" + id + "'</H2>" );

    cW.println( "Use this form to assign a " + target + " to another person." );

    try {
      Object item =
        target.equalsIgnoreCase( "bug" )
          ? (Object) Bug.getBug( id )
          : (Object) Report.getReport( id );

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

      int respId =
        target.equalsIgnoreCase( "bug" )
          ? ((Bug) item).getResponsible()
          : ((Report) item).getResponsible();

      Person p = Person.getPerson( respId );

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

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

      cW.println( "Reassign the " + target + " with ID " );
      cW.println( id );
      cW.println( " <strong>from</strong> " );

      cW.println( (p == null) ? "Not assigned" : p.getName() );
      if ( p != null )
        {
        cW.println( " ( " );
        cW.println( p.getEmail() );
        cW.println( " )" );
        }

      cW.println( "<strong>to:</strong>" );
      cW.println( "<P>" );

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

      cW.println( "<P>" );

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

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

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

  /**
   *
     * processReassignBug - reassign a bug to another person
     *
     * UNDONE This is not thread safe due to the ability for one
   *        servlet to define the action, then another to modify
   *        the assignment, then the first commits, leaving the
   *        audit trail out of sync.
   *
   *        We need to create locks for bugs and reports.
   *
     */
    private void
    processReassign( BugRatRequest bReq, String target )
    throws IOException
    {
    DBConfig config = this.getDBConfig();
            
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader
      ( bReq, cW, "BugRat - Reassign " + target );

    boolean isBug = target.equalsIgnoreCase( "Bug" );

    try {
      String value;
      String[] valAry;

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

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

      int id = -1;
      int personId = -1;
      try {
        id = Integer.parseInt( idStr );
        personId = Integer.parseInt( personIdStr );

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

        if ( item == null )
          {
          cW.println( "<h2>Reassigning " +target+ " #" + id + "</h2>" );
          this.reportError( bReq, cW,
            "Could not retrieve " +target+ " #" + id );
          }
        else
          {
          int oldRespId = 0;

          if ( isBug )
            {
            Bug bug = (Bug) item;
            oldRespId = bug.getResponsible();
            bug.setResponsible( personId );
            bug.commit();
            }
          else
            {
            Report rep = (Report) item;
            oldRespId = rep.getResponsible();
            rep.setResponsible( personId );
            rep.commit();
            }

          BugRatAction action =
            BugRatAction.getNewAction( ACTION_ASSIGN );
         
          int actorId = this.getUserId( bReq );
          if ( actorId == 0 )
            {
            this.log
              ( "WARNING getUserId() returned no actor "
                + "for action #" + action.getId() );
            }

          action.setActorId( actorId );
          action.setActionTime( new Date() );
          action.setTarget( isBug ? TARGET_BUG : TARGET_REPORT );
          action.setTargetId( id );
          action.setArgOne( oldRespId );
          action.setArgTwo( personId );
          action.setComment
            ( "assigned "
              + (isBug ? "bug" : "report" )
              + " #" + id
              + " from person #" + oldRespId
              + " to person #" + personId
              + " by person #" + actorId );

          action.commit();

          String address = null;

          Person p = Person.getPerson( personId );
          if ( p == null )
            {
            throw new DBIException
              ( "Could not find assignment person #"
                + personId );
            }

          Person oldP = Person.getPerson( oldRespId );

          String subject =
              "BugRat " +target+ " #" + id
              + " was assigned to " + p.getName();

          StringBuffer body = new StringBuffer();
          body.append( target + " #" );
          body.append( id );
          body.append( " was assigned to Person #" );
          body.append( personId );
          body.append( "\n\n" );
          body.append( "   Name:     " );
          body.append( p.getName() );
          body.append( "\n" );
          body.append( "   Email:    " );
          body.append( p.getEmail() );
          body.append( "\n" );
          body.append( "   HomePage: " );
          body.append( p.getURL() );
          body.append( "\n" );
          body.append( "   Phone:    " );
          body.append( p.getPhone() );
          body.append( "\n" );
          body.append( "   FAX:      " );
          body.append( p.getFAX() );

          body.append( "\n\n" );

          if ( oldP != null )
            {
            body.append( "The " );
            body.append( isBug ? "bug" : "report" );
            body.append( " was previously assigned to person #" );
            body.append( oldP.getId() );
            body.append( "\n\n" );
            body.append( "   Name:     " );
            body.append( oldP.getName() );
            body.append( "\n" );
            body.append( "   Email:    " );
            body.append( oldP.getEmail() );
            body.append( "\n" );
            body.append( "   HomePage: " );
            body.append( oldP.getURL() );
            body.append( "\n" );
            body.append( "   Phone:    " );
            body.append( oldP.getPhone() );
            body.append( "\n" );
            body.append( "   FAX:      " );
            body.append( oldP.getFAX() );
            }
          else
            {
            body.append( "The " );
            body.append( isBug ? "bug" : "report" );
            body.append( " was previously unassigned." );
            }

          InternetAddress[] toAddrs =
            new InternetAddress[ (oldP == null) ? 1 : 2 ];

          toAddrs[0] =
            new InternetAddress
              ( p.getEmail(), p.getName() );

          if ( oldP != null )
            {
            toAddrs[1] =
              new InternetAddress
                ( oldP.getEmail(), oldP.getName() );
            }

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

          if ( isBug )
            this.getOutput().showBug( bReq, cW, id );
          else
            this.getOutput().showReport( bReq, cW, id );
          }
        }
      catch ( NumberFormatException ex )
        {
        cW.println( "<h2>Reassigning " + target + "</h2>" );
        throw this.new RequiredException
          ( "could not parse '"
            + ( (id == -1)
              ? ( isBug ? "bug" : "report" )
              : "person" )
            + "' id, " + ex.getMessage() );
        }
      catch ( DBIException ex )
        {
        cW.println( "<h2>Reassigning " + target + "</h2>" );
        this.reportError( bReq, cW,
          "Error committing reassignment of "
          + target + " #" + 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();
    }

  /**
   *
     * processClose - close a bug or a report
   *
     */
    private void
    processClose( BugRatRequest bReq, int id, String target )
    throws IOException
    {
    DBConfig config = this.getDBConfig();
            
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader
      ( bReq, cW, "BugRat - Closed " + target );

    boolean isBug = target.equalsIgnoreCase( "Bug" );

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

      if ( item == null )
        {
        cW.println( "<h2>Closing " +target+ " #" + id + "</h2>" );
        this.reportError( bReq, cW,
          "Could not retrieve " + target + " #" + id );
        }
      else
        {
        int respId = 0;
       
        if ( isBug )
          {
          Bug bug = (Bug) item;
          bug.setState( STATE_CLOSED );
          bug.setCloseDate( new Date() );
          bug.commit();
          respId = bug.getResponsible();
          }
        else
          {
          Report rep = (Report) item;
          rep.setState( STATE_CLOSED );
          // Reports don't have close dates....
          // rep.setCloseDate( new Date() );
          rep.commit();
          respId = rep.getResponsible();
          }

        BugRatAction action =
          BugRatAction.getNewAction( ACTION_CLOSE );
       
        int actorId = this.getUserId( bReq );
        if ( actorId == 0 )
          {
          this.log
            ( "WARNING getUserId() returned no actor "
              + "for action #" + action.getId() );
          }

        action.setActorId( actorId );
        action.setActionTime( new Date() );
        action.setTarget( isBug ? TARGET_BUG : TARGET_REPORT );
        action.setTargetId( id );
        action.setArgOne( 0 );
        action.setArgTwo( 0 );
        action.setComment
          ( "closed " + (isBug?"bug":"report") + " #" + id );

        action.commit();

        String address = null;
        String subject =
            "BugRat " +target+ " #" + id
            + " was closed";

        StringBuffer body = new StringBuffer();
        body.append( target );
        body.append( " #" );
        body.append( id );
        body.append( " was closed by Person #" );

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

        if ( desc != null )
          {
          body.append( actorId );
          body.append( "\n\n" );
          body.append( "   Synopsis: " );
          body.append( desc.getSynopsis() );
          // UNDONE - Add the description? All details?
          //          We need some common "formatters"
          //          to produce text/plain and text/html
          //          descriptions of bugs and reports.
          }

        // If this is a bug, send notice to submitters of
        // all reports linked to this bug.

        Vector repV = null;
       
        if ( isBug )
          {
          repV = Report.matchReports
            (
            "SELECT report.id " +
            "FROM report, repbug " +
            "WHERE report.id = repbug.report " +
            "AND repbug.bug = " + id
            );
          }
        else
          {
          repV = new Vector();
          repV.addElement( (Report) item );
          }

        Person p = Person.getPerson( respId );
        if ( p == null )
          {
          respId = config.getDefaultResponsible();
          p = Person.getPerson( respId );
          }

        if ( p != null )
          {
          InternetAddress[] toAddrs =
            new InternetAddress[ 1 ];

          toAddrs[0] =
            new InternetAddress
              ( p.getEmail(), p.getName() );

          InternetAddress[] ccAddrs = null;

          if ( repV.size() > 0 )
            {
            Vector ccV = new Vector();
            for ( int i = 0, sz = repV.size(); i < sz ; i ++ )
              {
              Report rep = (Report) repV.elementAt( i );

              Person sub =
                Person.getPerson( rep.getSubmitter() );

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

            ccAddrs = new InternetAddress[ ccV.size() ];
            ccV.copyInto( ccAddrs );
            }

          this.mailQueue.addMailJob
            ( subject, body.toString(), toAddrs, ccAddrs );
          }
        else
          {
          // UNDONE Log case of no resposible person, or
          }

        if ( isBug )
          this.getOutput().showBug( bReq, cW, id );
        else
          this.getOutput().showReport( bReq, cW, id );
        }
      }
    catch ( DBIException ex )
      {
      cW.println( "<h2>Closing " +target+ "</h2>" );
      this.reportError( bReq, cW,
        "Error committing closure of "
        + (isBug?"bug":"report") + " #"
        + id + ", " + ex.getMessage() );
      }

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

  private void
  sendEditPropertyForm( BugRatRequest bReq, String propKey )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader
      ( bReq, cW, "BugRat - Edit Property '" + propKey + "'" );

    String propValue = "";
    BRATProperty prop = null;
    if ( propKey != null && propKey.length() > 0 )
      {
      try { prop = BRATProperty.getProperty( propKey ); }
      catch ( DBIException ex )
        { prop = null; }
      }

    cW.println( "<h2>Edit Property " );
    cW.println( (propKey==null || propKey.length()==0) ? "" : propKey );
    cW.println( "</h2>" );

    cW.println( "Use this form to add or edit properties." );

    if ( prop == null )
      {
      cW.println( "<p>" );
      cW.println( "<B>NOTE</B>" );
      cW.println( "The property named '" );
      cW.println( propKey );
      cW.println( "' was not found in the property table in the" );
      cW.println( "database. If you set the property via this form" );
      cW.println( "a new entry will be created in the property" );
      cW.println( "table with the key and value you enter." );
      }
    else
      {
      propValue = prop.getValue();
      }

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

    cW.println( "<strong>Property Key:</strong>" );
    cW.print  ( "<INPUT type=\"textfield\" size=\"48\"" );
    cW.print  ( "       name=\"propkey\" value=\"" );
    cW.print  ( propKey );
    cW.println( "\">" );
    cW.println( "<br>" );
    cW.println( "<strong>Property Value:</strong>" );
    cW.println( "<br>" );
    cW.println( "<textarea rows=24 cols=64 name=\"propvalue\">" );
    cW.println( propValue );
    cW.println( "</textarea>" );

    cW.println( "<br>" );

    cW.print  ( "<INPUT type=\"submit\"" );
    cW.print  ( "       name=\"submit\" value=\"Set Property\">" );

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

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

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

    cW.println( "<h2>BugRat Configuration Properties</h2>" );

    cW.println( "Click on any property to view/edit its value." );

    cW.println( "<UL>" );

    Vector sKeys = new Vector( 256 );
    Enumeration enum = this.dbConfig.getPropertyEnumerator();
    for ( ; enum.hasMoreElements() ; )
      {
      boolean inserted = false;
      BRATProperty prop = (BRATProperty) enum.nextElement();
      String key = prop.getKey().toLowerCase();

      for ( int i = 0, sz = sKeys.size() ; i < sz ; ++i )
        {
        String vKey = ((String)sKeys.elementAt(i)).toLowerCase();
        if ( key.compareTo( vKey ) < 0 )
          {
          inserted = true;
          sKeys.insertElementAt( prop.getKey(), i );
          break;
          }
        }

      if ( ! inserted )
        {
        sKeys.addElement( prop.getKey() );
        }
      }

    for ( int i = 0, sz = sKeys.size() ; i < sz ; ++i )
      {
      String key = (String) sKeys.elementAt(i);
      cW.println( "<LI>" );
      cW.print  ( "<A HREF=\"" );
      cW.print  ( bReq.getServletPath() );
      cW.print  ( "/EditProperty/" );
      cW.print  ( key );
      cW.println( "\">" );
      cW.println( "<strong>" );
      cW.println( key );
      cW.println( "</strong>" );
      cW.println( "</A>" );
      cW.println( "</LI>" );
      }

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

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

  /**
   *
     * processSetProperty - process the posting of an edited bug
     *
     *
     */
    private void
    processSetProperty( BugRatRequest bReq )
    throws IOException
    {
    DBConfig config = this.getDBConfig();
            
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader
      ( bReq, cW, "BugRat - Edit Property" );

    cW.println( "<h2>Setting Property</h2>" );

    try {
      String value;
      String[] valAry;

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

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

      try {
        BRATProperty prop =
          BRATProperty.getProperty( propKey );

        if ( prop == null )
          {
          prop = new BRATProperty( propKey, propValue );
          }
        else
          {
          prop.setValue( propValue );
          }

        prop.commit();

        this.getDBConfig().retrieveConfiguration();

        cW.print  ( "Successfully set property <strong>'" );
        cW.print  ( prop.getKey() );
        cW.println( "'</strong>." );
        cW.println( "<h3>Value:</h3>" );
        cW.print  ( "<pre>" );
        cW.print  ( prop.getValue() );
        cW.println( "</pre>" );
        }
      catch ( DBIException ex )
        {
        this.reportError( bReq, cW,
          "Error committing property '" + propKey + "' to database, "
          + ex.getMessage() );
        }
      }
    catch ( RequiredException ex )
      {
      this.reportError( bReq, cW,
        "Required field '" + ex.getMessage() + "' is missing!" );
      }

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

  private void
  sendEditCategoryPage( BugRatRequest bReq, String[] catArgs )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();

    cW.println( "<h2>Edit Category</h2>" );

    cW.println( "Use this form to change the person responsible for " );
    cW.println( "this category, or to change its display name or its " );
    cW.println( "description. You can not change the pkg, category, or " );
    cW.println( "subcat, since they are primaty keys. You must create a " );
    cW.println( "new record and delete the old one to change one of the " );
    cW.println( "key values." );

    this.sendEditCategoryForm( bReq, cW, catArgs );

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


  private void
  sendEditCategoryForm( BugRatRequest bReq, PrintWriter cW, String[] catArgs )
    throws IOException
    {
    DBConfig config = this.getDBConfig();

    String pkgStr = catArgs[0];
    String catStr = (catArgs.length > 1) ? catArgs[1] : "";
    String subStr = (catArgs.length > 2) ? catArgs[2] : "";

    String displayName = pkgStr + "," + catStr + "," + subStr;

    Category cat = null;
   
    try { cat = Category.getCategory( pkgStr, catStr, subStr ); }
    catch ( DBIException ex )
      { cat = null; }

    if ( cat == null )
      {
      this.reportError( bReq, cW,
        "Category '" + displayName + "' does not exist." );
      }
    else
      {
      cW.print  ( "<FORM method=\"POST\" action=\"" );
      cW.print  ( bReq.getServletPath() );
      cW.print  ( "/SetCategory\">" );

      cW.print  ( "<INPUT type=\"hidden\" name=\"pkg\"" );
      cW.print  ( "       value=\"" + pkgStr + "\">" );
      cW.print  ( "<INPUT type=\"hidden\" name=\"cat\"" );
      cW.print  ( "       value=\"" + catStr + "\">" );
      cW.print  ( "<INPUT type=\"hidden\" name=\"sub\"" );
      cW.print  ( "       value=\"" + subStr + "\">" );

      cW.println( "<table width=\"100%\">" );

      cW.println( "<tr>" );

      cW.println( "<th align=\"left\">" );
      cW.println( "Project:" );
      cW.println( "</th>" );

      boolean linkIt;

      linkIt = cat.isCategory() || cat.isSubCategory();
      cW.println( "<td>" );
      if ( linkIt )
        {
        cW.println( "<A HREF=\"" );
        cW.print  ( bReq.getServletPath() );
        cW.print  ( "/EditCategory/" );
        cW.print  ( pkgStr );
        cW.println( "\">" );
        }
      cW.println( config.getProjectName( pkgStr ) );
      if ( linkIt )
        {
        cW.println( "</A>" );
        }
      cW.print  ( "(&nbsp;" );
      cW.print  ( cat.getProject() );
      cW.println( "&nbsp;)" );
      cW.println( "</td>" );

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

      if ( cat.isCategory()
          || cat.isSubCategory() )
        {
        cW.println( "<tr>" );

        cW.println( "<th align=\"left\">" );
        cW.println( "Category:" );
        cW.println( "</th>" );

        linkIt = cat.isSubCategory();
        cW.println( "<td>" );
        if ( linkIt )
          {
          cW.println( "<A HREF=\"" );
          cW.print  ( bReq.getServletPath() );
          cW.print  ( "/EditCategory/" );
          cW.print  ( pkgStr );
          cW.print  ( "/" );
          cW.print  ( catStr );
          cW.println( "\">" );
          }
        cW.println( config.getCategoryName( pkgStr, catStr ) );
        if ( linkIt )
          {
          cW.println( "</A>" );
          }
        cW.print  ( "(&nbsp;" );
        cW.print  ( cat.getCategory() );
        cW.println( "&nbsp;)" );
        cW.println( "</td>" );

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

      if ( cat.isSubCategory() )
        {
        cW.println( "<tr>" );

        cW.println( "<th align=\"left\">" );
        cW.println( "SubCategory:" );
        cW.println( "</th>" );

        cW.println( "<td>" );
        cW.println( config.getSubCategoryName
                ( pkgStr, catStr, subStr ) );
        cW.print  ( "(&nbsp;" );
        cW.print  ( cat.getSubCategory() );
        cW.println( "&nbsp;)" );
        cW.println( "</td>" );

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

      cW.println( "<tr>" );

      cW.println( "<th align=\"left\">" );
      cW.println( "Responsible:" );
      cW.println( "</th>" );

      cW.println( "<td>" );

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

      Person p = null;
      try { p = Person.getPerson( cat.getResponsible() ); }
      catch ( DBIException ex )
        { p = null; }

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

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

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

      cW.println( "<th align=\"left\">" );
      cW.println( "Name:" );
      cW.println( "</th>" );

      cW.println( "<td>" );

      cW.print  ( "<INPUT type=\"textfield\" size=\"48\"" );
      cW.print  ( "       name=\"catname\" value=\"" );
      cW.print  ( cat.getName() );
      cW.println( "\">" );

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

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

      cW.println( "<th align=\"left\" valign=\"top\">" );
      cW.println( "Description:" );
      cW.println( "</th>" );

      cW.println( "<td>" );

      cW.println( "<textarea rows=6 cols=48 name=\"catdesc\">" );
      cW.println( cat.getDescription() );
      cW.println( "</textarea>" );

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

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

      cW.println( "<tr>" );

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

      cW.print  ( "<INPUT type=\"submit\"" );
      cW.print  ( "       name=\"submit\" value=\"Save Category\">" );

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

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

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

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

  /**
   *
     * processSetProperty - process the posting of an edited bug
     *
     *
     */
    private void
    processSetCategory( BugRatRequest bReq )
    throws IOException
    {
    DBConfig config = this.getDBConfig();
            
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader
      ( bReq, cW, "BugRat - Saving Category" );

    try {
      String[] valAry;
      String pkgStr, catStr, subStr;

      valAry = bReq.getParameterValues( "pkg" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "project id" );
      pkgStr = valAry[0];

      valAry = bReq.getParameterValues( "cat" );
      if ( this.isEmptyParameter( valAry ) )
        catStr = "";
      else
        catStr = valAry[0];

      valAry = bReq.getParameterValues( "sub" );
      if ( this.isEmptyParameter( valAry ) )
        subStr = "";
      else
        subStr = valAry[0];

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

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

      valAry = bReq.getParameterValues( "catdesc" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "category description" );
      String catDesc = valAry[0];

      try {
        Category cat =
          Category.getCategory( pkgStr, catStr, subStr );

        if ( cat == null )
          {
          this.reportError( bReq, cW,
            "Could not locate category '"
              + pkgStr + "," + catStr + "," + subStr
              + "'." );
          }
        else
          {
          int respId = Integer.parseInt( respStr );

          cat.setName( catName );
          cat.setResponsible( respId );
          cat.setDescription( catDesc );
          }

        cat.commit();

        config.retrieveCategories();

        int alen =
          ( subStr.length() > 0 ? 3 :
          ( catStr.length() > 0 ? 2 : 1 ) );

        String[] catArgs = new String[ alen ];
        catArgs[0] = pkgStr;
        if ( catArgs.length > 1 )
          catArgs[1] = catStr;
        if ( catArgs.length > 2 )
          catArgs[2] = subStr;

        cW.println( "<h2>Category Saved</h2>" );

        cW.println( "Your modifications to the category were saved. " );
        cW.println( "You may continue to edit the category with this " );
        cW.println( "form. " );

        this.sendEditCategoryForm( bReq, cW, catArgs );
        }
      catch ( DBIException ex )
        {
        cW.println( "<h2>Error Saving Category</h2>" );
        this.reportError( bReq, cW,
          "Error committing category '"
            + pkgStr + "," + catStr + "," + subStr
            + "', " + ex.getMessage() );
        }
      catch ( NumberFormatException ex )
        {
        cW.println( "<h2>Error Saving Category</h2>" );
        this.reportError( bReq, cW,
          "Error parsing category person responsible id '"
            + respStr + "', " + ex.getMessage() );
        }
      }
    catch ( RequiredException ex )
      {
      cW.println( "<h2>Error Saving Category</h2>" );
      this.reportError( bReq, cW,
        "Required field '" + ex.getMessage() + "' is missing!" );
      }

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

  private void
  chooseReportToLink( BugRatRequest bReq )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Link Report To Bug" );

    cW.println( "<h2>Select A Project</h2>" );

    cW.println( "Use this form to show all of the reports in the." );
    cW.println( "project that you specify. Select the project you" );
    cW.println( "are interested in from the list below, and click" );
    cW.println( "the 'Show Reports' button to see the list of reports." );

    cW.println( "<FORM method=\"POST\" action=\"ShowReports\">" );
    cW.println( "Project:<br>" );
    cW.print  ( "<INPUT type=\"hidden\"" );
    cW.println( "       name=\"scope\" value=\"project\">" );
    cW.print  ( "<INPUT type=\"hidden\"" );
    cW.println( "       name=\"action\" value=\"LinkReport\">" );
    cW.println( "<SELECT name=\"project\" size=\"10\">" );

    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();
      cW.print  ( "<OPTION value=\"" + projStr + "\">" );
      cW.println( projectName );
      }

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

    cW.println( "<br>" );

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

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

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

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

    cW.println( "<h2>Select A Project</h2>" );

    cW.println( "Use this form to show all of the bugs in the." );
    cW.println( "project that you specify. Select the project you" );
    cW.println( "are interested in from the list below, and click" );
    cW.println( "the 'Show Bugs' button to see the list of bugs." );

    cW.println( "<FORM method=\"POST\" action=\"ShowBugs\">" );
    cW.println( "Project:<br>" );
    cW.print  ( "<INPUT type=\"hidden\"" );
    cW.println( "       name=\"scope\" value=\"project\">" );
    cW.print  ( "<INPUT type=\"hidden\"" );
    cW.println( "       name=\"action\" value=\"EditBug\">" );
    cW.println( "<SELECT name=\"project\" size=\"10\">" );

    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();
      cW.print  ( "<OPTION value=\"" + projStr + "\">" );
      cW.println( projectName );
      }

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

    cW.println( "<br>" );

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

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

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

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

    this.sendPropertyHTML( bReq, cW, "adminServlet.indexHtml" );

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

  private void
  sendEditPreferencesForm( BugRatRequest bReq, String prefSelector )
    throws IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Edit Bug" );

    if ( prefSelector.equalsIgnoreCase( "Admin" ) )
      {
      this.sendAdminPrefsForm( bReq, cW );
      }
    else
      {
      cW.println( "<h2>UNKNOWN Preferences</h2>" );
      cW.print  ( "THIS IS AN INTERNAL ERROR. Selector = '" );
      cW.print  ( prefSelector );
      cW.println( "'." );
      }

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

  private void
  sendAdminPrefsForm( BugRatRequest bReq, PrintWriter cW )
    throws IOException
    {
    boolean allowBugComments =
      bReq.allowsBugComments();

    boolean newUserRequiresAdmin =
      bReq.getNewUserRequiresAdmin();

    cW.println( "<h2>Administrative Preferences</h2>" );

    cW.println( "Use this form to edit the administration preferences." );

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

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

    cW.print  ( "<INPUT type=\"checkbox\" name=\"newuserpublic\"" );
    if ( ! newUserRequiresAdmin )
      cW.print( " checked " );
    cW.print  ( " value=\"true\">" );
    cW.println( "&nbsp;New User May Be Created By Anyone" );

    cW.println( "<p>" );

    cW.print  ( "<INPUT type=\"checkbox\" name=\"bugcomments\"" );
    if ( allowBugComments )
      cW.print( " checked " );
    cW.print  ( " value=\"true\">" );
    cW.println( "&nbsp;Allow admin to add comments to bugs" );

    cW.println( "<p>" );

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

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



    private void
    processSavePrefs( BugRatRequest bReq )
    throws IOException
    {
    DBConfig config = this.getDBConfig();
            
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader
      ( bReq, cW, "BugRat - Save Preferences" );

    try {
      String[] valAry = bReq.getParameterValues( "scope" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "scope" );

      String scopeStr = valAry[0];

      String key = null;
      String value = null;
      BRATProperty prop = null;

      if ( scopeStr.equalsIgnoreCase( "admin" ) )
        {
        boolean newUserPublic = false;
        valAry = bReq.getParameterValues( "newuserpublic" );
        if ( this.isEmptyParameter( valAry ) )
          newUserPublic = false;
        else
          newUserPublic = true;

        boolean bugComments = false;
        valAry = bReq.getParameterValues( "bugcomments" );
        if ( this.isEmptyParameter( valAry ) )
          bugComments = false;
        else
          bugComments = true;

        try {
          key = "commonServlet.allowsBugComments";
          value = bugComments ? "true" : "false";

          prop = BRATProperty.getProperty( key );
          if ( prop != null )
            prop.setValue( value );
          else
            prop = new BRATProperty( key, value );

          prop.commit();

          key = "commonServlet.newPersonRequiresAdmin";
          value = newUserPublic ? "false" : "true";

          prop = BRATProperty.getProperty( key );
          if ( prop != null )
            prop.setValue( value );
          else
            prop = new BRATProperty( key, value );

          prop.commit();

          this.getDBConfig().retrieveConfiguration();

          this.sendAdminPrefsForm( bReq, cW );
          }
        catch ( DBIException ex )
          {
          cW.println( "<h2>Error Saving Preferences</h2>" );
          this.reportError( bReq, cW,
            "Error saving preferences to database, key='"
            + key + "', " + ex.getMessage() );
          }
        }
      else
        {
        cW.println( "<h2>Error Saving Preferences</h2>" );
        this.reportError( bReq, cW,
          "Error saving preferences to database, "
          + "unknown scope '" + scopeStr + "'" );
        }
      }
    catch ( RequiredException ex )
      {
      this.reportError( bReq, cW,
        "Required field '" + ex.getMessage() + "' is missing" );
      }

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

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

    cW.println( "<h2>Admin Mail Queue Information</h2>" );

    if ( this.mailQueue == null )
      {
      cW.println( "The mail queue has not been established yet.<br>" );
      cW.println( "Try refreshing this page in a few seconds." );
      }
    else
      {
      StringBuffer buf = new StringBuffer();

      this.dateFmt.format
        ( this.mailQueue.getStartTime(), buf, new FieldPosition(0) );

      cW.println( "<p>" );
      cW.println( "<B>Start Time:</B> " );
      cW.println( buf.toString() );
      cW.println( "</p>" );

      buf.setLength(0);
      Date last = this.mailQueue.getLastMailTime();
      if ( last != null )
        this.dateFmt.format( last, buf, new FieldPosition(0) );
      else
        buf.append( "No email has been successfully sent yet." );

      cW.println( "<p>" );
      cW.println( "<B>Mail Transport:</B> " );
      cW.println( this.mailQueue.getTransportName() );
      cW.println( "</p>" );

      cW.println( "<p>" );
      cW.println( "<B>Mail Hostname:</B> " );
      cW.println( this.mailQueue.getMailHostname() );
      cW.println( "</p>" );

      cW.println( "<p>" );
      cW.println( "<B>Administrator Address:</B> " );
      cW.println( this.mailQueue.getAdminAddress() );
      cW.println( "</p>" );

      cW.println( "<p>" );
      cW.println( "<B>Last Mail Time:</B> " );
      cW.println( buf.toString() );
      cW.println( "</p>" );

      cW.println( "<p>" );
      cW.println( "<B>Number Of Messages Mailed:</B> " );
      cW.println( "" + this.mailQueue.getNumMessagesMailed() );
      cW.println( "</p>" );

      cW.println( "<p>" );
      cW.println( "<B>Number Of Messages Failed:</B> " );
      cW.println( "" + this.mailQueue.getNumMessagesFailed() );
      cW.println( "</p>" );

      cW.println( "<p>" );
      cW.println( "<B>Current Number of Messages Queued:</B> " );
      cW.println( "" + this.mailQueue.getQueueSize() );
      cW.println( "</p>" );

      Enumeration enum = this.mailQueue.getMessageExceptions();
      if ( enum.hasMoreElements() )
        {
        cW.println( "<table bgcolor=\"#E0E0E0\">" );
        cW.println( "<tr>" );
        cW.println( "<td bgcolor=\"#C0B0F0\">" );
        cW.println( "<font size=\"+1\"><B>" );
        cW.println( "The MailQueue has seen exceptions" );
        cW.println( "</B></font>" );
        cW.println( "</td>" );
        cW.println( "</tr>" );
        for ( ; enum.hasMoreElements() ; )
          {
          cW.println( "<tr>" );
          cW.println( "<td bgcolor=\"#FFFFFF\">" );
          cW.println( (String) enum.nextElement() );
          cW.println( "</td>" );
          cW.println( "</tr>" );
          }
        cW.println( "</table>" );
        }
      }

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

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

    cW.println( "<h2>BugRat Adjusted Record Ids</h2>" );

    try {
      DBAdmin.adjustSequenceIds();
      this.sendNextIdDetails( bReq, cW );
      }
    catch ( DBIException ex )
      {
      this.log( "ADJUSTING ALL SEQUENCE IDS", ex );
      this.reportError( bReq, cW,
        "Error adjusting the sequence IDs '"
          + ex.getMessage() + "', is sequence table defined?" );
      }

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

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

    cW.println( "<h2>BugRat Record Id Information</h2>" );

    this.sendNextIdDetails( bReq, cW );

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

  private void
  sendNextIdDetails( BugRatRequest bReq, PrintWriter cW )
    throws IOException
    {
    StringBuffer buf = new StringBuffer();

    try {
      Hashtable ids = DBAdmin.getAllSequenceIds();

      cW.println( "<ul> " );

      Enumeration enum = ids.keys();
      for ( ; enum.hasMoreElements() ; )
        {
        String name = (String) enum.nextElement();
        Integer nextSeq = (Integer) ids.get( name );
        cW.println( "<li>" );
        cW.println( "ID Name '" + name + "'&nbsp;" );
        cW.println( "NextSequenceId = " + nextSeq.intValue() );
        cW.println( "</li>" );
        }

      cW.println( "</ul> " );
      }
    catch ( DBIException ex )
      {
      this.reportError( bReq, cW,
        "Error getting sequence IDs '"
          + ex.getMessage() + "', is sequence table defined?" );
      }
    }

  /**
  *
  *  editBug - display a page to allow editing of report
  *
  **/
  private void
  editBug( BugRatRequest bReq, int id )
    throws IOException
    {
    Vector lpV = null;
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Edit Bug #" + id );

    try {
      DBConfig config = this.getDBConfig();

      String bgColor = config.getProperty( "reportServlet.bgColor" );
      if ( bgColor == null ) bgColor = "#E0E0E0";
      String hdrColor = config.getProperty( "reportServlet.hdrColor" );
      if ( hdrColor == null ) hdrColor = bgColor;
      String reqColor = config.getProperty( "reportServlet.reqColor" );
      if ( reqColor == null ) reqColor = "#B0E0B0";

      Bug bug = Bug.getBug( id );

      if ( bug == null )
        {
        throw new DBIException
          ( "Bug #" + id + " can not be found" );
        }

      String projectName = bug.getProject();
      String categoryName = bug.getCategory();
      String subCategoryName = bug.getSubCategory();

      Description desc = bug.getDescription();
      EnvDescription eDesc = bug.getEnvDescription();

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

      cW.print  ( "<INPUT type=\"hidden\" name=\"bugId\" value=\"" );
      cW.print  ( bug.getId() );
      cW.println( "\">" );

      cW.println( "<table width=\"100%\" border=\"3\" cellpadding=\"0\">" );
      cW.println( "<tr bgcolor=\"#E0E0FF\">" );
      cW.print  ( "<td colspan=\"2\" align=\"center\" valign=\"top\" width=\"100%\" >" );

      String title = "Edit&nbsp;Bug&nbsp;&#035;" + bug.getId();
      this.getOutput().sendTableTitle( bReq, cW, title )

      cW.println( "</td>" );
      cW.println( "</tr>" );

      //
      // REQUIRED FIELDS (GREEN AREA) TABLE
      //
      cW.println( "<tr bgcolor=\"" + reqColor + "\">" );
      cW.print  ( "<td align=\"center\" valign=\"top\" width=\"100%\" >" );

      // P/C/S SELECTIONS IN LEFT COLUMN

      cW.println( "<table width=\"100%\">" );

      cW.println( "<tr>" );

      cW.println( "<td width=\"100%\" align=\"left\" valign=\"top\">" );
      cW.print  ( "<strong>" );
      cW.print  ( config.getProjectName( projectName ) );
      cW.print  ( "&nbsp;&#047;&nbsp;" );
      cW.print  ( config.getCategoryName
              ( projectName, categoryName ) );
      cW.print  ( "&nbsp;&#047;&nbsp;" );
      cW.print  ( config.getSubCategoryName
              ( projectName, categoryName, subCategoryName ) );
      cW.println( "</strong>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td width=\"100%\" align=\"left\">" );

      cW.println( "<SELECT NAME=\"pcs\" SIZE=12>" );
                       
      Vector projects = this.getDBConfig().getProjects();
      for ( int pi = 0, psz = projects.size() ; pi < psz ; ++pi )
        {
        Category pc = (Category) projects.elementAt(pi);
        String proj = pc.getProject();
        String selprojectName = pc.getName();
        Vector categories =
          config.getProjectCategories( proj );

        if ( pi > 0 )
          cW.println( "<OPTION VALUE=\"SEP\"> --- </OPTION>" );
               
        for ( int ci = 0, csz = categories.size() ; ci < csz ; ++ci )
          {
          Category cc = (Category) categories.elementAt(ci);
          String cat = cc.getCategory();
          String selcategoryName = cc.getName();
          Vector subcats =
            config.getCategorySubCats( proj, cat );

          for ( int si = 0, ssz = subcats.size() ; si < ssz ;++si )
            {
            Category sc = (Category) subcats.elementAt(si);

            String value =
              sc.getProject() + "/" +
              sc.getCategory() + "/" +
              sc.getSubCategory();

            String name =
              selprojectName + " / "
              selcategoryName + " / " +
              sc.getName();

            if ( bug.getProject().equals( proj )
                && bug.getCategory().equals( cat )
                && bug.getSubCategory().equals
                  ( sc.getSubCategory() ) )
              {
              cW.println
                ( "<OPTION SELECTED VALUE=\""
                  + value + "\">");
              }
            else
              {
              cW.println( "<OPTION VALUE=\"" + value + "\">");
              }

            cW.println( name );
            cW.println( "</OPTION>" );
            }
          }
        }

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

      cW.println( "</td>" );
      cW.println( "</tr>" );

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

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

      // PRIORITY, ET.AL., SELECTIONS IN RIGHT COLUMN

      cW.print  ( "<td align=\"center\" valign=\"top\">" );

      cW.println( "<table>" );

      cW.println( "<tr>" );     
      cW.println( "<td align=\"right\">" );
      cW.println( "Priority" );
      cW.println( "</td>" );
      cW.println( "<td width=\"100%\">" );

      cW.println( "<SELECT NAME=\"priority\" SIZE=\"1\">" );
      lpV = this.getDBConfig().getPriorities();
      for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
        {
        LevelParam lp = (LevelParam) lpV.elementAt(i);

        if ( lp.getId().equals( bug.getPriority() ) )
          cW.println( "<OPTION SELECTED VALUE=\"" + lp.getId() + "\">" );
        else
          cW.println( "<OPTION VALUE=\"" + lp.getId() + "\">" );
        cW.println( lp.getName() );
        cW.println( "</OPTION>" );
        }

      cW.println( "</SELECT>" );
      cW.println( "</td>" );  
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"right\">" );
      cW.println( "Severity" );
      cW.println( "</td>" );   
      cW.println( "<td width=\"100%\">" );

      cW.println( "<SELECT NAME=\"severity\" SIZE=\"1\">" );
      lpV = this.getDBConfig().getSeverities();
      for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
        {
        LevelParam lp = (LevelParam) lpV.elementAt(i);

        if ( lp.getId().equals( bug.getSeverity() ) )
          cW.println( "<OPTION SELECTED VALUE=\"" + lp.getId() + "\">" );
        else
          cW.println( "<OPTION VALUE=\"" + lp.getId() + "\">" );
        cW.println( lp.getName() );
        cW.println( "</OPTION>" );
        }

      cW.println( "</SELECT>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );  

      cW.println( "<tr>" );
      cW.println( "<td align=\"right\">" );
      cW.println( "Class" );
      cW.println( "</td>" );  
      cW.println( "<td width=\"100%\">" );

      cW.println( "<SELECT NAME=\"class\" SIZE=\"1\">" );
      lpV = this.getDBConfig().getClasses();
      for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
        {
        LevelParam lp = (LevelParam) lpV.elementAt(i);

        if ( lp.getId().equals( bug.getClass() ) )
          cW.println( "<OPTION SELECTED VALUE=\"" + lp.getId() + "\">" );
        else
          cW.println( "<OPTION VALUE=\"" + lp.getId() + "\">" );
        cW.println( lp.getName() );
        cW.println( "</OPTION>" );
        }

      cW.println( "</SELECT>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"right\">" );
      cW.println( "Confidence" );
      cW.println( "</td>" );
      cW.println( "<td width=\"100%\">" );

      cW.println( "<SELECT NAME=\"confidence\" SIZE=\"1\">" );
      lpV = this.getDBConfig().getConfidences();
      for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
        {
        LevelParam lp = (LevelParam) lpV.elementAt(i);

        if ( lp.getId().equals( bug.getConfidence() ) )
          cW.println( "<OPTION SELECTED VALUE=\"" + lp.getId() + "\">" );
        else
          cW.println( "<OPTION VALUE=\"" + lp.getId() + "\">" );
        cW.println( lp.getName() );
        cW.println( "</OPTION>" );
        }

      cW.println( "</SELECT>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"right\">" );
      cW.println( "State" );
      cW.println( "</td>" );  
      cW.println( "<td width=\"100%\">" );

      cW.println( "<SELECT NAME=\"state\" SIZE=\"1\">" );
      lpV = this.getDBConfig().getStates();
      for ( int i = 0, sz = lpV.size() ; i < sz ; ++i )
        {
        LevelParam lp = (LevelParam) lpV.elementAt(i);

        if ( lp.getId().equals( bug.getState() ) )
          cW.println( "<OPTION SELECTED VALUE=\"" + lp.getId() + "\">" );
        else
          cW.println( "<OPTION VALUE=\"" + lp.getId() + "\">" );
        cW.println( lp.getName() );
        cW.println( "</OPTION>" );
        }

      cW.println( "</SELECT>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"right\">" );
      cW.println( "Responsible" );
      cW.println( "</td>" );
      cW.println( "<td width=\"100%\">" );

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

      this.getOutput().sendPersonSelector
        ( bReq, cW, bug.getResponsible(), -1,
          "responsible", notAssgnOption, null );

      cW.println( "</td>" );
      cW.println( "</tr>" );

      Description bugDesc = bug.getDescription();
      EnvDescription envDesc = bug.getEnvDescription();

      cW.println( "<tr>" );
      cW.println( "<td align=\"right\">" );
      cW.println( "Project&nbsp;Release" );
      cW.println( "</td>" );
      cW.println( "<td>" );
      cW.print  ( "<INPUT type=\"text\" size=\"16\"" );
      cW.print  ( " name=\"release\" value=\"" );
      cW.print  ( (envDesc == null) ? "" : envDesc.getRelease() );
      cW.println( "\">" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"right\">" );
      cW.println( "JVM&nbsp;Release" );
      cW.println( "</td>" );
      cW.println( "<td>" );
      cW.print  ( "<INPUT type=\"text\" size=\"16\"" );
      cW.print  ( " name=\"envjvm\" value=\"" );
      cW.print  ( (envDesc == null) ? "" : envDesc.getJVM() );
      cW.println( "\">" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"right\">" );
      cW.println( "OS" );  
      cW.println( "</td>" );
      cW.println( "<td>" );
      cW.print  ( "<INPUT type=\"text\" size=\"16\"" );
      cW.print  ( " name=\"envos\" value=\"" );
      cW.print  ( (envDesc == null) ? "" : envDesc.getOS() );
      cW.println( "\">" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"right\">" );
      cW.println( "OS&nbsp;Release" );
      cW.println( "</td>" );
      cW.println( "<td>" );
      cW.print  ( "<INPUT type=\"text\" size=\"16\"" );
      cW.print  ( " name=\"envosrel\" value=\"" );
      cW.print  ( (envDesc == null) ? "" : envDesc.getOSRelease() );
      cW.println( "\">" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"right\">" );
      cW.println( "Platform" );
      cW.println( "</td>" );
      cW.println( "<td>" );
      cW.print  ( "<INPUT type=\"text\" size=\"16\"" );
      cW.print  ( " name=\"envplat\" value=\"" );
      cW.print  ( (envDesc == null) ? "" : envDesc.getPlatform() );
      cW.println( "\">" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      // END of Priority table...
      cW.println( "</table>" );

      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"center\" colspan=\"2\" width=\"100%\">" );
      cW.println( "<table border=\"0\" cellspacing=\"0\"" );
      cW.println( " cellpadding=\"3\" width=\"100%\">" );

/* // Email/Name should be kept the same, i.e., not edited
      cW.println( "<tr bgcolor=\"" + reqColor + "\">" );
      cW.println( "<td align=\"left\">" );
      cW.println( "<strong>Your Email Address:</strong>" );
      cW.println( "</td>" );
      cW.println( "<td align=\"left\">" );
      cW.println( "<strong>Your Full Name:</strong>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr bgcolor=\"" + reqColor + "\">" );
      cW.println( "<td align=\"left\">" );
      cW.println( "<INPUT type=\"text\" size=\"36\" name=\"emailaddr\">" );
      cW.println( "</td>" );
      cW.println( "<td align=\"left\">" );
      cW.println( "<INPUT type=\"text\" size=\"36\" name=\"fullname\">" );
      cW.println( "</td>" );
      cW.println( "</tr>" );
*/

      cW.println( "<tr bgcolor=\"" + reqColor + "\">" );
      cW.println( "<td align=\"left\" colspan=\"2\">" );
      cW.println( "<strong>Bug Synopsis (required):</strong>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );
      cW.println( "<tr bgcolor=\"" + reqColor + "\">" );
      cW.println( "<td align=\"left\" colspan=\"2\">" );
      cW.print  ( "<INPUT type=\"text\" size=\"72\"" );
      cW.print  ( " name=\"synopsis\" value=\"" );
      cW.print  ( (bugDesc == null) ? "" : bugDesc.getSynopsis() );
      cW.println( "\">" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"left\" colspan=\"2\">" );
      cW.println( "<strong>Bug Description (optional):</strong>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );
      cW.println( "<tr>" );
      cW.println( "<td align=\"left\" colspan=\"2\">" );
      cW.print  ( "<TEXTAREA name=\"bugdesc\" rows=\"12\" cols=\"60\">" );
      cW.print  ( (bugDesc == null) ? "" : bugDesc.getDescription() );
      cW.println( "</TEXTAREA>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"left\" colspan=\"2\">" );
      cW.println( "<strong>Additional Environment Description (optional):</strong>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );
      cW.println( "<tr>" );
      cW.println( "<td align=\"left\" colspan=\"2\">" );
      cW.print  ( "<TEXTAREA name=\"envdesc\" rows=\"3\" cols=\"60\">" );
      cW.print  ( (envDesc == null) ? "" : envDesc.getDescription() );
      cW.println( "</TEXTAREA>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );   

      cW.println( "<tr>" );
      cW.println( "<td align=\"left\" colspan=\"2\">" );
      cW.println( "<strong>How To Reproduce (optional):</strong>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );
      cW.println( "<tr>" );
      cW.println( "<td align=\"left\" colspan=\"2\">" );
      cW.print  ( "<TEXTAREA name=\"repro\" rows=\"6\" cols=\"60\">" );

      if ( bug.getReproDescription() != null )
        cW.print ( bug.getReproDescription().getSynopsis() );

      cW.println( "</TEXTAREA>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td align=\"left\" colspan=\"2\">" );
      cW.println( "<strong>Known Work Around (optional):</strong>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );
      cW.println( "<tr>" );
      cW.println( "<td align=\"left\" colspan=\"2\">" );
      cW.print  ( "<TEXTAREA name=\"around\" rows=\"6\" cols=\"60\">" );

      if ( bug.getAroundDescription() != null )
        cW.print( bug.getAroundDescription().getSynopsis() );

      cW.println( "</TEXTAREA>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "</table>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );

      cW.println( "<tr>" );
      cW.println( "<td colspan=\"2\" width=\"100%\" align=\"center\">" );
      cW.println( "<table width=\"100%\" cellpadding=\"8\">" );

      cW.println( "<table width=\"100%\" cellpadding=\"8\">" );
      cW.println( "<tr>" );
      cW.println( "<td align=\"center\">" );
      cW.println( "<INPUT type=\"submit\" name=\"submit\"" );
      cW.println( " value=\"Submit Bug Revision\">" )
      cW.println( "</td>" );
      cW.println( "<td align=\"center\">" );
      cW.println( "<INPUT type=\"reset\" name=\"reset\"" );
      cW.println( " value=\"Clear Bug Revision\">" );
      cW.println( "</td>" );
      cW.println( "</tr>" );
      cW.println( "</table>" );  

      cW.println( "</td>" );
      cW.println( "</tr>" );
      cW.println( "</table>" );
      cW.println( "</center>" );
      cW.println( "</form>" );
      }
    catch ( DBIException ex )
      {
      this.reportError
        ( bReq, cW,
          "Could not retrieve Bug #"
            + id + ", " + ex.getMessage() );
      }

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


  /**
   *
     * processEditBug - process the posting of an edited bug
     *
     *
     */
    private void
    processEditBug( 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 - Edit Bug" );
            
    try {
      String value;
      String[] valAry = bReq.getParameterValues( "bugId" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "bugID" );

      //
      // V A L I D A T E
      // ( don't validate name/email, though since it's an edit )
      //

      String bugIdStr = valAry[0];
      valAry = bReq.getParameterValues( "pcs" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException
          ( "project/category/subcat" );

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

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

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

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

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

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

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

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

      String relStr = valAry[0];
      valAry = bReq.getParameterValues( "envjvm" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "environment JVM release" );

      String jvmStr = valAry[0];
      valAry = bReq.getParameterValues( "envos" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "environment OS" );

      String osStr = valAry[0];
      valAry = bReq.getParameterValues( "envosrel" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "environment OS release" );

      String osRelStr = valAry[0];
      valAry = bReq.getParameterValues( "envplat" );
      if ( this.isEmptyParameter( valAry ) )
        throw this.new RequiredException( "environment platform" );

      String platStr = valAry[0];
      valAry = bReq.getParameterValues( "bugdesc" );
      String bugDescStr = ( valAry == null ? null : valAry[0] );
               
      valAry = bReq.getParameterValues( "envdesc" );
      String envDescStr = ( valAry == null ? null : valAry[0] );

      valAry = bReq.getParameterValues( "around" );
      String aroundDescStr = ( valAry == null ? null : valAry[0] );
      if ( aroundDescStr != null && aroundDescStr.length() == 0 )
        aroundDescStr = null;

      valAry = bReq.getParameterValues( "repro" );
      String reproDescStr = ( valAry == null ? null : valAry[0] );
      if ( reproDescStr != null && reproDescStr.length() == 0 )
        reproDescStr = null;

      //
      // P R O C E S S
      //
      int bugId = Integer.parseInt( bugIdStr );
       
      Bug bug = Bug.getBug( bugId );

      Bug saveBug = (Bug) bug.clone();

      String[] cats = this.splitString( pcsStr, "/" );

      bug.setProject( cats[0] );
      bug.setCategory( cats[1] );
      bug.setSubCategory( cats[2] );

      bug.setConfidence( confStr );
      bug.setPriority( priStr );
      bug.setSeverity( sevStr );
      bug.setBugClass( clsStr );

      this.changeState( bug, stateStr );

      Integer responsibleInt = new Integer ( personStr );
      bug.setResponsible( responsibleInt.intValue() );

      Description bugDesc = bug.getDescription();
      if ( bugDesc == null )
        {
        bugDesc = Description.getNewDescription();
        bug.setDescription( bugDesc );
        }

      bugDesc.setSynopsis( synStr );
      bugDesc.setDescription( bugDescStr );

      EnvDescription eDesc = bug.getEnvDescription();
      if ( eDesc == null )
        {
        eDesc = Description.getNewEnvDescription();
        bug.setEnvDescription( eDesc );
        }

      eDesc.setRelease( relStr );
      eDesc.setJVM( jvmStr );
      eDesc.setOS( osStr );
      eDesc.setOSRelease( osRelStr );
      eDesc.setPlatform( platStr );
      eDesc.setDescription( envDescStr );

      if ( reproDescStr != null )
        {
        Description repro = bug.getReproDescription();
        if ( repro != null )  
          {
          repro.setDescription( reproDescStr );
          }
        else
          {
          repro = Description.getNewDescription();
          repro.setSynopsis( "Reproduce" );
          repro.setDescription( reproDescStr );
          bug.setReproDescription( repro );
          }
        }

      if ( aroundDescStr != null )
        {
        Description around = bug.getAroundDescription();
        if ( around != null )
          {
          around.setDescription( aroundDescStr );
          }
        else
          {
          around = Description.getNewDescription();
          around.setSynopsis( "Work Around" );
          around.setDescription( aroundDescStr );
          bug.setAroundDescription( around );
          }
        }

      bug.commit();

      int actorId = this.getUserId( bReq );
      if ( actorId == 0 )
        {
        this.log
          ( "WARNING getUserId() returned no actor "
            + "for edit bug #" + bugId );
        }

      // UNDONE We are not handling the case of "no changes" very well!

      Description modDesc = Description.getNewDescription();

      modDesc.setMimeType( "text/plain" );
      modDesc.setSynopsis
        ( "edit bug #" + bugId
          + " by person #" + actorId );

      StringBuffer buf = new StringBuffer();
      bug.getDeltaDescription( saveBug, "", buf, this.getDBConfig() );
      if ( buf.length() == 0 )
        {
        buf.append( "There appear to be no modifications." );
        }

      modDesc.setDescription( buf.toString() );

      modDesc.commit();

      BugRatAction action =
        BugRatAction.getNewAction( ACTION_MODIFY );

      action.setActorId( actorId );
      action.setActionTime( new Date() );
      action.setTarget( TARGET_BUG );
      action.setTargetId( bugId );
      action.setArgOne( modDesc.getId() );
      action.setArgTwo( 0 );
      action.setComment( modDesc.getSynopsis() );

      action.commit();

      try {
        Person p = Person.getPerson( bug.getResponsible() );
        if ( p != null )
          {
          this.log
            ( "Queueing Edit Bug Email To: '" +p.getEmail()+ "'" );

          this.mailQueue.addMailJob
            ( modDesc.getSynopsis(),
              modDesc.getDescription(),
                p.getEmail(), null );
          }
        else
          {
          this.log
            ( "ERROR Edit Bug could not get responsible person "
              + "to email to '" + bug.getResponsible() + "'" );
          }
        }
      catch ( MessagingException ex )
        {
        this.log
          ( "ERROR Failed sending mail notice for edit bug #"
            + bugId, ex );
        }

      // Generate HTML page
      this.getOutput().showBug( bReq, cW, bug.getId() );
      }
    catch ( DBIException ex )
      {
      this.log( "Processing EditBug", ex );

      cW.println( "<h2> Error Processing Bug </h2>" );
      cW.println( "<table border=\"5\" cellpadding=\"5\">" );
      cW.println( "<tr>" );
      cW.println( "<td bgcolor=\"#FFFFFF\">" );
      cW.println( "An error occurred trying to process your" );
      cW.println( "BugRat bug. The bug was not updated," );
      cW.println( "or was partially updated and needs to be" );
      cW.println( "backed out. Please report the following" );
      cW.println( "information to the BugRat Administrator." );
      cW.println( "</td>" );
      cW.println( "</tr>" );
      cW.println( "<tr>" );
      cW.println( "<td bgcolor=\"" + errColor + "\">" );
      cW.println( "<strong>SQLException:</strong><p>" );
      cW.print  ( "<PRE>" );
      cW.println( ex.getMessage() );
      cW.println( "</PRE>" );
      cW.println( "</td>" );
      cW.println( "</tr>" );  
      cW.println( "</table>" );
      }
    catch ( RequiredException ex )
      // UNDONE - check for bad ID exception
      {
      this.log
        ( "Missing Required Field '" + ex.getMessage() + "'", ex );

      cW.println( "<h2> Missing Required Field or Bad ID</h2>" );
      cW.println( "You have a missing field that is required." );
      cW.println( "Please use the 'Back' key in your browser" );
      cW.println( "to go back to the previous page, which will" );
      cW.println( "be your partially completed bug form." );
      cW.println( "Fill in the missing field and resubmit." );  
      cW.println( "<p>" );
      cW.println( "The missing field was <strong> '" );
      cW.println( ex.getMessage() + "'.</strong>" );
      }

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


  private boolean
  isReportLinkedToBug( int repId, int bugId )
    {
    boolean result = false;
    DBIManager dbiMgr = DBIManager.getInstance();

    try {
      result =
        dbiMgr.getReportDBI().isReportLinkedToBug( repId, bugId );
      }
    catch ( DBIException ex )
      {
      ex.printStackTrace( System.err );
      result = false;
      }
   
    return result;
    }

  private void
  linkReportToBug( int repId, int bugId )
    throws DBIException
    {
    DBIManager dbiMgr = DBIManager.getInstance();
    dbiMgr.getReportDBI().linkReport( repId, bugId );
    }

  /** LinkReport
  *
  * This function determines which project a report belongs to
  * then lists the bugs in that project. One is selected, and
  * the report is linked to that bug in the repbug table
  *
  **/

  private void
  linkReport( BugRatRequest bReq, int repId )
    throws DBIException, IOException
    {
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader
      ( bReq, cW, "BugRat - Link Report #" + repId + " To A Bug" );

    cW.print  ( "<h2>Select A Bug To Link Report " );
    cW.print  ( repId );
    cW.println( " To</h2>" );

    if ( this.debug )
      this.log( "BugRatAdmin.linkReport: " + repId );

    Report report = Report.getReport( repId );

    String matchstring =
      "SELECT * from bug " +
      "WHERE project = '" + report.getProject() + "'";

    Vector bugvector = Bug.matchBugs( matchstring );

    cW.print  ( "<FORM method=\"POST\" action=\"" );
    cW.print  ( bReq.getServletPath() );
    cW.println( "/LinkReportPost\">" );
    cW.println( "Report " + repId + " Synopsis:<br><br>");
    cW.println( report.getDescription().getSynopsis() );
    cW.println( "<br><br><br>" );
    cW.print  ( "<h3>Bugs in project \"" );
    cW.print  ( report.getProject() );
    cW.println( "\":<br></h3>" );
    cW.print  ( "<INPUT type=\"hidden\"" );
    cW.println( "       name=\"report\" value=\"" + repId + "\">" );
    cW.println( "<SELECT name=\"bug\" size=\"10\">" );

    if ( this.debug )
      this.log( "#bugs in match = " + bugvector.size());

    for ( int i = 0, sz = bugvector.size() ; i < sz ; ++i )
      {
      Bug bug = ( Bug ) bugvector.elementAt( i );
      String bugdesc =
        bug.getDescription().getSynopsis();

      if ( this.debug )
        this.log( bugdesc );

      cW.print  ( "<OPTION value=\"" + bug.getId() + "\">" );
      cW.println( bug.getId() + ":" + bugdesc );
      }

    cW.println( "<BR>");
    cW.println( "<OPTION value=\"0\"> Convert To New Bug" );

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

    cW.println( "<br>" );

    cW.print  ( "<INPUT type=\"submit\"" );
    cW.println( "       name=\"submit\" value=\"Link Report to Bug\">" );

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

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

  private void
  processLinkReportPost( BugRatRequest bReq )
    throws IOException
    {
    Bug bug = null;
    PrintWriter cW = bReq.getHTMLWriter();
    this.sendCommonHeader( bReq, cW, "BugRat - Link Report To A Bug" );

    // UNDONE - clean up this code!
    String repIdStr = bReq.getParameterValues( "report" )[0];
    int repId = 0;
    try { repId = Integer.parseInt( repIdStr ); }
    catch ( NumberFormatException ex )
      {
      throw new IOException
        ( "can not parse report ID '" + repIdStr + "'" );
      }

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

      this.log
        ( "BugRatAdmin.processLinkReport: repId = "
          + repId + ", bugId = " + bugIdStr );

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

      try {
        boolean sendNotice = false;
        Report rep = Report.getReport( repId );

        if ( bugId < 0 )
          {
          this.getOutput().reportError( bReq, cW,
            "INTERNAL ERROR, could not parse bug ID '"
            + bugIdStr + "'" );
          }
        else if ( bugId > 0 )
          {
          bug = Bug.getBug( bugId );
          if ( ! this.isReportLinkedToBug( repId, bugId ) )
            {
            this.linkReportToBug( repId, bugId );
            sendNotice = true;
            }

          this.getOutput().showBug( bReq, cW, bugId );
          }
        else
          {
          Bug newbug = (Bug) Bug.getNewBug();
          bugId = newbug.getId();

          this.linkReportToBug( repId, bugId );

          // Begin copying information
          newbug.setSource( rep.getSource() );
          newbug.setOpenDate( new Date() );
          newbug.setCloseDate( null );
          newbug.setSeverity( rep.getSeverity() );
          newbug.setSourceId( rep.getSourceId() );
          newbug.setConfidence( rep.getConfidence() );
          newbug.setPriority( rep.getPriority() );
          //
          // REVIEW It seems that all new bug reports should
          //        start out as open, regardless of the state
          //        of the report.
          // newbug.setState( rep.getState() );
          //
          newbug.setState( STATE_OPEN );
          newbug.setBugClass( rep.getReportClass() );
          newbug.setProject( rep.getProject() );
          newbug.setCategory( rep.getCategory() );
          newbug.setSubCategory( rep.getSubCategory() );

          int respId = rep.getResponsible();
          if ( respId == 0 )
            {
            // If the report was not assigned to anyone, then
            // assign this bug to the person linking it...
            respId = this.getUserId( bReq );
            }

          newbug.setResponsible( respId );

          Description bugdesc = newbug.getDescription();
          Description repdesc = rep.getDescription();

          bugdesc.setSynopsis( repdesc.getSynopsis() );
          bugdesc.setEmailId( repdesc.getEmailId() );
          bugdesc.setURL( repdesc.getURL() );
          bugdesc.setDescription( repdesc.getDescription() );
          bugdesc.setMimeType( repdesc.getMimeType() );

          EnvDescription bugenvdesc = newbug.getEnvDescription();
          EnvDescription repenvdesc = rep.getEnvDescription();

          bugenvdesc.setRelease( repenvdesc.getRelease() );
          bugenvdesc.setJVM( repenvdesc.getJVM() );
          bugenvdesc.setOS( repenvdesc.getOS() );
          bugenvdesc.setOSRelease( repenvdesc.getOSRelease() );
          bugenvdesc.setPlatform( repenvdesc.getPlatform() );
          bugenvdesc.setDescription( repenvdesc.getDescription() );

          Description repReproDesc = rep.getReproDescription();
          if ( repReproDesc != null )
            {
            Description bugReproDesc = Description.getNewDescription();
            bugReproDesc.setSynopsis( repReproDesc.getSynopsis() );
            newbug.setReproDescription( bugReproDesc );
            }
          else
            {
            newbug.setReproDescription( null );
            }

          Description repAroundDesc = rep.getAroundDescription();
          if ( repAroundDesc != null )
            {
            Description bugAroundDesc = Description.getNewDescription();
            bugAroundDesc.setSynopsis( repAroundDesc.getSynopsis() );
            newbug.setAroundDescription( bugAroundDesc );
            }
          else
            {
            newbug.setAroundDescription( null );
            }

          newbug.commit();

          // Change the report's state to 'L'inked.
          rep.setState( STATE_LINKED );
          rep.commit();

          sendNotice = true;
          bug = newbug;

          this.getOutput().showBug( bReq, cW, bugId );
          }

        if ( sendNotice )
          {
          BugRatAction action =
            BugRatAction.getNewAction( ACTION_LINK );

          int actorId = this.getUserId( bReq );
          if ( actorId == 0 )
            {
            this.log
              ( "WARNING getUserId() returned no actor "
                + "for action #" + action.getId() );
            }

          action.setActorId( actorId );
          action.setActionTime( new Date() );
          action.setTarget( TARGET_REPORT );
          action.setTargetId( repId );
          action.setArgOne( bugId );
          action.setArgTwo( 0 );
          action.setComment
            ( "linked report #" + repId
              + " to bug #" + bugId
              + " by person #" + actorId );

          action.commit();

          try {
            String address = null;

            String subject =
                "BugRat Report #" + repId
                + " was linked to Bug #" + bugId;

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

            pW.println
              ( "BugRat Report #" + repId
                + " was linked to Bug #" + bugId + "." );

            Person p = Person.getPerson( rep.getResponsible() );
            if ( p == null )
              {
              address = this.dbConfig.getAdminEmailAddress();
              pW.println( "" );
              pW.println( "*** NOTE Report #" + repId
                    + " has no responsible person." );
              pW.println
                ( "*** Mailed to the BugRat administrator, as determined" );
              pW.println
                ( "*** by the database property 'global.adminAddress'." );
              pW.println( "" );
              }
            else
              {
              address = p.getEmail();
              }

            pW.println( "" );
            pW.println( "=== Bug Details ============================" );

            this.bugFmt.format( bug, bReq, pW, "text/plain", true );

            pW.println( "" );
            pW.println( "=== Report Details ============================" );

            this.reportFmt.format( rep, bReq, pW, "text/plain", true );

            pW.close();

            this.mailQueue.addMailJob
              ( subject, sW.toString(), address, null );
            }
          catch ( MessagingException ex )
            {
            this.log
              ( "Failed sending mail notice for report #"
                + repId + " link to bug #" + bugId, ex );
            }
          }
        }
      catch ( DBIException ex )
        {
        this.log( "LINKING REPORT", ex );
        this.reportError
          ( bReq, cW,
          "Could not link Report #"
          + repId + " to the bug, " + ex.getMessage() );
        }
      }

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

  private void
  changeState( Bug bug, String stateStr )
    {
    //
    // UNDONE
    // If the state changes to !CLOSED, setCloseDate(null)!
    //
    if ( stateStr.equals( STATE_OPEN ) )
      {
      // Open Bug
      if ( ! bug.getState().equals( stateStr ) )
        {
        Date now = new Date();
        bug.setOpenDate( now );
        }

      bug.setState( stateStr );
      }
    else if ( stateStr.equals( STATE_CLOSED ) )
      {
      // Close Bug
      if ( ! bug.getState().equals( stateStr ) )
        {
        Date now = new Date();
        bug.setCloseDate( now );
        }

      bug.setState( stateStr );
      }
    else
      {
      bug.setState( stateStr );
      }
    }

  }

TOP

Related Classes of org.gjt.bugrat.servlet.BugRatAdmin

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.