Subversion Repositories DevTools

Rev

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