3333import java .util .HashMap ;
3434import java .util .List ;
3535import java .util .Map ;
36- import java .util .Scanner ;
3736import java .util .concurrent .Callable ;
3837import java .util .concurrent .CompletableFuture ;
38+ import java .util .stream .Collectors ;
3939
4040import org .apache .log4j .Logger ;
41- import org .apache .commons .text .StringSubstitutor ;
4241import org .apache .log4j .BasicConfigurator ;
4342
4443import org .apache .commons .io .filefilter .WildcardFileFilter ;
@@ -148,6 +147,7 @@ public GitHubFolderDownloader(String accessToken) {
148147 }
149148
150149 public void downloadFolder (String owner , String repo , String ref , String path , Path destPath ) throws IOException , URISyntaxException {
150+ List <CompletableFuture <Void >> futures = new ArrayList <>();
151151
152152 // Create destination directory if it doesn't exist
153153 LOGGER .debug (
@@ -165,24 +165,33 @@ public void downloadFolder(String owner, String repo, String ref, String path, P
165165 );
166166
167167 for (GitHubContent item : contents ) {
168- String type = item .getType ();
169- String itemPath = item .getPath ();
170- String itemName = item .getName ();
171-
172- if ("file" .equals (type )) {
173- // Download file
174- String downloadUrl = item .getDownloadUrl ();
175- if (downloadUrl == null ) {
176- // For some refs, we need to fetch the raw content differently
177- downloadUrl = String .format ("https://raw.githubusercontent.com/%s/%s/%s/%s" ,
178- owner , repo , ref , itemPath );
168+ futures .add (CompletableFuture .runAsync (() -> {
169+ try {
170+ String type = item .getType ();
171+ String itemPath = item .getPath ();
172+ String itemName = item .getName ();
173+
174+ if ("file" .equals (type )) {
175+ // Download file
176+ String downloadUrl = item .getDownloadUrl ();
177+ if (downloadUrl == null ) {
178+ // For some refs, we need to fetch the raw content differently
179+ downloadUrl = String .format ("https://raw.githubusercontent.com/%s/%s/%s/%s" ,
180+ owner , repo , ref , itemPath );
181+ }
182+
183+ downloadFile (downloadUrl , destPath .resolve (itemName ));
184+ } else if ("dir" .equals (type )) {
185+ // Recursively download subdirectory
186+ downloadFolder (owner , repo , ref , itemPath , destPath .resolve (itemName ));
187+ }
188+ } catch (Exception e ) {
189+ throw new RuntimeException (e );
179190 }
180- downloadFile (downloadUrl , destPath .resolve (itemName ));
181- } else if ("dir" .equals (type )) {
182- // Recursively download subdirectory
183- downloadFolder (owner , repo , ref , itemPath , destPath .resolve (itemName ));
184- }
191+ }));
185192 }
193+
194+ CompletableFuture .allOf (futures .toArray (new CompletableFuture [0 ])).join ();
186195 }
187196
188197 private String makeApiRequest (String apiUrl ) throws IOException , URISyntaxException {
@@ -457,6 +466,12 @@ public Integer call() throws Exception {
457466 ObjectMapper objectMapper = new ObjectMapper ();
458467 List <Source > sources = objectMapper .readValue (bufferedReader , new TypeReference <List <Source >>(){});
459468
469+ Map <Source , List <CompletableFuture <Void >>> sourceFutures = sources .stream ()
470+ .collect (Collectors .toMap (
471+ source -> source ,
472+ source -> new ArrayList <>()
473+ ));
474+
460475 this .docsRootPath = Paths .get (docsRoot );
461476 this .templateDirPath = Paths .get (templateDir );
462477
@@ -465,18 +480,41 @@ public Integer call() throws Exception {
465480 for (Source source : sources ) {
466481 LOGGER .info ("Found source: " + source );
467482
468- //Download the dev branch
469- processSource (ghFolderDownloader , source , source .getDevelopmentBranch (), false );
483+ sourceFutures .get (source ).add (CompletableFuture .runAsync (() -> {
484+ try {
485+ //Download the dev branch
486+ processSource (ghFolderDownloader , source , source .getDevelopmentBranch (), false );
487+ } catch (Exception e ) {
488+ throw new RuntimeException (e );
489+ }
490+ }));
470491
471492 //Download each of the tags
472493 for (String tag : source .getTags ()) {
473- processSource (ghFolderDownloader , source , tag , true );
494+ sourceFutures .get (source ).add (CompletableFuture .runAsync (() -> {
495+ try {
496+ processSource (ghFolderDownloader , source , tag , true );
497+ } catch (Exception e ) {
498+ throw new RuntimeException (e );
499+ }
500+ }));
474501 }
475502
476- // Create the contents page for this source
477- createSourceContentsPage (source );
503+ // Wait for the development branch and tags of this source to finish processing, then generate a contents page
504+ CompletableFuture <Void > branchAndTagFutures = CompletableFuture .allOf (sourceFutures .get (source ).toArray (new CompletableFuture [0 ]));
505+ sourceFutures .get (source ).add (branchAndTagFutures .thenRun (() -> {
506+ try {
507+ // Create the contents page for this source
508+ createSourceContentsPage (source );
509+ } catch (IOException e ) {
510+ throw new RuntimeException (e );
511+ }
512+ }));
478513 }
479514
515+ // Wait for everything to finish processing and generating
516+ CompletableFuture .allOf (sourceFutures .values ().stream ().flatMap (List ::stream ).toArray (CompletableFuture []::new )).join ();
517+
480518 return 0 ;
481519 }
482520}
0 commit comments