Subversion Repositories DevTools

Rev

Rev 6914 | Rev 7033 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6914 dpurdie 1
package com.erggroup.buildtool.ripple;
2
 
3
import org.apache.log4j.Logger;
4
 
5
import com.erggroup.buildtool.smtp.CreateUrls;
6
import com.erggroup.buildtool.smtp.Smtpsend;
7
 
8
import java.sql.SQLException;
9
import java.util.ArrayList;
10
import java.util.Iterator;
11
 
12
/**entity class holding build exclusion data
13
 */
14
public class BuildExclusion
15
{
16
  /**Logger
17
   * @attribute
18
   */
19
  private static final Logger mLogger = Logger.getLogger(BuildExclusion.class);
20
 
21
  /**The pvid of the package being excluded
22
   * @attribute
23
   */
24
  private int mId;
25
 
26
  /**root identifier is the PVID of the package that is causing the exclusion
27
   * A NULL value indicates that this entry(package) is the root cause of the of an exclusion
28
   * @attribute
29
   */
30
  private int mRootId;
31
 
32
  /**root cause
33
   * If not NULL, then this is the reason this package is being excluded
34
   * @attribute
35
   */
36
  private String mRootCause;
37
 
38
  /**test build instruction
39
   * @attribute
40
   */
41
  private int mTestBuildInstruction;
42
 
43
  /**Indicates that the item has been processed
44
   * @attribute
45
   */
46
  private boolean mProcessed = false;
7032 dpurdie 47
 
48
  /** Indicates that the entry was imported from the database
49
   *  Used to determine entries that are no-longer needed and can be removed from the database
50
   *  Really only applied to indirect exclusions where the reason for the exclusion no longer exists
51
   *  
52
   */
53
  private boolean mImported = false;
6914 dpurdie 54
 
55
  /**constructor
7032 dpurdie 56
   *    @param  identifier - pvid of the package being excluded
57
   *    @param  rootIdentifier  - pvid of the root package causing the exclusion. May be null
58
   *    @param  rootCause - Short (< 50 Char) string explaining the cause
59
   *    @param  testBuildInstruction - Indicates a text build instruction
6914 dpurdie 60
   */
61
  public BuildExclusion(int identifier, int rootIdentifier, String rootCause, int testBuildInstruction )
62
  {
63
    mLogger.debug("BuildExclusion");
64
    mId = identifier;
65
    mRootId = dealWithNullRootPvId(identifier, rootIdentifier);
66
    mRootCause = rootCause;
67
    mTestBuildInstruction = testBuildInstruction;
68
  }
69
 
70
  /**sets mProcessed true
71
   */
7032 dpurdie 72
  void setProcessed()
6914 dpurdie 73
  {
74
    mLogger.debug("process " + mId);
75
    mProcessed = true;
76
  }
77
 
78
  /** @returns true if the item has been marked as processed. 
7032 dpurdie 79
   * Appears to be an indication that the entry has been superseded.
6914 dpurdie 80
   */
81
  boolean isProcessed()
82
  {
83
    mLogger.debug("isProcessed " + mId);
84
    mLogger.info("isProcessed returned " + mProcessed);
85
    return mProcessed;
86
  }
7032 dpurdie 87
 
88
  /** Flag as an imported entry
89
   *  Used to detect indirect exclusions that are no longer valid
90
   */
91
  void setImported()
92
  {
93
      mImported = true;
94
  }
6914 dpurdie 95
 
7032 dpurdie 96
  /** Test the state of the imported flag
97
   * 
98
   */
99
  boolean isImported()
100
  {
101
      return mImported;
102
  }
103
 
6914 dpurdie 104
  /**
105
   * Compare this item with parameters
106
   * @param identifier          - Related Package identifier
107
   * @param rootIdentifier      - Package identifier of root cause
108
   * @param  rootCause          - Root cause string. May be null
109
   * @return true if all attributes match
110
   */
111
  boolean compare( int identifier, int rootIdentifier, String rootCause)
112
  {
113
    mLogger.debug("compare " + mId + ", " + identifier + ", " + rootIdentifier + ", " + rootCause);
114
    boolean retVal = false;
115
    rootIdentifier = dealWithNullRootPvId(identifier, rootIdentifier);
116
 
117
    if ( mRootCause == null )
118
    {
119
      if ( mId == identifier && mRootId == rootIdentifier && rootCause == null )
120
      {
121
        retVal = true;
122
      }
123
    }
124
    else
125
    {
126
      if ( mId == identifier && mRootId == rootIdentifier && mRootCause.compareTo(rootCause) == 0 )
127
      {
128
        retVal = true;
129
      }
130
    }
131
 
132
    mLogger.info("compare returned " + retVal);
133
    return retVal;
134
  }
135
 
136
  /**
137
   * @param identifier  - identifier to match
138
   * @return true if mId attribute matches
139
   */
140
  boolean compare( int identifier )
141
  {
142
    mLogger.debug("compare " + mId + ", " + identifier);
143
    boolean retVal = false;
144
 
145
    if ( mId == identifier )
146
    {
147
      retVal = true;
148
    }
149
 
150
    mLogger.info("compare returned " + retVal);
151
    return retVal;
152
  }
153
 
154
  /**runs exclude from build
155
   * Assumes that a connection to RM has been established
156
   * 
157
   * @param rm          Release Manager instance
158
   * @param rtag_id     Rtag Id we are working against
159
   */
160
  void excludeFromBuild( ReleaseManager rm, int rtag_id ) throws SQLException, Exception
161
  {
162
    mLogger.debug("excludeFromBuild " + mId);
163
 
164
    // a null version and log file is passed to oracle
165
    // the planned version is only needed to remove a planned version from the planned version table
166
    // the ripple engine does not get this far ie it excludes pvs before claiming a version
167
    // this is the one instance where an existing build failure must be superseded in the database
168
    rm.excludeFromBuild(true, 
169
                        mId, 
170
                        null, 
171
                        rtag_id, 
172
    		            mRootId == -1 ? null : String.valueOf(mRootId), 
173
    		            mRootCause, 
174
    		            null, 
175
    		            true, (mTestBuildInstruction > 0) );
176
  }
177
 
178
  /**runs include to build
179
   * Include a previously excluded package-version back into the build set
180
   * 
181
   * @param rm          Release Manager instance
182
   * @param rtag_id     Rtag Id we are working against
183
   */
184
  void includeToBuild( ReleaseManager rm, int rtag_id ) throws SQLException, Exception
185
  {
186
    mLogger.debug("includeToBuild " + mId);
187
    rm.includeToBuild(mId, rtag_id);
188
  }
189
 
190
  /**
191
   * Match this items id against that provided
192
   * @param id  - Id to match
193
   * @return true if id matches mId
194
   */
195
    private boolean isRelevant(int id)
196
    {
197
      mLogger.debug("isRelevant " + mId + ", " + id);
198
      boolean retVal = false;
199
 
200
      if ( mId == id )
201
      {
202
        retVal = true;
203
      }
204
 
205
      mLogger.info("isRelevant " + mId +  ", " + id + " returned " + retVal);
206
      return retVal;
207
    }
208
 
209
  /**
210
   * Match this items mRootId against the id's provided in a collection
211
   * ie: Determine if any items in the collection are the root cause of this items
212
   * ie: Used to determine if an entry is for an indirectly excluded package where
213
   *     the root cause of the exclusion has been removed.
214
   *     
215
   * @param buildExclusionCollection - Collection to be processed
216
   * @return false: Indirectly excluded package whose root cause no longer exists
217
   */
218
  boolean isRelevant(ArrayList<BuildExclusion> buildExclusionCollection)
219
  {
220
    mLogger.debug("isRelevant " + mId);
221
    boolean retVal = false;
222
 
223
    if ( mRootId == -1 )     {
224
      retVal = true;
225
 
226
    } else if(mRootId == -2 ) {
227
        // Excluded due to Ripple Stop
228
        // Will be recalculated so its not relevant
229
        retVal = false;
230
 
231
    } else {
7032 dpurdie 232
 
233
      retVal = false;
6914 dpurdie 234
      for (Iterator<BuildExclusion> it = buildExclusionCollection.iterator(); it.hasNext(); )
235
      {
236
        BuildExclusion buildExclusion = it.next();
237
 
238
        if ( buildExclusion.isRelevant( mRootId ) )
239
        {
240
          retVal = true;
241
          break;
242
        }
243
      }
244
    }
245
 
246
    mLogger.info("isRelevant " + mId + " returned " + retVal);
247
    return retVal;
248
  }
249
 
250
  /**
251
   * @return true if the root_pv_id is null (-1). This indicates that the item is the root case, and is not simply
252
   *         a by product of some other cause.
253
   */
254
  boolean isARootCause()
255
  {
256
    mLogger.debug("isARootCause " + mId);
257
    boolean retVal = false;
258
 
259
    if ( mRootId == -1 )
260
    {
261
      retVal = true;
262
    }
263
 
264
    mLogger.info("isARootCause " + mId + " returned " + retVal);
265
    return retVal;
266
  }
267
 
268
  /**
269
   * Send an email notifying users about a build excluded package
270
   * It is user friendly, in that it does not trigger a storm of emails because a low level package 
271
   * has a build issue. It limits the emails to the low level package
272
   * 
273
   * i.e. only send email if the build exclusion has a null root pv id
274
   * and a non null root cause
275
   * 
276
   * @param    rippleEngine        - Ripple Engine Instance
277
   * @param    packageCollection   - Collection to process
278
   */
279
    public void email(RippleEngine rippleEngine, ArrayList<Package> packageCollection) throws SQLException, Exception
280
    {
281
      mLogger.debug("email " + mId);
282
 
283
      //
284
      //    Only process entries that are direct failures of ripple engine detected failure
285
      //    Do not process entries that are indirectly excluded as this will cause an email storm
286
      //    Direct build failure: 
287
      //        Have no RootId and have a rootCause
288
      //
289
      if ( mRootId == -1 && mRootCause != null )
290
      {
291
        //  Locate the associated package entry
292
        Package pkg= rippleEngine.mReleaseManager.findPackage(mId, packageCollection);
293
 
294
        if ( pkg != ReleaseManager.NULL_PACKAGE )
295
        {
296
 
297
          // Is there anyone to send an email to
298
          String owners = pkg.emailInfoNonAntTask(rippleEngine);
299
 
300
          if ( owners != null )
301
          {
302
 
303
            String body =
304
            "Release: " + rippleEngine.mBaselineName + "<p>" +
305
            "Package: " + pkg.mName + "<p>" + 
306
            "Cause: "   + mRootCause + "<p>"+
307
            "RmRef: "   + CreateUrls.generateRmUrl(rippleEngine.getRtagId(), pkg.mId) +"<p>";
308
 
309
            try
310
            {
311
              Smtpsend.send(
7032 dpurdie 312
              rippleEngine.getMailServer(),             // mailServer
313
              rippleEngine.getMailSender(),             // source
6914 dpurdie 314
              owners,                                   // target
315
              null,                                     // cc
316
              null,                                     // bcc
317
              "BUILD FAILURE on package " + pkg.mName,  // subject
318
              body,                                     // body
319
              null                                      // attachment
320
              );
321
            }
322
            catch( Exception e )
323
            {
324
            }
325
          }
326
 
327
          // Having sent the build failure email, complete a test build if applicable.
328
          // This ensures the test build instruction is not processed indefinitely
329
          // as there is no notion of excluding test builds
330
          pkg.completeTestBuild(rippleEngine, false);
331
        }
332
      }
333
    }
334
 
335
    /**
336
     * Hides how a rootPvId is treated
337
     * Only use rootPvId if not equal to the pvid
338
     * 
339
     * If the provided rootPvId matches the pvId, then the rootPvId will be set to null (-1)
340
     * This is to drive a direct build exclusion in the release manager
341
     * 
342
     * @param   pvid        - id
343
     * @param   rootPvId    - rootPvid
344
     * 
345
     * @returns rootPvId unless pvId matches= rootPvId, when it returns a null (-1)
346
    */
347
    private int dealWithNullRootPvId( int pvId, int rootPvId )
348
    {
349
      int retVal = rootPvId;
350
 
351
      if ( pvId == rootPvId )
352
      {
353
        retVal = -1;    // -1 == null entry
354
      }
355
 
356
      return retVal;
357
    }
358
 
359
    /**
360
     * Generate a single text line of info
361
     * Used within the UTF to 
362
     * @return String form of the state of the entry
363
     */
364
    public String info()
365
    {
366
        String rv = "";
367
        rv += "pvid=" + mId + ",RootId=" + mRootId + ",Processed=" + mProcessed + ",TestBuild=" + mTestBuildInstruction + ",RootCause=" + mRootCause;
7032 dpurdie 368
        if ( mImported ) {
369
            rv += ",Imported=" + mImported;
370
        }
6914 dpurdie 371
        return rv;
372
    }
373
}