55
66import java .io .File ;
77import java .io .IOException ;
8+ import java .net .UnknownHostException ;
89import java .util .ArrayList ;
910import java .util .Collections ;
1011import java .util .List ;
@@ -36,6 +37,42 @@ public class AruUtil {
3637
3738 private static final String BUG_SEARCH_URL = ARU_REST_URL + "/search?bug=%s" ;
3839
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+
3976 /**
4077 * Get ARU HTTP helper instance.
4178 * @return ARU helper.
@@ -98,13 +135,14 @@ List<AruPatch> getLatestPsu(AruProduct product, String version, String userId, S
98135 try {
99136 logger .info ("IMG-0019" , product .description ());
100137 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 ));
102140 logger .exiting ();
103141 return AruPatch .removeStackPatchBundle (AruPatch .getPatches (aruRecommendations , "[./psu_bundle]" ));
104142 } catch (NoPatchesFoundException | ReleaseNotFoundException ex ) {
105143 logger .exiting ();
106144 return Collections .emptyList ();
107- } catch (IOException | XPathExpressionException e ) {
145+ } catch (RetryFailedException | XPathExpressionException e ) {
108146 throw logger .throwing (
109147 new AruException (Utils .getMessage ("IMG-0032" , product .description (), version ), e ));
110148 }
@@ -149,7 +187,8 @@ List<AruPatch> getRecommendedPatches(AruProduct product, String version, String
149187 try {
150188 logger .info ("IMG-0067" , product .description ());
151189 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 ));
153192 List <AruPatch > patches = AruPatch .removeStackPatchBundle (AruPatch .getPatches (aruRecommendations ));
154193 String psuVersion = getPsuVersion (patches );
155194 if (!Utils .isEmptyString (psuVersion )) {
@@ -159,8 +198,10 @@ List<AruPatch> getRecommendedPatches(AruProduct product, String version, String
159198 // get release number for PSU
160199 String psuReleaseNumber = getReleaseNumber (product , psuVersion , userId , password );
161200 // 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 ));
164205 }
165206 patches .forEach (p -> logger .info ("IMG-0068" , product .description (), p .patchId (), p .description ()));
166207 logger .exiting (patches );
@@ -170,7 +211,7 @@ List<AruPatch> getRecommendedPatches(AruProduct product, String version, String
170211 } catch (NoPatchesFoundException npf ) {
171212 logger .info ("IMG-0069" , product .description (), version );
172213 return Collections .emptyList ();
173- } catch (IOException | XPathExpressionException e ) {
214+ } catch (RetryFailedException | XPathExpressionException e ) {
174215 throw new AruException (Utils .getMessage ("IMG-0070" , product .description (), version ), e );
175216 }
176217 }
@@ -275,16 +316,15 @@ Document getAllReleases(String userId, String password) throws AruException {
275316 if (allReleasesDocument == null ) {
276317 logger .fine ("Getting all releases document from ARU..." );
277318 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" ));
283322 }
284323 }
285324 return allReleasesDocument ;
286325 }
287326
327+ // could be private, but leaving as protected for unit testing
288328 Document getRecommendedPatchesMetadata (AruProduct product , String releaseNumber , String userId , String password )
289329 throws IOException , AruException , XPathExpressionException {
290330
@@ -356,7 +396,13 @@ public static boolean checkCredentials(String username, String password) {
356396 return aruHttpHelper .success ();
357397 }
358398
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 {
360406 NodeList nodeList = XPathUtil .nodelist (response , "/results/error" );
361407 if (nodeList .getLength () > 0 ) {
362408 String errorMessage = XPathUtil .string (response , "/results/error/message" );
@@ -371,6 +417,7 @@ void verifyResponse(Document response) throws AruException, XPathExpressionExcep
371417 logger .throwing (error );
372418 throw error ;
373419 }
420+ return response ;
374421 }
375422
376423 /**
@@ -393,13 +440,14 @@ public List<AruPatch> getPatches(String bugNumber, String userId, String passwor
393440
394441 String url = String .format (BUG_SEARCH_URL , bugNumber );
395442 logger .info ("IMG-0063" , bugNumber );
396- Document response = HttpUtil .getXMLContent (url , userId , password );
397443 try {
398- verifyResponse (response );
444+ Document response = retry (() -> getAndVerify (url , userId , password ));
445+ return AruPatch .getPatches (response );
399446 } catch (NoPatchesFoundException patchEx ) {
400447 throw new NoPatchesFoundException (Utils .getMessage ("IMG-0086" , bugNumber ), patchEx );
448+ } catch (RetryFailedException retryEx ) {
449+ throw new AruException (Utils .getMessage ("IMG-0110" , retryEx ));
401450 }
402- return AruPatch .getPatches (response );
403451 }
404452
405453 /**
@@ -426,13 +474,39 @@ public String downloadAruPatch(AruPatch aruPatch, String targetDir, String usern
426474 .socketTimeout (30000 ))
427475 .saveContent (new File (filename ));
428476 } 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 ());
431478 logger .severe (message );
432479 throw new IOException (message , ex );
433480 }
434481 logger .exiting (filename );
435482 return filename ;
436483 }
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+ }
437511}
438512
0 commit comments