@@ -281,6 +281,7 @@ class JavaJarServer(SubprocessServer):
281281
282282 MAVEN_CENTRAL_REPOSITORY = 'https://repo.maven.apache.org/maven2'
283283 MAVEN_STAGING_REPOSITORY = 'https://repository.apache.org/content/groups/staging' # pylint: disable=line-too-long
284+ GOOGLE_MAVEN_MIRROR = 'https://maven-central.storage-download.googleapis.com/maven2' # pylint: disable=line-too-long
284285 BEAM_GROUP_ID = 'org.apache.beam'
285286 JAR_CACHE = os .path .expanduser ("~/.apache_beam/cache/jars" )
286287
@@ -419,6 +420,32 @@ def path_to_beam_jar(
419420 return cls .path_to_maven_jar (
420421 artifact_id , cls .BEAM_GROUP_ID , version , maven_repo , appendix = appendix )
421422
423+ @classmethod
424+ def _download_jar_to_cache (
425+ cls , download_url , cached_jar_path , user_agent = None ):
426+ """Downloads a jar from the given URL to the specified cache path.
427+
428+ Args:
429+ download_url (str): The URL to download from.
430+ cached_jar_path (str): The local path where the jar should be cached.
431+ user_agent (str): The user agent to use when downloading.
432+ """
433+ try :
434+ url_read = FileSystems .open (download_url )
435+ except ValueError :
436+ if user_agent is None :
437+ user_agent = cls ._DEFAULT_USER_AGENT
438+ url_request = Request (download_url , headers = {'User-Agent' : user_agent })
439+ url_read = urlopen (url_request )
440+ with open (cached_jar_path + '.tmp' , 'wb' ) as jar_write :
441+ shutil .copyfileobj (url_read , jar_write , length = 1 << 20 )
442+ try :
443+ os .rename (cached_jar_path + '.tmp' , cached_jar_path )
444+ except FileNotFoundError :
445+ # A race when multiple programs run in parallel and the cached_jar
446+ # is already moved. Safe to ignore.
447+ pass
448+
422449 @classmethod
423450 def local_jar (cls , url , cache_dir = None , user_agent = None ):
424451 """Returns a local path to the given jar, downloading it if necessary.
@@ -449,25 +476,31 @@ def local_jar(cls, url, cache_dir=None, user_agent=None):
449476 os .makedirs (cache_dir )
450477 # TODO: Clean up this cache according to some policy.
451478 try :
452- try :
453- url_read = FileSystems .open (url )
454- except ValueError :
455- if user_agent is None :
456- user_agent = cls ._DEFAULT_USER_AGENT
457- url_request = Request (url , headers = {'User-Agent' : user_agent })
458- url_read = urlopen (url_request )
459- with open (cached_jar + '.tmp' , 'wb' ) as jar_write :
460- shutil .copyfileobj (url_read , jar_write , length = 1 << 20 )
461- try :
462- os .rename (cached_jar + '.tmp' , cached_jar )
463- except FileNotFoundError :
464- # A race when multiple programs run in parallel and the cached_jar
465- # is already moved. Safe to ignore.
466- pass
479+ cls ._download_jar_to_cache (url , cached_jar , user_agent )
467480 except URLError as e :
468- raise RuntimeError (
469- f'Unable to fetch remote job server jar at { url } : { e } . If no '
470- f'Internet access at runtime, stage the jar at { cached_jar } ' )
481+ # Try Google Maven mirror as fallback if the original URL is from
482+ # Maven Central
483+ if url .startswith (cls .MAVEN_CENTRAL_REPOSITORY ):
484+ fallback_url = url .replace (
485+ cls .MAVEN_CENTRAL_REPOSITORY , cls .GOOGLE_MAVEN_MIRROR )
486+ _LOGGER .info (
487+ 'Trying Google Maven mirror fallback: %s' % fallback_url )
488+ try :
489+ cls ._download_jar_to_cache (fallback_url , cached_jar , user_agent )
490+ _LOGGER .info (
491+ 'Successfully downloaded from Google Maven mirror: %s' %
492+ fallback_url )
493+ except URLError as fallback_e :
494+ raise RuntimeError (
495+ f'Unable to fetch remote job server jar at { url } : { e } . '
496+ f'Also failed to fetch from Google Maven mirror at '
497+ f'{ fallback_url } : { fallback_e } . '
498+ f'If no Internet access at runtime, stage the jar at '
499+ f'{ cached_jar } ' )
500+ else :
501+ raise RuntimeError (
502+ f'Unable to fetch remote job server jar at { url } : { e } . If no '
503+ f'Internet access at runtime, stage the jar at { cached_jar } ' )
471504 return cached_jar
472505
473506 @classmethod
0 commit comments