Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
814 mhunt 1
package com.erggroup.buildtool.daemon;
2
 
3
import com.erggroup.buildtool.daemon.ResumeTimerTask;
4
import com.erggroup.buildtool.ripple.ReleaseManager;
5
 
6
import java.io.BufferedReader;
7
import java.io.File;
8
import java.io.FileNotFoundException;
9
import java.io.FileOutputStream;
10
import java.io.FileWriter;
11
import java.io.FilenameFilter;
12
 
13
import java.io.IOException;
14
import java.io.PrintStream;
15
import java.io.StringReader;
16
 
17
import java.sql.SQLException;
18
 
19
import java.util.Date;
20
import java.util.Timer;
21
 
22
import org.apache.log4j.Logger;
23
import org.apache.tools.ant.BuildException;
24
import org.apache.tools.ant.DefaultLogger;
25
import org.apache.tools.ant.Project;
26
import org.apache.tools.ant.ProjectHelper;
27
 
28
/**Build Thread sub component
29
 */
30
public abstract class BuildThread
31
  extends Thread
32
{
33
  /**baseline identifier (which release manager release this BuildThread is dealing with)
34
   * @attribute
35
   */
36
  protected int mRtagId = 0;
37
 
38
  /**unique identifier of this BuildThread
39
   * @attribute
40
   */
41
  protected int mRconId = 0;
42
 
43
  /**
44
   * @aggregation composite
45
   */
46
  protected RunLevel mRunLevel;
47
 
48
  /**
49
   * @aggregation composite
50
   */
51
  protected ReleaseManager mReleaseManager;
52
 
53
  /**configured GBEBUILDFILTER for this BuildThread
54
   * @attribute
55
   */
56
  protected String mGbebuildfilter = "";
57
 
58
  /**
59
   * @aggregation composite
60
   */
61
  protected static ResumeTimerTask mResumeTimerTask;
62
 
63
  /**
64
   * @aggregation composite
65
   */
66
  private static Timer mTimer;
67
 
68
  /**Synchroniser object
69
   * Use to Synchronize on by multiple threads
70
   * @attribute
71
   */
72
  static final Object mSynchroniser = new Object();
73
 
74
  /**BuildThread group
75
   * @attribute
76
   */
77
  public static final ThreadGroup mThreadGroup = new ThreadGroup("BuildThread");
78
 
79
  /**the advertised build file content when either
80
   * a) no package in the baseline has a build requirement
81
   * b) the next package in the baseline with a build requirement is generic
82
   * @attribute
83
   */
84
  protected static final String mDummyBuildFileContent = new String("<dummy/>");
85
 
86
  /**Set true when last build cycle was benign.
87
   * @attribute
88
   */
89
  protected boolean mSleep;
90
 
854 mhunt 91
  /**Set true when ant error reported on any target.
92
   * @attribute
93
   */
94
  private boolean mErrorReported;
95
 
866 mhunt 96
  /**Logger
854 mhunt 97
   * @attribute
98
   */
866 mhunt 99
  private static final Logger mLogger = Logger.getLogger(BuildThread.class);
854 mhunt 100
 
866 mhunt 101
  /**Package name for reporting purposes.
814 mhunt 102
   * @attribute
103
   */
866 mhunt 104
  protected String mReportingPackageName;
814 mhunt 105
 
866 mhunt 106
  /**Package version for reporting purposes.
107
   * @attribute
108
   */
109
  protected String mReportingPackageVersion;
110
 
111
  /**Package extension for reporting purposes.
112
   * @attribute
113
   */
114
  protected String mReportingPackageExtension;
115
 
116
  /**Package location for reporting purposes.
117
   * @attribute
118
   */
119
  protected String mReportingPackageLocation;
120
 
121
  /**Package dependencies for reporting purposes.
122
   * @attribute
123
   */
124
  protected String mReportingPackageDepends;
125
 
126
  /**Is ripple flag for reporting purposes.
127
   * @attribute
128
   */
129
  protected String mReportingIsRipple;
130
 
131
  /**Package version identifier for reporting purposes.
132
   * @attribute
133
   */
134
  protected String mReportingPackageVersionId;
135
 
136
  /**Fully published flag for reporting purposes.
137
   * @attribute
138
   */
139
  protected String mReportingFullyPublished;
140
 
141
  /**New label for reporting purposes.
142
   * @attribute
143
   */
144
  protected String mReportingNewLabel;
145
 
146
  /**Source control interaction for reporting purposes.
147
   * @attribute
148
   */
149
  protected String mReportingDoesNotRequireSourceControlInteraction;
150
 
151
  /**Log file location for reporting purposes.
152
   * @attribute
153
   */
154
  protected String mReportingBuildFailureLogFile;
155
 
814 mhunt 156
  /**constructor
157
   */
158
  BuildThread()
159
  {
160
    super(mThreadGroup, "");
161
    mLogger.debug("BuildThread");
162
    mSleep = false;
854 mhunt 163
    mErrorReported = false;
814 mhunt 164
    mReleaseManager = new ReleaseManager();
165
 
166
    // no need to be synchronized - BuildThreads are instantiated in a single thread
167
    if ( mResumeTimerTask == null )
168
    {
169
      mResumeTimerTask = new ResumeTimerTask();
170
      mTimer = new Timer();
171
      mResumeTimerTask.setTimer(mTimer);
172
    }
173
  }
174
 
175
  /**initially changes the run level to IDLE
176
   * determines if the BuildThread is still configured
177
   * a) determines if the BuildThread is running in scheduled downtime
178
   * b) determines if the BuildThread is directed to pause
179
   * changes the run level to PAUSED if a) or b) are true
180
   * throws ExitException when not configured
181
   * otherwise changes the run level to WAITING and returns when allowed to proceed
182
   * implements the sequence diagrams allowed to proceed, not allowed to proceed, exit
183
   */
184
  protected void allowedToProceed() throws ExitException, SQLException, Exception
185
  {
186
    mLogger.debug("allowedToProceed");
187
 
188
    if (mSleep)
189
    {
190
      try
191
      {
818 mhunt 192
        mRunLevel = RunLevel.IDLE;
193
        mLogger.warn("allowedToProceed changing run level to IDLE for rcon_id " + mRconId);
194
        mRunLevel.persist(mReleaseManager, mRconId);
195
        mReleaseManager.clearCurrentPackageBeingBuilt(mRconId);
196
 
814 mhunt 197
        mLogger.warn("allowedToProceed sleep 5 mins no build requirement");
198
        Thread.sleep(300000);
199
        mLogger.info("allowedToProceed sleep returned");
200
      }
818 mhunt 201
      catch(SQLException e)
202
      {
203
        mLogger.warn("allowedToProceed caught SQLException");
204
      }
814 mhunt 205
      catch(InterruptedException e)
206
      {
207
        mLogger.warn("allowedToProceed sleep caught InterruptedException");
208
      }
209
    }
210
 
211
    // IMPORTANT - this is done AFTER a Thread.sleep by design
212
    // In the case of an SQLException (signifying a database access issue)
213
    // avoid accessing the database immediately
214
    mRunLevel = RunLevel.IDLE;
816 mhunt 215
    mLogger.warn("allowedToProceed changing run level to IDLE for rcon_id " + mRconId);
814 mhunt 216
    mRunLevel.persist(mReleaseManager, mRconId);
217
    boolean proceed = false;
218
 
219
    while ( !proceed )
220
    {
221
      mReleaseManager.connect();
222
      if ( !mReleaseManager.queryReleaseConfig(mRtagId, mRconId, BuildDaemon.mHostname, getMode(), mGbebuildfilter) )
223
      {
224
        mReleaseManager.disconnect();
858 mhunt 225
        mLogger.warn("allowedToProceed queryReleaseConfig failed");
814 mhunt 226
        throw new ExitException();
227
      }
228
 
229
      Date resumeTime = new Date( 0 );
230
      if ( !mReleaseManager.queryRunLevelSchedule(resumeTime) )
231
      {
232
        mLogger.info("allowedToProceed scheduled downtime");
233
        mReleaseManager.disconnect();
234
        mRunLevel = RunLevel.PAUSED;
816 mhunt 235
        mLogger.warn("allowedToProceed changing run level to PAUSED for rcon_id " + mRconId);
814 mhunt 236
        mRunLevel.persist(mReleaseManager, mRconId);
237
 
238
        synchronized(mSynchroniser)
239
        {
240
          // contain the schedule and wait in the same synchronized block to prevent a deadlock
241
          // eg this thread calls schedule, timer thread calls notifyall, this thread calls wait (forever)
242
          try
243
          {
244
            if (mResumeTimerTask.isCancelled())
245
            {
246
              mResumeTimerTask = new ResumeTimerTask();
247
              mTimer = new Timer();
248
              mResumeTimerTask.setTimer(mTimer);
249
            }
250
            mLogger.warn("allowedToProceed schedule passed " + resumeTime.getTime());
251
            mTimer.schedule(mResumeTimerTask, resumeTime);
252
          }
253
          catch( IllegalStateException e )
254
          {
255
            // this may be thrown by schedule if already scheduled
256
            // it signifies another BuildThread has already scheduled the ResumeTimerTask
257
             mLogger.warn("allowedToProceed already scheduled");
258
          }
259
 
260
          try
261
          {
262
            mLogger.warn("allowedToProceed wait");
263
            mSynchroniser.wait();
264
            mLogger.warn("allowedToProceed wait returned");
265
 
266
            if ( mGbebuildfilter.compareTo("unit test not allowed to proceed") == 0 )
267
            {
268
              throw new ExitException();
269
            }
270
          }
271
          catch( InterruptedException e )
272
          {
273
            mLogger.warn("allowedToProceed caught InterruptedException");
274
          }
275
        }
276
 
277
      }
278
      else
279
      {
280
        if ( !mReleaseManager.queryDirectedRunLevel(mRconId) )
281
        {
282
          mLogger.info("allowedToProceed downtime");
283
          mReleaseManager.disconnect();
832 mhunt 284
          mRunLevel = RunLevel.PAUSED;
285
          mLogger.warn("allowedToProceed changing run level to PAUSED for rcon_id " + mRconId);
286
          mRunLevel.persist(mReleaseManager, mRconId);
814 mhunt 287
          try
288
          {
289
            // to do, sleep for periodicMs
290
            mLogger.warn("allowedToProceed sleep 5 mins directed downtime");
291
            Thread.sleep(300000);
292
            mLogger.info("allowedToProceed sleep returned");
293
          }
294
          catch (InterruptedException e)
295
          {
296
            mLogger.warn("allowedToProceed caught InterruptedException");
297
          }
298
        }
299
        else
300
        {
301
          mReleaseManager.disconnect();
302
          proceed = true;
303
        }
304
      }
305
    }
306
 
307
    mRunLevel = RunLevel.WAITING;
816 mhunt 308
    mLogger.warn("allowedToProceed changing run level to WAITING for rcon_id " + mRconId);
814 mhunt 309
    mRunLevel.persist(mReleaseManager, mRconId);
310
 
311
  }
312
 
313
  /**periodically 
314
   * a) performs disk housekeeping
315
   * b) determines if a minimum threshold of disk space is available
316
   * changes the run level to CANNOT_CONTINUE if insufficient disk space
317
   * otherwise changes the run level to ACTIVE and returns
318
   * implements the sequence diagram check environment
319
   */
320
  protected void checkEnvironment() throws Exception
321
  {
322
    mLogger.debug("checkEnvironment");
323
    boolean exit = false;
324
 
325
    while( !exit )
326
    {
327
      housekeep();
328
 
329
      // attempt to exit
330
      exit = true;
331
 
332
      if ( !hasSufficientDiskSpace() )
333
      {
334
        mLogger.warn("checkEnvironment below disk free threshold");
335
        exit = false;
336
        mRunLevel = RunLevel.CANNOT_CONTINUE;
816 mhunt 337
        mLogger.warn("checkEnvironment changing run level to CANNOT_CONTINUE for rcon_id " + mRconId);
814 mhunt 338
        mRunLevel.persist(mReleaseManager, mRconId);
339
        try
340
        {
341
          // to do, sleep for periodicMs
342
          if ( mGbebuildfilter.compareTo("unit test check environment") != 0 )
343
          {
344
            mLogger.warn("checkEnvironment sleep 5 mins below disk free threshold");
345
            Thread.sleep(300000);
346
            mLogger.info("checkEnvironment sleep returned");
347
          }
348
        }
349
        catch (InterruptedException e)
350
        {
351
          mLogger.warn("checkEnvironment caught InterruptedException");
352
        }
353
      }
354
    }
355
 
356
    mRunLevel = RunLevel.ACTIVE;    
816 mhunt 357
    mLogger.warn("checkEnvironment changing run level to ACTIVE for rcon_id " + mRconId);
814 mhunt 358
    mRunLevel.persist(mReleaseManager, mRconId);
359
  }
360
 
361
  /**performs disk housekeeping which involves deleting build directories > 5 days old
362
   * refer to the sequence diagram check environment
363
   */
364
  private void housekeep()
365
  {
366
    mLogger.debug("housekeep");
367
    FilenameFilter filter = new FilenameFilter()
368
    {
369
      public boolean accept(File file, String name)
370
      {
371
        mLogger.debug("accept " + name);
372
        boolean retVal = false;
373
 
374
        if ( file.isDirectory() && !name.startsWith( "." ) )
375
        {
376
          retVal = true;
377
        }
378
 
379
        mLogger.info("accept returned " + retVal);
380
        return retVal;
381
      }
382
    };
383
 
384
    try
385
    {
842 mhunt 386
      // DEVI 46729, 46730, solaris 10 core dumps implicate deleteDirectory
387
      // let each BuildThread look after its own housekeeping
854 mhunt 388
      File ocwd = new File( BuildDaemon.mGbeLog );
389
      File hcwd = new File( ocwd, BuildDaemon.mHostname );
390
      File cwd = new File( hcwd, String.valueOf( mRtagId ) );
842 mhunt 391
 
814 mhunt 392
      File[] children = cwd.listFiles( filter );
393
 
394
      if ( children != null )
395
      {
396
        for ( int child=0; child < children.length; child++ )
397
        {
854 mhunt 398
          // child is named uniquely to encapsulate a build
399
          // 5 days = 432,000,000 milliseconds
400
          if ( ( System.currentTimeMillis() - children[ child ].lastModified() ) > 432000000 )
814 mhunt 401
          {
854 mhunt 402
            // the directory is over 5 days old
403
            mLogger.warn("housekeep deleting directory " + children[ child ].getName());
404
            if ( mGbebuildfilter.compareTo("unit test check environment") != 0 )
814 mhunt 405
            {
854 mhunt 406
              deleteDirectory( children[ child ] );
814 mhunt 407
            }
408
          }
409
        }
410
      }
411
    }
412
    catch( SecurityException e )
413
    {
414
      // this can be thrown by lastModified
415
       mLogger.warn("housekeep caught SecurityException");
416
    }
417
 
418
  }
419
 
420
  /**returns true if free disk space > 10G
421
   * this may become configurable if the need arises
422
   * refer to the sequence diagram check environment
423
   */
424
  private boolean hasSufficientDiskSpace()
425
  {
426
    mLogger.debug("hasSufficientDiskSpace");
427
    boolean retVal = true;
428
    long freeSpace = 0;
429
 
430
    try
431
    {
432
      File cwd = new File( "." );
433
 
434
      // 5G = 5368709120 bytes
435
      if ( mGbebuildfilter.compareTo("unit test check environment") == 0 )
436
      {
864 mhunt 437
        if ( ReleaseManager.mPersistedRunLevelCollection.size() == 0 )
814 mhunt 438
        {
439
          retVal = false;
440
        }
441
        else
442
        {
443
          retVal = true;
444
        }
445
      }
446
      else
447
      {
816 mhunt 448
        freeSpace = cwd.getUsableSpace();
814 mhunt 449
 
450
        if ( freeSpace < 5368709120L )
451
        {
816 mhunt 452
          mLogger.warn("hasSufficientDiskSpace on " + cwd.getAbsolutePath() + " freeSpace " + freeSpace);
814 mhunt 453
          retVal = false;
454
        }
455
      }
456
    }
457
    catch( SecurityException e )
458
    {
459
      // this can be thrown by getFreeSpace
460
       mLogger.warn("hasSufficientDiskSpace caught SecurityException");
461
    }
462
 
463
    mLogger.info("hasSufficientDiskSpace returned " + retVal + " " + freeSpace);
464
    return retVal;
465
  }
466
 
467
  /**abstract method
468
   */
469
  public abstract void run();
470
 
471
  /**deletes directory and all its files
472
   */
473
  protected void deleteDirectory(File directory)
474
  {
475
    mLogger.debug("deleteDirectory " + directory.getName());
476
    try
477
    {
478
      if ( directory.exists() )
479
      {
480
        FilenameFilter filter = new FilenameFilter()
481
        {
482
          public boolean accept(File file, String name)
483
          {
484
            mLogger.debug("accept " + name);
485
            boolean retVal = false;
486
 
840 mhunt 487
            if ( name.compareTo(".") != 0 && ( name.compareTo("..") != 0 ) )
814 mhunt 488
            {
489
              retVal = true;
490
            }
491
 
492
            mLogger.info("accept returned " + retVal);
493
            return retVal;
494
          }
495
        };
496
 
497
        File[] children = directory.listFiles( filter );
498
 
499
        if ( children != null )
500
        {
501
          for ( int child=0; child < children.length; child++ )
502
          {
503
            if ( children[ child ].isDirectory() )
504
            {
505
              deleteDirectory( children[ child ] );
506
            }
507
            else
508
            {
509
              children[ child ].delete();
510
            }
511
          }
512
        }
513
        directory.delete();
514
      }
515
    }
516
    catch( SecurityException e )
517
    {
518
      // this can be thrown by exists and delete
519
       mLogger.warn("deleteDirectory caught SecurityException");
520
    }
521
  }
522
 
523
  /**abstract method
524
   */
525
  protected abstract char getMode();
526
 
527
  /**injects GBE_BUILDFILTER into the passed buildFileContent
528
   * builds a buildFile from the buildFileContent
529
   * triggers ant to operate on the buildFile
530
   */
854 mhunt 531
  protected void deliverChange(String buildFileContent, String target, boolean master)
814 mhunt 532
  {
533
    mLogger.debug("deliverChange");
854 mhunt 534
 
866 mhunt 535
    // always perform a AbtSetUp, AbtPublish (master only), and AbtTearDown
536
    if ( target == null && mErrorReported )
854 mhunt 537
    {
866 mhunt 538
      // AbtSetUp failed
539
      // the default target will inevitably fail and will generate further email if allowed to proceed
540
      // do not mask the root cause
854 mhunt 541
      return;
542
    }
543
 
814 mhunt 544
    File buildFile = new File(mRtagId + "build.xml");
862 mhunt 545
    boolean logError = true;
866 mhunt 546
    Project p = new Project();
814 mhunt 547
 
548
    try
549
    {
550
      // clear the file contents
551
      if ( buildFileContent != null && target != null && target.compareTo("AbtSetUp") == 0 )
552
      {
553
        FileOutputStream buildFileOutputStream = new FileOutputStream(buildFile, false);
554
        buildFileOutputStream.close();
555
 
556
        StringReader buildFileContentStringReader = new StringReader(buildFileContent);
557
        BufferedReader buildFileBufferedReader = new BufferedReader(buildFileContentStringReader);
558
 
559
        // sanitise the buildFileContent
560
        // it may contain line.separators of "\n", "\r", or "\r\n" variety, depending on the location of the ripple engine
561
        String sanitisedBFC = new String();
562
        String lf = new String( System.getProperty("line.separator") );
563
        int lineCount = 0;
564
        String line = new String();
565
 
566
        while( ( line = buildFileBufferedReader.readLine() ) != null)
567
        {
568
          sanitisedBFC += line + lf;
569
          lineCount++;
570
 
571
          if ( lineCount == 2 )
572
          {
573
            // have read the first two lines
862 mhunt 574
            String inject = "<property name=\"abt_MASTER\" value=\"";
814 mhunt 575
 
576
            if ( master )
577
            {
578
              inject += "yes\"/>" + lf;
579
            }
580
            else
581
            {
582
              inject += "no\"/>" + lf;
583
            }
584
 
585
            // insert a GBE_BUILDFILTER property if necessary
586
            if ( mGbebuildfilter.length() > 0 )
587
            {
862 mhunt 588
              inject += "<property name=\"abt_GBE_BUILDFILTER\" value=\"" + mGbebuildfilter + "\"/>" + lf;
814 mhunt 589
            }
590
 
591
            mLogger.info("deliverChange injecting " + inject);
592
            sanitisedBFC += inject;
593
          }
594
        }
595
        buildFileBufferedReader.close();
596
        FileWriter buildFileWriter = new FileWriter(buildFile);
597
        buildFileWriter.write(sanitisedBFC);
598
        buildFileWriter.close();
599
      }
600
 
866 mhunt 601
      mReportingPackageName = null;
602
      mReportingPackageVersion = null;
603
      mReportingPackageExtension = null;
604
      mReportingPackageLocation = null;
605
      mReportingPackageDepends = null;
606
      mReportingIsRipple = null;
607
      mReportingPackageVersionId = null;
608
      mReportingDoesNotRequireSourceControlInteraction = null;
609
      mReportingFullyPublished = null;
610
      mReportingNewLabel = null;
611
 
612
      if ( buildFile.exists() )
814 mhunt 613
      {
866 mhunt 614
        p.setProperty("ant.file", buildFile.getAbsolutePath());
615
        DefaultLogger dl = new DefaultLogger();
616
        PrintStream ps = new PrintStream(mRtagId + ".log");
617
        dl.setOutputPrintStream(ps);
618
        dl.setMessageOutputLevel(Project.MSG_INFO);
619
        p.addBuildListener(dl);
620
        p.init();
621
        ProjectHelper pH = ProjectHelper.getProjectHelper();
622
        p.addReference("ant.projectHelper", pH);
623
 
624
        // parse can throw BuildException, this is serious
625
        pH.parse(p, buildFile);
626
        mLogger.warn("deliverChange ant launched on " + buildFile.getAbsolutePath());
627
 
628
        if ( target == null )
629
        {
630
          target = p.getDefaultTarget();
631
        }
632
        mLogger.warn("deliverChange ant launched against target " + target);
633
 
634
        // executeTarget can throw BuildException, this is not serious
635
        logError = false;
636
        // set up project properties for reporting purposes
637
        // this first group are hard coded in the build file
638
        mReportingPackageName = p.getProperty("abt_package_name");
639
        mReportingPackageVersion = p.getProperty("abt_package_version");
640
        mReportingPackageExtension = p.getProperty("abt_package_extension");
641
        mReportingPackageLocation = p.getProperty("basedir") + p.getProperty("abt_package_location");
642
        mReportingPackageDepends = p.getProperty("abt_package_depends");
643
        mReportingIsRipple = p.getProperty("abt_is_ripple");
644
        mReportingPackageVersionId = p.getProperty("abt_package_version_id");
645
        mReportingDoesNotRequireSourceControlInteraction = p.getProperty("abt_does_not_require_source_control_interaction");
646
 
647
        p.executeTarget(target);
648
        mLogger.warn("deliverChange ant returned");
649
 
814 mhunt 650
      }
651
    }
652
    catch( BuildException e )
653
    {
862 mhunt 654
      if ( logError )
655
      {
656
        mLogger.error("deliverChange caught BuildException, the build failed " + e.getMessage());
657
      }
658
      else
659
      {
866 mhunt 660
        if ( mReportingBuildFailureLogFile == null )
661
        {
662
          mReportingBuildFailureLogFile = e.getMessage();
663
        }
664
        mLogger.debug("deliverChange caught BuildException, big deal, the build failed " + mReportingBuildFailureLogFile);
862 mhunt 665
      }
854 mhunt 666
 
667
      mErrorReported = true;
814 mhunt 668
    }
669
    catch( FileNotFoundException e )
670
    {
671
      mLogger.error("deliverChange caught FileNotFoundException");
672
    }
673
    catch( IOException e )
674
    {
675
      mLogger.error("deliverChange caught IOException");
676
    }
677
 
866 mhunt 678
    // this group are set at run time (by the AbtPublish target only)
679
    // they will be null for every other target,
680
    // and null if an error occurs in the AbtPublish target
681
    mReportingFullyPublished = p.getProperty("abt_fully_published");
682
    mReportingNewLabel = p.getProperty("abt_new_label");
683
 
814 mhunt 684
  }
685
 
686
  /**sets up a ClearCase static view
687
   */
854 mhunt 688
  protected void setViewUp(String content, boolean master)
814 mhunt 689
  {
690
    mLogger.debug("setViewUp");
866 mhunt 691
    mReportingBuildFailureLogFile = null;
854 mhunt 692
    mErrorReported = false;
814 mhunt 693
    // run ant on the AbtSetUp target
694
    deliverChange(content, "AbtSetUp", master);
695
  }
696
 
697
  /**Checks the archive for the <packageName>/<packageVersion>/built.<machtype> existence
698
   */
699
  protected boolean published(String archive, String packageName, 
700
                            String packageVersion, String machtype,
701
                            String generic)
702
  {
703
    mLogger.debug("published");
704
    boolean retVal = false;
705
 
706
    String fs = System.getProperty( "file.separator" );
707
    String destination = archive + fs + packageName + fs + packageVersion;
708
 
709
    mLogger.debug("published " + destination);
710
    String filename = "built.";
711
 
712
    if ( generic.compareTo("generic") == 0 )
713
    {
714
      filename += "generic";
715
    }
716
    else
717
    {
718
      filename += machtype;
719
    }
720
 
721
    mLogger.debug("published " + filename);
722
    File flag = new File( destination, filename );
723
 
724
    if ( flag.exists() )
725
    {
726
      retVal = true;
727
    }
728
    mLogger.debug("published returned " + retVal);
729
    return retVal;
730
  }
731
}