merge of the actual master into 3.x branch
diff --git a/NOTICE.md b/NOTICE.md
index 6f2a9ea..ca03fd1 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -47,7 +47,7 @@
* Copyright: 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
* by the @authors tag.
-Hibernate Validator CDI, 7.0.0.Final
+Hibernate Validator CDI, 7.0.5.Final
* License: Apache License, 2.0
* Project: https://beanvalidation.org/
* Repackaged in org.glassfish.jersey.server.validation.internal.hibernate
@@ -65,7 +65,7 @@
* License: Apache License, 2.0
* Copyright (C) 2009 The JSR-330 Expert Group
-Javassist Version 3.25.0-GA
+Javassist Version 3.29.0-GA
* License: Apache License, 2.0
* Project: http://www.javassist.org/
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
@@ -95,7 +95,7 @@
* Project: http://www.kineticjs.com, https://github.com/ericdrowell/KineticJS
* Copyright: Eric Rowell
-org.objectweb.asm Version 9.3
+org.objectweb.asm Version 9.4
* License: Modified BSD (https://asm.ow2.io/license.html)
* Copyright (c) 2000-2011 INRIA, France Telecom. All rights reserved.
diff --git a/bundles/apidocs/pom.xml b/bundles/apidocs/pom.xml
index 2658a92..073f826 100644
--- a/bundles/apidocs/pom.xml
+++ b/bundles/apidocs/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -63,12 +63,12 @@
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-apache-connector</artifactId>
<version>${project.version}</version>
- <exclusions>
+ <!--<exclusions>
<exclusion>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
- </exclusions>
+ </exclusions>-->
</dependency>
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
diff --git a/connectors/apache-connector/pom.xml b/connectors/apache-connector/pom.xml
index 269b753..b36502a 100644
--- a/connectors/apache-connector/pom.xml
+++ b/connectors/apache-connector/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright (c) 2011, 2022 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2023 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -40,18 +40,6 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
- <exclusions>
- <exclusion>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- <version>${commons.codec.version}</version>
- <scope>test</scope>
</dependency>
<dependency>
diff --git a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java
index fdfbccf..264c453 100644
--- a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java
+++ b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,6 +24,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.net.Socket;
import java.net.URI;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -46,6 +47,7 @@
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import org.glassfish.jersey.client.ClientProperties;
@@ -53,6 +55,7 @@
import org.glassfish.jersey.client.ClientResponse;
import org.glassfish.jersey.client.RequestEntityProcessing;
import org.glassfish.jersey.client.innate.ClientProxy;
+import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
import org.glassfish.jersey.client.spi.Connector;
import org.glassfish.jersey.internal.util.PropertiesHelper;
@@ -103,6 +106,7 @@
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.io.ChunkedOutputStream;
import org.apache.http.io.SessionOutputBuffer;
+import org.apache.http.protocol.HttpContext;
import org.apache.http.util.TextUtils;
import org.apache.http.util.VersionInfo;
@@ -180,6 +184,7 @@
class ApacheConnector implements Connector {
private static final Logger LOGGER = Logger.getLogger(ApacheConnector.class.getName());
+ private static final String JERSEY_REQUEST_ATTR_NAME = "JerseyRequestAttribute";
private static final VersionInfo vi;
private static final String release;
@@ -255,10 +260,16 @@
}
}
+ final boolean useSystemProperties =
+ PropertiesHelper.isProperty(config.getProperties(), ApacheClientProperties.USE_SYSTEM_PROPERTIES);
+
final SSLContext sslContext = client.getSslContext();
final HttpClientBuilder clientBuilder = HttpClientBuilder.create();
- clientBuilder.setConnectionManager(getConnectionManager(client, config, sslContext));
+ if (useSystemProperties) {
+ clientBuilder.useSystemProperties();
+ }
+ clientBuilder.setConnectionManager(getConnectionManager(client, config, sslContext, useSystemProperties));
clientBuilder.setConnectionManagerShared(
PropertiesHelper.getValue(config.getProperties(), ApacheClientProperties.CONNECTION_MANAGER_SHARED, false, null));
clientBuilder.setSSLContext(sslContext);
@@ -337,7 +348,8 @@
private HttpClientConnectionManager getConnectionManager(final Client client,
final Configuration config,
- final SSLContext sslContext) {
+ final SSLContext sslContext,
+ final boolean useSystemProperties) {
final Object cmObject = config.getProperties().get(ApacheClientProperties.CONNECTION_MANAGER);
// Connection manager from configuration.
@@ -355,9 +367,6 @@
}
}
- final boolean useSystemProperties =
- PropertiesHelper.isProperty(config.getProperties(), ApacheClientProperties.USE_SYSTEM_PROPERTIES);
-
// Create custom connection manager.
return createConnectionManager(
client,
@@ -381,15 +390,15 @@
final LayeredConnectionSocketFactory sslSocketFactory;
if (sslContext != null) {
- sslSocketFactory = new SSLConnectionSocketFactory(
+ sslSocketFactory = new SniSSLConnectionSocketFactory(
sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifier);
} else {
if (useSystemProperties) {
- sslSocketFactory = new SSLConnectionSocketFactory(
+ sslSocketFactory = new SniSSLConnectionSocketFactory(
(SSLSocketFactory) SSLSocketFactory.getDefault(),
supportedProtocols, supportedCipherSuites, hostnameVerifier);
} else {
- sslSocketFactory = new SSLConnectionSocketFactory(
+ sslSocketFactory = new SniSSLConnectionSocketFactory(
SSLContexts.createDefault(),
hostnameVerifier);
}
@@ -450,14 +459,16 @@
public ClientResponse apply(final ClientRequest clientRequest) throws ProcessingException {
final HttpUriRequest request = getUriHttpRequest(clientRequest);
final Map<String, String> clientHeadersSnapshot = writeOutBoundHeaders(clientRequest, request);
+ final HttpHost httpHost = getHost(request);
try {
final CloseableHttpResponse response;
final HttpClientContext context = HttpClientContext.create();
+
if (preemptiveBasicAuth) {
final AuthCache authCache = new BasicAuthCache();
final BasicScheme basicScheme = new BasicScheme();
- authCache.put(getHost(request), basicScheme);
+ authCache.put(httpHost, basicScheme);
context.setAuthCache(authCache);
}
@@ -468,7 +479,8 @@
context.setCredentialsProvider(credentialsProvider);
}
- response = client.execute(getHost(request), request, context);
+ context.setAttribute(JERSEY_REQUEST_ATTR_NAME, clientRequest);
+ response = client.execute(httpHost, request, context);
HeaderUtils.checkHeaderChanges(clientHeadersSnapshot, clientRequest.getHeaders(),
this.getClass().getName(), clientRequest.getConfiguration());
@@ -821,4 +833,56 @@
return super.createOutputStream(len, outbuffer);
}
}
+
+ private static final class SniSSLConnectionSocketFactory extends SSLConnectionSocketFactory {
+
+ private final ThreadLocal<HttpContext> httpContexts = new ThreadLocal<>();
+
+ public SniSSLConnectionSocketFactory(final SSLContext sslContext,
+ final String[] supportedProtocols,
+ final String[] supportedCipherSuites,
+ final HostnameVerifier hostnameVerifier) {
+ super(sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifier);
+ }
+
+ public SniSSLConnectionSocketFactory(final javax.net.ssl.SSLSocketFactory socketFactory,
+ final String[] supportedProtocols,
+ final String[] supportedCipherSuites,
+ final HostnameVerifier hostnameVerifier) {
+ super(socketFactory, supportedProtocols, supportedCipherSuites, hostnameVerifier);
+ }
+
+ public SniSSLConnectionSocketFactory(
+ final SSLContext sslContext, final HostnameVerifier hostnameVerifier) {
+ super(sslContext, hostnameVerifier);
+ }
+
+ @Override
+ public Socket createLayeredSocket(
+ final Socket socket,
+ final String target,
+ final int port,
+ final HttpContext context) throws IOException {
+ httpContexts.set(context);
+ try {
+ return super.createLayeredSocket(socket, target, port, context);
+ } finally {
+ httpContexts.remove();
+ }
+ }
+
+ @Override
+ protected void prepareSocket(SSLSocket socket) throws IOException {
+ HttpContext context = httpContexts.get();
+
+ if (context != null) {
+ Object objectRequest = context.getAttribute(JERSEY_REQUEST_ATTR_NAME);
+ if (objectRequest != null) {
+ ClientRequest clientRequest = (ClientRequest) objectRequest;
+ SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().request(clientRequest).build();
+ sniConfig.setSNIServerName(socket);
+ }
+ }
+ }
+ }
}
diff --git a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java
index 9e4e9ac..f7c30a9 100644
--- a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java
+++ b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,6 +24,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
@@ -46,8 +47,10 @@
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
+import org.apache.hc.client5.http.AuthenticationStrategy;
import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
import org.apache.hc.client5.http.HttpRequestRetryStrategy;
import org.apache.hc.client5.http.auth.AuthCache;
@@ -65,6 +68,7 @@
import org.apache.hc.client5.http.impl.auth.BasicAuthCache;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.auth.BasicScheme;
+import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
@@ -86,6 +90,7 @@
import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
import org.apache.hc.core5.http.io.entity.AbstractHttpEntity;
import org.apache.hc.core5.http.io.entity.BufferedHttpEntity;
+import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.util.TextUtils;
import org.apache.hc.core5.util.Timeout;
@@ -95,6 +100,7 @@
import org.glassfish.jersey.client.ClientResponse;
import org.glassfish.jersey.client.RequestEntityProcessing;
import org.glassfish.jersey.client.innate.ClientProxy;
+import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
import org.glassfish.jersey.client.spi.Connector;
import org.glassfish.jersey.internal.util.PropertiesHelper;
@@ -176,6 +182,7 @@
class Apache5Connector implements Connector {
private static final Logger LOGGER = Logger.getLogger(Apache5Connector.class.getName());
+ private static final String JERSEY_REQUEST_ATTR_NAME = "JerseyRequestAttribute";
private static final VersionInfo vi;
private static final String release;
@@ -251,10 +258,17 @@
}
}
+ final boolean useSystemProperties =
+ PropertiesHelper.isProperty(config.getProperties(), Apache5ClientProperties.USE_SYSTEM_PROPERTIES);
+
final SSLContext sslContext = client.getSslContext();
final HttpClientBuilder clientBuilder = HttpClientBuilder.create();
- clientBuilder.setConnectionManager(getConnectionManager(client, config, sslContext));
+ if (useSystemProperties) {
+ clientBuilder.useSystemProperties();
+ }
+
+ clientBuilder.setConnectionManager(getConnectionManager(client, config, sslContext, useSystemProperties));
clientBuilder.setConnectionManagerShared(
PropertiesHelper.getValue(
config.getProperties(),
@@ -341,7 +355,8 @@
private HttpClientConnectionManager getConnectionManager(final Client client,
final Configuration config,
- final SSLContext sslContext) {
+ final SSLContext sslContext,
+ final boolean useSystemProperties) {
final Object cmObject = config.getProperties().get(Apache5ClientProperties.CONNECTION_MANAGER);
// Connection manager from configuration.
@@ -359,9 +374,6 @@
}
}
- final boolean useSystemProperties =
- PropertiesHelper.isProperty(config.getProperties(), Apache5ClientProperties.USE_SYSTEM_PROPERTIES);
-
// Create custom connection manager.
return createConnectionManager(
client,
@@ -385,15 +397,15 @@
final LayeredConnectionSocketFactory sslSocketFactory;
if (sslContext != null) {
- sslSocketFactory = new SSLConnectionSocketFactory(
+ sslSocketFactory = new SniSSLConnectionSocketFactory(
sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifier);
} else {
if (useSystemProperties) {
- sslSocketFactory = new SSLConnectionSocketFactory(
+ sslSocketFactory = new SniSSLConnectionSocketFactory(
(SSLSocketFactory) SSLSocketFactory.getDefault(),
supportedProtocols, supportedCipherSuites, hostnameVerifier);
} else {
- sslSocketFactory = new SSLConnectionSocketFactory(
+ sslSocketFactory = new SniSSLConnectionSocketFactory(
SSLContexts.createDefault(),
hostnameVerifier);
}
@@ -458,12 +470,7 @@
try {
final CloseableHttpResponse response;
final HttpClientContext context = HttpClientContext.create();
- if (preemptiveBasicAuth) {
- final AuthCache authCache = new BasicAuthCache();
- final BasicScheme basicScheme = new BasicScheme();
- authCache.put(getHost(request), basicScheme);
- context.setAuthCache(authCache);
- }
+ final HttpHost httpHost = getHost(request);
// If a request-specific CredentialsProvider exists, use it instead of the default one
CredentialsProvider credentialsProvider =
@@ -472,7 +479,18 @@
context.setCredentialsProvider(credentialsProvider);
}
- response = client.execute(getHost(request), request, context);
+ if (preemptiveBasicAuth) {
+ final AuthCache authCache = new BasicAuthCache();
+ final BasicScheme basicScheme = new BasicScheme();
+ final AuthScope authScope = new AuthScope(httpHost);
+ basicScheme.initPreemptive(credentialsProvider.getCredentials(authScope, context));
+ context.resetAuthExchange(httpHost, basicScheme);
+ authCache.put(httpHost, basicScheme); // must be after initPreemptive
+ context.setAuthCache(authCache);
+ }
+
+ context.setAttribute(JERSEY_REQUEST_ATTR_NAME, clientRequest);
+ response = client.execute(httpHost, request, context);
HeaderUtils.checkHeaderChanges(clientHeadersSnapshot, clientRequest.getHeaders(),
this.getClass().getName(), clientRequest.getConfiguration());
@@ -798,4 +816,77 @@
);
}
}
+
+ private static final class SniSSLConnectionSocketFactory extends SSLConnectionSocketFactory {
+
+ private final ThreadLocal<HttpContext> httpContexts = new ThreadLocal<>();
+
+ public SniSSLConnectionSocketFactory(final SSLContext sslContext,
+ final String[] supportedProtocols,
+ final String[] supportedCipherSuites,
+ final HostnameVerifier hostnameVerifier) {
+ super(sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifier);
+ }
+
+ public SniSSLConnectionSocketFactory(final javax.net.ssl.SSLSocketFactory socketFactory,
+ final String[] supportedProtocols,
+ final String[] supportedCipherSuites,
+ final HostnameVerifier hostnameVerifier) {
+ super(socketFactory, supportedProtocols, supportedCipherSuites, hostnameVerifier);
+ }
+
+ public SniSSLConnectionSocketFactory(
+ final SSLContext sslContext, final HostnameVerifier hostnameVerifier) {
+ super(sslContext, hostnameVerifier);
+ }
+
+ /* Pre 5.2 */
+ @Override
+ public Socket createLayeredSocket(
+ final Socket socket,
+ final String target,
+ final int port,
+ final HttpContext context) throws IOException {
+ httpContexts.set(context);
+ try {
+ return super.createLayeredSocket(socket, target, port, context);
+ } finally {
+ httpContexts.remove();
+ }
+ }
+
+ /* Post 5.2 */
+ public Socket createLayeredSocket(
+ final Socket socket,
+ final String target,
+ final int port,
+ final Object attachment,
+ final HttpContext context) throws IOException {
+ httpContexts.set(context);
+ try {
+ return super.createLayeredSocket(socket, target, port, attachment, context);
+ } finally {
+ httpContexts.remove();
+ }
+ }
+
+ @Override
+ protected void prepareSocket(SSLSocket socket) throws IOException {
+ HttpContext context = httpContexts.get();
+
+ if (context != null) {
+ Object objectRequest = context.getAttribute(JERSEY_REQUEST_ATTR_NAME);
+ if (objectRequest != null) {
+ ClientRequest clientRequest = (ClientRequest) objectRequest;
+ SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().request(clientRequest).build();
+ sniConfig.setSNIServerName(socket);
+
+ final int socketTimeout = ((ClientRequest) objectRequest).resolveProperty(ClientProperties.READ_TIMEOUT, -1);
+ if (socketTimeout >= 0) {
+ socket.setSoTimeout(socketTimeout);
+ }
+ }
+ }
+ }
+ }
}
diff --git a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/ConnectorConfiguration.java b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/ConnectorConfiguration.java
index 39fb0ab..422d919 100644
--- a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/ConnectorConfiguration.java
+++ b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/ConnectorConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -19,6 +19,7 @@
import java.net.CookiePolicy;
import java.net.URI;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -30,6 +31,7 @@
import org.glassfish.jersey.SslConfigurator;
import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
import org.glassfish.jersey.jdk.connector.JdkConnectorProperties;
/**
@@ -57,6 +59,7 @@
private final int responseTimeout;
private final int connectTimeout;
private final ProxyConfiguration proxyConfiguration;
+ private final AtomicReference<SSLParamConfigurator> sniConfigs = new AtomicReference<>(null);
ConnectorConfiguration(Client client, Configuration config) {
final Map<String, Object> properties = config.getProperties();
@@ -170,6 +173,14 @@
return proxyConfiguration;
}
+ void setSniConfig(SSLParamConfigurator sniConfig) {
+ this.sniConfigs.compareAndSet(null, sniConfig);
+ }
+
+ SSLParamConfigurator getSniConfig() {
+ return sniConfigs.get();
+ }
+
@Override
public String toString() {
return "ConnectorConfiguration{"
diff --git a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnection.java b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnection.java
index 2330dd4..d9ea76e 100644
--- a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnection.java
+++ b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -199,7 +199,8 @@
}
- socket = new SslFilter(transportFilter, sslContext, uri.getHost(), configuration.getHostnameVerifier());
+ socket = new SslFilter(transportFilter, sslContext, uri.getHost(),
+ configuration.getHostnameVerifier(), configuration.getSniConfig());
} else {
socket = new TransportFilter(INPUT_BUFFER_SIZE, configuration.getThreadPoolConfig(),
configuration.getContainerIdleTimeout());
diff --git a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnectionPool.java b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnectionPool.java
index 28c7500..b20f00c 100644
--- a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnectionPool.java
+++ b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpConnectionPool.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -16,7 +16,11 @@
package org.glassfish.jersey.jdk.connector.internal;
+import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
+
import java.net.CookieManager;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
@@ -45,10 +49,16 @@
}
void send(HttpRequest httpRequest, CompletionHandler<HttpResponse> completionHandler) {
+ final Map<String, List<Object>> headers = new HashMap<>();
+ httpRequest.getHeaders().forEach((k, v) -> headers.put(k, (List) v));
+ final SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().uri(httpRequest.getUri()).headers(headers).build();
+ connectorConfiguration.setSniConfig(sniConfig);
+
final DestinationConnectionPool.DestinationKey destinationKey = new DestinationConnectionPool.DestinationKey(
- httpRequest.getUri());
+ sniConfig.getSNIUri());
DestinationConnectionPool destinationConnectionPool = destinationPools.get(destinationKey);
+
if (destinationConnectionPool == null) {
synchronized (this) {
// check again while holding the lock
diff --git a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/SslFilter.java b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/SslFilter.java
index 85f4541..979a9ce 100644
--- a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/SslFilter.java
+++ b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/SslFilter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -16,6 +16,8 @@
package org.glassfish.jersey.jdk.connector.internal;
+import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
+
import java.nio.ByteBuffer;
import java.nio.Buffer;
import java.util.LinkedList;
@@ -26,7 +28,6 @@
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLParameters;
/**
@@ -87,7 +88,8 @@
SslFilter(Filter<ByteBuffer, ByteBuffer, ?, ?> downstreamFilter,
SSLContext sslContext,
String serverHost,
- HostnameVerifier customHostnameVerifier) {
+ HostnameVerifier customHostnameVerifier,
+ SSLParamConfigurator sniConfig) {
super(downstreamFilter);
this.serverHost = serverHost;
sslEngine = sslContext.createSSLEngine(serverHost, -1);
@@ -100,11 +102,11 @@
* when {@link SslEngineConfigurator} supports Java 7.
*/
if (customHostnameVerifier == null) {
- SSLParameters sslParameters = sslEngine.getSSLParameters();
- sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
- sslEngine.setSSLParameters(sslParameters);
+ sniConfig.setEndpointIdentificationAlgorithm(sslEngine);
}
+ sniConfig.setSNIServerName(sslEngine);
+
applicationInputBuffer = ByteBuffer.allocate(sslEngine.getSession().getApplicationBufferSize());
networkOutputBuffer = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize());
}
diff --git a/connectors/jdk-connector/src/test/java/org/glassfish/jersey/jdk/connector/internal/SslFilterTest.java b/connectors/jdk-connector/src/test/java/org/glassfish/jersey/jdk/connector/internal/SslFilterTest.java
index 5d205ce..ef13997 100644
--- a/connectors/jdk-connector/src/test/java/org/glassfish/jersey/jdk/connector/internal/SslFilterTest.java
+++ b/connectors/jdk-connector/src/test/java/org/glassfish/jersey/jdk/connector/internal/SslFilterTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,10 +23,12 @@
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketException;
+import java.net.URI;
import java.nio.ByteBuffer;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
@@ -41,7 +43,9 @@
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
+
import org.glassfish.jersey.SslConfigurator;
+import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
@@ -391,7 +395,10 @@
.keyStorePassword("asdfgh");
TransportFilter transportFilter = new TransportFilter(17_000, ThreadPoolConfig.defaultConfig(), 100_000);
- final SslFilter sslFilter = new SslFilter(transportFilter, sslConfig.createSSLContext(), host, customHostnameVerifier);
+ final SSLParamConfigurator sslParamConfigurator = SSLParamConfigurator.builder()
+ .uri(URI.create("Https://" + host)).headers(Collections.emptyMap()).build();
+ final SslFilter sslFilter = new SslFilter(
+ transportFilter, sslConfig.createSSLContext(), host, customHostnameVerifier, sslParamConfigurator);
// exceptions errors that occur before SSL handshake has finished are thrown from this method
final AtomicReference<Throwable> exception = new AtomicReference<>();
diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
index 5d52e76..5a776b6 100644
--- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
+++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -83,6 +83,7 @@
import org.glassfish.jersey.client.ClientRequest;
import org.glassfish.jersey.client.ClientResponse;
import org.glassfish.jersey.client.innate.ClientProxy;
+import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
import org.glassfish.jersey.client.spi.Connector;
import org.glassfish.jersey.message.internal.OutboundMessageContext;
@@ -278,17 +279,20 @@
(String[]) null, /* enable default protocols */
false /* true if the first write request shouldn't be encrypted */
);
- int port = requestUri.getPort();
- SslHandler sslHandler = jdkSslContext.newHandler(ch.alloc(), requestUri.getHost(),
- port <= 0 ? 443 : port, executorService);
+
+ final int port = requestUri.getPort();
+ final SSLParamConfigurator sslConfig = SSLParamConfigurator.builder()
+ .request(jerseyRequest).setSNIAlways(true).build();
+ final SslHandler sslHandler = jdkSslContext.newHandler(
+ ch.alloc(), sslConfig.getSNIHostName(), port <= 0 ? 443 : port, executorService
+ );
if (ClientProperties.getValue(config.getProperties(),
NettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION, true)) {
- SSLEngine sslEngine = sslHandler.engine();
- SSLParameters sslParameters = sslEngine.getSSLParameters();
- sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
- sslEngine.setSSLParameters(sslParameters);
+ sslConfig.setEndpointIdentificationAlgorithm(sslHandler.engine());
}
+ sslConfig.setSNIServerName(sslHandler.engine());
+
p.addLast(sslHandler);
}
@@ -374,7 +378,9 @@
setHeaders(jerseyRequest, nettyRequest.headers());
// host header - http 1.1
- nettyRequest.headers().add(HttpHeaderNames.HOST, jerseyRequest.getUri().getHost());
+ if (!nettyRequest.headers().contains(HttpHeaderNames.HOST)) {
+ nettyRequest.headers().add(HttpHeaderNames.HOST, jerseyRequest.getUri().getHost());
+ }
if (jerseyRequest.hasEntity()) {
// guard against prematurely closed channel
diff --git a/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/FollowRedirectsTest.java b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/FollowRedirectsTest.java
index f675270..3a1cf69 100644
--- a/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/FollowRedirectsTest.java
+++ b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/FollowRedirectsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -20,6 +20,7 @@
import static org.junit.jupiter.api.Assertions.fail;
import java.net.URI;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Logger;
import jakarta.ws.rs.GET;
@@ -37,12 +38,20 @@
import org.glassfish.jersey.netty.connector.internal.RedirectException;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class FollowRedirectsTest extends JerseyTest {
private static final Logger LOGGER = Logger.getLogger(FollowRedirectsTest.class.getName());
- private static final String TEST_URL = "http://localhost:9998/test";
+ private static final String TEST_URL = "http://localhost:%d/test";
+ private static final AtomicReference<String> TEST_URL_REF = new AtomicReference<>();
+
+ @BeforeEach
+ public void before() {
+ final String url = String.format(TEST_URL, getPort());
+ TEST_URL_REF.set(url);
+ }
@Path("/test")
public static class RedirectResource {
@@ -54,19 +63,19 @@
@GET
@Path("redirect")
public Response redirect() {
- return Response.seeOther(URI.create(TEST_URL)).build();
+ return Response.seeOther(URI.create(TEST_URL_REF.get())).build();
}
@GET
@Path("loop")
public Response loop() {
- return Response.seeOther(URI.create(TEST_URL + "/loop")).build();
+ return Response.seeOther(URI.create(TEST_URL_REF.get() + "/loop")).build();
}
@GET
@Path("redirect2")
public Response redirect2() {
- return Response.seeOther(URI.create(TEST_URL + "/redirect")).build();
+ return Response.seeOther(URI.create(TEST_URL_REF.get() + "/redirect")).build();
}
}
diff --git a/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/AbstractJdkHttpServerTester.java b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/AbstractJdkHttpServerTester.java
index 4f769f2..3886ea9 100644
--- a/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/AbstractJdkHttpServerTester.java
+++ b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/AbstractJdkHttpServerTester.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,6 +21,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import jakarta.ws.rs.RuntimeType;
import jakarta.ws.rs.core.UriBuilder;
import com.sun.net.httpserver.HttpServer;
@@ -37,7 +38,7 @@
public abstract class AbstractJdkHttpServerTester {
public static final String CONTEXT = "";
- private final int DEFAULT_PORT = 9998;
+ private final int DEFAULT_PORT = 0; // rather JDK server choose than 9998
private static final Logger LOGGER = Logger.getLogger(AbstractJdkHttpServerTester.class.getName());
@@ -47,6 +48,9 @@
* @return The HTTP port of the URI
*/
protected final int getPort() {
+ if (server != null) {
+ return server.getAddress().getPort();
+ }
final String value =
AccessController.doPrivileged(PropertiesHelper.getSystemProperty("jersey.config.test.container.port"));
if (value != null) {
@@ -68,10 +72,20 @@
return DEFAULT_PORT;
}
+ private final int getPort(RuntimeType runtimeType) {
+ switch (runtimeType) {
+ case SERVER:
+ return getPort();
+ case CLIENT:
+ return server.getAddress().getPort();
+ default:
+ throw new IllegalStateException("Unexpected runtime type");
+ }
+ }
private volatile HttpServer server;
public UriBuilder getUri() {
- return UriBuilder.fromUri("http://localhost").port(getPort()).path(CONTEXT);
+ return UriBuilder.fromUri("http://localhost").port(getPort(RuntimeType.CLIENT)).path(CONTEXT);
}
public void startServer(Class... resources) {
@@ -79,18 +93,18 @@
config.register(LoggingFeature.class);
final URI baseUri = getBaseUri();
server = JdkHttpServerFactory.createHttpServer(baseUri, config);
- LOGGER.log(Level.INFO, "jdk-http server started on base uri: " + baseUri);
+ LOGGER.log(Level.INFO, "jdk-http server started on base uri: " + server.getAddress());
}
public void startServer(ResourceConfig config) {
final URI baseUri = getBaseUri();
config.register(LoggingFeature.class);
server = JdkHttpServerFactory.createHttpServer(baseUri, config);
- LOGGER.log(Level.INFO, "jdk-http server started on base uri: " + baseUri);
+ LOGGER.log(Level.INFO, "jdk-http server started on base uri: " + server.getAddress());
}
public URI getBaseUri() {
- return UriBuilder.fromUri("http://localhost/").port(getPort()).build();
+ return UriBuilder.fromUri("http://localhost/").port(getPort(RuntimeType.SERVER)).build();
}
public void stopServer() {
diff --git a/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java
index 0ad2944..472d5ed 100644
--- a/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java
+++ b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -116,7 +116,7 @@
// access the https server with not configured client
final Client client = ClientBuilder.newBuilder().newClient();
try {
- client.target(httpsUri).path("testHttps").request().get(String.class);
+ client.target(updatePort(httpsUri)).path("testHttps").request().get(String.class);
} catch (final ProcessingException e) {
throw e.getCause();
}
@@ -136,8 +136,8 @@
server.start();
final Client client = ClientBuilder.newBuilder().newClient();
- try {
- client.target(httpsUri).path("testHttps").request().get(String.class);
+ try {
+ client.target(updatePort(httpsUri)).path("testHttps").request().get(String.class);
} catch (final ProcessingException e) {
throw e.getCause();
}
@@ -173,7 +173,7 @@
final SSLContext clientSslContext = getClientSslContext();
final Client client = ClientBuilder.newBuilder().sslContext(clientSslContext).build();
- final String response = client.target(httpsUri).path("testHttps").request().get(String.class);
+ final String response = client.target(updatePort(httpsUri)).path("testHttps").request().get(String.class);
assertEquals("test", response);
}
@@ -216,6 +216,11 @@
return sslConfigServer.createSSLContext();
}
+
+ private URI updatePort(URI uri) {
+ return UriBuilder.fromUri(httpsUri).port(server.getAddress().getPort()).build();
+ }
+
@AfterEach
public void tearDown() {
if (server != null) {
diff --git a/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/AbstractJettyServerTester.java b/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/AbstractJettyServerTester.java
index 1d7cac2..3a953e1 100644
--- a/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/AbstractJettyServerTester.java
+++ b/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/AbstractJettyServerTester.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,6 +21,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import jakarta.ws.rs.RuntimeType;
import jakarta.ws.rs.core.UriBuilder;
import org.glassfish.jersey.logging.LoggingFeature;
@@ -42,7 +43,7 @@
private static final Logger LOGGER = Logger.getLogger(AbstractJettyServerTester.class.getName());
public static final String CONTEXT = "";
- private static final int DEFAULT_PORT = 9998;
+ private static final int DEFAULT_PORT = 0; // rather Jetty choose than 9998
/**
* Get the port to be used for test application deployments.
@@ -71,10 +72,21 @@
return DEFAULT_PORT;
}
+ private final int getPort(RuntimeType runtimeType) {
+ switch (runtimeType) {
+ case SERVER:
+ return getPort();
+ case CLIENT:
+ return server.getURI().getPort();
+ default:
+ throw new IllegalStateException("Unexpected runtime type");
+ }
+ }
+
private volatile Server server;
public UriBuilder getUri() {
- return UriBuilder.fromUri("http://localhost").port(getPort()).path(CONTEXT);
+ return UriBuilder.fromUri("http://localhost").port(getPort(RuntimeType.CLIENT)).path(CONTEXT);
}
public void startServer(Class... resources) {
@@ -82,17 +94,17 @@
config.register(new LoggingFeature(LOGGER, LoggingFeature.Verbosity.PAYLOAD_ANY));
final URI baseUri = getBaseUri();
server = JettyHttpContainerFactory.createServer(baseUri, config);
- LOGGER.log(Level.INFO, "Jetty-http server started on base uri: " + baseUri);
+ LOGGER.log(Level.INFO, "Jetty-http server started on base uri: " + server.getURI());
}
public void startServer(ResourceConfig config) {
final URI baseUri = getBaseUri();
server = JettyHttpContainerFactory.createServer(baseUri, config);
- LOGGER.log(Level.INFO, "Jetty-http server started on base uri: " + baseUri);
+ LOGGER.log(Level.INFO, "Jetty-http server started on base uri: " + server.getURI());
}
public URI getBaseUri() {
- return UriBuilder.fromUri("http://localhost/").port(getPort()).build();
+ return UriBuilder.fromUri("http://localhost/").port(getPort(RuntimeType.SERVER)).build();
}
public void stopServer() {
diff --git a/containers/simple-http/src/test/java/org/glassfish/jersey/simple/AbstractSimpleServerTester.java b/containers/simple-http/src/test/java/org/glassfish/jersey/simple/AbstractSimpleServerTester.java
index d36c54f..3543e50 100644
--- a/containers/simple-http/src/test/java/org/glassfish/jersey/simple/AbstractSimpleServerTester.java
+++ b/containers/simple-http/src/test/java/org/glassfish/jersey/simple/AbstractSimpleServerTester.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,6 +21,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import jakarta.ws.rs.RuntimeType;
import jakarta.ws.rs.core.UriBuilder;
import org.glassfish.jersey.internal.util.PropertiesHelper;
@@ -39,7 +40,7 @@
public abstract class AbstractSimpleServerTester {
public static final String CONTEXT = "";
- private final int DEFAULT_PORT = 9998;
+ private final int DEFAULT_PORT = 0; // rather SimpleFramework server choose than 9998
private static final Logger LOGGER = Logger.getLogger(AbstractSimpleServerTester.class.getName());
@@ -72,10 +73,20 @@
return DEFAULT_PORT;
}
+ private final int getPort(RuntimeType runtimeType) {
+ switch (runtimeType) {
+ case SERVER:
+ return getPort();
+ case CLIENT:
+ return server.getPort();
+ default:
+ throw new IllegalStateException("Unexpected runtime type");
+ }
+ }
private volatile SimpleServer server;
public UriBuilder getUri() {
- return UriBuilder.fromUri("http://localhost").port(getPort()).path(CONTEXT);
+ return UriBuilder.fromUri("http://localhost").port(getPort(RuntimeType.CLIENT)).path(CONTEXT);
}
public void startServer(Class... resources) {
@@ -83,21 +94,21 @@
config.register(LoggingFeature.class);
final URI baseUri = getBaseUri();
server = SimpleContainerFactory.create(baseUri, config);
- LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + baseUri);
+ LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + baseUri.getHost() + ":" + server.getPort());
}
public void startServerNoLoggingFilter(Class... resources) {
ResourceConfig config = new ResourceConfig(resources);
final URI baseUri = getBaseUri();
server = SimpleContainerFactory.create(baseUri, config);
- LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + baseUri);
+ LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + baseUri.getHost() + ":" + server.getPort());
}
public void startServer(ResourceConfig config) {
final URI baseUri = getBaseUri();
config.register(LoggingFeature.class);
server = SimpleContainerFactory.create(baseUri, config);
- LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + baseUri);
+ LOGGER.log(Level.INFO, "Simple-http server started on base uri: " + baseUri.getHost() + ":" + server.getPort());
}
public void startServer(ResourceConfig config, int count, int select) {
@@ -108,7 +119,7 @@
}
public URI getBaseUri() {
- return UriBuilder.fromUri("http://localhost/").port(getPort()).build();
+ return UriBuilder.fromUri("http://localhost/").port(getPort(RuntimeType.SERVER)).build();
}
public void setDebug(boolean enable) {
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ChunkedInputReader.java b/core-client/src/main/java/org/glassfish/jersey/client/ChunkedInputReader.java
index 72374cc..8ecbfaa 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ChunkedInputReader.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ChunkedInputReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -43,10 +43,15 @@
@ConstrainedTo(RuntimeType.CLIENT)
class ChunkedInputReader implements MessageBodyReader<ChunkedInput> {
+ private final Provider<MessageBodyWorkers> messageBodyWorkers;
+ private final Provider<PropertiesDelegate> propertiesDelegateProvider;
+
@Inject
- private Provider<MessageBodyWorkers> messageBodyWorkers;
- @Inject
- private Provider<PropertiesDelegate> propertiesDelegateProvider;
+ public ChunkedInputReader(Provider<MessageBodyWorkers> messageBodyWorkers,
+ Provider<PropertiesDelegate> propertiesDelegateProvider) {
+ this.messageBodyWorkers = messageBodyWorkers;
+ this.propertiesDelegateProvider = propertiesDelegateProvider;
+ }
@Override
public boolean isReadable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java
index 43737f1..4dca460 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018 Payara Foundation and/or its affiliates.
*
* This program and the accompanying materials are made available under the
@@ -35,6 +35,7 @@
import org.glassfish.jersey.CommonProperties;
import org.glassfish.jersey.ExtendedConfig;
import org.glassfish.jersey.client.internal.LocalizationMessages;
+import org.glassfish.jersey.client.innate.inject.NonInjectionManager;
import org.glassfish.jersey.client.internal.inject.ParameterUpdaterConfigurator;
import org.glassfish.jersey.client.spi.Connector;
import org.glassfish.jersey.client.spi.ConnectorProvider;
@@ -410,7 +411,7 @@
final State runtimeCfgState = this.copy();
runtimeCfgState.markAsShared();
- InjectionManager injectionManager = Injections.createInjectionManager();
+ final InjectionManager injectionManager = findInjectionManager();
injectionManager.register(new ClientBinder(runtimeCfgState.getProperties()));
final ClientBootstrapBag bootstrapBag = new ClientBootstrapBag();
@@ -471,6 +472,14 @@
return crt;
}
+ private final InjectionManager findInjectionManager() {
+ try {
+ return Injections.createInjectionManager(RuntimeType.CLIENT);
+ } catch (IllegalStateException ise) {
+ return new NonInjectionManager(true);
+ }
+ }
+
@Override
public boolean equals(final Object o) {
if (this == o) {
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/filter/EncodingFilter.java b/core-client/src/main/java/org/glassfish/jersey/client/filter/EncodingFilter.java
index 7b99abd..8d773a6 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/filter/EncodingFilter.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/filter/EncodingFilter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -49,10 +49,15 @@
* @author Martin Matula
*/
public final class EncodingFilter implements ClientRequestFilter {
- @Inject
- private InjectionManager injectionManager;
+
+ private final InjectionManager injectionManager;
private volatile List<Object> supportedEncodings = null;
+ @Inject
+ public EncodingFilter(InjectionManager injectionManager) {
+ this.injectionManager = injectionManager;
+ }
+
@Override
public void filter(ClientRequestContext request) throws IOException {
if (getSupportedEncodings().isEmpty()) {
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java
new file mode 100644
index 0000000..33ef0b6
--- /dev/null
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SSLParamConfigurator.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.client.innate.http;
+
+import org.glassfish.jersey.client.ClientRequest;
+
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+import jakarta.ws.rs.core.UriBuilder;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * A unified routines to configure {@link SSLParameters}.
+ * To be reused in connectors.
+ */
+public final class SSLParamConfigurator {
+ private final URI uri;
+ private final Map<String, List<Object>> httpHeaders;
+ private final Optional<SniConfigurator> sniConfigurator;
+
+ /**
+ * Builder of the {@link SSLParamConfigurator} instance.
+ */
+ public static final class Builder {
+ private ClientRequest clientRequest;
+ private URI uri;
+ private Map<String, List<Object>> httpHeaders;
+ private boolean setAlways = false;
+
+ /**
+ * Sets the {@link ClientRequest} instance.
+ * @param clientRequest the {@link ClientRequest}
+ * @return the builder instance
+ */
+ public Builder request(ClientRequest clientRequest) {
+ this.clientRequest = clientRequest;
+ this.httpHeaders = null;
+ this.uri = null;
+ return this;
+ }
+
+ /**
+ * Sets the HTTP request {@link URI} instance.
+ * @param uri The request uri
+ * @return the builder instance
+ */
+ public Builder uri(URI uri) {
+ this.clientRequest = null;
+ this.uri = uri;
+ return this;
+ }
+
+ /**
+ * Sets the HTTP request headers
+ * @param httpHeaders the http request headers
+ * @return the builder instance
+ */
+ public Builder headers(Map<String, List<Object>> httpHeaders) {
+ this.clientRequest = null;
+ this.httpHeaders = httpHeaders;
+ return this;
+ }
+
+ /**
+ * Sets SNI only when {@link jakarta.ws.rs.core.HttpHeaders#HOST} differs from the request host name if set to
+ * {@code false}. Default is {@code false}.
+ * @param setAlways set SNI always (default)
+ * @return the builder instance
+ */
+ public Builder setSNIAlways(boolean setAlways) {
+ this.setAlways = setAlways;
+ return this;
+ }
+
+ /**
+ * Builds the {@link SSLParamConfigurator} instance.
+ * @return the configured {@link SSLParamConfigurator} instance.
+ */
+ public SSLParamConfigurator build() {
+ return new SSLParamConfigurator(this);
+ }
+ }
+
+ private SSLParamConfigurator(SSLParamConfigurator.Builder builder) {
+ this.uri = builder.clientRequest != null ? builder.clientRequest.getUri() : builder.uri;
+ this.httpHeaders = builder.clientRequest != null ? builder.clientRequest.getHeaders() : builder.httpHeaders;
+ sniConfigurator = SniConfigurator.createWhenHostHeader(uri, httpHeaders, builder.setAlways);
+ }
+
+ /**
+ * Create a new instance of TlsSupport class
+ **/
+ public static SSLParamConfigurator.Builder builder() {
+ return new SSLParamConfigurator.Builder();
+ }
+
+ /**
+ * Get the host name either set by the request URI or by
+ * {@link jakarta.ws.rs.core.HttpHeaders#HOST} header if it differs from HTTP request host name.
+ * @return the hostName the {@link SSLEngine} is to use.
+ */
+ public String getSNIHostName() {
+ return sniConfigurator.isPresent() ? sniConfigurator.get().getHostName() : uri.getHost();
+ }
+
+ /**
+ * Replaces hostname within the {@link ClientRequest} uri with a resolved IP address. Should the hostname be not known,
+ * the original request URI is returned. The purpose of this method is to replace the host with the IP so that
+ * {code HttpUrlConnection} does not replace user defined {@link javax.net.ssl.SNIHostName} with the host from the request
+ * uri.
+ * @return the request uri with ip address of the resolved host.
+ */
+ public URI toIPRequestUri() {
+ String host = uri.getHost();
+ try {
+ InetAddress ip = InetAddress.getByName(host);
+ return UriBuilder.fromUri(uri).host(ip.getHostAddress()).build();
+ } catch (UnknownHostException e) {
+ return uri;
+ }
+ }
+
+ /**
+ * Return true iff SNI is to be set, i.e.
+ * {@link jakarta.ws.rs.core.HttpHeaders#HOST} header if it differs from HTTP request host name.
+ * @return Return {@code true} when {@link javax.net.ssl.SNIHostName} is to be set.
+ */
+ public boolean isSNIRequired() {
+ return sniConfigurator.isPresent();
+ }
+
+ /**
+ * Get the request URI or altered by {@link jakarta.ws.rs.core.HttpHeaders#HOST} header.
+ * @return The possibly altered request URI.
+ * @see #getSNIHostName()
+ */
+ public URI getSNIUri() {
+ return sniConfigurator.isPresent() ? UriBuilder.fromUri(uri).host(getSNIHostName()).build() : uri;
+ }
+
+ /**
+ * Set {@link javax.net.ssl.SNIServerName} for the {@link SSLParameters} when SNI should be used
+ * (i.e. {@link jakarta.ws.rs.core.HttpHeaders#HOST} differs from HTTP request host name)
+ * @param sslEngine the {@link SSLEngine} the {@link SSLParameters} are set for.
+ */
+ public void setSNIServerName(SSLEngine sslEngine) {
+ sniConfigurator.ifPresent(sni -> sni.setServerNames(sslEngine));
+ }
+
+
+ /**
+ * Set {@link javax.net.ssl.SNIServerName} for the {@link SSLParameters} when SNI should be used
+ * (i.e. {@link jakarta.ws.rs.core.HttpHeaders#HOST} differs from HTTP request host name)
+ * @param sslSocket the {@link SSLSocket} the {@link SSLParameters} are set for.
+ */
+ public void setSNIServerName(SSLSocket sslSocket) {
+ sniConfigurator.ifPresent(sni -> sni.setServerNames(sslSocket));
+ }
+
+ /**
+ * Set setEndpointIdentificationAlgorithm to HTTPS. This is to prevent man-in-the-middle attacks.
+ * @param sslEngine the {@link SSLEngine} the algorithm is set for.
+ * @see SSLParameters#setEndpointIdentificationAlgorithm(String)
+ */
+ public void setEndpointIdentificationAlgorithm(SSLEngine sslEngine) {
+ SSLParameters sslParameters = sslEngine.getSSLParameters();
+ sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
+ sslEngine.setSSLParameters(sslParameters);
+ }
+}
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java
new file mode 100644
index 0000000..39a339d
--- /dev/null
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.client.innate.http;
+
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SNIServerName;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+import jakarta.ws.rs.core.HttpHeaders;
+import java.net.URI;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * A unified routines to set {@link SNIHostName} for the {@link javax.net.ssl.SSLContext}.
+ * To be reused in connectors.
+ */
+final class SniConfigurator {
+ private final String hostName;
+ private SniConfigurator(String hostName) {
+ this.hostName = hostName;
+ }
+
+ /**
+ * Get the hostName from the {@link HttpHeaders#HOST} header.
+ * @return
+ */
+ String getHostName() {
+ return hostName;
+ }
+
+ /**
+ * Create ClientSNI when {@link HttpHeaders#HOST} is set different from the request URI host (or {@code whenDiffer}.is false).
+ * @param hostUri the Uri of the HTTP request
+ * @param headers the HttpHeaders
+ * @param whenDiffer create {@SniConfigurator only when different from the request URI host}
+ * @return ClientSNI or empty when {@link HttpHeaders#HOST}
+ */
+ static Optional<SniConfigurator> createWhenHostHeader(URI hostUri, Map<String, List<Object>> headers, boolean whenDiffer) {
+ List<Object> hostHeaders = headers.get(HttpHeaders.HOST);
+ if (hostHeaders == null || hostHeaders.get(0) == null) {
+ return Optional.empty();
+ }
+
+ final String hostHeader = hostHeaders.get(0).toString();
+ final String trimmedHeader;
+ if (hostHeader != null) {
+ int index = hostHeader.indexOf(':'); // RFC 7230 Host = uri-host [ ":" port ] ;
+ final String trimmedHeader0 = index != -1 ? hostHeader.substring(0, index).trim() : hostHeader.trim();
+ trimmedHeader = trimmedHeader0.isEmpty() ? hostHeader : trimmedHeader0;
+ } else {
+ return Optional.empty();
+ }
+
+ final String hostUriString = hostUri.getHost();
+ if (!whenDiffer && hostUriString.equals(trimmedHeader)) {
+ return Optional.empty();
+ }
+
+ return Optional.of(new SniConfigurator(trimmedHeader));
+ }
+
+ /**
+ * Set {@link SNIServerName} for the given {@link SSLEngine} SSLParameters.
+ * @param sslEngine
+ */
+ void setServerNames(SSLEngine sslEngine) {
+ SSLParameters sslParameters = sslEngine.getSSLParameters();
+ updateSSLParameters(sslParameters);
+ sslEngine.setSSLParameters(sslParameters);
+ }
+
+ /**
+ * Set {@link SNIServerName} for the given {@link SSLSocket} SSLParameters.
+ * @param sslSocket
+ */
+ void setServerNames(SSLSocket sslSocket) {
+ SSLParameters sslParameters = sslSocket.getSSLParameters();
+ updateSSLParameters(sslParameters);
+ sslSocket.setSSLParameters(sslParameters);
+ }
+
+ private SSLParameters updateSSLParameters(SSLParameters sslParameters) {
+ SNIHostName serverName = new SNIHostName(hostName);
+ List<SNIServerName> serverNames = new LinkedList<>();
+ serverNames.add(serverName);
+
+ sslParameters.setServerNames(serverNames);
+
+ return sslParameters;
+ }
+
+}
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/package-info.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/package-info.java
new file mode 100644
index 0000000..bbedce0
--- /dev/null
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/**
+ * Jersey client MOST INTERNAL http related classes/interfaces.
+ * Shall not be used outside of Jersey. The module shall not be exported to outside of Jersey.
+ */
+package org.glassfish.jersey.client.innate.http;
\ No newline at end of file
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java
new file mode 100644
index 0000000..7062bab
--- /dev/null
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.client.innate.inject;
+
+import org.glassfish.jersey.client.internal.LocalizationMessages;
+import org.glassfish.jersey.internal.inject.Binder;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.ClassBinding;
+import org.glassfish.jersey.internal.inject.DisposableSupplier;
+import org.glassfish.jersey.internal.inject.ForeignDescriptor;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InstanceBinding;
+import org.glassfish.jersey.internal.inject.PerThread;
+import org.glassfish.jersey.internal.inject.ServiceHolder;
+import org.glassfish.jersey.internal.inject.ServiceHolderImpl;
+import org.glassfish.jersey.internal.inject.SupplierClassBinding;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
+import org.glassfish.jersey.internal.util.collection.LazyValue;
+import org.glassfish.jersey.internal.util.collection.Value;
+import org.glassfish.jersey.internal.util.collection.Values;
+import org.glassfish.jersey.process.internal.RequestScope;
+import org.glassfish.jersey.process.internal.RequestScoped;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.inject.Inject;
+import jakarta.inject.Provider;
+import jakarta.inject.Singleton;
+import jakarta.ws.rs.ConstrainedTo;
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+import jakarta.ws.rs.core.MultivaluedMap;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.function.Supplier;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+@ConstrainedTo(RuntimeType.CLIENT)
+public final class NonInjectionManager implements InjectionManager {
+ private static final Logger logger = Logger.getLogger(NonInjectionManager.class.getName());
+
+ private final MultivaluedMap<Class<?>, InstanceBinding<?>> instanceBindings = new MultivaluedHashMap<>();
+ private final MultivaluedMap<Class<?>, ClassBinding<?>> contractBindings = new MultivaluedHashMap<>();
+ private final MultivaluedMap<Class<?>, SupplierInstanceBinding<?>> supplierInstanceBindings = new MultivaluedHashMap<>();
+ private final MultivaluedMap<Class<?>, SupplierClassBinding<?>> supplierClassBindings = new MultivaluedHashMap<>();
+ private final MultivaluedMap<Type, InstanceBinding<?>> instanceTypeBindings = new MultivaluedHashMap<>();
+ private final MultivaluedMap<Type, ClassBinding<?>> contractTypeBindings = new MultivaluedHashMap<>();
+ private final MultivaluedMap<Type, SupplierInstanceBinding<?>> supplierTypeInstanceBindings = new MultivaluedHashMap<>();
+ private final MultivaluedMap<Type, SupplierClassBinding<?>> supplierTypeClassBindings = new MultivaluedHashMap<>();
+
+ private final MultivaluedMap<DisposableSupplier, Object> disposableSupplierObjects = new MultivaluedHashMap<>();
+
+ private final Instances instances = new Instances();
+ private final Types types = new Types();
+
+ private volatile boolean isRequestScope = false;
+ private volatile boolean shutdown = false;
+
+ /**
+ * A class that holds singleton instances and thread-scope instances. Provides thread safe access to singletons
+ * and thread-scope instances. The instances are created for Type (ParametrizedType) and for a Class.
+ * @param <TYPE> the type for which the instance is created, either Class, or ParametrizedType (for instance
+ * Provider<SomeClass>).
+ */
+ private class TypedInstances<TYPE> {
+ private final MultivaluedMap<TYPE, InstanceContext<?>> singletonInstances = new MultivaluedHashMap<>();
+ private final ThreadLocal<MultivaluedMap<TYPE, InstanceContext<?>>> threadInstances = new ThreadLocal<>();
+ private final List<Object> threadPredestroyables = Collections.synchronizedList(new LinkedList<>());
+
+ private <T> List<InstanceContext<?>> _getSingletons(TYPE clazz) {
+ List<InstanceContext<?>> si;
+ synchronized (singletonInstances) {
+ si = singletonInstances.get(clazz);
+ }
+ return si;
+ }
+
+ @SuppressWarnings("unchecked")
+ <T> T _addSingleton(TYPE clazz, T instance, Binding<?, ?> binding, Annotation[] qualifiers) {
+ synchronized (singletonInstances) {
+ // check existing singleton with a qualifier already created by another thread io a meantime
+ List<InstanceContext<?>> values = singletonInstances.get(clazz);
+ if (values != null) {
+ List<InstanceContext<?>> qualified
+ = values.stream()
+ .filter(ctx -> ctx.hasQualifiers(qualifiers))
+ .collect(Collectors.toList());
+ if (!qualified.isEmpty()) {
+ return (T) qualified.get(0).instance;
+ }
+ }
+ singletonInstances.add(clazz, new InstanceContext<>(instance, binding, qualifiers));
+ threadPredestroyables.add(instance);
+ return instance;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ <T> T addSingleton(TYPE clazz, T t, Binding<?, ?> binding, Annotation[] instanceQualifiers) {
+ T t2 = _addSingleton(clazz, t, binding, instanceQualifiers);
+ if (t2 == t) {
+ for (Type contract : binding.getContracts()) {
+ if (!clazz.equals(contract) && isClass(contract)) {
+ _addSingleton((TYPE) contract, t, binding, instanceQualifiers);
+ }
+ }
+ }
+ return t2;
+ }
+
+ private List<InstanceContext<?>> _getThreadInstances(TYPE clazz) {
+ MultivaluedMap<TYPE, InstanceContext<?>> ti = threadInstances.get();
+ List<InstanceContext<?>> list = ti == null ? null : new LinkedList<>();
+ if (ti != null) {
+ return ti.get(clazz);
+ }
+ return list;
+ }
+
+ private <T> void _addThreadInstance(TYPE clazz, T instance, Binding<T, ?> binding, Annotation[] qualifiers) {
+ MultivaluedMap<TYPE, InstanceContext<?>> map = threadInstances.get();
+ if (map == null) {
+ map = new MultivaluedHashMap<>();
+ threadInstances.set(map);
+ }
+ map.add(clazz, new InstanceContext<>(instance, binding, qualifiers));
+ threadPredestroyables.add(instance);
+ }
+
+ <T> void addThreadInstance(TYPE clazz, T t, Binding<T, ?> binding, Annotation[] instanceQualifiers) {
+ _addThreadInstance(clazz, t, binding, instanceQualifiers);
+ for (Type contract : binding.getContracts()) {
+ if (!clazz.equals(contract) && isClass(contract)) {
+ _addThreadInstance((TYPE) contract, t, binding, instanceQualifiers);
+ }
+ }
+ }
+
+ private <T> List<T> getInstances(TYPE clazz, Annotation[] annotations) {
+ List<InstanceContext<?>> i = _getContexts(clazz);
+ return InstanceContext.toInstances(i, annotations);
+ }
+
+ <T> List<InstanceContext<?>> getContexts(TYPE clazz, Annotation[] annotations) {
+ List<InstanceContext<?>> i = _getContexts(clazz);
+ return InstanceContext.filterInstances(i, annotations);
+ }
+
+ private <T> List<InstanceContext<?>> _getContexts(TYPE clazz) {
+ List<InstanceContext<?>> si = _getSingletons(clazz);
+ List<InstanceContext<?>> ti = _getThreadInstances(clazz);
+ if (si == null && ti != null) {
+ si = ti;
+ } else if (ti != null) {
+ si.addAll(ti);
+ }
+ return si;
+ }
+
+ <T> T getInstance(TYPE clazz, Annotation[] annotations) {
+ List<T> i = getInstances(clazz, annotations);
+ if (i != null) {
+ checkUnique(i);
+ return i.get(0);
+ }
+ return null;
+ }
+
+ void dispose() {
+ singletonInstances.forEach((clazz, instances) -> instances.forEach(instance -> preDestroy(instance.getInstance())));
+ threadPredestroyables.forEach(NonInjectionManager.this::preDestroy);
+ }
+ }
+
+ private class Instances extends TypedInstances<Class<?>> {
+ }
+
+ private class Types extends TypedInstances<Type> {
+ }
+
+ public NonInjectionManager() {
+ }
+
+ public NonInjectionManager(boolean warning) {
+ if (warning) {
+ logger.warning(LocalizationMessages.NONINJECT_FALLBACK());
+ } else {
+ logger.log(Level.FINER, LocalizationMessages.NONINJECT_FALLBACK());
+ }
+ }
+
+ @Override
+ public void completeRegistration() {
+ instances._addSingleton(InjectionManager.class, this, new InjectionManagerBinding(), null);
+ }
+
+ @Override
+ public void shutdown() {
+ shutdown = true;
+
+ disposableSupplierObjects.forEach((supplier, objects) -> objects.forEach(supplier::dispose));
+ disposableSupplierObjects.clear();
+
+ instances.dispose();
+ types.dispose();
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return shutdown;
+ }
+
+ private void checkShutdown() {
+ if (shutdown) {
+ throw new IllegalStateException(LocalizationMessages.NONINJECT_SHUTDOWN());
+ }
+ }
+
+ @Override
+ public void register(Binding binding) {
+ checkShutdown();
+ if (InstanceBinding.class.isInstance(binding)) {
+ InstanceBinding instanceBinding = (InstanceBinding) binding;
+ Class<?> mainType = binding.getImplementationType();
+ if (!instanceBindings.containsKey(mainType)) { // the class could be registered twice, for reader & for writer
+ instanceBindings.add(mainType, (InstanceBinding) binding);
+ }
+ for (Type type : (Iterable<Type>) instanceBinding.getContracts()) {
+ if (isClass(type)) {
+ if (!mainType.equals(type)) {
+ instanceBindings.add((Class<?>) type, instanceBinding);
+ }
+ } else {
+ instanceTypeBindings.add(type, instanceBinding);
+ }
+ }
+ } else if (ClassBinding.class.isInstance(binding)) {
+ ClassBinding<?> contractBinding = (ClassBinding<?>) binding;
+ Class<?> mainType = binding.getImplementationType();
+ if (!contractBindings.containsKey(mainType)) { // the class could be registered twice, for reader & for writer
+ contractBindings.add(mainType, contractBinding);
+ }
+ for (Type type : contractBinding.getContracts()) {
+ if (isClass(type)) {
+ if (!mainType.equals(type)) {
+ contractBindings.add((Class<?>) type, contractBinding);
+ }
+ } else {
+ contractTypeBindings.add(type, contractBinding);
+ }
+ }
+ } else if (SupplierInstanceBinding.class.isInstance(binding)) {
+ SupplierInstanceBinding<?> supplierBinding = (SupplierInstanceBinding<?>) binding;
+ for (Type type : supplierBinding.getContracts()) {
+ if (isClass(type)) {
+ supplierInstanceBindings.add((Class<?>) type, supplierBinding);
+ } else {
+ supplierTypeInstanceBindings.add(type, supplierBinding);
+ }
+ }
+ } else if (SupplierClassBinding.class.isInstance(binding)) {
+ SupplierClassBinding<?> supplierBinding = (SupplierClassBinding<?>) binding;
+ for (Type type : supplierBinding.getContracts()) {
+ if (isClass(type)) {
+ supplierClassBindings.add((Class<?>) type, supplierBinding);
+ } else {
+ supplierTypeClassBindings.add(type, supplierBinding);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void register(Iterable<Binding> descriptors) {
+ checkShutdown();
+ for (Binding binding : descriptors) {
+ register(binding);
+ }
+ }
+
+ @Override
+ public void register(Binder binder) {
+ checkShutdown();
+ binder.getBindings().stream().iterator().forEachRemaining(this::register);
+ }
+
+ @Override
+ public void register(Object provider) throws IllegalArgumentException {
+ throw new UnsupportedOperationException("Register " + provider);
+ }
+
+ @Override
+ public boolean isRegistrable(Class<?> clazz) {
+ return false; // for external creators
+ }
+
+ @Override
+ public <T> List<ServiceHolder<T>> getAllServiceHolders(Class<T> contractOrImpl, Annotation... qualifiers) {
+ checkShutdown();
+
+ ClassBindings<T> classBindings = classBindings(contractOrImpl, qualifiers);
+ return classBindings.getAllServiceHolders(qualifiers);
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl, Annotation... qualifiers) {
+ checkShutdown();
+
+ ClassBindings<T> classBindings = classBindings(contractOrImpl, qualifiers);
+ classBindings.matchQualifiers(qualifiers);
+ return classBindings.getInstance();
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl, String classAnalyzer) {
+ throw new UnsupportedOperationException("getInstance(Class, String)");
+ }
+
+ @Override
+ public <T> T getInstance(Class<T> contractOrImpl) {
+ checkShutdown();
+
+ T instance = instances.getInstance(contractOrImpl, null);
+ if (instance != null) {
+ return instance;
+ }
+ return create(contractOrImpl);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getInstance(Type contractOrImpl) {
+ checkShutdown();
+
+ if (ParameterizedType.class.isInstance(contractOrImpl)) {
+ T instance = types.getInstance(contractOrImpl, null);
+ if (instance != null) {
+ return instance;
+ }
+
+ TypeBindings<T> typeBindings = typeBindings(contractOrImpl);
+ return typeBindings.getInstance();
+ } else if (isClass(contractOrImpl)) {
+ return getInstance((Class<? extends T>) contractOrImpl);
+ }
+ throw new IllegalStateException(LocalizationMessages.NONINJECT_UNSATISFIED(contractOrImpl));
+ }
+
+ private static boolean isClass(Type type) {
+ return Class.class.isAssignableFrom(type.getClass());
+ }
+
+ @Override
+ public Object getInstance(ForeignDescriptor foreignDescriptor) {
+ throw new UnsupportedOperationException("getInstance(ForeignDescriptor foreignDescriptor) ");
+ }
+
+ @Override
+ public ForeignDescriptor createForeignDescriptor(Binding binding) {
+ throw new UnsupportedOperationException("createForeignDescriptor(Binding binding) ");
+ }
+
+ @Override
+ public <T> List<T> getAllInstances(Type contractOrImpl) {
+ checkShutdown();
+
+ if (!isClass(contractOrImpl)) {
+ TypeBindings<T> typeBindings = typeBindings(contractOrImpl);
+ return typeBindings.allInstances();
+ }
+
+ @SuppressWarnings("unchecked")
+ ClassBindings<T> classBindings = classBindings((Class<T>) contractOrImpl);
+ return classBindings.allInstances();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T create(Class<T> createMe) {
+ checkShutdown();
+
+ if (InjectionManager.class.equals(createMe)) {
+ return (T) this;
+ }
+ if (RequestScope.class.equals(createMe)) {
+ if (!isRequestScope) {
+ isRequestScope = true;
+ return (T) new NonInjectionRequestScope();
+ } else {
+ throw new IllegalStateException(LocalizationMessages.NONINJECT_REQUESTSCOPE_CREATED());
+ }
+ }
+
+ ClassBindings<T> classBindings = classBindings(createMe);
+ return classBindings.create();
+ }
+
+ private <T> T justCreate(Class<T> createMe) {
+ T result = null;
+ try {
+ Constructor<T> mostArgConstructor = findConstructor(createMe);
+ if (mostArgConstructor != null) {
+ int argCount = mostArgConstructor.getParameterCount();
+ if (argCount == 0) {
+ ensureAccessible(mostArgConstructor);
+ result = mostArgConstructor.newInstance();
+ } else if (argCount > 0) {
+ Object[] args = getArguments(mostArgConstructor, argCount);
+ if (args != null) {
+ ensureAccessible(mostArgConstructor);
+ result = mostArgConstructor.newInstance(args);
+ }
+ }
+ }
+ if (result == null) {
+ throw new IllegalStateException(LocalizationMessages.NONINJECT_NO_CONSTRUCTOR(createMe.getName()));
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+
+ inject(result);
+ return result;
+ }
+
+ private static <T> Constructor<T> findConstructor(Class<T> forClass) {
+ Constructor<T>[] constructors = (Constructor<T>[]) forClass.getDeclaredConstructors();
+ Constructor<T> mostArgConstructor = null;
+ int argCount = -1;
+ for (Constructor<T> constructor : constructors) {
+ if (constructor.isAnnotationPresent(Inject.class) || constructor.getParameterCount() == 0) {
+ if (constructor.getParameterCount() > argCount) {
+ mostArgConstructor = constructor;
+ argCount = constructor.getParameterCount();
+ }
+ }
+ }
+ return mostArgConstructor;
+ }
+
+ private Object[] getArguments(Executable executable, int argCount) {
+ if (executable == null) {
+ return null;
+ }
+ Object[] args = new Object[argCount];
+ for (int i = 0; i != argCount; i++) {
+ Type type = executable.getAnnotatedParameterTypes()[i].getType();
+ args[i] = isClass(type) ? getInstance((Class<?>) type) : getInstance(type);
+ }
+ return args;
+ }
+
+ private static void ensureAccessible(Executable executable) {
+ try {
+ if (!executable.isAccessible()) {
+ executable.setAccessible(true);
+ }
+ } catch (Exception e) {
+ // consume. It will fail later with invoking the executable
+ }
+ }
+
+ private void checkUnique(List<?> list) {
+ if (list.size() != 1) {
+ throw new IllegalStateException(LocalizationMessages.NONINJECT_AMBIGUOUS_SERVICES(list.get(0)));
+ }
+ }
+
+ @Override
+ public <T> T createAndInitialize(Class<T> createMe) {
+ return justCreate(createMe);
+ }
+
+ @Override
+ public void inject(Object injectMe) {
+ Method postConstruct = getAnnotatedMethod(injectMe, PostConstruct.class);
+ if (postConstruct != null) {
+ ensureAccessible(postConstruct);
+ try {
+ postConstruct.invoke(injectMe);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ @Override
+ public void inject(Object injectMe, String classAnalyzer) {
+ throw new UnsupportedOperationException("inject(Object injectMe, String classAnalyzer)");
+ }
+
+ @Override
+ public void preDestroy(Object preDestroyMe) {
+ Method preDestroy = getAnnotatedMethod(preDestroyMe, PreDestroy.class);
+ if (preDestroy != null) {
+ ensureAccessible(preDestroy);
+ try {
+ preDestroy.invoke(preDestroyMe);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ private static Method getAnnotatedMethod(Object object, Class<? extends Annotation> annotation) {
+ Class<?> clazz = object.getClass();
+ for (Method method : clazz.getMethods()) {
+ if (method.isAnnotationPresent(annotation)
+ && /* do not invoke interceptors */ method.getParameterCount() == 0) {
+ return method;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Some {@link Binding} requires the proxy to be created rather than just the instance,
+ * for instance a proxy of an instance supplied by a supplier that is not known at a time of the proxy creation.
+ * @param createProxy the nullable {@link Binding#isProxiable()} information
+ * @param iface the type of which the proxy is created
+ * @param supplier the reference to the supplier
+ * @param <T> the type the supplier should supply
+ * @return The proxy for the instance supplied by a supplier or the instance if not required to be proxied.
+ */
+ @SuppressWarnings("unchecked")
+ private <T> T createSupplierProxyIfNeeded(Boolean createProxy, Class<T> iface, Supplier<T> supplier) {
+ if (createProxy != null && createProxy && iface.isInterface()) {
+ T proxy = (T) Proxy.newProxyInstance(iface.getClassLoader(), new Class[]{iface}, new InvocationHandler() {
+ final SingleRegisterSupplier<T> singleSupplierRegister = new SingleRegisterSupplier<>(supplier);
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ T t = singleSupplierRegister.get();
+ Object ret = method.invoke(t, args);
+ return ret;
+ }
+ });
+ return proxy;
+ } else {
+ return registerDisposableSupplierAndGet(supplier);
+ }
+ }
+
+ /**
+ * A holder class making sure the Supplier (especially the {@link DisposableSupplier}) supplying the instance
+ * supplies (and is registered for being disposed at the end of the lifecycle) only once.
+ * @param <T>
+ */
+ private class SingleRegisterSupplier<T> {
+ private final LazyValue<T> once;
+
+ private SingleRegisterSupplier(Supplier<T> supplier) {
+ once = Values.lazy((Value<T>) () -> registerDisposableSupplierAndGet(supplier));
+ }
+
+ T get() {
+ return once.get();
+ }
+ }
+
+ private <T> T registerDisposableSupplierAndGet(Supplier<T> supplier) {
+ T instance = supplier.get();
+ if (DisposableSupplier.class.isInstance(supplier)) {
+ disposableSupplierObjects.add((DisposableSupplier<T>) supplier, instance);
+ }
+ return instance;
+ }
+
+ /**
+ * Create {@link ClassBindings} instance containing bindings and instances for the given Type.
+ * @param clazz the given class.
+ * @param instancesQualifiers The qualifiers the expected instances of the given class should have.
+ * @param <T> Expected return class type.
+ * @return the {@link ClassBindings}.
+ */
+ @SuppressWarnings("unchecked")
+ private <T> ClassBindings<T> classBindings(Class<T> clazz, Annotation... instancesQualifiers) {
+ ClassBindings<T> classBindings = new ClassBindings<>(clazz, instancesQualifiers);
+ List<InstanceBinding<?>> ib = instanceBindings.get(clazz);
+ if (ib != null) {
+ ib.forEach(binding -> classBindings.instanceBindings.add((InstanceBinding<T>) binding));
+ }
+ List<SupplierInstanceBinding<?>> sib = supplierInstanceBindings.get(clazz);
+ if (sib != null) {
+ sib.forEach(binding -> classBindings.supplierInstanceBindings.add((SupplierInstanceBinding<T>) binding));
+ }
+ List<ClassBinding<?>> cb = contractBindings.get(clazz);
+ if (cb != null) {
+ cb.forEach(binding -> classBindings.classBindings.add((ClassBinding<T>) binding));
+ }
+ List<SupplierClassBinding<?>> scb = supplierClassBindings.get(clazz);
+ if (scb != null) {
+ scb.forEach(binding -> classBindings.supplierClassBindings.add((SupplierClassBinding<T>) binding));
+ }
+ return classBindings;
+ }
+
+ /**
+ * Create {@link TypeBindings} instance containing bindings and instances for the given Type.
+ * @param type the given type.
+ * @param <T> Expected return type.
+ * @return the {@link TypeBindings}.
+ */
+ @SuppressWarnings("unchecked")
+ private <T> TypeBindings<T> typeBindings(Type type) {
+ TypeBindings<T> typeBindings = new TypeBindings<>(type);
+ List<InstanceBinding<?>> ib = instanceTypeBindings.get(type);
+ if (ib != null) {
+ ib.forEach(binding -> typeBindings.instanceBindings.add((InstanceBinding<T>) binding));
+ }
+ List<SupplierInstanceBinding<?>> sib = supplierTypeInstanceBindings.get(type);
+ if (sib != null) {
+ sib.forEach(binding -> typeBindings.supplierInstanceBindings.add((SupplierInstanceBinding<T>) binding));
+ }
+ List<ClassBinding<?>> cb = contractTypeBindings.get(type);
+ if (cb != null) {
+ cb.forEach(binding -> typeBindings.classBindings.add((ClassBinding<T>) binding));
+ }
+ List<SupplierClassBinding<?>> scb = supplierTypeClassBindings.get(type);
+ if (scb != null) {
+ scb.forEach(binding -> typeBindings.supplierClassBindings.add((SupplierClassBinding<T>) binding));
+ }
+ return typeBindings;
+ }
+
+ /**
+ * <p>
+ * A class that contains relevant bindings for a given TYPE, filtered from all registered bindings.
+ * The TYPE is either Type (ParametrizedType) or Class.
+ * </p>
+ * <p>
+ * The class also filters any bindings for which the singleton or thread-scoped instance already is created.
+ * The class either provides the existing instance, or all instances of the TYPE, or {@link ServiceHolder}s.
+ * </p>
+ * @param <X> The expected return type for the TYPE.
+ * @param <TYPE> The Type for which a {@link Binding} has been created.
+ */
+ private abstract class XBindings<X, TYPE> {
+
+ protected final List<InstanceBinding<X>> instanceBindings = new LinkedList<>();
+ protected final List<SupplierInstanceBinding<X>> supplierInstanceBindings = new LinkedList<>();
+ protected final List<ClassBinding<X>> classBindings = new LinkedList<>();
+ protected final List<SupplierClassBinding<X>> supplierClassBindings = new LinkedList<>();
+
+ protected final TYPE type;
+ protected final Annotation[] instancesQualifiers;
+ protected final TypedInstances<TYPE> instances;
+
+ protected XBindings(TYPE type, Annotation[] instancesQualifiers, TypedInstances<TYPE> instances) {
+ this.type = type;
+ this.instancesQualifiers = instancesQualifiers;
+ this.instances = instances;
+ }
+
+ int size() {
+ return instanceBindings.size()
+ + supplierInstanceBindings.size()
+ + classBindings.size()
+ + supplierClassBindings.size();
+ }
+
+ private void _checkUnique() {
+ if (size() > 1) {
+ throw new IllegalStateException(LocalizationMessages.NONINJECT_AMBIGUOUS_SERVICES(type));
+ }
+ }
+
+ void filterBinding(Binding binding) {
+ if (InstanceBinding.class.isInstance(binding)) {
+ instanceBindings.remove(binding);
+ } else if (ClassBinding.class.isInstance(binding)) {
+ classBindings.remove(binding);
+ } else if (SupplierInstanceBinding.class.isInstance(binding)) {
+ supplierInstanceBindings.remove(binding);
+ } else if (SupplierClassBinding.class.isInstance(binding)) {
+ supplierClassBindings.remove(binding);
+ }
+ }
+
+ /**
+ * Match the binging qualifiers
+ * @param bindingQualifiers the qualifiers registered with the bindings
+ */
+ void matchQualifiers(Annotation... bindingQualifiers) {
+ if (bindingQualifiers != null) {
+ _filterRequested(instanceBindings, bindingQualifiers);
+ _filterRequested(classBindings, bindingQualifiers);
+ _filterRequested(supplierInstanceBindings, bindingQualifiers);
+ _filterRequested(supplierClassBindings, bindingQualifiers);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void _filterRequested(List<? extends Binding<?, ?>> bindingList, Annotation... requestedQualifiers) {
+ for (Iterator<? extends Binding> bindingIterator = bindingList.iterator(); bindingIterator.hasNext();) {
+ Binding<X, ?> binding = bindingIterator.next();
+ classLoop:
+ for (Annotation requestedQualifier : requestedQualifiers) {
+ for (Annotation bindingQualifier : binding.getQualifiers()) {
+ if (requestedQualifier.annotationType().isInstance(bindingQualifier)) {
+ continue classLoop;
+ }
+ }
+ bindingIterator.remove();
+ }
+ }
+ }
+
+ protected boolean _isPerThread(Class<? extends Annotation> scope) {
+ return RequestScoped.class.equals(scope) || PerThread.class.equals(scope);
+ }
+
+ private X _getInstance(InstanceBinding<X> instanceBinding) {
+ return instanceBinding.getService();
+ }
+
+ private X _create(SupplierInstanceBinding<X> binding) {
+ Supplier<X> supplier = binding.getSupplier();
+ X t = registerDisposableSupplierAndGet(supplier);
+ if (Singleton.class.equals(binding.getScope())) {
+ _addInstance(t, binding);
+ } else if (_isPerThread(binding.getScope())) {
+ _addThreadInstance(t, binding);
+ }
+ return t;
+ }
+
+ X create() {
+ _checkUnique();
+ if (!instanceBindings.isEmpty()) {
+ return _getInstance(instanceBindings.get(0));
+ } else if (!supplierInstanceBindings.isEmpty()) {
+ return _create(supplierInstanceBindings.get(0));
+ } else if (!classBindings.isEmpty()) {
+ return _createAndStore(classBindings.get(0));
+ } else if (!supplierClassBindings.isEmpty()) {
+ return _create(supplierClassBindings.get(0));
+ }
+
+ throw new IllegalStateException(LocalizationMessages.NONINJECT_NO_BINDING(type));
+ }
+
+ protected X getInstance() {
+ X instance = instances.getInstance(type, instancesQualifiers);
+ if (instance != null) {
+ return instance;
+ }
+ return create();
+ }
+
+ List<X> allInstances() {
+ List<X> list = new LinkedList<>();
+ List<InstanceContext<?>> instanceContextList;
+
+ instanceContextList = instances.getContexts(type, instancesQualifiers);
+ if (instanceContextList != null) {
+ instanceContextList.forEach(instanceContext -> filterBinding(instanceContext.getBinding()));
+ instanceContextList.forEach(instanceContext -> list.add((X) instanceContext.getInstance()));
+ }
+
+ list.addAll(instanceBindings.stream()
+ .map(this::_getInstance)
+ .collect(Collectors.toList()));
+
+ list.addAll(classBindings.stream()
+ .map(this::_createAndStore)
+ .collect(Collectors.toList()));
+
+ list.addAll(supplierInstanceBindings.stream()
+ .map(this::_create)
+ .collect(Collectors.toList()));
+
+ list.addAll(supplierClassBindings.stream()
+ .map(this::_create)
+ .collect(Collectors.toList()));
+
+ return list;
+ }
+
+ protected abstract X _create(SupplierClassBinding<X> binding);
+
+ protected abstract X _createAndStore(ClassBinding<X> binding);
+
+ protected <T> T _addInstance(TYPE type, T instance, Binding<?, ?> binding) {
+ return instances.addSingleton(type, instance, binding, instancesQualifiers);
+ }
+
+ protected void _addThreadInstance(TYPE type, Object instance, Binding binding) {
+ instances.addThreadInstance(type, instance, binding, instancesQualifiers);
+ }
+
+ protected <T> T _addInstance(T instance, Binding<?, ?> binding) {
+ return instances.addSingleton(type, instance, binding, instancesQualifiers);
+ }
+
+ protected void _addThreadInstance(Object instance, Binding binding) {
+ instances.addThreadInstance(type, instance, binding, instancesQualifiers);
+ }
+ }
+
+
+ private class ClassBindings<T> extends XBindings<T, Class<?>> {
+ private ClassBindings(Class<T> clazz, Annotation[] instancesQualifiers) {
+ super(clazz, instancesQualifiers, NonInjectionManager.this.instances);
+ }
+
+ @SuppressWarnings("unchecked")
+ List<ServiceHolder<T>> getAllServiceHolders(Annotation... qualifiers) {
+ matchQualifiers(qualifiers);
+
+ List<ServiceHolder<T>> holders = new LinkedList<>();
+ List<InstanceContext<?>> instanceContextList;
+
+ instanceContextList = instances.getContexts(type, qualifiers);
+
+ if (instanceContextList != null) {
+ instanceContextList.forEach(instanceContext -> filterBinding(instanceContext.getBinding()));
+ instanceContextList.forEach(instanceContext -> holders.add(new ServiceHolderImpl<T>(
+ (T) instanceContext.getInstance(),
+ (Class<T>) instanceContext.getInstance().getClass(),
+ instanceContext.getBinding().getContracts(),
+ instanceContext.getBinding().getRank() == null ? 0 : instanceContext.getBinding().getRank())
+ ));
+ }
+
+ List<ServiceHolder<T>> instanceBindingHolders = instanceBindings.stream()
+ .map(this::_serviceHolder)
+ .collect(Collectors.toList());
+ holders.addAll(instanceBindingHolders);
+
+ List<ServiceHolder<T>> classBindingHolders = classBindings.stream()
+ .filter(binding -> NonInjectionManager.this.findConstructor(binding.getService()) != null)
+ .map(this::_serviceHolder)
+ .collect(Collectors.toList());
+ holders.addAll(classBindingHolders);
+
+ return holders;
+ }
+
+ private <T> ServiceHolderImpl<T> _serviceHolder(InstanceBinding<T> binding) {
+ return new ServiceHolderImpl<T>(
+ binding.getService(),
+ binding.getImplementationType(),
+ binding.getContracts(),
+ binding.getRank() == null ? 0 : binding.getRank());
+ }
+
+ private <T> ServiceHolderImpl<T> _serviceHolder(ClassBinding<T> binding) {
+ return new ServiceHolderImpl<T>(
+ NonInjectionManager.this.create(binding.getService()),
+ binding.getImplementationType(),
+ binding.getContracts(),
+ binding.getRank() == null ? 0 : binding.getRank());
+ }
+
+ protected T _create(SupplierClassBinding<T> binding) {
+ Supplier<T> supplier = instances.getInstance(binding.getSupplierClass(), null);
+ if (supplier == null) {
+ supplier = justCreate(binding.getSupplierClass());
+ if (Singleton.class.equals(binding.getSupplierScope())) {
+ supplier = instances.addSingleton(binding.getSupplierClass(), supplier, binding, null);
+ } else if (_isPerThread(binding.getSupplierScope())) {
+ instances.addThreadInstance(binding.getSupplierClass(), supplier, binding, null);
+ }
+ }
+
+ T t = createSupplierProxyIfNeeded(binding.isProxiable(), (Class<T>) type, supplier);
+ if (Singleton.class.equals(binding.getScope())) {
+ t = _addInstance(type, t, binding);
+ } else if (_isPerThread(binding.getScope())) {
+ _addThreadInstance(type, t, binding);
+ }
+ return t;
+ }
+
+ protected T _createAndStore(ClassBinding<T> binding) {
+ T result = justCreate(binding.getService());
+ result = _addInstance(binding.getService(), result, binding);
+ return result;
+ }
+ }
+
+ private class TypeBindings<T> extends XBindings<T, Type> {
+ private TypeBindings(Type type) {
+ super(type, null, types);
+ }
+
+ protected T _create(SupplierClassBinding<T> binding) {
+ Supplier<T> supplier = justCreate(binding.getSupplierClass());
+
+ T t = registerDisposableSupplierAndGet(supplier);
+ if (Singleton.class.equals(binding.getScope())) {
+ t = _addInstance(type, t, binding);
+ } else if (_isPerThread(binding.getScope())) {
+ _addThreadInstance(type, t, binding);
+ }
+ return t;
+ }
+
+ @Override
+ protected T _createAndStore(ClassBinding<T> binding) {
+ T result = justCreate(binding.getService());
+ result = _addInstance(type, result, binding);
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ T create() {
+ if (ParameterizedType.class.isInstance(type)) {
+ ParameterizedType pt = (ParameterizedType) type;
+ if (Provider.class.equals(pt.getRawType())) {
+ return (T) new Provider<Object>() {
+ final SingleRegisterSupplier<Object> supplier = new SingleRegisterSupplier<>(new Supplier<Object>() {
+ @Override
+ public Object get() {
+ Type actualTypeArgument = pt.getActualTypeArguments()[0];
+ if (isClass(actualTypeArgument)) {
+ return NonInjectionManager.this.getInstance((Class<? extends T>) actualTypeArgument);
+ } else {
+ return NonInjectionManager.this.getInstance(actualTypeArgument);
+ }
+ }
+ });
+
+ @Override
+ public Object get() {
+ return supplier.get(); //Not disposable
+ }
+ };
+ }
+ }
+ return super.create();
+ }
+ }
+
+ /**
+ * A triplet of created instance, the registered {@link Binding} that prescribed the creation of the instance
+ * and {@link Annotation qualifiers} the instance was created with.
+ * @param <T> type of the instance.
+ * @see NonInjectionManager#getInstance(Class, Annotation[])
+ */
+ private static class InstanceContext<T> {
+ private final T instance;
+ private final Binding<?, ?> binding;
+ private final Annotation[] createdWithQualifiers;
+
+ private InstanceContext(T instance, Binding<?, ?> binding, Annotation[] qualifiers) {
+ this.instance = instance;
+ this.binding = binding;
+ this.createdWithQualifiers = qualifiers;
+ }
+
+ public Binding<?, ?> getBinding() {
+ return binding;
+ }
+
+ public T getInstance() {
+ return instance;
+ }
+
+ @SuppressWarnings("unchecked")
+ static <T> List<T> toInstances(List<InstanceContext<?>> instances, Annotation[] qualifiers) {
+ return instances != null
+ ? instances.stream()
+ .filter(instance -> instance.hasQualifiers(qualifiers))
+ .map(pair -> (T) pair.getInstance())
+ .collect(Collectors.toList())
+ : null;
+ }
+
+ private static List<InstanceContext<?>> filterInstances(List<InstanceContext<?>> instances, Annotation... qualifiers) {
+ return instances != null
+ ? instances.stream()
+ .filter(instance -> instance.hasQualifiers(qualifiers))
+ .collect(Collectors.toList())
+ : null;
+ }
+
+ private boolean hasQualifiers(Annotation[] requested) {
+ if (requested != null) {
+ classLoop:
+ for (Annotation req : requested) {
+ if (createdWithQualifiers != null) {
+ for (Annotation cur : createdWithQualifiers) {
+ if (cur.annotationType().isInstance(req)) {
+ continue classLoop;
+ }
+ }
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Singleton Binding this {@link NonInjectionManager} was supposed to be created based upon.
+ */
+ private static final class InjectionManagerBinding extends Binding<InjectionManager, Binding<?, ?>> {
+ }
+
+}
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionRequestScope.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionRequestScope.java
new file mode 100644
index 0000000..258780d
--- /dev/null
+++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionRequestScope.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.client.innate.inject;
+
+import org.glassfish.jersey.internal.util.ExtendedLogger;
+import org.glassfish.jersey.internal.util.LazyUid;
+import org.glassfish.jersey.process.internal.RequestScope;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class NonInjectionRequestScope extends RequestScope {
+ @Override
+ public org.glassfish.jersey.process.internal.RequestContext createContext() {
+ return new Instance();
+ }
+
+ /**
+ * Implementation of the request scope instance.
+ */
+ public static final class Instance implements org.glassfish.jersey.process.internal.RequestContext {
+
+ private static final ExtendedLogger logger = new ExtendedLogger(Logger.getLogger(Instance.class.getName()), Level.FINEST);
+
+ /*
+ * Scope instance UUID.
+ *
+ * For performance reasons, it's only generated if toString() method is invoked,
+ * e.g. as part of some low-level logging.
+ */
+ private final LazyUid id = new LazyUid();
+
+ /**
+ * Holds the number of snapshots of this scope.
+ */
+ private final AtomicInteger referenceCounter;
+
+ private Instance() {
+ this.referenceCounter = new AtomicInteger(1);
+ }
+
+ /**
+ * Get a "new" reference of the scope instance. This will increase
+ * the internal reference counter which prevents the scope instance
+ * to be destroyed until a {@link #release()} method is explicitly
+ * called (once per each {@code getReference()} method call).
+ *
+ * @return referenced scope instance.
+ */
+ @Override
+ public NonInjectionRequestScope.Instance getReference() {
+ // TODO: replace counter with a phantom reference + reference queue-based solution
+ referenceCounter.incrementAndGet();
+ return this;
+ }
+
+
+ /**
+ * Release a single reference to the current request scope instance.
+ * <p>
+ * Once all instance references are released, the instance will be recycled.
+ */
+ @Override
+ public void release() {
+ referenceCounter.decrementAndGet();
+ }
+
+ @Override
+ public String toString() {
+ return "Instance{"
+ + "id=" + id
+ + ", referenceCounter=" + referenceCounter
+ + '}';
+ }
+ }
+}
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
index 31a3583..c7e0ac2 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,10 +21,13 @@
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
+import java.net.InetAddress;
import java.net.ProtocolException;
+import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.UnknownHostException;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
@@ -42,6 +45,7 @@
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.client.Client;
@@ -55,6 +59,7 @@
import org.glassfish.jersey.client.JerseyClient;
import org.glassfish.jersey.client.RequestEntityProcessing;
import org.glassfish.jersey.client.innate.ClientProxy;
+import org.glassfish.jersey.client.innate.http.SSLParamConfigurator;
import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
import org.glassfish.jersey.client.spi.Connector;
import org.glassfish.jersey.internal.util.PropertiesHelper;
@@ -315,11 +320,35 @@
}
}
+ /**
+ * Secure connection if necessary.
+ * <p/>
+ * Provided implementation sets {@link HostnameVerifier} and {@link SSLSocketFactory} to give connection, if that
+ * is an instance of {@link HttpsURLConnection}.
+ *
+ * @param clientRequest the actual client request.
+ * @param uc http connection to be secured.
+ */
+ private void secureConnection(
+ final ClientRequest clientRequest, final HttpURLConnection uc, final SSLParamConfigurator sniConfig) {
+ secureConnection(clientRequest.getClient(), uc); // keep this for compatibility
+
+ if (sniConfig.isSNIRequired() && uc instanceof HttpsURLConnection) { // set SNI
+ HttpsURLConnection suc = (HttpsURLConnection) uc;
+ SniSSLSocketFactory socketFactory = new SniSSLSocketFactory(suc.getSSLSocketFactory());
+ socketFactory.setSniConfig(sniConfig);
+ suc.setSSLSocketFactory(socketFactory);
+ }
+ }
+
private ClientResponse _apply(final ClientRequest request) throws IOException {
final HttpURLConnection uc;
- Optional<ClientProxy> proxy = ClientProxy.proxyFromRequest(request);
+ final Optional<ClientProxy> proxy = ClientProxy.proxyFromRequest(request);
+ final SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().request(request).build();
+ final URI sniUri = sniConfig.isSNIRequired() ? sniConfig.toIPRequestUri() : request.getUri();
+
proxy.ifPresent(clientProxy -> ClientProxy.setBasicAuthorizationHeader(request.getHeaders(), proxy.get()));
- uc = this.connectionFactory.getConnection(request.getUri().toURL(), proxy.isPresent() ? proxy.get().proxy() : null);
+ uc = this.connectionFactory.getConnection(sniUri.toURL(), proxy.isPresent() ? proxy.get().proxy() : null);
uc.setDoInput(true);
final String httpMethod = request.getMethod();
@@ -335,7 +364,7 @@
uc.setReadTimeout(request.resolveProperty(ClientProperties.READ_TIMEOUT, uc.getReadTimeout()));
- secureConnection(request.getClient(), uc);
+ secureConnection(request, uc, sniConfig);
final Object entity = request.getEntity();
Exception storedException = null;
@@ -559,4 +588,84 @@
public String getName() {
return "HttpUrlConnection " + AccessController.doPrivileged(PropertiesHelper.getSystemProperty("java.version"));
}
+
+ private static class SniSSLSocketFactory extends SSLSocketFactory {
+ private final SSLSocketFactory socketFactory;
+ private ThreadLocal<SSLParamConfigurator> sniConfigs = new ThreadLocal<>();
+
+ public void setSniConfig(SSLParamConfigurator sniConfigs) {
+ this.sniConfigs.set(sniConfigs);
+ }
+
+ private SniSSLSocketFactory(SSLSocketFactory socketFactory) {
+ this.socketFactory = socketFactory;
+ }
+
+ @Override
+ public String[] getDefaultCipherSuites() {
+ return socketFactory.getDefaultCipherSuites();
+ }
+
+ @Override
+ public String[] getSupportedCipherSuites() {
+ return socketFactory.getSupportedCipherSuites();
+ }
+
+ @Override
+ public Socket createSocket(Socket socket, String s, int i, boolean b) throws IOException {
+ Socket superSocket = socketFactory.createSocket(socket, s, i, b);
+ setSNIServerName(superSocket);
+ return superSocket;
+ }
+
+ @Override
+ public Socket createSocket(String s, int i) throws IOException, UnknownHostException {
+ Socket superSocket = socketFactory.createSocket(s, i);
+ setSNIServerName(superSocket);
+ return superSocket;
+ }
+
+ @Override
+ public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException, UnknownHostException {
+ Socket superSocket = socketFactory.createSocket(s, i, inetAddress, i1);
+ setSNIServerName(superSocket);
+ return superSocket;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress inetAddress, int i) throws IOException {
+ Socket superSocket = socketFactory.createSocket(inetAddress, i);
+ setSNIServerName(superSocket);
+ return superSocket;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException {
+ Socket superSocket = socketFactory.createSocket(inetAddress, i, inetAddress1, i1);
+ setSNIServerName(superSocket);
+ return superSocket;
+ }
+
+ @Override
+ public Socket createSocket(Socket s, InputStream consumed, boolean autoClose) throws IOException {
+ Socket superSocket = socketFactory.createSocket(s, consumed, autoClose);
+ setSNIServerName(superSocket);
+ return superSocket;
+ }
+
+ @Override
+ public Socket createSocket() throws IOException {
+ Socket superSocket = socketFactory.createSocket();
+ setSNIServerName(superSocket);
+ return superSocket;
+ }
+
+ private void setSNIServerName(Socket superSocket) {
+ SSLParamConfigurator sniConfig = this.sniConfigs.get();
+ if (null != sniConfig && SSLSocket.class.isInstance(superSocket)) {
+ sniConfig.setSNIServerName((SSLSocket) superSocket);
+ }
+ this.sniConfigs.remove();
+ }
+ }
}
diff --git a/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties b/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
index e66ceab..ee80184 100644
--- a/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
+++ b/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0, which is available at
@@ -48,7 +48,14 @@
Using default cached thread pool.
negative.chunk.size=Negative chunked HTTP transfer coding chunk size value specified in the client configuration property: [{0}] \
Reverting to programmatically set default: [{1}]
-negative.input.parameter="Input parameter {0} must not be negative."
+negative.input.parameter="Input parameter {0} must not be negative1."
+noninject.ambiguous.services=Ambiguous providing services ${0}.
+noninject.fallback=Falling back to injection-less client.
+noninject.no.constructor=No applicable constructor for ${0} found.
+noninject.no.binding=No binding found for ${0}.
+noninject.requestscope.created=RequestScope already created.
+noninject.shutdown=InjectionManager is already shutdown.
+noninject.unsatisfied=Unsatisfied dependency for ${0}.
null.connector.provider=ConnectorProvider must not be set to null.
null.executor.service=ExecutorService must not be set to null.
null.input.parameter=Input method parameter {0} must not be null.
diff --git a/core-client/src/test/java/org/glassfish/jersey/client/ClientConfigTest.java b/core-client/src/test/java/org/glassfish/jersey/client/ClientConfigTest.java
index 8ab88e7..aaa88c9 100644
--- a/core-client/src/test/java/org/glassfish/jersey/client/ClientConfigTest.java
+++ b/core-client/src/test/java/org/glassfish/jersey/client/ClientConfigTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -112,7 +112,7 @@
}
@Provider
- public class MyProvider implements ContextResolver<String> {
+ public static class MyProvider implements ContextResolver<String> {
@Override
public String getContext(final Class<?> type) {
diff --git a/core-client/src/test/java/org/glassfish/jersey/client/JerseyClientTest.java b/core-client/src/test/java/org/glassfish/jersey/client/JerseyClientTest.java
index 05ac6ea..a985579 100644
--- a/core-client/src/test/java/org/glassfish/jersey/client/JerseyClientTest.java
+++ b/core-client/src/test/java/org/glassfish/jersey/client/JerseyClientTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -272,8 +272,12 @@
}
public static class CustomProvider implements ClientRequestFilter {
+ private final CustomContract customContract;
+
@Inject
- private CustomContract customContract;
+ CustomProvider(CustomContract customContract) {
+ this.customContract = customContract;
+ }
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
diff --git a/core-client/src/test/java/org/glassfish/jersey/client/JerseyCompletionStageRxInvokerTest.java b/core-client/src/test/java/org/glassfish/jersey/client/JerseyCompletionStageRxInvokerTest.java
index d7643aa..515bb83 100644
--- a/core-client/src/test/java/org/glassfish/jersey/client/JerseyCompletionStageRxInvokerTest.java
+++ b/core-client/src/test/java/org/glassfish/jersey/client/JerseyCompletionStageRxInvokerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -34,7 +34,6 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
@@ -71,7 +70,6 @@
}
@Test
- @Disabled("TODO JAX-RS 2.1")
public void testNewClientExecutor() throws Exception {
testClient(ClientBuilder.newBuilder()
.executorService(executor)
diff --git a/core-client/src/test/java/org/glassfish/jersey/client/spi/PreInvocationInterceptorTest.java b/core-client/src/test/java/org/glassfish/jersey/client/spi/PreInvocationInterceptorTest.java
index 2df0307..deafb62 100644
--- a/core-client/src/test/java/org/glassfish/jersey/client/spi/PreInvocationInterceptorTest.java
+++ b/core-client/src/test/java/org/glassfish/jersey/client/spi/PreInvocationInterceptorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,13 +22,13 @@
import org.junit.jupiter.api.Test;
import jakarta.annotation.Priority;
+import jakarta.inject.Inject;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.client.ClientRequestFilter;
import jakarta.ws.rs.client.Invocation;
import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.Response;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
@@ -263,8 +263,12 @@
}
private static class InjectedPreInvocationInterceptor implements PreInvocationInterceptor {
- @Context
- Configuration configuration;
+ private final Configuration configuration;
+
+ @Inject
+ public InjectedPreInvocationInterceptor(Configuration configuration) {
+ this.configuration = configuration;
+ }
@Override
public void beforeRequest(ClientRequestContext requestContext) {
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/JaxrsProviders.java b/core-common/src/main/java/org/glassfish/jersey/internal/JaxrsProviders.java
index bc5c722..57c7d24 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/JaxrsProviders.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/JaxrsProviders.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -62,12 +62,18 @@
}
}
+ private final Provider<MessageBodyWorkers> workers;
+ private final Provider<ContextResolvers> resolvers;
+ private final Provider<ExceptionMappers> mappers;
+
@Inject
- private Provider<MessageBodyWorkers> workers;
- @Inject
- private Provider<ContextResolvers> resolvers;
- @Inject
- private Provider<ExceptionMappers> mappers;
+ public JaxrsProviders(Provider<MessageBodyWorkers> workers,
+ Provider<ContextResolvers> resolvers,
+ Provider<ExceptionMappers> mappers) {
+ this.workers = workers;
+ this.resolvers = resolvers;
+ this.mappers = mappers;
+ }
@Override
public <T> MessageBodyReader<T> getMessageBodyReader(Class<T> type,
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/Injections.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/Injections.java
index 19177cf..1750dd8 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/Injections.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/Injections.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -20,6 +20,8 @@
import java.util.List;
import java.util.Optional;
+import jakarta.ws.rs.ConstrainedTo;
+import jakarta.ws.rs.RuntimeType;
import jakarta.ws.rs.WebApplicationException;
import org.glassfish.jersey.internal.LocalizationMessages;
@@ -36,22 +38,32 @@
public class Injections {
/**
- * Creates a {@link InjectionManager} without parent and initial binder.
+ * Creates an {@link InjectionManager} without parent and initial binder.
*
- * @return a injection manager with all the bindings.
+ * @return an injection manager with all the bindings.
*/
public static InjectionManager createInjectionManager() {
- return lookupInjectionManagerFactory().create();
+ return lookupInjectionManagerFactory(RuntimeType.SERVER).create();
+ }
+
+ /**
+ * Creates an {@link InjectionManager} without parent and initial binder.
+ * @param type {@link RuntimeType} the {@link InjectionManagerFactory} must be {@link ConstrainedTo} if annotated.
+ *
+ * @return an injection manager with all the bindings.
+ */
+ public static InjectionManager createInjectionManager(RuntimeType type) {
+ return lookupInjectionManagerFactory(type).create();
}
/**
* Creates a {@link InjectionManager} with initial binder that is immediately registered.
*
* @param binder custom the {@link Binder binder}.
- * @return a injection manager with all the bindings.
+ * @return an injection manager with all the bindings.
*/
public static InjectionManager createInjectionManager(Binder binder) {
- InjectionManagerFactory injectionManagerFactory = lookupInjectionManagerFactory();
+ InjectionManagerFactory injectionManagerFactory = lookupInjectionManagerFactory(RuntimeType.SERVER);
InjectionManager injectionManager = injectionManagerFactory.create();
injectionManager.register(binder);
return injectionManager;
@@ -66,11 +78,11 @@
* @return an injection manager with all the bindings.
*/
public static InjectionManager createInjectionManager(Object parent) {
- return lookupInjectionManagerFactory().create(parent);
+ return lookupInjectionManagerFactory(RuntimeType.SERVER).create(parent);
}
- private static InjectionManagerFactory lookupInjectionManagerFactory() {
- return lookupService(InjectionManagerFactory.class)
+ private static InjectionManagerFactory lookupInjectionManagerFactory(RuntimeType type) {
+ return lookupService(InjectionManagerFactory.class, type)
.orElseThrow(() -> new IllegalStateException(LocalizationMessages.INJECTION_MANAGER_FACTORY_NOT_FOUND()));
}
@@ -80,12 +92,17 @@
*
* @param clazz type of service to look for.
* @param <T> type of service to look for.
+ * @param type {@link RuntimeType} the {@link InjectionManagerFactory} must be {@link ConstrainedTo} if annotated.
* @return instance of service with highest priority or {@code null} if service of given type cannot be found.
* @see jakarta.annotation.Priority
*/
- private static <T> Optional<T> lookupService(final Class<T> clazz) {
+ private static <T> Optional<T> lookupService(final Class<T> clazz, RuntimeType type) {
List<RankedProvider<T>> providers = new LinkedList<>();
for (T provider : ServiceFinder.find(clazz)) {
+ ConstrainedTo constrain = provider.getClass().getAnnotation(ConstrainedTo.class);
+ if (constrain != null && type != constrain.value()) {
+ continue;
+ }
providers.add(new RankedProvider<>(provider));
}
providers.sort(new RankedComparator<>(RankedComparator.Order.DESCENDING));
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/SourceProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/SourceProvider.java
index d30f655..8d6a8ef 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/SourceProvider.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/SourceProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,11 +22,11 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
+import jakarta.inject.Inject;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.MessageBodyReader;
@@ -95,7 +95,8 @@
private final Provider<SAXParserFactory> spf;
- public SaxSourceReader(@Context Provider<SAXParserFactory> spf) {
+ @Inject
+ public SaxSourceReader(Provider<SAXParserFactory> spf) {
this.spf = spf;
}
@@ -135,7 +136,8 @@
private final Provider<DocumentBuilderFactory> dbf;
- public DomSourceReader(@Context Provider<DocumentBuilderFactory> dbf) {
+ @Inject
+ public DomSourceReader(Provider<DocumentBuilderFactory> dbf) {
this.dbf = dbf;
}
@@ -176,8 +178,9 @@
private final Provider<SAXParserFactory> saxParserFactory;
private final Provider<TransformerFactory> transformerFactory;
- public SourceWriter(@Context Provider<SAXParserFactory> spf,
- @Context Provider<TransformerFactory> tf) {
+ @Inject
+ public SourceWriter(Provider<SAXParserFactory> spf,
+ Provider<TransformerFactory> tf) {
this.saxParserFactory = spf;
this.transformerFactory = tf;
}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.java
index c8c9684..e85d57a 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/AnnotationAcceptingListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -319,7 +319,7 @@
private void accept(final ClassVisitor classVisitor, final int parsingOptions) {
final int originalVersion = getMajorVersion(b);
- if (originalVersion == WARN_VERSION + 1) {
+ if (originalVersion > WARN_VERSION) {
// temporarily downgrade version to bypass check in ASM
setMajorVersion(WARN_VERSION, b);
LOGGER.warning("Unsupported class file major version " + originalVersion);
diff --git a/docs/src/main/docbook/client.xml b/docs/src/main/docbook/client.xml
index 1ba38d2..e19ffe0 100644
--- a/docs/src/main/docbook/client.xml
+++ b/docs/src/main/docbook/client.xml
@@ -1087,8 +1087,22 @@
<para>
See javadoc of the &jersey.client.HttpAuthenticationFeature; for more details.
</para>
- </section>
+ </section>
+ <section>
+ <title><anchor xml:id="SNI"/>Server Name Indication (SNI) Support</title>
+ <para>
+ When using SSL/TLS protocols for the connection, <literal>SNIHostName</literal> is set automatically
+ based on the host name in the HTTPS request.
+ </para>
+ <para>
+ There might be use-cases where the <literal>SNIHostName</literal> is required to be set for other host
+ than the host specified in the HTTPS request. For those cases, when the HTTP header <literal>Host</literal>
+ is set, the <literal>SNIHostName</literal> is set for the host specified in the <literal>Host</literal> header.
+ Note that only <literal>Apache Connector, JDK Connector, Netty connector</literal>, and the default
+ <literal>HttpUrlConnector</literal> do support this feature.
+ </para>
+ </section>
</section>
diff --git a/etc/config/copyright-exclude b/etc/config/copyright-exclude
index 987175b..9577477 100644
--- a/etc/config/copyright-exclude
+++ b/etc/config/copyright-exclude
@@ -69,6 +69,7 @@
/tests/e2e/server/mvc/MvcEncodingTest/MustacheResource.mustache
/test/resources/org/glassfish/jersey/server/config/jaxrs-components
/tests/e2e-entity/src/test/resources/org/glassfish/jersey/tests/e2e/entity/xxe.txt
+/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/explorer
/core-server/src/main/java/com/sun/research/ws/wadl
/core-common/src/main/java/org/glassfish/jersey/internal/jsr166
/core-common/src/main/jsr166/org/glassfish/jersey/internal/jsr166
diff --git a/examples/NOTICE.md b/examples/NOTICE.md
index 84c7087..71390cd 100644
--- a/examples/NOTICE.md
+++ b/examples/NOTICE.md
@@ -43,6 +43,11 @@
* Copyright: 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
* by the @authors tag.
+Hibernate Validator CDI, 7.0.5.Final
+* License: Apache License, 2.0
+* Project: https://beanvalidation.org/
+* Repackaged in org.glassfish.jersey.server.validation.internal.hibernate
+
Bootstrap v3.3.7
* License: MIT license (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Project: http://getbootstrap.com
@@ -61,12 +66,12 @@
* License: Apache License, 2.0
* Copyright (C) 2009 The JSR-330 Expert Group
-Javassist Version 3.25.0-GA
+Javassist Version 3.29.0-GA
* License: Apache License, 2.0
* Project: http://www.javassist.org/
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
-Jackson JAX-RS Providers Version 2.11.3
+Jackson JAX-RS Providers Version 2.14.1
* License: Apache License, 2.0
* Project: https://github.com/FasterXML/jackson-jaxrs-providers
* Copyright: (c) 2009-2011 FasterXML, LLC. All rights reserved unless otherwise indicated.
@@ -91,7 +96,7 @@
* Project: http://www.kineticjs.com, https://github.com/ericdrowell/KineticJS
* Copyright: Eric Rowell
-org.objectweb.asm Version 9.0
+org.objectweb.asm Version 9.4
* License: Modified BSD (https://asm.ow2.io/license.html)
* Copyright (c) 2000-2011 INRIA, France Telecom. All rights reserved.
diff --git a/ext/bean-validation/src/main/resources/META-INF/NOTICE.markdown b/ext/bean-validation/src/main/resources/META-INF/NOTICE.markdown
index c728f22..0e566a0 100644
--- a/ext/bean-validation/src/main/resources/META-INF/NOTICE.markdown
+++ b/ext/bean-validation/src/main/resources/META-INF/NOTICE.markdown
@@ -31,7 +31,7 @@
## Third-party Content
-Hibernate Validator CDI, 7.0.0.Final
+Hibernate Validator CDI, 7.0.5.Final
* License: Apache License, 2.0
* Project: https://beanvalidation.org/
* Repackaged in org.glassfish.jersey.server.validation.internal.hibernate
\ No newline at end of file
diff --git a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityInspectorImpl.java b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityInspectorImpl.java
index 3a69f66..b5c0943 100644
--- a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityInspectorImpl.java
+++ b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityInspectorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -51,9 +51,7 @@
@Singleton
final class EntityInspectorImpl implements EntityInspector {
private final List<EntityProcessor> entityProcessors;
-
- @Inject
- private EntityGraphProvider graphProvider;
+ private final EntityGraphProvider graphProvider;
/**
* Constructor expecting {@link InjectionManager} to be injected.
@@ -61,10 +59,11 @@
* @param injectionManager injection manager to be injected.
*/
@Inject
- public EntityInspectorImpl(final InjectionManager injectionManager) {
+ public EntityInspectorImpl(final InjectionManager injectionManager, EntityGraphProvider graphProvider) {
Spliterator<EntityProcessor> entities =
Providers.getAllProviders(injectionManager, EntityProcessor.class, new RankedComparator<>()).spliterator();
this.entityProcessors = StreamSupport.stream(entities, false).collect(Collectors.toList());
+ this.graphProvider = graphProvider;
}
@Override
diff --git a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/ObjectGraphProvider.java b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/ObjectGraphProvider.java
index 5f911e3..9eb5933 100644
--- a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/ObjectGraphProvider.java
+++ b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/ObjectGraphProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -17,7 +17,12 @@
package org.glassfish.jersey.message.filtering;
import org.glassfish.jersey.message.filtering.spi.AbstractObjectProvider;
+import org.glassfish.jersey.message.filtering.spi.EntityGraphProvider;
+import org.glassfish.jersey.message.filtering.spi.EntityInspector;
import org.glassfish.jersey.message.filtering.spi.ObjectGraph;
+import org.glassfish.jersey.message.filtering.spi.ScopeProvider;
+
+import jakarta.inject.Inject;
/**
* {@link org.glassfish.jersey.message.filtering.spi.ObjectProvider Object provider} and
@@ -28,6 +33,13 @@
*/
final class ObjectGraphProvider extends AbstractObjectProvider<ObjectGraph> {
+ @Inject
+ public ObjectGraphProvider(ScopeProvider scopeProvider,
+ EntityInspector entityInspector,
+ EntityGraphProvider graphProvider) {
+ super(scopeProvider, entityInspector, graphProvider);
+ }
+
@Override
public ObjectGraph transform(final ObjectGraph graph) {
return graph;
diff --git a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/spi/AbstractObjectProvider.java b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/spi/AbstractObjectProvider.java
index ac3422b..ce354db 100644
--- a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/spi/AbstractObjectProvider.java
+++ b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/spi/AbstractObjectProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -46,15 +46,18 @@
private final Cache<EntityContext, T> filteringObjects = CacheBuilder.newBuilder().maximumSize(PROVIDER_CACHE_SIZE).build();
- @Inject
private ScopeProvider scopeProvider;
-
- @Inject
private EntityInspector entityInspector;
-
- @Inject
private EntityGraphProvider graphProvider;
+ public AbstractObjectProvider(ScopeProvider scopeProvider,
+ EntityInspector entityInspector,
+ EntityGraphProvider graphProvider) {
+ this.scopeProvider = scopeProvider;
+ this.entityInspector = entityInspector;
+ this.graphProvider = graphProvider;
+ }
+
@Override
public final T getFilteringObject(final Type genericType, final boolean forWriter, final Annotation... annotations) {
return getFilteringObject(FilteringHelper.getEntityClass(genericType), forWriter, annotations);
diff --git a/ext/metainf-services/src/test/java/org/glassfish/jersey/message/MetaInfServicesTest.java b/ext/metainf-services/src/test/java/org/glassfish/jersey/message/MetaInfServicesTest.java
index db18e3b..8458471 100644
--- a/ext/metainf-services/src/test/java/org/glassfish/jersey/message/MetaInfServicesTest.java
+++ b/ext/metainf-services/src/test/java/org/glassfish/jersey/message/MetaInfServicesTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,13 +22,13 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
+import jakarta.inject.Inject;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
@@ -72,7 +72,10 @@
public static class MessageProvider implements MessageBodyReader<MetaInf>, MessageBodyWriter<MetaInf> {
- @Context
+ @Inject
+ MessageProvider(Configuration configuration) {
+ this.config = configuration;
+ }
private Configuration config;
@Override
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/FormParamModel.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/FormParamModel.java
index d38a41e..23b3ca5 100644
--- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/FormParamModel.java
+++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/FormParamModel.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -45,7 +45,7 @@
form.param(formParamName, v.toString());
}
} else {
- form.param(formParamName, resolvedValue.toString());
+ form.param(formParamName, resolvedValue == null ? null : resolvedValue.toString());
}
return form;
}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyProxyResolverTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyProxyResolverTest.java
index 5b45ea4..9c1e9f9 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyProxyResolverTest.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyProxyResolverTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -96,7 +96,7 @@
@Test
public void testProxyCreated() {
- MyInjectionResolver injectionResolver = new MyInjectionResolver(new JaxrsProviders());
+ MyInjectionResolver injectionResolver = new MyInjectionResolver(new JaxrsProviders(null, null, null));
InjecteeImpl injectee = new InjecteeImpl();
injectee.setRequiredType(Providers.class);
injectee.setParent(FIELDS[0]);
@@ -108,7 +108,7 @@
@Test
public void testProxyCached() {
- MyInjectionResolver injectionResolver = new MyInjectionResolver(new JaxrsProviders());
+ MyInjectionResolver injectionResolver = new MyInjectionResolver(new JaxrsProviders(null, null, null));
InjecteeImpl injectee1 = new InjecteeImpl();
injectee1.setRequiredType(Providers.class);
injectee1.setParent(FIELDS[0]);
@@ -125,7 +125,7 @@
@Test
public void testProxyCacheNotMismatched() {
- MyInjectionResolver injectionResolver1 = new MyInjectionResolver(new JaxrsProviders());
+ MyInjectionResolver injectionResolver1 = new MyInjectionResolver(new JaxrsProviders(null, null, null));
InjecteeImpl injectee1 = new InjecteeImpl();
injectee1.setRequiredType(Providers.class);
injectee1.setParent(FIELDS[0]);
diff --git a/incubator/injectless-client/pom.xml b/incubator/injectless-client/pom.xml
new file mode 100644
index 0000000..d1a31cf
--- /dev/null
+++ b/incubator/injectless-client/pom.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<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">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.incubator</groupId>
+ <artifactId>project</artifactId>
+ <version>3.0.99-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>jersey-injectless-client</artifactId>
+ <packaging>jar</packaging>
+ <name>jersey-inject-injectless-client</name>
+
+ <description>Client side support of no injection mechanism</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <inherited>true</inherited>
+ <extensions>true</extensions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/incubator/injectless-client/src/main/java/org/glassfish/jersey/inject/injectless/NonInjectionManagerFactory.java b/incubator/injectless-client/src/main/java/org/glassfish/jersey/inject/injectless/NonInjectionManagerFactory.java
new file mode 100644
index 0000000..61e6455
--- /dev/null
+++ b/incubator/injectless-client/src/main/java/org/glassfish/jersey/inject/injectless/NonInjectionManagerFactory.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+package org.glassfish.jersey.inject.injectless;
+
+import org.glassfish.jersey.client.innate.inject.NonInjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionManagerFactory;
+
+import jakarta.annotation.Priority;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.ConstrainedTo;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.RuntimeType;
+
+/**
+ * <p>
+ * This {@link InjectionManagerFactory} implementation provides a special {@link InjectionManager}. The highest priority
+ * of this injection manager is not to require any DI container. It is designed for pure REST client performing a request
+ * without a further requirements for performing injections in the customer client classes, such a filter or a provider.
+ * It means the customer classes do not have any injection points defined by {@link Inject} or {@link Context}.
+ * </p>
+ * <p>
+ * Using this injection manager does not prevent using any Jersey modules (such as Jersey-Media-Jackson module) from working
+ * with the client.
+ * </p>
+ */
+@Priority(15)
+@ConstrainedTo(RuntimeType.CLIENT)
+public class NonInjectionManagerFactory implements InjectionManagerFactory {
+ @Override
+ public InjectionManager create(Object parent) {
+ return new NonInjectionManager(false);
+ }
+}
diff --git a/incubator/injectless-client/src/main/resources/META-INF/services/org.glassfish.jersey.internal.inject.InjectionManagerFactory b/incubator/injectless-client/src/main/resources/META-INF/services/org.glassfish.jersey.internal.inject.InjectionManagerFactory
new file mode 100644
index 0000000..8473fa4
--- /dev/null
+++ b/incubator/injectless-client/src/main/resources/META-INF/services/org.glassfish.jersey.internal.inject.InjectionManagerFactory
@@ -0,0 +1 @@
+org.glassfish.jersey.inject.injectless.NonInjectionManagerFactory
\ No newline at end of file
diff --git a/incubator/kryo/src/main/java/org/glassfish/jersey/kryo/internal/KryoMessageBodyProvider.java b/incubator/kryo/src/main/java/org/glassfish/jersey/kryo/internal/KryoMessageBodyProvider.java
index afd77b1..124e7b2 100644
--- a/incubator/kryo/src/main/java/org/glassfish/jersey/kryo/internal/KryoMessageBodyProvider.java
+++ b/incubator/kryo/src/main/java/org/glassfish/jersey/kryo/internal/KryoMessageBodyProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,11 +23,10 @@
import java.lang.reflect.Type;
import java.util.Optional;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
-import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.ContextResolver;
@@ -55,7 +54,8 @@
private final ContextResolver<Kryo> contextResolver;
private final Optional<KryoPool> kryoPool;
- public KryoMessageBodyProvider(@Context Providers providers) {
+ @Inject
+ public KryoMessageBodyProvider(Providers providers) {
final MediaType mediaType = new MediaType("application", "x-kryo");
contextResolver = providers.getContextResolver(Kryo.class, mediaType);
kryoPool = getKryoPool();
diff --git a/incubator/pom.xml b/incubator/pom.xml
index e82e47b..65f0a44 100644
--- a/incubator/pom.xml
+++ b/incubator/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2022 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2023 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -40,6 +40,7 @@
<module>declarative-linking</module>
<module>gae-integration</module>
<module>html-json</module>
+ <module>injectless-client</module>
<module>kryo</module>
<module>open-tracing</module>
</modules>
diff --git a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/injector/JerseyProxyResolverTest.java b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/injector/JerseyProxyResolverTest.java
index da6526d..a71e486 100644
--- a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/injector/JerseyProxyResolverTest.java
+++ b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/injector/JerseyProxyResolverTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -97,7 +97,7 @@
@Test
public void testProxyCreated() {
- MyInjectionResolver injectionResolver = new MyInjectionResolver(new JaxrsProviders());
+ MyInjectionResolver injectionResolver = new MyInjectionResolver(new JaxrsProviders(null, null, null));
InjecteeImpl injectee = new InjecteeImpl();
injectee.setRequiredType(Providers.class);
injectee.setParent(FIELDS[0]);
@@ -109,7 +109,7 @@
@Test
public void testProxyCached() {
- MyInjectionResolver injectionResolver = new MyInjectionResolver(new JaxrsProviders());
+ MyInjectionResolver injectionResolver = new MyInjectionResolver(new JaxrsProviders(null, null, null));
InjecteeImpl injectee1 = new InjecteeImpl();
injectee1.setRequiredType(Providers.class);
injectee1.setParent(FIELDS[0]);
@@ -126,7 +126,7 @@
@Test
public void testProxyCacheNotMismatched() {
- MyInjectionResolver injectionResolver1 = new MyInjectionResolver(new JaxrsProviders());
+ MyInjectionResolver injectionResolver1 = new MyInjectionResolver(new JaxrsProviders(null, null, null));
InjecteeImpl injectee1 = new InjecteeImpl();
injectee1.setRequiredType(Providers.class);
injectee1.setParent(FIELDS[0]);
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractCollectionJaxbProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractCollectionJaxbProvider.java
index 441023f..76e8750 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractCollectionJaxbProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractCollectionJaxbProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -39,6 +39,7 @@
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.NoContentException;
@@ -120,12 +121,12 @@
}
};
- public AbstractCollectionJaxbProvider(Providers ps) {
- super(ps);
+ public AbstractCollectionJaxbProvider(Providers ps, Configuration config) {
+ super(ps, config);
}
- public AbstractCollectionJaxbProvider(Providers ps, MediaType mt) {
- super(ps, mt);
+ public AbstractCollectionJaxbProvider(Providers ps, MediaType mt, Configuration config) {
+ super(ps, mt, config);
}
@Override
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbElementProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbElementProvider.java
index ec53720..63cd318 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbElementProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbElementProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -27,6 +27,7 @@
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.NoContentException;
@@ -67,8 +68,8 @@
*
* @param providers JAX-RS providers.
*/
- public AbstractJaxbElementProvider(Providers providers) {
- super(providers);
+ public AbstractJaxbElementProvider(Providers providers, Configuration config) {
+ super(providers, config);
}
/**
@@ -77,8 +78,8 @@
* @param providers JAX-RS providers.
* @param resolverMediaType JAXB component context resolver media type to be used.
*/
- public AbstractJaxbElementProvider(Providers providers, MediaType resolverMediaType) {
- super(providers, resolverMediaType);
+ public AbstractJaxbElementProvider(Providers providers, MediaType resolverMediaType, Configuration config) {
+ super(providers, resolverMediaType, config);
}
@Override
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java
index eac25ae..1d3c5c5 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractJaxbProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -25,7 +25,6 @@
import java.util.logging.Logger;
import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.ext.ContextResolver;
import jakarta.ws.rs.ext.Providers;
@@ -71,8 +70,8 @@
*
* @param providers JAX-RS providers.
*/
- public AbstractJaxbProvider(final Providers providers) {
- this(providers, null);
+ public AbstractJaxbProvider(final Providers providers, final Configuration config) {
+ this(providers, null, config);
}
/**
@@ -81,7 +80,7 @@
* @param providers JAX-RS providers.
* @param resolverMediaType JAXB component context resolver media type to be used.
*/
- public AbstractJaxbProvider(final Providers providers, final MediaType resolverMediaType) {
+ public AbstractJaxbProvider(final Providers providers, final MediaType resolverMediaType, final Configuration config) {
this.jaxrsProviders = providers;
fixedResolverMediaType = resolverMediaType != null;
@@ -112,10 +111,10 @@
this.mtUnmarshaller = null;
this.mtMarshaller = null;
}
+ setConfiguration(config);
}
// TODO This provider should be registered and configured via a feature.
- @Context
public void setConfiguration(final Configuration config) {
formattedOutput = Values.lazy(new Value<Boolean>() {
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractRootElementJaxbProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractRootElementJaxbProvider.java
index fa12ef9..afc9dc9 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractRootElementJaxbProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/AbstractRootElementJaxbProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -26,6 +26,7 @@
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.NoContentException;
@@ -69,8 +70,8 @@
*
* @param providers JAX-RS providers.
*/
- public AbstractRootElementJaxbProvider(Providers providers) {
- super(providers);
+ public AbstractRootElementJaxbProvider(Providers providers, Configuration config) {
+ super(providers, config);
}
/**
@@ -79,8 +80,8 @@
* @param providers JAX-RS providers.
* @param resolverMediaType JAXB component context resolver media type to be used.
*/
- public AbstractRootElementJaxbProvider(Providers providers, MediaType resolverMediaType) {
- super(providers, resolverMediaType);
+ public AbstractRootElementJaxbProvider(Providers providers, MediaType resolverMediaType, Configuration config) {
+ super(providers, resolverMediaType, config);
}
@Override
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/DocumentBuilderFactoryInjectionProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/DocumentBuilderFactoryInjectionProvider.java
index e327214..00bac95 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/DocumentBuilderFactoryInjectionProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/DocumentBuilderFactoryInjectionProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -39,11 +39,11 @@
*/
// TODO This provider should be registered and configured via a feature.
@Inject
- public DocumentBuilderFactoryInjectionProvider(final Configuration config) {
+ public DocumentBuilderFactoryInjectionProvider(final InjectionManager injectionManager, final Configuration config) {
super(config);
+ this.injectionManager = injectionManager;
}
- @Inject
private InjectionManager injectionManager;
@Override
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/DocumentProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/DocumentProvider.java
index 9a27215..4fbfcf1 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/DocumentProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/DocumentProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -55,10 +55,14 @@
@Singleton
public final class DocumentProvider extends AbstractMessageReaderWriterProvider<Document> {
+ private final Provider<DocumentBuilderFactory> dbf;
+ private final Provider<TransformerFactory> tf;
+
@Inject
- private Provider<DocumentBuilderFactory> dbf;
- @Inject
- private Provider<TransformerFactory> tf;
+ public DocumentProvider(Provider<DocumentBuilderFactory> dbf, Provider<TransformerFactory> tf) {
+ this.dbf = dbf;
+ this.tf = tf;
+ }
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/SaxParserFactoryInjectionProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/SaxParserFactoryInjectionProvider.java
index 24f862a..c629439 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/SaxParserFactoryInjectionProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/SaxParserFactoryInjectionProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -50,11 +50,11 @@
*/
// TODO This provider should be registered and configured via a feature.
@Inject
- public SaxParserFactoryInjectionProvider(final Configuration config) {
+ public SaxParserFactoryInjectionProvider(final InjectionManager injectionManager, final Configuration config) {
super(config);
+ this.injectionManager = injectionManager;
}
- @Inject
private InjectionManager injectionManager;
@Override
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/TransformerFactoryInjectionProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/TransformerFactoryInjectionProvider.java
index a647e6e..213c4ac 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/TransformerFactoryInjectionProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/TransformerFactoryInjectionProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -45,11 +45,11 @@
*/
// TODO This provider should be registered and configured via a feature.
@Inject
- public TransformerFactoryInjectionProvider(final Configuration config) {
+ public TransformerFactoryInjectionProvider(final InjectionManager injectionManager, final Configuration config) {
super(config);
+ this.injectionManager = injectionManager;
}
- @Inject
private InjectionManager injectionManager;
@Override
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlCollectionJaxbProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlCollectionJaxbProvider.java
index bf26f3d..4f0af6f 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlCollectionJaxbProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlCollectionJaxbProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,9 +24,10 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.ext.Providers;
@@ -50,14 +51,14 @@
private final Provider<XMLInputFactory> xif;
- XmlCollectionJaxbProvider(Provider<XMLInputFactory> xif, Providers ps) {
- super(ps);
+ XmlCollectionJaxbProvider(Provider<XMLInputFactory> xif, Providers ps, Configuration config) {
+ super(ps, config);
this.xif = xif;
}
- XmlCollectionJaxbProvider(Provider<XMLInputFactory> xif, Providers ps, MediaType mt) {
- super(ps, mt);
+ XmlCollectionJaxbProvider(Provider<XMLInputFactory> xif, Providers ps, MediaType mt, Configuration config) {
+ super(ps, mt, config);
this.xif = xif;
}
@@ -71,8 +72,9 @@
@Singleton
public static final class App extends XmlCollectionJaxbProvider {
- public App(@Context Provider<XMLInputFactory> xif, @Context Providers ps) {
- super(xif, ps, MediaType.APPLICATION_XML_TYPE);
+ @Inject
+ public App(Provider<XMLInputFactory> xif, Providers ps, Configuration config) {
+ super(xif, ps, MediaType.APPLICATION_XML_TYPE, config);
}
}
@@ -85,8 +87,9 @@
@Singleton
public static final class Text extends XmlCollectionJaxbProvider {
- public Text(@Context Provider<XMLInputFactory> xif, @Context Providers ps) {
- super(xif, ps, MediaType.TEXT_XML_TYPE);
+ @Inject
+ public Text(Provider<XMLInputFactory> xif, Providers ps, Configuration config) {
+ super(xif, ps, MediaType.TEXT_XML_TYPE, config);
}
}
@@ -99,8 +102,9 @@
@Singleton
public static final class General extends XmlCollectionJaxbProvider {
- public General(@Context Provider<XMLInputFactory> xif, @Context Providers ps) {
- super(xif, ps);
+ @Inject
+ public General(Provider<XMLInputFactory> xif, Providers ps, Configuration config) {
+ super(xif, ps, config);
}
@Override
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlInputFactoryInjectionProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlInputFactoryInjectionProvider.java
index 99aacb3..24bb77e 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlInputFactoryInjectionProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlInputFactoryInjectionProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -38,11 +38,11 @@
*/
// TODO This provider should be registered and configured via a feature.
@Inject
- public XmlInputFactoryInjectionProvider(final Configuration config) {
+ public XmlInputFactoryInjectionProvider(final InjectionManager injectionManager, final Configuration config) {
super(config);
+ this.injectionManager = injectionManager;
}
- @Inject
private InjectionManager injectionManager;
@Override
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlJaxbElementProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlJaxbElementProvider.java
index 6ea3eee..10b3646 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlJaxbElementProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlJaxbElementProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -20,9 +20,10 @@
import java.io.OutputStream;
import java.nio.charset.Charset;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.ext.Providers;
@@ -44,14 +45,14 @@
private final Provider<SAXParserFactory> spf;
- public XmlJaxbElementProvider(Provider<SAXParserFactory> spf, Providers ps) {
- super(ps);
+ public XmlJaxbElementProvider(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(ps, config);
this.spf = spf;
}
- public XmlJaxbElementProvider(Provider<SAXParserFactory> spf, Providers ps, MediaType mt) {
- super(ps, mt);
+ public XmlJaxbElementProvider(Provider<SAXParserFactory> spf, Providers ps, MediaType mt, Configuration config) {
+ super(ps, mt, config);
this.spf = spf;
}
@@ -65,8 +66,9 @@
@Singleton
public static final class App extends XmlJaxbElementProvider {
- public App(@Context Provider<SAXParserFactory> spf, @Context Providers ps) {
- super(spf, ps, MediaType.APPLICATION_XML_TYPE);
+ @Inject
+ public App(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(spf, ps, MediaType.APPLICATION_XML_TYPE, config);
}
}
@@ -79,8 +81,9 @@
@Singleton
public static final class Text extends XmlJaxbElementProvider {
- public Text(@Context Provider<SAXParserFactory> spf, @Context Providers ps) {
- super(spf, ps, MediaType.TEXT_XML_TYPE);
+ @Inject
+ public Text(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(spf, ps, MediaType.TEXT_XML_TYPE, config);
}
}
@@ -93,8 +96,9 @@
@Singleton
public static final class General extends XmlJaxbElementProvider {
- public General(@Context Provider<SAXParserFactory> spf, @Context Providers ps) {
- super(spf, ps);
+ @Inject
+ public General(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(spf, ps, config);
}
@Override
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlRootElementJaxbProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlRootElementJaxbProvider.java
index 1f08d4e..397b9ae 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlRootElementJaxbProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlRootElementJaxbProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -18,9 +18,10 @@
import java.io.InputStream;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.ext.Providers;
@@ -45,14 +46,14 @@
// Delay construction of factory
private final Provider<SAXParserFactory> spf;
- XmlRootElementJaxbProvider(Provider<SAXParserFactory> spf, Providers ps) {
- super(ps);
+ XmlRootElementJaxbProvider(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(ps, config);
this.spf = spf;
}
- XmlRootElementJaxbProvider(Provider<SAXParserFactory> spf, Providers ps, MediaType mt) {
- super(ps, mt);
+ XmlRootElementJaxbProvider(Provider<SAXParserFactory> spf, Providers ps, MediaType mt, Configuration config) {
+ super(ps, mt, config);
this.spf = spf;
}
@@ -67,8 +68,9 @@
@Singleton
public static final class App extends XmlRootElementJaxbProvider {
- public App(@Context Provider<SAXParserFactory> spf, @Context Providers ps) {
- super(spf, ps, MediaType.APPLICATION_XML_TYPE);
+ @Inject
+ public App(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(spf, ps, MediaType.APPLICATION_XML_TYPE, config);
}
}
@@ -82,8 +84,9 @@
@Singleton
public static final class Text extends XmlRootElementJaxbProvider {
- public Text(@Context Provider<SAXParserFactory> spf, @Context Providers ps) {
- super(spf, ps, MediaType.TEXT_XML_TYPE);
+ @Inject
+ public Text(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(spf, ps, MediaType.TEXT_XML_TYPE, config);
}
}
@@ -97,8 +100,9 @@
@Singleton
public static final class General extends XmlRootElementJaxbProvider {
- public General(@Context Provider<SAXParserFactory> spf, @Context Providers ps) {
- super(spf, ps);
+ @Inject
+ public General(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(spf, ps, config);
}
@Override
diff --git a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlRootObjectJaxbProvider.java b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlRootObjectJaxbProvider.java
index 9a8593c..76e61a1 100644
--- a/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlRootObjectJaxbProvider.java
+++ b/media/jaxb/src/main/java/org/glassfish/jersey/jaxb/internal/XmlRootObjectJaxbProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,12 +22,13 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
+import jakarta.inject.Inject;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
-import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.NoContentException;
@@ -53,14 +54,14 @@
private final Provider<SAXParserFactory> spf;
- XmlRootObjectJaxbProvider(Provider<SAXParserFactory> spf, Providers ps) {
- super(ps);
+ XmlRootObjectJaxbProvider(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(ps, config);
this.spf = spf;
}
- XmlRootObjectJaxbProvider(Provider<SAXParserFactory> spf, Providers ps, MediaType mt) {
- super(ps, mt);
+ XmlRootObjectJaxbProvider(Provider<SAXParserFactory> spf, Providers ps, MediaType mt, Configuration config) {
+ super(ps, mt, config);
this.spf = spf;
}
@@ -79,8 +80,9 @@
@Singleton
public static final class App extends XmlRootObjectJaxbProvider {
- public App(@Context Provider<SAXParserFactory> spf, @Context Providers ps) {
- super(spf, ps, MediaType.APPLICATION_XML_TYPE);
+ @Inject
+ public App(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(spf, ps, MediaType.APPLICATION_XML_TYPE, config);
}
}
@@ -93,8 +95,9 @@
@Singleton
public static final class Text extends XmlRootObjectJaxbProvider {
- public Text(@Context Provider<SAXParserFactory> spf, @Context Providers ps) {
- super(spf, ps, MediaType.TEXT_XML_TYPE);
+ @Inject
+ public Text(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(spf, ps, MediaType.TEXT_XML_TYPE, config);
}
}
@@ -107,8 +110,9 @@
@Singleton
public static final class General extends XmlRootObjectJaxbProvider {
- public General(@Context Provider<SAXParserFactory> spf, @Context Providers ps) {
- super(spf, ps);
+ @Inject
+ public General(Provider<SAXParserFactory> spf, Providers ps, Configuration config) {
+ super(spf, ps, config);
}
@Override
diff --git a/media/jaxb/src/test/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProviderTest.java b/media/jaxb/src/test/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProviderTest.java
index a0b4c26..2285de0 100644
--- a/media/jaxb/src/test/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProviderTest.java
+++ b/media/jaxb/src/test/java/org/glassfish/jersey/jaxb/internal/JaxbStringReaderProviderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -48,7 +48,7 @@
public void stringReaderDoesNotReadExternalDtds() {
Provider<SAXParserFactory> saxParserFactoryProvider = new Provider<SAXParserFactory>() {
- final SaxParserFactoryInjectionProvider spf = new SaxParserFactoryInjectionProvider(
+ final SaxParserFactoryInjectionProvider spf = new SaxParserFactoryInjectionProvider(null,
new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL));
@Override
diff --git a/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/internal/JsonBindingProvider.java b/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/internal/JsonBindingProvider.java
index efc7c81..c2ffe9e 100644
--- a/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/internal/JsonBindingProvider.java
+++ b/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/internal/JsonBindingProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,10 +23,15 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
+import jakarta.json.bind.Jsonb;
+import jakarta.json.bind.JsonbBuilder;
+import jakarta.json.bind.JsonbException;
+
import org.glassfish.jersey.jsonb.LocalizationMessages;
import org.glassfish.jersey.message.internal.AbstractMessageReaderWriterProvider;
import org.glassfish.jersey.message.internal.EntityInputStream;
+import jakarta.inject.Inject;
import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbException;
@@ -34,7 +39,6 @@
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.NoContentException;
@@ -55,9 +59,10 @@
private static final String JSON = "json";
private static final String PLUS_JSON = "+json";
- private Providers providers;
+ private final Providers providers;
- public JsonBindingProvider(@Context Providers providers) {
+ @Inject
+ public JsonBindingProvider(Providers providers) {
this.providers = providers;
}
diff --git a/media/json-gson/src/main/java/org/glassfish/jersey/gson/internal/JsonGsonProvider.java b/media/json-gson/src/main/java/org/glassfish/jersey/gson/internal/JsonGsonProvider.java
index a35dfad..ec86d03 100644
--- a/media/json-gson/src/main/java/org/glassfish/jersey/gson/internal/JsonGsonProvider.java
+++ b/media/json-gson/src/main/java/org/glassfish/jersey/gson/internal/JsonGsonProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,11 +23,11 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.NoContentException;
@@ -56,7 +56,8 @@
private Providers providers;
- public JsonGsonProvider(@Context Providers providers) {
+ @Inject
+ public JsonGsonProvider(Providers providers) {
this.providers = providers;
}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
index 527f1db..9abfbf1 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -25,19 +25,25 @@
import java.util.Arrays;
import java.util.List;
import jakarta.annotation.PostConstruct;
+import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.ext.Providers;
/**
* Entity Data provider based on Jackson JSON provider.
*/
@Singleton
public class DefaultJacksonJaxbJsonProvider extends JacksonJaxbJsonProvider {
-
- @Context
private Configuration commonConfig;
+ @Inject
+ public DefaultJacksonJaxbJsonProvider(Providers providers, Configuration config) {
+ super(new JacksonMapperConfigurator(null, DEFAULT_ANNOTATIONS));
+ this.commonConfig = config;
+ _providers = providers;
+ }
+
//do not register JaxbAnnotationModule because it brakes default annotations processing
private static final String[] EXCLUDE_MODULE_NAMES = {"JaxbAnnotationModule", "JakartaXmlBindAnnotationModule"};
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/FilteringJacksonJaxbJsonProvider.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/FilteringJacksonJaxbJsonProvider.java
index 815b45e..486ec09 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/FilteringJacksonJaxbJsonProvider.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/FilteringJacksonJaxbJsonProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,12 +22,14 @@
import java.lang.reflect.Method;
import java.lang.reflect.Type;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.inject.Singleton;
+import jakarta.ws.rs.ext.Providers;
import org.glassfish.jersey.internal.util.ReflectionHelper;
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.cfg.EndpointConfigBase;
@@ -57,8 +59,15 @@
@Singleton
public final class FilteringJacksonJaxbJsonProvider extends DefaultJacksonJaxbJsonProvider {
+ private final Provider<ObjectProvider<FilterProvider>> provider;
+
@Inject
- private Provider<ObjectProvider<FilterProvider>> provider;
+ public FilteringJacksonJaxbJsonProvider(Provider<ObjectProvider<FilterProvider>> provider,
+ Providers providers, Configuration config) {
+ super(providers, config);
+ this.provider = provider;
+ }
+
@Override
protected JsonEndpointConfig _configForWriting(final ObjectMapper mapper, final Annotation[] annotations,
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonObjectProvider.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonObjectProvider.java
index d341486..b4b37f4 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonObjectProvider.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonObjectProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,6 +23,8 @@
import java.util.Stack;
import org.glassfish.jersey.message.filtering.spi.AbstractObjectProvider;
+import org.glassfish.jersey.message.filtering.spi.EntityGraphProvider;
+import org.glassfish.jersey.message.filtering.spi.EntityInspector;
import org.glassfish.jersey.message.filtering.spi.ObjectGraph;
import com.fasterxml.jackson.core.JsonGenerator;
@@ -35,12 +37,22 @@
import com.fasterxml.jackson.databind.ser.PropertyFilter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
+import org.glassfish.jersey.message.filtering.spi.ScopeProvider;
+
+import jakarta.inject.Inject;
/**
* @author Michal Gajdos
*/
final class JacksonObjectProvider extends AbstractObjectProvider<FilterProvider> {
+ @Inject
+ public JacksonObjectProvider(ScopeProvider scopeProvider,
+ EntityInspector entityInspector,
+ EntityGraphProvider graphProvider) {
+ super(scopeProvider, entityInspector, graphProvider);
+ }
+
@Override
public FilterProvider transform(final ObjectGraph graph) {
// Root entity.
diff --git a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForDisabledModulesTest.java b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForDisabledModulesTest.java
index dc68332..9b7beb9 100644
--- a/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForDisabledModulesTest.java
+++ b/media/json-jackson/src/test/java/org/glassfish/jersey/jackson/internal/DefaultJsonJacksonProviderForDisabledModulesTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -55,6 +55,9 @@
private static class TestJacksonJaxbJsonProvider extends JacksonJaxbJsonProvider {
@Inject
+ public TestJacksonJaxbJsonProvider(Configuration configuration) {
+ this.configuration = configuration;
+ }
private Configuration configuration;
@PostConstruct
diff --git a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonJaxbElementProvider.java b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonJaxbElementProvider.java
index 51ec8ad..e8c3ac6 100644
--- a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonJaxbElementProvider.java
+++ b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonJaxbElementProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,9 +24,10 @@
import java.lang.reflect.Type;
import java.nio.charset.Charset;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.ext.Providers;
@@ -47,12 +48,12 @@
*/
public class JettisonJaxbElementProvider extends AbstractJaxbElementProvider {
- JettisonJaxbElementProvider(Providers ps) {
- super(ps);
+ JettisonJaxbElementProvider(Providers ps, Configuration config) {
+ super(ps, config);
}
- JettisonJaxbElementProvider(Providers ps, MediaType mt) {
- super(ps, mt);
+ JettisonJaxbElementProvider(Providers ps, MediaType mt, Configuration config) {
+ super(ps, mt, config);
}
@Override
@@ -69,8 +70,9 @@
@Consumes("application/json")
public static final class App extends JettisonJaxbElementProvider {
- public App(@Context Providers ps) {
- super(ps, MediaType.APPLICATION_JSON_TYPE);
+ @Inject
+ public App(Providers ps, Configuration config) {
+ super(ps, MediaType.APPLICATION_JSON_TYPE, config);
}
}
@@ -78,8 +80,9 @@
@Consumes("*/*")
public static final class General extends JettisonJaxbElementProvider {
- public General(@Context Providers ps) {
- super(ps);
+ @Inject
+ public General(Providers ps, Configuration config) {
+ super(ps, config);
}
@Override
diff --git a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonListElementProvider.java b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonListElementProvider.java
index 8f6395b..61380c1 100644
--- a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonListElementProvider.java
+++ b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonListElementProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -28,9 +28,10 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.ext.Providers;
@@ -54,12 +55,12 @@
*/
public class JettisonListElementProvider extends AbstractCollectionJaxbProvider {
- JettisonListElementProvider(Providers ps) {
- super(ps);
+ JettisonListElementProvider(Providers ps, Configuration config) {
+ super(ps, config);
}
- JettisonListElementProvider(Providers ps, MediaType mt) {
- super(ps, mt);
+ JettisonListElementProvider(Providers ps, MediaType mt, Configuration config) {
+ super(ps, mt, config);
}
@Override
@@ -75,9 +76,9 @@
@Produces("application/json")
@Consumes("application/json")
public static final class App extends JettisonListElementProvider {
-
- public App(@Context Providers ps) {
- super(ps, MediaType.APPLICATION_JSON_TYPE);
+ @Inject
+ public App(Providers ps, Configuration config) {
+ super(ps, MediaType.APPLICATION_JSON_TYPE, config);
}
}
@@ -85,8 +86,9 @@
@Consumes("*/*")
public static final class General extends JettisonListElementProvider {
- public General(@Context Providers ps) {
- super(ps);
+ @Inject
+ public General(Providers ps, Configuration config) {
+ super(ps, config);
}
@Override
diff --git a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonRootElementProvider.java b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonRootElementProvider.java
index 71e4810..b43ea1d 100644
--- a/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonRootElementProvider.java
+++ b/media/json-jettison/src/main/java/org/glassfish/jersey/jettison/internal/entity/JettisonRootElementProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,9 +24,10 @@
import java.lang.reflect.Type;
import java.nio.charset.Charset;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.ext.Providers;
@@ -48,12 +49,12 @@
*/
public class JettisonRootElementProvider extends AbstractRootElementJaxbProvider {
- JettisonRootElementProvider(Providers ps) {
- super(ps);
+ JettisonRootElementProvider(Providers ps, Configuration config) {
+ super(ps, config);
}
- JettisonRootElementProvider(Providers ps, MediaType mt) {
- super(ps, mt);
+ JettisonRootElementProvider(Providers ps, MediaType mt, Configuration config) {
+ super(ps, mt, config);
}
@Override
@@ -69,18 +70,18 @@
@Produces("application/json")
@Consumes("application/json")
public static final class App extends JettisonRootElementProvider {
-
- public App(@Context Providers ps) {
- super(ps, MediaType.APPLICATION_JSON_TYPE);
+ @Inject
+ public App(Providers ps, Configuration config) {
+ super(ps, MediaType.APPLICATION_JSON_TYPE, config);
}
}
@Produces("*/*")
@Consumes("*/*")
public static final class General extends JettisonRootElementProvider {
-
- public General(@Context Providers ps) {
- super(ps);
+ @Inject
+ public General(Providers ps, Configuration config) {
+ super(ps, config);
}
@Override
diff --git a/media/moxy/src/main/java/org/glassfish/jersey/moxy/internal/MoxyObjectProvider.java b/media/moxy/src/main/java/org/glassfish/jersey/moxy/internal/MoxyObjectProvider.java
index a5d4b7d..0e33d25 100644
--- a/media/moxy/src/main/java/org/glassfish/jersey/moxy/internal/MoxyObjectProvider.java
+++ b/media/moxy/src/main/java/org/glassfish/jersey/moxy/internal/MoxyObjectProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -20,9 +20,12 @@
import java.util.Map;
import java.util.Set;
+import jakarta.inject.Inject;
import jakarta.xml.bind.JAXBException;
import org.glassfish.jersey.message.filtering.spi.AbstractObjectProvider;
+import org.glassfish.jersey.message.filtering.spi.EntityGraphProvider;
+import org.glassfish.jersey.message.filtering.spi.EntityInspector;
import org.glassfish.jersey.message.filtering.spi.ObjectGraph;
import org.eclipse.persistence.jaxb.JAXBContext;
@@ -30,6 +33,7 @@
import org.eclipse.persistence.jaxb.JAXBHelper;
import org.eclipse.persistence.jaxb.Subgraph;
import org.eclipse.persistence.jaxb.TypeMappingInfo;
+import org.glassfish.jersey.message.filtering.spi.ScopeProvider;
/**
* @author Michal Gajdos
@@ -47,6 +51,13 @@
}
}
+ @Inject
+ public MoxyObjectProvider(ScopeProvider scopeProvider,
+ EntityInspector entityInspector,
+ EntityGraphProvider graphProvider) {
+ super(scopeProvider, entityInspector, graphProvider);
+ }
+
@Override
public org.eclipse.persistence.jaxb.ObjectGraph transform(final ObjectGraph graph) {
return createObjectGraph(graph.getEntityClass(), graph);
diff --git a/media/moxy/src/main/java/org/glassfish/jersey/moxy/json/internal/ConfigurableMoxyJsonProvider.java b/media/moxy/src/main/java/org/glassfish/jersey/moxy/json/internal/ConfigurableMoxyJsonProvider.java
index b7f3f09..6d07e04 100644
--- a/media/moxy/src/main/java/org/glassfish/jersey/moxy/json/internal/ConfigurableMoxyJsonProvider.java
+++ b/media/moxy/src/main/java/org/glassfish/jersey/moxy/json/internal/ConfigurableMoxyJsonProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -26,9 +26,9 @@
import java.util.Map;
import java.util.Set;
+import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.ContextResolver;
@@ -77,11 +77,13 @@
return propertyNames;
}
- @Context
- private Providers providers;
+ private final Configuration config;
- @Context
- private Configuration config;
+ @Inject
+ public ConfigurableMoxyJsonProvider(Providers providers, Configuration config) {
+ this.providers = providers;
+ this.config = config;
+ }
private MoxyJsonConfig globalConfig;
diff --git a/media/moxy/src/main/java/org/glassfish/jersey/moxy/json/internal/FilteringMoxyJsonProvider.java b/media/moxy/src/main/java/org/glassfish/jersey/moxy/json/internal/FilteringMoxyJsonProvider.java
index ac0a0a8..2a0ef42 100644
--- a/media/moxy/src/main/java/org/glassfish/jersey/moxy/json/internal/FilteringMoxyJsonProvider.java
+++ b/media/moxy/src/main/java/org/glassfish/jersey/moxy/json/internal/FilteringMoxyJsonProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -19,12 +19,14 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
+import jakarta.ws.rs.core.Configuration;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.inject.Singleton;
+import jakarta.ws.rs.ext.Providers;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;
@@ -41,9 +43,15 @@
*/
@Singleton
public class FilteringMoxyJsonProvider extends ConfigurableMoxyJsonProvider {
+ private final Provider<ObjectProvider<ObjectGraph>> provider;
@Inject
- private Provider<ObjectProvider<ObjectGraph>> provider;
+ public FilteringMoxyJsonProvider(Provider<ObjectProvider<ObjectGraph>> provider,
+ Providers providers,
+ Configuration config) {
+ super(providers, config);
+ this.provider = provider;
+ }
@Override
protected void preWriteTo(final Object object, final Class<?> type, final Type genericType, final Annotation[] annotations,
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartReaderClientSide.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartReaderClientSide.java
index 6d1f0f4..d8d4762 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartReaderClientSide.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartReaderClientSide.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -32,7 +32,6 @@
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.RuntimeType;
import jakarta.ws.rs.WebApplicationException;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
@@ -77,16 +76,15 @@
* Injectable helper to look up appropriate {@link MessageBodyReader}s
* for our body parts.
*/
- @Inject
private Provider<MessageBodyWorkers> messageBodyWorkers;
-
private final MIMEConfig mimeConfig;
/**
* Accepts constructor injection of the configuration parameters for this
* application.
*/
- public MultiPartReaderClientSide(@Context final Providers providers) {
+ @Inject
+ public MultiPartReaderClientSide(final Providers providers, Provider<MessageBodyWorkers> messageBodyWorkers) {
final ContextResolver<MultiPartProperties> contextResolver =
providers.getContextResolver(MultiPartProperties.class, MediaType.WILDCARD_TYPE);
@@ -98,6 +96,7 @@
properties = new MultiPartProperties();
}
+ this.messageBodyWorkers = messageBodyWorkers;
mimeConfig = createMimeConfig(properties);
}
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartReaderServerSide.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartReaderServerSide.java
index 0662c04..59c4c58 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartReaderServerSide.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartReaderServerSide.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,7 +23,6 @@
import jakarta.ws.rs.ConstrainedTo;
import jakarta.ws.rs.RuntimeType;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.MessageBodyReader;
@@ -34,6 +33,7 @@
import jakarta.inject.Singleton;
import org.glassfish.jersey.media.multipart.MultiPart;
+import org.glassfish.jersey.message.MessageBodyWorkers;
import org.glassfish.jersey.server.CloseableService;
import org.jvnet.mimepull.MIMEParsingException;
@@ -52,9 +52,10 @@
private final Provider<CloseableService> closeableServiceProvider;
@Inject
- public MultiPartReaderServerSide(@Context final Providers providers,
- final Provider<CloseableService> closeableServiceProvider) {
- super(providers);
+ public MultiPartReaderServerSide(final Providers providers,
+ final Provider<CloseableService> closeableServiceProvider,
+ final Provider<MessageBodyWorkers> messageBodyWorkers) {
+ super(providers, messageBodyWorkers);
this.closeableServiceProvider = closeableServiceProvider;
}
diff --git a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartWriter.java b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartWriter.java
index 4e155f8..5237d7e 100644
--- a/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartWriter.java
+++ b/media/multipart/src/main/java/org/glassfish/jersey/media/multipart/internal/MultiPartWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -27,9 +27,9 @@
import java.util.List;
import java.util.Map;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
@@ -64,7 +64,8 @@
*/
private final Providers providers;
- public MultiPartWriter(@Context final Providers providers) {
+ @Inject
+ public MultiPartWriter(final Providers providers) {
this.providers = providers;
}
diff --git a/media/sse/src/main/java/org/glassfish/jersey/media/sse/EventInputReader.java b/media/sse/src/main/java/org/glassfish/jersey/media/sse/EventInputReader.java
index cf5db6a..91ea8ba 100644
--- a/media/sse/src/main/java/org/glassfish/jersey/media/sse/EventInputReader.java
+++ b/media/sse/src/main/java/org/glassfish/jersey/media/sse/EventInputReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -31,7 +31,6 @@
import org.glassfish.jersey.internal.PropertiesDelegate;
import org.glassfish.jersey.message.MessageBodyWorkers;
-import org.glassfish.jersey.message.MessageUtils;
import org.glassfish.jersey.message.internal.ReaderInterceptorExecutor;
/**
@@ -41,10 +40,14 @@
*/
class EventInputReader implements MessageBodyReader<EventInput> {
+ private final Provider<MessageBodyWorkers> messageBodyWorkers;
+ private final Provider<PropertiesDelegate> propertiesDelegateProvider;
+
@Inject
- private Provider<MessageBodyWorkers> messageBodyWorkers;
- @Inject
- private Provider<PropertiesDelegate> propertiesDelegateProvider;
+ EventInputReader(Provider<MessageBodyWorkers> messageBodyWorkers, Provider<PropertiesDelegate> propertiesDelegateProvider) {
+ this.messageBodyWorkers = messageBodyWorkers;
+ this.propertiesDelegateProvider = propertiesDelegateProvider;
+ }
@Override
public boolean isReadable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
diff --git a/media/sse/src/main/java/org/glassfish/jersey/media/sse/InboundEventReader.java b/media/sse/src/main/java/org/glassfish/jersey/media/sse/InboundEventReader.java
index d4401f6..93eb446 100644
--- a/media/sse/src/main/java/org/glassfish/jersey/media/sse/InboundEventReader.java
+++ b/media/sse/src/main/java/org/glassfish/jersey/media/sse/InboundEventReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -49,8 +49,12 @@
private static final Logger LOGGER = Logger.getLogger(InboundEventReader.class.getName());
private static final byte[] EOL_DATA = new byte[] {'\n'};
+ private final Provider<MessageBodyWorkers> messageBodyWorkers;
+
@Inject
- private Provider<MessageBodyWorkers> messageBodyWorkers;
+ InboundEventReader(Provider<MessageBodyWorkers> messageBodyWorkers) {
+ this.messageBodyWorkers = messageBodyWorkers;
+ }
private enum State {
SKIPPING_PREPENDED_EMPTY_EVENTS,
diff --git a/media/sse/src/main/java/org/glassfish/jersey/media/sse/OutboundEventWriter.java b/media/sse/src/main/java/org/glassfish/jersey/media/sse/OutboundEventWriter.java
index b0ba040..18d9546 100644
--- a/media/sse/src/main/java/org/glassfish/jersey/media/sse/OutboundEventWriter.java
+++ b/media/sse/src/main/java/org/glassfish/jersey/media/sse/OutboundEventWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -52,8 +52,12 @@
private static final byte[] DATA_LEAD = "data: ".getBytes(UTF8);
private static final byte[] EOL = {'\n'};
+ private final Provider<MessageBodyWorkers> workersProvider;
+
@Inject
- private Provider<MessageBodyWorkers> workersProvider;
+ public OutboundEventWriter(Provider<MessageBodyWorkers> workersProvider) {
+ this.workersProvider = workersProvider;
+ }
@Override
public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations,
diff --git a/pom.xml b/pom.xml
index 10b3e20..399326e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -428,6 +428,12 @@
junit.jupiter.execution.parallel.mode.default=same_thread
</configurationParameters>
</properties>
+ <systemProperties>
+ <property>
+ <name>jersey.config.test.container.port</name>
+ <value>${jersey.config.test.container.port}</value>
+ </property>
+ </systemProperties>
<threadCount>124</threadCount>
</configuration>
<dependencies>
@@ -629,6 +635,12 @@
<skipTests>${skip.tests}</skipTests>
<skipITs>${skip.tests}</skipITs>
<argLine>${failsafe.coverage.argline}</argLine>
+ <systemProperties>
+ <property>
+ <name>jersey.config.test.container.port</name>
+ <value>${jersey.config.test.container.port}</value>
+ </property>
+ </systemProperties>
</configuration>
<executions>
<execution>
@@ -853,6 +865,26 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>${buildhelper.mvn.plugin.version}</version>
+ <configuration>
+ <portNames>
+ <portName>jersey.config.test.container.port</portName>
+ <portName>jersey.config.test.container.stop.port</portName>
+ </portNames>
+ </configuration>
+ <executions>
+ <execution>
+ <id>reserve-port</id>
+ <phase>process-test-classes</phase> <!-- pre-integration-test -->
+ <goals>
+ <goal>reserve-network-port</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
<extensions>
<extension>
@@ -1450,7 +1482,7 @@
<doctitle>Jersey ${jersey.version} API Documentation</doctitle>
<windowtitle>Jersey ${jersey.version} API</windowtitle>
<bottom>
- <![CDATA[Copyright © 2007-2022,
+ <![CDATA[Copyright © 2007-2023,
<a href="http://www.oracle.com">Oracle</a>
and/or its affiliates.
All Rights Reserved. Use is subject to license terms.]]>
@@ -2221,8 +2253,8 @@
<xmlunit.version>2.9.0</xmlunit.version>
<hk2.osgi.version>org.glassfish.hk2.*;version="[2.5,4)"</hk2.osgi.version>
<hk2.jvnet.osgi.version>org.jvnet.hk2.*;version="[2.5,4)"</hk2.jvnet.osgi.version>
- <httpclient.version>4.5.13</httpclient.version>
- <httpclient5.version>5.1.3</httpclient5.version>
+ <httpclient.version>4.5.14</httpclient.version>
+ <httpclient5.version>5.2.1</httpclient5.version>
<jackson.version>2.14.1</jackson.version>
<javassist.version>3.29.0-GA</javassist.version>
<jboss.logging.version>3.4.2.Final</jboss.logging.version>
diff --git a/security/oauth1-client/src/main/java/org/glassfish/jersey/client/oauth1/OAuth1ClientFilter.java b/security/oauth1-client/src/main/java/org/glassfish/jersey/client/oauth1/OAuth1ClientFilter.java
index eab1cb1..b3d466a 100644
--- a/security/oauth1-client/src/main/java/org/glassfish/jersey/client/oauth1/OAuth1ClientFilter.java
+++ b/security/oauth1-client/src/main/java/org/glassfish/jersey/client/oauth1/OAuth1ClientFilter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -48,11 +48,14 @@
@Priority(Priorities.AUTHENTICATION)
class OAuth1ClientFilter implements ClientRequestFilter {
- @Inject
private Provider<OAuth1Signature> oAuthSignature;
+ private Provider<MessageBodyWorkers> messageBodyWorkers;
@Inject
- private Provider<MessageBodyWorkers> messageBodyWorkers;
+ public OAuth1ClientFilter(Provider<OAuth1Signature> oAuthSignature, Provider<MessageBodyWorkers> messageBodyWorkers) {
+ this.oAuthSignature = oAuthSignature;
+ this.messageBodyWorkers = messageBodyWorkers;
+ }
@Override
public void filter(ClientRequestContext request) throws IOException {
diff --git a/security/oauth2-client/src/main/java/org/glassfish/jersey/client/oauth2/AuthCodeGrantImpl.java b/security/oauth2-client/src/main/java/org/glassfish/jersey/client/oauth2/AuthCodeGrantImpl.java
index bed3cee..6a54ce1 100644
--- a/security/oauth2-client/src/main/java/org/glassfish/jersey/client/oauth2/AuthCodeGrantImpl.java
+++ b/security/oauth2-client/src/main/java/org/glassfish/jersey/client/oauth2/AuthCodeGrantImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -354,11 +354,15 @@
static class DefaultTokenMessageBodyReader implements MessageBodyReader<TokenResult> {
// Provider here prevents circular dependency error from HK2 (workers inject providers and this provider inject workers)
- @Inject
- private Provider<MessageBodyWorkers> workers;
+ private final Provider<MessageBodyWorkers> workers;
+ private final Provider<PropertiesDelegate> propertiesDelegateProvider;
@Inject
- private Provider<PropertiesDelegate> propertiesDelegateProvider;
+ public DefaultTokenMessageBodyReader(Provider<MessageBodyWorkers> workers,
+ Provider<PropertiesDelegate> propertiesDelegateProvider) {
+ this.propertiesDelegateProvider = propertiesDelegateProvider;
+ this.workers = workers;
+ }
private static Iterable<ReaderInterceptor> EMPTY_INTERCEPTORS = new ArrayList<>();
diff --git a/tests/e2e-client/pom.xml b/tests/e2e-client/pom.xml
index 8dae6fa..35dd31c 100644
--- a/tests/e2e-client/pom.xml
+++ b/tests/e2e-client/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2023 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -46,6 +46,25 @@
<sun.net.http.allowRestrictedHeaders>true</sun.net.http.allowRestrictedHeaders>
</systemPropertyVariables>
</configuration>
+ <executions>
+ <execution>
+ <id>WithHK2</id>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <excludes>
+ <exclude>**/NonInjectionManagerTest.java</exclude>
+ </excludes>
+ <systemPropertyVariables>
+ <jersey.injectionmanager.hk2>true</jersey.injectionmanager.hk2>
+ </systemPropertyVariables>
+ <classpathDependencyExcludes>
+ <classpathDependencyExclude>org.glassfish.jersey.incubator:jersey-injectless-client</classpathDependencyExclude>
+ </classpathDependencyExcludes>
+ </configuration>
+ </execution>
+ </executions>
</plugin>
</plugins>
</build>
@@ -161,6 +180,12 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.incubator</groupId>
+ <artifactId>jersey-injectless-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpHeadersInjectionTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpHeadersInjectionTest.java
index a0d90fb..a1a6418 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpHeadersInjectionTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/HttpHeadersInjectionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -20,6 +20,7 @@
import org.glassfish.jersey.test.JerseyTest;
import org.junit.jupiter.api.Test;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
@@ -43,7 +44,6 @@
import jakarta.ws.rs.ext.WriterInterceptor;
import jakarta.ws.rs.ext.WriterInterceptorContext;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -74,10 +74,13 @@
}
public static class HttpHeadersFilter implements ClientRequestFilter {
-
- @Context
HttpHeaders headers;
+ @Inject
+ public HttpHeadersFilter(HttpHeaders headers) {
+ this.headers = headers;
+ }
+
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
requestContext.abortWith(Response.ok(headers.getHeaderString(HEADER_NAME)).build());
@@ -85,10 +88,13 @@
}
public static class HttpHeadersResponseFilter implements ClientResponseFilter {
-
- @Context
HttpHeaders headers;
+ @Inject
+ public HttpHeadersResponseFilter(HttpHeaders headers) {
+ this.headers = headers;
+ }
+
private static int headerValue = 0;
public int getHeaderValue() {
@@ -103,9 +109,13 @@
@Produces(MediaType.TEXT_PLAIN)
public static class StringWriter implements MessageBodyWriter<String> {
- @Context
HttpHeaders headers;
+ @Inject
+ public StringWriter(HttpHeaders headers) {
+ this.headers = headers;
+ }
+
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return true;
@@ -122,10 +132,13 @@
@Consumes({MediaType.TEXT_PLAIN})
public static class StringReader implements MessageBodyReader<String> {
-
- @Context
HttpHeaders headers;
+ @Inject
+ public StringReader(HttpHeaders headers) {
+ this.headers = headers;
+ }
+
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return true;
@@ -140,10 +153,13 @@
}
public static class HttpHeadersReaderInterceptor implements ReaderInterceptor {
-
- @Context
HttpHeaders headers;
+ @Inject
+ public HttpHeadersReaderInterceptor(HttpHeaders headers) {
+ this.headers = headers;
+ }
+
@Override
public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
context.getInputStream().close();
@@ -153,10 +169,13 @@
}
public static class HttpHeadersWriterInterceptor implements WriterInterceptor {
-
- @Context
HttpHeaders headers;
+ @Inject
+ public HttpHeadersWriterInterceptor(HttpHeaders headers) {
+ this.headers = headers;
+ }
+
@Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
OutputStreamWriter osw = new OutputStreamWriter(context.getOutputStream());
@@ -177,7 +196,7 @@
@Test
public void testHttpHeadersInjectionInResponseFilter() {
final String value = "1";
- final HttpHeadersResponseFilter filter = new HttpHeadersResponseFilter();
+ final HttpHeadersResponseFilter filter = new HttpHeadersResponseFilter(null);
final String response = target().register(HttpHeadersResponseFilter.class).request().header(HEADER_NAME, value)
.buildPost(Entity.entity(value, MediaType.TEXT_PLAIN_TYPE)).invoke(String.class);
assertThat(response, is(value));
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/InjectedClientBodyWorker.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/InjectedClientBodyWorker.java
index 7cf59c2..e42453b 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/InjectedClientBodyWorker.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/InjectedClientBodyWorker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,6 +22,7 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
+import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
@@ -30,7 +31,6 @@
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.ContextResolver;
@@ -73,10 +73,13 @@
@Provider
@Produces(ProviderType)
public static class ProvidersInjectedWriter implements MessageBodyWriter<String> {
-
- @Context
Providers providers;
+ @Inject
+ public ProvidersInjectedWriter(Providers providers) {
+ this.providers = providers;
+ }
+
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return type == String.class;
@@ -105,9 +108,13 @@
@Consumes(ProviderType)
public static class ProvidersInjectedReader implements MessageBodyReader<String> {
- @Context
Providers providers;
+ @Inject
+ ProvidersInjectedReader(Providers providers) {
+ this.providers = providers;
+ }
+
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return type == String.class;
@@ -132,9 +139,13 @@
@Produces(ConfigurationTYPE)
public static class ConfigurationInjectedWriter implements MessageBodyWriter<String> {
- @Context
Configuration configuration;
+ @Inject
+ public ConfigurationInjectedWriter(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return type == String.class;
@@ -158,10 +169,13 @@
@Provider
@Consumes(ConfigurationTYPE)
public static class ConfigurationInjectedReader implements MessageBodyReader<String> {
-
- @Context
Configuration configuration;
+ @Inject
+ public ConfigurationInjectedReader(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return type == String.class;
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/NonInjectionManagerTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/NonInjectionManagerTest.java
new file mode 100644
index 0000000..d547792
--- /dev/null
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/NonInjectionManagerTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.client;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.Response;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+import org.glassfish.jersey.inject.injectless.NonInjectionManagerFactory;
+
+public class NonInjectionManagerTest {
+ @Test
+ public void testNonInjectionManagerIsUsed() {
+ String value = System.getProperty("jersey.injectionmanager.hk2");
+ if ("true".equals(value)) {
+ return;
+ }
+
+ Records records = new Records();
+ Logger logger = Logger.getLogger(new NonInjectionManagerFactory().create(null).getClass().getName());
+ Level oldLevel = logger.getLevel();
+ logger.setLevel(Level.FINEST);
+ logger.addHandler(records);
+
+ ClientBuilder.newClient().register((ClientRequestFilter) requestContext -> {
+ requestContext.abortWith(Response.ok().build());
+ }).target("http://localhost:9998/nevermind").request().get();
+
+ logger.removeHandler(records);
+ logger.setLevel(oldLevel);
+
+ LogRecord warning = records.records.get(0);
+ Assertions.assertTrue(warning.getMessage().contains("injection-less"));
+ }
+
+ private static class Records extends Handler {
+ private List<LogRecord> records = new LinkedList<>();
+ @Override
+ public void publish(LogRecord record) {
+ records.add(record);
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void close() throws SecurityException {
+ }
+ }
+}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/RequestScopedReadEntityTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/RequestScopedReadEntityTest.java
index d53685e..78ce436 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/RequestScopedReadEntityTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/RequestScopedReadEntityTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -71,9 +71,12 @@
@Produces("text/plain")
public static class ScopedMessageEntityProvider extends AbstractMessageReaderWriterProvider<Message> {
+ private final Provider<ClientRequest> clientRequestProvider;
@Inject
- private Provider<ClientRequest> clientRequestProvider;
+ public ScopedMessageEntityProvider(Provider<ClientRequest> clientRequestProvider) {
+ this.clientRequestProvider = clientRequestProvider;
+ }
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
diff --git a/tests/e2e-entity/pom.xml b/tests/e2e-entity/pom.xml
index 7e0c7db..06324ed 100644
--- a/tests/e2e-entity/pom.xml
+++ b/tests/e2e-entity/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2023 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -43,6 +43,19 @@
<enableAssertions>false</enableAssertions>
<skipTests>${skip.e2e}</skipTests>
</configuration>
+ <executions>
+ <execution>
+ <id>WithHK2</id>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <classpathDependencyExcludes>
+ <classpathDependencyExclude>org.glassfish.jersey.incubator:jersey-injectless-client</classpathDependencyExclude>
+ </classpathDependencyExcludes>
+ </configuration>
+ </execution>
+ </executions>
</plugin>
</plugins>
</build>
@@ -171,6 +184,13 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.glassfish.jersey.incubator</groupId>
+ <artifactId>jersey-injectless-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<scope>test</scope>
diff --git a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/FilteringMessageBodyProvider.java b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/FilteringMessageBodyProvider.java
index fe6c3df..b76f67a 100644
--- a/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/FilteringMessageBodyProvider.java
+++ b/tests/e2e-entity/src/test/java/org/glassfish/jersey/tests/e2e/entity/filtering/FilteringMessageBodyProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -52,8 +52,12 @@
private static final Logger LOGGER = Logger.getLogger(FilteringMessageBodyProvider.class.getName());
+ private final jakarta.inject.Provider<ObjectProvider<ObjectGraph>> provider;
+
@Inject
- private jakarta.inject.Provider<ObjectProvider<ObjectGraph>> provider;
+ public FilteringMessageBodyProvider(jakarta.inject.Provider<ObjectProvider<ObjectGraph>> provider) {
+ this.provider = provider;
+ }
@Override
public boolean isReadable(final Class<?> type, final Type genericType, final Annotation[] annotations,
diff --git a/tests/e2e-server/pom.xml b/tests/e2e-server/pom.xml
index a3760af..57873f4 100644
--- a/tests/e2e-server/pom.xml
+++ b/tests/e2e-server/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2017, 2023 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -43,6 +43,19 @@
<enableAssertions>false</enableAssertions>
<skipTests>${skip.e2e}</skipTests>
</configuration>
+ <executions>
+ <execution>
+ <id>WithHK2</id>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <classpathDependencyExcludes>
+ <classpathDependencyExclude>org.glassfish.jersey.incubator:jersey-injectless-client</classpathDependencyExclude>
+ </classpathDependencyExcludes>
+ </configuration>
+ </execution>
+ </executions>
</plugin>
</plugins>
</build>
@@ -179,6 +192,13 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.glassfish.jersey.incubator</groupId>
+ <artifactId>jersey-injectless-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-util</artifactId>
<scope>test</scope>
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ManagedClientExecutorTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ManagedClientExecutorTest.java
index 43d18e0..b771c54 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ManagedClientExecutorTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/ManagedClientExecutorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -33,6 +33,7 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.LogRecord;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@@ -63,6 +64,11 @@
*/
public class ManagedClientExecutorTest extends JerseyTest {
+ public ManagedClientExecutorTest() {
+ // The tests need to run on port 9998, since @Uri() annotation needs a constant String with a port
+ System.setProperty(TestProperties.CONTAINER_PORT, "9998");
+ }
+
@Override
protected ResourceConfig configure() {
enable(TestProperties.LOG_TRAFFIC);
@@ -213,11 +219,15 @@
*/
public static class SchedulerThreadNameReader implements MessageBodyReader<SchedulerThreadName> {
- @Inject
- ScheduledExecutorServiceProvider injectedProvider;
+ private final ScheduledExecutorServiceProvider injectedProvider;
+ private final ScheduledExecutorService injectedService;
@Inject
- ScheduledExecutorService injectedService;
+ public SchedulerThreadNameReader(ScheduledExecutorService injectedService,
+ ScheduledExecutorServiceProvider injectedProvider) {
+ this.injectedProvider = injectedProvider;
+ this.injectedService = injectedService;
+ }
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
@@ -256,8 +266,15 @@
@Test
public void testManagedClientExecutor() {
- final String response = target().path("test/executor").request().get(String.class);
- Assertions.assertEquals("foo-executor-service-0", response);
+ try {
+ final String response = target().path("test/executor").request().get(String.class);
+ Assertions.assertEquals("foo-executor-service-0", response);
+ } catch (Exception e) {
+ for (LogRecord record : getLoggedRecords()) {
+ System.out.println(record.getMessage());
+ }
+ }
+
}
@Test
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionOverrideTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionOverrideTest.java
index e2830bd..8aa3801 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionOverrideTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/validation/validateonexecution/ValidateOnExecutionOverrideTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -19,6 +19,7 @@
import java.util.List;
import java.util.logging.Level;
import java.util.logging.LogRecord;
+import java.util.stream.Collectors;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@@ -101,8 +102,13 @@
private void _test(final String path) throws Exception {
assertThat(target(path).request().get().getStatus(), equalTo(500));
- final List<LogRecord> loggedRecords = getLoggedRecords();
+ final List<LogRecord> loggedRecords = getLoggedRecords()
+ .stream()
+ .filter(log -> log.getSourceClassName().equals(LOGGER_NAME)) // Skip warnings from outside of Validation
+ .collect(Collectors.toList());
assertThat(loggedRecords.size(), equalTo(1));
assertThat(loggedRecords.get(0).getThrown(), instanceOf(ValidationException.class));
}
+
+ private static final String LOGGER_NAME = "org.glassfish.jersey.server.validation.internal.ValidationExceptionMapper";
}
diff --git a/tests/e2e-tls/pom.xml b/tests/e2e-tls/pom.xml
new file mode 100644
index 0000000..1ae746c
--- /dev/null
+++ b/tests/e2e-tls/pom.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<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/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.glassfish.jersey.tests</groupId>
+ <artifactId>project</artifactId>
+ <version>3.0.99-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>e2e-tls</artifactId>
+ <name>jersey-tests-e2e-tls</name>
+ <packaging>jar</packaging>
+
+ <description>Jersey E2E SSL/TLS tests</description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <forkCount>1</forkCount>
+ <reuseForks>false</reuseForks>
+ <enableAssertions>false</enableAssertions>
+ <skipTests>${skip.e2e}</skipTests>
+ <systemPropertyVariables>
+ <sun.net.http.allowRestrictedHeaders>true</sun.net.http.allowRestrictedHeaders>
+ <property>
+ <name>ssl.debug</name>
+ <value>true</value>
+ </property>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-bundle</artifactId>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-suite</artifactId>
+ <version>${junit-platform-suite.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.specto</groupId>
+ <artifactId>hoverfly-java-junit5</artifactId>
+ <version>0.14.0</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-apache5-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-grizzly-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-jetty-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.connectors</groupId>
+ <artifactId>jersey-jdk-connector</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-signature</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>jdk11+</id>
+ <activation>
+ <jdk>[11,)</jdk>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-osgi</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <properties>
+ <!-- https://bugs.openjdk.java.net/browse/JDK-8211426 -->
+ <surefire.security.argline>-Djdk.tls.server.protocols=TLSv1.2</surefire.security.argline>
+ </properties>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/ClientHelloTestServer.java b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/ClientHelloTestServer.java
new file mode 100644
index 0000000..703d1c8
--- /dev/null
+++ b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/ClientHelloTestServer.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.tls;
+
+import org.glassfish.jersey.tests.e2e.tls.explorer.SSLCapabilities;
+import org.glassfish.jersey.tests.e2e.tls.explorer.SSLExplorer;
+
+import javax.net.ServerSocketFactory;
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SNIMatcher;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+public class ClientHelloTestServer {
+ private ServerSocket serverSocket;
+ private Thread serverThread;
+ private volatile State state = State.NONE;
+
+ private enum State {
+ NONE,
+ INIT,
+ STARTED,
+ STOPPED
+ }
+
+ protected ServerSocketFactory getServerSocketFactory() {
+ return ServerSocketFactory.getDefault();
+ }
+
+ protected void afterHandshake(Socket socket, SSLCapabilities capabilities) {
+
+ }
+
+ public void init(int port) {
+ ServerSocketFactory factory = getServerSocketFactory();
+ try {
+ serverSocket = factory.createServerSocket(port);
+
+ state = State.INIT;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void start() {
+ if (state != State.INIT) {
+ System.out.println("Server has not been initialized");
+ }
+ Thread thread = new Thread(() -> {
+ while (state == State.INIT) {
+ Socket socket = null;
+ try {
+ socket = serverSocket.accept();
+
+ inspect(socket);
+ } catch (SocketException e) {
+ if (!e.getMessage().equals("Interrupted function call: accept failed")) {
+ e.printStackTrace();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ serverThread = thread;
+ thread.start();
+ }
+
+ public void stop() {
+ try {
+ state = State.STOPPED;
+ serverSocket.close();
+ serverThread.join();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void inspect(Socket socket) throws IOException {
+ InputStream ins = socket.getInputStream();
+
+ byte[] buffer = new byte[0xFF];
+ int position = 0;
+ SSLCapabilities capabilities = null;
+
+// Read the header of TLS record
+ while (position < SSLExplorer.RECORD_HEADER_SIZE) {
+ int count = SSLExplorer.RECORD_HEADER_SIZE - position;
+ int n = ins.read(buffer, position, count);
+ if (n < 0) {
+ throw new IOException("unexpected end of stream!");
+ }
+ position += n;
+ }
+
+// Get the required size to explore the SSL capabilities
+ int recordLength = SSLExplorer.getRequiredSize(buffer, 0, position);
+ if (buffer.length < recordLength) {
+ buffer = Arrays.copyOf(buffer, recordLength);
+ }
+
+ while (position < recordLength) {
+ int count = recordLength - position;
+ int n = ins.read(buffer, position, count);
+ if (n < 0) {
+ throw new IOException("unexpected end of stream!");
+ }
+ position += n;
+ }
+
+// Explore
+ capabilities = SSLExplorer.explore(buffer, 0, recordLength);
+ if (capabilities != null) {
+ System.out.println("Record version: " + capabilities.getRecordVersion());
+ System.out.println("Hello version: " + capabilities.getHelloVersion());
+ }
+
+ afterHandshake(socket, capabilities);
+ }
+}
diff --git a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SniTest.java b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SniTest.java
new file mode 100644
index 0000000..1e8d893
--- /dev/null
+++ b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/SniTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.tls;
+
+import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
+import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.client.spi.ConnectorProvider;
+import org.glassfish.jersey.jdk.connector.JdkConnectorProvider;
+import org.glassfish.jersey.netty.connector.NettyConnectorProvider;
+import org.glassfish.jersey.tests.e2e.tls.explorer.SSLCapabilities;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import javax.net.ssl.SNIServerName;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class SniTest {
+ private static final int PORT = 8443;
+ private static final String LOCALHOST = "127.0.0.1";
+
+
+ static {
+ // JDK specific settings
+ System.setProperty("jdk.net.hosts.file", SniTest.class.getResource("/hosts").getPath());
+ }
+
+ public static ConnectorProvider[] getConnectors() {
+ return new ConnectorProvider[] {
+ new NettyConnectorProvider(),
+ new ApacheConnectorProvider(),
+ new Apache5ConnectorProvider(),
+ new JdkConnectorProvider(),
+ new HttpUrlConnectorProvider()
+ };
+ }
+
+ @ParameterizedTest
+ @MethodSource("getConnectors")
+ public void server1Test(ConnectorProvider provider) {
+ ClientConfig clientConfig = new ClientConfig();
+ clientConfig.connectorProvider(provider);
+ serverTest(clientConfig, "www.host1.com");
+ }
+
+ public void serverTest(ClientConfig clientConfig, String hostName) {
+ String newHostName = replaceWhenHostNotKnown(hostName);
+ final List<SNIServerName> serverNames = new LinkedList<>();
+ final String[] requestHostName = new String[1];
+ ClientHelloTestServer server = new ClientHelloTestServer() {
+ @Override
+ protected void afterHandshake(Socket socket, SSLCapabilities capabilities) {
+ serverNames.addAll(capabilities.getServerNames());
+ }
+ };
+ server.init(PORT);
+ server.start();
+
+ clientConfig.property(ClientProperties.READ_TIMEOUT, 2000);
+ clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 2000);
+ try (Response r = ClientBuilder.newClient(clientConfig)
+ .register(new ClientRequestFilter() {
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ requestHostName[0] = requestContext.getUri().getHost();
+ }
+ })
+ .target("https://" + (newHostName.equals(LOCALHOST) ? LOCALHOST : "www.host0.com") + ":" + PORT)
+ .path("host")
+ .request()
+ .header(HttpHeaders.HOST, hostName + ":8080")
+ .get()) {
+ // empty
+ } catch (Exception e) {
+ Throwable cause = e;
+ while (cause != null
+ && !SocketTimeoutException.class.isInstance(cause)
+ && TimeoutException.class.isInstance(cause)) {
+ cause = cause.getCause();
+ }
+ if (cause == null && /*IOE*/ !e.getMessage().contains("Stream closed")) {
+ throw e;
+ }
+ }
+
+ server.stop();
+
+ if (serverNames.isEmpty()) {
+ throw new IllegalStateException("ServerNames are empty");
+ }
+
+ String clientSniName = new String(serverNames.get(0).getEncoded());
+ if (!hostName.equals(clientSniName)) {
+ throw new IllegalStateException("Unexpected client SNI name " + clientSniName);
+ }
+
+ if (!LOCALHOST.equals(newHostName) && requestHostName[0].equals(hostName)) {
+ throw new IllegalStateException("The HTTP Request is made with the same");
+ }
+
+ System.out.append("Found expected Client SNI ").println(serverNames.get(0));
+ }
+
+ /*
+ * The method checks whether the JDK-dependent property "jdk.net.hosts.file" works.
+ * If it does, the request is made with the hostname, so that the 3rd party client has
+ * the request with the hostname. If a real address is returned or UnknownHostException
+ * is thrown, the property did not work and the request needs to use 127.0.0.1.
+ */
+ private static String replaceWhenHostNotKnown(String hostName) {
+ try {
+ InetAddress inetAddress = InetAddress.getByName(hostName);
+ return LOCALHOST.equals(inetAddress.getHostAddress()) ? hostName : LOCALHOST;
+ } catch (UnknownHostException e) {
+ return LOCALHOST;
+ }
+ }
+}
diff --git a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/explorer/SSLCapabilities.java b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/explorer/SSLCapabilities.java
new file mode 100644
index 0000000..e21b86a
--- /dev/null
+++ b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/explorer/SSLCapabilities.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle or the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.glassfish.jersey.tests.e2e.tls.explorer;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import javax.net.ssl.SNIServerName;
+
+/**
+ * Encapsulates the security capabilities of an SSL/TLS connection.
+ * <P>
+ * The security capabilities are the list of ciphersuites to be accepted in
+ * an SSL/TLS handshake, the record version, the hello version, and server
+ * name indication, etc., of an SSL/TLS connection.
+ * <P>
+ * <code>SSLCapabilities</code> can be retrieved by exploring the network
+ * data of an SSL/TLS connection via {@link SSLExplorer#explore(ByteBuffer)}
+ * or {@link SSLExplorer#explore(byte[], int, int)}.
+ *
+ * @see SSLExplorer
+ */
+public abstract class SSLCapabilities {
+
+ /**
+ * Returns the record version of an SSL/TLS connection
+ *
+ * @return a non-null record version
+ */
+ public abstract String getRecordVersion();
+
+ /**
+ * Returns the hello version of an SSL/TLS connection
+ *
+ * @return a non-null hello version
+ */
+ public abstract String getHelloVersion();
+
+ /**
+ * Returns a <code>List</code> containing all {@link SNIServerName}s
+ * of the server name indication.
+ *
+ * @return a non-null immutable list of {@link SNIServerName}s
+ * of the server name indication parameter, may be empty
+ * if no server name indication.
+ *
+ * @see SNIServerName
+ */
+ public abstract List<SNIServerName> getServerNames();
+}
+
diff --git a/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/explorer/SSLExplorer.java b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/explorer/SSLExplorer.java
new file mode 100644
index 0000000..71c1f4e
--- /dev/null
+++ b/tests/e2e-tls/src/test/java/org/glassfish/jersey/tests/e2e/tls/explorer/SSLExplorer.java
@@ -0,0 +1,627 @@
+package org.glassfish.jersey.tests.e2e.tls.explorer;
+
+/*
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle or the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import javax.net.ssl.SNIHostName;
+import javax.net.ssl.SNIServerName;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLProtocolException;
+import javax.net.ssl.StandardConstants;
+import java.nio.ByteBuffer;
+import java.nio.BufferUnderflowException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Instances of this class acts as an explorer of the network data of an
+ * SSL/TLS connection.
+ */
+public final class SSLExplorer {
+
+ // Private constructor prevents construction outside this class.
+ private SSLExplorer() {
+ }
+
+ /**
+ * The header size of TLS/SSL records.
+ * <P>
+ * The value of this constant is {@value}.
+ */
+ public static final int RECORD_HEADER_SIZE = 0x05;
+
+ /**
+ * Returns the required number of bytes in the {@code source}
+ * {@link ByteBuffer} necessary to explore SSL/TLS connection.
+ * <P>
+ * This method tries to parse as few bytes as possible from
+ * {@code source} byte buffer to get the length of an
+ * SSL/TLS record.
+ * <P>
+ * This method accesses the {@code source} parameter in read-only
+ * mode, and does not update the buffer's properties such as capacity,
+ * limit, position, and mark values.
+ *
+ * @param source
+ * a {@link ByteBuffer} containing
+ * inbound or outbound network data for an SSL/TLS connection.
+ * @throws BufferUnderflowException if less than {@code RECORD_HEADER_SIZE}
+ * bytes remaining in {@code source}
+ * @return the required size in byte to explore an SSL/TLS connection
+ */
+ public static int getRequiredSize(ByteBuffer source) {
+
+ ByteBuffer input = source.duplicate();
+
+ // Do we have a complete header?
+ if (input.remaining() < RECORD_HEADER_SIZE) {
+ throw new BufferUnderflowException();
+ }
+
+ // Is it a handshake message?
+ byte firstByte = input.get();
+ byte secondByte = input.get();
+ byte thirdByte = input.get();
+ if ((firstByte & 0x80) != 0 && thirdByte == 0x01) {
+ // looks like a V2ClientHello
+ // return (((firstByte & 0x7F) << 8) | (secondByte & 0xFF)) + 2;
+ return RECORD_HEADER_SIZE; // Only need the header fields
+ } else {
+ return (((input.get() & 0xFF) << 8) | (input.get() & 0xFF)) + 5;
+ }
+ }
+
+ /**
+ * Returns the required number of bytes in the {@code source} byte array
+ * necessary to explore SSL/TLS connection.
+ * <P>
+ * This method tries to parse as few bytes as possible from
+ * {@code source} byte array to get the length of an
+ * SSL/TLS record.
+ *
+ * @param source
+ * a byte array containing inbound or outbound network data for
+ * an SSL/TLS connection.
+ * @param offset
+ * the start offset in array {@code source} at which the
+ * network data is read from.
+ * @param length
+ * the maximum number of bytes to read.
+ *
+ * @throws BufferUnderflowException if less than {@code RECORD_HEADER_SIZE}
+ * bytes remaining in {@code source}
+ * @return the required size in byte to explore an SSL/TLS connection
+ */
+ public static int getRequiredSize(byte[] source,
+ int offset, int length) throws IOException {
+
+ ByteBuffer byteBuffer =
+ ByteBuffer.wrap(source, offset, length).asReadOnlyBuffer();
+ return getRequiredSize(byteBuffer);
+ }
+
+ /**
+ * Launch and explore the security capabilities from byte buffer.
+ * <P>
+ * This method tries to parse as few records as possible from
+ * {@code source} byte buffer to get the {@link SSLCapabilities}
+ * of an SSL/TLS connection.
+ * <P>
+ * Please NOTE that this method must be called before any handshaking
+ * occurs. The behavior of this method is not defined in this release
+ * if the handshake has begun, or has completed.
+ * <P>
+ * This method accesses the {@code source} parameter in read-only
+ * mode, and does not update the buffer's properties such as capacity,
+ * limit, position, and mark values.
+ *
+ * @param source
+ * a {@link ByteBuffer} containing
+ * inbound or outbound network data for an SSL/TLS connection.
+ *
+ * @throws IOException on network data error
+ * @throws BufferUnderflowException if not enough source bytes available
+ * to make a complete exploration.
+ *
+ * @return the explored {@link SSLCapabilities} of the SSL/TLS
+ * connection
+ */
+ public static SSLCapabilities explore(ByteBuffer source)
+ throws IOException {
+
+ ByteBuffer input = source.duplicate();
+
+ // Do we have a complete header?
+ if (input.remaining() < RECORD_HEADER_SIZE) {
+ throw new BufferUnderflowException();
+ }
+
+ // Is it a handshake message?
+ byte firstByte = input.get();
+ byte secondByte = input.get();
+ byte thirdByte = input.get();
+ if ((firstByte & 0x80) != 0 && thirdByte == 0x01) {
+ // looks like a V2ClientHello
+ return exploreV2HelloRecord(input,
+ firstByte, secondByte, thirdByte);
+ } else if (firstByte == 22) { // 22: handshake record
+ return exploreTLSRecord(input,
+ firstByte, secondByte, thirdByte);
+ } else {
+ throw new SSLException("Not handshake record");
+ }
+ }
+
+ /**
+ * Launch and explore the security capabilities from byte array.
+ * <P>
+ * Please NOTE that this method must be called before any handshaking
+ * occurs. The behavior of this method is not defined in this release
+ * if the handshake has begun, or has completed. Once handshake has
+ * begun, or has completed, the security capabilities can not and
+ * should not be launched with this method.
+ *
+ * @param source
+ * a byte array containing inbound or outbound network data for
+ * an SSL/TLS connection.
+ * @param offset
+ * the start offset in array {@code source} at which the
+ * network data is read from.
+ * @param length
+ * the maximum number of bytes to read.
+ *
+ * @throws IOException on network data error
+ * @throws BufferUnderflowException if not enough source bytes available
+ * to make a complete exploration.
+ * @return the explored {@link SSLCapabilities} of the SSL/TLS
+ * connection
+ *
+ * @see #explore(ByteBuffer)
+ */
+ public static SSLCapabilities explore(byte[] source,
+ int offset, int length) throws IOException {
+ ByteBuffer byteBuffer =
+ ByteBuffer.wrap(source, offset, length).asReadOnlyBuffer();
+ return explore(byteBuffer);
+ }
+
+ /*
+ * uint8 V2CipherSpec[3];
+ * struct {
+ * uint16 msg_length; // The highest bit MUST be 1;
+ * // the remaining bits contain the length
+ * // of the following data in bytes.
+ * uint8 msg_type; // MUST be 1
+ * Version version;
+ * uint16 cipher_spec_length; // It cannot be zero and MUST be a
+ * // multiple of the V2CipherSpec length.
+ * uint16 session_id_length; // This field MUST be empty.
+ * uint16 challenge_length; // SHOULD use a 32-byte challenge
+ * V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];
+ * opaque session_id[V2ClientHello.session_id_length];
+ * opaque challenge[V2ClientHello.challenge_length;
+ * } V2ClientHello;
+ */
+ private static SSLCapabilities exploreV2HelloRecord(
+ ByteBuffer input, byte firstByte, byte secondByte,
+ byte thirdByte) throws IOException {
+
+ // We only need the header. We have already had enough source bytes.
+ // int recordLength = (firstByte & 0x7F) << 8) | (secondByte & 0xFF);
+ try {
+ // Is it a V2ClientHello?
+ if (thirdByte != 0x01) {
+ throw new SSLException(
+ "Unsupported or Unrecognized SSL record");
+ }
+
+ // What's the hello version?
+ byte helloVersionMajor = input.get();
+ byte helloVersionMinor = input.get();
+
+ // 0x00: major version of SSLv20
+ // 0x02: minor version of SSLv20
+ //
+ // SNIServerName is an extension, SSLv20 doesn't support extension.
+ return new SSLCapabilitiesImpl((byte) 0x00, (byte) 0x02,
+ helloVersionMajor, helloVersionMinor,
+ Collections.<SNIServerName>emptyList());
+ } catch (BufferUnderflowException bufe) {
+ throw new SSLProtocolException(
+ "Invalid handshake record");
+ }
+ }
+
+ /*
+ * struct {
+ * uint8 major;
+ * uint8 minor;
+ * } ProtocolVersion;
+ *
+ * enum {
+ * change_cipher_spec(20), alert(21), handshake(22),
+ * application_data(23), (255)
+ * } ContentType;
+ *
+ * struct {
+ * ContentType type;
+ * ProtocolVersion version;
+ * uint16 length;
+ * opaque fragment[TLSPlaintext.length];
+ * } TLSPlaintext;
+ */
+ private static SSLCapabilities exploreTLSRecord(
+ ByteBuffer input, byte firstByte, byte secondByte,
+ byte thirdByte) throws IOException {
+
+ // Is it a handshake message?
+ if (firstByte != 22) { // 22: handshake record
+ throw new SSLException("Not handshake record");
+ }
+
+ // We need the record version to construct SSLCapabilities.
+ byte recordMajorVersion = secondByte;
+ byte recordMinorVersion = thirdByte;
+
+ // Is there enough data for a full record?
+ int recordLength = getInt16(input);
+ if (recordLength > input.remaining()) {
+ throw new BufferUnderflowException();
+ }
+
+ // We have already had enough source bytes.
+ try {
+ return exploreHandshake(input,
+ recordMajorVersion, recordMinorVersion, recordLength);
+ } catch (BufferUnderflowException bufe) {
+ throw new SSLProtocolException(
+ "Invalid handshake record");
+ }
+ }
+
+ /*
+ * enum {
+ * hello_request(0), client_hello(1), server_hello(2),
+ * certificate(11), server_key_exchange (12),
+ * certificate_request(13), server_hello_done(14),
+ * certificate_verify(15), client_key_exchange(16),
+ * finished(20)
+ * (255)
+ * } HandshakeType;
+ *
+ * struct {
+ * HandshakeType msg_type;
+ * uint24 length;
+ * select (HandshakeType) {
+ * case hello_request: HelloRequest;
+ * case client_hello: ClientHello;
+ * case server_hello: ServerHello;
+ * case certificate: Certificate;
+ * case server_key_exchange: ServerKeyExchange;
+ * case certificate_request: CertificateRequest;
+ * case server_hello_done: ServerHelloDone;
+ * case certificate_verify: CertificateVerify;
+ * case client_key_exchange: ClientKeyExchange;
+ * case finished: Finished;
+ * } body;
+ * } Handshake;
+ */
+ private static SSLCapabilities exploreHandshake(
+ ByteBuffer input, byte recordMajorVersion,
+ byte recordMinorVersion, int recordLength) throws IOException {
+
+ // What is the handshake type?
+ byte handshakeType = input.get();
+ if (handshakeType != 0x01) { // 0x01: client_hello message
+ throw new IllegalStateException("Not initial handshaking");
+ }
+
+ // What is the handshake body length?
+ int handshakeLength = getInt24(input);
+
+ // Theoretically, a single handshake message might span multiple
+ // records, but in practice this does not occur.
+ if (handshakeLength > (recordLength - 4)) { // 4: handshake header size
+ throw new SSLException("Handshake message spans multiple records");
+ }
+
+ input = input.duplicate();
+ input.limit(handshakeLength + input.position());
+ return exploreClientHello(input,
+ recordMajorVersion, recordMinorVersion);
+ }
+
+ /*
+ * struct {
+ * uint32 gmt_unix_time;
+ * opaque random_bytes[28];
+ * } Random;
+ *
+ * opaque SessionID<0..32>;
+ *
+ * uint8 CipherSuite[2];
+ *
+ * enum { null(0), (255) } CompressionMethod;
+ *
+ * struct {
+ * ProtocolVersion client_version;
+ * Random random;
+ * SessionID session_id;
+ * CipherSuite cipher_suites<2..2^16-2>;
+ * CompressionMethod compression_methods<1..2^8-1>;
+ * select (extensions_present) {
+ * case false:
+ * struct {};
+ * case true:
+ * Extension extensions<0..2^16-1>;
+ * };
+ * } ClientHello;
+ */
+ private static SSLCapabilities exploreClientHello(
+ ByteBuffer input,
+ byte recordMajorVersion,
+ byte recordMinorVersion) throws IOException {
+
+ List<SNIServerName> snList = Collections.<SNIServerName>emptyList();
+
+ // client version
+ byte helloMajorVersion = input.get();
+ byte helloMinorVersion = input.get();
+
+ // ignore random
+ int position = input.position();
+ input.position(position + 32); // 32: the length of Random
+
+ // ignore session id
+ ignoreByteVector8(input);
+
+ // ignore cipher_suites
+ ignoreByteVector16(input);
+
+ // ignore compression methods
+ ignoreByteVector8(input);
+
+ if (input.remaining() > 0) {
+ snList = exploreExtensions(input);
+ }
+
+ return new SSLCapabilitiesImpl(
+ recordMajorVersion, recordMinorVersion,
+ helloMajorVersion, helloMinorVersion, snList);
+ }
+
+ /*
+ * struct {
+ * ExtensionType extension_type;
+ * opaque extension_data<0..2^16-1>;
+ * } Extension;
+ *
+ * enum {
+ * server_name(0), max_fragment_length(1),
+ * client_certificate_url(2), trusted_ca_keys(3),
+ * truncated_hmac(4), status_request(5), (65535)
+ * } ExtensionType;
+ */
+ private static List<SNIServerName> exploreExtensions(ByteBuffer input)
+ throws IOException {
+
+ int length = getInt16(input); // length of extensions
+ while (length > 0) {
+ int extType = getInt16(input); // extenson type
+ int extLen = getInt16(input); // length of extension data
+
+ if (extType == 0x00) { // 0x00: type of server name indication
+ return exploreSNIExt(input, extLen);
+ } else { // ignore other extensions
+ ignoreByteVector(input, extLen);
+ }
+
+ length -= extLen + 4;
+ }
+
+ return Collections.<SNIServerName>emptyList();
+ }
+
+ /*
+ * struct {
+ * NameType name_type;
+ * select (name_type) {
+ * case host_name: HostName;
+ * } name;
+ * } ServerName;
+ *
+ * enum {
+ * host_name(0), (255)
+ * } NameType;
+ *
+ * opaque HostName<1..2^16-1>;
+ *
+ * struct {
+ * ServerName server_name_list<1..2^16-1>
+ * } ServerNameList;
+ */
+ private static List<SNIServerName> exploreSNIExt(ByteBuffer input,
+ int extLen) throws IOException {
+
+ Map<Integer, SNIServerName> sniMap = new LinkedHashMap<>();
+
+ int remains = extLen;
+ if (extLen >= 2) { // "server_name" extension in ClientHello
+ int listLen = getInt16(input); // length of server_name_list
+ if (listLen == 0 || listLen + 2 != extLen) {
+ throw new SSLProtocolException(
+ "Invalid server name indication extension");
+ }
+
+ remains -= 2; // 0x02: the length field of server_name_list
+ while (remains > 0) {
+ int code = getInt8(input); // name_type
+ int snLen = getInt16(input); // length field of server name
+ if (snLen > remains) {
+ throw new SSLProtocolException(
+ "Not enough data to fill declared vector size");
+ }
+ byte[] encoded = new byte[snLen];
+ input.get(encoded);
+
+ SNIServerName serverName;
+ switch (code) {
+ case StandardConstants.SNI_HOST_NAME:
+ if (encoded.length == 0) {
+ throw new SSLProtocolException(
+ "Empty HostName in server name indication");
+ }
+ serverName = new SNIHostName(encoded);
+ break;
+ default:
+ serverName = new UnknownServerName(code, encoded);
+ }
+ // check for duplicated server name type
+ if (sniMap.put(serverName.getType(), serverName) != null) {
+ throw new SSLProtocolException("Duplicated server name of type " + serverName.getType());
+ }
+
+ remains -= encoded.length + 3; // NameType: 1 byte
+ // HostName length: 2 bytes
+ }
+ } else if (extLen == 0) { // "server_name" extension in ServerHello
+ throw new SSLProtocolException(
+ "Not server name indication extension in client");
+ }
+
+ if (remains != 0) {
+ throw new SSLProtocolException(
+ "Invalid server name indication extension");
+ }
+
+ return Collections.<SNIServerName>unmodifiableList(
+ new ArrayList<>(sniMap.values()));
+ }
+
+ private static int getInt8(ByteBuffer input) {
+ return input.get();
+ }
+
+ private static int getInt16(ByteBuffer input) {
+ return ((input.get() & 0xFF) << 8) | (input.get() & 0xFF);
+ }
+
+ private static int getInt24(ByteBuffer input) {
+ return ((input.get() & 0xFF) << 16) | ((input.get() & 0xFF) << 8) | (input.get() & 0xFF);
+ }
+
+ private static void ignoreByteVector8(ByteBuffer input) {
+ ignoreByteVector(input, getInt8(input));
+ }
+
+ private static void ignoreByteVector16(ByteBuffer input) {
+ ignoreByteVector(input, getInt16(input));
+ }
+
+ private static void ignoreByteVector24(ByteBuffer input) {
+ ignoreByteVector(input, getInt24(input));
+ }
+
+ private static void ignoreByteVector(ByteBuffer input, int length) {
+ if (length != 0) {
+ int position = input.position();
+ input.position(position + length);
+ }
+ }
+
+ private static class UnknownServerName extends SNIServerName {
+ UnknownServerName(int code, byte[] encoded) {
+ super(code, encoded);
+ }
+ }
+
+ private static final class SSLCapabilitiesImpl extends SSLCapabilities {
+ private static final Map<Integer, String> versionMap = new HashMap<>(5);
+
+ private final String recordVersion;
+ private final String helloVersion;
+ List<SNIServerName> sniNames;
+
+ static {
+ versionMap.put(0x0002, "SSLv2Hello");
+ versionMap.put(0x0300, "SSLv3");
+ versionMap.put(0x0301, "TLSv1");
+ versionMap.put(0x0302, "TLSv1.1");
+ versionMap.put(0x0303, "TLSv1.2");
+ }
+
+ SSLCapabilitiesImpl(byte recordMajorVersion, byte recordMinorVersion,
+ byte helloMajorVersion, byte helloMinorVersion,
+ List<SNIServerName> sniNames) {
+
+ int version = (recordMajorVersion << 8) | recordMinorVersion;
+ this.recordVersion = versionMap.get(version) != null
+ ? versionMap.get(version)
+ : unknownVersion(recordMajorVersion, recordMinorVersion);
+
+ version = (helloMajorVersion << 8) | helloMinorVersion;
+ this.helloVersion = versionMap.get(version) != null
+ ? versionMap.get(version)
+ : unknownVersion(helloMajorVersion, helloMinorVersion);
+
+ this.sniNames = sniNames;
+ }
+
+ @Override
+ public String getRecordVersion() {
+ return recordVersion;
+ }
+
+ @Override
+ public String getHelloVersion() {
+ return helloVersion;
+ }
+
+ @Override
+ public List<SNIServerName> getServerNames() {
+ if (!sniNames.isEmpty()) {
+ return Collections.<SNIServerName>unmodifiableList(sniNames);
+ }
+
+ return sniNames;
+ }
+
+ private static String unknownVersion(byte major, byte minor) {
+ return "Unknown-" + ((int) major) + "." + ((int) minor);
+ }
+ }
+}
+
diff --git a/tests/e2e-tls/src/test/resources/hosts b/tests/e2e-tls/src/test/resources/hosts
new file mode 100644
index 0000000..438ebb6
--- /dev/null
+++ b/tests/e2e-tls/src/test/resources/hosts
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+#
+# This program and the accompanying materials are made available under the
+# terms of the Eclipse Public License v. 2.0, which is available at
+# http://www.eclipse.org/legal/epl-2.0.
+#
+# This Source Code may also be made available under the following Secondary
+# Licenses when the conditions for such availability set forth in the
+# Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+# version 2 with the GNU Classpath Exception, which is available at
+# https://www.gnu.org/software/classpath/license.html.
+#
+# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+127.0.0.1 www.host0.com
+127.0.0.1 www.host1.com
+127.0.0.1 www.host2.com
+127.0.0.1 www.host3.com
\ No newline at end of file
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MessageBodyWriterTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MessageBodyWriterTest.java
index 661cb46..d3d7fa9 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MessageBodyWriterTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/MessageBodyWriterTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,6 +21,7 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
+import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.POST;
@@ -32,7 +33,6 @@
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Configuration;
-import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
@@ -75,9 +75,13 @@
@Provider
@Produces("text/plain")
public static class OverridingStringProvider implements MessageBodyWriter<String> {
+ private final Configuration config;
- @Context
- private Configuration config;
+ @Inject
+ public OverridingStringProvider(Configuration config) {
+ this.config = config;
+ }
+
@Override
public boolean isWriteable(
@@ -120,10 +124,13 @@
@Provider
@Produces("text/html")
public static class HtmlStringProvider implements MessageBodyWriter<String> {
-
- @Context
private Configuration config;
+ @Inject
+ public HtmlStringProvider(Configuration config) {
+ this.config = config;
+ }
+
@Override
public boolean isWriteable(
final Class<?> type,
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/LoggingFeatureTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/LoggingFeatureTest.java
index 9958cd9..cd54930 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/LoggingFeatureTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/common/LoggingFeatureTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -19,6 +19,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
@@ -707,29 +708,36 @@
// --- client request log entry
// client added header before request has sent (and logged)
- assertThat(getLoggedRecords().get(0).getMessage(),
+ Iterator<LogRecord> it = getLoggedRecords().iterator();
+ LogRecord logRecord = it.next();
+ while (logRecord.getLevel() == Level.WARNING) { // Skip any warning at the beginning
+ logRecord = it.next();
+ }
+ assertThat(logRecord.getMessage(),
containsString("1 > custom_header: client/request\n"));
// --- container request log entry
// container receives header from client request
- assertThat(getLoggedRecords().get(1).getMessage(),
+ logRecord = it.next();
+ assertThat(logRecord.getMessage(),
containsString("1 > custom_header: client/request\n"));
// container has added its own header after logging filter logged message
- assertThat(getLoggedRecords().get(1).getMessage(),
+ assertThat(logRecord.getMessage(),
not(containsString("1 > custom_header: container/request\n")));
// --- container response log entry
// container added header to the response and it was logged
- assertThat(getLoggedRecords().get(2).getMessage(),
+ assertThat(it.next().getMessage(),
containsString("1 < custom_header: container/response\n"));
// --- client response log entry
// client received header
- assertThat(getLoggedRecords().get(3).getMessage(),
+ logRecord = it.next();
+ assertThat(logRecord.getMessage(),
containsString("1 < custom_header: container/response\n"));
- assertThat(getLoggedRecords().get(3).getMessage(),
+ assertThat(logRecord.getMessage(),
not(containsString("1 < custom_header: client/response\n")));
}
diff --git a/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java b/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java
index cdca445..c6ecc29 100644
--- a/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java
+++ b/tests/integration/externalproperties/src/test/java/org/glassfish/jersey/tests/externalproperties/HttpProxyTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,6 +22,7 @@
import org.glassfish.jersey.ExternalProperties;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.TestProperties;
import org.glassfish.jersey.test.jetty.JettyTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
@@ -37,9 +38,12 @@
import jakarta.ws.rs.core.Response;
public class HttpProxyTest extends JerseyTest {
+ public HttpProxyTest() {
+ set(TestProperties.CONTAINER_PORT, 0);
+ }
private static final String PROXY_HOST = "localhost";
- private static final String PROXY_PORT = "9997";
+ private static final String PROXY_PORT = "0";
private static boolean proxyHit = false;
@Path("resource")
@@ -60,7 +64,6 @@
@BeforeEach
public void startFakeProxy() {
System.setProperty(ExternalProperties.HTTP_PROXY_HOST, PROXY_HOST);
- System.setProperty(ExternalProperties.HTTP_PROXY_PORT, PROXY_PORT);
Server server = new Server(Integer.parseInt(PROXY_PORT));
server.setHandler(new ProxyHandler(false));
try {
@@ -68,6 +71,7 @@
} catch (Exception e) {
}
+ System.setProperty(ExternalProperties.HTTP_PROXY_PORT, String.valueOf(server.getURI().getPort()));
}
@Override
diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/ApplicationResource.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/ApplicationResource.java
index 7c927f2..1c7d2c0 100644
--- a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/ApplicationResource.java
+++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/ApplicationResource.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,6 +21,7 @@
import jakarta.json.JsonValue;
import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.POST;
@@ -76,4 +77,10 @@
@Path("content1/{content1}/content0/{content0: [0-9]{4}}")
@Produces(MediaType.TEXT_PLAIN)
String regex0(@PathParam("content1") String context0, @PathParam("content0") String context1);
+
+ @POST
+ @Path("formParam")
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ @Produces(MediaType.TEXT_PLAIN)
+ String formParam(@FormParam("param") String param);
}
diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/ApplicationResourceImpl.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/ApplicationResourceImpl.java
index dd10f72..56dc5bd 100644
--- a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/ApplicationResourceImpl.java
+++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/ApplicationResourceImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -71,4 +71,9 @@
public String regex0(String context0, String context1) {
return context0 + "_" + context1;
}
+
+ @Override
+ public String formParam(String param) {
+ return param;
+ }
}
diff --git a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/RestClientModelTest.java b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/RestClientModelTest.java
index 24c0308..469b215 100644
--- a/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/RestClientModelTest.java
+++ b/tests/integration/microprofile/rest-client/src/test/java/org/glassfish/jersey/test/microprofile/restclient/RestClientModelTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -56,4 +56,12 @@
assertEquals("Hi", app.sayHi());
}
+
+ @Test
+ public void testFormParam() throws URISyntaxException {
+ String response = RestClientBuilder.newBuilder()
+ .baseUri(new URI("http://localhost:9998"))
+ .build(ApplicationResource.class).formParam(null);
+ assertEquals("", response);
+ }
}
diff --git a/tests/pom.xml b/tests/pom.xml
index 946aa00..025ebb1 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2011, 2022 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2011, 2023 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -44,6 +44,7 @@
<module>e2e-inject</module>
<module>e2e-server</module>
<module>e2e-testng</module>
+ <module>e2e-tls</module>
<module>integration</module>
<module>jmockit</module>
<module>mem-leaks</module>
@@ -105,5 +106,14 @@
</plugins>
</build>
</profile>
+ <profile>
+ <id>JDK11+</id>
+ <activation>
+ <jdk>[11,)</jdk>
+ </activation>
+ <modules>
+ <module>release-test</module>
+ </modules>
+ </profile>
</profiles>
</project>
diff --git a/tests/release-test/pom.xml b/tests/release-test/pom.xml
index 3d58845..e5dc66c 100644
--- a/tests/release-test/pom.xml
+++ b/tests/release-test/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,22 +21,20 @@
<modelVersion>4.0.0</modelVersion>
<parent>
- <groupId>org.eclipse.ee4j</groupId>
+ <groupId>org.glassfish.jersey</groupId>
<artifactId>project</artifactId>
- <version>1.0.8</version>
- <relativePath>../../../pom.xml</relativePath>
+ <version>3.0.99-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
</parent>
<groupId>org.glassfish.jersey.tests</groupId>
<artifactId>release-test</artifactId>
- <version>3.0.99-SNAPSHOT</version>
<packaging>jar</packaging>
<name>jersey-release-test</name>
<description>Jersey post-release validation tests</description>
<properties>
- <jersey.version>${jersey.version}</jersey.version> <!-- Must pass using -Djersey.version= -->
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<maven.version>3.8.6</maven.version>
@@ -54,8 +52,7 @@
<reuseForks>false</reuseForks>
<enableAssertions>false</enableAssertions>
<includes>
- <include>**/DownloadBomPomDependencies.java</include>
- <include>**/*Test.class</include>
+ <include>**/NoticeFilesTest.class</include>
</includes>
</configuration>
</plugin>
@@ -117,6 +114,60 @@
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-http</artifactId>
<version>${maven.resolver.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-common</artifactId>
</dependency>
</dependencies>
+
+ <profiles>
+ <profile>
+ <id>ReleaseTests</id>
+ <activation>
+ <property>
+ <name>jersey.version</name>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>3.0.0-M7</version>
+ <configuration>
+ <forkCount>1</forkCount>
+ <reuseForks>false</reuseForks>
+ <enableAssertions>false</enableAssertions>
+ <includes>
+ <include>**/DownloadBomPomDependencies.java</include>
+ <include>**/*Test.class</include>
+ </includes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey</groupId>
+ <artifactId>jersey-bom</artifactId>
+ <version>${jersey.version}</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <properties>
+ <jersey.version>${jersey.version}</jersey.version> <!-- Must pass using -Djersey.version= -->
+ </properties>
+ </profile>
+ </profiles>
</project>
diff --git a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.java b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.java
index 43e5327..743d609 100644
--- a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.java
+++ b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.java
@@ -1,13 +1,17 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0,
- * or the Eclipse Distribution License v. 1.0 which is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
*
- * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.test.artifacts;
diff --git a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyPair.java b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyPair.java
index dd31588..3256d48 100644
--- a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyPair.java
+++ b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyPair.java
@@ -1,13 +1,17 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0,
- * or the Eclipse Distribution License v. 1.0 which is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
*
- * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.test.artifacts;
diff --git a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.java b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.java
index 5df3bc1..b1a7ee3 100644
--- a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.java
+++ b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.java
@@ -1,13 +1,17 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0,
- * or the Eclipse Distribution License v. 1.0 which is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
*
- * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.test.artifacts;
diff --git a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.java b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.java
index 2c5b3a2..68d0a14 100644
--- a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.java
+++ b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.java
@@ -1,14 +1,19 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0,
- * or the Eclipse Distribution License v. 1.0 which is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
*
- * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
+
package org.glassfish.jersey.test.artifacts;
import org.apache.maven.model.Dependency;
@@ -103,7 +108,7 @@
.filter(dep -> dep.getType().equals("jar"));
}
- private static Model getModelFromFile(String fileName) throws IOException, XmlPullParserException {
+ static Model getModelFromFile(String fileName) throws IOException, XmlPullParserException {
File pomFile = new File(fileName);
return getModelFromFile(pomFile);
}
diff --git a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/TestResult.java b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/TestResult.java
index 172c596..5c357fc 100644
--- a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/TestResult.java
+++ b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/TestResult.java
@@ -1,14 +1,19 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0,
- * or the Eclipse Distribution License v. 1.0 which is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
*
- * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
+
package org.glassfish.jersey.test.artifacts;
import java.io.IOException;
@@ -53,24 +58,24 @@
}
@Override
- public MessageBuilder append(CharSequence csq) throws IOException {
+ public MessageBuilder append(CharSequence csq) {
builder.append(csq);
return this;
}
- public MessageBuilder append(int i) throws IOException {
+ public MessageBuilder append(int i) {
builder.append(i);
return this;
}
@Override
- public MessageBuilder append(CharSequence csq, int start, int end) throws IOException {
+ public MessageBuilder append(CharSequence csq, int start, int end) {
builder.append(csq, start, end);
return this;
}
@Override
- public MessageBuilder append(char c) throws IOException {
+ public MessageBuilder append(char c) {
builder.append(c);
return this;
}
diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.java
index ef31d4e..01ba01e 100644
--- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.java
+++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.java
@@ -1,14 +1,19 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0,
- * or the Eclipse Distribution License v. 1.0 which is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
*
- * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
+
package org.glassfish.jersey.test.artifacts;
import org.eclipse.aether.DefaultRepositorySystemSession;
diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.java
index 8da0835..0c77d69 100644
--- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.java
+++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.java
@@ -1,13 +1,17 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0,
- * or the Eclipse Distribution License v. 1.0 which is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
*
- * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.test.artifacts;
@@ -28,7 +32,7 @@
private static final String BUNDLE_NAME_ATTRIBUTE = "Bundle-Name";
private static final String BUNDLE_VERSION_ATTRIBUTE = "Bundle-Version";
- private static final String [] EXCLUDED_JARS = {"test", "rx-client", "oauth", "weld2-se", "spring",
+ private static final String[] EXCLUDED_JARS = {"test", "rx-client", "oauth", "weld2-se", "spring",
"servlet-portability", /* obsolete */
"helidon-connector", /* Helidon does not contain OSGi headers */
"grizzly-connector", /* Limited maintenance */
diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java
index deef29a..288932a 100644
--- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java
+++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java
@@ -1,13 +1,17 @@
/*
- * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0,
- * or the Eclipse Distribution License v. 1.0 which is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
*
- * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.jersey.test.artifacts;
diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/NoticeFilesTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/NoticeFilesTest.java
new file mode 100644
index 0000000..6cda528
--- /dev/null
+++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/NoticeFilesTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.test.artifacts;
+
+import org.apache.maven.model.Model;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.junit.Assert;
+import org.junit.Test;
+
+import jakarta.ws.rs.core.MediaType;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+
+public class NoticeFilesTest {
+
+ @Test
+ public void test() throws IOException, XmlPullParserException {
+ Model model = MavenUtil.getModelFromFile("../../pom.xml");
+ List<NoticeDependencyVersionPair> mainExpectedNoticeDeps = mainExpectedDependencies();
+
+ File mainNotice = new File("../../NOTICE.md");
+ List<NoticeDependencyVersionPair> mainNoticeDeps = parseNoticeFileVersions(mainNotice);
+ TestResult testResult = compareDependencies(mainExpectedNoticeDeps, mainNoticeDeps, model, mainNotice.getCanonicalPath());
+
+ // Nothing to check here, yet
+// File commonNotice = new File("../../core-common/src/main/resources/META-INF/NOTICE.markdown");
+// List<NoticeDependencyVersionPair> commonNoticeDeps = parseNoticeFileVersions(mainNotice);
+// testResult.append(compareDependencies(expectedNoticeDeps, commonNoticeDeps, model, commonNotice.getCanonicalPath()));
+
+ File serverNotice = new File("../../core-server/src/main/resources/META-INF/NOTICE.markdown");
+ List<NoticeDependencyVersionPair> serverNoticeDeps = parseNoticeFileVersions(serverNotice);
+ List<NoticeDependencyVersionPair> serverExpectedNoticeDeps = serverExpectedDependencies();
+ testResult.append(
+ compareDependencies(serverExpectedNoticeDeps, serverNoticeDeps, model, serverNotice.getCanonicalPath()));
+
+ File jacksonNotice = new File("../../media/json-jackson/src/main/resources/META-INF/NOTICE.markdown");
+ List<NoticeDependencyVersionPair> jacksonNoticeDeps = parseNoticeFileVersions(jacksonNotice);
+ List<NoticeDependencyVersionPair> jacksonExpectedNoticeDeps = jacksonExpectedDependencies();
+ testResult.append(
+ compareDependencies(jacksonExpectedNoticeDeps, jacksonNoticeDeps, model, jacksonNotice.getCanonicalPath()));
+
+ File bvNotice = new File("../../ext/bean-validation/src/main/resources/META-INF/NOTICE.markdown");
+ List<NoticeDependencyVersionPair> bvNoticeDeps = parseNoticeFileVersions(bvNotice);
+ List<NoticeDependencyVersionPair> bvExpectedNoticeDeps = bvExpectedDependencies();
+ testResult.append(
+ compareDependencies(bvExpectedNoticeDeps, bvNoticeDeps, model, bvNotice.getCanonicalPath()));
+
+ File examplesNotice = new File("../../examples/NOTICE.md");
+ List<NoticeDependencyVersionPair> examplesNoticeDeps = parseNoticeFileVersions(examplesNotice);
+ testResult.append(
+ compareDependencies(mainExpectedNoticeDeps, examplesNoticeDeps, model, examplesNotice.getCanonicalPath()));
+
+ Assert.assertTrue("Some error occurred, see previous messages", testResult.result());
+ }
+
+ private TestResult compareDependencies(List<NoticeDependencyVersionPair> expectedDeps,
+ List<NoticeDependencyVersionPair> actualDeps,
+ Model model, String noticeName) {
+ TestResult testResult = new TestResult();
+ NextExpected:
+ for (NoticeDependencyVersionPair expectedDep : expectedDeps) {
+ for (NoticeDependencyVersionPair actualDep : actualDeps) {
+ if (expectedDep.dependency.equals(actualDep.dependency)) {
+ String expectedVersion = findVersionInModel(expectedDep, model);
+ testResult.ok().append("Expected dependency ").append(expectedDep.dependency).println(" found");
+ if (expectedVersion.equals(actualDep.version)) {
+ testResult.ok().append("Dependency ").append(actualDep.dependency).append(" contains expected version ")
+ .append(expectedVersion).append(" in ").println(noticeName);
+ } else {
+ testResult.exception().append("Dependency ").append(actualDep.dependency).append(" differs version ")
+ .append(expectedVersion).append(" from ").append(noticeName).append(" version ")
+ .println(actualDep.version);
+ }
+ continue NextExpected;
+ }
+ }
+ testResult.exception().append("Expected dependency ").append(expectedDep.dependency).append(" not found in ")
+ .println(noticeName);
+ }
+ return testResult;
+ }
+
+ private static String findVersionInModel(NoticeDependencyVersionPair pair, Model model) {
+ if (pair.version.startsWith("${")) {
+ String version = pair.version.substring(2, pair.version.length() - 1);
+ return model.getProperties().getProperty(version);
+ } else {
+ return pair.version;
+ }
+ }
+
+ private void cat(File path) throws IOException {
+ StringTokenizer tokenizer = tokenizerFromNoticeFile(path);
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ if (token.trim().length() > 1 && !token.trim().startsWith("*")) {
+ System.out.println(token);
+// String filteredToken = removeUnnecessary(token);
+// System.out.println(filteredToken);
+// Pattern versionizer = Pattern.compile("([.*])?([\\d])");
+// System.out.println(versionizer.matcher(filteredToken).replaceFirst("$1:$2"));
+ }
+ }
+ }
+
+ private List<NoticeDependencyVersionPair> parseNoticeFileVersions(File path) throws IOException {
+ List<NoticeDependencyVersionPair> list = new LinkedList<>();
+ StringTokenizer tokenizer = tokenizerFromNoticeFile(path);
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ if (token.trim().length() > 1 && !token.trim().startsWith("*")) {
+ String filteredToken = removeUnnecessary(token);
+ Pattern versionizer = Pattern.compile("([.*])?([\\d])");
+ String[] args = versionizer.matcher(filteredToken).replaceFirst("$1:$2").split(":", 2);
+ NoticeDependencyVersionPair pair = args.length == 2
+ ? new NoticeDependencyVersionPair(args[0], args[1])
+ : new NoticeDependencyVersionPair(args[0], "");
+ list.add(pair);
+ }
+ }
+
+ return list;
+ }
+
+ private StringTokenizer tokenizerFromNoticeFile(File path) throws IOException {
+ StringTokenizer tokenizer = new StringTokenizer(getFile(path), "\n");
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ if (token.trim().startsWith("## Third-party Content")) {
+ break;
+ }
+ }
+ return tokenizer;
+ }
+
+ private String getFile(File path) throws IOException {
+ return ReaderWriter.readFromAsString(new FileInputStream(path), MediaType.TEXT_PLAIN_TYPE);
+ }
+
+ private String removeUnnecessary(String dependency) {
+ String filtered = dependency
+ .replace(" Version ", "").replace(" version ", "")
+ .replace(" API ", "")
+ .replace(" v", "")
+ .replace(", ", "").replace(",", "")
+ .replace(": ", "").replace(": ", "");
+ return filtered;
+ }
+
+ /**
+ * Return pair of Notice file dependency name & pom.xml version property name
+ */
+ private List<NoticeDependencyVersionPair> mainExpectedDependencies() {
+ final List<NoticeDependencyVersionPair> dependencyPairs = new LinkedList<>();
+ dependencyPairs.add(new NoticeDependencyVersionPair("org.objectweb.asm", "${asm.version}"));
+ dependencyPairs.add(new NoticeDependencyVersionPair("org.osgi.core", "${osgi.version}"));
+ dependencyPairs.add(new NoticeDependencyVersionPair("Jackson JAX-RS Providers", "${jackson.version}"));
+ dependencyPairs.add(new NoticeDependencyVersionPair("Javassist", "${javassist.version}"));
+ dependencyPairs.add(new NoticeDependencyVersionPair("Hibernate Validator CDI", "${validation.impl.version}"));
+ dependencyPairs.add(new NoticeDependencyVersionPair("Bean Validation", "${jakarta.validation.api.version}"));
+ return dependencyPairs;
+ }
+
+ private List<NoticeDependencyVersionPair> serverExpectedDependencies() {
+ final List<NoticeDependencyVersionPair> dependencyPairs = new LinkedList<>();
+ dependencyPairs.add(new NoticeDependencyVersionPair("org.objectweb.asm", "${asm.version}"));
+ return dependencyPairs;
+ }
+
+ private List<NoticeDependencyVersionPair> bvExpectedDependencies() {
+ final List<NoticeDependencyVersionPair> dependencyPairs = new LinkedList<>();
+ dependencyPairs.add(new NoticeDependencyVersionPair("Hibernate Validator CDI", "${validation.impl.version}"));
+ return dependencyPairs;
+ }
+
+ private List<NoticeDependencyVersionPair> jacksonExpectedDependencies() {
+ final List<NoticeDependencyVersionPair> dependencyPairs = new LinkedList<>();
+ dependencyPairs.add(new NoticeDependencyVersionPair("Jackson JAX-RS Providers", "${jackson.version}"));
+ return dependencyPairs;
+ }
+
+ private static class NoticeDependencyVersionPair {
+ private final String dependency;
+ private final String version;
+
+ private NoticeDependencyVersionPair(String dependency, String version) {
+ this.dependency = dependency.trim();
+ this.version = version.trim();
+ }
+ }
+}