Subversion Repositories DevTools

Rev

Rev 7033 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6914 dpurdie 1
package com.erggroup.buildtool.abt;
2
 
3
import java.io.File;
4
import java.io.FileInputStream;
5
import java.io.FileOutputStream;
6
import java.io.FileWriter;
7
import java.io.IOException;
8
import java.util.ArrayList;
9
import java.util.Iterator;
10
import java.util.Properties;
11
 
7033 dpurdie 12
import org.slf4j.Logger;
13
import org.slf4j.LoggerFactory;
6914 dpurdie 14
import org.apache.tools.ant.BuildException;
15
import org.apache.tools.ant.Project;
16
import org.apache.tools.ant.Target;
17
import org.apache.tools.ant.Task;
18
import org.apache.tools.ant.taskdefs.Execute;
19
import org.apache.tools.ant.taskdefs.Redirector;
20
 
21
import com.erggroup.buildtool.abt.RemoteExecution.LogOutput;
22
import com.erggroup.buildtool.smtp.CreateUrls;
23
import com.erggroup.buildtool.smtp.Smtpsend;
24
import com.erggroup.buildtool.utilities.CommandBuilder;
25
import com.erggroup.buildtool.utilities.ElapseTime;
26
import com.erggroup.buildtool.utilities.utilities;
27
 
28
public class ABT extends Task
29
{
30
    private String ls = System.getProperty( "line.separator" );
31
    private String gbeMachtype = System.getenv("GBE_MACHTYPE");
32
    private String dpkgArchive = System.getenv("GBE_DPKG");
33
    private String hostname = System.getenv("GBE_HOSTNAME");
34
    private String gbeMachClass;          // Escrow Only
35
 
36
    // ant built in
37
    private Project project;
38
    private String basedir;
39
 
40
    // global
41
    private boolean master = false;
42
    private String gbebuildfilter;
43
    private String mailServer;
44
    private String mailSender;
45
 
46
    // project related
47
    private String rtagId;
48
    private String daemon;
49
    private String release;
50
    private String buildtoolVersion;
51
    private String family;
52
    private String oldExtension;
53
    private String newExtension;
54
    private ABTData abtData;
55
 
56
    // target related
57
    private Target target;
58
    private String packageVersionID;
59
    private String packageAlias;
60
    private String packageName;
61
    private String packageVersion;
62
    private String packageFullVersion;
63
    private String packageExtension;
64
    private String packageLoc;
65
    private String packageVcsTag;
66
    private String directChange;
67
    private String doesNotRequireSourceControlInteraction;
68
    private boolean isaRipple;
69
    private int testBuildInstruction = 0;
70
    private boolean generic = false;
71
    private boolean packageTarBall = false;
72
    private boolean useTestArchive = false;
73
    private String loc;
74
    private String unittests;
75
    private ArrayList<Depend> dependCollection = new ArrayList<Depend> ();
76
    private ArrayList<BuildInfo> buildInfoCollection = new ArrayList<BuildInfo>();
77
    private StringBuilder owners = new StringBuilder();;
78
    private Machine mMachine;
79
    private String logBase;
80
 
81
    // set up in execute
82
    private BuildStandards packageStandard = BuildStandards.NONE;           // Build standard for the package
83
    private BuildStandards buildStandard = BuildStandards.NONE;             // Build Standard for this instance
84
    private JavaVersions javaVersion = JavaVersions.NONE;
85
    private CompileTargets compileTarget = CompileTargets.NONE;
86
    // abt task result property
87
    private String propertyValue = "0";
88
    // output redirector
89
    private Redirector re;
90
    private File output;
91
    // exec thread
92
    private CommandBuilder command = new CommandBuilder();
93
    private String cwd;
94
    private Execute thread;
95
    private File wd;
96
    private String newVcsTag;
7033 dpurdie 97
    private static final Logger mLogger = LoggerFactory.getLogger(ABT.class);
6914 dpurdie 98
    private boolean fullyPublished = false;
99
 
100
    private static final char DEBUG = 0;
101
    private static final char INFO = 1;
102
    private static final char WARN = 2;
103
    private static final char ERROR = 3;
104
    private static final char FATAL = 4;
105
 
106
    //  Simple class to contain error information to be reported to the user
107
    private class ErrorInfo {
108
        String cmd;
109
        int result;
110
        String error;
111
 
112
        public ErrorInfo (String error)
113
        {
114
            this.error = error;
115
        }
116
 
117
        public ErrorInfo(String cmd, int result, String error)
118
        {
119
            this.cmd = cmd;
120
            this.result = result;
121
            this.error = error;
122
        }
123
 
124
        public String toString()
125
        {
126
            String rv = error;
127
            if (cmd != null)
128
            {
129
                rv += " : " + cmd;
130
                rv += " returned " + result;
131
            }
132
            return rv;
133
        }
134
 
135
        public String toHtml() {
136
            String rv = "Error : " + error;
137
            if (cmd != null)
138
            {
139
                rv += "<br>Command : " + cmd;
140
                rv += "<br>Returned: " + result;
141
            }
142
            return rv;
143
        }
144
    }
145
 
146
    /** Log a message to two locations
147
     *  1) log4j application wide log - using facility
148
     *  2) Ant Command output log - always
149
     * 
150
     * @param message   - Message to log
151
     * @param facility  - Log level
152
     */
153
    private void logMsg(String message, char facility)
154
    {
155
        if ( daemon != null )
156
        {
157
            if ( facility == DEBUG)
158
            {
159
                mLogger.debug(message);
160
            }
161
            else if ( facility == INFO)
162
            {
163
                mLogger.info(message);
164
            }
165
            else if ( facility == WARN)
166
            {
167
                mLogger.warn(message);
168
            }
169
            else if ( facility == ERROR)
170
            {
171
                mLogger.error(message);
172
            }
173
            else
174
            {
7033 dpurdie 175
                mLogger.error(message);
6914 dpurdie 176
            }
177
        }
178
 
179
        log( message );
180
    }
181
 
182
    /** Log two strings as 'info'
183
     *  The two strings are simply concatenated.
184
     * 
185
     * @param message1  - First part of the message
186
     * @param message2  - Second part of the message
187
     */
188
    private void logMsg(String message1, String message2)
189
    {
190
        logMsg( message1 + message2, INFO );
191
    }
192
 
193
 
194
    /** Add package location options
195
     *  Options depend on the build standard in use
196
     */
197
    private void addCommandLocate()
198
    {
199
        if ( packageStandard == BuildStandards.ANT )
200
        {
201
            command.add( "-locatefile=" + packageName + ".xml" );
202
        }
203
        else
204
        {
205
            command.add( "-locatepkg=" + packageLoc );
206
        }
207
    }
208
 
209
 
210
    /** Execute the command currently being assembled
211
     *  Logs command, exit code and execution duration
212
     * 
213
     * @param message           - Null: Don't report errors, otherwise text to prepend to the reported error
214
     * @return                  - Return code from the executed command
215
     * @throws Exception
216
     */
217
    private int runCommand( String message ) throws Exception
218
    {
219
        ElapseTime et = new ElapseTime();
220
 
221
        //  Need to create a cmd array with exactly the required number of arguments
222
        //  thread.setCommandline() cannot handle null items in the array
223
        //  Create a single logMessage while processing the array
224
        String logMessage = command.toString();
225
        logMsg( logMessage, WARN );
226
 
227
        thread.setCommandline(command.getArray());
228
        int retVal = thread.execute();
229
 
230
        //  Report error conditions 
231
 
232
        if ( retVal == Execute.INVALID )
233
        {
234
            reportErrorException( "Failure to execute thread, internal ABT problem", 256 );
235
        }
236
        else
237
        {
238
            logMsg( "command returned: "+ retVal  + ", elapsed time (S): " + et.toString(), WARN);
239
 
240
            if ( message != null && retVal != 0 )
241
            {
242
                ErrorInfo errorData = new ErrorInfo(command.toString() , retVal, message );
243
                reportErrorException( errorData, retVal );
244
            }
245
        }
246
 
247
        return retVal;
248
    }
249
 
250
    /**
251
     * Check that one marker file has been published into dpkg_archive 
252
     * Assumption - not called in Escrow Mode 
253
     * 
254
     * @param archive     - Archive to test
255
     * @param tag         - Marker suffix
256
     * 
257
     * @return true if the package is published 
258
     */
259
    private boolean checkPublished(String archive, String tag) throws Exception
260
    {
261
        if (archive == null)
262
        {
263
            reportErrorException( "GBE_DPKG environment variable not set", 256 );
264
        }
265
 
266
        String filename = "built." + tag;
267
        String destination = utilities.catDir(archive, packageName,  packageFullVersion); 
268
 
269
        //
270
        //  Have been having issues with NFS caching
271
        //  Current attempt is to flush NFS caches using freshFile(), but at the moment
272
        //  the code will still retry a number of time. This 'should' not be required if the
273
        //  flushing code is operational.
274
        //
275
        //  Insert log info if we have tried more than once
276
        //  Idea is to monitor first time failures and then delete this code
277
        //
278
 
279
        boolean found = false;
280
        int   maxwait = 2 * 4;
281
        for ( int ii = 0; ii < maxwait && !found; ii++)
282
        {
283
            found = utilities.freshFileExists(utilities.catDir(destination, filename));
284
            if ( !found )
285
            {
286
                // Debug - display files in the 
287
                try
288
                {
289
                    String files;
290
                    File folder = new File(destination);
291
                    File[] listOfFiles = folder.listFiles();
292
                    if ( listOfFiles == null )
293
                    {
294
                        logMsg( "published. Destination not a dir: " + destination, FATAL );
295
                    }
296
                    else
297
                    {
298
                        for (int i = 0; i < listOfFiles.length; i++) 
299
                        {
300
                            if (listOfFiles[i].isFile())
301
                            {
302
                                files = listOfFiles[i].getName();
303
                                logMsg("published. DirContent:" + files , WARN);
304
                            }
305
                        }
306
                    }
307
                }
308
                catch( Exception e )
309
                {
310
                    logMsg( "published. Display files caught Exception:" + e.getMessage(), FATAL );
311
                }
312
 
313
 
314
                Thread.sleep(500);
315
                logMsg("published. Wait for " + filename + ".(" + ii +")" , WARN);
316
            }
317
        }
318
 
319
        if ( found )
320
        {
321
            logMsg("published. " + filename + " exists", WARN);
322
        }
323
        else
324
        {
325
            logMsg("published. " + filename + " does not exist", WARN);
326
        }
327
 
328
        return found;
329
    }
330
 
331
    /** Print a line of text to a file
332
     * 
333
     * @param file  - FileWrite to print to
334
     * @param msg1  - Text to write. Will append line separator
335
     * @throws IOException
336
     */
337
    private void printPackage( FileWriter file, String msg1 ) throws IOException
338
    {
339
        file.write( msg1 + ls );
340
    }
341
 
342
    /** Copy a file
343
     * 
344
     * @param source    - Source File
345
     * @param dest      - Target File
346
     */
347
    private void copyFile( File source, File dest )
348
    {
349
        if ( source.exists() )
350
        {
351
            try
352
            {
353
                FileInputStream fis = new FileInputStream(source);
354
                FileOutputStream fos = new FileOutputStream(dest);
355
                byte[] buf = new byte[1024];
356
                int i = 0;
357
                while( (i=fis.read(buf)) != -1)
358
                {
359
                    fos.write(buf, 0, i);
360
                }
361
                fis.close();
362
                fos.close();
363
            }
364
            catch( Exception e )
365
            {
366
                logMsg( "copyFile caught Exception", ERROR );
367
            }
368
        }
369
    }
370
 
371
    /** Save the log file
372
     *  <br>Used on error build
373
     *  <br>Used on complete build
374
     * 
375
     * @return  True: Can log ( Daemon mode)
376
     */
377
 
378
    private boolean saveLogs()
379
    {
380
        if ( daemon == null )
381
        {
382
            // do nothing more in escrow
383
            return false;
384
        }
385
 
386
        // persist the failure log to GBE_LOG/hostname/rtagid/daemon
387
        String log = System.getenv("GBE_LOG");
388
 
389
        if ( log == null )
390
        {
391
            // cannot happen, GBE_LOG is checked in BuildDaemon at startup
392
            return false;
393
        }
394
 
395
        File destinationLog = new File( log );
396
        File destinationHostname = new File( destinationLog, hostname );
397
        File destinationRtagId = new File( destinationHostname, rtagId );
398
        // create directories
399
        new File( destinationRtagId, daemon).mkdirs();
400
 
401
        File destinationDaemon = new File( destinationRtagId, daemon );
402
 
403
        if ( destinationDaemon.exists() )
404
        {
405
            File buildsource = new File(rtagId + "build.xml");
406
            File buildcopy = new File( destinationDaemon, logBase + ".xml");
407
            copyFile( buildsource, buildcopy );
408
 
409
            File logsource = new File(rtagId + ".log");
410
            File logcopy = new File( destinationDaemon, logBase + ".log");
411
            copyFile( logsource, logcopy );
412
 
413
            logMsg("reportError persisting " + logcopy.getName(), WARN);
414
        }
415
 
416
        return true;
417
    }
418
 
419
    private void reportError(String error, int retVal)
420
    {
421
        reportError( new ErrorInfo(error), retVal);
422
    }
423
    private void reportError(ErrorInfo error, int retVal)
424
    {
425
        propertyValue = String.valueOf( retVal );
426
 
427
        logMsg( error.toString(), ABT.ERROR );
428
        logMsg( "reportError propertyValue = " + propertyValue + ", ", error.toString());
429
 
430
        //  Save the logs
431
        //      Will return false in situations were we can't proceed
432
        if ( ! saveLogs() )
433
        {
434
            return;
435
        }
436
 
437
        //  Only send emails if we have all the bits required
438
        //  Will not get this far unless we are in daemon mode
439
        if ( owners.length() > 0 && mailServer != null && mailSender != null )
440
        {
441
 
442
            String href = hostname + "/" + rtagId + "/" + daemon + "/" + logBase + ".log"; 
443
            String unc =  CreateUrls.generateUncBaseUrl() + "/" + href;
444
 
445
            String body = "Release: " + release + "<p>" +
446
                   "Package: " + packageName + "<p>" + 
447
                   "RM link: " + CreateUrls.generateRmUrl(rtagId,packageVersionID) + "<p>" +
448
                   "Build machine: " + hostname + "<p>" +
449
                   "Machine type: " + gbeMachtype + "<p>" +
450
                   error.toHtml() + "<p>" +
451
                   "Log file: <a href=\"" + unc + "\">" + href + "</a> ... URL expires in 5 working days time<p><hr>";
452
 
453
            try
454
            {
455
                Smtpsend.send( mailServer,          // mailServer
456
                               mailSender,          // source
457
                               owners.toString(),   // target
458
                               null,                // cc
459
                               null,                // bcc
460
                               "BUILD FAILURE on package " + packageName, // subject
461
                               body,                // body
462
                               null                 // attachment
463
                        );
464
            }
465
            catch( Exception e )
466
            {
467
                // not fatal
468
                logMsg( "reportError caught Exception", WARN);
469
            }
470
        }
471
 
472
    }
473
 
474
    private void reportErrorException(String error, int retVal) throws Exception
475
    {
476
        reportError( error, retVal );
477
        throw new Exception( hostname );
478
    }
479
 
480
    private void reportErrorException(ErrorInfo error, int retVal) throws Exception
481
    {
482
        reportError( error, retVal );
483
        throw new Exception( hostname );
484
    }
485
 
486
    /**
487
     * Init the metrics generation process
488
     * 
489
     * @exception Exception
490
     */
491
    private void metricsBegin() throws Exception
492
    {
493
        if ( master )
494
        {
495
            // gather metrics
496
            // jats -locatefile=.jats.packageroot etool jats_metrics -mode=init -rootdir=.
497
            // -locate=.jats.packageroot causes jats to cd to the folder containing the file .jats.packageroot
498
            // this file is created in the -path folder by jats release -extract
499
            // DEVI 51370 it is essential for metrics branch calculation the metrics utility is started within a static view
500
            //
501
            command.init("jats" );
502
            command.add( "-locatefile=.jats.packageroot" );
503
            command.add( "etool", "jats_metrics" );
504
            command.add( "-mode=init" );
505
            command.add( "-rootdir=." );
506
 
507
            runCommand( "Failure to collect metrics" );
508
        }     
509
    }
510
 
511
    /**
512
     * Complete the metrics generation process
513
     * 
514
     * @exception Exception
515
     */
516
    private void metricsEnd() throws Exception
517
    {
518
        if ( master )
519
        {
520
            File metrics = new File(utilities.catDir(basedir, rtagId + "abtmetrics.txt"));
521
            if ( metrics.exists() )
522
            {
523
                metrics.delete();
524
            }
525
 
526
            // gather metrics
527
            // jats -locatefile=.jats.packageroot etool jats_metrics -mode=finish -out=abtmetrics.txt
528
            command.init("jats" );
529
            command.add( "-locatefile=.jats.packageroot" );
530
            command.add( "etool", "jats_metrics" );
531
            command.add( "-mode=finish" );
532
            command.add( "-out=" + metrics.getAbsolutePath() );
533
 
534
            runCommand( "Failure to collect metrics" );
535
        }    
536
    }
537
 
538
    /**
539
     * Generate the build dependency data file.
540
     * 
541
     * @exception Exception
542
     */
543
    private void genbuild() throws Exception
544
    {
545
 
546
        //
547
        //  Create build files with updated dependency information
548
        //  In escrow mode : No new dependency information
549
        //  In daemon mode :
550
        //      Ripple     : New dependency information
551
        //      Verify     : Existing dependency information
552
        //
553
        //  In all modes  : ANT builds need an auto.xml
554
        //
555
        //  In order to create auto.xml/auto.pl with package dependencies need to
556
        //  create file with dependency data (auto.cfg) only because its
557
        //  needed by "jats_rewrite"
558
        //
559
        File cfg = null;
560
        boolean  createFile = false;
561
        if ( daemon != null )
562
        {
563
            createFile = true;
564
 
565
            // always generate auto.cfg
566
            cfg = new File( utilities.catDir(cwd, "auto.cfg"));
567
            cfg.createNewFile();
568
 
569
            if ( !cfg.exists() || !cfg.canWrite() )
570
            {
571
                reportErrorException( "Failed to open auto.cfg", 263 );
572
            }
573
 
574
            try
575
            {
576
                FileWriter cfgfw = new FileWriter(cfg);
577
                printPackage( cfgfw, packageName + " " + packageFullVersion );
578
 
579
                // provide releasemanager.projectname=<name[0]> and releasemanager.releasename=<name[1]>
580
                String[] name = release.split( " > ", 2 );
581
 
582
                if ( name.length == 2 )
583
                {
584
                    printPackage( cfgfw, "releasemanager.projectname=" + name[0] );
585
                    printPackage( cfgfw, "releasemanager.releasename=" + name[1] );
586
                }
587
 
588
                for (Iterator<Depend> it=dependCollection.iterator(); it.hasNext(); )
589
                {
590
                    Depend depend = it.next();
591
                    printPackage( cfgfw, depend.getPackage_Alias() );
592
                }
593
 
594
                cfgfw.close();
595
            }
596
            catch( IOException e )
597
            {
598
                reportErrorException( "Failure to write to auto.cfg", 263 );
599
            }
600
        }
601
        else
602
            if ( packageStandard == BuildStandards.ANT )
603
            {
604
                // Have not created an auto.xml with updated dependencies
605
                // Ant build still would like an auto.xml file
606
                //
607
                // ie packages with a line <import file="auto.xml" optional="true"/> are fine
608
                //    but in escrow and rebuild we still need an auto.xml to be kind
609
                //
610
                createFile = true;
611
            }
612
 
613
        //
614
        //  Create the auto.pl/auto.xml file if required
615
        //
616
        if ( createFile )
617
        {
618
            command.init("jats");
619
            addCommandLocate();
620
            command.add( "etool", "jats_rewrite" );
621
 
622
            if ( packageStandard == BuildStandards.ANT )
623
            {
624
                command.add( "-infile=" + packageName + "depends.xml" );
625
                command.add( "-outfile=auto.xml" );
626
            }
627
            else
628
            {
629
                command.add( "-infile=build.pl" );
630
                command.add( "-outfile=auto.pl" );
631
            }
632
 
633
            if ( cfg != null && daemon != null)
634
            {
635
                command.add( "-config=" + cfg.getAbsolutePath() );
636
 
637
                //  Validate the Release Manager versions against those in the build files
638
                //  Only do this in daemon mode for:
639
                //      We are rebuilding the package
640
                //          This is detected as: Not have VCS interaction AND is not a test Build
641
                boolean isaRebuild = doesNotRequireSourceControlInteraction != null && testBuildInstruction == 0;
642
                command.add(isaRebuild, "-validate");
643
 
644
                //  Ensure that we don't have excessive packages in the Metadata
645
                //  Only do this in daemon mode, for 'new' or 'test' builds
646
                //  Don't do for:
647
                //      Escrow builds - they can't fix it
648
                //      Ripple builds - it will break a lot of stuff
649
                //      Rebuilds      - it will break stuff
650
                // Do for:
651
                //      New Versions  - User can fix it
652
                //      Test Builds   - User can fix it
653
                boolean isaTestBuild = doesNotRequireSourceControlInteraction != null && testBuildInstruction > 0;
654
                boolean isaNewVersion = !isaRipple && !isaRebuild && !isaTestBuild;
655
                command.add( isaNewVersion || isaTestBuild, "-errors");
656
 
657
            }
658
            else
659
            {
660
                command.add( "-noconfig");
661
            }
662
 
663
            if ( oldExtension != null )
664
            {
665
                command.add( "-oldproject", oldExtension );
666
                command.add( "-newproject", newExtension );
667
            }
668
 
669
            runCommand( "Failure to generate build dependency information. Potentially caused by a mismatch between build files and Release Manager database" );
670
        }
671
    }
672
 
673
    /**
674
     * Build the package
675
     * 
676
     * @exception Exception
677
     */
678
    private void jatsBuildPackage() throws Exception
679
    {
680
        //--------------------------------------------------------------------------
681
        //  Wait for package replication and caching
682
        //      If there is a GBE_DPKG_REPLICA, then there may be a delay between
683
        //      a package being built and the package being available on the replica
684
        //      We need to wait for the required packages to replicate
685
        //
686
        //      If there is a GBE_DPKG_CACHE, then we need to cache the package
687
        //      into the local store - mostly for windows as it seriously speeds
688
        //      up the builds.
689
 
690
        Boolean hasReplica = System.getenv("GBE_DPKG_REPLICA") != null;
691
        Boolean hasCache   = System.getenv("GBE_DPKG_CACHE") != null;
692
 
693
        if (daemon != null && (hasReplica || hasCache)  && !dependCollection.isEmpty())
694
        {
695
            /*
696
             * Limit the command line length provided to the following utility
697
             * Very very long dependency lists may over fill the command line
698
             */
699
            Iterator<Depend> it=dependCollection.iterator();
700
            while( it.hasNext() )
701
            {
702
 
703
                command.init( "jats", "etool", "cache_dpkg");
704
                command.add( hasReplica, "-wait" );
705
 
706
                // ANT builds require the package to be cached
707
                // JATS does not - if its needed it will be done later
708
                command.add( buildStandard != BuildStandards.ANT , "-nocache");
709
 
710
                // Add PackageName/PackageVersion
711
                for (int maxArgs = 0; maxArgs < 10 && it.hasNext(); maxArgs++ )
712
                {
713
                    Depend depend = it.next();
714
                    command.add(depend.getPackageNameVersion());
715
                }
716
 
717
                // Run the command - don't care if it fails
718
                runCommand( null );
719
            }
720
        }
721
 
722
        //--------------------------------------------------------------------------
723
        //  Build Phase
724
        //  Create build environment
725
 
726
        command.init( "jats" );
727
        command.add( gbebuildfilter != null ,"-buildfilter", gbebuildfilter);
728
        addCommandLocate();
729
 
730
        if ( buildStandard == BuildStandards.ANT )
731
        {
732
            command.add( "abt" );
733
            command.add( "-java=" + javaVersion.getJavaVersion() );
734
            command.add( "-buildfile=" + packageName + ".xml" );
735
            command.add( "build" );
736
        }
737
        else
738
        {
739
            command.add( "build", "--package" );
740
 
741
            // Daemon: Sanity check the building of Generic packages
742
            // Escrow: Allow this error - for backward compatibility
743
            if ( daemon != null )
744
            {
745
                if (generic) 
746
                    command.add( "-generic" );
747
                else
748
                    command.add( "-nogeneric" );
749
            }
750
 
751
            // Cache packages into a machine-local archive
752
            //  Will only do this if the package is really built
753
            //
754
            command.add(hasCache, "--cache" );
755
        }
756
 
757
        runCommand( "Failure to set up sandbox" );
758
 
759
        //--------------------------------------------------------------------------
760
        //  Make Package phase
761
        //  Create the package (make)
762
 
763
        command.init("jats" );
764
        command.add( gbebuildfilter != null, "-buildfilter", gbebuildfilter);
765
        addCommandLocate();
766
 
767
        if ( buildStandard == BuildStandards.ANT )
768
        {
769
            command.add( "abt" );
770
            command.add( "-java=" + javaVersion.getJavaVersion() );
771
            command.add( "-buildfile=" + packageName + ".xml" );
772
            command.add( "make_package" );
773
        }
774
        else
775
        {
776
            command.add( "make", "NODEPEND=1" );
777
 
778
            if ( compileTarget == CompileTargets.PROD )
779
            {
780
                command.add( "prod", "package_prod" );
781
            }
782
            else if ( compileTarget == CompileTargets.DEBUG )
783
            {
784
                command.add( "debug", "package_debug" );
785
            }
786
            else
787
            {
788
                command.add( "all" );
789
            }
790
        }
791
 
792
        runCommand( "Failure to generate derived files" );
793
 
794
 
795
        //--------------------------------------------------------------------------
796
        //  Unit tests phase
797
        //  Run autonomous unit tests
798
 
799
        if ( unittests != null )
800
        {
801
            command.init("jats" );
802
            command.add( gbebuildfilter != null, "-buildfilter", gbebuildfilter);
803
            addCommandLocate();
804
 
805
            if ( buildStandard == BuildStandards.ANT )
806
            {
807
                command.add( "abt" );
808
                command.add( "-java=" + javaVersion.getJavaVersion() );
809
                command.add( "-buildfile=" + packageName + ".xml" );
810
                command.add( "run_tests" );
811
            }
812
            else
813
            {
814
                command.add( "make" );
815
                if ( compileTarget == CompileTargets.PROD )
816
                {
817
                    command.add( "run_unit_tests_prod" );
818
                }
819
                else if ( compileTarget == CompileTargets.DEBUG )
820
                {
821
                    command.add( "run_unit_tests_debug" );
822
                }
823
                else
824
                {
825
                    command.add( "run_unit_tests" );
826
                }
827
            }
828
 
829
            runCommand( "Failure to run unit tests" );
830
        }
831
 
832
        //--------------------------------------------------------------------------
833
        //  create_dpkg phase
834
        //  Publish the package to dpkg_archive
835
        //
836
 
837
        command.init("jats" );
838
        addCommandLocate();
839
        command.add( "create_dpkg", "-m" );
840
        command.add( packageTarBall, "-tarmode");
841
        command.add( generic, "-generic" );
842
        command.add( "-pname", packageName );
843
        command.add( "-pversion", packageFullVersion );
844
 
845
        runCommand( "Failure to publish to archive" );
846
 
847
        insertEscrowMarker();
848
    }
849
 
850
    /** Skip Build an ANT Package 
851
     *  Only used on ANT based builds in which it has been determined that another machine
852
     *  is performing the build.
853
     *  
854
     *  Insert required marker files to indicate that the build has occurred
855
     *  Perform this using JATS commands to ensure correct creation of the marker files
856
     *  Basically, a dummy publish phase
857
     *  
858
     *  Note: Skip Builds cannot be generic
859
     *  
860
     */
861
    private void jatsSkipPackage() throws Exception
862
    {
863
        command.init( "jats" );
864
        command.add( "-here" );
865
        command.add( "create_dpkg", "-m" );
866
        command.add( packageTarBall, "-tarmode");
867
        command.add( "-noBuild" );
868
        command.add( "-pname", packageName );
869
        command.add( "-pversion", packageFullVersion );
870
 
871
        runCommand( "Failure to (skip)publish to archive" );
872
    }
873
 
874
    /**   Check if the package has been Published on all the required machines
875
     *    If its a 'generic' package then a tag of built.generic will have been placed in the package
876
     *    Otherwise each build machine will place a built.<MachName> file in the package when
877
     *    its build is completed successfully.
878
     *  
879
     *    If we don't have a complete set of 'built' files, then the package failed to build
880
     *    on one or more platforms. The assumption is that the build failure has been reported
881
     *    by the build daemon.
882
     *  
883
     *    All we know is which MachTypes we build for. This needs to be expanded into
884
     *    a list of MachineNames. Thus a build-set with multiple machines of the same MachType
885
     *    can indicate build failures.
886
     */
887
    private void puplishPackage() throws Exception
888
    {  
889
        //  If the package fragments are being delivered as tarballs then they needs to be reassembled
890
        if (packageTarBall)
891
        {
892
            fullyPublished = assemblePackage();
893
        }
894
 
895
        if (fullyPublished)
896
        {
897
            if ( generic )
898
            {
899
                //  Generic - only one marker file
900
                fullyPublished = checkPublished( dpkgArchive, "generic" );
901
            }
902
            else
903
            {
904
                //  Multi machine package
905
                //  Scan required target machines artifacts
906
                //  Expand from MachType to one or more MachName's
907
                scanBuilds:
908
                    for (Iterator<BuildInfo> ip=buildInfoCollection.iterator(); ip.hasNext(); )
909
                    {
910
                        BuildInfo buildInfo = ip.next();
911
                        for (Iterator<Machine> it=abtData.machineCollection.iterator(); it.hasNext(); )
912
                        {
913
                            Machine ma = it.next();
914
                            if (ma.getMachtype().compareTo(buildInfo.getMachtype()) == 0 )
915
                            {
916
                                fullyPublished = checkPublished( dpkgArchive, ma.getName() );
917
                                if ( !fullyPublished )
918
                                {
919
                                    //  Break out of both loops
920
                                    //  Once we have seen an error we need to retain it.
921
                                    break scanBuilds;
922
                                }
923
                            }
924
                        }
925
                    }
926
            }
927
        }
928
 
929
        //  Detect problem with zero length descpkg file
930
        //      May be caused by write clash from multiple machines
931
        //      Don't know
932
        //
933
        //  Not forcing NFS flush as this will have been done in the previous step
934
        //
935
        if ( fullyPublished )
936
        {
937
            String destination = utilities.catDir(dpkgArchive, packageName, packageFullVersion, "descpkg");
938
            File flag = new File( destination);
939
 
940
            //  File Must
941
            //      Exist
942
            //      Be a File
943
            //      Have a length. Problem appears to be zero length file
944
            //
945
            boolean found = false;
946
            logMsg( "published. Descpkg Sanity Test: " + flag.getPath(), DEBUG );
947
            if (!flag.exists() ) {
948
                reportErrorException( "No descpkg file. Package may not build with current build filters", 261 );
949
 
950
            } else if ( !flag.isFile()) {
951
                reportErrorException( "Descpkg Sanity Test: Is not a file", 261 );
952
 
953
            } else if ( flag.length() <= 0 ) {
954
                reportErrorException( "Descpkg Sanity Test: Zero length File", 261 );
955
 
956
            } else {
957
                logMsg( "published. Descpkg Sanity Test: Passed", INFO );
958
                found = true;
959
            }
960
 
961
            if (!found) {
962
                fullyPublished = false;
963
            }
964
        }
965
 
966
        if ( fullyPublished && daemon != null )
967
        {
968
            if ( doesNotRequireSourceControlInteraction == null )
969
            {
970
                //
971
                //  Save modified build files
972
                //  Label the resultant files
973
                //  Create a command of the form:
974
                //      jats etool jats_vcssave_build
975
                //          -infile     auto.xml/auto.pl
976
                //          -outfile    xxxdepends.xml/build.pl
977
                //          -pname      package_name
978
                //          -pversion   package_version
979
                //          -infofile   path_to_info_file
980
                //          -wiplabel   Existing WIP label (optional)
981
                //          -baselabel  View label
982
 
983
                logMsg("publish save build files", WARN);
984
 
985
                File saveinfo = new File(utilities.catDir(basedir, rtagId + "abtinfo.txt"));
986
                if ( saveinfo.exists() )
987
                {
988
                    saveinfo.delete();
989
                }
990
 
991
                command.init("jats" );
992
                addCommandLocate();
993
                command.add( "etool", "jats_vcssave_build" );
994
 
995
                if ( packageStandard == BuildStandards.ANT )
996
                {
997
                    command.add( "-infile", "auto.xml" );
998
                    command.add( "-outfile", packageName + "depends.xml" );
999
                }
1000
                else
1001
                {
1002
                    command.add( "-infile", "auto.pl" );
1003
                    command.add( "-outfile", "build.pl" );
1004
                }
1005
 
1006
                command.add( "-pname", packageName );
1007
                command.add( "-pversion", packageFullVersion );
1008
                command.add( directChange != null, "-isawip" );
1009
                command.add( "-infofile", saveinfo.getAbsolutePath() );
1010
                command.add( "-baselabel", packageVcsTag );
1011
 
1012
                if ( oldExtension != null && newExtension != null && packageExtension.compareTo( newExtension ) == 0 )
1013
                {
1014
                    // only branch build.pl where its extension is being migrated
1015
                    command.add( "-branch", "project_migration_branch", "-newbranch" );
1016
                }
1017
 
1018
                runCommand( "Failure to save build file changes into source control" );
1019
 
1020
                //
1021
                //  The command creates an info file(saveinfo) to pass information back
1022
                //  to the caller (me). This is a 'properties' file
1023
                //  Need to extract the following information
1024
                //    newVcsTag - which is held as VCS.tag
1025
                //
1026
                logMsg("publish read info file", INFO);
1027
 
1028
                Properties properties = new Properties();
1029
                try
1030
                {
1031
                    properties.load(new FileInputStream(saveinfo));
1032
                }
1033
                catch (IOException e)
1034
                {
1035
                    reportErrorException( "Failed to open save_build info file", 262 );
1036
                }
1037
 
1038
                newVcsTag = properties.getProperty("VCS.tag" );
1039
                if ( newVcsTag == null )
1040
                {
1041
                    reportErrorException( "Save_build info. Missing property:VCS.tag", 262 );
1042
                }
1043
                logMsg("publish read info file. Label:" + newVcsTag , INFO);
1044
            }
1045
        }
1046
    }
1047
 
1048
    /** Re-assemble package fragments into a package within the target archive
1049
     *  Used only in non-escrow mode
1050
     *  
1051
     *  This method will invoke a command on the target package server
1052
     *  This is done to overcome several issues:
1053
     *  1) Atomic merging of package fragments
1054
     *  2) Very long times seen in transferring a package with a large number of files
1055
     *     over a non-local network. It may take a second to create a file. For a 3000 file
1056
     *     package we were seeing times of about an hour simply to transfer the files from AWS(Sydney)
1057
     *     to the package server in Perth.
1058
     *     
1059
     *  The down side is that we need to set up an SSH session to the package server
1060
     *  We need:
1061
     *  1) Network name of the machine
1062
     *  2) User on the machine to do the work
1063
     *  3) Credentials for that user
1064
     *  
1065
     *   The existence of these items will have been performed by the daemon at startup
1066
     *   This simplifies the process of reporting errors
1067
     * 
1068
     * @return  true - reassemble occurred correctly
1069
     * @throws Exception 
1070
     */
1071
    private boolean assemblePackage() throws Exception 
1072
    {
1073
        if ( daemon == null )
1074
        {
1075
            // Not to be used in escrow
1076
            return false;
1077
        }
1078
        /*
1079
         *  Setup the credentials
1080
         *  The format 'should' have been checked as the daemon started
1081
         *  The link should have been authenticated before the build was started,
1082
         *  but it may have gone down since.
1083
         */
1084
        LogOutput logger = new LogOutput()
1085
        {
1086
            @Override
1087
            public void data(String message) {
1088
                logMsg( message, INFO );
1089
            }
1090
 
1091
            @Override
1092
            public void info(String message) {
1093
                logMsg( message, INFO );
1094
            }
1095
 
1096
            @Override
1097
            public void fatal(String message) {
1098
                logMsg( message, FATAL);
1099
            }
1100
        };
1101
 
1102
        ElapseTime et = new ElapseTime();
1103
        RemoteExecution mRemoteExecution = new RemoteExecution(logger);
1104
 
1105
        /*
1106
         * Generate the command string
1107
         * Its being executed over an ssh session so we need to:
1108
         *  1) Set up the required environment
1109
         *  2) Set the location of GBE_DPKG - more for testing
1110
         */
1111
        command.init();
1112
        command.add("sudo","-n", "-u", "buildadm", "/home/releasem/sbin/jatsTool", "assemble_dpkg");
1113
        command.add(useTestArchive, "-testArchive");
1114
        command.add("'-pname=" + packageName + "'");
1115
        command.add("'-pversion=" + packageFullVersion + "'");
1116
 
1117
        String cmd = command.toString();
1118
        logMsg( "assemblePackage. Command:" + cmd, WARN );
1119
        int retCode = mRemoteExecution.execute(cmd);
1120
        logMsg( "command returned: "+ retCode + ", elapsed time (S): " + et.toString(), WARN);
1121
        if (retCode != 0)
1122
        {
1123
            reportErrorException( "Package reassembly error", 267 );
1124
        }
1125
        return 0 == retCode;
1126
    }
1127
 
1128
    /** determineBuildStandard
1129
     *  Process the current target and set up
1130
     *      buildStandard
1131
     *          compileTarget
1132
     *          javaVersion
1133
     *          
1134
     *      packageStandard
1135
     *          The package standard is used to determine the mode used to process the auto.cfg file
1136
     *          
1137
     */
1138
    private void determineBuildStandard() throws Exception 
1139
    {
1140
        // Scan the platform collection looking for an entry that matches the current machine
1141
        //
1142
        // Just wanting to set up
1143
        //    buildStandard and one of
1144
        //        compileTarget
1145
        //    OR  javaVersion
1146
 
1147
        for (Iterator<BuildInfo> it = buildInfoCollection.iterator(); it.hasNext();)
1148
        {
1149
            BuildInfo buildInfo = it.next();
1150
            String method = buildInfo.getMethod();
1151
            String arg = buildInfo.getArg();            
1152
 
1153
            //  Capture the first non-null build standard as the packageStandard
1154
            if ( packageStandard == BuildStandards.NONE)
1155
            {
1156
                if (method.equals("jats"))
1157
                {
1158
                    packageStandard = BuildStandards.JATS;
1159
                }
1160
                else if (method.equals("ant"))
1161
                {
1162
                    packageStandard = BuildStandards.ANT;
1163
                }
1164
            }
1165
 
1166
            //  Capture the build standard for the current machine type
1167
            if (gbeMachtype.compareTo(buildInfo.getMachtype()) == 0)
1168
            {
1169
                if (method.equals("jats"))
1170
                {
1171
                    buildStandard = BuildStandards.JATS;
1172
                    if (arg.compareTo("production") == 0)
1173
                    {
1174
                        compileTarget = CompileTargets.PROD;
1175
 
1176
                    }
1177
                    else if (arg.compareTo("debug") == 0)
1178
                    {
1179
                        compileTarget = CompileTargets.DEBUG;
1180
 
1181
                    }
1182
                    else if (arg.compareTo("all") == 0)
1183
                    {
1184
                        compileTarget = CompileTargets.ALL;
1185
 
1186
                    }
1187
                    else
1188
                    {
1189
                        reportErrorException("Failure, unsupported Jats build environment " + arg + ", internal ABT problem", 256);
1190
                    }   
1191
                }
1192
                else if (method.equals("ant"))
1193
                {
1194
                    buildStandard = BuildStandards.ANT;
1195
 
1196
                    //    Handle version of 'none' and of the form 'n.n'
1197
                    //    Anything else is an error
1198
 
1199
                    javaVersion = new JavaVersions(arg);
1200
                    if ( javaVersion.isBad())
1201
                    {
1202
                        reportErrorException("Failure, unsupported Ant build environment " + arg + ", internal ABT problem", 256);
1203
                    }
1204
                }
1205
 
1206
                else if (method.equals("none"))
1207
                {
1208
                    buildStandard = BuildStandards.NONE;
1209
                }
1210
                else
1211
                {
1212
                    reportErrorException("Failure, unsupported build method " + method + ", internal ABT problem", 256);    
1213
                }
1214
            }
1215
        }
1216
 
1217
        //
1218
        //    Log the build method and arguments
1219
        //
1220
        logMsg("execute packageStandard: ", packageStandard.getBuildStandard());
1221
        logMsg("execute buildStandard: ", buildStandard.getBuildStandard());
1222
        if (buildStandard == BuildStandards.ANT )
1223
        {
1224
            logMsg("execute javaVersion: ", javaVersion.getJavaVersion());    
1225
        }
1226
        else if (buildStandard == BuildStandards.JATS )
1227
        {
1228
            logMsg("execute compileTarget: ", compileTarget.getCompileTarget());    
1229
        }
1230
 
1231
 
1232
        //  Daemon Mode Only
1233
        //  If we have an ANT Build then we may have an additional problem.
1234
        //  If there is more than one machine of the same 'Machine Class' in the buildset, then
1235
        //  we need to limit the build to just one of them.
1236
        //  In Escrow this is not an issue as the builds are done serially
1237
        //
1238
        //  The rule is:
1239
        //    If there is only one machine in the class - then use it
1240
        //    If there are multiple machines of the same class - then use the first one that has JAVA in its build filter
1241
        //    If none have JAVA in the build filter, then use the first one in the list
1242
        // Supplementary Rules:
1243
        //    If a machine does no have a buildfilter, then assume that it can build everything
1244
        // 
1245
        // Rule Simplification:
1246
        //    If this machine is building ANT, then exclude ourself from the build if
1247
        //    another machine satisfies the criteria. ie: another machine will determine that
1248
        //    it will build the ANT component.
1249
        //
1250
        if (buildStandard == BuildStandards.ANT && daemon != null)
1251
        {
1252
            int classCount = 0;
1253
            Machine firstWithJava = null;
1254
            Machine firstInMachClass = null;
1255
 
1256
            for (Iterator<Machine> it = abtData.machineCollection.iterator(); it.hasNext();)
1257
            {
1258
                Machine ma = it.next();
1259
                if (ma.getMachclass().equals(mMachine.getMachclass()) )
1260
                {
1261
                    classCount++;
1262
 
1263
                    if (firstInMachClass == null)
1264
                        firstInMachClass = ma;
1265
 
1266
                    if (firstWithJava == null)
1267
                    {
1268
                        String buildFilter = ma.getBuildfilter();
1269
                        if (buildFilter != null)
1270
                        {
1271
                            buildFilter = "," + buildFilter.replace(" ", ",") + ",";
1272
                        }
1273
 
1274
                        if (buildFilter == null || buildFilter.contains(",JAVA,"))
1275
                        {
1276
                            firstWithJava = ma;
1277
                        }
1278
                    }
1279
                }
1280
            }
1281
 
1282
            // If none have 'JAVA', then used the first machine in the nominated class
1283
            if (firstWithJava == null)
1284
            {
1285
                firstWithJava = firstInMachClass;
1286
            }
1287
 
1288
 
1289
            //
1290
            //  Apply the rule described above.
1291
            //  Really only need to disqualify ourselves iff there is another machine that will do the build
1292
            //
1293
            if ((classCount > 1) && (firstWithJava != null) && (mMachine != firstWithJava))
1294
            {
1295
                javaVersion = JavaVersions.SKIP;
1296
                logMsg("execute determineBuildStandard: Exclude myself from ANT Build", INFO);
1297
            }
1298
        }
1299
    }
1300
 
1301
 
1302
    /** execute
1303
     *  The Ant Task entry point. This is invoked to perform the targets action
1304
     *      Display the start and end time of the action
1305
     */
1306
    @Override
1307
    public void execute()
1308
    {
1309
        ElapseTime et = new ElapseTime();
1310
 
1311
        //  Setup enough information to enable logging
1312
        project = getProject();
1313
        target = getOwningTarget();
1314
        daemon = project.getProperty("abt_daemon");
1315
        rtagId = project.getProperty("abt_rtag_id");
1316
        release = project.getProperty("abt_release");
1317
 
1318
        logMsg( "execute start: " + ElapseTime.getTimeStamp(), WARN );
1319
        if ( daemon != null ) {
1320
            logMsg("execute daemon: yes", INFO);
1321
        }
1322
 
1323
        try {
1324
            executeAbtTask();    
1325
        }
1326
        finally         {
1327
            logMsg( "execute complete: " + ElapseTime.getTimeStamp(), INFO );
1328
            logMsg( "execute elapsed time (S): " + et.toString(), WARN);
1329
        }
1330
    }
1331
 
1332
    /** executeAbtTask
1333
     *  Body of the ABT execution task
1334
     *  Factored out so that a time stamp can be added to the log
1335
     */
1336
    private void executeAbtTask()
1337
    {
1338
        boolean errorReported = false;
1339
        boolean benign = false;
1340
        boolean skipped = false;
1341
 
1342
        try
1343
        {
1344
            // required by the Execute API on non win32 platforms, don't ask because I don't know
1345
            project.setProperty("ant.home", System.getenv("ANT_HOME"));
1346
 
1347
            // Setup the base name of the output log file
1348
            // Need to do before we report errors
1349
            if ( daemon != null )
1350
            {
1351
                //  Use the packages name and version
1352
                packageName = project.getProperty("abt_package_name");
1353
                logMsg("execute packageName: ", packageName);
1354
 
1355
                packageFullVersion = project.getProperty("abt_package_version");
1356
                logMsg("execute packageFullVersion: ", packageFullVersion);
1357
 
1358
                logBase = packageName + "_" +  packageFullVersion;
1359
            }
1360
            else
1361
            {
1362
                // Use the current target - which will be the packages name and version
1363
                logBase = target.getName();
1364
            }
1365
 
1366
            // Check the current hostname
1367
            //    Needed early as its used in error reporting
1368
            //    JATS should ensure that this value is set
1369
            // Daemon Mode:
1370
            //    When sending emails
1371
            //    Identify the target machine parameters
1372
            // Escrow Mode:
1373
            //    Determine escrow build components
1374
            //    
1375
            if (hostname == null) {
1376
                hostname = "unknown";
1377
                reportErrorException( "GBE_HOSTNAME environment variable not set", 256 );
1378
            }
1379
 
1380
            // early target related
1381
            packageAlias = target.getName();
1382
            packageVcsTag = project.getProperty(packageAlias + "packagevcstag");
1383
            logMsg("execute packageVcsTag: ", packageVcsTag);
1384
 
1385
            if ( packageVcsTag == null )
1386
            {
1387
                // this abt task has no properties, by design
1388
                // future use to estimate build completion time
1389
                logMsg("execute packageAlias: " + packageAlias, INFO);
1390
                return;
1391
            }
1392
 
1393
            logMsg("execute packageAlias: " + packageAlias, WARN);
1394
 
1395
            // ant built in
1396
            basedir = project.getProperty("basedir");
1397
            logMsg("execute basedir: ", basedir);
1398
 
1399
            // global
1400
 
1401
            if ( gbeMachtype == null ) {
1402
                reportErrorException( "GBE_MACHTYPE environment variable not set", 256 );
1403
            }
1404
 
1405
            if (dpkgArchive == null) {
1406
                reportErrorException( "GBE_DPKG environment variable not set", 256 );
1407
            }
1408
 
1409
            //  Locate ABTDATA
1410
            //  This will be referenced by a known ID
1411
            abtData = (ABTData) project.getReference("global-abt-data");
1412
            if (abtData == null) {
1413
                reportErrorException( "ABTData Task not found", 256 );
1414
            }
1415
 
1416
            if ( daemon != null )
1417
            {
1418
 
1419
                mailServer = project.getProperty("abt_mail_server");
1420
                if ( mailServer == null )
1421
                {
1422
                    reportErrorException( "Missing ANT property: abt_mail_server", 256 );
1423
                }
1424
                logMsg("execute mailServer: ", mailServer);
1425
 
1426
                mailSender = project.getProperty( "abt_mail_sender" );
1427
                if ( mailSender == null )
1428
                {
1429
                    reportErrorException( "Missing ANT property: abt_mail_sender", 256 );
1430
                }
1431
                logMsg("execute mailSender: ", mailSender);
1432
 
1433
                for (Iterator<Owner> it=abtData.ownerCollection.iterator(); it.hasNext(); )
1434
                {
1435
                    Owner owner = it.next();
1436
 
1437
                    if ( owners.length() > 0 )
1438
                    {
1439
                        owners.append(",");
1440
                    }
1441
                    owners.append(owner.getEmail());
1442
                    logMsg("execute owner: ", owner.getEmail());
1443
                }
1444
                logMsg("execute owners: ", owners.toString());
1445
            }
1446
 
1447
            if ( daemon == null)
1448
            {
1449
                // Locate any entry for my machType and use it to convert into machClass
1450
                // In escrow the hostName cannot be used.
1451
                //    
1452
                for (Iterator<Machine> it=abtData.machineCollection.iterator(); it.hasNext(); )
1453
                {
1454
                    Machine ma = it.next();
1455
                    if (ma.getMachtype().compareTo(gbeMachtype) == 0 )
1456
                    {
1457
                        gbeMachClass = ma.getMachclass();
1458
                        break;
1459
                    }
1460
                }
1461
 
1462
                if (gbeMachClass == null)
1463
                {
1464
                    reportErrorException( "No MachClass mapping for " + gbeMachtype, 256 );
1465
                }
1466
                logMsg("execute gbeMachClass: ", gbeMachClass);
1467
            }
1468
 
1469
            // project related
1470
            // Some data has already been collected. Just log it.
1471
            logMsg("execute rtagId: ", rtagId);
1472
            logMsg("execute release: ", release);
1473
 
1474
            packageVersionID = project.getProperty("abt_package_version_id");
1475
            if (packageVersionID != null)
1476
            {
1477
                logMsg("execute packageVersionID: ", packageVersionID); 
1478
            }
1479
 
1480
            buildtoolVersion = project.getProperty("abt_buildtool_version");
1481
            logMsg("execute buildtoolVersion: ", buildtoolVersion);
1482
 
1483
            family = project.getProperty("abt_family");
1484
            logMsg("execute family: ", family);
1485
 
1486
            oldExtension = project.getProperty("abt_old_extension");
1487
            logMsg("execute oldExtension: ", oldExtension);
1488
 
1489
            newExtension = project.getProperty("abt_new_extension");
1490
            logMsg("execute newExtension: ", newExtension);
1491
 
1492
            {
1493
                 String prop = project.getProperty("abt_test_build_instruction");
1494
                 logMsg("execute testBuildInstruction: ", prop);
1495
                 testBuildInstruction = 0;
1496
                 if ( prop != null)
1497
                 {
1498
                     testBuildInstruction = Integer.parseInt(prop);
1499
                 }
1500
            }
1501
 
1502
            {
1503
                String prop = project.getProperty("abt_is_ripple");
1504
                logMsg("execute isRipple: ", prop);
1505
                isaRipple = ( prop != null && Integer.parseInt(prop) > 0);
1506
            }
1507
 
1508
 
1509
            if ( project.getProperty("abt_packagetarball") != null ) {
1510
                packageTarBall = true;
1511
                logMsg("execute packageTarBall: yes", INFO);  
1512
            }
1513
 
1514
            if ( project.getProperty("abt_usetestarchive") != null ) {
1515
                useTestArchive = true;
1516
                logMsg("execute useTestArchive: yes", INFO);  
1517
            }
1518
 
1519
            // Locate Machine Information for this machine
1520
            //    It contains the build filter for the current machine
1521
            //    Only present in daemon builds
1522
            //
1523
            for (Iterator<Machine> it=abtData.machineCollection.iterator(); it.hasNext(); )
1524
            {
1525
                Machine ma = it.next();
1526
                if (ma.getName().compareTo(hostname) == 0 )
1527
                {
1528
                    mMachine = ma;
1529
                    logMsg("execute machine: ", mMachine.getName() + ", Type:" + mMachine.getMachtype() + ", Class:" + mMachine.getMachclass() + ", Master:" + mMachine.getMaster() ); 
1530
                    break;
1531
                }
1532
            }
1533
 
1534
            if ( (daemon != null) && (mMachine == null) ) {
1535
                reportErrorException( "Cannot find Machine entry for: " + hostname, 256 );
1536
            }
1537
 
1538
            //  Setup machine specific information
1539
            //    Build Filter
1540
            //    Master Mode
1541
            if (mMachine != null) 
1542
            {
1543
                if (mMachine.getMaster() != null)
1544
                {
1545
                    master = true;
1546
                    logMsg("execute master: ", "true");
1547
                }
1548
 
1549
                gbebuildfilter = mMachine.getBuildfilter(); 
1550
                if ( gbebuildfilter != null )
1551
                {
1552
                    //
1553
                    // Ensure the Execute task passes gbebuildfilter as one parameter...
1554
                    // Replace spaces with commas
1555
                    //
1556
                    gbebuildfilter = gbebuildfilter.replace( " ", ",");
1557
                    logMsg("execute gbebuildfilter: ", gbebuildfilter);
1558
                }
1559
            }
1560
 
1561
            // Extract the build standard information from the abt element
1562
            //  Sets up buildStandard and one of
1563
            //            compileTarget
1564
            //        OR  javaVersion
1565
 
1566
            determineBuildStandard();
1567
            if ( buildStandard == BuildStandards.NONE)
1568
            {
1569
                //  Flag a benign build is good
1570
                //  A benign is a no-operation. The build is not required on the current machine
1571
                //
1572
                benign = true;
1573
            }
1574
 
1575
            if ( buildStandard == BuildStandards.ANT && javaVersion == JavaVersions.SKIP )
1576
            {
1577
                //  Flag a benign build - we are not building
1578
                //  Flag a skipped build - we need to place a marker in dpkg_archive
1579
                // 
1580
                //  JavaVersions.SKIP is used when a ANT build could be done on multiple machines
1581
                //  It must only be done on one such machine
1582
                // 
1583
                benign = true;
1584
                skipped = true;
1585
            }
1586
 
1587
            // Do we really need to extract and work with the source
1588
            //      Escrow Mode : yes (Not done here)
1589
            //      Daemon Mode :
1590
            //          If Master : Yes. We need to generate metrics and update the build file
1591
            //          Not Master: May be
1592
            //                      If a benign build : No
1593
            boolean extractSource = true;
1594
            if ( daemon != null && !master && benign ) {
1595
                extractSource = false;
1596
            }
1597
            logMsg("execute extractSource: ", Boolean.toString(extractSource));
1598
            logMsg("execute benign: ", Boolean.toString(benign));
1599
            logMsg("execute skipped: ", Boolean.toString(skipped));
1600
 
1601
            // redirect all thread (therefore jats) output to the output file in the basedir
1602
            re = new Redirector(this);
1603
            if ( daemon != null )
1604
            {
1605
                // thread logging is done to <rtagId>thread.log and is continually re-used every build
1606
                // full thread and non thread (ie abt logging) is done to the DefaultLogger set up by the build daemons, <rtagId>.log
1607
                // this file is copied on a build failure to cwd (if it exists) and is continually re-used every build
1608
 
1609
                // capture full logging
1610
                re.setAlwaysLog(true);
1611
            }
1612
            else
1613
            {
1614
                output = new File( logBase + ".log" );
1615
            }
1616
 
1617
            if (output != null)
1618
            {
1619
                re.setOutput( output );
1620
            }
1621
            thread = new Execute(re.createHandler());
1622
            thread.setAntRun( project );
1623
            thread.setVMLauncher(false);
1624
 
1625
            // must set up package name and owners before reportError
1626
            packageName = project.getProperty(packageAlias + "packagename");
1627
            logMsg("execute packageName: ", packageName);
1628
 
1629
            //-----------------------------------------------------------------------
1630
            //    AbtTestPath
1631
            //
1632
            if ( packageAlias.compareTo("AbtTestPath") == 0 )
1633
            {
1634
 
1635
                // jats -label check pkgVcsTag
1636
                command.init("jats", "label","-check" );
1637
                command.add( packageVcsTag );
1638
                //command.add( "-verbose=2" );
1639
 
1640
                runCommand( "Failure to validate label in source control" );
1641
 
1642
                return;
1643
            }
1644
 
1645
            //-----------------------------------------------------------------------
1646
            //    AbtSetUp
1647
            //
1648
            if ( packageAlias.compareTo("AbtSetUp") == 0 )
1649
            {
1650
                // create rtag_id directory from scratch
1651
                File rId = new File( rtagId );
1652
                deleteDirectory(rId);
1653
                if (rId.exists())
1654
                {
1655
                    reportErrorException( "Build directory not empty", 264 );
1656
                }
1657
                rId.mkdirs();
1658
 
1659
                if (extractSource)
1660
                {
1661
                    // jats jats_vcsrelease -extract -label=pkgVcsTag -path=src_path -root=rtag_id/timestamp -tag=timestamp -noprefix
1662
                    command.init("jats", "jats_vcsrelease","-extract" );
1663
                    command.add( "-label=" + packageVcsTag );
1664
                    command.add( "-root=" + rtagId );
1665
                    command.add( "-tag=" + daemon );
1666
                    command.add( "-noprefix" );
1667
                    command.add(!master, "-extractfiles");
1668
                    //command.add( "-verbose=2" );
1669
 
1670
                    runCommand( "Failure to extract source code from source control" );
1671
                }
1672
                return;
1673
            }
1674
 
1675
            //-----------------------------------------------------------------------
1676
            //    AbtTearDown
1677
            //
1678
            if ( packageAlias.compareTo("AbtTearDown") == 0 )
1679
            {
1680
                // tear the build view down, regardless of build error
1681
                wd = new File( basedir );
1682
 
1683
                // only now change the thread working directory back
1684
                thread.setWorkingDirectory( wd );
1685
 
1686
                File buildDirectory = new File(wd + getProject().getProperty("abt_package_location"));
1687
 
1688
                if ( buildDirectory.exists() )
1689
                {
1690
                    // jats jats_vcsrelease -label pkgTag -root=rtag_id/timestamp -tag=timestamp -noprefix -delete=2
1691
                    command.init("jats", "jats_vcsrelease" );
1692
                    command.add( "-label=" + packageVcsTag );
1693
                    command.add( "-root=" + rtagId );
1694
                    command.add( "-tag=" + daemon );
1695
                    command.add( "-noprefix" );
1696
                    command.add( "-delete=2" );
1697
                    //command.add( "-verbose=2" );
1698
 
1699
                    runCommand( "Failure to remove source code extraction" );
1700
                }
1701
 
1702
                //  delete the rtagId directory
1703
                //  If it cannot be deleted then the build has done something ugly
1704
                //  Left over bits will only hurt following builds
1705
                File rId = new File( rtagId );
1706
                deleteDirectory(rId);
1707
                if (rId.exists() )
1708
                {
1709
                    reportErrorException( "Build directory cannot be removed after build", 264 );
1710
                }
1711
 
1712
                // Always save the log files
1713
                saveLogs();
1714
 
1715
                return;      
1716
            }
1717
 
1718
            // target related    
1719
            packageVersion = project.getProperty(packageAlias + "packageversion");
1720
            logMsg("execute packageVersion: ", packageVersion);
1721
 
1722
            packageExtension = project.getProperty(packageAlias + "packageextension");
1723
            logMsg("execute packageExtension: ", packageExtension);
1724
 
1725
            packageFullVersion = packageVersion + packageExtension;
1726
            logMsg("execute packageFullVersion: ", packageFullVersion);
1727
 
1728
            packageLoc = packageName + packageExtension;
1729
            logMsg("execute packageLoc: ", packageLoc);
1730
 
1731
            if ( project.getProperty(packageAlias + "generic") != null ) {
1732
                generic = true;
1733
                logMsg("execute generic: yes", INFO);  
1734
            }
1735
 
1736
            directChange = project.getProperty(packageAlias + "directchange");
1737
            if ( directChange != null )
1738
            {
1739
                logMsg("execute directChange: yes", INFO);  
1740
            }
1741
 
1742
            doesNotRequireSourceControlInteraction = project.getProperty(packageAlias + "doesnotrequiresourcecontrolinteraction");
1743
            if ( doesNotRequireSourceControlInteraction != null )
1744
            {
1745
                logMsg("execute doesNotRequireSourceControlInteraction: true", INFO);  
1746
            }
1747
 
1748
            //    Display details of the BuildInfo Jats and Ant elements within the
1749
            //    current ABT element
1750
            //
1751
            for (Iterator<BuildInfo> it=buildInfoCollection.iterator(); it.hasNext(); )
1752
            {
1753
                BuildInfo buildInfo = it.next();
1754
                logMsg("execute buildinfo: ", "MachType: " +  buildInfo.getMachtype() + " Method: " + buildInfo.getMethod() + " " + buildInfo.getArg() );
1755
            }
1756
 
1757
 
1758
            // Set newVsTag to the existing VcsTag
1759
            // Will be used when rebuilding a package that already exists
1760
            newVcsTag = packageVcsTag;
1761
 
1762
            //
1763
            //    Determine the location of the package, relative to 'basedir'
1764
            //    Change to this directory for the remainder of the build processing
1765
            loc = project.getProperty(packageAlias + "loc");
1766
            logMsg("execute loc: ", loc);
1767
 
1768
            cwd = utilities.catDir(basedir, loc);
1769
            logMsg("execute cwd: ", cwd);
1770
 
1771
            wd = new File( cwd );
1772
            if ( !wd.exists() )
1773
            {
1774
                reportErrorException( "Failure " + cwd + " does not exist", 265 );
1775
            }
1776
 
1777
            // only now change the thread working directory
1778
            thread.setWorkingDirectory( wd );
1779
 
1780
            //-----------------------------------------------------------------------
1781
            //    AbtPublish
1782
            //    Note: Have changed directory to the working directory
1783
            //
1784
            if ( packageAlias.compareTo("AbtPublish") == 0 )
1785
            {
1786
                puplishPackage();
1787
                if ( daemon != null )
1788
                {
1789
                    // set properties to drive BuildThread attributes
1790
                    // these are used to determine what ant did
1791
                    getProject().setProperty("abt_fully_published", Boolean.toString(fullyPublished));
1792
                    getProject().setProperty("abt_new_vcstag", newVcsTag);
1793
                }
1794
 
1795
                return;
1796
            }
1797
 
1798
            //-----------------------------------------------------------------------
1799
            //    Build Target
1800
            //    Note: Have changed directory to the working directory
1801
            //
1802
            packageVersionID = project.getProperty(packageAlias + "pv_id");
1803
            logMsg("execute packageVersionID: ", packageVersionID);
1804
 
1805
            unittests = project.getProperty(packageAlias + "unittests");
1806
            if ( unittests != null )
1807
            {
1808
                logMsg("execute unittests: yes", INFO);
1809
            }
1810
 
1811
            for (Iterator<Depend> it=dependCollection.iterator(); it.hasNext(); )
1812
            {
1813
                Depend depend = it.next();
1814
                logMsg("execute depend: ", depend.getPackage_Alias());
1815
            }
1816
 
1817
            if ( daemon == null )
1818
            {
1819
                // Escrow Only
1820
                // Recognize an escrow will be run multiple times on a build stage
1821
                //      Do not force continuous rebuilding each time
1822
                //      Has this package version already been published on this platform
1823
                if ( checkEscrowMarker() )
1824
                {
1825
                    logMsg( "execute package has been published on this platform - skipping", INFO);
1826
                    propertyValue = "257";
1827
                    throw new Exception();
1828
                }
1829
            }
1830
            else
1831
            {
1832
                // DEVI 56714 daemon centric check
1833
                String majorV = this.getClass().getPackage().getSpecificationVersion();
1834
 
1835
                if ( buildtoolVersion.compareTo( majorV ) != 0 )
1836
                {
1837
                    reportErrorException( "Failure, incompatible build.xml not generated with version " + majorV, 256 );
1838
                }
1839
            }
1840
 
1841
 
1842
            if (extractSource)
1843
            {
1844
                //  Init the metrics gathering process
1845
                metricsBegin();
1846
 
1847
                //  Generate auto.pl or <PackageName>depends.xml file
1848
                genbuild();
1849
 
1850
                //  Active build
1851
                //      Build the target package unless we are simply doing metrics generation
1852
                //
1853
                if ( !benign )
1854
                {
1855
                    jatsBuildPackage();
1856
                }
1857
 
1858
                //  Complete the metrics gathering
1859
                metricsEnd();
1860
            }
1861
 
1862
            //
1863
            //  Process Skipped builds
1864
            //    Create a built.xxx marker for the publish check
1865
            //
1866
            if (skipped)
1867
            {
1868
                jatsSkipPackage();
1869
            }
1870
 
1871
        }
1872
        catch( SecurityException e)
1873
        {
1874
            errorReported = true;
1875
            reportError( "Failure caught SecurityException", 256 );
1876
        }
1877
        catch( IOException e)
1878
        {
1879
            errorReported = true;
1880
            reportError( "Failure caught IOException", 256 );
1881
        }
1882
        catch( Exception e)
1883
        {
1884
            // assume this condition has been reported on
1885
            errorReported = true;
1886
 
1887
            if ( e.getMessage() != null )
1888
            {
1889
                logMsg( "execute caught Exception " + e.getMessage(), WARN );
1890
            }
1891
            else
1892
            {
1893
                logMsg( "execute caught Exception", WARN );
1894
            }
1895
        }
1896
        finally
1897
        {
1898
            try
1899
            {
1900
                if ( daemon != null )
1901
                {
1902
                    // do not write to publish.log
1903
                    throw new IOException();
1904
                }
1905
 
1906
                FileWriter publish = new FileWriter( utilities.catDir(basedir,"publish.log"), true );
1907
                if ( propertyValue.compareTo( "0" ) == 0 )
1908
                {
1909
                    if ( benign )
1910
                    {
1911
                        publish.write( "successfully published " + packageName + " at " + packageFullVersion + ", no action required on this platform" );
1912
                    }
1913
                    else
1914
                    {
1915
                        publish.write( "successfully published " + packageName + " at " + packageFullVersion );
1916
                    }
1917
 
1918
                    publish.write( ls );
1919
                }
1920
                else if ( propertyValue.compareTo( "256" ) == 0 )
1921
                {
1922
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion +  ", internal abt issue" + ls );
1923
                }
1924
                else if ( propertyValue.compareTo( "257" ) == 0 )
1925
                {
1926
                    errorReported = false;
1927
                    publish.write( "previously published " + packageName + " at " + packageFullVersion + ls );
1928
                }
1929
                else if ( propertyValue.compareTo( "261" ) == 0 )
1930
                {
1931
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", missing or bad descpkg file" + ls );
1932
                }
1933
                else if ( propertyValue.compareTo( "262" ) == 0 )
1934
                {
1935
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", couldn't process save_build info" + ls );
1936
                }
1937
                else if ( propertyValue.compareTo( "263" ) == 0 )
1938
                {
1939
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", couldn't write to auto.cfg" + ls );
1940
                }
1941
                else if ( propertyValue.compareTo( "265" ) == 0 )
1942
                {
1943
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", " + cwd + " does not exist" + ls );
1944
                }
1945
                else if ( propertyValue.compareTo( "264" ) == 0 )
1946
                {
1947
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", " + " Could not delete build directory" + ls );
1948
                }
1949
                else if ( propertyValue.compareTo( "267" ) == 0 )
1950
                {
1951
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", " + " Could not assemble package fragments" + ls );
1952
                }
1953
                else
1954
                {
1955
                    // nb jats or ant can presumably return a value 1 to 255
1956
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", jats or ant failed" + ls );
1957
                }
1958
 
1959
                publish.close();
1960
            }
1961
            catch( IOException e )
1962
            {
1963
                if ( daemon == null )
1964
                {
1965
                    reportError( "Failure to write to publish.log", 266 );
1966
                }
1967
            }
1968
            catch( Exception e )
1969
            {
1970
                if ( daemon == null )
1971
                {
1972
                    reportError( "Failure to write to publish.log", 266 );
1973
                }
1974
            }
1975
 
1976
            getProject().setProperty(packageAlias + ".res", propertyValue);
1977
 
1978
            if ( errorReported )
1979
            {
1980
                // designed to prevent subsequent build activity on this build file
1981
                // supply the build failure log file in message with / as file sep
1982
                // takes the form hostname/rtag_id/daemon/logfile
1983
                if ( daemon != null )
1984
                {
1985
                    String message = hostname + "/" + rtagId + "/" + daemon + "/" + logBase + ".log";
1986
                    throw new BuildException( message );
1987
                }
1988
                else
1989
                {
1990
                    throw new BuildException();
1991
                }
1992
            }
1993
 
1994
        }
1995
    }
1996
 
1997
 
1998
    /**
1999
     * Delete a directory and all of its contents
2000
     * Set directories and sub directories writable in case the user has messed with permissions. 
2001
     * This function is called recursively to delete the entire directory tree
2002
     * 
2003
     * Note: Having some issues deleting directories
2004
     *       Try many times. On the second attempt log the files that remained
2005
     * 
2006
     * @param directory The top level directory to delete
2007
     */
2008
    private void deleteDirectory(File directory)
2009
    {
2010
        logMsg("deleteDirectory " + directory.getName(), DEBUG);
2011
 
2012
        int attempts = 0;
2013
        boolean verbose = false;
2014
        while (directory.exists()) {
2015
            attempts++;
2016
 
2017
            // Use Java native method fist
2018
            // The Jats utility is good, but there is some interaction with VirusScanners/Indexing that a bit strange
2019
            //
2020
            if ( (attempts & 1) == 1) {
2021
                deleteDirectoryInternalViaJava(directory, verbose);
2022
            }  else {
2023
                deleteDirectoryInternalViaJats(directory, verbose);
2024
            }
2025
 
2026
            if (!directory.exists()) {
2027
                logMsg("deleteDirectory deleted after " + attempts + " attempts " + directory.getName(), FATAL);
2028
                break;
2029
            }
2030
            verbose = true;
2031
 
2032
            if (attempts > 10)
2033
            {
2034
                logMsg("deleteDirectory give up delete after " + attempts + " attempts " + directory.getName(), FATAL);
2035
                break;
2036
            }
2037
 
2038
            logMsg("deleteDirectory not deleted after " + attempts + " attempts " + directory.getName(), FATAL);
2039
 
2040
//          //
2041
//          //  Debugging code
2042
//          //  Display all handles in the system (windows only)
2043
//          //
2044
//          if(System.getProperty("os.name").startsWith("Windows"))
2045
//          {
2046
//              String[] cmd = {"handle"};
2047
//              Log("deleteDirectory Execute handle.", warn);
2048
//              thread.setCommandline(cmd);
2049
//              try {
2050
//                  thread.execute();
2051
//              } catch (IOException e) {
2052
//                  logMsg("deleteDirectory Did not execute handle: " + e.getMessage(), WARN);
2053
//              }
2054
//          }
2055
 
2056
            //  Wait a short while before attempting to delete the directory again
2057
            //  Rational:
2058
            //      - AntiVirus software may be having a sniff, so let it finish
2059
            //      - Program shut down may take a few seconds
2060
            //      - Because nothing else appears to work
2061
            try {
2062
                logMsg("deleteDirectory sleep before attempt:" + attempts, DEBUG);
2063
                Thread.sleep(10 * 1000L);
2064
            } catch (InterruptedException e) {
2065
                logMsg("deleteDirectory sleep exception: " + e.getMessage(), WARN);
2066
                Thread.currentThread().interrupt();
2067
                break;
2068
            }
2069
 
2070
        }
2071
    }
2072
 
2073
    /**
2074
     * The body of the deleteDirectory operation
2075
     * Used simply to avoid excessive logging.
2076
     * 
2077
     * @param directory The top level directory to delete
2078
     * @param verbose - display files and folders as they are deleted
2079
     */
2080
    private void deleteDirectoryInternalViaJava(File directory, boolean verbose)
2081
    {
2082
        try
2083
        {
2084
            if ( directory.exists() )
2085
            {
2086
                File[] children = directory.listFiles();
2087
                directory.setWritable(true);
2088
                if ( children != null )
2089
                {
2090
                    for ( int child=0; child < children.length; child++ )
2091
                    {
2092
                        if ( children[ child ].isDirectory() )
2093
                        {
2094
                            deleteDirectoryInternalViaJava( children[ child ], verbose );
2095
                        }
2096
                        else
2097
                        {
2098
                            if(verbose)
2099
                            {
2100
                                logMsg("deleteDirectory File:" + children[ child ].getName(), DEBUG);
2101
                            }
2102
                            children[ child ].setWritable(true);
2103
                            children[ child ].delete();
2104
                        }
2105
                    }
2106
                }
2107
                if (verbose)
2108
                {
2109
                    logMsg("deleteDirectory Dir:" + directory.getName(), DEBUG);
2110
                }
2111
                directory.delete();
2112
            }
2113
        }
2114
        catch( SecurityException e )
2115
        {
2116
            // this can be thrown by exists and delete
2117
            logMsg("deleteDirectory caught SecurityException", WARN);
2118
        }
2119
    }
2120
 
2121
 
2122
    /**
2123
     * The body of the deleteDirectory operation done with JATS utility
2124
     * Used simply to avoid excessive logging.
2125
     * 
2126
     * @param directory The top level directory to delete
2127
     * @param verbose - display files and folders as they are deleted
2128
     */
2129
    private void deleteDirectoryInternalViaJats(File directory, boolean verbose)
2130
    {
2131
 
2132
        //  Use jats ebin JatsFileUtil T0 TextMsg DirName to delete the directory tree
2133
        //  Address issues that cannot be solved in java
2134
 
2135
        command.init("jats", "ebin","JatsFileUtil" );
2136
        command.add( verbose, "T9" );
2137
        command.add( !verbose, "T0" );
2138
        command.add( "DeleteDir-" + rtagId );
2139
        command.add(directory.getAbsolutePath());
2140
 
2141
        // Run the command - don't care if it fails
2142
        //  It should not generate an exception
2143
        try {
2144
            runCommand(null);
2145
        } catch (Exception e1) {
2146
            logMsg("deleteDirectory caught Exception", ERROR);
2147
        }
2148
    }
2149
 
2150
    /**
2151
     * Insert a marker into the created package so that the
2152
     * escrow build can detect that the package has been built.
2153
     * 
2154
     * This is used in the following situations:
2155
     * 
2156
     * 1) ANT packages that could be build on multiple machines
2157
     * 2) Restarted build on the same machine
2158
     */
2159
    private void insertEscrowMarker()
2160
    {
2161
        //
2162
        //  Only used in escrow mode
2163
        //
2164
        if ( daemon == null && packageStandard == BuildStandards.ANT)
2165
        {
2166
            //
2167
            //  ANT builds are performed on a machine type basis
2168
            //  Create a 'MachClass' based marker
2169
            //
2170
            String destination = utilities.catDir(dpkgArchive, packageName, packageFullVersion);
2171
            String filename = "built." + gbeMachClass; 
2172
 
2173
            try
2174
            {
2175
                new File(destination).mkdirs(); 
2176
                new File(destination, filename).createNewFile();
2177
            } 
2178
            catch (IOException ioe)
2179
            {
2180
                logMsg("Cannot insert Escrow Marker", FATAL);
2181
            }
2182
        }
2183
    }
2184
 
2185
 
2186
    /**
2187
     * Check for the existence of an Escrow marker
2188
     * Used so that the build system can detect if this
2189
     * package has already been built.
2190
     * 
2191
     * Can occur under two conditions
2192
     * 
2193
     * 1) ANT packages that can be built on multiple machines
2194
     * 2) ReStarted build on same machine 
2195
     *  
2196
     * Assumption: Only called in Escrow Mode 
2197
     * 
2198
     * @return TRUE  - Marker Detected
2199
     *         FALSE - Marker not Detected
2200
     */
2201
    private boolean checkEscrowMarker() throws Exception
2202
    {
2203
        String destination = utilities.catDir(dpkgArchive, packageName, packageFullVersion);
2204
        String filename = "built." + (generic ? "generic" : hostname);
2205
 
2206
        if (new File( destination, filename ).exists())
2207
        {
2208
            return true;
2209
        }
2210
 
2211
        if ( packageStandard == BuildStandards.ANT)
2212
        {
2213
            //
2214
            //  ANT builds are performed on a machine type basis
2215
            //  Check for a 'MachClass' based marker
2216
            //
2217
            filename = "built." + gbeMachClass; 
2218
            if (new File( destination, filename).exists())
2219
            {
2220
                return true;
2221
            }
2222
        }
2223
        return false;
2224
    }
2225
 
2226
    //---------------------------------------------------------------------------
2227
    //    Extend the <abt> task with several new elements
2228
    //
2229
    //        <depend package_alias="${debian_dpkg.cots}"/>
2230
    //        <buildinfo gbe_machtype="solaris10_x86" method="jats" arg="debug"/>
2231
    //
2232
    public Depend createDepend()
2233
    {
2234
        Depend depend = new Depend();
2235
        dependCollection.add(depend);
2236
        return depend;
2237
    }
2238
 
2239
    public BuildInfo createBuildInfo()
2240
    {
2241
        BuildInfo buildInfo = new BuildInfo();
2242
        buildInfoCollection.add(buildInfo);
2243
        return buildInfo;
2244
    }
2245
 
2246
}