|
5 | 5 |
|
6 | 6 | package io.opentelemetry.agents; |
7 | 7 |
|
8 | | -import static org.joox.JOOX.$; |
9 | | - |
10 | 8 | import java.io.IOException; |
11 | 9 | import java.nio.file.Files; |
12 | 10 | import java.nio.file.Path; |
13 | 11 | import java.nio.file.Paths; |
14 | | -import java.nio.file.StandardOpenOption; |
| 12 | +import java.nio.file.StandardCopyOption; |
15 | 13 | import java.util.Optional; |
16 | | -import java.time.Duration; |
17 | | -import okhttp3.OkHttpClient; |
18 | | -import okhttp3.Request; |
19 | | -import okhttp3.Response; |
20 | | -import okhttp3.ResponseBody; |
21 | | -import org.joox.Match; |
22 | 14 | import org.slf4j.Logger; |
23 | 15 | import org.slf4j.LoggerFactory; |
24 | | -import org.w3c.dom.Document; |
25 | 16 |
|
26 | 17 | public class LatestAgentSnapshotResolver { |
27 | 18 |
|
28 | 19 | private static final Logger logger = LoggerFactory.getLogger(LatestAgentSnapshotResolver.class); |
29 | 20 |
|
30 | | - static final String BASE_URL = |
31 | | - "https://oss.sonatype.org/content/repositories/snapshots/io/opentelemetry/javaagent/opentelemetry-javaagent"; |
32 | | - static final String LATEST_SNAPSHOT_META = BASE_URL + "/maven-metadata.xml"; |
33 | | - |
34 | | - private static final OkHttpClient client = new OkHttpClient.Builder() |
35 | | - .connectTimeout(Duration.ofMinutes(1)) |
36 | | - .readTimeout(Duration.ofMinutes(1)) |
37 | | - .build(); |
38 | | - |
39 | 21 | Optional<Path> resolve() throws IOException { |
40 | | - String version = fetchLatestSnapshotVersion(); |
41 | | - logger.info("Latest snapshot version is {}", version); |
42 | | - String latestFilename = fetchLatestFilename(version); |
43 | | - String url = BASE_URL + "/" + version + "/" + latestFilename; |
44 | | - byte[] jarBytes = fetchBodyBytesFrom(url); |
45 | | - Path path = Paths.get(".", "opentelemetry-javaagent-SNAPSHOT.jar"); |
46 | | - Files.write( |
47 | | - path, |
48 | | - jarBytes, |
49 | | - StandardOpenOption.CREATE, |
50 | | - StandardOpenOption.WRITE, |
51 | | - StandardOpenOption.TRUNCATE_EXISTING); |
52 | | - return Optional.of(path); |
53 | | - } |
| 22 | + Path localJavaagentPath = findLocalJavaagentJar(); |
54 | 23 |
|
55 | | - private String fetchLatestFilename(String version) throws IOException { |
56 | | - String url = BASE_URL + "/" + version + "/maven-metadata.xml"; |
57 | | - String body = fetchBodyStringFrom(url); |
58 | | - Document document = $(body).document(); |
59 | | - Match match = $(document).xpath("/metadata/versioning/snapshotVersions/snapshotVersion"); |
60 | | - return match.get().stream() |
61 | | - .filter( |
62 | | - elem -> { |
63 | | - Match classifierMatch = $(elem).child("classifier"); |
64 | | - String classifier = classifierMatch == null ? null : classifierMatch.content(); |
65 | | - String extension = $(elem).child("extension").content(); |
66 | | - return "jar".equals(extension) && (classifier == null); |
67 | | - }) |
68 | | - .map(e -> $(e).child("value").content()) |
69 | | - .findFirst() |
70 | | - .map(value -> "opentelemetry-javaagent-" + value + ".jar") |
71 | | - .orElseThrow(); |
72 | | - } |
| 24 | + if (localJavaagentPath == null || !Files.exists(localJavaagentPath)) { |
| 25 | + throw new IOException("Local javaagent JAR not found. Please run './gradlew :javaagent:assemble' from the project root first."); |
| 26 | + } |
73 | 27 |
|
74 | | - private String fetchLatestSnapshotVersion() throws IOException { |
75 | | - String url = LATEST_SNAPSHOT_META; |
76 | | - String body = fetchBodyStringFrom(url); |
77 | | - Document document = $(body).document(); |
78 | | - Match match = $(document).xpath("/metadata/versioning/latest"); |
79 | | - return match.get(0).getTextContent(); |
80 | | - } |
| 28 | + logger.info("Using local javaagent JAR: {}", localJavaagentPath); |
81 | 29 |
|
82 | | - private String fetchBodyStringFrom(String url) throws IOException { |
83 | | - return fetchBodyFrom(url).string(); |
| 30 | + Path targetPath = Paths.get(".", "opentelemetry-javaagent-SNAPSHOT.jar"); |
| 31 | + Files.copy(localJavaagentPath, targetPath, StandardCopyOption.REPLACE_EXISTING); |
| 32 | + return Optional.of(targetPath); |
84 | 33 | } |
85 | 34 |
|
86 | | - private byte[] fetchBodyBytesFrom(String url) throws IOException { |
87 | | - return fetchBodyFrom(url).bytes(); |
88 | | - } |
| 35 | + private Path findLocalJavaagentJar() { |
| 36 | + Path relativePath = Paths.get("../javaagent/build/libs").toAbsolutePath().normalize(); |
| 37 | + Path javaagentJar = findJavaagentJarInDirectory(relativePath); |
89 | 38 |
|
90 | | - // The sonatype repository can be very unreliable, so we retry a few times |
91 | | - private ResponseBody fetchBodyFrom(String url) throws IOException { |
92 | | - Request request = new Request.Builder().url(url).build(); |
93 | | - IOException lastException = null; |
| 39 | + if (javaagentJar != null) { |
| 40 | + return javaagentJar; |
| 41 | + } |
94 | 42 |
|
95 | | - for (int attempt = 0; attempt < 3; attempt++) { |
96 | | - try { |
97 | | - try (Response response = client.newCall(request).execute()) { |
98 | | - if (!response.isSuccessful()) { |
99 | | - throw new IOException("Unexpected HTTP code " + response.code() + " for " + url); |
100 | | - } |
101 | | - ResponseBody body = response.body(); |
102 | | - if (body != null) { |
103 | | - byte[] data = body.bytes(); |
104 | | - return ResponseBody.create(data, body.contentType()); |
105 | | - } else { |
106 | | - throw new IOException("Response body is null"); |
107 | | - } |
108 | | - } |
109 | | - } catch (IOException e) { |
110 | | - lastException = e; |
111 | | - if (attempt < 2) { |
112 | | - logger.warn("Attempt {} to fetch {} failed: {}. Retrying...", attempt + 1, url, e.getMessage()); |
| 43 | + // If not found, try from the project root (in case running from different location) |
| 44 | + Path projectRoot = Paths.get(".").toAbsolutePath().normalize(); |
| 45 | + while (projectRoot.getParent() != null) { |
| 46 | + Path gradlewFile = projectRoot.resolve("gradlew"); |
| 47 | + if (Files.exists(gradlewFile)) { |
| 48 | + // Found the project root |
| 49 | + Path javaagentLibsDir = projectRoot.resolve("javaagent/build/libs"); |
| 50 | + javaagentJar = findJavaagentJarInDirectory(javaagentLibsDir); |
| 51 | + if (javaagentJar != null) { |
| 52 | + return javaagentJar; |
113 | 53 | } |
| 54 | + break; |
114 | 55 | } |
| 56 | + projectRoot = projectRoot.getParent(); |
| 57 | + } |
| 58 | + |
| 59 | + return null; |
| 60 | + } |
| 61 | + |
| 62 | + private Path findJavaagentJarInDirectory(Path directory) { |
| 63 | + if (!Files.exists(directory) || !Files.isDirectory(directory)) { |
| 64 | + return null; |
| 65 | + } |
| 66 | + |
| 67 | + try { |
| 68 | + return Files.list(directory) |
| 69 | + .filter(path -> { |
| 70 | + String filename = path.getFileName().toString(); |
| 71 | + // Look for the main jar: opentelemetry-javaagent-VERSION.jar (no additional suffixes) |
| 72 | + return filename.startsWith("opentelemetry-javaagent-") && |
| 73 | + filename.endsWith(".jar") && |
| 74 | + !filename.matches(".*-[a-z]+\\.jar"); // excludes anything with -word.jar pattern |
| 75 | + }) |
| 76 | + .findFirst() |
| 77 | + .orElse(null); |
| 78 | + } catch (IOException e) { |
| 79 | + logger.warn("Failed to list files in directory {}: {}", directory, e.getMessage()); |
| 80 | + return null; |
115 | 81 | } |
116 | | - throw lastException; |
117 | 82 | } |
118 | 83 | } |
119 | 84 |
|
0 commit comments