Rev 888 | Blame | Last modification | View Log | RSS feed
package com.erggroup.buildtool.ripple;import java.io.File;import java.util.Iterator;import java.util.Vector;import org.apache.log4j.Logger;public class Package{/**name of package, must not contain spaces* @attribute*/String mName = new String();/**package scope* @attribute*/String mExtension = new String();/**instance identifier* @attribute*/String mVersion = new String();/**unique identifier* for daemon builds = mName + mExtension* for escrow builds = mName + mVersion + mExtension* @attribute*/String mAlias = new String();/**clearcase vob location, must not contain spaces* @attribute*/String mLocation = new String();/**clearcase source file instance identifier* @attribute*/String mLabel = new String();/**build standards* @attribute*/Vector<BuildStandard> mBuildStandardCollection = new Vector<BuildStandard>();/**GBE_MACHTYPE used to build generic packages for this baseline* only has meaning in the daemon build, not the escrow build* accessed by BuildStandard::getPlatform, getBuildStandard* @attribute*/public static final String mGenericMachtype = System.getenv("GBE_MACHTYPE");/**build dependencies by package alias* @attribute*/Vector<String> mDependencyCollection = new Vector<String>();/**primary package version key pv_id in database* @attribute*/int mId;/**indication of the nature of change* @attribute*/Package.VersionNumberingStandard mChangeType = new VersionNumberingStandard();/**determines what field is rippled on a package version whose dependencies have changed* @attribute*/Package.VersionNumberingStandard mRippleField = new VersionNumberingStandard();/**interested owners* @attribute*/private Vector<String> mBuildFailureEmailCollection = new Vector<String>();/**when true will trigger unit tests as part of the package build phase in daemon mode* @attribute*/boolean mHasAutomatedUnitTests = false;/**when true, do not ripple this package through packages which are dependent upon it in daemon mode* @attribute*/boolean mAdvisoryRipple = false;/**determines the build file the package is built in, or not* 1 buildfile 1 etc* 0 not yet processed (initial value)* -1 not reproducible* -2 not reproducible on the build platforms configured for this release* -3 do not ripple* -4 directly dependent on package versions not in the baseline* -5 indirectly dependent on package versions which are not reproducible* because of -1, -2 (escrow), -3 (daemon), -4* @attribute*/int mBuildFile = 0;/**build dependencies by package* @attribute*/Vector<Package> mPackageDependencyCollection = new Vector<Package>();/**used for escrow build purposes* set true when a package has been processed* @attribute*/boolean mProcessed = false;/**set true for WIP package versions* only used in daemon mode* @attribute*/boolean mDirectlyPlanned = false;/**set true when it is determined to be ripple built* @attribute*/boolean mIndirectlyPlanned = false;/**build dependencies by pv_id (-1 or not used for planned dependencies)* @attribute*/Vector<Integer> mDependencyIDCollection = new Vector<Integer>();/**unique pkg_id in the database* used for querying package version existence in the database in daemon mode* @attribute*/int mPid;/**maximum major number supported for determining ripple number* @attribute*/int mMajorLimit;/**maximum minor number supported for determining ripple number* @attribute*/int mMinorLimit;/**maximum patch number supported for determining ripple number* @attribute*/int mPatchLimit;/**maximum build number number supported for determining ripple number* @attribute*/int mBuildLimit;/**Logger* @attribute*/private static final Logger mLogger = Logger.getLogger(Package.class);/**dpkg archive location* @attribute*/public static final String mGbeDpkg = System.getenv("GBE_DPKG");/**deploy archive location* @attribute*/public static final String mGbeDply = System.getenv("GBE_DPLY");/**true if the package exists in the dpkg or deploy archive* @attribute*/private boolean mArchivalExistence = true;/**when true will trigger source control interaction eg labelling* @attribute*/public boolean mRequiresSourceControlInteraction = true;/**constructor*/Package(int pv_id, String pkg_name, String v_ext, String alias,String pkg_label, String src_path, char change_type){mLogger.debug("Package 1: pv_id " + pv_id + " pkg_name " + pkg_name + " v_ext " + v_ext + " alias " + alias + " pkg_label " + pkg_label + " src_path " + src_path + " change_type " + change_type);mId = pv_id;mName = pkg_name;mVersion = "0.0.0000";mExtension = v_ext;mAlias = alias;mLabel = pkg_label;mLocation = src_path;if (change_type == 'M'){mChangeType.setMajor();}else if (change_type == 'N'){mChangeType.setMinor();}else{mChangeType.setPatch();}}/**constructor*/Package(int pv_id, String pkg_name, String pkg_version, String v_ext,String alias, String pkg_label, String src_path,char ripple_field){mLogger.debug("Package 2: pv_id " + pv_id + " pkg_name " + pkg_name + " pkg_version " + pkg_version + " v_ext " + v_ext + " alias " + alias + " pkg_label " + pkg_label + " src_path " + src_path + " ripple_field " + ripple_field);mId = pv_id;mName = pkg_name;mVersion = pkg_version;int endindex = mVersion.length() - v_ext.length();if ( endindex > 0 ){mVersion = mVersion.substring(0, endindex);}mExtension = v_ext;mAlias = alias;mLabel = pkg_label;mLocation = src_path;// setBuild is the defaultif (ripple_field == 'M'){mRippleField.setMajor();}else if (ripple_field == 'm'){mRippleField.setMinor();}else if (ripple_field == 'p'){mRippleField.setPatch();}else if (ripple_field == 'L'){mRippleField.setLimit();}}/**constructor*/Package(){mLogger.debug("Package 3");mId = 0;mName = "null";mExtension = "null";mAlias = "null";mLabel = "null";mLocation = "null";}/**constructor for unit test purposes*/public Package(ReleaseManager rm, String version, int majorLimit, int minorLimit, int patchLimit, int buildNumberLimit){mId = -1;mRippleField.setLimit();mVersion = version;mMajorLimit = majorLimit;mMinorLimit = minorLimit;mPatchLimit = patchLimit;mBuildLimit = buildNumberLimit;try{mId = applyPV( rm, 0 );}catch(Exception e){}}/**accessor for unit test purposes*/public int getId(){return mId;}/**accessor for unit test purposes*/public String getVersion(){return mVersion;}/**returns true if mBuildStandardCollection is not empty*/boolean isReproducible(){mLogger.debug("isReproducible on Package " + mName);boolean retVal = false;if ( mBuildStandardCollection.size() > 0 ){retVal = true;}mLogger.info("isReproducible returned " + retVal);return retVal;}/**returns true if at least one of its BuildStandards has mWin32 or mGeneric true*/boolean isWin32Built(){mLogger.debug("isWin32Built on Package " + mName);boolean retVal = false;for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); ){BuildStandard buildStandard = it.next();if (buildStandard.getWin32() || buildStandard.getGeneric()){retVal = true;break;}}mLogger.info("isWin32Built returned " + retVal);return retVal;}/**returns true if at least one of its BuildStandards has mSolaris or mGeneric true*/boolean isSolarisBuilt(){mLogger.debug("isSolarisBuilt on Package " + mName);boolean retVal = false;for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); ){BuildStandard buildStandard = it.next();if (buildStandard.getSolaris() || buildStandard.getGeneric()){retVal = true;break;}}mLogger.info("isSolarisBuilt returned " + retVal);return retVal;}/**returns true if at least one of its BuildStandards has mLinux or mGeneric true*/boolean isLinuxBuilt(){mLogger.debug("isLinuxBuilt on Package " + mName);boolean retVal = false;for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); ){BuildStandard buildStandard = it.next();if (buildStandard.getLinux() || buildStandard.getGeneric()){retVal = true;break;}}mLogger.info("isLinuxBuilt returned " + retVal);return retVal;}/**returns true if at least one of its BuildStandards has mGeneric true*/boolean isGeneric(){mLogger.debug("isGeneric on Package " + mName);boolean retVal = false;for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); ){BuildStandard buildStandard = it.next();if (buildStandard.getGeneric()){retVal = true;break;}}mLogger.info("isGeneric returned " + retVal);return retVal;}/**applies the required version number change* returns 0 on success* 1 on cannot work with non standard versioning* 2 on ripple field limitations prevent a ripple build*/int applyPV(ReleaseManager releaseManager, int rtag_id) throws Exception{mLogger.debug("applyPV on Package " + mName);// three scenarios, only applyPV for 2 of them// WIP exists: mDirectlyPlanned == true; mIndirectlyPlanned == true; mArchivalExistence don't care - applyPV// Package version is out of date: mDirectlyPlanned == false; mIndirectlyPlanned == true; mArchivalExistence == true - applyPV// Package version does not exist: mDirectlyPlanned == false; mIndirectlyPlanned == true; mArchivalExistence == false - do not applyPVif ( !mDirectlyPlanned && mIndirectlyPlanned && !mArchivalExistence ){// the package has an mIndirectlyPlanned flag set true in daemon mode because the package does not exist in an archive// do not apply a different package versionmLogger.info("applyPV !mDirectlyPlanned && mIndirectlyPlanned && !mArchivalExistence on Package " + mName);releaseManager.claimVersion(mPid, mVersion + mExtension, rtag_id);mLogger.info("applyPv returned 0");return 0;}MutableInt major = new MutableInt();major.value = 0;MutableInt minor = new MutableInt();minor.value = 0;MutableInt patch = new MutableInt();patch.value = 1000;String field[] = mVersion.split("\\D");String nonStandardCotsVersion = "";if ( field.length == 3 ){major.value = Integer.parseInt(field[0]);minor.value = Integer.parseInt(field[1]);patch.value = Integer.parseInt(field[2]);}else{if ( !mChangeType.mMajor &&!mChangeType.mMinor &&!mChangeType.mPatch &&mRippleField.mBuild &&mExtension.compareTo(".cots") == 0 &&field.length > 0 ){// DEVI 52782// allow and work with (ripple build) versions a.b.c.d....xxxx// where xxxx.length > 3String patchStr = field[field.length - 1];int patchLen = patchStr.length();// check patchStr is the last (at least 4) digitsif ( patchLen > 3 && mVersion.substring( mVersion.length() - patchLen, mVersion.length() ).compareTo(patchStr) == 0 ){patch.value = Integer.parseInt(patchStr);nonStandardCotsVersion = mVersion.substring(0, mVersion.length() - patchLen );}}if ( nonStandardCotsVersion.length() == 0 ){// cannot work with non standard versioningmLogger.error("applyPV cannot work with non standard versioning");mLogger.info("applyPv returned 1");return 1;}}if ( nonStandardCotsVersion.length() == 0 &&patch.value < 1000 &&field[2].substring(0, 1).compareTo("0") != 0 ){mLogger.info("applyPV accomodate old style mVersion of the form 1.0.1");patch.value = patch.value * 1000;}// mChangeType overrides mRippleFielddo{if ( mChangeType.mMajor ){if ( !incrementFieldsAccordingToLimits(4, major, minor, patch) ){mLogger.info("applyPv returned 2");return 2;}}else if ( mChangeType.mMinor ){if ( !incrementFieldsAccordingToLimits(3, major, minor, patch) ){mLogger.info("applyPv returned 2");return 2;}}else if ( mChangeType.mPatch ){if ( !incrementFieldsAccordingToLimits(2, major, minor, patch) ){mLogger.info("applyPv returned 2");return 2;}}else{if ( mRippleField.mMajor ){major.value++;mLogger.info("applyPV mRippleField.mMajor " + major.value);minor.value = 0;patch.value = 0;}else if ( mRippleField.mMinor ){minor.value++;mLogger.info("applyPV mRippleField.mMinor " + minor.value);patch.value = 0;}else if ( mRippleField.mPatch ){do{patch.value++;} while ( ( patch.value / 1000 ) * 1000 != patch.value );mLogger.info("applyPV mRippleField.mPatch " + patch.value);}else if ( mRippleField.mBuild ){patch.value++;mLogger.info("applyPV mRippleField.mBuild " + patch.value);}else{if ( !incrementFieldsAccordingToLimits(1, major, minor, patch) ){mLogger.info("applyPv returned 2");return 2;}}}if ( nonStandardCotsVersion.length() == 0 ){mVersion = String.valueOf(major.value) + "." + String.valueOf(minor.value) + ".";}else{mVersion = nonStandardCotsVersion;}if ( patch.value < 10 ){mVersion += "000";}else if ( patch.value < 100 ){mVersion += "00";}else if ( patch.value < 1000 ){mVersion += "0";}mVersion += String.valueOf(patch.value);} while ( exists(releaseManager, rtag_id) );releaseManager.claimVersion(mPid, mVersion + mExtension, rtag_id);mLogger.info("applyPv returned 0");return 0;}/**increments fields according to mRippleField.mLimit if necessary* will apply it to the field passed as follows* 1 = build* 2 = patch* 3 = minor* other = major* returns true on success* false on ripple field limitations prevent a ripple build*/private boolean incrementFieldsAccordingToLimits(int field, MutableInt major, MutableInt minor, MutableInt patch){boolean retVal = true;if (!mRippleField.mLimit){// simple case// no need to take field limits into considerationswitch (field){case 1:// unreachable// the only scenario involving build number manipulation involves the mRippleField.mLimit being setretVal = false;break;case 2:do{patch.value++;} while ( ( patch.value / 1000 ) * 1000 != patch.value );mLogger.info("incrementFieldsAccordingToLimits patch " + patch.value);break;case 3:minor.value++;mLogger.info("incrementFieldsAccordingToLimits minor " + minor.value);patch.value = 0;break;default:major.value++;mLogger.info("incrementFieldsAccordingToLimits major " + major.value);minor.value = 0;patch.value = 0;}}else{// take field limits into considerationboolean changeOccurred = false;boolean incrementField = true;switch (field){case 1:if ( mBuildLimit != 0 ){// increment or reset the patch build numberint buildNumber = patch.value - (patch.value/1000) * 1000;if ( buildNumber < mBuildLimit ){// can increment the patch build numberpatch.value++;mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit build number " + patch.value);changeOccurred = true;incrementField = false;}else{if ( mPatchLimit == 0 ){// reset the patch number and patch build numberpatch.value = 0;}}}// no break by designcase 2:if ( mPatchLimit != 0 && incrementField ){// increment or reset the patch numberif ( ( patch.value / 1000 ) < mPatchLimit ){do{patch.value++;} while ( ( patch.value / 1000 ) * 1000 != patch.value );mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit patch " + patch.value);changeOccurred = true;incrementField = false;}else{// reset the patch number and patch build numberpatch.value = 0;}}// no break by designcase 3:if ( mMinorLimit != 0 && incrementField ){// increment or reset the minor numberif ( minor.value < mMinorLimit ){minor.value++;patch.value = 0;mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit minor " + minor.value);changeOccurred = true;incrementField = false;}else{// reset the minor numberminor.value = 0;}}// no break by designdefault:if ( mMajorLimit != 0 && incrementField ){// increment or reset the major numberif ( major.value < mMajorLimit ){// increment the major numberchangeOccurred = true;major.value++;minor.value = 0;patch.value = 0;mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit major " + major.value);}}}if ( !changeOccurred ){// unable to increment a field due to field limitationsmLogger.error("incrementFieldsAccordingToLimits ripple field limitations prevent a ripple build");mLogger.info("incrementFieldsAccordingToLimits returned false");retVal = false;}}return retVal;}/**returns true if the version exists in the dpkg_archive, deploy_archive or release manager database* claims the version in the release manager database*/private boolean exists(ReleaseManager releaseManager, int rtag_id) throws Exception{mLogger.debug("exists 1 on Package " + mName + " version " + mVersion + " extension " + mExtension);boolean retVal = false;if ( !ReleaseManager.mUseDatabase ){mLogger.info("exists 1 !releaseManager.mUseDatabase");}else{retVal = exists();if ( !retVal ){String pkg_version = new String(mVersion);if ( mExtension.length() > 0 ){pkg_version += mExtension;}retVal = releaseManager.queryPackageVersions(mPid, pkg_version);}}mLogger.info("exists 1 returned " + retVal);return retVal;}/**returns true if the version exists in the dpkg_archive or deploy_archive*/boolean exists()throws Exception{mLogger.debug("exists 2 on Package " + mName);boolean retVal = false;String Release = mGbeDpkg;String Deploy = mGbeDply;if (Release == null || Deploy == null){mLogger.fatal("exists 2 Release == null || Deploy == null");throw new Exception("exists 2 Release == null || Deploy == null");}String fs = System.getProperty( "file.separator" );String name = new String(Release);name += fs + mName + fs + mVersion + mExtension;File release = new File(name);if (release.exists()){mLogger.info("exists 2 release.exists()");retVal = true;}if (!retVal && (Release != Deploy)){name = Deploy + fs + mName + fs + mVersion + mExtension;File deploy = new File(name);if (deploy.exists()){mLogger.info("exists 2 deploy.exists()");retVal = true;}}mArchivalExistence = retVal;mLogger.info("exists 2 returned " + retVal);return retVal;}/**returns email information*/String emailInfo( String lf ){String retVal = new String();for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); ){String email = it.next();retVal +=" <owner email=\"" + email +"\"/>" + lf;}return retVal;}/**returns email information*/String emailInfoNonAntTask(){String retVal = null;for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); ){String email = it.next();if ( retVal == null ){retVal = new String();}else{retVal += ",";}retVal += email;}return retVal;}/**adds email to mBuildFailureEmailCollection if unique*/void addEmail( String email ){boolean alreadyExists = false;for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); ){String existingEmail = it.next();if ( existingEmail.compareTo(email) == 0 ){alreadyExists = true;break;}}if ( !alreadyExists ){mBuildFailureEmailCollection.add(email);}}/**entity class supporting the ERG version numbering standard:* <major>.<minor>.<patch/build>* patch/build is at least a 4 digit number whose last 3 digits represent the build*/public class VersionNumberingStandard{/**in terms of the mChangeType Package field,* when true indicates the contract of the package has changed in a non backwardly compatible manner* in terms of the mRippleField Package field,* when true indicates the major version number will be incremented* @attribute*/private boolean mMajor = false;/**in terms of the mChangeType Package field,* when true indicates the contract of the package has changed in a backwardly compatible manner* in terms of the mRippleField Package field,* when true indicates the minor version number will be incremented* @attribute*/private boolean mMinor = false;/**in terms of the mChangeType Package field,* when true indicates the contract of the package has not changed, but the package has changed internally* in terms of the mRippleField Package field,* when true indicates the minor version number will be incremented* @attribute*/private boolean mPatch = false;/**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 mBuild = true;/**in terms of the mChangeType Package field,* always false, does not apply* in terms of the mRippleField Package field,* when true indicates the major, minor, patch and build number will be incremented according to field limits* @attribute*/private boolean mLimit = false;/**constructor*/private VersionNumberingStandard(){mLogger.debug("VersionNumberingStandard");}/**sets mBuild true, mMajor false, mMinor false, mPatch false, mLimit false*/void setBuild(){mLogger.debug("setBuild");mBuild = true;mMajor = false;mMinor = false;mPatch = false;mLimit = false;}/**sets mBuild false, mMajor true, mMinor false, mPatch false, mLimit false*/void setMajor(){mLogger.debug("setMajor");mBuild = false;mMajor = true;mMinor = false;mPatch = false;mLimit = false;}/**sets mBuild false, mMajor false, mMinor true, mPatch false, mLimit false*/void setMinor(){mLogger.debug("setMinor");mBuild = false;mMajor = false;mMinor = true;mPatch = false;mLimit = false;}/**sets mBuild false, mMajor false, mMinor false, mPatch true, mLimit false*/void setPatch(){mLogger.debug("setPatch");mBuild = false;mMajor = false;mMinor = false;mPatch = true;mLimit = false;}/**sets mBuild false, mMajor false, mMinor false, mPatch false, mLimit true*/void setLimit(){mLogger.debug("setPatch");mBuild = false;mMajor = false;mMinor = false;mPatch = false;mLimit = true;}}}