Rev 7033 | Blame | Compare with Previous | Last modification | View Log | RSS feed
package com.erggroup.buildtool.ripple;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.erggroup.buildtool.smtp.CreateUrls;import com.erggroup.buildtool.smtp.Smtpsend;import java.sql.SQLException;import java.util.ArrayList;import java.util.Iterator;/**entity class holding build exclusion data*/public class BuildExclusion{/**Logger* @attribute*/private static final Logger mLogger = LoggerFactory.getLogger(BuildExclusion.class);/**The pvid of the package being excluded* @attribute*/private int mId;/**root identifier is the PVID of the package that is causing the exclusion* A NULL value indicates that this entry(package) is the root cause of the of an exclusion* @attribute*/private int mRootId;/**root cause* If not NULL, then this is the reason this package is being excluded* @attribute*/private String mRootCause;/**test build instruction* @attribute*/private int mTestBuildInstruction;/**Indicates that the item has been processed* @attribute*/private boolean mProcessed = false;/** Indicates that the entry was imported from the database* Used to determine entries that are no-longer needed and can be removed from the database* Really only applied to indirect exclusions where the reason for the exclusion no longer exists**/private boolean mImported = false;/**constructor* @param identifier - pvid of the package being excluded* @param rootIdentifier - pvid of the root package causing the exclusion. May be null* @param rootCause - Short (< 50 Char) string explaining the cause* @param testBuildInstruction - Indicates a text build instruction*/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 setProcessed(){mLogger.debug("process {}", mId);mProcessed = true;}/** @returns true if the item has been marked as processed.* Appears to be an indication that the entry has been superseded.*/boolean isProcessed(){mLogger.debug("isProcessed {}", mId);mLogger.info("isProcessed returned {}", mProcessed);return mProcessed;}/** Flag as an imported entry* Used to detect indirect exclusions that are no longer valid*/void setImported(){mImported = true;}/** Test the state of the imported flag**/boolean isImported(){return mImported;}/*** Compare this item with parameters* @param identifier - Related Package identifier* @param rootIdentifier - Package identifier of root cause* @param rootCause - Root cause string. May be null* @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;}/*** @param identifier - identifier to match* @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* Assumes that a connection to RM has been established** @param rm Release Manager instance* @param rtagId Rtag Id we are working against*/void excludeFromBuild( ReleaseManager rm, int rtagId ) throws SQLException, Exception{mLogger.debug("excludeFromBuild {}", mId);// 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 superseded in the databaserm.excludeFromBuild(true,mId,null,rtagId,mRootId == -1 ? null : String.valueOf(mRootId),mRootCause,null,true, (mTestBuildInstruction > 0) );}/**runs include to build* Include a previously excluded package-version back into the build set** @param rm Release Manager instance* @param rtagId Rtag Id we are working against*/void includeToBuild( ReleaseManager rm, int rtagId ) throws SQLException, Exception{mLogger.debug("includeToBuild {}", mId);rm.includeToBuild(mId, rtagId);}/*** Match this items id against that provided* @param id - Id to match* @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 {},{}, returned {}", mId, id, retVal);return retVal;}/*** Match this items mRootId against the id's provided in a collection* ie: Determine if any items in the collection are the root cause of this items* ie: Used to determine if an entry is for an indirectly excluded package where* the root cause of the exclusion has been removed.** @param buildExclusionCollection - Collection to be processed* @return false: Indirectly excluded package whose root cause no longer exists*/boolean isRelevant(ArrayList<BuildExclusion> buildExclusionCollection){mLogger.debug("isRelevant {}", mId);boolean retVal = false;if ( mRootId == -1 ) {retVal = true;} else if(mRootId == -2 ) {// Excluded due to Ripple Stop// Will be recalculated so its not relevantretVal = false;} else {retVal = false;for (Iterator<BuildExclusion> it = buildExclusionCollection.iterator(); it.hasNext(); ){BuildExclusion buildExclusion = it.next();if ( buildExclusion.isRelevant( mRootId ) ){retVal = true;break;}}}mLogger.info("isRelevant {} returned {}", mId, retVal);return retVal;}/*** @return true if the root_pv_id is null (-1). This indicates that the item is the root case, and is not simply* a by product of some other cause.*/boolean isARootCause(){mLogger.debug("isARootCause {}", mId);boolean retVal = false;if ( mRootId == -1 ){retVal = true;}mLogger.info("isARootCause {} returned {}",mId, retVal);return retVal;}/*** Send an email notifying users about a build excluded package* It is user friendly, in that it does not trigger a storm of emails because a low level package* has a build issue. It limits 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** @param rippleEngine - Ripple Engine Instance* @param packageCollection - Collection to process*/public void email(RippleEngine rippleEngine, ArrayList<Package> packageCollection) throws SQLException, Exception{mLogger.debug("email {}", mId);//// Only process entries that are direct failures of ripple engine detected failure// Do not process entries that are indirectly excluded as this will cause an email storm// Direct build failure:// Have no RootId and have a rootCause//if ( mRootId == -1 && mRootCause != null ){// Locate the associated package entryPackage pkg= rippleEngine.mReleaseManager.findPackage(mId, packageCollection);if ( pkg != ReleaseManager.NULL_PACKAGE ){// Is there anyone to send an email toString owners = pkg.emailInfoNonAntTask(rippleEngine);if ( owners != null ){String body ="Release: " + rippleEngine.mBaselineName + "<p>" +"Package: " + pkg.mName + "<p>" +"Cause: " + mRootCause + "<p>"+"RmRef: " + CreateUrls.generateRmUrl(rippleEngine.getRtagId(), pkg.mId) +"<p>";try{Smtpsend.send(rippleEngine.getMailServer(), // mailServerrippleEngine.getMailSender(), // sourceowners, // targetnull, // ccnull, // bcc"BUILD FAILURE on package " + pkg.mName, // subjectbody, // bodynull // attachment);}catch( Exception e ){mLogger.info("email send 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 buildspkg.completeTestBuild(rippleEngine, false);}}}/*** Hides how a rootPvId is treated* Only use rootPvId if not equal to the pvid** If the provided rootPvId matches the pvId, then the rootPvId will be set to null (-1)* This is to drive a direct build exclusion in the release manager** @param pvid - id* @param rootPvId - rootPvid** @returns rootPvId unless pvId matches= rootPvId, when it returns a null (-1)*/private int dealWithNullRootPvId( int pvId, int rootPvId ){int retVal = rootPvId;if ( pvId == rootPvId ){retVal = -1; // -1 == null entry}return retVal;}/*** Generate a single text line of info* Used within the UTF to* @return String form of the state of the entry*/public String info(){String rv = "";rv += "pvid=" + mId + ",RootId=" + mRootId + ",Processed=" + mProcessed + ",TestBuild=" + mTestBuildInstruction + ",RootCause=" + mRootCause;if ( mImported ) {rv += ",Imported=" + mImported;}return rv;}}