Subversion Repositories DevTools

Rev

Rev 908 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.erggroup.buildtool.ripple;

import org.apache.log4j.Logger;

import com.erggroup.buildtool.smtp.Smtpsend;

import java.sql.SQLException;
import java.util.Iterator;
import java.util.Vector;

/**entity class holding build exclusion data
 */
public class BuildExclusion
{
  /**Logger
   * @attribute
   */
  private static final Logger mLogger = Logger.getLogger(BuildExclusion.class);

  /**identifier
   * @attribute
   */
  private int mId;

  /**root identifier
   * @attribute
   */
  private int mRootId;

  /**root cause
   * @attribute
   */
  private String mRootCause;

  /**test build instruction
   * @attribute
   */
  private int mTestBuildInstruction;

  /**in terms of the mChangeType Package field,
   * when true indicates the package has not changed, its dependencies potentially have
   * in terms of the mRippleField Package field,
   * when true indicates the build number will be incremented
   * @attribute
   */
  private boolean mProcessed = false;

  /**constructor
   */
  public BuildExclusion(int identifier, int rootIdentifier, String rootCause, int testBuildInstruction )
  {
    mLogger.debug("BuildExclusion");
    mId = identifier;
    mRootId = dealWithNullRootPvId(identifier, rootIdentifier);
    mRootCause = rootCause;
    mTestBuildInstruction = testBuildInstruction;
  }

  /**sets mProcessed true
   */
  void process()
  {
    mLogger.debug("process " + mId);
    mProcessed = true;
  }

  /**accessor
   */
  boolean isProcessed()
  {
    mLogger.debug("isProcessed " + mId);
    mLogger.info("isProcessed returned " + mProcessed);
    return mProcessed;
  }

  /**return true if all attributes match
   */
  boolean compare( int identifier, int rootIdentifier, String rootCause)
  {
    mLogger.debug("compare " + mId + ", " + identifier + ", " + rootIdentifier + ", " + rootCause);
    boolean retVal = false;
    rootIdentifier = dealWithNullRootPvId(identifier, rootIdentifier);
    
    if ( mRootCause == null )
    {
      if ( mId == identifier && mRootId == rootIdentifier && rootCause == null )
      {
        retVal = true;
      }
    }
    else
    {
      if ( mId == identifier && mRootId == rootIdentifier && mRootCause.compareTo(rootCause) == 0 )
      {
        retVal = true;
      }
    }
    
    mLogger.info("compare returned " + retVal);
    return retVal;
  }
  
  /**return true if mId attribute matches
   */
  boolean compare( int identifier )
  {
    mLogger.debug("compare " + mId + ", " + identifier);
    boolean retVal = false;
    
    if ( mId == identifier )
    {
      retVal = true;
    }
    
    mLogger.info("compare returned " + retVal);
    return retVal;
  }
  
  /**runs exclude from build
   */
  void excludeFromBuild( ReleaseManager rm, int rtag_id ) throws SQLException, Exception
  {
    mLogger.debug("excludeFromBuild " + mId);
    Integer id = mId;
    Integer rootId = mRootId;
    Integer r = rtag_id;
    // a null version and log file is passed to oracle
    // the planned version is only needed to remove a planned version from the planned version table
    // the ripple engine does not get this far ie it excludes pvs before claiming a version
    // this is the one instance where an existing build failure must be superceded in the database
    rm.excludeFromBuild(id.toString(), null, r.toString(), rootId == -1 ? null : rootId.toString(), mRootCause, null, true, mTestBuildInstruction);
  }
  
  /**runs exclude from build
   */
  void includeToBuild( ReleaseManager rm, int rtag_id ) throws SQLException, Exception
  {
    mLogger.debug("includeToBuild " + mId);
    Integer id = mId;
    Integer r = rtag_id;
    // a null version and log file is passed to oracle
    // the planned version is only needed to remove a planned version from the planned version table
    // the ripple engine does not get this far ie it excludes pvs before claiming a version
    rm.includeToBuild(id.toString(), r.toString());
  }
  
  /**
   * return true if the root_pv_id is null (-1) or the it points to a pv_id in the collection
   */
  boolean isRelevant(Vector<BuildExclusion> buildExclusionCollection)
  {
    mLogger.debug("isRelevant " + mId);
    boolean retVal = false;
    
    if ( mRootId == -1 )
    {
      retVal = true;
    }
    else
    {
      for (Iterator<BuildExclusion> it = buildExclusionCollection.iterator(); it.hasNext(); )
      {
        BuildExclusion buildExclusion = it.next();
        
        if ( buildExclusion.isRelevant( mRootId ) )
        {
          retVal = true;
          break;
        }
      }
    }

    mLogger.info("isRelevant " + mId + " returned " + retVal);
    return retVal;
  }

  /**
   * return true if the root_pv_id is null (-1)
   */
  boolean isARootCause()
  {
    mLogger.debug("isARootCause " + mId);
    boolean retVal = false;
    
    if ( mRootId == -1 )
    {
      retVal = true;
    }

    mLogger.info("isARootCause " + mId + " returned " + retVal);
    return retVal;
  }

  /**
   * return true if id matches mId
   */
    private boolean isRelevant(int id)
    {
      mLogger.debug("isRelevant " + mId + ", " + id);
      boolean retVal = false;
      
      if ( mId == id )
      {
        retVal = true;
      }

      mLogger.info("isRelevant " + mId +  ", " + id + " returned " + retVal);
      return retVal;
    }

  /**
    * user friendly
    * does not trigger a storm of emails because a low level package has a build issue
    * limit the emails to the low level package
    * i.e. only send email if the build exclusion has a null root pv id
    * and a non null root cause
   */
    public void email(Vector<Package>packageCollection, String mailServer, String mailSender, String release, ReleaseManager releaseManager) throws SQLException, Exception
    {
      mLogger.debug("email " + mId);
      if ( mRootId == -1 && mRootCause != null )
      {
        // this is a direct build failure with a ripple engine induced root cause
        // send email
        Package pkg = null;
  
        for (Iterator<Package> it = packageCollection.iterator(); it.hasNext(); )
        {
          Package p = it.next();
          
          if ( compare(p.mId) )
          {
            pkg = p;
            break;
          }
        }
        
        if ( pkg != null )
        {
          // has the pkg any owners
          String owners = pkg.emailInfoNonAntTask();
          
          if ( owners != null )
          {
            String body =
            "Release: " + release + "<p>" +
            "Package: " + pkg.mName + "<p>" + 
            "Cause: " + mRootCause + "<p><hr>";
            
            try
            {
              Smtpsend.send(
              mailServer,       // mailServer
              mailSender,       // source
              owners,           // target
              null,             // cc
              null,             // bcc
              "BUILD FAILURE on package " + pkg.mName, // subject
              body,             // body
              null              // attachment
              );
            }
            catch( Exception e )
            {
            }
          }
          
          // having sent the build failure email, complete a test build if applicable
          // this ensures the test build instruction is not processed indefinitely
          // as there is no notion of excluding test builds
          pkg.completeTestBuild(mailServer, mailSender, releaseManager, release, false);
        }
      }
    }
    
    /**
     * hides how a root_pv_id is treated
     * only use root_pv_id if not equal to the pv_id
     * this is to drive a direct build exclusion in the release manager
    */
    private int dealWithNullRootPvId( int pvId, int rootPvId )
    {
      int retVal = rootPvId;
      
      if ( pvId == rootPvId )
      {
        // force a null root_pv_id in the database
        retVal = -1;
      }
      
      return retVal;
    }
}