diff --git a/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/DependencyInfoCheck.java b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/DependencyInfoCheck.java index b205804c06..fdf61936cf 100644 --- a/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/DependencyInfoCheck.java +++ b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/DependencyInfoCheck.java @@ -1,6 +1,9 @@ package com.google.cloud; +import com.google.cloud.model.DependencyResponse; +import com.google.cloud.model.MavenCoordinate; import com.google.cloud.model.PackageInfo; +import com.google.cloud.model.Relation; import com.google.gson.Gson; import java.io.IOException; import java.net.URI; @@ -9,42 +12,101 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Queue; import java.util.stream.Collectors; public class DependencyInfoCheck { + private final static HttpClient client = HttpClient.newHttpClient(); public final static Gson gson = new Gson(); + private final static String packageInfoUrlBase = "https://api.deps.dev/v3alpha/query?versionKey.system=maven&versionKey.name=%s:%s&versionKey.version=%s"; + + private final static String dependencyUrlBase = "https://api.deps.dev/v3alpha/systems/maven/packages/%s:%s/versions/%s:dependencies"; + private DependencyInfoCheck() { } - public static List licenseCheck(String groupId, String artifactId, String version) + + public static Map> infoCheck(String groupId, String artifactId, String version) throws URISyntaxException, IOException, InterruptedException { + MavenCoordinate mavenCoordinate = new MavenCoordinate(groupId, artifactId, version); + Queue queue = new ArrayDeque<>(); + queue.offer(mavenCoordinate); + List dependencies = new ArrayList<>(); + while (!queue.isEmpty()) { + MavenCoordinate coordinate = queue.poll(); + dependencies.add(coordinate); + List directDependencies = getDirectDependencies(coordinate); + directDependencies.forEach(queue::offer); + } + + Map> res = new HashMap<>(); + for (MavenCoordinate coordinate : dependencies) { + PackageInfo packageInfo = getPackageInfo(coordinate); + List licenses = packageInfo + .getVersions() + .stream() + .flatMap(v -> v.getLicenses().stream()) + .collect(Collectors.toList()); + res.put(coordinate.toString(), licenses); + } + + return res; + } + + private static List getDirectDependencies(MavenCoordinate mavenCoordinate) + throws URISyntaxException, IOException, InterruptedException { + HttpResponse response = getResponse( + getDependencyUrl( + mavenCoordinate.getGroupId(), + mavenCoordinate.getArtifactId(), + mavenCoordinate.getVersion() + ) + ); + DependencyResponse dependencyResponse = gson.fromJson(response.body(), + DependencyResponse.class); + return dependencyResponse + .getNodes() + .stream() + .filter(node -> node.getRelation().equals(Relation.DIRECT)) + .map(node -> node.getVersionKey().toMavenCoordinate()) + .collect(Collectors.toList()); + } + + private static PackageInfo getPackageInfo(MavenCoordinate mavenCoordinate) + throws URISyntaxException, IOException, InterruptedException { + HttpResponse response = getResponse( + getPackageInfoUrl( + mavenCoordinate.getGroupId(), + mavenCoordinate.getArtifactId(), + mavenCoordinate.getVersion() + ) + ); + return gson.fromJson(response.body(), PackageInfo.class); + } + + private static String getPackageInfoUrl(String groupId, String artifactId, String version) { + return String.format(packageInfoUrlBase, groupId, artifactId, version); + } - String urlBase = "https://api.deps.dev/v3alpha/query?versionKey.system=maven&versionKey.name="; - HttpRequest request = HttpRequest.newBuilder().uri( - new URI(String.format("%s%s:%s&versionKey.version=%s", urlBase, groupId, artifactId, version)) - ).GET().build(); - HttpResponse response = client.send(request, BodyHandlers.ofString()); - PackageInfo packageInfo = gson.fromJson(response.body(), PackageInfo.class); - return packageInfo.getVersions().stream().flatMap(v -> v.getLicenses().stream()).collect( - Collectors.toList()); + private static String getDependencyUrl(String groupId, String artifactId, String version) { + return String.format(dependencyUrlBase, groupId, artifactId, version); } - private static List getDependencies(String groupId, String artifactId, String version) + private static HttpResponse getResponse(String endpoint) throws URISyntaxException, IOException, InterruptedException { - String urlBase = "https://api.deps.dev/v3alpha/systems/maven/packages"; - HttpRequest request = HttpRequest.newBuilder().uri( - new URI(String.format("%s/%s:%s/versions/%s:dependencies", urlBase, groupId, artifactId, version)) - ).GET().build(); - HttpResponse response = client.send(request, BodyHandlers.ofString()); - return null; + HttpRequest request = HttpRequest.newBuilder().uri(new URI(endpoint)).GET().build(); + return client.send(request, BodyHandlers.ofString()); } public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException { - System.out.println(licenseCheck("io.opentelemetry", "opentelemetry-api", "1.35.0")); - System.out.println(getDependencies("io.opentelemetry", "opentelemetry-api", "1.35.0")); + System.out.println(infoCheck("io.opentelemetry", "opentelemetry-api", "1.35.0")); } } diff --git a/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/DependencyResponse.java b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/DependencyResponse.java new file mode 100644 index 0000000000..7ee317ce92 --- /dev/null +++ b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/DependencyResponse.java @@ -0,0 +1,15 @@ +package com.google.cloud.model; + +import java.util.List; + +public class DependencyResponse { + private List nodes; + + public DependencyResponse(List nodes) { + this.nodes = nodes; + } + + public List getNodes() { + return nodes; + } +} diff --git a/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/MavenCoordinate.java b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/MavenCoordinate.java new file mode 100644 index 0000000000..79744f7e77 --- /dev/null +++ b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/MavenCoordinate.java @@ -0,0 +1,30 @@ +package com.google.cloud.model; + +public class MavenCoordinate { + private final String groupId; + private final String artifactId; + private final String version; + + public MavenCoordinate(String groupId, String artifactId, String version) { + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + } + + public String getGroupId() { + return groupId; + } + + public String getArtifactId() { + return artifactId; + } + + public String getVersion() { + return version; + } + + @Override + public String toString() { + return String.format("%s:%s:%s", groupId, artifactId, version); + } +} diff --git a/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/Node.java b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/Node.java new file mode 100644 index 0000000000..972a4ec43c --- /dev/null +++ b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/Node.java @@ -0,0 +1,19 @@ +package com.google.cloud.model; + +public class Node { + private final VersionKey versionKey; + private final Relation relation; + + public Node(VersionKey versionKey, Relation relation) { + this.versionKey = versionKey; + this.relation = relation; + } + + public VersionKey getVersionKey() { + return versionKey; + } + + public Relation getRelation() { + return relation; + } +} diff --git a/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/PackageInfo.java b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/PackageInfo.java index 54020af738..a77a96366c 100644 --- a/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/PackageInfo.java +++ b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/PackageInfo.java @@ -1,6 +1,7 @@ package com.google.cloud.model; import java.util.List; +import java.util.stream.Collectors; public class PackageInfo { private final List versions; @@ -12,4 +13,11 @@ public PackageInfo(List versions) { public List getVersions() { return versions; } + + public List toMavenCoordinates() { + return getVersions() + .stream() + .map(version -> version.getVersionKey().toMavenCoordinate()) + .collect(Collectors.toList()); + } } diff --git a/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/Relation.java b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/Relation.java new file mode 100644 index 0000000000..09aff06b86 --- /dev/null +++ b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/Relation.java @@ -0,0 +1,6 @@ +package com.google.cloud.model; + +public enum Relation { + SELF, + DIRECT +} diff --git a/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/Version.java b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/Version.java index 14d24a43cd..96c993553a 100644 --- a/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/Version.java +++ b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/Version.java @@ -3,13 +3,19 @@ import java.util.List; public class Version { + private final VersionKey versionKey; private final List licenses; - public Version(List licenses) { + public Version(VersionKey versionKey, List licenses) { + this.versionKey = versionKey; this.licenses = licenses; } public List getLicenses() { return licenses; } + + public VersionKey getVersionKey() { + return versionKey; + } } diff --git a/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/VersionKey.java b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/VersionKey.java new file mode 100644 index 0000000000..91d853816e --- /dev/null +++ b/java-shared-dependencies/unmanaged-dependency-check/src/main/java/com/google/cloud/model/VersionKey.java @@ -0,0 +1,20 @@ +package com.google.cloud.model; + +import org.apache.bcel.generic.NEW; + +public class VersionKey { + private final String system; + private final String name; + private final String version; + + public VersionKey(String system, String name, String version) { + this.system = system; + this.name = name; + this.version = version; + } + + public MavenCoordinate toMavenCoordinate() { + String[] splits = name.split(":"); + return new MavenCoordinate(splits[0], splits[1], version); + } +}