Skip to content

Commit 57b8227

Browse files
committed
Remove Jackson dependency
Assisted-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 77eb68d commit 57b8227

22 files changed

Lines changed: 1743 additions & 165 deletions

File tree

exporters/common/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ plugins {
77

88
description = "OpenTelemetry Exporter Common"
99
otelJava.moduleName.set("io.opentelemetry.exporter.internal")
10-
otelJava.osgiOptionalPackages.set(listOf("com.fasterxml.jackson.core", "com.google.common.io", "io.opentelemetry.api.incubator.config", "io.opentelemetry.sdk.autoconfigure.spi"))
10+
otelJava.osgiOptionalPackages.set(listOf("com.google.common.io", "io.opentelemetry.api.incubator.config", "io.opentelemetry.sdk.autoconfigure.spi"))
1111
// sun.misc, io.grpc, and org.jspecify are not OSGi bundles and have no package versioning; must use unversioned optional.
1212
otelJava.osgiUnversionedOptionalPackages.set(listOf("sun.misc", "io.grpc", "org.jspecify.annotations"))
1313
// This bundle's exporters load sender implementations via SPI.
@@ -71,13 +71,13 @@ dependencies {
7171

7272
// We include helpers shared by gRPC exporters but do not want to impose these
7373
// dependency on all of our consumers.
74-
compileOnly("com.fasterxml.jackson.core:jackson-core")
7574
// sun.misc.Unsafe from the JDK isn't found by the compiler, we provide our own trimmed down
7675
// version that we can compile against.
7776
compileOnly("io.grpc:grpc-stub")
7877

7978
testImplementation(project(":sdk:common"))
8079
testImplementation(project(":sdk:testing"))
80+
testImplementation("com.fasterxml.jackson.core:jackson-core")
8181

8282
testImplementation("com.google.protobuf:protobuf-java-util")
8383
testImplementation("com.linecorp.armeria:armeria-junit5")
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.internal.marshal;
7+
8+
import java.io.IOException;
9+
import java.io.OutputStream;
10+
import java.nio.charset.StandardCharsets;
11+
12+
final class JsonEscaping {
13+
14+
private static final char[] HEX_DIGITS = {
15+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
16+
};
17+
18+
static void escapeStringTo(StringBuilder sb, String value) {
19+
for (int i = 0; i < value.length(); i++) {
20+
char c = value.charAt(i);
21+
switch (c) {
22+
case '"':
23+
sb.append("\\\"");
24+
break;
25+
case '\\':
26+
sb.append("\\\\");
27+
break;
28+
case '\b':
29+
sb.append("\\b");
30+
break;
31+
case '\f':
32+
sb.append("\\f");
33+
break;
34+
case '\n':
35+
sb.append("\\n");
36+
break;
37+
case '\r':
38+
sb.append("\\r");
39+
break;
40+
case '\t':
41+
sb.append("\\t");
42+
break;
43+
default:
44+
if (c < 0x20) {
45+
sb.append("\\u");
46+
sb.append(HEX_DIGITS[(c >> 12) & 0xF]);
47+
sb.append(HEX_DIGITS[(c >> 8) & 0xF]);
48+
sb.append(HEX_DIGITS[(c >> 4) & 0xF]);
49+
sb.append(HEX_DIGITS[c & 0xF]);
50+
} else {
51+
sb.append(c);
52+
}
53+
}
54+
}
55+
}
56+
57+
static void escapeStringTo(byte[] buf, int[] posRef, OutputStream out, String value)
58+
throws IOException {
59+
for (int i = 0; i < value.length(); i++) {
60+
char c = value.charAt(i);
61+
String escape = null;
62+
switch (c) {
63+
case '"':
64+
escape = "\\\"";
65+
break;
66+
case '\\':
67+
escape = "\\\\";
68+
break;
69+
case '\b':
70+
escape = "\\b";
71+
break;
72+
case '\f':
73+
escape = "\\f";
74+
break;
75+
case '\n':
76+
escape = "\\n";
77+
break;
78+
case '\r':
79+
escape = "\\r";
80+
break;
81+
case '\t':
82+
escape = "\\t";
83+
break;
84+
default:
85+
if (c < 0x20) {
86+
escape =
87+
"\\u"
88+
+ HEX_DIGITS[(c >> 12) & 0xF]
89+
+ HEX_DIGITS[(c >> 8) & 0xF]
90+
+ HEX_DIGITS[(c >> 4) & 0xF]
91+
+ HEX_DIGITS[c & 0xF];
92+
}
93+
}
94+
if (escape != null) {
95+
writeAscii(buf, posRef, out, escape);
96+
} else {
97+
// Non-escape character: find the run of non-escape chars and write them as a UTF-8 chunk
98+
int start = i;
99+
while (i + 1 < value.length()) {
100+
char next = value.charAt(i + 1);
101+
if (next == '"' || next == '\\' || next < 0x20) {
102+
break;
103+
}
104+
i++;
105+
}
106+
writeUtf8(buf, posRef, out, value, start, i + 1);
107+
}
108+
}
109+
}
110+
111+
private static void writeAscii(byte[] buf, int[] posRef, OutputStream out, String ascii)
112+
throws IOException {
113+
int pos = posRef[0];
114+
int len = ascii.length();
115+
if (pos + len > buf.length) {
116+
out.write(buf, 0, pos);
117+
pos = 0;
118+
}
119+
for (int i = 0; i < len; i++) {
120+
buf[pos++] = (byte) ascii.charAt(i);
121+
}
122+
posRef[0] = pos;
123+
}
124+
125+
private static void writeUtf8(
126+
byte[] buf, int[] posRef, OutputStream out, String value, int start, int end)
127+
throws IOException {
128+
byte[] utf8 = value.substring(start, end).getBytes(StandardCharsets.UTF_8);
129+
int pos = posRef[0];
130+
if (pos + utf8.length > buf.length) {
131+
out.write(buf, 0, pos);
132+
pos = 0;
133+
}
134+
if (utf8.length > buf.length) {
135+
out.write(utf8);
136+
posRef[0] = pos;
137+
return;
138+
}
139+
System.arraycopy(utf8, 0, buf, pos, utf8.length);
140+
posRef[0] = pos + utf8.length;
141+
}
142+
143+
private JsonEscaping() {}
144+
}

0 commit comments

Comments
 (0)