This is an automated email from the ASF dual-hosted git repository.
apurtell pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hbase-thirdparty.git
The following commit(s) were added to refs/heads/master by this push:
new 3316313 HBASE-30194 [thirdparty] Onboard libthrift to
hbase-thirdparty (#160)
3316313 is described below
commit 33163133229810ad24c60a8ba396688e07b8eea3
Author: Andrew Purtell <[email protected]>
AuthorDate: Mon Jun 8 11:44:09 2026 -0700
HBASE-30194 [thirdparty] Onboard libthrift to hbase-thirdparty (#160)
Signed-off-by: Dávid Paksy <[email protected]>
Signed-off-by: Duo Zhang <[email protected]>
Signed-off-by: Nick Dimiduk <[email protected]>
Signed-off-by: Nihal Jain <[email protected]>
Co-Authored-by: Claude Opus 4.8[1m] <[email protected]>
---
.gitignore | 2 +
hbase-shaded-thrift/pom.xml | 227 +++++++++++++++++++++
.../src/main/appended-resources/META-INF/LICENSE | 19 ++
.../src/main/appended-resources/META-INF/NOTICE | 8 +
.../patches/HBASE-30194-01-servlet-javax.patch | 39 ++++
.../main/patches/HBASE-30194-02-httpclient4.patch | 129 ++++++++++++
pom.xml | 19 ++
7 files changed, 443 insertions(+)
diff --git a/.gitignore b/.gitignore
index f4b640b..53cd238 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,8 @@
**/dependency-reduced-pom.xml
hbase-shaded-protobuf/src/main/java
hbase-shaded-protobuf/src/main/resources
+hbase-shaded-thrift/src/main/java
+hbase-shaded-thrift/src/main/resources
.project
.settings
.classpath
diff --git a/hbase-shaded-thrift/pom.xml b/hbase-shaded-thrift/pom.xml
new file mode 100644
index 0000000..521904e
--- /dev/null
+++ b/hbase-shaded-thrift/pom.xml
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <!--
+/**
+ * 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.
+ */
+-->
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.hbase.thirdparty</groupId>
+ <artifactId>hbase-thirdparty</artifactId>
+ <version>${revision}</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>hbase-shaded-thrift</artifactId>
+ <name>Apache HBase Patched and Relocated (Shaded) Thrift</name>
+ <description>Pulls down libthrift, patches it, compiles, and then
relocates/shades.</description>
+ <properties>
+ <!-- Override parent's JDK 17 settings to force JDK 8 for
hbase-shaded-thrift, matching the
+ other source-distribution shaded modules in this project (e.g.
hbase-shaded-protobuf). The
+ patches we apply put libthrift back on the javax.servlet and Apache
HttpClient 4.x surface,
+ which are Java 8 friendly. -->
+
<toolchain.jdk.version>${hbase.unsafe.and.protobuf.java.version}</toolchain.jdk.version>
+ <maven.compiler.source>${java.release.version}</maven.compiler.source>
+ <maven.compiler.target>${java.release.version}</maven.compiler.target>
+ </properties>
+ <!--
+ The patched libthrift sources reference slf4j-api, javax.servlet-api,
Apache HttpClient/Core
+ 4.x, and commons-lang3 at compile time. These are NOT shaded; downstream
consumers must
+ provide their own runtime versions (hbase-thrift already does). We declare
them as provided
+ scope so they participate in compilation but never get bundled into the
shaded jar. All
+ versions come from properties in the parent pom so they stay aligned with
what the rest of
+ HBase expects at runtime.
+ -->
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>${servlet-api.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>${httpclient.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ <version>${httpcore.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>${commons-lang3.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <!-- Clean needs to purge src/main/java since this is where we overlay
the unpack of
+ libthrift. Do it for usual clean goal but also before we unpack
in case patches
+ delete/add files. We use src/main/java instead of dir under
'target' because the
+ jar plugin is dumb, hard to make it source from other then
src/main/java. -->
+ <artifactId>maven-clean-plugin</artifactId>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>${basedir}/src/main/java</directory>
+ <includes>
+ <include>**/**</include>
+ </includes>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ <fileset>
+ <directory>${basedir}/src/main/resources</directory>
+ <includes>
+ <include>**/**</include>
+ </includes>
+ <followSymlinks>false</followSymlinks>
+ </fileset>
+ </filesets>
+ </configuration>
+ <executions>
+ <execution>
+ <id>pre-generate-sources</id>
+ <goals>
+ <goal>clean</goal>
+ </goals>
+ <phase>generate-sources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <!--Download our dependency src, i.e. libthrift, and
+ unpack it. Overlays src/main/java so ready for
+ compile-time (the jar plugin expects src in
+ src/main/java)-->
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack</id>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <phase>generate-sources</phase>
+ <configuration>
+ <!--
+ The libthrift compile dependencies (slf4j, javax.servlet,
httpclient, ...) are
+ declared as provided above, not here. We only unpack the
source jar here.
+ -->
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.thrift</groupId>
+ <artifactId>libthrift</artifactId>
+ <version>${thrift.version}</version>
+ <classifier>sources</classifier>
+ <type>jar</type>
+ <overWrite>true</overWrite>
+ <outputDirectory>${basedir}/src/main/java</outputDirectory>
+ <includes>**/**</includes>
+ </artifactItem>
+ <!-- for the bundled LICENSE.txt / NOTICE.txt of libthrift -->
+ <artifactItem>
+ <groupId>org.apache.thrift</groupId>
+ <artifactId>libthrift</artifactId>
+ <version>${thrift.version}</version>
+ <type>jar</type>
+ <overWrite>true</overWrite>
+
<outputDirectory>${basedir}/src/main/resources</outputDirectory>
+ <includes>META-INF/LICENSE.txt,META-INF/NOTICE.txt</includes>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ </plugin>
+ <!--Apply our patches to the unpacked libthrift src-->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-patch-plugin</artifactId>
+ <configuration>
+ <targetDirectory>${basedir}</targetDirectory>
+ <skipApplication>false</skipApplication>
+ </configuration>
+ <executions>
+ <execution>
+ <id>patch</id>
+ <goals>
+ <goal>apply</goal>
+ </goals>
+ <phase>process-sources</phase>
+ <configuration>
+ <strip>1</strip>
+ <patchDirectory>${basedir}/src/main/patches</patchDirectory>
+
<patchTrackingFile>${project.build.directory}/patches-applied.txt</patchTrackingFile>
+ <naturalOrderProcessing>true</naturalOrderProcessing>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <!--Above we built a jar. Now at package step, do relocation/shade-->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <shadeSourcesContent>true</shadeSourcesContent>
+ <createSourcesJar>true</createSourcesJar>
+ <relocations>
+ <relocation>
+ <pattern>org.apache.thrift</pattern>
+
<shadedPattern>${rename.offset}.org.apache.thrift</shadedPattern>
+ </relocation>
+ </relocations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/hbase-shaded-thrift/src/main/appended-resources/META-INF/LICENSE
b/hbase-shaded-thrift/src/main/appended-resources/META-INF/LICENSE
new file mode 100644
index 0000000..8c1cee5
--- /dev/null
+++ b/hbase-shaded-thrift/src/main/appended-resources/META-INF/LICENSE
@@ -0,0 +1,19 @@
+
+---
+
+This project incorporates portions of the 'Apache Thrift' project (libthrift),
+which is published under the Apache License, Version 2.0.
+
+ Copyright (C) 2006 - 2024, The Apache Software Foundation
+
+ Licensed 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.
diff --git a/hbase-shaded-thrift/src/main/appended-resources/META-INF/NOTICE
b/hbase-shaded-thrift/src/main/appended-resources/META-INF/NOTICE
new file mode 100644
index 0000000..11ae5f0
--- /dev/null
+++ b/hbase-shaded-thrift/src/main/appended-resources/META-INF/NOTICE
@@ -0,0 +1,8 @@
+
+---
+
+Apache Thrift
+Copyright (C) 2006 - 2024, The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git
a/hbase-shaded-thrift/src/main/patches/HBASE-30194-01-servlet-javax.patch
b/hbase-shaded-thrift/src/main/patches/HBASE-30194-01-servlet-javax.patch
new file mode 100644
index 0000000..16e0be7
--- /dev/null
+++ b/hbase-shaded-thrift/src/main/patches/HBASE-30194-01-servlet-javax.patch
@@ -0,0 +1,39 @@
+diff --git a/src/main/java/org/apache/thrift/server/TServlet.java
b/src/main/java/org/apache/thrift/server/TServlet.java
+--- a/src/main/java/org/apache/thrift/server/TServlet.java
++++ b/src/main/java/org/apache/thrift/server/TServlet.java
+@@ -1,9 +1,9 @@
+ package org.apache.thrift.server;
+
+-import jakarta.servlet.ServletException;
+-import jakarta.servlet.http.HttpServlet;
+-import jakarta.servlet.http.HttpServletRequest;
+-import jakarta.servlet.http.HttpServletResponse;
++import javax.servlet.ServletException;
++import javax.servlet.http.HttpServlet;
++import javax.servlet.http.HttpServletRequest;
++import javax.servlet.http.HttpServletResponse;
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.io.OutputStream;
+diff --git a/src/main/java/org/apache/thrift/server/TExtensibleServlet.java
b/src/main/java/org/apache/thrift/server/TExtensibleServlet.java
+--- a/src/main/java/org/apache/thrift/server/TExtensibleServlet.java
++++ b/src/main/java/org/apache/thrift/server/TExtensibleServlet.java
+@@ -19,12 +19,12 @@
+
+ package org.apache.thrift.server;
+
+-import jakarta.servlet.ServletConfig;
+-import jakarta.servlet.ServletContext;
+-import jakarta.servlet.ServletException;
+-import jakarta.servlet.http.HttpServlet;
+-import jakarta.servlet.http.HttpServletRequest;
+-import jakarta.servlet.http.HttpServletResponse;
++import javax.servlet.ServletConfig;
++import javax.servlet.ServletContext;
++import javax.servlet.ServletException;
++import javax.servlet.http.HttpServlet;
++import javax.servlet.http.HttpServletRequest;
++import javax.servlet.http.HttpServletResponse;
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.io.OutputStream;
diff --git
a/hbase-shaded-thrift/src/main/patches/HBASE-30194-02-httpclient4.patch
b/hbase-shaded-thrift/src/main/patches/HBASE-30194-02-httpclient4.patch
new file mode 100644
index 0000000..e76ac3e
--- /dev/null
+++ b/hbase-shaded-thrift/src/main/patches/HBASE-30194-02-httpclient4.patch
@@ -0,0 +1,129 @@
+diff --git a/src/main/java/org/apache/thrift/THttpClientResponseHandler.java
b/src/main/java/org/apache/thrift/THttpClientResponseHandler.java
+--- a/src/main/java/org/apache/thrift/THttpClientResponseHandler.java
++++ b/src/main/java/org/apache/thrift/THttpClientResponseHandler.java
+@@ -4,18 +4,18 @@
+ import java.io.ByteArrayOutputStream;
+ import java.io.IOException;
+ import java.io.InputStream;
+-import org.apache.hc.core5.http.ClassicHttpResponse;
+-import org.apache.hc.core5.http.HttpEntity;
+-import org.apache.hc.core5.http.HttpException;
+-import org.apache.hc.core5.http.HttpStatus;
+-import org.apache.hc.core5.http.io.HttpClientResponseHandler;
++import org.apache.http.HttpEntity;
++import org.apache.http.HttpResponse;
++import org.apache.http.HttpStatus;
++import org.apache.http.client.ResponseHandler;
++import org.apache.http.client.ClientProtocolException;
+
+-public class THttpClientResponseHandler implements
HttpClientResponseHandler<InputStream> {
++public class THttpClientResponseHandler implements
ResponseHandler<InputStream> {
+ @Override
+- public InputStream handleResponse(ClassicHttpResponse response)
+- throws HttpException, IOException {
++ public InputStream handleResponse(HttpResponse response)
++ throws ClientProtocolException, IOException {
+ try (InputStream is = response.getEntity().getContent()) {
+- int responseCode = response.getCode();
++ int responseCode = response.getStatusLine().getStatusCode();
+ if (responseCode != HttpStatus.SC_OK) {
+ throw new IOException("HTTP Response code: " + responseCode);
+ }
+diff --git a/src/main/java/org/apache/thrift/transport/THttpClient.java
b/src/main/java/org/apache/thrift/transport/THttpClient.java
+--- a/src/main/java/org/apache/thrift/transport/THttpClient.java
++++ b/src/main/java/org/apache/thrift/transport/THttpClient.java
+@@ -27,13 +27,11 @@
+ import java.util.Collections;
+ import java.util.HashMap;
+ import java.util.Map;
+-import org.apache.hc.client5.http.classic.HttpClient;
+-import org.apache.hc.client5.http.classic.methods.HttpPost;
+-import org.apache.hc.client5.http.config.ConnectionConfig;
+-import org.apache.hc.client5.http.config.RequestConfig;
+-import org.apache.hc.core5.http.HttpHost;
+-import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
+-import org.apache.hc.core5.util.Timeout;
++import org.apache.http.HttpHost;
++import org.apache.http.client.HttpClient;
++import org.apache.http.client.config.RequestConfig;
++import org.apache.http.client.methods.HttpPost;
++import org.apache.http.entity.ByteArrayEntity;
+ import org.apache.thrift.TConfiguration;
+ import org.apache.thrift.THttpClientResponseHandler;
+
+@@ -138,9 +136,9 @@
+ this.client = client;
+ this.host =
+ new HttpHost(
+- url_.getProtocol(),
+ url_.getHost(),
+- -1 == url_.getPort() ? url_.getDefaultPort() : url_.getPort());
++ -1 == url_.getPort() ? url_.getDefaultPort() : url_.getPort(),
++ url_.getProtocol());
+ } catch (IOException iox) {
+ throw new TTransportException(iox);
+ }
+@@ -153,9 +151,9 @@
+ this.client = client;
+ this.host =
+ new HttpHost(
+- url_.getProtocol(),
+ url_.getHost(),
+- -1 == url_.getPort() ? url_.getDefaultPort() : url_.getPort());
++ -1 == url_.getPort() ? url_.getDefaultPort() : url_.getPort(),
++ url_.getProtocol());
+ } catch (IOException iox) {
+ throw new TTransportException(iox);
+ }
+@@ -166,10 +164,8 @@
+ }
+
+ /**
+- * Use instead {@link
+- *
org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager#setConnectionConfig}
or
+- * {@link
+- *
org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager#setDefaultConnectionConfig}
++ * Use instead a {@link RequestConfig} pre-configured on the underlying
Apache HttpClient (e.g.
++ * via {@code HttpClientBuilder#setDefaultRequestConfig}).
+ */
+ @Deprecated
+ public void setReadTimeout(int timeout) {
+@@ -233,25 +229,14 @@
+ }
+
+ private RequestConfig getRequestConfig() {
+- RequestConfig requestConfig = RequestConfig.DEFAULT;
++ RequestConfig.Builder builder = RequestConfig.custom();
+ if (connectTimeout_ > 0) {
+- requestConfig =
+- RequestConfig.copy(requestConfig)
+-
.setConnectionRequestTimeout(Timeout.ofMilliseconds(connectTimeout_))
+- .build();
++
builder.setConnectTimeout(connectTimeout_).setConnectionRequestTimeout(connectTimeout_);
+ }
+- return requestConfig;
+- }
+-
+- private ConnectionConfig getConnectionConfig() {
+- ConnectionConfig connectionConfig = ConnectionConfig.DEFAULT;
+ if (readTimeout_ > 0) {
+- connectionConfig =
+- ConnectionConfig.copy(connectionConfig)
+- .setSocketTimeout(Timeout.ofMilliseconds(readTimeout_))
+- .build();
++ builder.setSocketTimeout(readTimeout_);
+ }
+- return connectionConfig;
++ return builder.build();
+ }
+
+ private static Map<String, String> getDefaultHeaders() {
+@@ -279,7 +264,7 @@
+ if (null != customHeaders_) {
+ customHeaders_.forEach(post::addHeader);
+ }
+- post.setEntity(new ByteArrayEntity(data, null));
++ post.setEntity(new ByteArrayEntity(data));
+ inputStream_ = client.execute(this.host, post, new
THttpClientResponseHandler());
+ } catch (IOException ioe) {
+ // Abort method so the connection gets released back to the connection
manager
diff --git a/pom.xml b/pom.xml
index 5b2d441..2118ea2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -95,6 +95,7 @@
</mailingLists>
<modules>
<module>hbase-shaded-protobuf</module>
+ <module>hbase-shaded-thrift</module>
<module>hbase-shaded-netty</module>
<module>hbase-shaded-netty-tcnative</module>
<module>hbase-shaded-gson</module>
@@ -137,6 +138,10 @@
<os.maven.version>1.7.1</os.maven.version>
<rename.offset>org.apache.hbase.thirdparty</rename.offset>
<protobuf.version>4.34.0</protobuf.version>
+ <!-- libthrift sources jar pulled, patched, and shaded by
hbase-shaded-thrift. The patches
+ under hbase-shaded-thrift/src/main/patches were authored against this
exact version and will
+ not apply cleanly against any other. -->
+ <thrift.version>0.23.0</thrift.version>
<netty.version>4.1.131.Final</netty.version>
<netty.tcnative.version>2.0.75.Final</netty.tcnative.version>
<guava.version>33.4.8-jre</guava.version>
@@ -155,6 +160,15 @@
<javassist.version>3.30.2-GA</javassist.version>
<jackson-jaxrs-json-provider.version>2.21.1</jackson-jaxrs-json-provider.version>
<spotless.version>2.30.0</spotless.version>
+ <!--
+ Compile-time deps used by the patched libthrift sources in
hbase-shaded-thrift. The
+ shaded thrift jar does NOT bundle these. We set them at 'provided' scope
at compile
+ time and downstream consumers supply them.
+ -->
+ <slf4j.version>1.7.36</slf4j.version>
+ <httpclient.version>4.5.13</httpclient.version>
+ <httpcore.version>4.4.13</httpcore.version>
+ <commons-lang3.version>3.12.0</commons-lang3.version>
<!-- Below is copied from hbase project -->
<hbase-surefire.jdk17.flags>-Dorg.apache.hbase.thirdparty.io.netty.tryReflectionSetAccessible=true
@@ -243,8 +257,13 @@
<exclude>**/src/main/patches/**</exclude>
<!--Exclude the unpacked google src-->
<exclude>**/src/main/java/com/google/protobuf/**</exclude>
+ <exclude>**/src/main/patches/**</exclude>
<exclude>**/src/main/resources/google/**</exclude>
<exclude>**/src/main/java/META-INF/**</exclude>
+ <!--Exclude the unpacked libthrift src and bundled
license/notice-->
+
<exclude>**/hbase-shaded-thrift/src/main/java/org/apache/thrift/**</exclude>
+
<exclude>**/hbase-shaded-thrift/src/main/resources/META-INF/LICENSE.txt</exclude>
+
<exclude>**/hbase-shaded-thrift/src/main/resources/META-INF/NOTICE.txt</exclude>
</excludes>
</configuration>
</plugin>