5
5
6
6
import java .io .File ;
7
7
import java .io .IOException ;
8
+ import java .net .UnknownHostException ;
8
9
import java .util .ArrayList ;
9
10
import java .util .Collections ;
10
11
import java .util .List ;
@@ -36,6 +37,42 @@ public class AruUtil {
36
37
37
38
private static final String BUG_SEARCH_URL = ARU_REST_URL + "/search?bug=%s" ;
38
39
40
+ private static int REST_RETRIES = 10 ;
41
+ private static int REST_INTERVAL = 500 ;
42
+
43
+ static {
44
+ // static block to parst environment variable overrides for REST call defaults
45
+ final String retriesEnvVar = "WLSIMG_REST_RETRY_MAX" ;
46
+ final String retriesString = System .getenv (retriesEnvVar );
47
+ try {
48
+ if (retriesString != null ) {
49
+ REST_RETRIES = Integer .parseInt (retriesString );
50
+ if (REST_RETRIES < 1 ) {
51
+ REST_RETRIES = 10 ;
52
+ logger .severe ("IMG-0109" , retriesEnvVar , retriesString , 1 , REST_RETRIES );
53
+ }
54
+ logger .fine ("Retry max set to {0}" , REST_RETRIES );
55
+ }
56
+ } catch (NumberFormatException nfe ) {
57
+ logger .warning ("IMG-0108" , retriesEnvVar , retriesString );
58
+ }
59
+
60
+ final String waitEnvVar = "WLSIMG_REST_RETRY_INTERVAL" ;
61
+ final String waitString = System .getenv (waitEnvVar );
62
+ try {
63
+ if (waitString != null ) {
64
+ REST_INTERVAL = Integer .parseInt (waitString );
65
+ if (REST_INTERVAL < 0 ) {
66
+ REST_INTERVAL = 500 ;
67
+ logger .severe ("IMG-0109" , waitEnvVar , waitString , 0 , REST_INTERVAL );
68
+ }
69
+ logger .fine ("Retry interval set to {0}" , REST_INTERVAL );
70
+ }
71
+ } catch (NumberFormatException nfe ) {
72
+ logger .warning ("IMG-0108" , waitEnvVar , waitString );
73
+ }
74
+ }
75
+
39
76
/**
40
77
* Get ARU HTTP helper instance.
41
78
* @return ARU helper.
@@ -98,13 +135,14 @@ List<AruPatch> getLatestPsu(AruProduct product, String version, String userId, S
98
135
try {
99
136
logger .info ("IMG-0019" , product .description ());
100
137
String releaseNumber = getReleaseNumber (product , version , userId , password );
101
- Document aruRecommendations = getRecommendedPatchesMetadata (product , releaseNumber , userId , password );
138
+ Document aruRecommendations = retry (
139
+ () -> getRecommendedPatchesMetadata (product , releaseNumber , userId , password ));
102
140
logger .exiting ();
103
141
return AruPatch .removeStackPatchBundle (AruPatch .getPatches (aruRecommendations , "[./psu_bundle]" ));
104
142
} catch (NoPatchesFoundException | ReleaseNotFoundException ex ) {
105
143
logger .exiting ();
106
144
return Collections .emptyList ();
107
- } catch (IOException | XPathExpressionException e ) {
145
+ } catch (RetryFailedException | XPathExpressionException e ) {
108
146
throw logger .throwing (
109
147
new AruException (Utils .getMessage ("IMG-0032" , product .description (), version ), e ));
110
148
}
@@ -149,7 +187,8 @@ List<AruPatch> getRecommendedPatches(AruProduct product, String version, String
149
187
try {
150
188
logger .info ("IMG-0067" , product .description ());
151
189
String releaseNumber = getReleaseNumber (product , version , userId , password );
152
- Document aruRecommendations = getRecommendedPatchesMetadata (product , releaseNumber , userId , password );
190
+ Document aruRecommendations = retry (
191
+ () -> getRecommendedPatchesMetadata (product , releaseNumber , userId , password ));
153
192
List <AruPatch > patches = AruPatch .removeStackPatchBundle (AruPatch .getPatches (aruRecommendations ));
154
193
String psuVersion = getPsuVersion (patches );
155
194
if (!Utils .isEmptyString (psuVersion )) {
@@ -159,8 +198,10 @@ List<AruPatch> getRecommendedPatches(AruProduct product, String version, String
159
198
// get release number for PSU
160
199
String psuReleaseNumber = getReleaseNumber (product , psuVersion , userId , password );
161
200
// get recommended patches for PSU release (Overlay patches are only recommended on the PSU release)
162
- Document psuRecommendation = getRecommendedPatchesMetadata (product , psuReleaseNumber , userId , password );
163
- patches = AruPatch .removeStackPatchBundle (AruPatch .getPatches (psuRecommendation ));
201
+ Document psuOverrides = retry (
202
+ () -> getRecommendedPatchesMetadata (product , psuReleaseNumber , userId , password ));
203
+
204
+ patches = AruPatch .removeStackPatchBundle (AruPatch .getPatches (psuOverrides ));
164
205
}
165
206
patches .forEach (p -> logger .info ("IMG-0068" , product .description (), p .patchId (), p .description ()));
166
207
logger .exiting (patches );
@@ -170,7 +211,7 @@ List<AruPatch> getRecommendedPatches(AruProduct product, String version, String
170
211
} catch (NoPatchesFoundException npf ) {
171
212
logger .info ("IMG-0069" , product .description (), version );
172
213
return Collections .emptyList ();
173
- } catch (IOException | XPathExpressionException e ) {
214
+ } catch (RetryFailedException | XPathExpressionException e ) {
174
215
throw new AruException (Utils .getMessage ("IMG-0070" , product .description (), version ), e );
175
216
}
176
217
}
@@ -275,16 +316,15 @@ Document getAllReleases(String userId, String password) throws AruException {
275
316
if (allReleasesDocument == null ) {
276
317
logger .fine ("Getting all releases document from ARU..." );
277
318
try {
278
- Document response = HttpUtil .getXMLContent (REL_URL , userId , password );
279
- verifyResponse (response );
280
- allReleasesDocument = response ;
281
- } catch (IOException | AruException | XPathExpressionException ex ) {
282
- throw new AruException (Utils .getMessage ("IMG-0081" ), ex );
319
+ allReleasesDocument = retry (() -> getAndVerify (REL_URL , userId , password ));
320
+ } catch (RetryFailedException e ) {
321
+ throw new AruException (Utils .getMessage ("IMG-0081" ));
283
322
}
284
323
}
285
324
return allReleasesDocument ;
286
325
}
287
326
327
+ // could be private, but leaving as protected for unit testing
288
328
Document getRecommendedPatchesMetadata (AruProduct product , String releaseNumber , String userId , String password )
289
329
throws IOException , AruException , XPathExpressionException {
290
330
@@ -356,7 +396,13 @@ public static boolean checkCredentials(String username, String password) {
356
396
return aruHttpHelper .success ();
357
397
}
358
398
359
- void verifyResponse (Document response ) throws AruException , XPathExpressionException {
399
+ private Document getAndVerify (String url , String userId , String password )
400
+ throws IOException , XPathExpressionException , AruException {
401
+ Document response = HttpUtil .getXMLContent (url , userId , password );
402
+ return verifyResponse (response );
403
+ }
404
+
405
+ private Document verifyResponse (Document response ) throws AruException , XPathExpressionException {
360
406
NodeList nodeList = XPathUtil .nodelist (response , "/results/error" );
361
407
if (nodeList .getLength () > 0 ) {
362
408
String errorMessage = XPathUtil .string (response , "/results/error/message" );
@@ -371,6 +417,7 @@ void verifyResponse(Document response) throws AruException, XPathExpressionExcep
371
417
logger .throwing (error );
372
418
throw error ;
373
419
}
420
+ return response ;
374
421
}
375
422
376
423
/**
@@ -393,13 +440,14 @@ public List<AruPatch> getPatches(String bugNumber, String userId, String passwor
393
440
394
441
String url = String .format (BUG_SEARCH_URL , bugNumber );
395
442
logger .info ("IMG-0063" , bugNumber );
396
- Document response = HttpUtil .getXMLContent (url , userId , password );
397
443
try {
398
- verifyResponse (response );
444
+ Document response = retry (() -> getAndVerify (url , userId , password ));
445
+ return AruPatch .getPatches (response );
399
446
} catch (NoPatchesFoundException patchEx ) {
400
447
throw new NoPatchesFoundException (Utils .getMessage ("IMG-0086" , bugNumber ), patchEx );
448
+ } catch (RetryFailedException retryEx ) {
449
+ throw new AruException (Utils .getMessage ("IMG-0110" , retryEx ));
401
450
}
402
- return AruPatch .getPatches (response );
403
451
}
404
452
405
453
/**
@@ -426,13 +474,39 @@ public String downloadAruPatch(AruPatch aruPatch, String targetDir, String usern
426
474
.socketTimeout (30000 ))
427
475
.saveContent (new File (filename ));
428
476
} catch (Exception ex ) {
429
- String message = String .format ("Failed to download and save file %s from %s: %s" , filename ,
430
- aruPatch .downloadUrl (), ex .getLocalizedMessage ());
477
+ String message = Utils .getMessage ("IMG-0107" , filename , aruPatch .downloadUrl (), ex .getLocalizedMessage ());
431
478
logger .severe (message );
432
479
throw new IOException (message , ex );
433
480
}
434
481
logger .exiting (filename );
435
482
return filename ;
436
483
}
484
+
485
+ private interface CallToRetry {
486
+ Document process () throws IOException , XPathExpressionException , AruException ;
487
+ }
488
+
489
+ // create an environment variable that can override the tries count (undocumented)
490
+ private static Document retry (CallToRetry call ) throws AruException , RetryFailedException {
491
+ for (int i = 0 ; i < REST_RETRIES ; i ++) {
492
+ try {
493
+ return call .process ();
494
+ } catch (UnknownHostException e ) {
495
+ throw new AruException (e .getLocalizedMessage (), e );
496
+ } catch (IOException | XPathExpressionException e ) {
497
+ logger .info ("IMG-0106" , e .getMessage (), (i + 1 ), REST_RETRIES );
498
+ }
499
+ try {
500
+ if (REST_INTERVAL > 0 ) {
501
+ logger .finer ("Waiting {0} ms before retry..." , REST_INTERVAL );
502
+ Thread .sleep (REST_INTERVAL );
503
+ }
504
+ } catch (InterruptedException wakeAndAbort ) {
505
+ break ;
506
+ }
507
+ }
508
+ // When all retries are exhausted, raise an ARU exception to exit the process (give up)
509
+ throw logger .throwing (new RetryFailedException ());
510
+ }
437
511
}
438
512
0 commit comments