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
 
5
import java.sql.SQLException;
6
 
7
import java.util.Iterator;
866 mhunt 8
import java.util.ListIterator;
814 mhunt 9
import java.util.Vector;
10
 
11
import org.apache.log4j.Logger;
12
 
830 mhunt 13
import java.util.regex.PatternSyntaxException;
14
 
814 mhunt 15
/**Plans release impact by generating a set of Strings containing build file content.
16
 */
17
public class RippleEngine
18
{
19
  /**collection of gbemachtypes in String form associated with the baseline
20
   * limited to the following items "win32", "sparc", "solaris10_sparc32", "solaris10_x86", "linux_i386"
21
   * accessed by Package::isLinuxBuilt, isSolarisBuilt, isWin32Built
22
   * @attribute
23
   */
864 mhunt 24
  Vector<String> mGbeMachtypeCollection = new Vector<String>();
866 mhunt 25
 
814 mhunt 26
  /**configured mail server
27
   * @attribute
28
   */
868 mhunt 29
  public String mMailServer = new String();
814 mhunt 30
 
31
  /**configured mail sender user
32
   * @attribute
33
   */
868 mhunt 34
  public String mMailSender = new String();
814 mhunt 35
 
868 mhunt 36
  /**configured global email target
37
   * @attribute
38
   */
39
  public String mGlobalTarget = new String();
40
 
814 mhunt 41
  /**name associated with the baseline
42
   * @attribute
43
   */
868 mhunt 44
  public String mBaselineName = new String();
814 mhunt 45
 
46
  /**collection of released pv_ids associated with the release
47
   * @attribute
48
   */
864 mhunt 49
  Vector<Integer> mReleasedPvIDCollection = new Vector<Integer>();
814 mhunt 50
 
51
  /**timestamp associated with build file generation
52
   * @attribute
53
   */
54
  long mTimestamp = 0;
55
 
56
  /**set to "non generic", "generic" or "dummy" to indicate the nature of the package in the build file in daemon mode
57
   * @attribute
58
   */
59
  String mAddendum = new String("dummy");
60
 
866 mhunt 61
  /**collection of build exceptions associated with the baseline
62
  /* used to determine (and report) what change in build exceptions happens as part of planRelease
63
   * deamon centric
64
   * @aggregation shared
65
   * @attribute
66
   */
67
  Vector<BuildExclusion> mBuildExclusionCollection = new Vector<BuildExclusion>();
68
 
814 mhunt 69
  /**Logger
70
   * @attribute
71
   */
72
  private static final Logger mLogger = Logger.getLogger(RippleEngine.class);
73
 
830 mhunt 74
  /**collection of escrow clearcase support file content in String form, set_up
814 mhunt 75
   * @attribute
76
   */
864 mhunt 77
  private Vector<String> mEscrowClearcaseSupportCollection = new Vector<String>();
814 mhunt 78
 
79
  /**package versions representing the baseline
866 mhunt 80
   * escrow centric
814 mhunt 81
   * @aggregation shared
82
   * @attribute
83
   */
864 mhunt 84
  private Vector<Package> mPackageCollection = new Vector<Package>();
814 mhunt 85
 
86
  /**index to current String item
87
   * @attribute
88
   */
89
  private int mBuildIndex;
90
 
91
  /**Database abstraction
92
   * @attribute
93
   */
94
  private ReleaseManager mReleaseManager;
95
 
96
  /**Baseline identifier (rtag_id for a release manager baseline, bom_id for deployment manager baseline)
97
   * @attribute
98
   */
99
  private int mBaseline;
100
 
101
  /**When true, mBuildCollection contains one item based on a release manager rtag_id and contains a daemon property
102
   * When false, mBuildCollection contains at least one item based on a deployment manager bom_id
103
   * Will be accessed by the Package class to calculate its mAlias
104
   * @attribute
105
   */
106
  boolean mDaemon;
107
 
108
  /**collection of build file content in String form
109
   * @attribute
110
   */
864 mhunt 111
  private Vector<String> mBuildCollection = new Vector<String>();
814 mhunt 112
 
113
  /**constructor
114
   */
115
  public RippleEngine(ReleaseManager releaseManager, int rtag_id, 
116
                      boolean isDaemon)
117
  {
118
    mLogger.debug("RippleEngine rtag_id " + rtag_id + " isDaemon " + isDaemon);
119
    mReleaseManager = releaseManager;
120
    mBaseline = rtag_id;
121
    mDaemon = isDaemon;
122
  }
123
 
124
  /**discards all build file content
125
   * plans new build file content
126
   */
127
  public void planRelease() throws SQLException, Exception
128
  {
129
    mLogger.warn("planRelease mDaemon " + mDaemon);
130
    mAddendum = "dummy";
131
    mBuildCollection.removeAllElements();
132
    mPackageCollection.removeAllElements();
133
    mReleasedPvIDCollection.removeAllElements();
134
 
135
    if ( !mDaemon )
136
    {
137
      mEscrowClearcaseSupportCollection.removeAllElements();  
138
    }
139
 
898 mhunt 140
    // use finally block in planRelease to ensure releaseMutex is called
141
    try
142
    {
143
      mReleaseManager.connect();
814 mhunt 144
 
898 mhunt 145
      if ( mDaemon )
866 mhunt 146
      {
898 mhunt 147
        // claim the mutex
148
        mReleaseManager.claimMutex();
149
        mBuildExclusionCollection.removeAllElements();
150
        Vector<BuildExclusion> tempBuildExclusionCollection = new Vector<BuildExclusion>();
866 mhunt 151
 
898 mhunt 152
        mReleaseManager.queryBuildExclusions(tempBuildExclusionCollection, mBaseline);
153
 
154
        // only populate mBuildExclusionCollection with tempBuildExclusionCollection entries which have a relevant root_pv_id
155
        // ie the root_pv_id is ONLY relevant if it is null (-1) or it points to a pv_id in the collection
156
        // the package with a pv_id which is a root_pv_id may be removed ie when fixing a build issue
157
        for (Iterator<BuildExclusion> it = tempBuildExclusionCollection.iterator(); it.hasNext(); )
866 mhunt 158
        {
898 mhunt 159
          BuildExclusion buildExclusion = it.next();
160
 
161
          if ( buildExclusion.isRelevant(tempBuildExclusionCollection) )
162
          {
163
            mBuildExclusionCollection.add(buildExclusion);
164
          }
165
          else
166
          {
167
            // this is just a cosmetic step
168
            // it includes package versions which have been indirectly excluded
169
            // the build daemon ignores this information, but it serves to clarify this point to users
170
            buildExclusion.includeToBuild(mReleaseManager, mBaseline);
171
          }
866 mhunt 172
        }
173
      }
898 mhunt 174
 
175
      mReleaseManager.queryPackageVersions(this, mPackageCollection, mDaemon, mBaseline);
176
 
177
      // set up mPackageDependencyCollection
178
      for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 179
      {
898 mhunt 180
        Package p = it.next();
181
 
182
        for (Iterator<String> it2 = p.mDependencyCollection.iterator(); it2.hasNext(); )
814 mhunt 183
        {
898 mhunt 184
          String alias = it2.next();
185
          Package dependency = findPackage(alias);
186
 
902 mhunt 187
          p.mPackageDependencyCollection.add(dependency);
188
        }
189
      }
190
 
191
      // DEVI 55483 now use the fully built mPackageDependencyCollection (in rippleBuildExclude)
192
      for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
193
      {
194
        Package p = it.next();
195
 
196
        for (Iterator<String> it2 = p.mDependencyCollection.iterator(); it2.hasNext(); )
197
        {
198
          String alias = it2.next();
199
          Package dependency = findPackage(alias);
200
 
898 mhunt 201
          if (dependency == ReleaseManager.NULL_PACKAGE)
202
          {
203
            mLogger.info("planRelease dependency is not in the baseline " + alias);
204
            // exclude all dependent packages
205
            // max 50 chars
900 mhunt 206
            rippleBuildExclude(p, p.mId, "Package build dependency not in the release", null, null);
898 mhunt 207
 
208
            // take the package out of the build
209
            p.mBuildFile = -4;
210
            mLogger.info("planRelease set mBuildFile to -4 for package " + p.mAlias );
211
            break;
212
          }
814 mhunt 213
        }
214
      }
902 mhunt 215
 
898 mhunt 216
      // process packages which are not reproducible, and all packages dependent upon them      
217
      for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 218
      {
898 mhunt 219
        Package p = it.next();
220
 
221
        if (p.mBuildFile == 0)
814 mhunt 222
        {
898 mhunt 223
          // package has yet to be processed
224
          if (!p.isReproducible())
225
          {
226
            // for escrow build purposes, exclude all dependent package versions
227
            mLogger.info("planRelease package not reproducible " + p.mName);
228
            // max 50 chars
900 mhunt 229
            rippleBuildExclude(p, p.mId, "Package has no build environment", null, null);
898 mhunt 230
 
231
            // package is not reproducible, discard
232
            p.mBuildFile = -1;
233
            mLogger.info("planRelease set mBuildFile to -1 for package " + p.mAlias );
234
          }
814 mhunt 235
        }
236
      }
898 mhunt 237
 
238
      // process packages which are not reproducible on the build platforms configured for this baseline
239
      for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 240
      {
898 mhunt 241
        Package p = it.next();
858 mhunt 242
 
898 mhunt 243
        if (p.mBuildFile == 0)
814 mhunt 244
        {
898 mhunt 245
          // package has yet to be processed
246
          // assume it does not need to be reproduced for this baseline
247
          boolean reproduce = false;
248
 
249
          for (Iterator<String> it2 = mGbeMachtypeCollection.iterator(); it2.hasNext(); )
814 mhunt 250
          {
898 mhunt 251
            String machtype = it2.next();
252
 
253
            if ( machtype.compareTo("linux_i386") == 0 )
814 mhunt 254
            {
898 mhunt 255
              if ( p.isLinuxBuilt() )
256
              {
257
                reproduce = true;
258
                mLogger.info("planRelease package built on linux " + p.mAlias );
259
                break;
260
              }
814 mhunt 261
            }
898 mhunt 262
            else if ( machtype.compareTo("win32") == 0 )
814 mhunt 263
            {
898 mhunt 264
              if ( p.isWin32Built() )
265
              {
266
                reproduce = true;
267
                mLogger.info("planRelease package built on win32 " + p.mAlias );
268
                break;
269
              }
814 mhunt 270
            }
898 mhunt 271
            else if ( machtype.compareTo("sparc") == 0
272
                   || machtype.compareTo("solaris10_x86") == 0
273
                   || machtype.compareTo("solaris10_sparc32") == 0 )
814 mhunt 274
            {
898 mhunt 275
              if ( p.isSolarisBuilt() )
276
              {
277
                reproduce = true;
278
                mLogger.info("planRelease package built on solaris " + p.mAlias );
279
                break;
280
              }
814 mhunt 281
            }
282
          }
898 mhunt 283
 
284
          if ( !reproduce )
285
          {
286
            // for escrow build purposes, exclude all dependent package versions
287
            mLogger.info("planRelease package not reproducible on the build platforms configured for this baseline " + p.mName);
288
            // max 50 chars
900 mhunt 289
            rippleBuildExclude(p, p.mId, "Package not built for configured platforms", null, null);
898 mhunt 290
 
291
            // package is not reproducible on the build platforms configured for this baseline, discard
292
            p.mBuildFile = -2;
293
            mLogger.info("planRelease set mBuildFile to -2 for package " + p.mAlias );
294
          }
858 mhunt 295
        }
898 mhunt 296
      }      
297
 
298
      if (mDaemon)
814 mhunt 299
      {
898 mhunt 300
        // process packages which are not ripple buildable, and all packages dependent upon them
301
        for (ListIterator<BuildExclusion> it = mBuildExclusionCollection.listIterator(); it.hasNext(); )
814 mhunt 302
        {
898 mhunt 303
          BuildExclusion be = it.next();
866 mhunt 304
 
898 mhunt 305
          for (Iterator<Package> it1 = mPackageCollection.iterator(); it1.hasNext(); )
814 mhunt 306
          {
898 mhunt 307
            Package p = it1.next();
308
 
900 mhunt 309
            // ensure only root cause build exclusions are excluded
310
            // mBuildExclusionCollection is at this point based on
311
            // relevant (direct and indirect) excluded pv's in the database
312
            if ( be.compare(p.mId) && be.isARootCause() )
866 mhunt 313
            {
900 mhunt 314
              // package is not reproducible, discard
315
              rippleBuildExclude( p, p.mId, null, it, be );
316
              p.mBuildFile = -3;
317
              mLogger.info("planRelease set mBuildFile to -3 for package " + p.mAlias );
898 mhunt 318
              break;
866 mhunt 319
            }
814 mhunt 320
          }
321
        }
898 mhunt 322
 
323
        // process packages which need to be ripple built
324
        for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 325
        {
898 mhunt 326
          Package p = it.next();
327
 
328
          if (p.mBuildFile == 0)
814 mhunt 329
          {
898 mhunt 330
            // package has yet to be processed
331
            if (p.mDirectlyPlanned)
814 mhunt 332
            {
898 mhunt 333
              // a WIP exists on the package
334
              // exclude all dependent package versions
335
              mLogger.info("planRelease package has WIP " + p.mName);
336
              rippleIndirectlyPlanned(p);
337
            }
338
            else
339
            {
340
              Iterator<Integer> it2 = p.mDependencyIDCollection.iterator();
341
              Iterator<Package> it3 = p.mPackageDependencyCollection.iterator();
342
              for ( ; it2.hasNext() && it3.hasNext(); )
814 mhunt 343
              {
898 mhunt 344
                Integer dpv_id = it2.next();
345
                Package dependency = it3.next();
346
 
347
                if ( !dependency.mAdvisoryRipple )
814 mhunt 348
                {
898 mhunt 349
                  // not advisory, ie has ripple build impact
350
                  boolean found = false;
351
 
352
                  for ( Iterator<Integer> it4 = mReleasedPvIDCollection.iterator(); it4.hasNext(); )
814 mhunt 353
                  {
898 mhunt 354
                    Integer pv_id = it4.next();
355
 
356
                    if ( pv_id.compareTo(dpv_id) == 0 )
357
                    {
358
                      found = true;
359
                      break;
360
                    }
361
                  }
362
 
363
                  if ( !found )
364
                  {
365
                    // the package is out of date
366
                    // exclude all dependent package versions
367
                    mLogger.info("planRelease package out of date " + p.mName);
368
                    rippleIndirectlyPlanned(p);                 
814 mhunt 369
                    break;
370
                  }
371
                }
372
              }
373
            }
374
          }
375
        }
898 mhunt 376
 
377
        // process packages which do not exist in the archive
378
        for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 379
        {
898 mhunt 380
          Package p = it.next();
381
 
382
          if (p.mBuildFile == 0)
814 mhunt 383
          {
898 mhunt 384
            // package has yet to be processed
385
            // for unit test purposes, assume all packages exist in the archive if released
386
            if ( ReleaseManager.mUseDatabase )
814 mhunt 387
            {
898 mhunt 388
              // only check existence outside the unit test
389
              if (!p.mDirectlyPlanned && !p.mIndirectlyPlanned)
814 mhunt 390
              {
898 mhunt 391
                // check package version archive existence
392
                if (!p.exists())
393
                {
394
                  mLogger.info("planRelease package not found in archive " + p.mName);
395
                  // DEVI 47395 the cause of this build is not WIP or ripple induced,
396
                  // it simply does not exist in the archive (has been removed)
397
                  // prevent source control interaction
398
                  p.mRequiresSourceControlInteraction = false;
399
                  rippleIndirectlyPlanned(p);
400
                }
814 mhunt 401
              }
402
            }
403
          }
404
        }
405
      }
826 mhunt 406
 
898 mhunt 407
      // process remaining packages which need to be reproduced for this baseline
408
      // determine the build file for each package
409
      // for daemon builds, determine the first package that can be built now, this means the first package not dependent upon packages also to be built
410
      // set its mBuildNumber to 1, all remaining reproducible packages to 2
411
      // for escrow builds, determine the package versions that can be built in the build iteration
412
      // set their mBuildNumber to the build iteration
413
      // increment the build iteration and repeat until all package versions that need to be reproduced have been assigned a build iteration
414
      boolean allProcessed = false;
415
      int buildFile = 1;
416
 
417
      // delete the file <rtagId>official
418
      Integer rtag = new Integer(mBaseline);
419
      File rtagIdOfficial = new File(rtag + "official");
420
 
421
      if (rtagIdOfficial.exists())
826 mhunt 422
      {
898 mhunt 423
        boolean del = rtagIdOfficial.delete();
424
 
826 mhunt 425
        if ( !del )
426
        {
898 mhunt 427
          // the delete failed
428
          // some literature suggests a forced garbage collection may free up resources associated with file handles
429
          // nothing to lose since the file "must" be deleted
430
          System.gc();
431
          del = rtagIdOfficial.delete();
432
 
433
          if ( !del )
434
          {
435
            mLogger.fatal("rtagIdOfficial.delete() returned " + del);
436
          }
826 mhunt 437
        }
438
      }
814 mhunt 439
 
898 mhunt 440
      String raw_data = new String("");
441
      String lf = new String( System.getProperty("line.separator") );
442
 
814 mhunt 443
      do
444
      {
898 mhunt 445
        boolean allDependenciesProcessed = true;
814 mhunt 446
 
898 mhunt 447
        do
814 mhunt 448
        {
898 mhunt 449
          // assume all dependencies have been processed
450
          allDependenciesProcessed = true;
814 mhunt 451
 
898 mhunt 452
          for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 453
          {
898 mhunt 454
            Package p = it.next();
455
 
456
            if ( mDaemon && ( ( !p.mDirectlyPlanned && !p.mIndirectlyPlanned ) || p.mBuildFile < 0 ) )
814 mhunt 457
            {
898 mhunt 458
              // flag packages with no build requirement as processed in daemon mode
459
              p.mProcessed = true;
460
              mLogger.info("planRelease package has no build requirement " + p.mName);            
461
            }
462
            else
463
            {
464
              if ( ( p.mBuildFile == 0 ) && ( (mDaemon && ( p.mDirectlyPlanned || p.mIndirectlyPlanned ) ) || ( !mDaemon ) ) )
814 mhunt 465
              {
898 mhunt 466
                // package yet to be processed and
467
                // in daemon mode has a build requirement or
468
                // in escrow mode
469
                boolean canBeBuiltNow = true;
470
                boolean allDependenciesForThisPackageProcessed = true;
814 mhunt 471
 
898 mhunt 472
                for ( Iterator<Package> it2 = p.mPackageDependencyCollection.iterator(); it2.hasNext(); )
814 mhunt 473
                {
898 mhunt 474
                  Package dependency = it2.next();
475
 
476
                  if ( !dependency.mProcessed )
814 mhunt 477
                  {
898 mhunt 478
                    // cannot determine canBeBuiltNow until this dependency has been processed
479
                    allDependenciesForThisPackageProcessed = false;
480
                    allDependenciesProcessed = false;
814 mhunt 481
                  }
898 mhunt 482
                  else if ( ( mDaemon && ( dependency.mDirectlyPlanned ) || ( dependency.mIndirectlyPlanned ) ) || 
483
                            ( !mDaemon &&
484
                              ( ( dependency.mBuildFile == 0 ) ||
485
                                ( dependency.mBuildFile == buildFile &&
486
                                  ( ( p.isLinuxBuilt() && !dependency.isLinuxBuilt() ) ||
487
                                    ( p.isWin32Built() && !dependency.isWin32Built() ) ||
488
                                    ( p.isSolarisBuilt() && !dependency.isSolarisBuilt() ) ||
489
                                    ( !p.isLinuxBuilt() && dependency.isLinuxBuilt() ) ||
490
                                    ( !p.isWin32Built() && dependency.isWin32Built() ) ||
491
                                    ( !p.isSolarisBuilt() && dependency.isSolarisBuilt() ) ) ) ) ) )
814 mhunt 492
                  {
898 mhunt 493
                    // in daemon mode this processed dependency has a build requirement or
494
                    // in escrow mode...
495
                    // this processed dependency has not been assigned to a build iteration or
496
                    // this processed dependency has been assigned to this build iteration and does not build on this platform
497
                    canBeBuiltNow = false;
498
                    mLogger.info("planRelease package cannot be built in this iteration " + p.mName);
499
                    break;
814 mhunt 500
                  }
501
                }
898 mhunt 502
 
503
                if (allDependenciesForThisPackageProcessed)
814 mhunt 504
                {
898 mhunt 505
                  p.mProcessed = true;
506
 
507
                  if ( mDaemon )
814 mhunt 508
                  {
898 mhunt 509
                    if ( canBeBuiltNow )
848 dpurdie 510
                    {
898 mhunt 511
                      // flag package with build requirement, may get downgraded to future build requirement
512
                      p.mBuildFile = 1;
513
                      mLogger.info("planRelease set mBuildFile to 1 for package " + p.mAlias );
514
                    }
515
                    else
516
                    {
517
                      // flag package with future build requirement
518
                      p.mBuildFile = 2;
519
                      mLogger.info("planRelease set mBuildFile to 2 for package " + p.mAlias );
520
                    }
521
                  }
522
                  else
523
                  {
524
                    if ( canBeBuiltNow )
525
                    {
526
                      if ( !mDaemon )
848 dpurdie 527
                      {
898 mhunt 528
                        String isWin32Built = new String("");
529
 
530
                        if ( p.isWin32Built() )
531
                        {
532
                          isWin32Built = "W";
533
                        }
534
 
535
                        String isLinuxBuilt = new String("");
536
 
537
                        if ( p.isLinuxBuilt() )
538
                        {
539
                          isLinuxBuilt = "L";
540
                        }
541
 
542
                        String isSolarisBuilt = new String("");
543
 
544
                        if ( p.isSolarisBuilt() )
545
                        {
546
                          isSolarisBuilt = "S";
547
                        }
548
 
549
                        String isGeneric = new String("");
550
 
551
                        if ( p.isGeneric() )
552
                        {
553
                          isGeneric = "G";
554
                        }
555
 
556
                        raw_data += p.mAlias + "," +
557
                                    isWin32Built + "," +
558
                                    isLinuxBuilt + "," +
559
                                    isSolarisBuilt + "," +
560
                                    isGeneric + "," +
561
                                    buildFile +
562
                                    lf;
848 dpurdie 563
                      }
564
 
898 mhunt 565
                      // not daemon
566
                      p.mBuildFile = buildFile;
567
                      mLogger.info("planRelease set mBuildFile to " + buildFile + " for package " + p.mAlias );
848 dpurdie 568
                    }
814 mhunt 569
                  }
570
                }
571
              }
572
            }
573
          }
898 mhunt 574
        } while( !allDependenciesProcessed );
575
 
576
        if ( mDaemon )
814 mhunt 577
        {
898 mhunt 578
          for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 579
          {
898 mhunt 580
            Package p = it.next();
581
 
582
            if ( p.mProcessed && p.mBuildFile == 1 )
814 mhunt 583
            {
898 mhunt 584
              p.mBuildFile = buildFile;
585
              mLogger.info("planRelease 2 set mBuildFile to " + buildFile + " for package " + p.mAlias );
586
 
587
              if ( buildFile == 1 )
874 mhunt 588
              {
898 mhunt 589
                int pvApplied = p.applyPV(mReleaseManager, mBaseline);
590
 
591
                if ( pvApplied == 1 )
592
                {
593
                  // max 50 chars
900 mhunt 594
                  rippleBuildExclude(p, p.mId, "Package has non standard versioning", null, null);
898 mhunt 595
                }
596
                else
597
                if ( pvApplied == 2 )
598
                {
599
                  // max 50 chars
900 mhunt 600
                  rippleBuildExclude(p, p.mId, "Package has reached ripple field limitations", null, null);
898 mhunt 601
                }
602
                else
603
                {
604
                  buildFile = 2;
605
                }
874 mhunt 606
              }
607
              else
608
              {
898 mhunt 609
                mLogger.info("planRelease package has future (downgraded) build requirement " + p.mName + " " + buildFile);              
874 mhunt 610
              }
814 mhunt 611
            }
898 mhunt 612
          }
613
        }
614
 
615
        // are more build files required
616
        allProcessed = true;
617
 
618
        if (mDaemon)
619
        {
620
          for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
621
          {
622
            Package p = it.next();
623
 
624
            if ( p.mBuildFile < 0 || ( !p.mDirectlyPlanned && !p.mIndirectlyPlanned ) )
814 mhunt 625
            {
898 mhunt 626
              // at this point...
627
              // only 1 package with a build requirement has a mBuildFile of 1,
628
              // all other packages with a build requirement have an mBuildFile of 2
629
              // give packages with no build requirement, reproducible or not, an mBuildFile of 3
630
              p.mBuildFile = 3;
631
              mLogger.info("planRelease 1 set mBuildFile to 3 for package " + p.mAlias );
814 mhunt 632
            }
633
          }
634
        }
898 mhunt 635
        else
636
        {
637
          // this is escrow mode centric
638
          for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
639
          {
640
            Package p = it.next();
641
 
642
            if ( p.mBuildFile == 0 )
643
            {
644
              // more build files are required
645
              allProcessed = false;
646
              mLogger.info("planRelease more build files are required for " + p.mName);
647
              break;
648
            }
649
          }
650
 
651
          buildFile++;
652
        }
653
      } while( !allProcessed );
814 mhunt 654
 
898 mhunt 655
      // persist the build files
656
      allProcessed = false;
657
      buildFile = 1;
814 mhunt 658
 
898 mhunt 659
      if ( mDaemon )
814 mhunt 660
      {
898 mhunt 661
        // all interesting packages in daemon mode match the following filter
662
        buildFile = 3;
663
      }
664
 
665
      mTimestamp = System.currentTimeMillis();
666
 
667
      if ( !ReleaseManager.mUseDatabase )
668
      {
669
        mTimestamp = 123456789;
670
      }
671
 
672
      do
673
      {
674
        String buildFileContent = new String( generateBuildFileHeader() );
675
 
864 mhunt 676
        for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 677
        {
864 mhunt 678
          Package p = it.next();
898 mhunt 679
 
680
          if ( ( p.mBuildFile > 0 ) && ( p.mBuildFile <= buildFile ) )
814 mhunt 681
          {
898 mhunt 682
            buildFileContent += generatePackageProperty(p);
814 mhunt 683
          }
684
        }
898 mhunt 685
 
686
        buildFileContent += generateTaskdef();
687
 
688
        String set_up = new String("");
689
        boolean daemonHasTarget = false;
690
 
864 mhunt 691
        for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 692
        {
864 mhunt 693
          Package p = it.next();
898 mhunt 694
 
695
          if ( p.mBuildFile > 0 && p.mBuildFile <= buildFile )
814 mhunt 696
          {
898 mhunt 697
            buildFileContent += generateTarget(p, buildFile);
698
 
699
            if ( p.mBuildFile == 1 )
700
            {
701
              daemonHasTarget = true;
702
            }
814 mhunt 703
          }
866 mhunt 704
 
898 mhunt 705
          if ( !mDaemon && buildFile == 1 )
866 mhunt 706
          {
898 mhunt 707
            // for the purposes of the set up, use /
708
            String loc = new String("");
709
            try
710
            {
711
              // The regular expression "\\\\" matches an escape character "\\" and a single backslash "\\"
712
              loc = p.mLocation.replaceAll("\\\\", "/");
713
            }
714
            catch( PatternSyntaxException e )
715
            {
716
            }
717
 
718
            set_up += "jats release -extractfiles"
719
                      + " \"-label=" + p.mLabel + "\""
720
                      + " \"-path=" + loc + "\""
721
                      + " \"-view=" + p.mAlias + "\""
722
                      + " -root=. -noprefix"
723
                      + lf;
866 mhunt 724
          }
814 mhunt 725
        }
898 mhunt 726
 
727
        if ( mDaemon && !daemonHasTarget )
728
        {
729
          // must have AbtSetUp, AbtTearDown, and AbtPublish targets
730
          buildFileContent += "<target name=\"AbtSetUp\"/>" + lf +
731
                              "<target name=\"AbtTearDown\"/>" + lf +
732
                              "<target name=\"AbtPublish\"/>" + lf;
733
        }
814 mhunt 734
 
735
        if ( !mDaemon && buildFile == 1 )
736
        {
898 mhunt 737
          mEscrowClearcaseSupportCollection.add(set_up);
738
          mEscrowClearcaseSupportCollection.add(raw_data);
739
        }
740
 
741
        buildFileContent += generateDefaultTarget( buildFile);
742
        buildFileContent += generateBuildFileFooter();
743
 
744
        mBuildCollection.add(buildFileContent);
745
 
746
        // are more build files required
747
        allProcessed = true;
748
 
749
        if (!mDaemon)
750
        {
751
          // this is escrow mode centric
752
          for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
848 dpurdie 753
          {
898 mhunt 754
            Package p = it.next();
755
 
756
            if ( p.mBuildFile > buildFile )
757
            {
758
              // more build files are required
759
              allProcessed = false;
760
              mLogger.info("planRelease reiterating package has no build requirement " + p.mName + " " + p.mBuildFile + " " + buildFile);
761
              break;
762
            }
763
          } 
764
 
765
          buildFile++;
814 mhunt 766
        }
898 mhunt 767
      } while( !allProcessed );
768
 
769
      if ( mDaemon )
866 mhunt 770
      {
898 mhunt 771
        // report what change in build exceptions happens as part of planRelease
772
        for (Iterator<BuildExclusion> it = mBuildExclusionCollection.iterator(); it.hasNext(); )
814 mhunt 773
        {
898 mhunt 774
          BuildExclusion buildExclusion = it.next();
775
 
776
          if ( !buildExclusion.isProcessed() )
814 mhunt 777
          {
898 mhunt 778
            // notify
779
            buildExclusion.excludeFromBuild(mReleaseManager, mBaseline);
780
            buildExclusion.email(mPackageCollection, mMailServer, mMailSender, mBaselineName);
814 mhunt 781
          }
898 mhunt 782
        }
814 mhunt 783
      }
898 mhunt 784
    }
785
    finally
866 mhunt 786
    {
898 mhunt 787
      // this block is executed regardless of what happens in the try block
788
      // even if an exception is thrown
789
      // ensure the SELECT FOR UPDATE is released
790
      if ( mDaemon )
866 mhunt 791
      {
898 mhunt 792
        // attempt to release the SELECT FOR UPDATE through a commit
793
        // a commit must be done in the normal case
794
        // a commit may as well be done in the Exception case
795
        // in the case of a SQLException indicating database connectivity has been lost
796
        // having a go at the commit is superfluous
797
        // as the SELECT FOR UPDATE will have been released upon disconnection
798
        mReleaseManager.releaseMutex();
866 mhunt 799
      }
898 mhunt 800
 
801
      // ensure disconnect
802
      mReleaseManager.disconnect();
866 mhunt 803
    }
804
 
814 mhunt 805
    mLogger.warn("planRelease mDaemon " + mDaemon + " returned");
806
  }
807
 
808
  /**returns first build file content
809
   * returns false if no build file content exists
810
   */
811
  public boolean getFirstBuildFileContent(MutableString content)
812
  {
813
    mLogger.debug("getFirstBuildFileContent");
814
    boolean retVal = true;
815
 
816
    try
817
    {
818
      mBuildIndex = 0;
819
      content.value = (String)mBuildCollection.get( mBuildIndex );
820
    }
821
    catch( ArrayIndexOutOfBoundsException e )
822
    {
823
      retVal = false;
824
    }
825
 
826
    mLogger.info("getFirstBuildFileContent returned " + retVal);
827
    return retVal;
828
  }
829
 
830
  /**returns next build file content
831
   * returns false if no next build file content exists
832
   */
833
  public boolean getNextBuildFileContent(MutableString content)
834
  {
835
    mLogger.debug("getNextBuildFileContent");
836
    boolean retVal = true;
837
 
838
    try
839
    {
840
      mBuildIndex++;
841
      content.value = (String)mBuildCollection.get( mBuildIndex );
842
    }
843
    catch( ArrayIndexOutOfBoundsException e )
844
    {
845
      retVal = false;
846
    }
847
 
848
    mLogger.debug("getNextBuildFileContent returned " + retVal);
849
    return retVal;
850
  }
851
 
852
  /**collects meta data associated with the baseline
868 mhunt 853
   * this is sufficient to send an indefinite pause email notification
814 mhunt 854
   */
868 mhunt 855
  public void collectMetaData() throws SQLException, Exception
814 mhunt 856
  {
857
    mLogger.debug("collectMetaData mDaemon " + mDaemon);
858
    mGbeMachtypeCollection.removeAllElements();
898 mhunt 859
 
860
    try
814 mhunt 861
    {
898 mhunt 862
      mReleaseManager.connect();
863
      mReleaseManager.queryMachtypes(mGbeMachtypeCollection, mDaemon, mBaseline);
864
 
865
      if (mDaemon)
866
      {
867
        mMailServer = mReleaseManager.queryMailServer();
868
        mMailSender = mReleaseManager.queryMailSender();
869
        mGlobalTarget = mReleaseManager.queryGlobalAddresses();
870
      }
871
      mBaselineName = mReleaseManager.queryBaselineName(mDaemon, mBaseline);
814 mhunt 872
    }
898 mhunt 873
    finally
874
    {
875
      // this block is executed regardless of what happens in the try block
876
      // even if an exception is thrown
877
      // ensure disconnect
878
      mReleaseManager.disconnect();
879
    }
814 mhunt 880
  }
881
 
882
  /**returns the Package with the matching mAlias or NULL_PACKAGE if no package has the mID
883
   */
884
  private Package findPackage(String alias)
885
  {
886
    mLogger.debug("findPackage");
887
    Package retVal = ReleaseManager.NULL_PACKAGE;
888
 
864 mhunt 889
    for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 890
    {
864 mhunt 891
      Package p = it.next();
814 mhunt 892
 
893
      if ( p.mAlias.compareTo( alias ) == 0 )
894
      {
895
        retVal = p;
896
        break;
897
      }
898
    }
899
 
900
    mLogger.info("findPackage returned " + retVal.mName);
901
    return retVal;
902
  }
903
 
904
  /**sets the mBuildFile to -5 for the package and all dependent packages
905
   */
900 mhunt 906
  private void rippleBuildExclude(Package p, int root_pv_id, String root_cause, ListIterator<BuildExclusion> list, BuildExclusion be )
814 mhunt 907
  {
908
    mLogger.debug("rippleBuildExclude");
874 mhunt 909
    if ( p.mBuildFile == 0 || p.mBuildFile == 1 )
814 mhunt 910
    {
911
      p.mBuildFile = -5;
894 mhunt 912
      mLogger.info("rippleBuildExclude set mBuildFile to -5 for package " + p.mAlias );
866 mhunt 913
 
900 mhunt 914
      if ( be != null )
866 mhunt 915
      {
900 mhunt 916
        be.process();
866 mhunt 917
      }
900 mhunt 918
      else
866 mhunt 919
      {
900 mhunt 920
        // if found, process it, else add it (unprocessed)
921
        boolean found = false;
866 mhunt 922
        for (Iterator<BuildExclusion> it = mBuildExclusionCollection.iterator(); it.hasNext(); )
923
        {
924
          BuildExclusion buildExclusion = it.next();
836 mhunt 925
 
900 mhunt 926
          if ( buildExclusion.compare(p.mId, root_pv_id, root_cause))
866 mhunt 927
          {
900 mhunt 928
            found = true;
866 mhunt 929
            buildExclusion.process();
900 mhunt 930
            break;
866 mhunt 931
          }
932
        }
933
 
900 mhunt 934
        if (!found)
866 mhunt 935
        {
900 mhunt 936
          // process all occurrences for this package
937
          // these will be superceded by a new build exclusion entry
938
          for (Iterator<BuildExclusion> it = mBuildExclusionCollection.iterator(); it.hasNext(); )
814 mhunt 939
          {
900 mhunt 940
            BuildExclusion buildExclusion = it.next();
814 mhunt 941
 
900 mhunt 942
            if ( buildExclusion.compare(p.mId))
814 mhunt 943
            {
900 mhunt 944
              buildExclusion.process();
814 mhunt 945
            }
946
          }
900 mhunt 947
 
948
          BuildExclusion buildExclusion = new BuildExclusion(p.mId, root_pv_id, root_cause);
949
 
950
          if ( list == null )
951
          {
952
            mBuildExclusionCollection.add(buildExclusion);
953
          }
954
          else
955
          {
956
            // must use the ListIterator interface to add to the collection whilst iterating through it
957
            list.add(buildExclusion);
958
          }
814 mhunt 959
        }
960
      }
961
 
866 mhunt 962
      for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
963
      {
964
        Package pkg = it.next();
965
 
966
        if ( pkg != p )
967
        {
968
          for (Iterator<Package> it2 = pkg.mPackageDependencyCollection.iterator(); it2.hasNext(); )
969
          {
970
            Package dependency = it2.next();
971
 
972
            if ( dependency == p )
973
            {
900 mhunt 974
              rippleBuildExclude( pkg, root_pv_id, null, list, null );
866 mhunt 975
              break;
976
            }
977
          }
978
        }
979
      }
980
    }
981
    mLogger.info("rippleBuildExclude set " + p.mName + " " + p.mBuildFile);
982
  }
983
 
814 mhunt 984
  /**returns a build file header for the mBaseline
985
   */
986
  private String generateBuildFileHeader()
987
  {
988
    mLogger.debug("generateBuildFileHeader");
989
    String lf = new String( System.getProperty("line.separator") );
990
    String retVal = new String("");
991
    retVal +=
862 mhunt 992
    "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>" + lf +
814 mhunt 993
    "<project name=\"mass\" default=\"full\" basedir=\".\">" + lf;
994
 
995
    if ( mDaemon )
996
    {
997
      retVal +=
998
      "<property name=\"abt_mail_server\" value=\"" + mMailServer + "\"/>" + lf +
999
      "<property name=\"abt_mail_sender\" value=\"" + mMailSender + "\"/>" + lf +
1000
      "<property name=\"abt_rtag_id\" value=\"" + mBaseline + "\"/>" + lf +
1001
      "<property name=\"abt_daemon\" value=\"" + mTimestamp + "\"/>" + lf;
866 mhunt 1002
 
1003
      for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
1004
      {
1005
        Package p = it.next();
1006
 
1007
        if ( p.mBuildFile == 1 )
1008
        {
1009
          retVal +=
1010
          "<property name=\"abt_package_name\" value=\"" + p.mName + "\"/>" + lf +
1011
          "<property name=\"abt_package_version\" value=\"" + p.mVersion + p.mExtension + "\"/>" + lf +
1012
          "<property name=\"abt_package_extension\" value=\"" + p.mExtension + "\"/>" + lf +
1013
          loc(p, "abt_package_location", lf) +
1014
          "<property name=\"abt_package_depends\" value=\"";
1015
 
1016
          // depends in the form 'cs','25.1.0000.cr';'Dinkumware_STL','1.0.0.cots'
1017
          String depends = new String();
1018
 
1019
          for (Iterator<Package> it3 = p.mPackageDependencyCollection.iterator(); it3.hasNext(); )
1020
          {
1021
            Package depend = it3.next();
1022
 
1023
            if ( depends.compareTo( "" ) != 0 )
1024
            {
1025
              depends += ";";
1026
            }
1027
            depends += "\'" + depend.mName + "\'";
1028
            depends += ",";
1029
            String dependsExtension = depend.mExtension;
1030
            String dependsVersion = depend.mVersion;
1031
 
1032
            if ( dependsExtension.length() > 0 )
1033
            {
1034
              dependsVersion += dependsExtension;
1035
            }
1036
            else
1037
            {
1038
              dependsExtension = ".";
1039
            }
1040
            depends += "\'" + dependsVersion + "\'";
1041
          }
1042
 
1043
          retVal += depends + "\"/>" + lf +
1044
          "<property name=\"abt_is_ripple\" value=\"";
1045
 
1046
          if ( p.mDirectlyPlanned )
1047
          {
1048
            retVal += "0";
1049
          }
1050
          else
1051
          {
1052
            retVal += "1";
1053
          }
1054
 
1055
          retVal += "\"/>" + lf +
1056
          "<property name=\"abt_package_version_id\" value=\"" + p.mId + "\"/>" + lf +
1057
          "<property name=\"abt_does_not_require_source_control_interaction\" value=\"";
1058
 
1059
          if ( ! p.mRequiresSourceControlInteraction )
1060
          {
1061
            retVal += "true";
1062
          }
1063
          else
1064
          {
1065
            retVal += "false";
1066
          }
1067
 
1068
          retVal += "\"/>" + lf;
1069
        }
1070
      }
814 mhunt 1071
    }
1072
    else
1073
    {
1074
      retVal +=
1075
      "<property name=\"abt_rtag_id\" value=\"-1\"/>" + lf;
1076
    }
1077
 
822 mhunt 1078
    String majorVersionNumber = this.getClass().getPackage().getSpecificationVersion();
1079
 
864 mhunt 1080
    if ( !ReleaseManager.mUseDatabase )
822 mhunt 1081
    {
1082
        // hard code 11 for unit test purposes
1083
         majorVersionNumber = "11";
1084
    }
1085
 
814 mhunt 1086
    retVal +=
1087
    "<property name=\"abt_release\" value=\"" + mBaselineName + "\"/>" + lf +
822 mhunt 1088
    "<property name=\"abt_buildtool_version\" value=\""+ majorVersionNumber + "\"/>" + lf +
814 mhunt 1089
    "<condition property=\"abt_family\" value=\"windows\">" + lf +
1090
    "  <os family=\"windows\"/>" + lf +
1091
    "</condition>" + lf +
1092
    "<property name=\"abt_family\" value=\"unix\"/>" + lf;
1093
    mLogger.info("generateBuildFileHeader returned " + retVal);
1094
    return retVal;
1095
  }
1096
 
1097
  /**returns an ant property for the passed Package
1098
   */
1099
  private String generatePackageProperty(Package p)
1100
  {
1101
    mLogger.debug("generatePackageProperty");
1102
    String lf = new String( System.getProperty("line.separator") );
1103
    String retVal = new String("");
1104
    retVal +=
1105
    "<property name=\"" + p.mAlias + "\" value=\"" + p.mName + " " + p.mVersion + p.mExtension + "\"/>" + lf;
1106
    mLogger.info("generatePackageProperty returned " + retVal);
1107
    return retVal;
1108
  }
1109
 
1110
  /**returns an ant taskdef for the abt ant task
1111
   */
1112
  private String generateTaskdef()
1113
  {
1114
    mLogger.debug("generateTaskdef");
1115
    String lf = new String( System.getProperty("line.separator") );
1116
    String retVal = new String("");
1117
    retVal +=
866 mhunt 1118
    "<taskdef name=\"abt\" classname=\"com.erggroup.buildtool.abt.ABT\"/>" + lf;
814 mhunt 1119
    return retVal;
1120
  }
1121
 
1122
  /**returns an ant target for the passed Package
1123
   * in daemon mode:
1124
   *  packages are categorised with one of three mBuildFile values:
1125
   *   1 the package to be built by this buildfile
1126
   *   2 the packages with a future build requirement
1127
   *   3 the packages with no build requirement
1128
   *  the returned target depends on this categorisation and will have
1129
   *   1 full abt info
1130
   *   2 full dependency info to determine future build ordering but no abt info (will not build this package)
1131
   *   3 only a name attribute (will not build this package)
1132
   * in escrow mode:
1133
   *  if the passed Package's mBuildFile is different (less than) the passed build file,
1134
   *  the returned target have only a name attribute (will not build this package) 
1135
   */
1136
  private String generateTarget(Package p, int buildFile)
1137
  {
1138
    mLogger.debug("generateTarget");
1139
 
832 mhunt 1140
    if ( ( mDaemon && p.mBuildFile == 1 ) || ( !mDaemon && !p.isGeneric() ) )
814 mhunt 1141
    {
1142
      // populate 'missing' BuildStandards
1143
      boolean solaris = false;
1144
      boolean linux = false;
1145
      boolean win32 = false;
1146
      boolean jats = false;
1147
      boolean determinedBuildStandard = false;
1148
 
864 mhunt 1149
      for (Iterator<BuildStandard> it = p.mBuildStandardCollection.iterator(); it.hasNext(); )
814 mhunt 1150
      {
864 mhunt 1151
        BuildStandard bs = it.next();
814 mhunt 1152
 
1153
        if ( bs.getSolaris() )
1154
        {
1155
          solaris = true;
1156
        }
1157
        else
1158
        if ( bs.getLinux() )
1159
        {
1160
          linux = true;
1161
        }
1162
        else
1163
        if ( bs.getWin32() )
1164
        {
1165
          win32 = true;
1166
        }
1167
 
864 mhunt 1168
        if ( !determinedBuildStandard && bs.getBuildStandard(!ReleaseManager.mUseDatabase).contains("<jats") )
814 mhunt 1169
        {
1170
          jats = true;
1171
          determinedBuildStandard = true;
1172
        }
1173
      }
1174
 
1175
      if ( !solaris )
1176
      {
1177
        BuildStandard bs = new BuildStandard(this);
1178
        bs.setSolaris();
1179
 
1180
        if ( jats )
1181
        {
1182
          bs.setJatsNone();
1183
        }
1184
        else
1185
        {
1186
          bs.setAntNone();
1187
        }
1188
 
1189
        p.mBuildStandardCollection.add(bs);
1190
      }
1191
 
1192
      if ( !linux )
1193
      {
1194
        BuildStandard bs = new BuildStandard(this);
1195
        bs.setLinux();
1196
 
1197
        if ( jats )
1198
        {
1199
          bs.setJatsNone();
1200
        }
1201
        else
1202
        {
1203
          bs.setAntNone();
1204
        }
1205
 
1206
        p.mBuildStandardCollection.add(bs);
1207
      }
1208
 
1209
      if ( !win32 )
1210
      {
1211
        BuildStandard bs = new BuildStandard(this);
1212
        bs.setWin32();
1213
 
1214
        if ( jats )
1215
        {
1216
          bs.setJatsNone();
1217
        }
1218
        else
1219
        {
1220
          bs.setAntNone();
1221
        }
1222
 
1223
        p.mBuildStandardCollection.add(bs);
1224
      }
1225
    }
1226
 
1227
    String lf = new String( System.getProperty("line.separator") );
1228
    String retVal = new String("");
1229
 
1230
    if ( ( mDaemon && p.mBuildFile == 3 ) ||
1231
         ( !mDaemon && ( p.mBuildFile < buildFile ) ) )
1232
    {
1233
      retVal +=
1234
      "<target name=\"" + p.mAlias + "\"/>" + lf;
1235
    }
1236
    else
1237
    {
848 dpurdie 1238
      retVal +=
814 mhunt 1239
      "<target name=\"" + p.mAlias + ".wrap\"";
1240
 
1241
      if ( p.mPackageDependencyCollection.size() > 0 )
1242
      {
1243
        retVal +=" depends=\"";
1244
        boolean comma = false;
1245
 
864 mhunt 1246
        for (Iterator<Package> it = p.mPackageDependencyCollection.iterator(); it.hasNext(); )
814 mhunt 1247
        {
1248
          if (comma)
1249
          {
1250
            retVal += ",";
1251
          }
1252
          comma = true;
1253
 
864 mhunt 1254
          Package dependency = it.next();
814 mhunt 1255
          retVal += dependency.mAlias;
1256
        }
1257
 
1258
        retVal += "\"";
1259
      }
1260
      retVal += ">" + lf;
1261
 
1262
      if ( !mDaemon )
1263
      {
1264
        boolean hasDependenciesBuiltInThisIteration = false;
1265
        if ( ( p.mPackageDependencyCollection.size() > 0 ) )
1266
        {
864 mhunt 1267
          for (Iterator<Package> it = p.mPackageDependencyCollection.iterator(); it.hasNext(); )
814 mhunt 1268
          {
864 mhunt 1269
            Package dependency = it.next();
814 mhunt 1270
 
1271
            if ( dependency.mBuildFile == buildFile )
1272
            {
1273
              hasDependenciesBuiltInThisIteration = true;
1274
              break;
1275
            }
1276
          }
1277
        }
1278
 
1279
        if ( hasDependenciesBuiltInThisIteration )
1280
        {
1281
          retVal +=
1282
          "  <condition property=\"" + p.mAlias + ".build\">" + lf +
1283
          "    <and>" + lf;
1284
 
864 mhunt 1285
          for (Iterator<Package> it = p.mPackageDependencyCollection.iterator(); it.hasNext(); )
814 mhunt 1286
          {
864 mhunt 1287
            Package dependency = it.next();
814 mhunt 1288
 
1289
            if ( dependency.mBuildFile == buildFile )
1290
            {
1291
              retVal +=
1292
              "      <or>" + lf +
1293
              "        <equals arg1=\"${" + dependency.mAlias + ".res}\" arg2=\"0\"/>" + lf +
1294
              "        <equals arg1=\"${" + dependency.mAlias + ".res}\" arg2=\"257\"/>" + lf +
1295
              "      </or>" + lf;
1296
            }
1297
          }
1298
 
1299
          retVal +=
1300
          "    </and>" + lf +
1301
          "  </condition>" + lf;
1302
        }
1303
        else
1304
        {
1305
          retVal += "  <property name=\"" + p.mAlias + ".build\" value=\"\"/>" + lf;
1306
        }
1307
      }
1308
 
1309
      retVal +=
1310
      "</target>" + lf +
1311
      "<target name=\"" + p.mAlias + "\" depends=\"" + p.mAlias + ".wrap\"";
1312
 
1313
      if ( !mDaemon )
1314
      {
1315
        retVal += " if=\"" + p.mAlias + ".build\"";
1316
      }
1317
 
1318
      retVal += ">" + lf;
1319
 
1320
      if ( mDaemon && p.mBuildFile == 1 )
1321
      {
1322
        retVal +=
1323
        "<property name=\"" + p.mAlias + "pkg_id\" value=\"" + p.mPid + "\"/>" + lf +
1324
        "<property name=\"" + p.mAlias + "pv_id\" value=\"" + p.mId + "\"/>" + lf;
1325
      }
1326
 
1327
      if ( ( mDaemon && p.mBuildFile == 1 ) || !mDaemon )
1328
      {
1329
        retVal +=
1330
        "<property name=\"" + p.mAlias + "packagename\" value=\"" + p.mName + "\"/>" + lf +
1331
        "<property name=\"" + p.mAlias + "packageversion\" value=\"" + p.mVersion + "\"/>" + lf +
1332
        "<property name=\"" + p.mAlias + "packageextension\" value=\"";
1333
 
1334
        if ( p.mExtension.length() > 0 )
1335
        {
1336
          // drop the .
1337
          retVal += p.mExtension.substring(1);
1338
        }
1339
        else
1340
        {
1341
          retVal += p.mExtension;
1342
        }
1343
 
1344
        retVal += "\"/>" + lf +
1345
        "<property name=\"" + p.mAlias + "packagelabel\" value=\"" + p.mLabel + "\"/>" + lf;
1346
 
1347
        if ( p.mDirectlyPlanned )
1348
        {
1349
          retVal += "<property name=\"" + p.mAlias + "directchange\" value=\"\"/>" + lf;
1350
        }
1351
 
852 mhunt 1352
        if ( ! p.mRequiresSourceControlInteraction )
1353
        {
1354
          retVal += "<property name=\"" + p.mAlias + "doesnotrequiresourcecontrolinteraction\" value=\"\"/>" + lf;
1355
        }
1356
 
814 mhunt 1357
        mAddendum = "non generic";
1358
 
1359
        if ( p.isGeneric() )
1360
        {
1361
          mAddendum = "generic";
1362
          retVal += "<property name=\"" + p.mAlias + "generic\" value=\"\"/>" + lf;
1363
        }
1364
 
1365
        retVal += loc(p, p.mAlias + "loc", lf);
1366
 
830 mhunt 1367
        if ( p.mHasAutomatedUnitTests && mDaemon )
814 mhunt 1368
        {
1369
          retVal += 
1370
          "<property name=\"" + p.mAlias + "unittests\" value=\"\"/>" + lf;
1371
        }
1372
      }
1373
 
1374
      retVal += "<abt>" + lf;
1375
 
1376
      if ( ( mDaemon && p.mBuildFile == 1 ) || !mDaemon )
1377
      {
864 mhunt 1378
        for (Iterator<Package> it = p.mPackageDependencyCollection.iterator(); it.hasNext(); )
814 mhunt 1379
        {
864 mhunt 1380
          Package dependency = it.next();
814 mhunt 1381
          retVal +=
1382
          "  <depend package_alias=\"${" + dependency.mAlias + "}\"/>" + lf;
1383
        }
1384
 
836 mhunt 1385
        retVal += buildInfo(p, lf, false);
814 mhunt 1386
      }
1387
 
1388
      if ( mDaemon && p.mBuildFile == 1 )
1389
      {
854 mhunt 1390
        retVal += p.emailInfo( lf );
814 mhunt 1391
      }
1392
 
1393
      retVal += "</abt>" + lf +
1394
      "</target>" + lf;
1395
 
1396
      if ( mDaemon && p.mBuildFile == 1 )
1397
      {
1398
        retVal +=
1399
        "<target name=\"AbtSetUp\">" + lf +
854 mhunt 1400
        "<property name=\"AbtSetUppackagelabel\" value=\"" + p.mLabel + "\"/>" + lf +
872 dpurdie 1401
        "<property name=\"AbtSetUppackagename\" value=\"" + p.mName + "\"/>" + lf +
1402
        "<property name=\"AbtSetUppackageSrcPath\" value=\"" + p.mLocation.replace('\\', '/') + "\"/>" + lf;
814 mhunt 1403
 
1404
        retVal +=
1405
        "<abt>" + lf +
854 mhunt 1406
        p.emailInfo( lf ) +
814 mhunt 1407
        "</abt>" + lf +
872 dpurdie 1408
        "</target>" + lf;
1409
 
1410
        retVal +=
814 mhunt 1411
        "<target name=\"AbtTearDown\">" + lf +
1412
        "<property name=\"AbtTearDownpackagelabel\" value=\"" + p.mLabel + "\"/>" + lf +
1413
        "<property name=\"AbtTearDownpackagename\" value=\"" + p.mName + "\"/>" + lf +
1414
        "<property name=\"AbtTearDownpackageversion\" value=\"" + p.mVersion + "\"/>" + lf +
1415
        "<property name=\"AbtTearDownpackageextension\" value=\"";
1416
 
1417
        if ( p.mExtension.length() > 0 )
1418
        {
1419
          // drop the .
1420
          retVal += p.mExtension.substring(1);
1421
        }
1422
        else
1423
        {
1424
          retVal += p.mExtension;
1425
        }
1426
 
1427
        retVal += "\"/>" + lf;
1428
 
1429
        if ( p.isGeneric() )
1430
        {
1431
          retVal += "<property name=\"" + p.mAlias + "generic\" value=\"\"/>" + lf;
1432
        }
1433
 
1434
        retVal +=        
1435
        "<abt>" + lf +
836 mhunt 1436
        buildInfo(p, lf, false) +
854 mhunt 1437
        p.emailInfo( lf ) +
814 mhunt 1438
        "</abt>" + lf +
1439
        "</target>" + lf +
1440
        "<target name=\"AbtPublish\">" + lf +
1441
        "<property name=\"AbtPublishpackagelabel\" value=\"" + p.mLabel + "\"/>" + lf +
1442
        "<property name=\"AbtPublishpackagename\" value=\"" + p.mName + "\"/>" + lf +
1443
        "<property name=\"AbtPublishpackageversion\" value=\"" + p.mVersion + "\"/>" + lf +
1444
        "<property name=\"AbtPublishpackageextension\" value=\"";
1445
 
1446
        if ( p.mExtension.length() > 0 )
1447
        {
1448
          // drop the .
1449
          retVal += p.mExtension.substring(1);
1450
        }
1451
        else
1452
        {
1453
          retVal += p.mExtension;
1454
        }
1455
 
1456
        retVal += "\"/>" + lf;
1457
 
1458
        if ( p.mDirectlyPlanned )
1459
        {
1460
          retVal += "<property name=\"AbtPublishdirectchange\" value=\"\"/>" + lf;
1461
        }
1462
 
852 mhunt 1463
        if ( ! p.mRequiresSourceControlInteraction )
1464
        {
1465
          retVal += "<property name=\"AbtPublishdoesnotrequiresourcecontrolinteraction\" value=\"\"/>" + lf;
1466
        }
1467
 
814 mhunt 1468
        if ( p.isGeneric() )
1469
        {
1470
          retVal += "<property name=\"AbtPublishgeneric\" value=\"\"/>" + lf;
1471
        }
1472
 
1473
        retVal += loc(p, "AbtPublishloc", lf);
1474
        retVal +=
816 mhunt 1475
        "<abt>" + lf +
854 mhunt 1476
        buildInfo(p, lf, true) +
1477
        p.emailInfo( lf ) +
814 mhunt 1478
        "</abt>" + lf +
1479
        "</target>" + lf;
1480
      }
1481
    }
1482
    mLogger.info("generateTarget returned " + retVal);
1483
    return retVal;
1484
  }
1485
 
1486
  /**returns an ant default target for the current build iteration
1487
   */
1488
  private String generateDefaultTarget(int buildFile)
1489
  {
1490
    mLogger.debug("generateDefaultTarget");
1491
    String lf = new String( System.getProperty("line.separator") );
1492
    String retVal = new String("");
1493
    retVal +=
1494
    "<target name=\"fullstart\">" + lf;
1495
 
1496
    if (buildFile == 1)
1497
    {
1498
      retVal +=
1499
      "<echo message=\"${line.separator}The following package versions are not reproducible on any build platform:${line.separator}${line.separator}\" file=\"publish.log\" append=\"true\"/>" + lf;
1500
 
864 mhunt 1501
      for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 1502
      {
864 mhunt 1503
        Package p = it.next();
814 mhunt 1504
 
1505
        if ( p.mBuildFile == -1 )
1506
        {
1507
          retVal +=
1508
          "<echo message=\"${line.separator}" + p.mAlias + "${line.separator}\" file=\"publish.log\" append=\"true\"/>" + lf;
1509
        }
1510
      }
1511
 
1512
      retVal +=
1513
      "<echo message=\"${line.separator}The following package versions are not reproducible on the build platforms associated with this baseline:${line.separator}${line.separator}\" file=\"publish.log\" append=\"true\"/>" + lf;
1514
 
864 mhunt 1515
      for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 1516
      {
864 mhunt 1517
        Package p = it.next();
814 mhunt 1518
 
1519
        if ( p.mBuildFile == -2 )
1520
        {
1521
          retVal +=
1522
          "<echo message=\"${line.separator}" + p.mAlias + "${line.separator}\" file=\"publish.log\" append=\"true\"/>" + lf;
1523
        }
1524
      }
1525
 
1526
      retVal +=
1527
      "<echo message=\"${line.separator}The following package versions are not reproducible as they are directly dependent upon package versions not in the baseline:${line.separator}${line.separator}\" file=\"publish.log\" append=\"true\"/>" + lf;
1528
 
864 mhunt 1529
      for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 1530
      {
864 mhunt 1531
        Package p = it.next();
814 mhunt 1532
 
1533
        if ( p.mBuildFile == -4 )
1534
        {
1535
          retVal +=
1536
          "<echo message=\"${line.separator}" + p.mAlias + "${line.separator}\" file=\"publish.log\" append=\"true\"/>" + lf;
1537
        }
1538
      }
1539
 
1540
      retVal +=
1541
      "<echo message=\"${line.separator}The following package versions are not reproducible as they are directly/indirectly dependent upon not reproducible package versions:${line.separator}${line.separator}\" file=\"publish.log\" append=\"true\"/>" + lf;
1542
 
864 mhunt 1543
      for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 1544
      {
864 mhunt 1545
        Package p = it.next();
814 mhunt 1546
 
1547
        if ( p.mBuildFile == -5 )
1548
        {
1549
          retVal +=
1550
          "<echo message=\"${line.separator}" + p.mAlias + "${line.separator}\" file=\"publish.log\" append=\"true\"/>" + lf;
1551
        }
1552
      }
1553
    }
1554
    if ( !mDaemon )
1555
    {
1556
      retVal +=
1557
      "<echo message=\"${line.separator}Build Started:${line.separator}${line.separator}\" file=\"publish.log\" append=\"true\"/>" + lf;
1558
    }
1559
 
1560
    retVal +=
1561
    "</target>" + lf +
1562
    "<target name=\"full\" depends=\"fullstart";
1563
 
864 mhunt 1564
    for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 1565
    {
864 mhunt 1566
      Package p = it.next();
814 mhunt 1567
 
1568
      if ( ( p.mBuildFile > 0 ) && ( p.mBuildFile <= buildFile ) )
1569
      {
1570
        retVal += "," + p.mAlias;
1571
      }
1572
    }
1573
 
1574
    retVal +=
1575
    "\">" + lf;
1576
 
1577
    if ( !mDaemon )
1578
    {
1579
      retVal +=
1580
      "<echo message=\"${line.separator}Build Finished${line.separator}\" file=\"publish.log\" append=\"true\"/>" + lf;
1581
    }
1582
 
1583
    retVal +=
1584
    "</target>" + lf;
1585
    return retVal;
1586
  }
1587
 
1588
  /**returns a build file footer
1589
   */
1590
  private String generateBuildFileFooter()
1591
  {
1592
    mLogger.debug("generateBuildFileFooter");
1593
    String retVal = new String("</project>");
1594
    return retVal;
1595
  }
1596
 
1597
  /**sets the mIndirectlyPlanned true for the package and all dependent packages
1598
   */
1599
  private void rippleIndirectlyPlanned(Package p)
1600
  {
1601
    mLogger.debug("rippleIndirectlyPlanned");
1602
    if ( !p.mIndirectlyPlanned && p.mBuildFile == 0 )
1603
    {
1604
      p.mIndirectlyPlanned = true;
1605
 
864 mhunt 1606
      for (Iterator<Package> it = mPackageCollection.iterator(); it.hasNext(); )
814 mhunt 1607
      {
864 mhunt 1608
        Package pkg = it.next();
814 mhunt 1609
 
1610
        if ( pkg != p )
1611
        {
864 mhunt 1612
          for (Iterator<Package> it2 = pkg.mPackageDependencyCollection.iterator(); it2.hasNext(); )
814 mhunt 1613
          {
864 mhunt 1614
            Package dependency = it2.next();
814 mhunt 1615
 
1616
            if ( dependency == p )
1617
            {
1618
              rippleIndirectlyPlanned( pkg );
1619
              break;
1620
            }
1621
          }
1622
        }
1623
      }
1624
    }
1625
    mLogger.info("rippleIndirectlyPlanned set " + p.mName + " " + p.mIndirectlyPlanned);    
1626
  }
1627
 
1628
  /**accessor method
1629
   */
830 mhunt 1630
  public String getESCROWSetUp()
814 mhunt 1631
  {
830 mhunt 1632
    mLogger.debug("getESCROWSetUp");
814 mhunt 1633
    String retVal = new String("");
1634
 
1635
    try
1636
    {
830 mhunt 1637
      if ( mEscrowClearcaseSupportCollection.size() >= 1 )
814 mhunt 1638
      {
1639
        retVal = (String)mEscrowClearcaseSupportCollection.get(0);
1640
      }
1641
    }
1642
    catch( ArrayIndexOutOfBoundsException e )
1643
    {
1644
    }
1645
 
830 mhunt 1646
    mLogger.info("getESCROWSetUp returned " + retVal);
814 mhunt 1647
    return retVal;
1648
  }
1649
 
1650
  /**accessor method
1651
   */
830 mhunt 1652
  public String getRawData()
814 mhunt 1653
  {
830 mhunt 1654
    mLogger.debug("getRawData");
814 mhunt 1655
    String retVal = new String("");
1656
 
1657
    try
1658
    {
830 mhunt 1659
      if ( mEscrowClearcaseSupportCollection.size() >= 2 )
814 mhunt 1660
      {
1661
        retVal = (String)mEscrowClearcaseSupportCollection.get(1);
1662
      }
1663
    }
1664
    catch( ArrayIndexOutOfBoundsException e )
1665
    {
1666
    }
1667
 
830 mhunt 1668
    mLogger.info("getRawData returned " + retVal);
814 mhunt 1669
    return retVal;
1670
  }
1671
 
1672
  /**returns first build file content and addendum
1673
   * the addendum value is one of "non generic", "generic" or "dummy"
1674
   */
1675
  public void getFirstBuildFileContent(MutableString content, 
1676
                                MutableString addendum)
1677
  {
1678
    mLogger.debug("getFirstBuildFileContent");
1679
    try
1680
    {
1681
      mBuildIndex = 0;
1682
      content.value = (String)mBuildCollection.get( mBuildIndex );
1683
      addendum.value = mAddendum;
1684
    }
1685
    catch( ArrayIndexOutOfBoundsException e )
1686
    {
1687
    }
1688
    mLogger.info("getFirstBuildFileContent passed " + content.value + addendum.value);
1689
  }
1690
 
872 dpurdie 1691
  /**returns the build loc
814 mhunt 1692
   */
1693
  private String loc(Package p, String target, String lf)
1694
  {
1695
    mLogger.debug("loc");
1696
    String retVal = new String();
872 dpurdie 1697
    String loc = new String("/");
1698
 
1699
    if (mDaemon)
814 mhunt 1700
    {
872 dpurdie 1701
      // Daemon: Start in root of view/workspace
878 mhunt 1702
      loc += mBaseline + "/" + p.mLabel;
814 mhunt 1703
    }
872 dpurdie 1704
    else
814 mhunt 1705
    {
872 dpurdie 1706
      // mAlias used with jats -extractfiles -view
1707
      loc += p.mAlias;
1708
    }
814 mhunt 1709
 
872 dpurdie 1710
    //
1711
    //  Always use '/' as a path seperator - even if user has specified '\'
1712
    //  Ant can handle it.
1713
    //
814 mhunt 1714
    loc = loc.replace('\\', '/');
1715
    retVal += 
1716
    "<property name=\"" + target + "\" value=\"" + loc + "\"/>" + lf;
1717
 
1718
    mLogger.info("loc returned " + retVal);
1719
    return retVal;
1720
  }
816 mhunt 1721
 
1722
  /**returns the buildInfo
1723
   */
836 mhunt 1724
  private String buildInfo(Package p, String lf, boolean filter)
816 mhunt 1725
  {
1726
    mLogger.debug("buildInfo");
1727
 
1728
    String platforms = new String();
1729
    String standards = new String();
1730
 
864 mhunt 1731
    for (Iterator<BuildStandard> it = p.mBuildStandardCollection.iterator(); it.hasNext(); )
816 mhunt 1732
    {
864 mhunt 1733
      BuildStandard bs = it.next();
816 mhunt 1734
 
836 mhunt 1735
      if ( !filter )
816 mhunt 1736
      {
864 mhunt 1737
        String platform = bs.getPlatform(!ReleaseManager.mUseDatabase);
816 mhunt 1738
 
1739
        if ( platform.length() > 0 )
1740
        {
1741
          platforms += platform + lf;
1742
        }
1743
 
864 mhunt 1744
        String standard = bs.getBuildStandard(!ReleaseManager.mUseDatabase);
816 mhunt 1745
 
1746
        if ( standard.length() > 0 )
1747
        {
1748
          standards += standard + lf;
1749
        }
1750
      }
1751
      else
1752
      {
864 mhunt 1753
        if ( !bs.getBuildStandard(!ReleaseManager.mUseDatabase).contains("\"none\"") )
816 mhunt 1754
        {
864 mhunt 1755
          String platform = bs.getPlatform(!ReleaseManager.mUseDatabase);
816 mhunt 1756
 
1757
          if ( platform.length() > 0 )
1758
          {
1759
            platforms += platform + lf;
1760
          }
836 mhunt 1761
 
864 mhunt 1762
          String standard = bs.getBuildStandard(!ReleaseManager.mUseDatabase);
836 mhunt 1763
 
1764
          if ( standard.length() > 0 )
1765
          {
1766
            standards += standard + lf;
1767
          }
816 mhunt 1768
        }
1769
      }
1770
    }
1771
 
1772
    mLogger.info("buildInfo returned " + platforms + standards);
1773
    return platforms + standards;
1774
  }
866 mhunt 1775
 
814 mhunt 1776
}