Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
814 mhunt 1
package com.erggroup.buildtool.ripple;
2
 
3
import java.io.File;
4
 
908 mhunt 5
import java.sql.SQLException;
814 mhunt 6
import java.util.Iterator;
7
import java.util.Vector;
8
 
9
import org.apache.log4j.Logger;
10
 
908 mhunt 11
import com.erggroup.buildtool.smtp.Smtpsend;
12
 
814 mhunt 13
public class Package
14
{
15
  /**name of package, must not contain spaces
16
   * @attribute
17
   */
18
  String mName = new String();
19
 
20
  /**package scope
21
   * @attribute
22
   */
23
  String mExtension = new String();
24
 
25
  /**instance identifier
26
   * @attribute
27
   */
28
  String mVersion = new String();
29
 
30
  /**unique identifier
31
   * for daemon builds = mName + mExtension
32
   * for escrow builds = mName + mVersion + mExtension
33
   * @attribute
34
   */
35
  String mAlias = new String();
36
 
37
  /**clearcase vob location, must not contain spaces
38
   * @attribute
39
   */
40
  String mLocation = new String();
41
 
42
  /**clearcase source file instance identifier
43
   * @attribute
44
   */
45
  String mLabel = new String();
46
 
47
  /**build standards
48
   * @attribute
49
   */
864 mhunt 50
  Vector<BuildStandard> mBuildStandardCollection = new Vector<BuildStandard>();
814 mhunt 51
 
52
  /**GBE_MACHTYPE used to build generic packages for this baseline
53
   * only has meaning in the daemon build, not the escrow build
54
   * accessed by BuildStandard::getPlatform, getBuildStandard
55
   * @attribute
56
   */
57
  public static final String mGenericMachtype = System.getenv("GBE_MACHTYPE");
58
 
59
  /**build dependencies by package alias
60
   * @attribute
61
   */
864 mhunt 62
  Vector<String> mDependencyCollection = new Vector<String>();
814 mhunt 63
 
64
  /**primary package version key pv_id in database
65
   * @attribute
66
   */
67
  int mId;
68
 
69
  /**indication of the nature of change
70
   * @attribute
71
   */
72
  Package.VersionNumberingStandard mChangeType = new VersionNumberingStandard();
73
 
74
  /**determines what field is rippled on a package version whose dependencies have changed
75
   * @attribute
76
   */
77
  Package.VersionNumberingStandard mRippleField = new VersionNumberingStandard();
78
 
79
  /**interested owners
80
   * @attribute
81
   */
864 mhunt 82
  private Vector<String> mBuildFailureEmailCollection = new Vector<String>();
814 mhunt 83
 
84
  /**when true will trigger unit tests as part of the package build phase in daemon mode
85
   * @attribute
86
   */
87
  boolean mHasAutomatedUnitTests = false;
88
 
89
  /**when true, do not ripple this package through packages which are dependent upon it in daemon mode
90
   * @attribute
91
   */
92
  boolean mAdvisoryRipple = false;
93
 
94
  /**determines the build file the package is built in, or not
95
   *  1 buildfile 1 etc
96
   *  0 not yet processed (initial value)
97
   * -1 not reproducible
98
   * -2 not reproducible on the build platforms configured for this release
99
   * -3 do not ripple
100
   * -4 directly dependent on package versions not in the baseline
101
   * -5 indirectly dependent on package versions which are not reproducible
910 mhunt 102
   *    because of -1, -2 (escrow), -3 (daemon), -4, -6
103
   * -6 circular dependency
814 mhunt 104
   * @attribute
105
   */
106
  int mBuildFile = 0;
107
 
108
  /**build dependencies by package
109
   * @attribute
110
   */
864 mhunt 111
  Vector<Package> mPackageDependencyCollection = new Vector<Package>();
814 mhunt 112
 
113
  /**used for escrow build purposes
114
   * set true when a package has been processed
115
   * @attribute
116
   */
117
  boolean mProcessed = false;
118
 
119
  /**set true for WIP package versions
120
   * only used in daemon mode
121
   * @attribute
122
   */
123
  boolean mDirectlyPlanned = false;
124
 
125
  /**set true when it is determined to be ripple built
126
   * @attribute
127
   */
128
  boolean mIndirectlyPlanned = false;
129
 
908 mhunt 130
  /**non zero instruction number when it is determined to be ripple built by force
131
   * @attribute
132
   */
133
  int mForcedRippleInstruction = 0;
134
 
135
  /**non zero instruction number when it is determined to be test built
136
   * @attribute
137
   */
138
  int mTestBuildInstruction = 0;
139
 
140
  /**test build email destination
141
   * @attribute
142
   */
143
  String mTestBuildEmail;
144
 
145
  /**clearcase vob location, must not contain spaces
146
   * @attribute
147
   */
148
  String mTestBuildLocation = new String();
149
 
150
  /**clearcase source file instance identifier
151
   * @attribute
152
   */
153
  String mTestBuildLabel = new String();
154
 
155
  /**build standards
156
   * @attribute
157
   */
158
  Vector<BuildStandard> mTestBuildStandardCollection = new Vector<BuildStandard>();
159
 
160
  /**build dependencies by package alias
161
   * @attribute
162
   */
163
  Vector<String> mTestBuildDependencyCollection = new Vector<String>();
164
 
814 mhunt 165
  /**build dependencies by pv_id (-1 or not used for planned dependencies)
166
   * @attribute
167
   */
864 mhunt 168
  Vector<Integer> mDependencyIDCollection = new Vector<Integer>();
814 mhunt 169
 
170
  /**unique pkg_id in the database
171
   * used for querying package version existence in the database in daemon mode
172
   * @attribute
173
   */
174
  int mPid;
175
 
874 mhunt 176
  /**maximum major number supported for determining ripple number
177
   * @attribute
178
   */
179
  int mMajorLimit;
180
 
181
  /**maximum minor number supported for determining ripple number
182
   * @attribute
183
   */
184
  int mMinorLimit;
185
 
186
  /**maximum patch number supported for determining ripple number
187
   * @attribute
188
   */
189
  int mPatchLimit;
190
 
191
  /**maximum build number number supported for determining ripple number
192
   * @attribute
193
   */
194
  int mBuildLimit;
195
 
814 mhunt 196
  /**Logger
197
   * @attribute
198
   */
199
  private static final Logger mLogger = Logger.getLogger(Package.class);
200
 
201
  /**dpkg archive location
202
   * @attribute
203
   */
204
  public static final String mGbeDpkg = System.getenv("GBE_DPKG");
205
 
206
  /**deploy archive location
207
   * @attribute
208
   */
209
  public static final String mGbeDply = System.getenv("GBE_DPLY");
210
 
896 mhunt 211
  /**Exception message used upon detection an archive does not exist
212
   * Seems this is a rare but transient and recoverable scenario
213
   * @attribute
214
   */
215
  public static final String mRecoverable = "dpkg or deploy_archive do not exist, recovery will be attempted";
216
 
814 mhunt 217
  /**true if the package exists in the dpkg or deploy archive
218
   * @attribute
219
   */
220
  private boolean mArchivalExistence = true;
221
 
852 mhunt 222
  /**when true will trigger source control interaction eg labelling
223
   * @attribute
224
   */
225
  public boolean mRequiresSourceControlInteraction = true;
226
 
910 mhunt 227
  /**when true has been checked for circular dependency
228
   * @attribute
229
   */
230
  boolean mCheckedCircularDependency = false;
231
 
232
  /**when true has circular dependency
233
   * @attribute
234
   */
235
  boolean mHasCircularDependency = false;
236
 
814 mhunt 237
  /**constructor
238
   */
239
  Package(int pv_id, String pkg_name, String v_ext, String alias, 
902 mhunt 240
          String pkg_label, String src_path, char change_type, char ripple_field)
814 mhunt 241
  {
242
    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);
243
    mId = pv_id;
244
    mName = pkg_name;
245
    mVersion = "0.0.0000";
246
    mExtension = v_ext;
247
    mAlias = alias;
248
    mLabel = pkg_label;
249
    mLocation = src_path;
250
 
251
    if (change_type == 'M')
252
    {
902 mhunt 253
      // a ripple_field of 'L' indicates this package has limited version numbering
254
      mChangeType.setMajor(ripple_field == 'L' ? true : false);
814 mhunt 255
    }
256
    else if (change_type == 'N')
257
    {
902 mhunt 258
      mChangeType.setMinor(ripple_field == 'L' ? true : false);
814 mhunt 259
    }
260
    else
261
    {
902 mhunt 262
      mChangeType.setPatch(ripple_field == 'L' ? true : false);
814 mhunt 263
    }
264
  }
265
 
266
  /**constructor
267
   */
268
  Package(int pv_id, String pkg_name, String pkg_version, String v_ext, 
269
          String alias, String pkg_label, String src_path, 
270
          char ripple_field)
271
  {
272
    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);
273
    mId = pv_id;
274
    mName = pkg_name;
275
    mVersion = pkg_version;
276
    int endindex = mVersion.length() - v_ext.length();
277
 
278
    if ( endindex > 0 )
279
    {
280
      mVersion = mVersion.substring(0, endindex);
281
    }
282
 
283
    mExtension = v_ext;
284
    mAlias = alias;
285
    mLabel = pkg_label;
286
    mLocation = src_path;
287
 
874 mhunt 288
    // setBuild is the default
814 mhunt 289
    if (ripple_field == 'M')
290
    {
291
      mRippleField.setMajor();
292
    }
293
    else if (ripple_field == 'm')
294
    {
295
      mRippleField.setMinor();
296
    }
297
    else if (ripple_field == 'p')
298
    {
299
      mRippleField.setPatch();
300
    }
874 mhunt 301
    else if (ripple_field == 'L')
302
    {
303
      mRippleField.setLimit();
304
    }
814 mhunt 305
  }
306
 
307
  /**constructor
308
   */
309
  Package()
310
  {
311
    mLogger.debug("Package 3");
312
    mId = 0;
313
    mName = "null";
314
    mExtension = "null";
315
    mAlias = "null";
316
    mLabel = "null";
317
    mLocation = "null";
318
  }
319
 
908 mhunt 320
  /**constructor for test build purposes
321
   */
322
  Package(String pkg_name, String v_ext, String alias, 
323
          String pkg_label, String src_path, int testBuildInstruction, String email)
324
  {
325
    mLogger.debug("Package 4: pkg_name " + pkg_name + " v_ext " + v_ext + " alias " + alias + " pkg_label " + pkg_label + " src_path " + src_path);
326
    // don't need pv_id
327
    mId = -1;
328
    mName = pkg_name;
329
    // avoid interaction with real versions
330
    mVersion = "0.0.0000";
331
    mExtension = v_ext;
332
    mAlias = alias;
333
    mTestBuildInstruction = testBuildInstruction;
334
    mTestBuildEmail = email;
335
    mTestBuildLocation = src_path;
336
    mTestBuildLabel = pkg_label;
337
  }
338
 
339
/**constructor for unit test purposes
874 mhunt 340
  */
341
  public Package(ReleaseManager rm, String version, int majorLimit, int minorLimit, int patchLimit, int buildNumberLimit)
342
  {
343
    mId = -1;
344
    mRippleField.setLimit();
345
    mVersion = version;
346
    mMajorLimit = majorLimit;
347
    mMinorLimit = minorLimit;
348
    mPatchLimit = patchLimit;
349
    mBuildLimit = buildNumberLimit;
350
    try
351
    {
352
      mId = applyPV( rm, 0 );
353
    }
354
    catch(Exception e)
355
    {
356
    }
357
  }
358
 
359
  /**accessor for unit test purposes
360
   */
361
  public int getId()
362
  {
363
    return mId;
364
  }
365
 
366
  /**accessor for unit test purposes
367
   */
368
  public String getVersion()
369
  {
370
    return mVersion;
371
  }
372
 
814 mhunt 373
  /**returns true if mBuildStandardCollection is not empty
374
   */
375
  boolean isReproducible()
376
  {
377
    mLogger.debug("isReproducible on Package " + mName);
378
    boolean retVal = false;
379
 
380
    if ( mBuildStandardCollection.size() > 0 )
381
    {
382
      retVal = true;
383
    }
384
 
385
    mLogger.info("isReproducible returned " + retVal);
386
    return retVal;
387
  }
388
 
389
  /**returns true if at least one of its BuildStandards has mWin32 or mGeneric true
390
   */
391
  boolean isWin32Built()
392
  {
393
    mLogger.debug("isWin32Built on Package " + mName);
394
    boolean retVal = false;
864 mhunt 395
    for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); )
814 mhunt 396
    {
864 mhunt 397
      BuildStandard buildStandard = it.next();
814 mhunt 398
 
399
      if (buildStandard.getWin32() || buildStandard.getGeneric())
400
      {
401
        retVal = true;
402
        break;
403
      }
404
    }
405
 
406
    mLogger.info("isWin32Built returned " + retVal);
407
    return retVal;
408
  }
409
 
410
  /**returns true if at least one of its BuildStandards has mSolaris or mGeneric true
411
   */
412
  boolean isSolarisBuilt()
413
  {
414
    mLogger.debug("isSolarisBuilt on Package " + mName);
415
    boolean retVal = false;
864 mhunt 416
    for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); )
814 mhunt 417
    {
864 mhunt 418
      BuildStandard buildStandard = it.next();
814 mhunt 419
 
420
      if (buildStandard.getSolaris() || buildStandard.getGeneric())
421
      {
422
        retVal = true;
423
        break;
424
      }
425
    }
426
 
427
    mLogger.info("isSolarisBuilt returned " + retVal);
428
    return retVal;
429
  }
430
 
431
  /**returns true if at least one of its BuildStandards has mLinux or mGeneric true
432
   */
433
  boolean isLinuxBuilt()
434
  {
435
    mLogger.debug("isLinuxBuilt on Package " + mName);
436
    boolean retVal = false;
864 mhunt 437
    for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); )
814 mhunt 438
    {
864 mhunt 439
      BuildStandard buildStandard = it.next();
814 mhunt 440
 
441
      if (buildStandard.getLinux() || buildStandard.getGeneric())
442
      {
443
        retVal = true;
444
        break;
445
      }
446
    }
447
 
448
    mLogger.info("isLinuxBuilt returned " + retVal);
449
    return retVal;
450
  }
451
 
452
  /**returns true if at least one of its BuildStandards has mGeneric true
453
   */
454
  boolean isGeneric()
455
  {
456
    mLogger.debug("isGeneric on Package " + mName);
457
    boolean retVal = false;
864 mhunt 458
    for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); )
814 mhunt 459
    {
864 mhunt 460
      BuildStandard buildStandard = it.next();
814 mhunt 461
 
462
      if (buildStandard.getGeneric())
463
      {
464
        retVal = true;
465
        break;
466
      }
467
    }
468
 
469
    mLogger.info("isGeneric returned " + retVal);
470
    return retVal;
471
  }
472
 
473
  /**applies the required version number change
874 mhunt 474
   * returns 0 on success
475
   *         1 on cannot work with non standard versioning
476
   *         2 on ripple field limitations prevent a ripple build
814 mhunt 477
   */
874 mhunt 478
  int applyPV(ReleaseManager releaseManager, int rtag_id) throws Exception
814 mhunt 479
  {
480
    mLogger.debug("applyPV on Package " + mName);
908 mhunt 481
    // four scenarios, only applyPV for 3 of them
482
    // WIP/test build exists:           mDirectlyPlanned == true;   mIndirectlyPlanned == true; mArchivalExistence don't care; mForcedRipple don't care - applyPV
483
    // Package version is out of date:  mDirectlyPlanned == false;  mIndirectlyPlanned == true; mArchivalExistence == true;    mForcedRipple don't care - applyPV
484
    // Forced ripple:                   mDirectlyPlanned == false;  mIndirectlyPlanned == true; mArchivalExistence don't care; mForcedRipple > 0        - applyPV
485
    // Package version does not exist:  mDirectlyPlanned == false;  mIndirectlyPlanned == true; mArchivalExistence == false;   mForcedRipple = 0    - do not applyPV
486
    if ( !mDirectlyPlanned && mIndirectlyPlanned && !mArchivalExistence && mForcedRippleInstruction == 0 )
814 mhunt 487
    {
488
      // the package has an mIndirectlyPlanned flag set true in daemon mode because the package does not exist in an archive
489
      // do not apply a different package version
908 mhunt 490
      mLogger.info("applyPV !mDirectlyPlanned && mIndirectlyPlanned && !mArchivalExistence && zero mForcedRippleInstruction on Package " + mName);
836 mhunt 491
      releaseManager.claimVersion(mPid, mVersion + mExtension, rtag_id);
874 mhunt 492
      mLogger.info("applyPv returned 0");
493
      return 0;
814 mhunt 494
    }
908 mhunt 495
 
496
    // override - no longer doing a rebuild - version number change from this point on
497
    if ( mTestBuildInstruction == 0 )
498
    {
499
      mRequiresSourceControlInteraction = true;
500
    }
814 mhunt 501
 
892 mhunt 502
    MutableInt major = new MutableInt();
503
    major.value = 0;
504
    MutableInt minor = new MutableInt();
505
    minor.value = 0;
506
    MutableInt patch = new MutableInt();
507
    patch.value = 1000;
814 mhunt 508
 
509
    String field[] = mVersion.split("\\D");
888 mhunt 510
    String nonStandardCotsVersion = "";
511
 
814 mhunt 512
    if ( field.length == 3 )
513
    {
892 mhunt 514
      major.value = Integer.parseInt(field[0]);
515
      minor.value = Integer.parseInt(field[1]);
516
      patch.value = Integer.parseInt(field[2]);
814 mhunt 517
    }
518
    else
519
    {
888 mhunt 520
      if ( !mChangeType.mMajor &&
521
           !mChangeType.mMinor &&
522
           !mChangeType.mPatch &&
523
           mRippleField.mBuild &&
524
           mExtension.compareTo(".cots") == 0 &&
525
           field.length > 0 )
526
      {
527
        // DEVI 52782
528
        // allow and work with (ripple build) versions a.b.c.d....xxxx
529
        // where xxxx.length > 3
530
        String patchStr = field[field.length - 1];
531
        int patchLen = patchStr.length();
532
 
533
        // check patchStr is the last (at least 4) digits
534
        if ( patchLen > 3 && mVersion.substring( mVersion.length() - patchLen, mVersion.length() ).compareTo(patchStr) == 0 )
535
        {
892 mhunt 536
          patch.value = Integer.parseInt(patchStr);
888 mhunt 537
          nonStandardCotsVersion = mVersion.substring(0, mVersion.length() - patchLen );
538
        }
539
      }
540
 
541
      if ( nonStandardCotsVersion.length() == 0 )
542
      {
543
        // cannot work with non standard versioning
544
        mLogger.error("applyPV cannot work with non standard versioning");
545
        mLogger.info("applyPv returned 1");
546
        return 1;
547
      }
814 mhunt 548
    }
549
 
888 mhunt 550
    if ( nonStandardCotsVersion.length() == 0 &&
892 mhunt 551
         patch.value < 1000 && 
888 mhunt 552
         field[2].substring(0, 1).compareTo("0") != 0 )
814 mhunt 553
    {
554
      mLogger.info("applyPV accomodate old style mVersion of the form 1.0.1");
892 mhunt 555
      patch.value = patch.value * 1000;
814 mhunt 556
    }
557
 
558
    // mChangeType overrides mRippleField
559
    do
560
    {
561
      if ( mChangeType.mMajor )
562
      {
892 mhunt 563
        if ( !incrementFieldsAccordingToLimits(4, major, minor, patch) )
564
        {
565
          mLogger.info("applyPv returned 2");
566
          return 2;
567
        }
814 mhunt 568
      }
569
      else if ( mChangeType.mMinor )
570
      {
892 mhunt 571
        if ( !incrementFieldsAccordingToLimits(3, major, minor, patch) )
572
        {
573
          mLogger.info("applyPv returned 2");
574
          return 2;
575
        }
814 mhunt 576
      }
577
      else if ( mChangeType.mPatch )
578
      {
892 mhunt 579
        if ( !incrementFieldsAccordingToLimits(2, major, minor, patch) )
814 mhunt 580
        {
892 mhunt 581
          mLogger.info("applyPv returned 2");
582
          return 2;
583
        }
814 mhunt 584
      }
585
      else
586
      {
587
        if ( mRippleField.mMajor )
588
        {
892 mhunt 589
          major.value++;
590
          mLogger.info("applyPV mRippleField.mMajor " + major.value);
591
          minor.value = 0;
592
          patch.value = 0;
814 mhunt 593
        }
594
        else if ( mRippleField.mMinor )
595
        {
892 mhunt 596
          minor.value++;
597
          mLogger.info("applyPV mRippleField.mMinor " + minor.value);
598
          patch.value = 0;
814 mhunt 599
        }
600
        else if ( mRippleField.mPatch )
601
        {
602
          do
603
          {
892 mhunt 604
            patch.value++;
605
          } while ( ( patch.value / 1000 ) * 1000 != patch.value );
606
          mLogger.info("applyPV mRippleField.mPatch " + patch.value);
814 mhunt 607
        }
874 mhunt 608
        else if ( mRippleField.mBuild )
814 mhunt 609
        {
892 mhunt 610
          patch.value++;
611
          mLogger.info("applyPV mRippleField.mBuild " + patch.value);
814 mhunt 612
        }
874 mhunt 613
        else
614
        {
892 mhunt 615
          if ( !incrementFieldsAccordingToLimits(1, major, minor, patch) )
874 mhunt 616
          {
617
            mLogger.info("applyPv returned 2");
618
            return 2;
619
          }
620
        }
814 mhunt 621
      }
888 mhunt 622
 
623
      if ( nonStandardCotsVersion.length() == 0 )
624
      {
892 mhunt 625
        mVersion = String.valueOf(major.value) + "." + String.valueOf(minor.value) + ".";
888 mhunt 626
      }
627
      else
628
      {
629
        mVersion = nonStandardCotsVersion;
630
      }
814 mhunt 631
 
892 mhunt 632
      if ( patch.value < 10 )
814 mhunt 633
      {
634
        mVersion += "000";
635
      }
892 mhunt 636
      else if ( patch.value < 100 )
814 mhunt 637
      {
638
        mVersion += "00";
639
      }
892 mhunt 640
      else if ( patch.value < 1000 )
814 mhunt 641
      {
642
        mVersion += "0";
643
      }
644
 
892 mhunt 645
      mVersion += String.valueOf(patch.value);
814 mhunt 646
    } while ( exists(releaseManager, rtag_id) );
647
 
648
    releaseManager.claimVersion(mPid, mVersion + mExtension, rtag_id);
874 mhunt 649
    mLogger.info("applyPv returned 0");
650
    return 0;
814 mhunt 651
  }
652
 
892 mhunt 653
  /**increments fields according to mRippleField.mLimit if necessary
654
   * will apply it to the field passed as follows
655
   * 1 = build
656
   * 2 = patch
657
   * 3 = minor
658
   * other = major
659
   * returns true on success
660
   *         false on ripple field limitations prevent a ripple build
661
   */
662
  private boolean incrementFieldsAccordingToLimits(int field, MutableInt major, MutableInt minor, MutableInt patch)
663
  {
664
    boolean retVal = true;
665
 
902 mhunt 666
    if (!mChangeType.mLimit && !mRippleField.mLimit)
892 mhunt 667
    {
668
      // simple case
669
      // no need to take field limits into consideration
670
      switch (field)
671
      {
672
      case 1:
673
        // unreachable
674
        // the only scenario involving build number manipulation involves the mRippleField.mLimit being set
675
        retVal = false;
676
        break;
677
      case 2:
678
        do
679
        {
680
          patch.value++;
681
        } while ( ( patch.value / 1000 ) * 1000 != patch.value );
682
        mLogger.info("incrementFieldsAccordingToLimits patch " + patch.value);
683
        break;
684
      case 3:
685
        minor.value++;
686
        mLogger.info("incrementFieldsAccordingToLimits minor " + minor.value);
687
        patch.value = 0;
688
        break;
689
      default:
690
        major.value++;
691
        mLogger.info("incrementFieldsAccordingToLimits major " + major.value);
692
        minor.value = 0;
693
        patch.value = 0;
694
      }
695
    }
696
    else
697
    {
698
      // take field limits into consideration
699
      boolean changeOccurred = false;
700
      boolean incrementField = true;
701
 
702
      switch (field)
703
      {
704
      case 1:
705
        if ( mBuildLimit != 0 )
706
        {
707
          // increment or reset the patch build number
708
          int buildNumber = patch.value - (patch.value/1000) * 1000;
709
 
710
          if ( buildNumber < mBuildLimit )
711
          {
712
            // can increment the patch build number
713
            patch.value++;
714
            mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit build number " + patch.value);
715
            changeOccurred = true;
716
            incrementField = false;
717
          }
718
          else
719
          {
720
            if ( mPatchLimit == 0 )
721
            {
722
              // reset the patch number and patch build number
723
              patch.value = 0;
724
            }
725
          }
726
        }
727
        // no break by design
728
      case 2:
729
        if ( mPatchLimit != 0 && incrementField )
730
        {
731
          // increment or reset the patch number
732
          if ( ( patch.value / 1000 ) < mPatchLimit )
733
          {
734
            do
735
            {
736
              patch.value++;
737
            } while ( ( patch.value / 1000 ) * 1000 != patch.value );
738
 
739
            mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit patch " + patch.value);
740
            changeOccurred = true;
741
            incrementField = false;
742
          }
743
          else
744
          {
745
            // reset the patch number and patch build number
746
            patch.value = 0;
747
          }
748
        }
749
        // no break by design
750
      case 3:
751
        if ( mMinorLimit != 0 && incrementField )
752
        {
753
          // increment or reset the minor number
754
          if ( minor.value < mMinorLimit )
755
          {
756
            minor.value++;
757
            patch.value = 0;
758
            mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit minor " + minor.value);
759
            changeOccurred = true;
760
            incrementField = false;
761
          }
762
          else
763
          {
764
            // reset the minor number
765
            minor.value = 0;
766
          }
767
        }
768
        // no break by design
769
      default:
770
        if ( mMajorLimit != 0 && incrementField )
771
        {
772
          // increment or reset the major number
773
          if ( major.value < mMajorLimit )
774
          {
775
            // increment the major number
776
            changeOccurred = true;
777
            major.value++;
778
            minor.value = 0;
779
            patch.value = 0;
780
            mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit major " + major.value);
781
          }
782
        }
783
      }
784
 
785
      if ( !changeOccurred )
786
      {
787
        // unable to increment a field due to field limitations
788
        mLogger.error("incrementFieldsAccordingToLimits ripple field limitations prevent a ripple build");
789
        mLogger.info("incrementFieldsAccordingToLimits returned false");
790
        retVal = false;
791
      }
792
    }
793
 
794
    return retVal;
795
  }
796
 
814 mhunt 797
  /**returns true if the version exists in the dpkg_archive, deploy_archive or release manager database
798
   * claims the version in the release manager database
799
   */
800
  private boolean exists(ReleaseManager releaseManager, int rtag_id) throws Exception
801
  {
802
    mLogger.debug("exists 1 on Package " + mName + " version " + mVersion + " extension " + mExtension);
803
    boolean retVal = false;
804
 
864 mhunt 805
    if ( !ReleaseManager.mUseDatabase )
814 mhunt 806
    {
807
      mLogger.info("exists 1 !releaseManager.mUseDatabase");
808
    }
809
    else
810
    {
811
      retVal = exists();
812
 
813
      if ( !retVal )
814
      {
815
        String pkg_version = new String(mVersion);
816
 
817
        if ( mExtension.length() > 0 )
818
        {
819
          pkg_version += mExtension;
820
        }
821
 
822
        retVal = releaseManager.queryPackageVersions(mPid, pkg_version);
823
      }
824
    }
825
 
826
    mLogger.info("exists 1 returned " + retVal);
827
    return retVal;
828
  }
829
 
896 mhunt 830
  /**returns true if the dpkg_archive and deploy_archive exist
831
   * attempt to recover from their transient loss 
832
   */
833
  public static boolean recover()
834
  {
835
    mLogger.debug("recover");
836
    boolean retVal = false;
837
 
838
    String Release = mGbeDpkg;
839
    String Deploy = mGbeDply;
840
 
841
    if (Release != null && Deploy != null)
842
    {
843
      File dpkg = new File(mGbeDpkg);
844
      File dply = new File(mGbeDply);
845
 
846
      if ( dpkg.exists() && dply.exists() )
847
      {
848
        retVal = true;
849
      }
850
    }
851
 
852
    mLogger.info("recover returned " + retVal);
853
    return retVal;
854
  }
855
 
814 mhunt 856
  /**returns true if the version exists in the dpkg_archive or deploy_archive
857
   */
858
  boolean exists()
859
    throws Exception
860
  {
861
    mLogger.debug("exists 2 on Package " + mName);
862
    boolean retVal = false;
863
 
864
    String Release = mGbeDpkg;
865
    String Deploy = mGbeDply;
866
 
867
    if (Release == null || Deploy == null)
868
    {
868 mhunt 869
      mLogger.fatal("exists 2 Release == null || Deploy == null");
870
      throw new Exception("exists 2 Release == null || Deploy == null");
814 mhunt 871
    }
896 mhunt 872
 
873
    File dpkg = new File(mGbeDpkg);
874
    File dply = new File(mGbeDply);
875
 
876
    if ( !dpkg.exists() || !dply.exists() )
877
    {
878
      mLogger.fatal("exists 2 " + mRecoverable);
879
      throw new Exception(mRecoverable);
880
    }
814 mhunt 881
 
882
    String fs = System.getProperty( "file.separator" );
883
    String name = new String(Release);
884
    name += fs + mName + fs + mVersion + mExtension;
885
    File release = new File(name);
886
 
887
    if (release.exists())
888
    {
889
      mLogger.info("exists 2 release.exists()");
890
      retVal = true;
891
    }
892
 
893
    if (!retVal && (Release != Deploy))
894
    {
895
      name = Deploy + fs + mName + fs + mVersion + mExtension;
896
 
897
      File deploy = new File(name);
898
 
899
      if (deploy.exists())
900
      {
901
        mLogger.info("exists 2 deploy.exists()");
902
        retVal = true;
903
      }
904
    }
905
 
906
    mArchivalExistence = retVal;
907
    mLogger.info("exists 2 returned " + retVal);
908
    return retVal;
909
  }
854 mhunt 910
 
911
  /**returns email information
912
   */
913
  String emailInfo( String lf )
914
  {
915
    String retVal = new String();
916
 
864 mhunt 917
    for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); )
854 mhunt 918
    {
864 mhunt 919
      String email = it.next();
854 mhunt 920
      retVal +=
921
      "  <owner email=\"" + email +"\"/>" + lf;
922
    }
923
 
924
    return retVal;
925
  }
814 mhunt 926
 
866 mhunt 927
  /**returns email information
928
   */
929
  String emailInfoNonAntTask()
930
  {
931
    String retVal = null;
932
 
933
    for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); )
934
    {
935
      String email = it.next();
936
 
937
      if ( retVal == null )
938
      {
939
        retVal = new String();
940
      }
941
      else
942
      {
943
        retVal += ",";
944
      }
945
      retVal += email;
946
    }
947
 
948
    return retVal;
949
  }
950
 
864 mhunt 951
  /**adds email to mBuildFailureEmailCollection if unique
952
   */
953
  void addEmail( String email )
954
  {
955
    boolean alreadyExists = false;
956
 
957
    for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); )
958
    {
959
      String existingEmail = it.next();
960
 
961
      if ( existingEmail.compareTo(email) == 0 )
962
      {
963
        alreadyExists = true;
964
        break;
965
      }
966
    }
967
 
968
    if ( !alreadyExists )
969
    {
970
      mBuildFailureEmailCollection.add(email);
971
    }
972
  }
973
 
908 mhunt 974
  /**accessor method
975
   */
976
  void setEmail()
977
  {
978
    mBuildFailureEmailCollection.clear();
979
    addEmail( mTestBuildEmail );
980
  }
981
 
982
  /**accessor method
983
   */
984
  void setDependencyCollection()
985
  {
986
    // does not worry about mPackageDendencyCollection by design
987
    mDependencyCollection.clear();
988
 
989
    for (Iterator<String> it = mTestBuildDependencyCollection.iterator(); it.hasNext(); )
990
    {
991
      String dependency = it.next();
992
      mDependencyCollection.add(dependency);
993
    }
994
  }
995
 
996
  /**accessor method
997
   */
998
  void setBuildStandardCollection()
999
  {
1000
    mBuildStandardCollection.clear();
1001
 
1002
    for (Iterator<BuildStandard> it = mTestBuildStandardCollection.iterator(); it.hasNext(); )
1003
    {
1004
      BuildStandard buildStandard = it.next();
1005
      mBuildStandardCollection.add(buildStandard);
1006
    }
1007
  }
1008
 
1009
  /**sends email notification and marks the instruction complete in the database
1010
   */
1011
  public void completeTestBuild( String mailServer, String mailSender, ReleaseManager releaseManager, String release, boolean success ) throws SQLException, Exception
1012
  {
1013
    mLogger.debug("completeTestBuild");
1014
 
1015
    if ( mTestBuildInstruction == 0)
1016
    {
1017
      return;
1018
    }
1019
 
1020
    String mailBody="Test build issues are identified in preceding build failure email.<p>" +
1021
                    "Release: " + release + "<br>" +
1022
                    "Package: " + mAlias + "<br>" +
1023
                    "Label: " + mLabel + "<br>" +
1024
                    "Location: " + mLocation + "<p>" +
1025
                    "Build dependencies:<p>";
1026
 
1027
    for (Iterator<Package> it3 = mPackageDependencyCollection.iterator(); it3.hasNext(); )
1028
    {
1029
      Package depend = it3.next();
1030
 
1031
      String dependsExtension = depend.mExtension;
1032
      String dependsVersion = depend.mVersion;
1033
 
1034
      if ( dependsExtension.length() > 0 )
1035
      {
1036
        dependsVersion += dependsExtension;
1037
      }
1038
      mailBody += "\'" + depend.mName + "\',\'" + dependsVersion + "\' <br>";
1039
    }
1040
 
1041
    mailBody += "<br>Build standards:<p>";
1042
 
1043
    for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); )
1044
    {
1045
      BuildStandard bs = it.next();
1046
 
1047
      String platform = bs.getPlatform(!ReleaseManager.mUseDatabase, false);
1048
 
1049
      if ( platform.length() > 0 )
1050
      {
1051
        mailBody += platform + ", ";
1052
      }
1053
 
1054
      String standard = bs.getBuildStandard(!ReleaseManager.mUseDatabase, false);
1055
 
1056
      if ( standard.length() > 0 )
1057
      {
1058
        mailBody += standard + "<br>";
1059
      }
1060
    }
1061
 
1062
    try
1063
    {
1064
      Smtpsend.send(
1065
      mailServer, // mailServer
1066
      mailSender, // source
1067
      emailInfoNonAntTask(), // target
1068
      null, // cc
1069
      null, // bcc
1070
      success == true ? "TEST BUILD COMPLETED SUCCESSFULLY" : "TEST BUILD FAILED", // subject
1071
      mailBody, // body
1072
      null // attachment
1073
      );
1074
    }
1075
    catch( Exception e )
1076
    {
1077
    }
1078
 
1079
    releaseManager.markDaemonInstCompletedConnect(mTestBuildInstruction);
1080
  }
1081
 
910 mhunt 1082
  /**returns true if the package has a circular dependency
1083
   */
1084
  public boolean hasCircularDependency(RippleEngine ripEng)
1085
  {
1086
    mLogger.debug("hasCircularDependency");
1087
    boolean retVal = detectCircularDependency( mAlias, ripEng );
1088
    mLogger.info("hasCircularDependency returned " + retVal);
1089
    return retVal;
1090
  }
1091
 
1092
  /**returns true if the package has a circular dependency
1093
   */
1094
  public boolean detectCircularDependency(String alias, RippleEngine ripEng)
1095
  {
1096
    mLogger.debug("detectCircularDependency");
1097
    boolean retVal = false;
1098
 
1099
    // if this package has yet to be checked for circular dependency
1100
    if ( !mCheckedCircularDependency )
1101
    {
1102
      for (Iterator<String> it2 = mDependencyCollection.iterator(); it2.hasNext(); )
1103
      {
1104
        String dependencyAlias = it2.next();
1105
 
1106
        // check its direct dependencies for an alias match
1107
        if ( alias.compareTo( dependencyAlias ) == 0 )
1108
        {
1109
          retVal = true;
1110
          break;
1111
        }
1112
 
1113
        Package dependency = ripEng.findPackage( dependencyAlias );
1114
 
1115
        // check its indirect dependencies for an alias match
1116
        if ( dependency.detectCircularDependency(alias, ripEng) )
1117
        {
1118
          retVal = true;
1119
          break;
1120
        }
1121
      }
1122
      // mark the check complete
1123
      mCheckedCircularDependency = true;
1124
      // persist the circular dependency outcome
1125
      mHasCircularDependency = retVal;
1126
    }
1127
    else
1128
    {
1129
      // return the persisted circular dependency outcome
1130
      retVal = mHasCircularDependency;
1131
    }
1132
    mLogger.info("detectCircularDependency 2 returned " + retVal);
1133
    return retVal;
1134
  }
1135
 
814 mhunt 1136
  /**entity class supporting the ERG version numbering standard:
1137
   * <major>.<minor>.<patch/build>
1138
   * patch/build is at least a 4 digit number whose last 3 digits represent the build
1139
   */
1140
  public class VersionNumberingStandard
1141
  {
1142
    /**in terms of the mChangeType Package field,
1143
     * when true indicates the contract of the package has changed in a non backwardly compatible manner
1144
     * in terms of the mRippleField Package field,
1145
     * when true indicates the major version number will be incremented
1146
     * @attribute
1147
     */
1148
    private boolean mMajor = false;
1149
 
1150
    /**in terms of the mChangeType Package field,
1151
     * when true indicates the contract of the package has changed in a backwardly compatible manner
1152
     * in terms of the mRippleField Package field,
1153
     * when true indicates the minor version number will be incremented
1154
     * @attribute
1155
     */
1156
    private boolean mMinor = false;
1157
 
1158
    /**in terms of the mChangeType Package field,
1159
     * when true indicates the contract of the package has not changed, but the package has changed internally
1160
     * in terms of the mRippleField Package field,
1161
     * when true indicates the minor version number will be incremented
1162
     * @attribute
1163
     */
1164
    private boolean mPatch = false;
1165
 
1166
    /**in terms of the mChangeType Package field,
1167
     * when true indicates the package has not changed, its dependencies potentially have
1168
     * in terms of the mRippleField Package field,
1169
     * when true indicates the build number will be incremented
1170
     * @attribute
1171
     */
1172
    private boolean mBuild = true;
1173
 
874 mhunt 1174
    /**in terms of the mChangeType Package field,
902 mhunt 1175
     * when true indicates the major, minor, and patch number will be incremented according to field limits
874 mhunt 1176
     * in terms of the mRippleField Package field,
1177
     * when true indicates the major, minor, patch and build number will be incremented according to field limits
1178
     * @attribute
1179
     */
1180
    private boolean mLimit = false;
1181
 
814 mhunt 1182
    /**constructor
1183
     */
1184
    private VersionNumberingStandard()
1185
    {
1186
      mLogger.debug("VersionNumberingStandard");
1187
    }
1188
 
874 mhunt 1189
    /**sets mBuild true, mMajor false, mMinor false, mPatch false, mLimit false
814 mhunt 1190
     */
1191
    void setBuild()
1192
    {
1193
      mLogger.debug("setBuild");
1194
      mBuild = true;
1195
      mMajor = false;
1196
      mMinor = false;
1197
      mPatch = false;
874 mhunt 1198
      mLimit = false;
814 mhunt 1199
    }
1200
 
874 mhunt 1201
    /**sets mBuild false, mMajor true, mMinor false, mPatch false, mLimit false
814 mhunt 1202
     */
1203
    void setMajor()
1204
    {
1205
      mLogger.debug("setMajor");
1206
      mBuild = false;
1207
      mMajor = true;
1208
      mMinor = false;
1209
      mPatch = false;
874 mhunt 1210
      mLimit = false;
814 mhunt 1211
    }
1212
 
902 mhunt 1213
    /**sets mBuild false, mMajor true, mMinor false, mPatch false, mLimit limit
1214
     */
1215
    void setMajor( boolean limit )
1216
    {
1217
      mLogger.debug("setMajor " + limit);
1218
      mBuild = false;
1219
      mMajor = true;
1220
      mMinor = false;
1221
      mPatch = false;
1222
      mLimit = limit;
1223
    }
1224
 
874 mhunt 1225
    /**sets mBuild false, mMajor false, mMinor true, mPatch false, mLimit false
814 mhunt 1226
     */
1227
    void setMinor()
1228
    {
1229
      mLogger.debug("setMinor");
1230
      mBuild = false;
1231
      mMajor = false;
1232
      mMinor = true;
1233
      mPatch = false;
874 mhunt 1234
      mLimit = false;
814 mhunt 1235
    }
1236
 
902 mhunt 1237
    /**sets mBuild false, mMajor false, mMinor true, mPatch false, mLimit limit
1238
     */
1239
    void setMinor( boolean limit )
1240
    {
1241
      mLogger.debug("setMinor " + limit);
1242
      mBuild = false;
1243
      mMajor = false;
1244
      mMinor = true;
1245
      mPatch = false;
1246
      mLimit = limit;
1247
    }
1248
 
874 mhunt 1249
    /**sets mBuild false, mMajor false, mMinor false, mPatch true, mLimit false
814 mhunt 1250
     */
1251
    void setPatch()
1252
    {
1253
      mLogger.debug("setPatch");
1254
      mBuild = false;
1255
      mMajor = false;
1256
      mMinor = false;
1257
      mPatch = true;
874 mhunt 1258
      mLimit = false;
814 mhunt 1259
    }
1260
 
902 mhunt 1261
    /**sets mBuild false, mMajor false, mMinor false, mPatch true, mLimit limit
1262
     */
1263
    void setPatch( boolean limit )
1264
    {
1265
      mLogger.debug("setPatch");
1266
      mBuild = false;
1267
      mMajor = false;
1268
      mMinor = false;
1269
      mPatch = true;
1270
      mLimit = limit;
1271
    }
1272
 
874 mhunt 1273
    /**sets mBuild false, mMajor false, mMinor false, mPatch false, mLimit true
1274
     */
1275
    void setLimit()
1276
    {
1277
      mLogger.debug("setPatch");
1278
      mBuild = false;
1279
      mMajor = false;
1280
      mMinor = false;
1281
      mPatch = false;
1282
      mLimit = true;
1283
    }
1284
 
814 mhunt 1285
  }
1286
 
1287
}