Subversion Repositories DevTools

Rev

Rev 7186 | Rev 7341 | 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
 
576
        if (buildStandard == BuildStandards.JATS )
577
        {
578
            command.add( "build", "buildinfo" );
579
        }
580
        else if (buildStandard == BuildStandards.ANT )
581
        {
582
            command.add( "etool", "antBuildInfo" );
583
            command.add( "-java=" + javaVersion.getJavaVersion() );
584
 
585
        }
586
        command.add( "-buildinfo=" + buildInfo.getAbsolutePath() );
587
 
588
        runCommand( "Failure to generate BuildInfo" );
589
    }
590
 
6914 dpurdie 591
    /**
592
     * Generate the build dependency data file.
593
     * 
594
     * @exception Exception
595
     */
596
    private void genbuild() throws Exception
597
    {
598
 
599
        //
600
        //  Create build files with updated dependency information
601
        //  In escrow mode : No new dependency information
602
        //  In daemon mode :
603
        //      Ripple     : New dependency information
604
        //      Verify     : Existing dependency information
605
        //
606
        //  In all modes  : ANT builds need an auto.xml
607
        //
608
        //  In order to create auto.xml/auto.pl with package dependencies need to
609
        //  create file with dependency data (auto.cfg) only because its
610
        //  needed by "jats_rewrite"
611
        //
612
        File cfg = null;
613
        boolean  createFile = false;
614
        if ( daemon != null )
615
        {
616
            createFile = true;
617
 
618
            // always generate auto.cfg
619
            cfg = new File( utilities.catDir(cwd, "auto.cfg"));
620
            cfg.createNewFile();
621
 
622
            if ( !cfg.exists() || !cfg.canWrite() )
623
            {
624
                reportErrorException( "Failed to open auto.cfg", 263 );
625
            }
626
 
627
            try
628
            {
629
                FileWriter cfgfw = new FileWriter(cfg);
630
                printPackage( cfgfw, packageName + " " + packageFullVersion );
631
 
632
                // provide releasemanager.projectname=<name[0]> and releasemanager.releasename=<name[1]>
633
                String[] name = release.split( " > ", 2 );
634
 
635
                if ( name.length == 2 )
636
                {
637
                    printPackage( cfgfw, "releasemanager.projectname=" + name[0] );
638
                    printPackage( cfgfw, "releasemanager.releasename=" + name[1] );
639
                }
640
 
641
                for (Iterator<Depend> it=dependCollection.iterator(); it.hasNext(); )
642
                {
643
                    Depend depend = it.next();
644
                    printPackage( cfgfw, depend.getPackage_Alias() );
645
                }
646
 
647
                cfgfw.close();
648
            }
649
            catch( IOException e )
650
            {
651
                reportErrorException( "Failure to write to auto.cfg", 263 );
652
            }
653
        }
654
        else
655
            if ( packageStandard == BuildStandards.ANT )
656
            {
657
                // Have not created an auto.xml with updated dependencies
658
                // Ant build still would like an auto.xml file
659
                //
660
                // ie packages with a line <import file="auto.xml" optional="true"/> are fine
661
                //    but in escrow and rebuild we still need an auto.xml to be kind
662
                //
663
                createFile = true;
664
            }
665
 
666
        //
667
        //  Create the auto.pl/auto.xml file if required
668
        //
669
        if ( createFile )
670
        {
671
            command.init("jats");
672
            addCommandLocate();
673
            command.add( "etool", "jats_rewrite" );
674
 
675
            if ( packageStandard == BuildStandards.ANT )
676
            {
677
                command.add( "-infile=" + packageName + "depends.xml" );
678
                command.add( "-outfile=auto.xml" );
679
            }
680
            else
681
            {
682
                command.add( "-infile=build.pl" );
683
                command.add( "-outfile=auto.pl" );
684
            }
685
 
686
            if ( cfg != null && daemon != null)
687
            {
688
                command.add( "-config=" + cfg.getAbsolutePath() );
689
 
690
                //  Validate the Release Manager versions against those in the build files
691
                //  Only do this in daemon mode for:
692
                //      We are rebuilding the package
693
                //          This is detected as: Not have VCS interaction AND is not a test Build
694
                boolean isaRebuild = doesNotRequireSourceControlInteraction != null && testBuildInstruction == 0;
695
                command.add(isaRebuild, "-validate");
696
 
697
                //  Ensure that we don't have excessive packages in the Metadata
698
                //  Only do this in daemon mode, for 'new' or 'test' builds
699
                //  Don't do for:
700
                //      Escrow builds - they can't fix it
701
                //      Ripple builds - it will break a lot of stuff
702
                //      Rebuilds      - it will break stuff
703
                // Do for:
704
                //      New Versions  - User can fix it
705
                //      Test Builds   - User can fix it
706
                boolean isaTestBuild = doesNotRequireSourceControlInteraction != null && testBuildInstruction > 0;
707
                boolean isaNewVersion = !isaRipple && !isaRebuild && !isaTestBuild;
708
                command.add( isaNewVersion || isaTestBuild, "-errors");
709
 
710
            }
711
            else
712
            {
713
                command.add( "-noconfig");
714
            }
715
 
716
            if ( oldExtension != null )
717
            {
718
                command.add( "-oldproject", oldExtension );
719
                command.add( "-newproject", newExtension );
720
            }
721
 
722
            runCommand( "Failure to generate build dependency information. Potentially caused by a mismatch between build files and Release Manager database" );
723
        }
724
    }
725
 
726
    /**
727
     * Build the package
728
     * 
729
     * @exception Exception
730
     */
731
    private void jatsBuildPackage() throws Exception
732
    {
733
        //--------------------------------------------------------------------------
734
        //  Wait for package replication and caching
735
        //      If there is a GBE_DPKG_REPLICA, then there may be a delay between
736
        //      a package being built and the package being available on the replica
737
        //      We need to wait for the required packages to replicate
738
        //
739
        //      If there is a GBE_DPKG_CACHE, then we need to cache the package
740
        //      into the local store - mostly for windows as it seriously speeds
741
        //      up the builds.
742
 
743
        Boolean hasReplica = System.getenv("GBE_DPKG_REPLICA") != null;
744
        Boolean hasCache   = System.getenv("GBE_DPKG_CACHE") != null;
745
 
746
        if (daemon != null && (hasReplica || hasCache)  && !dependCollection.isEmpty())
747
        {
748
            /*
749
             * Limit the command line length provided to the following utility
750
             * Very very long dependency lists may over fill the command line
751
             */
752
            Iterator<Depend> it=dependCollection.iterator();
753
            while( it.hasNext() )
754
            {
755
 
756
                command.init( "jats", "etool", "cache_dpkg");
757
                command.add( hasReplica, "-wait" );
758
 
759
                // ANT builds require the package to be cached
760
                // JATS does not - if its needed it will be done later
761
                command.add( buildStandard != BuildStandards.ANT , "-nocache");
762
 
763
                // Add PackageName/PackageVersion
764
                for (int maxArgs = 0; maxArgs < 10 && it.hasNext(); maxArgs++ )
765
                {
766
                    Depend depend = it.next();
767
                    command.add(depend.getPackageNameVersion());
768
                }
769
 
770
                // Run the command - don't care if it fails
771
                runCommand( null );
772
            }
773
        }
774
 
775
        //--------------------------------------------------------------------------
776
        //  Build Phase
777
        //  Create build environment
778
 
779
        command.init( "jats" );
780
        command.add( gbebuildfilter != null ,"-buildfilter", gbebuildfilter);
781
        addCommandLocate();
782
 
783
        if ( buildStandard == BuildStandards.ANT )
784
        {
785
            command.add( "abt" );
786
            command.add( "-java=" + javaVersion.getJavaVersion() );
787
            command.add( "-buildfile=" + packageName + ".xml" );
788
            command.add( "build" );
789
        }
790
        else
791
        {
792
            command.add( "build", "--package" );
793
 
794
            // Daemon: Sanity check the building of Generic packages
795
            // Escrow: Allow this error - for backward compatibility
796
            if ( daemon != null )
797
            {
798
                if (generic) 
799
                    command.add( "-generic" );
800
                else
801
                    command.add( "-nogeneric" );
802
            }
803
 
804
            // Cache packages into a machine-local archive
805
            //  Will only do this if the package is really built
806
            //
807
            command.add(hasCache, "--cache" );
808
        }
809
 
810
        runCommand( "Failure to set up sandbox" );
811
 
812
        //--------------------------------------------------------------------------
813
        //  Make Package phase
814
        //  Create the package (make)
815
 
816
        command.init("jats" );
817
        command.add( gbebuildfilter != null, "-buildfilter", gbebuildfilter);
818
        addCommandLocate();
819
 
820
        if ( buildStandard == BuildStandards.ANT )
821
        {
822
            command.add( "abt" );
823
            command.add( "-java=" + javaVersion.getJavaVersion() );
824
            command.add( "-buildfile=" + packageName + ".xml" );
825
            command.add( "make_package" );
826
        }
827
        else
828
        {
829
            command.add( "make", "NODEPEND=1" );
830
 
831
            if ( compileTarget == CompileTargets.PROD )
832
            {
833
                command.add( "prod", "package_prod" );
834
            }
835
            else if ( compileTarget == CompileTargets.DEBUG )
836
            {
837
                command.add( "debug", "package_debug" );
838
            }
839
            else
840
            {
841
                command.add( "all" );
842
            }
843
        }
844
 
845
        runCommand( "Failure to generate derived files" );
846
 
847
 
848
        //--------------------------------------------------------------------------
849
        //  Unit tests phase
850
        //  Run autonomous unit tests
851
 
852
        if ( unittests != null )
853
        {
854
            command.init("jats" );
855
            command.add( gbebuildfilter != null, "-buildfilter", gbebuildfilter);
856
            addCommandLocate();
857
 
858
            if ( buildStandard == BuildStandards.ANT )
859
            {
860
                command.add( "abt" );
861
                command.add( "-java=" + javaVersion.getJavaVersion() );
862
                command.add( "-buildfile=" + packageName + ".xml" );
863
                command.add( "run_tests" );
864
            }
865
            else
866
            {
867
                command.add( "make" );
868
                if ( compileTarget == CompileTargets.PROD )
869
                {
870
                    command.add( "run_unit_tests_prod" );
871
                }
872
                else if ( compileTarget == CompileTargets.DEBUG )
873
                {
874
                    command.add( "run_unit_tests_debug" );
875
                }
876
                else
877
                {
878
                    command.add( "run_unit_tests" );
879
                }
880
            }
881
 
882
            runCommand( "Failure to run unit tests" );
883
        }
884
 
885
        //--------------------------------------------------------------------------
886
        //  create_dpkg phase
887
        //  Publish the package to dpkg_archive
888
        //
889
 
890
        command.init("jats" );
891
        addCommandLocate();
892
        command.add( "create_dpkg", "-m" );
893
        command.add( packageTarBall, "-tarmode");
894
        command.add( generic, "-generic" );
895
        command.add( "-pname", packageName );
896
        command.add( "-pversion", packageFullVersion );
897
 
898
        runCommand( "Failure to publish to archive" );
899
 
900
        insertEscrowMarker();
901
    }
902
 
903
    /** Skip Build an ANT Package 
904
     *  Only used on ANT based builds in which it has been determined that another machine
905
     *  is performing the build.
906
     *  
907
     *  Insert required marker files to indicate that the build has occurred
908
     *  Perform this using JATS commands to ensure correct creation of the marker files
909
     *  Basically, a dummy publish phase
910
     *  
911
     *  Note: Skip Builds cannot be generic
912
     *  
913
     */
914
    private void jatsSkipPackage() throws Exception
915
    {
916
        command.init( "jats" );
917
        command.add( "-here" );
918
        command.add( "create_dpkg", "-m" );
919
        command.add( packageTarBall, "-tarmode");
920
        command.add( "-noBuild" );
921
        command.add( "-pname", packageName );
922
        command.add( "-pversion", packageFullVersion );
923
 
924
        runCommand( "Failure to (skip)publish to archive" );
925
    }
926
 
927
    /**   Check if the package has been Published on all the required machines
928
     *    If its a 'generic' package then a tag of built.generic will have been placed in the package
929
     *    Otherwise each build machine will place a built.<MachName> file in the package when
930
     *    its build is completed successfully.
931
     *  
932
     *    If we don't have a complete set of 'built' files, then the package failed to build
933
     *    on one or more platforms. The assumption is that the build failure has been reported
934
     *    by the build daemon.
935
     *  
936
     *    All we know is which MachTypes we build for. This needs to be expanded into
937
     *    a list of MachineNames. Thus a build-set with multiple machines of the same MachType
938
     *    can indicate build failures.
939
     */
940
    private void puplishPackage() throws Exception
941
    {  
942
        //  If the package fragments are being delivered as tarballs then they needs to be reassembled
943
        if (packageTarBall)
944
        {
945
            fullyPublished = assemblePackage();
946
        }
947
 
948
        if (fullyPublished)
949
        {
950
            if ( generic )
951
            {
952
                //  Generic - only one marker file
953
                fullyPublished = checkPublished( dpkgArchive, "generic" );
954
            }
955
            else
956
            {
957
                //  Multi machine package
958
                //  Scan required target machines artifacts
959
                //  Expand from MachType to one or more MachName's
960
                scanBuilds:
961
                    for (Iterator<BuildInfo> ip=buildInfoCollection.iterator(); ip.hasNext(); )
962
                    {
963
                        BuildInfo buildInfo = ip.next();
964
                        for (Iterator<Machine> it=abtData.machineCollection.iterator(); it.hasNext(); )
965
                        {
966
                            Machine ma = it.next();
967
                            if (ma.getMachtype().compareTo(buildInfo.getMachtype()) == 0 )
968
                            {
969
                                fullyPublished = checkPublished( dpkgArchive, ma.getName() );
970
                                if ( !fullyPublished )
971
                                {
972
                                    //  Break out of both loops
973
                                    //  Once we have seen an error we need to retain it.
974
                                    break scanBuilds;
975
                                }
976
                            }
977
                        }
978
                    }
979
            }
980
        }
981
 
982
        //  Detect problem with zero length descpkg file
983
        //      May be caused by write clash from multiple machines
984
        //      Don't know
985
        //
986
        //  Not forcing NFS flush as this will have been done in the previous step
987
        //
988
        if ( fullyPublished )
989
        {
990
            String destination = utilities.catDir(dpkgArchive, packageName, packageFullVersion, "descpkg");
991
            File flag = new File( destination);
992
 
993
            //  File Must
994
            //      Exist
995
            //      Be a File
996
            //      Have a length. Problem appears to be zero length file
997
            //
998
            boolean found = false;
999
            logMsg( "published. Descpkg Sanity Test: " + flag.getPath(), DEBUG );
1000
            if (!flag.exists() ) {
1001
                reportErrorException( "No descpkg file. Package may not build with current build filters", 261 );
1002
 
1003
            } else if ( !flag.isFile()) {
1004
                reportErrorException( "Descpkg Sanity Test: Is not a file", 261 );
1005
 
1006
            } else if ( flag.length() <= 0 ) {
1007
                reportErrorException( "Descpkg Sanity Test: Zero length File", 261 );
1008
 
1009
            } else {
1010
                logMsg( "published. Descpkg Sanity Test: Passed", INFO );
1011
                found = true;
1012
            }
1013
 
1014
            if (!found) {
1015
                fullyPublished = false;
1016
            }
1017
        }
1018
 
1019
        if ( fullyPublished && daemon != null )
1020
        {
1021
            if ( doesNotRequireSourceControlInteraction == null )
1022
            {
1023
                //
1024
                //  Save modified build files
1025
                //  Label the resultant files
1026
                //  Create a command of the form:
1027
                //      jats etool jats_vcssave_build
1028
                //          -infile     auto.xml/auto.pl
1029
                //          -outfile    xxxdepends.xml/build.pl
1030
                //          -pname      package_name
1031
                //          -pversion   package_version
1032
                //          -infofile   path_to_info_file
1033
                //          -wiplabel   Existing WIP label (optional)
1034
                //          -baselabel  View label
1035
 
1036
                logMsg("publish save build files", WARN);
1037
 
1038
                File saveinfo = new File(utilities.catDir(basedir, rtagId + "abtinfo.txt"));
1039
                if ( saveinfo.exists() )
1040
                {
1041
                    saveinfo.delete();
1042
                }
1043
 
1044
                command.init("jats" );
1045
                addCommandLocate();
1046
                command.add( "etool", "jats_vcssave_build" );
1047
 
1048
                if ( packageStandard == BuildStandards.ANT )
1049
                {
1050
                    command.add( "-infile", "auto.xml" );
1051
                    command.add( "-outfile", packageName + "depends.xml" );
1052
                }
1053
                else
1054
                {
1055
                    command.add( "-infile", "auto.pl" );
1056
                    command.add( "-outfile", "build.pl" );
1057
                }
1058
 
1059
                command.add( "-pname", packageName );
1060
                command.add( "-pversion", packageFullVersion );
1061
                command.add( directChange != null, "-isawip" );
1062
                command.add( "-infofile", saveinfo.getAbsolutePath() );
1063
                command.add( "-baselabel", packageVcsTag );
1064
 
1065
                if ( oldExtension != null && newExtension != null && packageExtension.compareTo( newExtension ) == 0 )
1066
                {
1067
                    // only branch build.pl where its extension is being migrated
1068
                    command.add( "-branch", "project_migration_branch", "-newbranch" );
1069
                }
1070
 
1071
                runCommand( "Failure to save build file changes into source control" );
1072
 
1073
                //
1074
                //  The command creates an info file(saveinfo) to pass information back
1075
                //  to the caller (me). This is a 'properties' file
1076
                //  Need to extract the following information
1077
                //    newVcsTag - which is held as VCS.tag
1078
                //
1079
                logMsg("publish read info file", INFO);
1080
 
1081
                Properties properties = new Properties();
1082
                try
1083
                {
1084
                    properties.load(new FileInputStream(saveinfo));
1085
                }
1086
                catch (IOException e)
1087
                {
1088
                    reportErrorException( "Failed to open save_build info file", 262 );
1089
                }
1090
 
1091
                newVcsTag = properties.getProperty("VCS.tag" );
1092
                if ( newVcsTag == null )
1093
                {
1094
                    reportErrorException( "Save_build info. Missing property:VCS.tag", 262 );
1095
                }
1096
                logMsg("publish read info file. Label:" + newVcsTag , INFO);
1097
            }
1098
        }
1099
    }
1100
 
1101
    /** Re-assemble package fragments into a package within the target archive
1102
     *  Used only in non-escrow mode
1103
     *  
1104
     *  This method will invoke a command on the target package server
1105
     *  This is done to overcome several issues:
1106
     *  1) Atomic merging of package fragments
1107
     *  2) Very long times seen in transferring a package with a large number of files
1108
     *     over a non-local network. It may take a second to create a file. For a 3000 file
1109
     *     package we were seeing times of about an hour simply to transfer the files from AWS(Sydney)
1110
     *     to the package server in Perth.
1111
     *     
1112
     *  The down side is that we need to set up an SSH session to the package server
1113
     *  We need:
1114
     *  1) Network name of the machine
1115
     *  2) User on the machine to do the work
1116
     *  3) Credentials for that user
1117
     *  
1118
     *   The existence of these items will have been performed by the daemon at startup
1119
     *   This simplifies the process of reporting errors
1120
     * 
1121
     * @return  true - reassemble occurred correctly
1122
     * @throws Exception 
1123
     */
1124
    private boolean assemblePackage() throws Exception 
1125
    {
1126
        if ( daemon == null )
1127
        {
1128
            // Not to be used in escrow
1129
            return false;
1130
        }
1131
        /*
1132
         *  Setup the credentials
1133
         *  The format 'should' have been checked as the daemon started
1134
         *  The link should have been authenticated before the build was started,
1135
         *  but it may have gone down since.
1136
         */
1137
        LogOutput logger = new LogOutput()
1138
        {
1139
            @Override
1140
            public void data(String message) {
1141
                logMsg( message, INFO );
1142
            }
1143
 
1144
            @Override
1145
            public void info(String message) {
1146
                logMsg( message, INFO );
1147
            }
1148
 
1149
            @Override
1150
            public void fatal(String message) {
1151
                logMsg( message, FATAL);
1152
            }
1153
        };
1154
 
1155
        ElapseTime et = new ElapseTime();
1156
        RemoteExecution mRemoteExecution = new RemoteExecution(logger);
1157
 
1158
        /*
1159
         * Generate the command string
1160
         * Its being executed over an ssh session so we need to:
1161
         *  1) Set up the required environment
1162
         *  2) Set the location of GBE_DPKG - more for testing
1163
         */
1164
        command.init();
1165
        command.add("sudo","-n", "-u", "buildadm", "/home/releasem/sbin/jatsTool", "assemble_dpkg");
1166
        command.add(useTestArchive, "-testArchive");
1167
        command.add("'-pname=" + packageName + "'");
1168
        command.add("'-pversion=" + packageFullVersion + "'");
1169
 
1170
        String cmd = command.toString();
1171
        logMsg( "assemblePackage. Command:" + cmd, WARN );
1172
        int retCode = mRemoteExecution.execute(cmd);
1173
        logMsg( "command returned: "+ retCode + ", elapsed time (S): " + et.toString(), WARN);
1174
        if (retCode != 0)
1175
        {
1176
            reportErrorException( "Package reassembly error", 267 );
1177
        }
1178
        return 0 == retCode;
1179
    }
1180
 
1181
    /** determineBuildStandard
1182
     *  Process the current target and set up
1183
     *      buildStandard
1184
     *          compileTarget
1185
     *          javaVersion
1186
     *          
1187
     *      packageStandard
1188
     *          The package standard is used to determine the mode used to process the auto.cfg file
1189
     *          
1190
     */
1191
    private void determineBuildStandard() throws Exception 
1192
    {
1193
        // Scan the platform collection looking for an entry that matches the current machine
1194
        //
1195
        // Just wanting to set up
1196
        //    buildStandard and one of
1197
        //        compileTarget
1198
        //    OR  javaVersion
1199
 
1200
        for (Iterator<BuildInfo> it = buildInfoCollection.iterator(); it.hasNext();)
1201
        {
1202
            BuildInfo buildInfo = it.next();
1203
            String method = buildInfo.getMethod();
1204
            String arg = buildInfo.getArg();            
1205
 
1206
            //  Capture the first non-null build standard as the packageStandard
1207
            if ( packageStandard == BuildStandards.NONE)
1208
            {
1209
                if (method.equals("jats"))
1210
                {
1211
                    packageStandard = BuildStandards.JATS;
1212
                }
1213
                else if (method.equals("ant"))
1214
                {
1215
                    packageStandard = BuildStandards.ANT;
1216
                }
1217
            }
1218
 
1219
            //  Capture the build standard for the current machine type
1220
            if (gbeMachtype.compareTo(buildInfo.getMachtype()) == 0)
1221
            {
1222
                if (method.equals("jats"))
1223
                {
1224
                    buildStandard = BuildStandards.JATS;
1225
                    if (arg.compareTo("production") == 0)
1226
                    {
1227
                        compileTarget = CompileTargets.PROD;
1228
 
1229
                    }
1230
                    else if (arg.compareTo("debug") == 0)
1231
                    {
1232
                        compileTarget = CompileTargets.DEBUG;
1233
 
1234
                    }
1235
                    else if (arg.compareTo("all") == 0)
1236
                    {
1237
                        compileTarget = CompileTargets.ALL;
1238
 
1239
                    }
1240
                    else
1241
                    {
1242
                        reportErrorException("Failure, unsupported Jats build environment " + arg + ", internal ABT problem", 256);
1243
                    }   
1244
                }
1245
                else if (method.equals("ant"))
1246
                {
1247
                    buildStandard = BuildStandards.ANT;
1248
 
1249
                    //    Handle version of 'none' and of the form 'n.n'
1250
                    //    Anything else is an error
1251
 
1252
                    javaVersion = new JavaVersions(arg);
1253
                    if ( javaVersion.isBad())
1254
                    {
1255
                        reportErrorException("Failure, unsupported Ant build environment " + arg + ", internal ABT problem", 256);
1256
                    }
1257
                }
1258
 
1259
                else if (method.equals("none"))
1260
                {
1261
                    buildStandard = BuildStandards.NONE;
1262
                }
1263
                else
1264
                {
1265
                    reportErrorException("Failure, unsupported build method " + method + ", internal ABT problem", 256);    
1266
                }
1267
            }
1268
        }
1269
 
1270
        //
1271
        //    Log the build method and arguments
1272
        //
1273
        logMsg("execute packageStandard: ", packageStandard.getBuildStandard());
1274
        logMsg("execute buildStandard: ", buildStandard.getBuildStandard());
1275
        if (buildStandard == BuildStandards.ANT )
1276
        {
1277
            logMsg("execute javaVersion: ", javaVersion.getJavaVersion());    
1278
        }
1279
        else if (buildStandard == BuildStandards.JATS )
1280
        {
1281
            logMsg("execute compileTarget: ", compileTarget.getCompileTarget());    
1282
        }
1283
 
1284
 
1285
        //  Daemon Mode Only
1286
        //  If we have an ANT Build then we may have an additional problem.
1287
        //  If there is more than one machine of the same 'Machine Class' in the buildset, then
1288
        //  we need to limit the build to just one of them.
1289
        //  In Escrow this is not an issue as the builds are done serially
1290
        //
1291
        //  The rule is:
1292
        //    If there is only one machine in the class - then use it
1293
        //    If there are multiple machines of the same class - then use the first one that has JAVA in its build filter
1294
        //    If none have JAVA in the build filter, then use the first one in the list
1295
        // Supplementary Rules:
1296
        //    If a machine does no have a buildfilter, then assume that it can build everything
1297
        // 
1298
        // Rule Simplification:
1299
        //    If this machine is building ANT, then exclude ourself from the build if
1300
        //    another machine satisfies the criteria. ie: another machine will determine that
1301
        //    it will build the ANT component.
1302
        //
1303
        if (buildStandard == BuildStandards.ANT && daemon != null)
1304
        {
1305
            int classCount = 0;
1306
            Machine firstWithJava = null;
1307
            Machine firstInMachClass = null;
1308
 
1309
            for (Iterator<Machine> it = abtData.machineCollection.iterator(); it.hasNext();)
1310
            {
1311
                Machine ma = it.next();
1312
                if (ma.getMachclass().equals(mMachine.getMachclass()) )
1313
                {
1314
                    classCount++;
1315
 
1316
                    if (firstInMachClass == null)
1317
                        firstInMachClass = ma;
1318
 
1319
                    if (firstWithJava == null)
1320
                    {
1321
                        String buildFilter = ma.getBuildfilter();
1322
                        if (buildFilter != null)
1323
                        {
1324
                            buildFilter = "," + buildFilter.replace(" ", ",") + ",";
1325
                        }
1326
 
1327
                        if (buildFilter == null || buildFilter.contains(",JAVA,"))
1328
                        {
1329
                            firstWithJava = ma;
1330
                        }
1331
                    }
1332
                }
1333
            }
1334
 
1335
            // If none have 'JAVA', then used the first machine in the nominated class
1336
            if (firstWithJava == null)
1337
            {
1338
                firstWithJava = firstInMachClass;
1339
            }
1340
 
1341
 
1342
            //
1343
            //  Apply the rule described above.
1344
            //  Really only need to disqualify ourselves iff there is another machine that will do the build
1345
            //
1346
            if ((classCount > 1) && (firstWithJava != null) && (mMachine != firstWithJava))
1347
            {
1348
                javaVersion = JavaVersions.SKIP;
1349
                logMsg("execute determineBuildStandard: Exclude myself from ANT Build", INFO);
1350
            }
1351
        }
1352
    }
1353
 
1354
 
1355
    /** execute
1356
     *  The Ant Task entry point. This is invoked to perform the targets action
1357
     *      Display the start and end time of the action
1358
     */
1359
    @Override
1360
    public void execute()
1361
    {
1362
        ElapseTime et = new ElapseTime();
1363
 
1364
        //  Setup enough information to enable logging
1365
        project = getProject();
1366
        target = getOwningTarget();
1367
        daemon = project.getProperty("abt_daemon");
1368
        rtagId = project.getProperty("abt_rtag_id");
1369
        release = project.getProperty("abt_release");
1370
 
1371
        logMsg( "execute start: " + ElapseTime.getTimeStamp(), WARN );
1372
        if ( daemon != null ) {
1373
            logMsg("execute daemon: yes", INFO);
1374
        }
1375
 
1376
        try {
1377
            executeAbtTask();    
1378
        }
1379
        finally         {
1380
            logMsg( "execute complete: " + ElapseTime.getTimeStamp(), INFO );
1381
            logMsg( "execute elapsed time (S): " + et.toString(), WARN);
1382
        }
1383
    }
1384
 
1385
    /** executeAbtTask
1386
     *  Body of the ABT execution task
1387
     *  Factored out so that a time stamp can be added to the log
1388
     */
1389
    private void executeAbtTask()
1390
    {
1391
        boolean errorReported = false;
1392
        boolean benign = false;
1393
        boolean skipped = false;
1394
 
1395
        try
1396
        {
1397
            // required by the Execute API on non win32 platforms, don't ask because I don't know
1398
            project.setProperty("ant.home", System.getenv("ANT_HOME"));
1399
 
1400
            // Setup the base name of the output log file
1401
            // Need to do before we report errors
1402
            if ( daemon != null )
1403
            {
1404
                //  Use the packages name and version
1405
                packageName = project.getProperty("abt_package_name");
1406
                logMsg("execute packageName: ", packageName);
1407
 
1408
                packageFullVersion = project.getProperty("abt_package_version");
1409
                logMsg("execute packageFullVersion: ", packageFullVersion);
1410
 
1411
                logBase = packageName + "_" +  packageFullVersion;
1412
            }
1413
            else
1414
            {
1415
                // Use the current target - which will be the packages name and version
1416
                logBase = target.getName();
1417
            }
1418
 
1419
            // Check the current hostname
1420
            //    Needed early as its used in error reporting
1421
            //    JATS should ensure that this value is set
1422
            // Daemon Mode:
1423
            //    When sending emails
1424
            //    Identify the target machine parameters
1425
            // Escrow Mode:
1426
            //    Determine escrow build components
1427
            //    
1428
            if (hostname == null) {
1429
                hostname = "unknown";
1430
                reportErrorException( "GBE_HOSTNAME environment variable not set", 256 );
1431
            }
1432
 
1433
            // early target related
1434
            packageAlias = target.getName();
1435
            packageVcsTag = project.getProperty(packageAlias + "packagevcstag");
1436
            logMsg("execute packageVcsTag: ", packageVcsTag);
1437
 
1438
            if ( packageVcsTag == null )
1439
            {
1440
                // this abt task has no properties, by design
1441
                // future use to estimate build completion time
1442
                logMsg("execute packageAlias: " + packageAlias, INFO);
1443
                return;
1444
            }
1445
 
1446
            logMsg("execute packageAlias: " + packageAlias, WARN);
1447
 
1448
            // ant built in
1449
            basedir = project.getProperty("basedir");
1450
            logMsg("execute basedir: ", basedir);
1451
 
1452
            // global
1453
 
1454
            if ( gbeMachtype == null ) {
1455
                reportErrorException( "GBE_MACHTYPE environment variable not set", 256 );
1456
            }
1457
 
1458
            if (dpkgArchive == null) {
1459
                reportErrorException( "GBE_DPKG environment variable not set", 256 );
1460
            }
1461
 
1462
            //  Locate ABTDATA
1463
            //  This will be referenced by a known ID
1464
            abtData = (ABTData) project.getReference("global-abt-data");
1465
            if (abtData == null) {
1466
                reportErrorException( "ABTData Task not found", 256 );
1467
            }
1468
 
1469
            if ( daemon != null )
1470
            {
1471
 
1472
                mailServer = project.getProperty("abt_mail_server");
1473
                if ( mailServer == null )
1474
                {
1475
                    reportErrorException( "Missing ANT property: abt_mail_server", 256 );
1476
                }
1477
                logMsg("execute mailServer: ", mailServer);
1478
 
1479
                mailSender = project.getProperty( "abt_mail_sender" );
1480
                if ( mailSender == null )
1481
                {
1482
                    reportErrorException( "Missing ANT property: abt_mail_sender", 256 );
1483
                }
1484
                logMsg("execute mailSender: ", mailSender);
1485
 
1486
                for (Iterator<Owner> it=abtData.ownerCollection.iterator(); it.hasNext(); )
1487
                {
1488
                    Owner owner = it.next();
1489
                    owners.append(owner.getEmail());
1490
                    logMsg("execute owner: ", owner.getEmail());
1491
                }
1492
                logMsg("execute owners: ", owners.toString());
1493
            }
1494
 
1495
            if ( daemon == null)
1496
            {
1497
                // Locate any entry for my machType and use it to convert into machClass
1498
                // In escrow the hostName cannot be used.
1499
                //    
1500
                for (Iterator<Machine> it=abtData.machineCollection.iterator(); it.hasNext(); )
1501
                {
1502
                    Machine ma = it.next();
1503
                    if (ma.getMachtype().compareTo(gbeMachtype) == 0 )
1504
                    {
1505
                        gbeMachClass = ma.getMachclass();
1506
                        break;
1507
                    }
1508
                }
1509
 
1510
                if (gbeMachClass == null)
1511
                {
1512
                    reportErrorException( "No MachClass mapping for " + gbeMachtype, 256 );
1513
                }
1514
                logMsg("execute gbeMachClass: ", gbeMachClass);
1515
            }
1516
 
1517
            // project related
1518
            // Some data has already been collected. Just log it.
1519
            logMsg("execute rtagId: ", rtagId);
1520
            logMsg("execute release: ", release);
1521
 
1522
            packageVersionID = project.getProperty("abt_package_version_id");
1523
            if (packageVersionID != null)
1524
            {
1525
                logMsg("execute packageVersionID: ", packageVersionID); 
1526
            }
1527
 
1528
            buildtoolVersion = project.getProperty("abt_buildtool_version");
1529
            logMsg("execute buildtoolVersion: ", buildtoolVersion);
1530
 
1531
            family = project.getProperty("abt_family");
1532
            logMsg("execute family: ", family);
1533
 
1534
            oldExtension = project.getProperty("abt_old_extension");
1535
            logMsg("execute oldExtension: ", oldExtension);
1536
 
1537
            newExtension = project.getProperty("abt_new_extension");
1538
            logMsg("execute newExtension: ", newExtension);
1539
 
1540
            {
1541
                 String prop = project.getProperty("abt_test_build_instruction");
1542
                 logMsg("execute testBuildInstruction: ", prop);
1543
                 testBuildInstruction = 0;
1544
                 if ( prop != null)
1545
                 {
1546
                     testBuildInstruction = Integer.parseInt(prop);
1547
                 }
1548
            }
1549
 
1550
            {
1551
                String prop = project.getProperty("abt_is_ripple");
1552
                logMsg("execute isRipple: ", prop);
1553
                isaRipple = ( prop != null && Integer.parseInt(prop) > 0);
1554
            }
1555
 
1556
 
1557
            if ( project.getProperty("abt_packagetarball") != null ) {
1558
                packageTarBall = true;
1559
                logMsg("execute packageTarBall: yes", INFO);  
1560
            }
1561
 
1562
            if ( project.getProperty("abt_usetestarchive") != null ) {
1563
                useTestArchive = true;
1564
                logMsg("execute useTestArchive: yes", INFO);  
1565
            }
1566
 
1567
            // Locate Machine Information for this machine
1568
            //    It contains the build filter for the current machine
1569
            //    Only present in daemon builds
1570
            //
1571
            for (Iterator<Machine> it=abtData.machineCollection.iterator(); it.hasNext(); )
1572
            {
1573
                Machine ma = it.next();
1574
                if (ma.getName().compareTo(hostname) == 0 )
1575
                {
1576
                    mMachine = ma;
1577
                    logMsg("execute machine: ", mMachine.getName() + ", Type:" + mMachine.getMachtype() + ", Class:" + mMachine.getMachclass() + ", Master:" + mMachine.getMaster() ); 
1578
                    break;
1579
                }
1580
            }
1581
 
1582
            if ( (daemon != null) && (mMachine == null) ) {
1583
                reportErrorException( "Cannot find Machine entry for: " + hostname, 256 );
1584
            }
1585
 
1586
            //  Setup machine specific information
1587
            //    Build Filter
1588
            //    Master Mode
1589
            if (mMachine != null) 
1590
            {
1591
                if (mMachine.getMaster() != null)
1592
                {
1593
                    master = true;
1594
                    logMsg("execute master: ", "true");
1595
                }
1596
 
1597
                gbebuildfilter = mMachine.getBuildfilter(); 
1598
                if ( gbebuildfilter != null )
1599
                {
1600
                    //
1601
                    // Ensure the Execute task passes gbebuildfilter as one parameter...
1602
                    // Replace spaces with commas
1603
                    //
1604
                    gbebuildfilter = gbebuildfilter.replace( " ", ",");
1605
                    logMsg("execute gbebuildfilter: ", gbebuildfilter);
1606
                }
1607
            }
1608
 
1609
            // Extract the build standard information from the abt element
1610
            //  Sets up buildStandard and one of
1611
            //            compileTarget
1612
            //        OR  javaVersion
1613
 
1614
            determineBuildStandard();
1615
            if ( buildStandard == BuildStandards.NONE)
1616
            {
1617
                //  Flag a benign build is good
1618
                //  A benign is a no-operation. The build is not required on the current machine
1619
                //
1620
                benign = true;
1621
            }
1622
 
1623
            if ( buildStandard == BuildStandards.ANT && javaVersion == JavaVersions.SKIP )
1624
            {
1625
                //  Flag a benign build - we are not building
1626
                //  Flag a skipped build - we need to place a marker in dpkg_archive
1627
                // 
1628
                //  JavaVersions.SKIP is used when a ANT build could be done on multiple machines
1629
                //  It must only be done on one such machine
1630
                // 
1631
                benign = true;
1632
                skipped = true;
1633
            }
1634
 
1635
            // Do we really need to extract and work with the source
1636
            //      Escrow Mode : yes (Not done here)
1637
            //      Daemon Mode :
1638
            //          If Master : Yes. We need to generate metrics and update the build file
1639
            //          Not Master: May be
1640
            //                      If a benign build : No
1641
            boolean extractSource = true;
1642
            if ( daemon != null && !master && benign ) {
1643
                extractSource = false;
1644
            }
1645
            logMsg("execute extractSource: ", Boolean.toString(extractSource));
1646
            logMsg("execute benign: ", Boolean.toString(benign));
1647
            logMsg("execute skipped: ", Boolean.toString(skipped));
1648
 
1649
            // redirect all thread (therefore jats) output to the output file in the basedir
1650
            re = new Redirector(this);
1651
            if ( daemon != null )
1652
            {
1653
                // thread logging is done to <rtagId>thread.log and is continually re-used every build
1654
                // full thread and non thread (ie abt logging) is done to the DefaultLogger set up by the build daemons, <rtagId>.log
1655
                // this file is copied on a build failure to cwd (if it exists) and is continually re-used every build
1656
 
1657
                // capture full logging
1658
                re.setAlwaysLog(true);
1659
            }
1660
            else
1661
            {
1662
                output = new File( logBase + ".log" );
1663
            }
1664
 
1665
            if (output != null)
1666
            {
1667
                re.setOutput( output );
1668
            }
1669
            thread = new Execute(re.createHandler());
1670
            thread.setAntRun( project );
1671
            thread.setVMLauncher(false);
1672
 
1673
            // must set up package name and owners before reportError
1674
            packageName = project.getProperty(packageAlias + "packagename");
1675
            logMsg("execute packageName: ", packageName);
1676
 
1677
            //-----------------------------------------------------------------------
1678
            //    AbtTestPath
1679
            //
1680
            if ( packageAlias.compareTo("AbtTestPath") == 0 )
1681
            {
1682
 
1683
                // jats -label check pkgVcsTag
1684
                command.init("jats", "label","-check" );
1685
                command.add( packageVcsTag );
1686
                //command.add( "-verbose=2" );
1687
 
1688
                runCommand( "Failure to validate label in source control" );
1689
 
1690
                return;
1691
            }
1692
 
1693
            //-----------------------------------------------------------------------
1694
            //    AbtSetUp
1695
            //
1696
            if ( packageAlias.compareTo("AbtSetUp") == 0 )
1697
            {
1698
                // create rtag_id directory from scratch
1699
                File rId = new File( rtagId );
1700
                deleteDirectory(rId);
1701
                if (rId.exists())
1702
                {
1703
                    reportErrorException( "Build directory not empty", 264 );
1704
                }
1705
                rId.mkdirs();
1706
 
1707
                if (extractSource)
1708
                {
1709
                    // jats jats_vcsrelease -extract -label=pkgVcsTag -path=src_path -root=rtag_id/timestamp -tag=timestamp -noprefix
1710
                    command.init("jats", "jats_vcsrelease","-extract" );
1711
                    command.add( "-label=" + packageVcsTag );
1712
                    command.add( "-root=" + rtagId );
1713
                    command.add( "-tag=" + daemon );
1714
                    command.add( "-noprefix" );
1715
                    command.add(!master, "-extractfiles");
1716
                    //command.add( "-verbose=2" );
1717
 
1718
                    runCommand( "Failure to extract source code from source control" );
1719
                }
1720
                return;
1721
            }
1722
 
1723
            //-----------------------------------------------------------------------
1724
            //    AbtTearDown
1725
            //
1726
            if ( packageAlias.compareTo("AbtTearDown") == 0 )
1727
            {
1728
                // tear the build view down, regardless of build error
1729
                wd = new File( basedir );
1730
 
1731
                // only now change the thread working directory back
1732
                thread.setWorkingDirectory( wd );
1733
 
7333 dpurdie 1734
                File buildDirectory = new File(wd, getProject().getProperty("abt_package_location"));
6914 dpurdie 1735
 
1736
                if ( buildDirectory.exists() )
1737
                {
1738
                    // jats jats_vcsrelease -label pkgTag -root=rtag_id/timestamp -tag=timestamp -noprefix -delete=2
1739
                    command.init("jats", "jats_vcsrelease" );
1740
                    command.add( "-label=" + packageVcsTag );
1741
                    command.add( "-root=" + rtagId );
1742
                    command.add( "-tag=" + daemon );
1743
                    command.add( "-noprefix" );
1744
                    command.add( "-delete=2" );
1745
                    //command.add( "-verbose=2" );
1746
 
1747
                    runCommand( "Failure to remove source code extraction" );
1748
                }
1749
 
1750
                //  delete the rtagId directory
1751
                //  If it cannot be deleted then the build has done something ugly
1752
                //  Left over bits will only hurt following builds
1753
                File rId = new File( rtagId );
1754
                deleteDirectory(rId);
1755
                if (rId.exists() )
1756
                {
1757
                    reportErrorException( "Build directory cannot be removed after build", 264 );
1758
                }
1759
 
1760
                // Always save the log files
1761
                saveLogs();
1762
 
1763
                return;      
1764
            }
1765
 
1766
            // target related    
1767
            packageVersion = project.getProperty(packageAlias + "packageversion");
1768
            logMsg("execute packageVersion: ", packageVersion);
1769
 
1770
            packageExtension = project.getProperty(packageAlias + "packageextension");
1771
            logMsg("execute packageExtension: ", packageExtension);
1772
 
1773
            packageFullVersion = packageVersion + packageExtension;
1774
            logMsg("execute packageFullVersion: ", packageFullVersion);
1775
 
1776
            packageLoc = packageName + packageExtension;
1777
            logMsg("execute packageLoc: ", packageLoc);
1778
 
1779
            if ( project.getProperty(packageAlias + "generic") != null ) {
1780
                generic = true;
1781
                logMsg("execute generic: yes", INFO);  
1782
            }
1783
 
1784
            directChange = project.getProperty(packageAlias + "directchange");
1785
            if ( directChange != null )
1786
            {
1787
                logMsg("execute directChange: yes", INFO);  
1788
            }
1789
 
1790
            doesNotRequireSourceControlInteraction = project.getProperty(packageAlias + "doesnotrequiresourcecontrolinteraction");
1791
            if ( doesNotRequireSourceControlInteraction != null )
1792
            {
1793
                logMsg("execute doesNotRequireSourceControlInteraction: true", INFO);  
1794
            }
1795
 
1796
            //    Display details of the BuildInfo Jats and Ant elements within the
1797
            //    current ABT element
1798
            //
1799
            for (Iterator<BuildInfo> it=buildInfoCollection.iterator(); it.hasNext(); )
1800
            {
1801
                BuildInfo buildInfo = it.next();
1802
                logMsg("execute buildinfo: ", "MachType: " +  buildInfo.getMachtype() + " Method: " + buildInfo.getMethod() + " " + buildInfo.getArg() );
1803
            }
1804
 
1805
 
1806
            // Set newVsTag to the existing VcsTag
1807
            // Will be used when rebuilding a package that already exists
1808
            newVcsTag = packageVcsTag;
1809
 
1810
            //
1811
            //    Determine the location of the package, relative to 'basedir'
1812
            //    Change to this directory for the remainder of the build processing
1813
            loc = project.getProperty(packageAlias + "loc");
1814
            logMsg("execute loc: ", loc);
1815
 
1816
            cwd = utilities.catDir(basedir, loc);
1817
            logMsg("execute cwd: ", cwd);
1818
 
1819
            wd = new File( cwd );
1820
            if ( !wd.exists() )
1821
            {
1822
                reportErrorException( "Failure " + cwd + " does not exist", 265 );
1823
            }
1824
 
1825
            // only now change the thread working directory
1826
            thread.setWorkingDirectory( wd );
1827
 
1828
            //-----------------------------------------------------------------------
1829
            //    AbtPublish
1830
            //    Note: Have changed directory to the working directory
1831
            //
1832
            if ( packageAlias.compareTo("AbtPublish") == 0 )
1833
            {
1834
                puplishPackage();
1835
                if ( daemon != null )
1836
                {
1837
                    // set properties to drive BuildThread attributes
1838
                    // these are used to determine what ant did
1839
                    getProject().setProperty("abt_fully_published", Boolean.toString(fullyPublished));
1840
                    getProject().setProperty("abt_new_vcstag", newVcsTag);
1841
                }
1842
 
1843
                return;
1844
            }
1845
 
1846
            //-----------------------------------------------------------------------
1847
            //    Build Target
1848
            //    Note: Have changed directory to the working directory
1849
            //
1850
            packageVersionID = project.getProperty(packageAlias + "pv_id");
1851
            logMsg("execute packageVersionID: ", packageVersionID);
1852
 
1853
            unittests = project.getProperty(packageAlias + "unittests");
1854
            if ( unittests != null )
1855
            {
1856
                logMsg("execute unittests: yes", INFO);
1857
            }
1858
 
1859
            for (Iterator<Depend> it=dependCollection.iterator(); it.hasNext(); )
1860
            {
1861
                Depend depend = it.next();
1862
                logMsg("execute depend: ", depend.getPackage_Alias());
1863
            }
1864
 
1865
            if ( daemon == null )
1866
            {
1867
                // Escrow Only
1868
                // Recognize an escrow will be run multiple times on a build stage
1869
                //      Do not force continuous rebuilding each time
1870
                //      Has this package version already been published on this platform
1871
                if ( checkEscrowMarker() )
1872
                {
1873
                    logMsg( "execute package has been published on this platform - skipping", INFO);
1874
                    propertyValue = "257";
1875
                    throw new Exception();
1876
                }
1877
            }
1878
            else
1879
            {
1880
                // DEVI 56714 daemon centric check
1881
                String majorV = this.getClass().getPackage().getSpecificationVersion();
1882
 
1883
                if ( buildtoolVersion.compareTo( majorV ) != 0 )
1884
                {
1885
                    reportErrorException( "Failure, incompatible build.xml not generated with version " + majorV, 256 );
1886
                }
1887
            }
1888
 
1889
 
1890
            if (extractSource)
1891
            {
1892
                //  Init the metrics gathering process
1893
                metricsBegin();
1894
 
1895
                //  Generate auto.pl or <PackageName>depends.xml file
1896
                genbuild();
7333 dpurdie 1897
 
1898
                //  Generate BuildInfo
1899
                genBuildInfo();
6914 dpurdie 1900
 
1901
                //  Active build
1902
                //      Build the target package unless we are simply doing metrics generation
1903
                //
1904
                if ( !benign )
1905
                {
1906
                    jatsBuildPackage();
1907
                }
1908
 
1909
                //  Complete the metrics gathering
1910
                metricsEnd();
1911
            }
1912
 
1913
            //
1914
            //  Process Skipped builds
1915
            //    Create a built.xxx marker for the publish check
1916
            //
1917
            if (skipped)
1918
            {
1919
                jatsSkipPackage();
1920
            }
1921
 
1922
        }
1923
        catch( SecurityException e)
1924
        {
1925
            errorReported = true;
1926
            reportError( "Failure caught SecurityException", 256 );
1927
        }
1928
        catch( IOException e)
1929
        {
1930
            errorReported = true;
1931
            reportError( "Failure caught IOException", 256 );
1932
        }
1933
        catch( Exception e)
1934
        {
1935
            // assume this condition has been reported on
1936
            errorReported = true;
1937
 
1938
            if ( e.getMessage() != null )
1939
            {
1940
                logMsg( "execute caught Exception " + e.getMessage(), WARN );
1941
            }
1942
            else
1943
            {
1944
                logMsg( "execute caught Exception", WARN );
1945
            }
1946
        }
1947
        finally
1948
        {
1949
            try
1950
            {
1951
                if ( daemon != null )
1952
                {
1953
                    // do not write to publish.log
1954
                    throw new IOException();
1955
                }
1956
 
1957
                FileWriter publish = new FileWriter( utilities.catDir(basedir,"publish.log"), true );
1958
                if ( propertyValue.compareTo( "0" ) == 0 )
1959
                {
1960
                    if ( benign )
1961
                    {
1962
                        publish.write( "successfully published " + packageName + " at " + packageFullVersion + ", no action required on this platform" );
1963
                    }
1964
                    else
1965
                    {
1966
                        publish.write( "successfully published " + packageName + " at " + packageFullVersion );
1967
                    }
1968
 
1969
                    publish.write( ls );
1970
                }
1971
                else if ( propertyValue.compareTo( "256" ) == 0 )
1972
                {
1973
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion +  ", internal abt issue" + ls );
1974
                }
1975
                else if ( propertyValue.compareTo( "257" ) == 0 )
1976
                {
1977
                    errorReported = false;
1978
                    publish.write( "previously published " + packageName + " at " + packageFullVersion + ls );
1979
                }
1980
                else if ( propertyValue.compareTo( "261" ) == 0 )
1981
                {
1982
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", missing or bad descpkg file" + ls );
1983
                }
1984
                else if ( propertyValue.compareTo( "262" ) == 0 )
1985
                {
1986
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", couldn't process save_build info" + ls );
1987
                }
1988
                else if ( propertyValue.compareTo( "263" ) == 0 )
1989
                {
1990
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", couldn't write to auto.cfg" + ls );
1991
                }
1992
                else if ( propertyValue.compareTo( "265" ) == 0 )
1993
                {
1994
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", " + cwd + " does not exist" + ls );
1995
                }
1996
                else if ( propertyValue.compareTo( "264" ) == 0 )
1997
                {
1998
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", " + " Could not delete build directory" + ls );
1999
                }
2000
                else if ( propertyValue.compareTo( "267" ) == 0 )
2001
                {
2002
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", " + " Could not assemble package fragments" + ls );
2003
                }
2004
                else
2005
                {
2006
                    // nb jats or ant can presumably return a value 1 to 255
2007
                    publish.write( "failed to publish " + packageName + " at " + packageFullVersion + ", jats or ant failed" + ls );
2008
                }
2009
 
2010
                publish.close();
2011
            }
2012
            catch( IOException e )
2013
            {
2014
                if ( daemon == null )
2015
                {
2016
                    reportError( "Failure to write to publish.log", 266 );
2017
                }
2018
            }
2019
            catch( Exception e )
2020
            {
2021
                if ( daemon == null )
2022
                {
2023
                    reportError( "Failure to write to publish.log", 266 );
2024
                }
2025
            }
2026
 
2027
            getProject().setProperty(packageAlias + ".res", propertyValue);
2028
 
2029
            if ( errorReported )
2030
            {
2031
                // designed to prevent subsequent build activity on this build file
2032
                // supply the build failure log file in message with / as file sep
2033
                // takes the form hostname/rtag_id/daemon/logfile
2034
                if ( daemon != null )
2035
                {
2036
                    String message = hostname + "/" + rtagId + "/" + daemon + "/" + logBase + ".log";
2037
                    throw new BuildException( message );
2038
                }
2039
                else
2040
                {
2041
                    throw new BuildException();
2042
                }
2043
            }
2044
 
2045
        }
2046
    }
2047
 
2048
 
2049
    /**
2050
     * Delete a directory and all of its contents
2051
     * Set directories and sub directories writable in case the user has messed with permissions. 
2052
     * This function is called recursively to delete the entire directory tree
2053
     * 
2054
     * Note: Having some issues deleting directories
2055
     *       Try many times. On the second attempt log the files that remained
2056
     * 
2057
     * @param directory The top level directory to delete
2058
     */
2059
    private void deleteDirectory(File directory)
2060
    {
2061
        logMsg("deleteDirectory " + directory.getName(), DEBUG);
2062
 
2063
        int attempts = 0;
2064
        boolean verbose = false;
2065
        while (directory.exists()) {
2066
            attempts++;
2067
 
2068
            // Use Java native method fist
2069
            // The Jats utility is good, but there is some interaction with VirusScanners/Indexing that a bit strange
2070
            //
2071
            if ( (attempts & 1) == 1) {
2072
                deleteDirectoryInternalViaJava(directory, verbose);
2073
            }  else {
2074
                deleteDirectoryInternalViaJats(directory, verbose);
2075
            }
2076
 
2077
            if (!directory.exists()) {
7186 dpurdie 2078
                logMsg("deleteDirectory deleted after " + attempts + " attempts " + directory.getName(), WARN);
6914 dpurdie 2079
                break;
2080
            }
2081
            verbose = true;
2082
 
2083
            if (attempts > 10)
2084
            {
2085
                logMsg("deleteDirectory give up delete after " + attempts + " attempts " + directory.getName(), FATAL);
2086
                break;
2087
            }
2088
 
7186 dpurdie 2089
            logMsg("deleteDirectory not deleted after " + attempts + " attempts " + directory.getName(), WARN);
6914 dpurdie 2090
 
2091
//          //
2092
//          //  Debugging code
2093
//          //  Display all handles in the system (windows only)
2094
//          //
2095
//          if(System.getProperty("os.name").startsWith("Windows"))
2096
//          {
2097
//              String[] cmd = {"handle"};
2098
//              Log("deleteDirectory Execute handle.", warn);
2099
//              thread.setCommandline(cmd);
2100
//              try {
2101
//                  thread.execute();
2102
//              } catch (IOException e) {
2103
//                  logMsg("deleteDirectory Did not execute handle: " + e.getMessage(), WARN);
2104
//              }
2105
//          }
2106
 
2107
            //  Wait a short while before attempting to delete the directory again
2108
            //  Rational:
2109
            //      - AntiVirus software may be having a sniff, so let it finish
2110
            //      - Program shut down may take a few seconds
2111
            //      - Because nothing else appears to work
2112
            try {
2113
                logMsg("deleteDirectory sleep before attempt:" + attempts, DEBUG);
2114
                Thread.sleep(10 * 1000L);
2115
            } catch (InterruptedException e) {
2116
                logMsg("deleteDirectory sleep exception: " + e.getMessage(), WARN);
2117
                Thread.currentThread().interrupt();
2118
                break;
2119
            }
2120
 
2121
        }
2122
    }
2123
 
2124
    /**
2125
     * The body of the deleteDirectory operation
2126
     * Used simply to avoid excessive logging.
2127
     * 
2128
     * @param directory The top level directory to delete
2129
     * @param verbose - display files and folders as they are deleted
2130
     */
2131
    private void deleteDirectoryInternalViaJava(File directory, boolean verbose)
2132
    {
2133
        try
2134
        {
2135
            if ( directory.exists() )
2136
            {
2137
                File[] children = directory.listFiles();
2138
                directory.setWritable(true);
2139
                if ( children != null )
2140
                {
2141
                    for ( int child=0; child < children.length; child++ )
2142
                    {
2143
                        if ( children[ child ].isDirectory() )
2144
                        {
2145
                            deleteDirectoryInternalViaJava( children[ child ], verbose );
2146
                        }
2147
                        else
2148
                        {
2149
                            if(verbose)
2150
                            {
2151
                                logMsg("deleteDirectory File:" + children[ child ].getName(), DEBUG);
2152
                            }
2153
                            children[ child ].setWritable(true);
2154
                            children[ child ].delete();
2155
                        }
2156
                    }
2157
                }
2158
                if (verbose)
2159
                {
2160
                    logMsg("deleteDirectory Dir:" + directory.getName(), DEBUG);
2161
                }
2162
                directory.delete();
2163
            }
2164
        }
2165
        catch( SecurityException e )
2166
        {
2167
            // this can be thrown by exists and delete
2168
            logMsg("deleteDirectory caught SecurityException", WARN);
2169
        }
2170
    }
2171
 
2172
 
2173
    /**
2174
     * The body of the deleteDirectory operation done with JATS utility
2175
     * Used simply to avoid excessive logging.
2176
     * 
2177
     * @param directory The top level directory to delete
2178
     * @param verbose - display files and folders as they are deleted
2179
     */
2180
    private void deleteDirectoryInternalViaJats(File directory, boolean verbose)
2181
    {
2182
 
2183
        //  Use jats ebin JatsFileUtil T0 TextMsg DirName to delete the directory tree
2184
        //  Address issues that cannot be solved in java
2185
 
2186
        command.init("jats", "ebin","JatsFileUtil" );
2187
        command.add( verbose, "T9" );
2188
        command.add( !verbose, "T0" );
2189
        command.add( "DeleteDir-" + rtagId );
2190
        command.add(directory.getAbsolutePath());
2191
 
2192
        // Run the command - don't care if it fails
2193
        //  It should not generate an exception
2194
        try {
2195
            runCommand(null);
2196
        } catch (Exception e1) {
2197
            logMsg("deleteDirectory caught Exception", ERROR);
2198
        }
2199
    }
2200
 
2201
    /**
2202
     * Insert a marker into the created package so that the
2203
     * escrow build can detect that the package has been built.
2204
     * 
2205
     * This is used in the following situations:
2206
     * 
2207
     * 1) ANT packages that could be build on multiple machines
2208
     * 2) Restarted build on the same machine
2209
     */
2210
    private void insertEscrowMarker()
2211
    {
2212
        //
2213
        //  Only used in escrow mode
2214
        //
2215
        if ( daemon == null && packageStandard == BuildStandards.ANT)
2216
        {
2217
            //
2218
            //  ANT builds are performed on a machine type basis
2219
            //  Create a 'MachClass' based marker
2220
            //
2221
            String destination = utilities.catDir(dpkgArchive, packageName, packageFullVersion);
2222
            String filename = "built." + gbeMachClass; 
2223
 
2224
            try
2225
            {
2226
                new File(destination).mkdirs(); 
2227
                new File(destination, filename).createNewFile();
2228
            } 
2229
            catch (IOException ioe)
2230
            {
2231
                logMsg("Cannot insert Escrow Marker", FATAL);
2232
            }
2233
        }
2234
    }
2235
 
2236
 
2237
    /**
2238
     * Check for the existence of an Escrow marker
2239
     * Used so that the build system can detect if this
2240
     * package has already been built.
2241
     * 
2242
     * Can occur under two conditions
2243
     * 
2244
     * 1) ANT packages that can be built on multiple machines
2245
     * 2) ReStarted build on same machine 
2246
     *  
2247
     * Assumption: Only called in Escrow Mode 
2248
     * 
2249
     * @return TRUE  - Marker Detected
2250
     *         FALSE - Marker not Detected
2251
     */
2252
    private boolean checkEscrowMarker() throws Exception
2253
    {
2254
        String destination = utilities.catDir(dpkgArchive, packageName, packageFullVersion);
2255
        String filename = "built." + (generic ? "generic" : hostname);
2256
 
2257
        if (new File( destination, filename ).exists())
2258
        {
2259
            return true;
2260
        }
2261
 
2262
        if ( packageStandard == BuildStandards.ANT)
2263
        {
2264
            //
2265
            //  ANT builds are performed on a machine type basis
2266
            //  Check for a 'MachClass' based marker
2267
            //
2268
            filename = "built." + gbeMachClass; 
2269
            if (new File( destination, filename).exists())
2270
            {
2271
                return true;
2272
            }
2273
        }
2274
        return false;
2275
    }
2276
 
2277
    //---------------------------------------------------------------------------
2278
    //    Extend the <abt> task with several new elements
2279
    //
2280
    //        <depend package_alias="${debian_dpkg.cots}"/>
2281
    //        <buildinfo gbe_machtype="solaris10_x86" method="jats" arg="debug"/>
2282
    //
2283
    public Depend createDepend()
2284
    {
2285
        Depend depend = new Depend();
2286
        dependCollection.add(depend);
2287
        return depend;
2288
    }
2289
 
2290
    public BuildInfo createBuildInfo()
2291
    {
2292
        BuildInfo buildInfo = new BuildInfo();
2293
        buildInfoCollection.add(buildInfo);
2294
        return buildInfo;
2295
    }
2296
 
2297
}