diff --git a/adapter/avro/pom.xml b/adapter/avro/pom.xml
index 827d19f2a2..4cb437703b 100644
--- a/adapter/avro/pom.xml
+++ b/adapter/avro/pom.xml
@@ -23,7 +23,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
../../pom.xml
diff --git a/adapter/jdbc/pom.xml b/adapter/jdbc/pom.xml
index 2f621d7a05..a5baf315d4 100644
--- a/adapter/jdbc/pom.xml
+++ b/adapter/jdbc/pom.xml
@@ -23,7 +23,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
../../pom.xml
diff --git a/adapter/orc/pom.xml b/adapter/orc/pom.xml
index c96ab36119..0821b03523 100644
--- a/adapter/orc/pom.xml
+++ b/adapter/orc/pom.xml
@@ -23,7 +23,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
../../pom.xml
diff --git a/algorithm/pom.xml b/algorithm/pom.xml
index 898c2605b6..9b6d95c37a 100644
--- a/algorithm/pom.xml
+++ b/algorithm/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-algorithm
Arrow Algorithms
diff --git a/arrow-variant/pom.xml b/arrow-variant/pom.xml
index 3a842178a4..b4d5608b54 100644
--- a/arrow-variant/pom.xml
+++ b/arrow-variant/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-variant
Arrow Variant
diff --git a/bom/pom.xml b/bom/pom.xml
index 0de43a1217..5af49b1ef4 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -29,7 +29,7 @@ under the License.
org.apache.arrow
arrow-bom
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
pom
Arrow Bill of Materials
diff --git a/c/pom.xml b/c/pom.xml
index c90b6dc0ef..5d7c50bc1b 100644
--- a/c/pom.xml
+++ b/c/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-c-data
diff --git a/compression/pom.xml b/compression/pom.xml
index 29f8b41788..7d932706dd 100644
--- a/compression/pom.xml
+++ b/compression/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-compression
Arrow Compression
diff --git a/dataset/pom.xml b/dataset/pom.xml
index 1852c6eddc..688229fddf 100644
--- a/dataset/pom.xml
+++ b/dataset/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-dataset
diff --git a/flight/flight-core/pom.xml b/flight/flight-core/pom.xml
index f1d58a0cad..597ac3aaa2 100644
--- a/flight/flight-core/pom.xml
+++ b/flight/flight-core/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-flight
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
flight-core
diff --git a/flight/flight-core/src/main/java/org/apache/arrow/flight/grpc/NettyClientBuilder.java b/flight/flight-core/src/main/java/org/apache/arrow/flight/grpc/NettyClientBuilder.java
index 42cdaac016..d688b26689 100644
--- a/flight/flight-core/src/main/java/org/apache/arrow/flight/grpc/NettyClientBuilder.java
+++ b/flight/flight-core/src/main/java/org/apache/arrow/flight/grpc/NettyClientBuilder.java
@@ -185,6 +185,28 @@ public NettyChannelBuilder build() {
"Scheme is not supported: " + location.getUri().getScheme());
}
+ try {
+ configureChannel(builder);
+ } catch (SSLException e) {
+ throw new RuntimeException(e);
+ }
+ return builder;
+ }
+
+ /**
+ * Build a {@link NettyChannelBuilder} using {@code forTarget()} instead of {@code forAddress()}.
+ *
+ *
This is required for proxy support: only the DNS resolver path ({@code dns:///host:port})
+ * invokes the {@link io.grpc.ProxyDetector}. {@code forAddress()} bypasses it entirely.
+ */
+ public NettyChannelBuilder buildForTarget(String target) throws SSLException {
+ final NettyChannelBuilder builder = NettyChannelBuilder.forTarget(target);
+ configureChannel(builder);
+ return builder;
+ }
+
+ /** Apply TLS and message-size configuration to an already-created {@link NettyChannelBuilder}. */
+ protected void configureChannel(NettyChannelBuilder builder) throws SSLException {
if (this.forceTls || LocationSchemes.GRPC_TLS.equals(location.getUri().getScheme())) {
builder.useTransportSecurity();
@@ -210,11 +232,8 @@ public NettyChannelBuilder build() {
sslContextBuilder.keyManager(this.clientCertificate, this.clientKey);
}
}
- try {
- builder.sslContext(sslContextBuilder.build());
- } catch (SSLException e) {
- throw new RuntimeException(e);
- }
+
+ builder.sslContext(sslContextBuilder.build());
if (this.overrideHostname != null) {
builder.overrideAuthority(this.overrideHostname);
@@ -227,6 +246,5 @@ public NettyChannelBuilder build() {
.maxTraceEvents(MAX_CHANNEL_TRACE_EVENTS)
.maxInboundMessageSize(maxInboundMessageSize)
.maxInboundMetadataSize(maxInboundMessageSize);
- return builder;
}
}
diff --git a/flight/flight-integration-tests/pom.xml b/flight/flight-integration-tests/pom.xml
index f0f10ada43..f525160e8a 100644
--- a/flight/flight-integration-tests/pom.xml
+++ b/flight/flight-integration-tests/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-flight
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
flight-integration-tests
diff --git a/flight/flight-sql-jdbc-core/pom.xml b/flight/flight-sql-jdbc-core/pom.xml
index da00baf32a..4e910eae9a 100644
--- a/flight/flight-sql-jdbc-core/pom.xml
+++ b/flight/flight-sql-jdbc-core/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-flight
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
flight-sql-jdbc-core
diff --git a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowFlightConnection.java b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowFlightConnection.java
index 623c2b81be..c7c6e65d3c 100644
--- a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowFlightConnection.java
+++ b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowFlightConnection.java
@@ -128,6 +128,9 @@ private static ArrowFlightSqlClientHandler createNewClientHandler(
.withConnectTimeout(config.getConnectTimeout())
.withDriverVersion(driverVersion)
.withOAuthConfiguration(config.getOauthConfiguration())
+ .withProxySettings(config.getProxyHost(), config.getProxyPort())
+ .withProxyBypassPattern(config.getProxyBypassPattern())
+ .withProxyDisable(config.getProxyDisable())
.build();
} catch (final SQLException e) {
try {
diff --git a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandler.java b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandler.java
index f0ea284239..60dc7e57e0 100644
--- a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandler.java
+++ b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandler.java
@@ -38,6 +38,7 @@
import org.apache.arrow.driver.jdbc.client.utils.ClientAuthenticationUtils;
import org.apache.arrow.driver.jdbc.client.utils.FlightClientCache;
import org.apache.arrow.driver.jdbc.client.utils.FlightLocationQueue;
+import org.apache.arrow.driver.jdbc.utils.ArrowFlightProxyDetector;
import org.apache.arrow.flight.CallOption;
import org.apache.arrow.flight.CallStatus;
import org.apache.arrow.flight.CloseSessionRequest;
@@ -693,6 +694,14 @@ public static final class Builder {
DriverVersion driverVersion;
+ @VisibleForTesting String proxyHost;
+
+ @VisibleForTesting Integer proxyPort;
+
+ @VisibleForTesting String proxyBypassPattern;
+
+ @VisibleForTesting String proxyDisable;
+
public Builder() {}
/**
@@ -1000,6 +1009,63 @@ public Builder withOAuthConfiguration(final OAuthConfiguration oauthConfig) {
return this;
}
+ /**
+ * Sets the explicit proxy host and port for this connection.
+ *
+ * @param proxyHost the proxy hostname or IP, or {@code null} to clear
+ * @param proxyPort the proxy port, or {@code null} to clear
+ * @return this builder instance
+ */
+ public Builder withProxySettings(
+ @Nullable final String proxyHost, @Nullable final Integer proxyPort) {
+ this.proxyHost = proxyHost;
+ this.proxyPort = proxyPort;
+ return this;
+ }
+
+ /**
+ * Sets the proxy bypass pattern in {@code http.nonProxyHosts} format ({@code |}-separated glob
+ * patterns).
+ *
+ * @param proxyBypassPattern bypass pattern, or {@code null} to clear
+ * @return this builder instance
+ */
+ public Builder withProxyBypassPattern(@Nullable final String proxyBypassPattern) {
+ this.proxyBypassPattern = proxyBypassPattern;
+ return this;
+ }
+
+ /**
+ * Sets the proxy disable flag. Pass {@code "force"} to disable proxy even when system
+ * properties or environment variables configure one.
+ *
+ * @param proxyDisable disable flag value, or {@code null} to clear
+ * @return this builder instance
+ */
+ public Builder withProxyDisable(@Nullable final String proxyDisable) {
+ this.proxyDisable = proxyDisable;
+ return this;
+ }
+
+ private String getDnsTarget() {
+ // Validate port is in valid range (0-65535) before passing to gRPC.
+ // gRPC's DNS resolver validates the port on a background thread, but background thread
+ // exceptions do not propagate to the caller and prevent proper error handling.
+ if (port < 0 || port > 65535) {
+ throw new IllegalArgumentException("port out of range: " + port);
+ }
+ // IPv6 addresses need brackets in the URI authority component
+ String normalizedHost = host.contains(":") && !host.startsWith("[") ? "[" + host + "]" : host;
+ return "dns:///" + normalizedHost + ":" + port;
+ }
+
+ private NettyChannelBuilder getChannelBuilder(final NettyClientBuilder clientBuilder)
+ throws IOException {
+ // forTarget() ensures the DNS resolver is used, which invokes ProxyDetector.
+ // forAddress() bypasses it entirely.
+ return clientBuilder.buildForTarget(getDnsTarget());
+ }
+
public String getCacheKey() {
return getLocation().toString();
}
@@ -1075,9 +1141,12 @@ public ArrowFlightSqlClientHandler build() throws SQLException {
}
}
- NettyChannelBuilder channelBuilder = clientBuilder.build();
+ NettyChannelBuilder channelBuilder = getChannelBuilder(clientBuilder);
channelBuilder.userAgent(userAgent);
+ // Always install — returns null when no proxy is applicable, safe for all connections
+ channelBuilder.proxyDetector(
+ new ArrowFlightProxyDetector(proxyHost, proxyPort, proxyBypassPattern, proxyDisable));
if (connectTimeout != null) {
channelBuilder.withOption(
diff --git a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImpl.java b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImpl.java
index d0ba74dbcc..cf35bb1dd0 100644
--- a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImpl.java
+++ b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightConnectionConfigImpl.java
@@ -182,6 +182,22 @@ public boolean useClientCache() {
return ArrowFlightConnectionProperty.USE_CLIENT_CACHE.getBoolean(properties);
}
+ public String getProxyHost() {
+ return ArrowFlightConnectionProperty.PROXY_HOST.getString(properties);
+ }
+
+ public Integer getProxyPort() {
+ return ArrowFlightConnectionProperty.PROXY_PORT.getInteger(properties);
+ }
+
+ public String getProxyBypassPattern() {
+ return ArrowFlightConnectionProperty.PROXY_BYPASS_PATTERN.getString(properties);
+ }
+
+ public String getProxyDisable() {
+ return ArrowFlightConnectionProperty.PROXY_DISABLE.getString(properties);
+ }
+
/**
* Gets the {@link CallOption}s from this {@link ConnectionConfig}.
*
@@ -284,6 +300,10 @@ public enum ArrowFlightConnectionProperty implements ConnectionProperty {
OAUTH_EXCHANGE_AUDIENCE("oauth.exchange.aud", null, Type.STRING, false),
OAUTH_EXCHANGE_REQUESTED_TOKEN_TYPE(
"oauth.exchange.requestedTokenType", null, Type.STRING, false),
+ PROXY_HOST("proxyHost", null, Type.STRING, false),
+ PROXY_PORT("proxyPort", null, Type.NUMBER, false),
+ PROXY_BYPASS_PATTERN("proxyBypassPattern", null, Type.STRING, false),
+ PROXY_DISABLE("proxyDisable", null, Type.STRING, false),
;
private final String camelName;
diff --git a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightProxyDetector.java b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightProxyDetector.java
new file mode 100644
index 0000000000..baadde45ac
--- /dev/null
+++ b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightProxyDetector.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.arrow.driver.jdbc.utils;
+
+import io.grpc.HttpConnectProxiedSocketAddress;
+import io.grpc.ProxiedSocketAddress;
+import io.grpc.ProxyDetector;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+/**
+ * gRPC {@link ProxyDetector} for Arrow Flight JDBC connections.
+ *
+ *
Resolution priority:
+ *
+ *
+ * - {@code proxyDisable=force} → no proxy (always)
+ *
- Target host matches {@code proxyBypassPattern} → no proxy
+ *
- Explicit {@code proxyHost} + {@code proxyPort} → use that proxy
+ *
- {@link ProxySelector} default → use first non-DIRECT proxy found
+ *
- No proxy
+ *
+ *
+ * {@code proxyBypassPattern} follows the {@code http.nonProxyHosts} format: {@code |}-separated
+ * glob patterns where {@code *} matches any sequence of characters. Matching is case-insensitive.
+ */
+public final class ArrowFlightProxyDetector implements ProxyDetector {
+
+ @Nullable private final String proxyHost;
+ @Nullable private final Integer proxyPort;
+ @Nullable private final String bypassPattern;
+ private final boolean forceDisabled;
+ @Nullable private final ProxySelector proxySelector;
+
+ /** Production constructor — falls back to {@link ProxySelector#getDefault()}. */
+ public ArrowFlightProxyDetector(
+ @Nullable String proxyHost,
+ @Nullable Integer proxyPort,
+ @Nullable String bypassPattern,
+ @Nullable String proxyDisable) {
+ this(proxyHost, proxyPort, bypassPattern, proxyDisable, ProxySelector.getDefault());
+ }
+
+ /** Package-private constructor for testing — accepts an explicit {@link ProxySelector}. */
+ ArrowFlightProxyDetector(
+ @Nullable String proxyHost,
+ @Nullable Integer proxyPort,
+ @Nullable String bypassPattern,
+ @Nullable String proxyDisable,
+ @Nullable ProxySelector proxySelector) {
+ this.proxyHost = proxyHost;
+ this.proxyPort = proxyPort;
+ this.bypassPattern = bypassPattern;
+ this.forceDisabled = "force".equalsIgnoreCase(proxyDisable);
+ this.proxySelector = proxySelector;
+ }
+
+ @Override
+ @Nullable
+ public ProxiedSocketAddress proxyFor(SocketAddress targetAddress) throws IOException {
+ if (forceDisabled) {
+ return null;
+ }
+ InetSocketAddress inetTarget = (InetSocketAddress) targetAddress;
+ if (matchesBypass(inetTarget.getHostString())) {
+ return null;
+ }
+ InetSocketAddress proxyAddr = resolveProxy(inetTarget);
+ if (proxyAddr == null) {
+ return null;
+ }
+ return HttpConnectProxiedSocketAddress.newBuilder()
+ .setTargetAddress(inetTarget)
+ .setProxyAddress(proxyAddr)
+ .build();
+ }
+
+ /**
+ * Returns true if {@code host} matches any pattern in the bypass list.
+ *
+ *
Patterns use {@code http.nonProxyHosts} format: {@code |}-separated globs, where {@code *}
+ * is a wildcard for any sequence of characters.
+ */
+ private boolean matchesBypass(String host) {
+ if (bypassPattern == null || bypassPattern.isEmpty()) {
+ return false;
+ }
+ for (String pattern : bypassPattern.split("\\|")) {
+ String trimmed = pattern.trim();
+ if (trimmed.isEmpty()) {
+ continue;
+ }
+ // Convert glob to regex: escape dots, replace * with .*
+ String regex = trimmed.replace(".", "\\.").replace("*", ".*");
+ if (host.matches("(?i)" + regex)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Resolves which proxy address to use for the given target.
+ *
+ *
Tries explicit proxy first, then {@link ProxySelector}.
+ *
+ * @return resolved proxy address, or {@code null} if no proxy should be used
+ */
+ @Nullable
+ private InetSocketAddress resolveProxy(InetSocketAddress target) {
+ if (proxyHost != null && proxyPort != null) {
+ // new InetSocketAddress(String, int) resolves IP literals without DNS;
+ // for hostnames it attempts DNS — required since HttpConnectProxiedSocketAddress
+ // validates the proxy address is resolved.
+ return new InetSocketAddress(proxyHost, proxyPort);
+ }
+ if (proxySelector == null) {
+ return null;
+ }
+ URI uri;
+ try {
+ uri = new URI("https", null, target.getHostString(), target.getPort(), null, null, null);
+ } catch (URISyntaxException e) {
+ return null;
+ }
+ List proxies = proxySelector.select(uri);
+ for (Proxy proxy : proxies) {
+ if (proxy.type() != Proxy.Type.DIRECT && proxy.address() instanceof InetSocketAddress) {
+ return (InetSocketAddress) proxy.address();
+ }
+ }
+ return null;
+ }
+}
diff --git a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandlerBuilderTest.java b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandlerBuilderTest.java
index a60a71f23d..d857429f1b 100644
--- a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandlerBuilderTest.java
+++ b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/client/ArrowFlightSqlClientHandlerBuilderTest.java
@@ -150,6 +150,12 @@ public void testDefaults() {
assertNull(builder.flightClientCache);
assertNull(builder.connectTimeout);
assertNull(builder.driverVersion);
+
+ // Proxy fields default to null
+ assertNull(builder.proxyHost);
+ assertNull(builder.proxyPort);
+ assertNull(builder.proxyBypassPattern);
+ assertNull(builder.proxyDisable);
}
@Test
@@ -175,4 +181,34 @@ public void testCatalog() {
assertTrue(rootBuilder.catalog.isPresent());
assertEquals(nameWithSpaces, rootBuilder.catalog.get());
}
+
+ @Test
+ public void testProxyFieldsSetViaWithMethods() {
+ final ArrowFlightSqlClientHandler.Builder builder = new ArrowFlightSqlClientHandler.Builder();
+
+ builder.withProxySettings("proxy.corp.net", 8080);
+ assertEquals("proxy.corp.net", builder.proxyHost);
+ assertEquals(Integer.valueOf(8080), builder.proxyPort);
+
+ builder.withProxyBypassPattern("*.internal|localhost");
+ assertEquals("*.internal|localhost", builder.proxyBypassPattern);
+
+ builder.withProxyDisable("force");
+ assertEquals("force", builder.proxyDisable);
+ }
+
+ @Test
+ public void testProxySettingsAcceptNull() {
+ final ArrowFlightSqlClientHandler.Builder builder = new ArrowFlightSqlClientHandler.Builder();
+
+ builder.withProxySettings(null, null);
+ assertNull(builder.proxyHost);
+ assertNull(builder.proxyPort);
+
+ builder.withProxyBypassPattern(null);
+ assertNull(builder.proxyBypassPattern);
+
+ builder.withProxyDisable(null);
+ assertNull(builder.proxyDisable);
+ }
}
diff --git a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightProxyDetectorTest.java b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightProxyDetectorTest.java
new file mode 100644
index 0000000000..088300d093
--- /dev/null
+++ b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/ArrowFlightProxyDetectorTest.java
@@ -0,0 +1,349 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.arrow.driver.jdbc.utils;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import io.grpc.HttpConnectProxiedSocketAddress;
+import io.grpc.ProxiedSocketAddress;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+/** Tests for {@link ArrowFlightProxyDetector}. */
+class ArrowFlightProxyDetectorTest {
+
+ private static final InetSocketAddress TARGET =
+ InetSocketAddress.createUnresolved("dev.iomete.cloud", 443);
+
+ // Use IP literals — InetSocketAddress resolves them without DNS, avoiding test-env failures.
+ // HttpConnectProxiedSocketAddress requires a resolved proxy address.
+ private static final String PROXY_HOST = "192.168.1.1";
+ private static final int PROXY_PORT = 8080;
+
+ @Nested
+ // force disabled nullifies explicit proxy; force disabled overrides ProxySelector
+ class ForceDisabled {
+
+ @Test
+ void givenForceDisabled_whenProxyFor_thenReturnsNull() throws IOException {
+ // GIVEN: force disabled with explicit proxy configured
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(PROXY_HOST, PROXY_PORT, null, "force", noProxySelector());
+
+ // WHEN
+ ProxiedSocketAddress result = sut.proxyFor(TARGET);
+
+ // THEN
+ assertNull(result);
+ }
+
+ @Test
+ void givenForceDisabledAndProxySelectorReturnsProxy_whenProxyFor_thenReturnsNull()
+ throws IOException {
+ // GIVEN: force disabled overrides even ProxySelector
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(
+ null, null, null, "force", proxySelectorReturning("192.168.1.2", 3128));
+
+ // WHEN
+ ProxiedSocketAddress result = sut.proxyFor(TARGET);
+
+ // THEN
+ assertNull(result);
+ }
+ }
+
+ @Nested
+ // returns configured proxy address; preserves target address
+ class ExplicitProxy {
+
+ @Test
+ void givenExplicitProxy_whenProxyFor_thenReturnsConfiguredProxy() throws IOException {
+ // GIVEN: explicit proxyHost + proxyPort
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(PROXY_HOST, PROXY_PORT, null, null, noProxySelector());
+
+ // WHEN
+ ProxiedSocketAddress result = sut.proxyFor(TARGET);
+
+ // THEN
+ assertProxyAddress(result, PROXY_HOST, PROXY_PORT);
+ }
+
+ @Test
+ void givenExplicitProxy_whenProxyFor_thenTargetAddressPreserved() throws IOException {
+ // GIVEN: explicit proxy
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(PROXY_HOST, PROXY_PORT, null, null, noProxySelector());
+
+ // WHEN
+ ProxiedSocketAddress result = sut.proxyFor(TARGET);
+
+ // THEN: target address is forwarded through the proxy
+ HttpConnectProxiedSocketAddress httpProxy =
+ assertInstanceOf(HttpConnectProxiedSocketAddress.class, result);
+ assertEquals(TARGET, httpProxy.getTargetAddress());
+ }
+ }
+
+ @Nested
+ // matching pattern bypasses proxy; non-matching pattern allows proxy; multiple pipe-separated
+ // patterns; case-insensitive matching
+ class BypassPattern {
+
+ @Test
+ void givenBypassMatchesTarget_whenProxyFor_thenReturnsNull() throws IOException {
+ // GIVEN: bypass pattern matches target, explicit proxy configured
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(
+ PROXY_HOST, PROXY_PORT, "*.iomete.cloud", null, noProxySelector());
+
+ // WHEN
+ ProxiedSocketAddress result = sut.proxyFor(TARGET);
+
+ // THEN: bypass wins over explicit proxy
+ assertNull(result);
+ }
+
+ @Test
+ void givenBypassDoesNotMatchTarget_whenProxyFor_thenReturnsProxy() throws IOException {
+ // GIVEN: bypass pattern does NOT match target
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(
+ PROXY_HOST, PROXY_PORT, "*.internal.net", null, noProxySelector());
+
+ // WHEN
+ ProxiedSocketAddress result =
+ sut.proxyFor(InetSocketAddress.createUnresolved("api.example.com", 443));
+
+ // THEN
+ assertProxyAddress(result, PROXY_HOST, PROXY_PORT);
+ }
+
+ @Test
+ void givenMultipleBypassPatterns_whenProxyFor_thenAnyMatchBypasses() throws IOException {
+ // GIVEN: pipe-separated patterns (http.nonProxyHosts format)
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(
+ PROXY_HOST,
+ PROXY_PORT,
+ "localhost|*.internal|10.*|exact.host.com",
+ null,
+ noProxySelector());
+
+ // THEN: each pattern type is tested
+ assertNull(sut.proxyFor(InetSocketAddress.createUnresolved("localhost", 443)), "exact match");
+ assertNull(
+ sut.proxyFor(InetSocketAddress.createUnresolved("db.internal", 5432)), "suffix wildcard");
+ assertNull(
+ sut.proxyFor(InetSocketAddress.createUnresolved("10.0.0.1", 443)), "prefix wildcard");
+ assertNull(
+ sut.proxyFor(InetSocketAddress.createUnresolved("exact.host.com", 443)),
+ "exact FQDN match");
+
+ // non-matching host goes through proxy
+ assertNotNull(
+ sut.proxyFor(InetSocketAddress.createUnresolved("external.com", 443)),
+ "non-matching host should use proxy");
+ }
+
+ @Test
+ void givenBypassPatternIsCaseInsensitive_whenProxyFor_thenMatchesRegardlessOfCase()
+ throws IOException {
+ // GIVEN: mixed-case bypass vs mixed-case target
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(
+ PROXY_HOST, PROXY_PORT, "*.Example.COM", null, noProxySelector());
+
+ // THEN
+ assertNull(sut.proxyFor(InetSocketAddress.createUnresolved("API.EXAMPLE.COM", 443)));
+ assertNull(sut.proxyFor(InetSocketAddress.createUnresolved("api.example.com", 443)));
+ }
+ }
+
+ @Nested
+ // uses selector when no explicit proxy; null when selector returns DIRECT; picks first non-DIRECT
+ // from multi-proxy list; handles null ProxySelector
+ class ProxySelectorFallback {
+
+ @Test
+ void givenNoExplicitProxyAndSelectorReturnsProxy_whenProxyFor_thenUsesSelector()
+ throws IOException {
+ // GIVEN: no explicit proxy, ProxySelector returns an HTTP proxy
+ String selectorHost = "192.168.1.2";
+ int selectorPort = 3128;
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(
+ null, null, null, null, proxySelectorReturning(selectorHost, selectorPort));
+
+ // WHEN
+ ProxiedSocketAddress result = sut.proxyFor(TARGET);
+
+ // THEN
+ assertProxyAddress(result, selectorHost, selectorPort);
+ }
+
+ @Test
+ void givenNoExplicitProxyAndSelectorReturnsDirect_whenProxyFor_thenReturnsNull()
+ throws IOException {
+ // GIVEN: ProxySelector returns DIRECT (no proxy)
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(null, null, null, null, noProxySelector());
+
+ // WHEN
+ ProxiedSocketAddress result = sut.proxyFor(TARGET);
+
+ // THEN
+ assertNull(result);
+ }
+
+ @Test
+ void givenNoExplicitProxyAndSelectorReturnsMultiple_whenProxyFor_thenUsesFirstNonDirect()
+ throws IOException {
+ // GIVEN: ProxySelector returns [DIRECT, HTTP proxy]
+ ProxySelector selector = mock(ProxySelector.class);
+ InetSocketAddress proxyAddr = new InetSocketAddress("192.168.1.3", 9090);
+ List proxies = List.of(Proxy.NO_PROXY, new Proxy(Proxy.Type.HTTP, proxyAddr));
+ when(selector.select(any(URI.class))).thenReturn(proxies);
+
+ ArrowFlightProxyDetector sut = new ArrowFlightProxyDetector(null, null, null, null, selector);
+
+ // WHEN
+ ProxiedSocketAddress result = sut.proxyFor(TARGET);
+
+ // THEN: skips DIRECT, uses the HTTP proxy
+ assertProxyAddress(result, "192.168.1.3", 9090);
+ }
+
+ @Test
+ void givenNullProxySelector_whenProxyFor_thenReturnsNull() throws IOException {
+ // GIVEN: null ProxySelector (can happen if JVM has no default)
+ ArrowFlightProxyDetector sut = new ArrowFlightProxyDetector(null, null, null, null, null);
+
+ // WHEN
+ ProxiedSocketAddress result = sut.proxyFor(TARGET);
+
+ // THEN
+ assertNull(result);
+ }
+ }
+
+ @Nested
+ // returns null when nothing is configured
+ class NoProxyConfigured {
+
+ @Test
+ void givenNothingConfigured_whenProxyFor_thenReturnsNull() throws IOException {
+ // GIVEN: no proxy, no bypass, not disabled, selector returns DIRECT
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(null, null, null, null, noProxySelector());
+
+ // WHEN
+ ProxiedSocketAddress result = sut.proxyFor(TARGET);
+
+ // THEN
+ assertNull(result);
+ }
+ }
+
+ @Nested
+ // forceDisabled > bypass > explicit > selector
+ class PriorityOrder {
+
+ @Test
+ void givenForceDisabledWithExplicitProxyAndBypass_whenProxyFor_thenForceDisabledWins()
+ throws IOException {
+ // GIVEN: all settings configured, force disabled takes highest priority
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(
+ PROXY_HOST,
+ PROXY_PORT,
+ "*.other.com",
+ "force",
+ proxySelectorReturning("192.168.1.2", 3128));
+
+ // THEN
+ assertNull(sut.proxyFor(TARGET));
+ }
+
+ @Test
+ void givenBypassMatchesAndExplicitProxy_whenProxyFor_thenBypassWins() throws IOException {
+ // GIVEN: target matches bypass, explicit proxy also configured
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(
+ PROXY_HOST,
+ PROXY_PORT,
+ "*.iomete.cloud",
+ null,
+ proxySelectorReturning("192.168.1.2", 3128));
+
+ // THEN: bypass takes priority over explicit proxy
+ assertNull(sut.proxyFor(TARGET));
+ }
+
+ @Test
+ void givenExplicitProxyAndSelector_whenProxyFor_thenExplicitWins() throws IOException {
+ // GIVEN: both explicit proxy and ProxySelector configured
+ ArrowFlightProxyDetector sut =
+ new ArrowFlightProxyDetector(
+ PROXY_HOST, PROXY_PORT, null, null, proxySelectorReturning("192.168.1.2", 3128));
+
+ // WHEN
+ ProxiedSocketAddress result = sut.proxyFor(TARGET);
+
+ // THEN: explicit proxy takes priority over selector
+ assertProxyAddress(result, PROXY_HOST, PROXY_PORT);
+ }
+ }
+
+ private static ProxySelector noProxySelector() {
+ ProxySelector selector = mock(ProxySelector.class);
+ when(selector.select(any(URI.class))).thenReturn(Collections.singletonList(Proxy.NO_PROXY));
+ return selector;
+ }
+
+ private static ProxySelector proxySelectorReturning(String host, int port) {
+ ProxySelector selector = mock(ProxySelector.class);
+ InetSocketAddress proxyAddr = new InetSocketAddress(host, port);
+ Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddr);
+ when(selector.select(any(URI.class))).thenReturn(Collections.singletonList(proxy));
+ return selector;
+ }
+
+ private static void assertProxyAddress(
+ ProxiedSocketAddress result, String expectedHost, int expectedPort) {
+ assertNotNull(result);
+ HttpConnectProxiedSocketAddress httpProxy =
+ assertInstanceOf(HttpConnectProxiedSocketAddress.class, result);
+ InetSocketAddress proxyAddr = (InetSocketAddress) httpProxy.getProxyAddress();
+ assertEquals(expectedHost, proxyAddr.getHostString());
+ assertEquals(expectedPort, proxyAddr.getPort());
+ }
+}
diff --git a/flight/flight-sql-jdbc-driver/pom.xml b/flight/flight-sql-jdbc-driver/pom.xml
index 559c42597d..b36019202c 100644
--- a/flight/flight-sql-jdbc-driver/pom.xml
+++ b/flight/flight-sql-jdbc-driver/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-flight
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
flight-sql-jdbc-driver
@@ -138,6 +138,14 @@ under the License.
+
+
+ IOMETE
+ IOMETE
+ 19.0.0-iomete.1
+ Apache Arrow Java 19.0.0
+
+
META-INF/LICENSE.txt
diff --git a/flight/flight-sql/pom.xml b/flight/flight-sql/pom.xml
index a5954819c3..cc26976302 100644
--- a/flight/flight-sql/pom.xml
+++ b/flight/flight-sql/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-flight
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
flight-sql
diff --git a/flight/pom.xml b/flight/pom.xml
index 2fc3e89ef8..5272f0baeb 100644
--- a/flight/pom.xml
+++ b/flight/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-flight
diff --git a/format/pom.xml b/format/pom.xml
index d3578b63d2..7a8fdb6b43 100644
--- a/format/pom.xml
+++ b/format/pom.xml
@@ -23,7 +23,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-format
diff --git a/gandiva/pom.xml b/gandiva/pom.xml
index 5367bfdedf..a0c4069d2a 100644
--- a/gandiva/pom.xml
+++ b/gandiva/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
org.apache.arrow.gandiva
diff --git a/memory/memory-core/pom.xml b/memory/memory-core/pom.xml
index 72ee69d60a..e65de94da1 100644
--- a/memory/memory-core/pom.xml
+++ b/memory/memory-core/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-memory
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-memory-core
diff --git a/memory/memory-netty-buffer-patch/pom.xml b/memory/memory-netty-buffer-patch/pom.xml
index 07dc7d2403..c8ccc77f0f 100644
--- a/memory/memory-netty-buffer-patch/pom.xml
+++ b/memory/memory-netty-buffer-patch/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-memory
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-memory-netty-buffer-patch
diff --git a/memory/memory-netty/pom.xml b/memory/memory-netty/pom.xml
index 6d660da117..9647482887 100644
--- a/memory/memory-netty/pom.xml
+++ b/memory/memory-netty/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-memory
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-memory-netty
diff --git a/memory/memory-unsafe/pom.xml b/memory/memory-unsafe/pom.xml
index 92dc0c9fe5..f8c7f68122 100644
--- a/memory/memory-unsafe/pom.xml
+++ b/memory/memory-unsafe/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-memory
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-memory-unsafe
diff --git a/memory/pom.xml b/memory/pom.xml
index bc34c26050..8ad4e850b2 100644
--- a/memory/pom.xml
+++ b/memory/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-memory
pom
diff --git a/mise.toml b/mise.toml
new file mode 100644
index 0000000000..262fd088c7
--- /dev/null
+++ b/mise.toml
@@ -0,0 +1,2 @@
+[tools]
+java = "temurin-17"
diff --git a/performance/pom.xml b/performance/pom.xml
index 3f18188e3a..5389a792fd 100644
--- a/performance/pom.xml
+++ b/performance/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-performance
jar
diff --git a/plan.md b/plan.md
new file mode 100644
index 0000000000..1cc5737eff
--- /dev/null
+++ b/plan.md
@@ -0,0 +1,102 @@
+# Plan: Package IOMETE Fork of Arrow Flight JDBC Driver
+
+## Context
+
+IOMETE maintains a fork of Apache Arrow Java with a gRPC proxy detector feature (`grpc-proxy-detector` branch). The fork adds HTTP CONNECT proxy tunneling support to the Flight SQL JDBC driver. We need to produce a distributable fat JAR that is identifiable as IOMETE's fork, distinct from the official Apache Arrow distribution.
+
+**Decisions made:**
+- Publish only the fat JAR (`flight-sql-jdbc-driver`) — single dependency for consumers
+- Keep `org.apache.arrow` groupId (drop-in replacement)
+- Version: `19.0.0-iomete.1` (dot-separated, encodes upstream version + IOMETE qualifier + patch)
+- Keep original Java package names (`org.apache.arrow.driver.jdbc.*`) for easy rebase
+- Local build only for now; artifact manager TBD
+
+## Risk Mitigation (keeping `org.apache.arrow` groupId)
+
+Since we're keeping the official groupId, we must prevent accidental resolution conflicts:
+- **Never publish to Maven Central** under `org.apache.arrow` without Apache PMC approval
+- When publishing to a private repo, ensure it takes priority over Maven Central in consumer `settings.xml`
+- The version `19.0.0-iomete.1` is distinct enough to avoid accidental resolution against official `19.0.0`
+
+## Steps
+
+### Step 1: Set version to `19.0.0-iomete.1`
+
+Use Maven's `versions:set` to change the version across all modules atomically:
+
+```bash
+mise exec -- mvn versions:set -DnewVersion=19.0.0-iomete.1 -DgenerateBackupPoms=false
+```
+
+This updates the root POM and all child modules that inherit from it. The fat JAR will be produced as `flight-sql-jdbc-driver-19.0.0-iomete.1.jar`.
+
+**Files affected:** All `pom.xml` files (version inheritance). No manual edits needed.
+
+### Step 2: Build the entire project
+
+The fat JAR module (`flight-sql-jdbc-driver`) depends on several sibling modules. We must build from root:
+
+```bash
+mise exec -- mvn install -DskipTests -Dcheckstyle.skip=true -Dspotless.check.skip=true
+```
+
+- `-DskipTests`: speed — tests were validated on the branch already
+- `-Dcheckstyle.skip` + `-Dspotless.check.skip`: avoid style failures on generated/unmodified code
+
+### Step 3: Verify the fat JAR
+
+The shaded JAR will be at:
+```
+flight/flight-sql-jdbc-driver/target/flight-sql-jdbc-driver-19.0.0-iomete.1.jar
+```
+
+Verify it contains the proxy detector and correct metadata:
+```bash
+# Check JAR size (should be ~40-60MB, it's a fat JAR)
+ls -lh flight/flight-sql-jdbc-driver/target/flight-sql-jdbc-driver-19.0.0-iomete.1.jar
+
+# Verify proxy detector class is present
+jar tf flight/flight-sql-jdbc-driver/target/flight-sql-jdbc-driver-19.0.0-iomete.1.jar | grep ProxyDetector
+
+# Verify JDBC ServiceLoader registration
+jar xf flight/flight-sql-jdbc-driver/target/flight-sql-jdbc-driver-19.0.0-iomete.1.jar META-INF/services/java.sql.Driver
+cat META-INF/services/java.sql.Driver
+
+# Check Maven metadata in JAR
+jar tf flight/flight-sql-jdbc-driver/target/flight-sql-jdbc-driver-19.0.0-iomete.1.jar | grep pom.properties
+```
+
+### Step 4: (Optional) Add IOMETE manifest entry
+
+Add a custom manifest attribute to the shade plugin config in `flight/flight-sql-jdbc-driver/pom.xml` for traceability:
+
+```xml
+
+
+ IOMETE
+ IOMETE
+ 19.0.0-iomete.1
+ Apache Arrow Java 19.0.0
+
+
+```
+
+**File:** `flight/flight-sql-jdbc-driver/pom.xml` (shade plugin `` section)
+
+### Step 5: Commit the version change
+
+Commit on the `grpc-proxy-detector` branch with a clear message indicating the IOMETE release version.
+
+## Verification
+
+1. Fat JAR exists at expected path with correct filename
+2. `ProxyDetector` class is inside the JAR (grep confirms)
+3. `META-INF/services/java.sql.Driver` points to `org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver`
+4. JAR can be loaded as a JDBC driver: `java -cp org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver` (no ClassNotFoundException)
+5. `pom.properties` inside JAR shows `version=19.0.0-iomete.1`
+
+## Future Considerations (not in scope now)
+
+- **Artifact manager**: When ready, add `` to root POM pointing to GitHub Packages / Nexus / Artifactory
+- **CI/CD**: GitHub Actions workflow to build + publish on git tag `v19.0.0-iomete.*`
+- **Upstream rebase**: When Arrow releases 20.0.0, rebase branch, bump to `20.0.0-iomete.1`
diff --git a/pom.xml b/pom.xml
index 19625617b1..f0da582645 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
pom
Apache Arrow Java Root POM
@@ -92,7 +92,7 @@ under the License.
- 1695310533
+ 1773860567
${project.build.directory}/generated-sources
1.9.0
5.12.2
@@ -611,6 +611,7 @@ under the License.
false
true
false
+ /Users/mateus/workspace/conductor-ai/repos/arrow-java/.git
false
false
diff --git a/tools/pom.xml b/tools/pom.xml
index d43adb1fdf..cdc261a9a2 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-tools
Arrow Tools
diff --git a/vector/pom.xml b/vector/pom.xml
index f46bd0e7b4..cdc0b6e0d0 100644
--- a/vector/pom.xml
+++ b/vector/pom.xml
@@ -22,7 +22,7 @@ under the License.
org.apache.arrow
arrow-java-root
- 19.0.0-SNAPSHOT
+ 19.0.0-iomete.1
arrow-vector
Arrow Vectors