Subversion Repositories DevTools

Rev

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