This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
The following commit(s) were added to refs/heads/master by this push:
new b3d0aea0 [MRESOLVER-426] Make some HTTP configuration shared (#356)
b3d0aea0 is described below
commit b3d0aea0e1466fdda025a1872efa6d535d3a9bf0
Author: Tamas Cservenak <[email protected]>
AuthorDate: Wed Nov 8 20:32:38 2023 +0100
[MRESOLVER-426] Make some HTTP configuration shared (#356)
Many of HTTP related options are not Apache HTTP transport specific. Also,
make possible some newer java.net.http.HttpClient options to be applied.
---
https://issues.apache.org/jira/browse/MRESOLVER-426
---
.../eclipse/aether/ConfigurationProperties.java | 38 ++++++++++
.../aether/transport/http/HttpTransporter.java | 35 +++++-----
.../aether/transport/http/HttpTransporterTest.java | 6 +-
.../aether/transport/jdk/JdkHttpTransporter.java | 6 +-
.../jdk/JdkHttpTransporterCustomizer.java | 38 ++++++++++
.../pom.xml | 63 +++--------------
.../jdk/JdkHttpTransporterCustomizer.java | 68 ++++++++++++++++++
.../pom.xml | 63 +++--------------
.../jdk/JdkHttpTransporterCustomizer.java | 70 +++++++++++++++++++
.../maven-resolver-transport-jdk/pom.xml | 80 ++++++++++++++++++++++
maven-resolver-transport-jdk-parent/pom.xml | 2 +
src/site/markdown/configuration.md | 2 +-
12 files changed, 343 insertions(+), 128 deletions(-)
diff --git
a/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java
b/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java
index 279e707c..959d2876 100644
---
a/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java
+++
b/maven-resolver-api/src/main/java/org/eclipse/aether/ConfigurationProperties.java
@@ -274,6 +274,44 @@ public final class ConfigurationProperties {
*/
public static final int DEFAULT_HTTP_MAX_CONNECTIONS_PER_ROUTE = 50;
+ /**
+ * The local address (interface) to use with HTTP transport. Not all
transport supports this option.
+ *
+ * @since 2.0.0
+ */
+ public static final String HTTP_LOCAL_ADDRESS = PREFIX_CONNECTOR +
"http.localAddress";
+
+ /**
+ * Boolean flag should the HTTP transport support WebDAV remote. Not all
transport support this option.
+ *
+ * @see #DEFAULT_HTTP_SUPPORT_WEBDAV
+ * @since 2.0.0 (moved out from maven-resolver-transport-http).
+ */
+ public static final String HTTP_SUPPORT_WEBDAV = PREFIX_CONNECTOR +
"http.supportWebDav";
+
+ /**
+ * Default value to use if {@link #HTTP_SUPPORT_WEBDAV} is not set: {@code
false}.
+ *
+ * @since 2.0.0
+ */
+ public static final boolean DEFAULT_HTTP_SUPPORT_WEBDAV = false;
+
+ /**
+ * Boolean flag should the HTTP transport use preemptive-auth for PUT
requests. Not all transport support this
+ * option.
+ *
+ * @see #DEFAULT_HTTP_PREEMPTIVE_PUT_AUTH
+ * @since 2.0.0 (moved out from maven-resolver-transport-http).
+ */
+ public static final String HTTP_PREEMPTIVE_PUT_AUTH = PREFIX_CONNECTOR +
"http.preemptivePutAuth";
+
+ /**
+ * Default value if {@link #HTTP_PREEMPTIVE_PUT_AUTH} is not set: {@code
true}.
+ *
+ * @since 2.0.0
+ */
+ public static final boolean DEFAULT_HTTP_PREEMPTIVE_PUT_AUTH = true;
+
/**
* The mode that sets HTTPS transport "security mode": to ignore any SSL
errors (certificate validity checks,
* hostname verification). The default value is {@link
#HTTPS_SECURITY_MODE_DEFAULT}.
diff --git
a/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java
b/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java
index 87020474..9bd58898 100644
---
a/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java
+++
b/maven-resolver-transport-http/src/main/java/org/eclipse/aether/transport/http/HttpTransporter.java
@@ -106,12 +106,6 @@ import static java.util.Objects.requireNonNull;
*/
final class HttpTransporter extends AbstractTransporter {
- static final String BIND_ADDRESS = "aether.connector.bind.address";
-
- static final String SUPPORT_WEBDAV = "aether.connector.http.supportWebDav";
-
- static final String PREEMPTIVE_PUT_AUTH =
"aether.connector.http.preemptivePutAuth";
-
static final String USE_SYSTEM_PROPERTIES =
"aether.connector.http.useSystemProperties";
static final String HTTP_RETRY_HANDLER_NAME =
"aether.connector.http.retryHandler.name";
@@ -211,11 +205,16 @@ final class HttpTransporter extends AbstractTransporter {
ConfigurationProperties.DEFAULT_HTTP_PREEMPTIVE_AUTH,
ConfigurationProperties.HTTP_PREEMPTIVE_AUTH + "." +
repository.getId(),
ConfigurationProperties.HTTP_PREEMPTIVE_AUTH);
- this.preemptivePutAuth = // defaults to true: Wagon does same
- ConfigUtils.getBoolean(
- session, true, PREEMPTIVE_PUT_AUTH + "." +
repository.getId(), PREEMPTIVE_PUT_AUTH);
- this.supportWebDav = // defaults to false: who needs it will enable it
- ConfigUtils.getBoolean(session, false, SUPPORT_WEBDAV + "." +
repository.getId(), SUPPORT_WEBDAV);
+ this.preemptivePutAuth = ConfigUtils.getBoolean(
+ session,
+ ConfigurationProperties.DEFAULT_HTTP_PREEMPTIVE_PUT_AUTH,
+ ConfigurationProperties.HTTP_PREEMPTIVE_PUT_AUTH + "." +
repository.getId(),
+ ConfigurationProperties.HTTP_PREEMPTIVE_PUT_AUTH);
+ this.supportWebDav = ConfigUtils.getBoolean(
+ session,
+ ConfigurationProperties.DEFAULT_HTTP_SUPPORT_WEBDAV,
+ ConfigurationProperties.HTTP_SUPPORT_WEBDAV + "." +
repository.getId(),
+ ConfigurationProperties.HTTP_SUPPORT_WEBDAV);
String credentialEncoding = ConfigUtils.getString(
session,
ConfigurationProperties.DEFAULT_HTTP_CREDENTIAL_ENCODING,
@@ -277,7 +276,7 @@ final class HttpTransporter extends AbstractTransporter {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectTimeout)
- .setLocalAddress(getBindAddress(session, repository))
+ .setLocalAddress(getHttpLocalAddress(session, repository))
.setSocketTimeout(requestTimeout)
.build();
@@ -338,9 +337,12 @@ final class HttpTransporter extends AbstractTransporter {
/**
* Returns non-null {@link InetAddress} if set in configuration, {@code
null} otherwise.
*/
- private InetAddress getBindAddress(RepositorySystemSession session,
RemoteRepository repository) {
- String bindAddress =
- ConfigUtils.getString(session, null, BIND_ADDRESS + "." +
repository.getId(), BIND_ADDRESS);
+ private InetAddress getHttpLocalAddress(RepositorySystemSession session,
RemoteRepository repository) {
+ String bindAddress = ConfigUtils.getString(
+ session,
+ null,
+ ConfigurationProperties.HTTP_LOCAL_ADDRESS + "." +
repository.getId(),
+ ConfigurationProperties.HTTP_LOCAL_ADDRESS);
if (bindAddress == null) {
return null;
}
@@ -591,7 +593,7 @@ final class HttpTransporter extends AbstractTransporter {
}
@SuppressWarnings("checkstyle:magicnumber")
- private <T extends HttpUriRequest> T resume(T request, GetTask task) {
+ private <T extends HttpUriRequest> void resume(T request, GetTask task) {
long resumeOffset = task.getResumeOffset();
if (resumeOffset > 0L && task.getDataFile() != null) {
request.setHeader(HttpHeaders.RANGE, "bytes=" + resumeOffset +
'-');
@@ -600,7 +602,6 @@ final class HttpTransporter extends AbstractTransporter {
DateUtils.formatDate(new
Date(task.getDataFile().lastModified() - 60L * 1000L)));
request.setHeader(HttpHeaders.ACCEPT_ENCODING, "identity");
}
- return request;
}
@SuppressWarnings("checkstyle:magicnumber")
diff --git
a/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java
b/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java
index 1226e7cc..1764a6a5 100644
---
a/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java
+++
b/maven-resolver-transport-http/src/test/java/org/eclipse/aether/transport/http/HttpTransporterTest.java
@@ -687,7 +687,7 @@ public class HttpTransporterTest {
@Test
void testPut_Authenticated_ExpectContinueBroken() throws Exception {
// this makes OPTIONS recover, and have only 1 PUT (startedCount=1 as
OPTIONS is not counted)
- session.setConfigProperty(HttpTransporter.SUPPORT_WEBDAV, true);
+ session.setConfigProperty(ConfigurationProperties.HTTP_SUPPORT_WEBDAV,
true);
httpServer.setAuthentication("testuser", "testpass");
httpServer.setExpectSupport(HttpServer.ExpectContinue.BROKEN);
auth = new AuthenticationBuilder()
@@ -828,7 +828,7 @@ public class HttpTransporterTest {
@Test
void testPut_WebDav() throws Exception {
httpServer.setWebDav(true);
- session.setConfigProperty(HttpTransporter.SUPPORT_WEBDAV, true);
+ session.setConfigProperty(ConfigurationProperties.HTTP_SUPPORT_WEBDAV,
true);
newTransporter(httpServer.getHttpUrl());
RecordingTransportListener listener = new RecordingTransportListener();
@@ -943,7 +943,7 @@ public class HttpTransporterTest {
@Test
void testPut_AuthCache() throws Exception {
- session.setConfigProperty(HttpTransporter.PREEMPTIVE_PUT_AUTH, false);
+
session.setConfigProperty(ConfigurationProperties.HTTP_PREEMPTIVE_PUT_AUTH,
false);
httpServer.setAuthentication("testuser", "testpass");
auth = new AuthenticationBuilder()
.addUsername("testuser")
diff --git
a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-11/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporter.java
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-11/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporter.java
index 2200aa87..ece18517 100644
---
a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-11/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporter.java
+++
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-11/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporter.java
@@ -389,6 +389,8 @@ final class JdkHttpTransporter extends AbstractTransporter {
.connectTimeout(Duration.ofMillis(connectTimeout))
.sslContext(sslContext);
+ JdkHttpTransporterCustomizer.customizeBuilder(session,
repository, builder);
+
if (repository.getProxy() != null) {
ProxySelector proxy = ProxySelector.of(new
InetSocketAddress(
repository.getProxy().getHost(),
@@ -417,7 +419,9 @@ final class JdkHttpTransporter extends AbstractTransporter {
});
}
- return builder.build();
+ HttpClient result = builder.build();
+ JdkHttpTransporterCustomizer.customizeHttpClient(session,
repository, result);
+ return result;
} catch (NoSuchAlgorithmException e) {
throw new WrapperEx(e);
}
diff --git
a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-11/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporterCustomizer.java
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-11/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporterCustomizer.java
new file mode 100644
index 00000000..7695d0e7
--- /dev/null
+++
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-11/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporterCustomizer.java
@@ -0,0 +1,38 @@
+/*
+ * 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.eclipse.aether.transport.jdk;
+
+import java.net.http.HttpClient;
+
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.repository.RemoteRepository;
+
+/**
+ * JDK Transport customizer.
+ *
+ * @since TBD
+ */
+final class JdkHttpTransporterCustomizer {
+ private JdkHttpTransporterCustomizer() {}
+
+ static void customizeBuilder(
+ RepositorySystemSession session, RemoteRepository repository,
HttpClient.Builder builder) {}
+
+ static void customizeHttpClient(RepositorySystemSession session,
RemoteRepository repository, HttpClient client) {}
+}
diff --git
a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk/pom.xml
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-19/pom.xml
similarity index 55%
copy from
maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk/pom.xml
copy to
maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-19/pom.xml
index f6b32f9a..4bbfc270 100644
--- a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk/pom.xml
+++
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-19/pom.xml
@@ -26,15 +26,17 @@
<version>2.0.0-SNAPSHOT</version>
</parent>
- <artifactId>maven-resolver-transport-jdk</artifactId>
+ <artifactId>maven-resolver-transport-jdk-19</artifactId>
<packaging>jar</packaging>
- <name>Maven Artifact Resolver Transport JDK (mr)</name>
+ <name>Maven Artifact Resolver Transport JDK (19)</name>
<description>Maven Artifact Transport JDK Java 11+.</description>
<properties>
<Automatic-Module-Name>org.apache.maven.resolver.transport.jdk</Automatic-Module-Name>
<Bundle-SymbolicName>${Automatic-Module-Name}</Bundle-SymbolicName>
+
+ <javaVersion>19</javaVersion>
</properties>
<dependencies>
@@ -59,56 +61,14 @@
</dependencies>
<build>
- <resources>
- <resource>
- <filtering>false</filtering>
- <directory>${project.build.directory}/generated-resources</directory>
- </resource>
- </resources>
<plugins>
<plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>java8</id>
- <goals>
- <goal>unpack</goal>
- </goals>
- <phase>generate-resources</phase>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.apache.maven.resolver</groupId>
- <artifactId>maven-resolver-transport-jdk-8</artifactId>
- <version>${project.version}</version>
- <type>jar</type>
-
<outputDirectory>${project.build.directory}/generated-resources</outputDirectory>
- <excludes>META-INF/maven/**</excludes>
- </artifactItem>
- </artifactItems>
- </configuration>
- </execution>
- <execution>
- <id>java11</id>
- <goals>
- <goal>unpack</goal>
- </goals>
- <phase>generate-resources</phase>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.apache.maven.resolver</groupId>
- <artifactId>maven-resolver-transport-jdk-11</artifactId>
- <version>${project.version}</version>
- <type>jar</type>
-
<outputDirectory>${project.build.directory}/generated-resources/META-INF/versions/11</outputDirectory>
- <includes>**/*.class</includes>
- </artifactItem>
- </artifactItems>
- </configuration>
- </execution>
- </executions>
+ <groupId>org.eclipse.sisu</groupId>
+ <artifactId>sisu-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>biz.aQute.bnd</groupId>
+ <artifactId>bnd-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -116,9 +76,6 @@
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
- <manifestEntries>
- <Multi-Release>true</Multi-Release>
- </manifestEntries>
</archive>
</configuration>
</plugin>
diff --git
a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-19/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporterCustomizer.java
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-19/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporterCustomizer.java
new file mode 100644
index 00000000..63929635
--- /dev/null
+++
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-19/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporterCustomizer.java
@@ -0,0 +1,68 @@
+/*
+ * 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.eclipse.aether.transport.jdk;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.net.http.HttpClient;
+
+import org.eclipse.aether.ConfigurationProperties;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.util.ConfigUtils;
+
+/**
+ * JDK Transport customizer.
+ *
+ * @since TBD
+ */
+final class JdkHttpTransporterCustomizer {
+ private JdkHttpTransporterCustomizer() {}
+
+ static void customizeBuilder(
+ RepositorySystemSession session, RemoteRepository repository,
HttpClient.Builder builder) {
+ InetAddress localAddress = getHttpLocalAddress(session, repository);
+ if (localAddress != null) {
+ builder.localAddress(localAddress);
+ }
+ }
+
+ static void customizeHttpClient(RepositorySystemSession session,
RemoteRepository repository, HttpClient client) {}
+
+ /**
+ * Returns non-null {@link InetAddress} if set in configuration, {@code
null} otherwise.
+ */
+ private static InetAddress getHttpLocalAddress(RepositorySystemSession
session, RemoteRepository repository) {
+ String bindAddress = ConfigUtils.getString(
+ session,
+ null,
+ ConfigurationProperties.HTTP_LOCAL_ADDRESS + "." +
repository.getId(),
+ ConfigurationProperties.HTTP_LOCAL_ADDRESS);
+ if (bindAddress == null) {
+ return null;
+ }
+ try {
+ return InetAddress.getByName(bindAddress);
+ } catch (UnknownHostException uhe) {
+ throw new IllegalArgumentException(
+ "Given bind address (" + bindAddress + ") cannot be
resolved for remote repository " + repository,
+ uhe);
+ }
+ }
+}
diff --git
a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk/pom.xml
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-21/pom.xml
similarity index 55%
copy from
maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk/pom.xml
copy to
maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-21/pom.xml
index f6b32f9a..74310123 100644
--- a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk/pom.xml
+++
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-21/pom.xml
@@ -26,15 +26,17 @@
<version>2.0.0-SNAPSHOT</version>
</parent>
- <artifactId>maven-resolver-transport-jdk</artifactId>
+ <artifactId>maven-resolver-transport-jdk-21</artifactId>
<packaging>jar</packaging>
- <name>Maven Artifact Resolver Transport JDK (mr)</name>
+ <name>Maven Artifact Resolver Transport JDK (21)</name>
<description>Maven Artifact Transport JDK Java 11+.</description>
<properties>
<Automatic-Module-Name>org.apache.maven.resolver.transport.jdk</Automatic-Module-Name>
<Bundle-SymbolicName>${Automatic-Module-Name}</Bundle-SymbolicName>
+
+ <javaVersion>19</javaVersion>
</properties>
<dependencies>
@@ -59,56 +61,14 @@
</dependencies>
<build>
- <resources>
- <resource>
- <filtering>false</filtering>
- <directory>${project.build.directory}/generated-resources</directory>
- </resource>
- </resources>
<plugins>
<plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>java8</id>
- <goals>
- <goal>unpack</goal>
- </goals>
- <phase>generate-resources</phase>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.apache.maven.resolver</groupId>
- <artifactId>maven-resolver-transport-jdk-8</artifactId>
- <version>${project.version}</version>
- <type>jar</type>
-
<outputDirectory>${project.build.directory}/generated-resources</outputDirectory>
- <excludes>META-INF/maven/**</excludes>
- </artifactItem>
- </artifactItems>
- </configuration>
- </execution>
- <execution>
- <id>java11</id>
- <goals>
- <goal>unpack</goal>
- </goals>
- <phase>generate-resources</phase>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.apache.maven.resolver</groupId>
- <artifactId>maven-resolver-transport-jdk-11</artifactId>
- <version>${project.version}</version>
- <type>jar</type>
-
<outputDirectory>${project.build.directory}/generated-resources/META-INF/versions/11</outputDirectory>
- <includes>**/*.class</includes>
- </artifactItem>
- </artifactItems>
- </configuration>
- </execution>
- </executions>
+ <groupId>org.eclipse.sisu</groupId>
+ <artifactId>sisu-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>biz.aQute.bnd</groupId>
+ <artifactId>bnd-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -116,9 +76,6 @@
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
- <manifestEntries>
- <Multi-Release>true</Multi-Release>
- </manifestEntries>
</archive>
</configuration>
</plugin>
diff --git
a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-21/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporterCustomizer.java
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-21/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporterCustomizer.java
new file mode 100644
index 00000000..51b8b9f3
--- /dev/null
+++
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk-21/src/main/java/org/eclipse/aether/transport/jdk/JdkHttpTransporterCustomizer.java
@@ -0,0 +1,70 @@
+/*
+ * 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.eclipse.aether.transport.jdk;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.net.http.HttpClient;
+
+import org.eclipse.aether.ConfigurationProperties;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.util.ConfigUtils;
+
+/**
+ * JDK Transport customizer.
+ *
+ * @since TBD
+ */
+final class JdkHttpTransporterCustomizer {
+ private JdkHttpTransporterCustomizer() {}
+
+ static void customizeBuilder(
+ RepositorySystemSession session, RemoteRepository repository,
HttpClient.Builder builder) {
+ InetAddress localAddress = getHttpLocalAddress(session, repository);
+ if (localAddress != null) {
+ builder.localAddress(localAddress);
+ }
+ }
+
+ static void customizeHttpClient(RepositorySystemSession session,
RemoteRepository repository, HttpClient client) {
+ // TODO: register client.close(); once onSessionClose feature present
+ }
+
+ /**
+ * Returns non-null {@link InetAddress} if set in configuration, {@code
null} otherwise.
+ */
+ private static InetAddress getHttpLocalAddress(RepositorySystemSession
session, RemoteRepository repository) {
+ String bindAddress = ConfigUtils.getString(
+ session,
+ null,
+ ConfigurationProperties.HTTP_LOCAL_ADDRESS + "." +
repository.getId(),
+ ConfigurationProperties.HTTP_LOCAL_ADDRESS);
+ if (bindAddress == null) {
+ return null;
+ }
+ try {
+ return InetAddress.getByName(bindAddress);
+ } catch (UnknownHostException uhe) {
+ throw new IllegalArgumentException(
+ "Given bind address (" + bindAddress + ") cannot be
resolved for remote repository " + repository,
+ uhe);
+ }
+ }
+}
diff --git
a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk/pom.xml
b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk/pom.xml
index f6b32f9a..b90c1cb9 100644
--- a/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk/pom.xml
+++ b/maven-resolver-transport-jdk-parent/maven-resolver-transport-jdk/pom.xml
@@ -38,6 +38,33 @@
</properties>
<dependencies>
+ <!-- These dependencies are actually included in this multi-release JAR -->
+ <dependency>
+ <groupId>org.apache.maven.resolver</groupId>
+ <artifactId>maven-resolver-transport-jdk-8</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.resolver</groupId>
+ <artifactId>maven-resolver-transport-jdk-11</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.resolver</groupId>
+ <artifactId>maven-resolver-transport-jdk-19</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.resolver</groupId>
+ <artifactId>maven-resolver-transport-jdk-21</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ </dependency>
+
+ <!-- Real dependencies -->
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-api</artifactId>
@@ -66,6 +93,21 @@
</resource>
</resources>
<plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>enforce-bytecode-version</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
@@ -108,6 +150,44 @@
</artifactItems>
</configuration>
</execution>
+ <execution>
+ <id>java19</id>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.maven.resolver</groupId>
+ <artifactId>maven-resolver-transport-jdk-19</artifactId>
+ <version>${project.version}</version>
+ <type>jar</type>
+
<outputDirectory>${project.build.directory}/generated-resources/META-INF/versions/19</outputDirectory>
+ <includes>**/*.class</includes>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ <execution>
+ <id>java21</id>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.apache.maven.resolver</groupId>
+ <artifactId>maven-resolver-transport-jdk-21</artifactId>
+ <version>${project.version}</version>
+ <type>jar</type>
+
<outputDirectory>${project.build.directory}/generated-resources/META-INF/versions/21</outputDirectory>
+ <includes>**/*.class</includes>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
</executions>
</plugin>
<plugin>
diff --git a/maven-resolver-transport-jdk-parent/pom.xml
b/maven-resolver-transport-jdk-parent/pom.xml
index d25f5805..78a50786 100644
--- a/maven-resolver-transport-jdk-parent/pom.xml
+++ b/maven-resolver-transport-jdk-parent/pom.xml
@@ -35,6 +35,8 @@
<modules>
<module>maven-resolver-transport-jdk-8</module>
<module>maven-resolver-transport-jdk-11</module>
+ <module>maven-resolver-transport-jdk-19</module>
+ <module>maven-resolver-transport-jdk-21</module>
<module>maven-resolver-transport-jdk</module>
</modules>
diff --git a/src/site/markdown/configuration.md
b/src/site/markdown/configuration.md
index d8bffd8e..acd48b5f 100644
--- a/src/site/markdown/configuration.md
+++ b/src/site/markdown/configuration.md
@@ -34,11 +34,11 @@ Option | Type | Description | Default Value | Supports Repo
ID Suffix
`aether.connector.basic.parallelPut` | boolean | Enables or disables parallel
PUT processing (parallel deploys) on basic connector globally or per remote
repository. When disabled, connector behaves exactly as in Maven 3.8.x did:
GETs are parallel while PUTs are sequential. | `true` | yes
`aether.connector.classpath.loader` | ClassLoader | `ClassLoader` from which
resources should be retrieved which start with the `classpath:` protocol. |
`Thread.currentThread().getContextClassLoader()` | no
`aether.connector.connectTimeout` | long | Connect timeout in milliseconds. |
`10000` | yes
-`aether.connector.http.bind.address` | String | Set the outgoing interface
(globally or per remote repository). Valid values are local accessible IP
addresses or host names. The default will use the system's default route.
Invalid addresses will result in HttpTransport creation failure. | - | yes
`aether.connector.http.cacheState` | boolean | Flag indicating whether a
memory-based cache is used for user tokens, connection managers, expect
continue requests and authentication schemes. | `true` | no
`aether.connector.http.connectionMaxTtl` | int | Total time to live in seconds
for an HTTP connection, after that time, the connection will be dropped (no
matter for how long it was idle). | `300` | yes
`aether.connector.http.credentialEncoding` | String | The encoding/charset to
use when exchanging credentials with HTTP servers. | `"ISO-8859-1"` | yes
`aether.connector.http.headers` | `Map<String, String>` | The request headers
to use for HTTP-based repository connectors. The headers are specified using a
map of strings mapping a header name to its value. The repository-specific
headers map is supposed to be complete, i.e. is not merged with the general
headers map. | - | yes
+`aether.connector.http.localAddress` | String | Set the outgoing interface
(globally or per remote repository). Valid values are local accessible IP
addresses or host names. The default will use the system's default route.
Invalid addresses will result in HttpTransport creation failure. | - | yes
`aether.connector.http.maxConnectionsPerRoute` | int | The maximum concurrent
connections per route HTTP client is allowed to use. | `50` | yes
`aether.connector.http.preemptiveAuth` | boolean | Should HTTP client use
preemptive-authentication for all HTTP verbs (works only w/ BASIC). By default
is disabled, as it is considered less secure. | `false` | yes
`aether.connector.http.preemptivePutAuth` | boolean | Should HTTP client use
preemptive-authentication for HTTP PUTs only (works only w/ BASIC). By default
is enabled (same as Wagon). | `true` | yes