# Copyright 2024 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""The fetch.py and install.py helpers for a 3pp Maven module."""
import os
import pathlib
import re
import shutil
import subprocess
import urllib.request
import common
APACHE_MAVEN_URL = 'https://repo.maven.apache.org/maven2'
_POM_TEMPLATE = """\
4.0.0
group
artifact
1
{group_id}
{artifact_id}
{version}
runtime
maven-assembly-plugin
3.3.0
jar-with-dependencies
package
single
placeholder_id
placeholder_name
{maven_url}
"""
def _detect_latest(maven_url, package):
metadata_url = '{}/{}/maven-metadata.xml'.format(
maven_url,
package.replace('.', '/').replace(':', '/'))
metadata = urllib.request.urlopen(metadata_url).read().decode('utf-8')
# Do not parse xml with the Python included parser since it is susceptible
# to maliciously crafted xmls. Only use regular expression parsing to be
# safe. RE should be enough to handle what we need to extract.
# TODO(agrieve): Use 'if m := ..." once docker image updates from Python 3.6.
m = re.search('([^<]+)', metadata)
if m:
latest = m.group(1)
else:
# If no latest info was found just hope the versions are sorted and the
# last one is the latest (as is commonly the case).
latest = re.findall('([^<]+)', metadata)[-1]
return latest
def _install(output_prefix,
deps_prefix,
maven_url,
package,
version,
jar_name=None):
# Runs in a docker container.
group_id, artifact_id = package.split(':')
if not jar_name:
jar_name = f'{artifact_id}.jar'
pathlib.Path('pom.xml').write_text(
_POM_TEMPLATE.format(version=version,
group_id=group_id,
artifact_id=artifact_id,
maven_url=maven_url))
# Set up JAVA_HOME for the mvn command to find the JDK.
env = os.environ.copy()
env['JAVA_HOME'] = common.path_within_checkout('third_party/jdk/current')
# Ensure that mvn works and the environment is set up correctly.
subprocess.run(['mvn', '-v'], check=True, env=env)
# Build the jar file, explicitly specify -f to reduce sources of error.
subprocess.run(['mvn', 'clean', 'assembly:single', '-f', 'pom.xml'],
check=True,
env=env)
# Move and rename output to the upload directory. Moving only the jar avoids
# polluting the output directory with maven intermediate outputs.
shutil.move('target/artifact-1-jar-with-dependencies.jar',
os.path.join(output_prefix, jar_name))
def main(*,
package,
jar_name=None,
maven_url='https://dl.google.com/android/maven2',
version_override=None):
"""3pp entry point for fetch.py.
Args:
package: E.g.: some.package:some-thing
jar_name: Name of .jar. Defaults to |some-thing|.jar
maven_url: URL of Maven repository.
version_override: Use this version instead of the latest one.
"""
def do_latest():
return version_override or _detect_latest(maven_url, package)
def do_install(args):
_install(args.output_prefix, args.deps_prefix, maven_url, package,
args.version, jar_name)
common.main(do_latest=do_latest,
do_install=do_install,
runtime_deps=['//third_party/jdk/current'])