Merge pull request #5106 from senivam/3x_merged
diff --git a/bom/pom.xml b/bom/pom.xml index e64e12f..889fc20 100644 --- a/bom/pom.xml +++ b/bom/pom.xml
@@ -285,6 +285,11 @@ </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-json-gson</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-binding</artifactId> <version>${project.version}</version> </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 0b08871..fdfbccf 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
@@ -29,6 +29,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicLong; @@ -51,6 +52,7 @@ import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; import org.glassfish.jersey.client.RequestEntityProcessing; +import org.glassfish.jersey.client.innate.ClientProxy; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; import org.glassfish.jersey.internal.util.PropertiesHelper; @@ -279,28 +281,20 @@ clientBuilder.setRetryHandler((HttpRequestRetryHandler) retryHandler); } - final Object proxyUri; - proxyUri = config.getProperty(ClientProperties.PROXY_URI); - if (proxyUri != null) { - final URI u = getProxyUri(proxyUri); - final HttpHost proxy = new HttpHost(u.getHost(), u.getPort(), u.getScheme()); - final String userName; - userName = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_USERNAME, String.class); - if (userName != null) { - final String password; - password = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_PASSWORD, String.class); - - if (password != null) { - final CredentialsProvider credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials( - new AuthScope(u.getHost(), u.getPort()), - new UsernamePasswordCredentials(userName, password) - ); - clientBuilder.setDefaultCredentialsProvider(credsProvider); - } + final Optional<ClientProxy> proxy = ClientProxy.proxyFromConfiguration(config); + proxy.ifPresent(clientProxy -> { + final URI u = clientProxy.uri(); + final HttpHost proxyHost = new HttpHost(u.getHost(), u.getPort(), u.getScheme()); + if (clientProxy.userName() != null && clientProxy.password() != null) { + final CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials( + new AuthScope(u.getHost(), u.getPort()), + new UsernamePasswordCredentials(clientProxy.userName(), clientProxy.password()) + ); + clientBuilder.setDefaultCredentialsProvider(credsProvider); } - clientBuilder.setProxy(proxy); - } + clientBuilder.setProxy(proxyHost); + }); final Boolean preemptiveBasicAuthProperty = (Boolean) config.getProperties() .get(ApacheClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION); @@ -452,16 +446,6 @@ return cookieStore; } - private static URI getProxyUri(final Object proxy) { - if (proxy instanceof URI) { - return (URI) proxy; - } else if (proxy instanceof String) { - return URI.create((String) proxy); - } else { - throw new ProcessingException(LocalizationMessages.WRONG_PROXY_URI_TYPE(ClientProperties.PROXY_URI)); - } - } - @Override public ClientResponse apply(final ClientRequest clientRequest) throws ProcessingException { final HttpUriRequest request = getUriHttpRequest(clientRequest);
diff --git a/connectors/apache-connector/src/main/resources/org/glassfish/jersey/apache/connector/localization.properties b/connectors/apache-connector/src/main/resources/org/glassfish/jersey/apache/connector/localization.properties index f0cc55b..3b06461 100644 --- a/connectors/apache-connector/src/main/resources/org/glassfish/jersey/apache/connector/localization.properties +++ b/connectors/apache-connector/src/main/resources/org/glassfish/jersey/apache/connector/localization.properties
@@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2022 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,7 +19,5 @@ failed.to.stop.client=Failed to stop the client. # {0} - property name, e.g. jersey.config.client.httpclient.connectionManager; {1}, {2} - full class name ignoring.value.of.property=Ignoring value of property "{0}" ("{1}") - not instance of "{2}". -# {0} - property name - jersey.config.client.httpclient.proxyUri -wrong.proxy.uri.type=The proxy URI ("{0}") property MUST be an instance of String or URI. invalid.configurable.component.type=The supplied component "{0}" is not assignable from JerseyClient or JerseyWebTarget. expected.connector.provider.not.used=The supplied component is not configured to use a ApacheConnectorProvider.
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 5cc2e63..9e4e9ac 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
@@ -30,6 +30,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.logging.Level; @@ -93,6 +94,7 @@ import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; import org.glassfish.jersey.client.RequestEntityProcessing; +import org.glassfish.jersey.client.innate.ClientProxy; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; import org.glassfish.jersey.internal.util.PropertiesHelper; @@ -280,28 +282,20 @@ clientBuilder.setRetryStrategy((HttpRequestRetryStrategy) retryHandler); } - final Object proxyUri; - proxyUri = config.getProperty(ClientProperties.PROXY_URI); - if (proxyUri != null) { - final URI u = getProxyUri(proxyUri); - final HttpHost proxy = new HttpHost(u.getScheme(), u.getHost(), u.getPort()); - final String userName; - userName = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_USERNAME, String.class); - if (userName != null) { - final String password; - password = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_PASSWORD, String.class); - - if (password != null) { - final CredentialsStore credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials( - new AuthScope(u.getHost(), u.getPort()), - new UsernamePasswordCredentials(userName, password.toCharArray()) - ); - clientBuilder.setDefaultCredentialsProvider(credsProvider); - } + final Optional<ClientProxy> proxy = ClientProxy.proxyFromConfiguration(config); + proxy.ifPresent(clientProxy -> { + final URI u = clientProxy.uri(); + final HttpHost proxyHost = new HttpHost(u.getScheme(), u.getHost(), u.getPort()); + if (clientProxy.userName() != null && clientProxy.password() != null) { + final CredentialsStore credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials( + new AuthScope(u.getHost(), u.getPort()), + new UsernamePasswordCredentials(clientProxy.userName(), clientProxy.password().toCharArray()) + ); + clientBuilder.setDefaultCredentialsProvider(credsProvider); } - clientBuilder.setProxy(proxy); - } + clientBuilder.setProxy(proxyHost); + }); final Boolean preemptiveBasicAuthProperty = (Boolean) config.getProperties() .get(Apache5ClientProperties.PREEMPTIVE_BASIC_AUTHENTICATION); @@ -456,16 +450,6 @@ return cookieStore; } - private static URI getProxyUri(final Object proxy) { - if (proxy instanceof URI) { - return (URI) proxy; - } else if (proxy instanceof String) { - return URI.create((String) proxy); - } else { - throw new ProcessingException(LocalizationMessages.WRONG_PROXY_URI_TYPE(ClientProperties.PROXY_URI)); - } - } - @Override public ClientResponse apply(final ClientRequest clientRequest) throws ProcessingException { final HttpUriRequest request = getUriHttpRequest(clientRequest);
diff --git a/connectors/apache5-connector/src/main/resources/org/glassfish/jersey/apache5/connector/localization.properties b/connectors/apache5-connector/src/main/resources/org/glassfish/jersey/apache5/connector/localization.properties index 16dbc30..1f6e4a6 100644 --- a/connectors/apache5-connector/src/main/resources/org/glassfish/jersey/apache5/connector/localization.properties +++ b/connectors/apache5-connector/src/main/resources/org/glassfish/jersey/apache5/connector/localization.properties
@@ -19,7 +19,5 @@ failed.to.stop.client=Failed to stop the client. # {0} - property name, e.g. jersey.config.client.httpclient.connectionManager; {1}, {2} - full class name ignoring.value.of.property=Ignoring value of property "{0}" ("{1}") - not instance of "{2}". -# {0} - property name - jersey.config.client.httpclient.proxyUri -wrong.proxy.uri.type=The proxy URI ("{0}") property MUST be an instance of String or URI. invalid.configurable.component.type=The supplied component "{0}" is not assignable from JerseyClient or JerseyWebTarget. expected.connector.provider.not.used=The supplied component is not configured to use a ApacheConnectorProvider.
diff --git a/connectors/grizzly-connector/src/main/java/org/glassfish/jersey/grizzly/connector/GrizzlyConnector.java b/connectors/grizzly-connector/src/main/java/org/glassfish/jersey/grizzly/connector/GrizzlyConnector.java index c1ff43d..f39e216 100644 --- a/connectors/grizzly-connector/src/main/java/org/glassfish/jersey/grizzly/connector/GrizzlyConnector.java +++ b/connectors/grizzly-connector/src/main/java/org/glassfish/jersey/grizzly/connector/GrizzlyConnector.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2022 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.net.URI; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Properties; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -39,6 +40,7 @@ import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; import org.glassfish.jersey.client.RequestEntityProcessing; +import org.glassfish.jersey.client.innate.ClientProxy; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; import org.glassfish.jersey.internal.Version; @@ -83,7 +85,7 @@ GrizzlyConnector(final Client client, final Configuration config, final GrizzlyConnectorProvider.AsyncClientCustomizer asyncClientCustomizer) { - AsyncHttpClientConfig.Builder builder = new AsyncHttpClientConfig.Builder(); + final AsyncHttpClientConfig.Builder builder = new AsyncHttpClientConfig.Builder(); ExecutorService executorService; if (config != null) { @@ -95,7 +97,7 @@ executorService = Executors.newCachedThreadPool(); } - builder = builder.setExecutorService(executorService); + builder.setExecutorService(executorService); builder.setConnectTimeout(ClientProperties.getValue(config.getProperties(), ClientProperties.CONNECT_TIMEOUT, 10000)); @@ -103,29 +105,23 @@ builder.setRequestTimeout(ClientProperties.getValue(config.getProperties(), ClientProperties.READ_TIMEOUT, 10000)); - Object proxyUri; - proxyUri = config.getProperty(ClientProperties.PROXY_URI); - if (proxyUri != null) { - final URI u = getProxyUri(proxyUri); + final Optional<ClientProxy> proxy = ClientProxy.proxyFromConfiguration(config); + proxy.ifPresent(clientProxy -> { + final URI u = clientProxy.uri(); final Properties proxyProperties = new Properties(); proxyProperties.setProperty(ProxyUtils.PROXY_PROTOCOL, u.getScheme()); proxyProperties.setProperty(ProxyUtils.PROXY_HOST, u.getHost()); proxyProperties.setProperty(ProxyUtils.PROXY_PORT, String.valueOf(u.getPort())); - final String userName = ClientProperties.getValue( - config.getProperties(), ClientProperties.PROXY_USERNAME, String.class); - if (userName != null) { - proxyProperties.setProperty(ProxyUtils.PROXY_USER, userName); - - final String password = ClientProperties.getValue( - config.getProperties(), ClientProperties.PROXY_PASSWORD, String.class); - if (password != null) { - proxyProperties.setProperty(ProxyUtils.PROXY_PASSWORD, password); + if (clientProxy.userName() != null) { + proxyProperties.setProperty(ProxyUtils.PROXY_USER, clientProxy.userName()); + if (clientProxy.password() != null) { + proxyProperties.setProperty(ProxyUtils.PROXY_PASSWORD, clientProxy.password()); } } ProxyServerSelector proxyServerSelector = ProxyUtils.createProxyServerSelector(proxyProperties); builder.setProxyServerSelector(proxyServerSelector); - } + }); } else { executorService = Executors.newCachedThreadPool(); builder.setExecutorService(executorService); @@ -140,7 +136,7 @@ } if (asyncClientCustomizer != null) { - builder = asyncClientCustomizer.customize(client, config, builder); + asyncClientCustomizer.customize(client, config, builder); } AsyncHttpClientConfig asyncClientConfig = builder.build(); @@ -148,17 +144,6 @@ this.grizzlyClient = new AsyncHttpClient(new GrizzlyAsyncHttpProvider(asyncClientConfig), asyncClientConfig); } - @SuppressWarnings("ChainOfInstanceofChecks") - private static URI getProxyUri(final Object proxy) { - if (proxy instanceof URI) { - return (URI) proxy; - } else if (proxy instanceof String) { - return URI.create((String) proxy); - } else { - throw new ProcessingException(LocalizationMessages.WRONG_PROXY_URI_TYPE(ClientProperties.PROXY_URI)); - } - } - /** * Get the underlying Grizzly {@link com.ning.http.client.AsyncHttpClient} instance. *
diff --git a/connectors/grizzly-connector/src/main/resources/org/glassfish/jersey/grizzly/connector/localization.properties b/connectors/grizzly-connector/src/main/resources/org/glassfish/jersey/grizzly/connector/localization.properties index 7fb050e..2d577c6 100644 --- a/connectors/grizzly-connector/src/main/resources/org/glassfish/jersey/grizzly/connector/localization.properties +++ b/connectors/grizzly-connector/src/main/resources/org/glassfish/jersey/grizzly/connector/localization.properties
@@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2022 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,5 +16,4 @@ error.buffering.entity=Error buffering the entity. expected.connector.provider.not.used=The supplied component is not configured to use a GrizzlyConnectorProvider. -invalid.configurable.component.type=The supplied component "{0}" is not assignable from JerseyClient or JerseyWebTarget. -wrong.proxy.uri.type=The proxy URI ("{0}") property MUST be an instance of String or URI. +invalid.configurable.component.type=The supplied component "{0}" is not assignable from JerseyClient or JerseyWebTarget. \ No newline at end of file
diff --git a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java b/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java index 655a203..504fb0e 100644 --- a/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java +++ b/connectors/jetty-connector/src/main/java11/org/glassfish/jersey/jetty/connector/JettyConnector.java
@@ -57,6 +57,7 @@ import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; +import org.glassfish.jersey.client.innate.ClientProxy; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; import org.glassfish.jersey.internal.util.collection.ByteBufferInputStream; @@ -193,19 +194,17 @@ auth.addAuthentication((BasicAuthentication) basicAuthProvider); } - final Object proxyUri = config.getProperties().get(ClientProperties.PROXY_URI); - if (proxyUri != null) { - final URI u = getProxyUri(proxyUri); + final Optional<ClientProxy> proxy = ClientProxy.proxyFromConfiguration(config); + proxy.ifPresent(clientProxy -> { final ProxyConfiguration proxyConfig = client.getProxyConfiguration(); + final URI u = clientProxy.uri(); proxyConfig.getProxies().add(new HttpProxy(u.getHost(), u.getPort())); - final Object proxyUsername = config.getProperties().get(ClientProperties.PROXY_USERNAME); - if (proxyUsername != null) { - final Object proxyPassword = config.getProperties().get(ClientProperties.PROXY_PASSWORD); + if (clientProxy.userName() != null) { auth.addAuthentication(new BasicAuthentication(u, "<<ANY_REALM>>", - String.valueOf(proxyUsername), String.valueOf(proxyPassword))); + clientProxy.userName(), clientProxy.password())); } - } + }); if (disableCookies) { client.setCookieStore(new HttpCookieStore.Empty()); @@ -229,17 +228,6 @@ this.cookieStore = client.getCookieStore(); } - @SuppressWarnings("ChainOfInstanceofChecks") - private static URI getProxyUri(final Object proxy) { - if (proxy instanceof URI) { - return (URI) proxy; - } else if (proxy instanceof String) { - return URI.create((String) proxy); - } else { - throw new ProcessingException(LocalizationMessages.WRONG_PROXY_URI_TYPE(ClientProperties.PROXY_URI)); - } - } - /** * Get the {@link HttpClient}. *
diff --git a/connectors/jetty-connector/src/main/resources/org/glassfish/jersey/jetty/connector/localization.properties b/connectors/jetty-connector/src/main/resources/org/glassfish/jersey/jetty/connector/localization.properties index af11518..128d40b 100644 --- a/connectors/jetty-connector/src/main/resources/org/glassfish/jersey/jetty/connector/localization.properties +++ b/connectors/jetty-connector/src/main/resources/org/glassfish/jersey/jetty/connector/localization.properties
@@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2022 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,8 +16,6 @@ # {0} - HTTP method, e.g. GET, DELETE method.not.supported=Method {0} not supported. -# {0} - property name - jersey.config.client.proxyUri -wrong.proxy.uri.type=The proxy URI ("{0}") property MUST be an instance of String or URI. invalid.configurable.component.type=The supplied component "{0}" is not assignable from JerseyClient or JerseyWebTarget. expected.connector.provider.not.used=The supplied component is not configured to use a JettyConnectorProvider. not.supported=Jetty connector is not supported on JDK version less than 11.
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 77d0d27..5d52e76 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
@@ -19,8 +19,6 @@ import java.io.IOException; import java.io.OutputStream; import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.ProxySelector; import java.net.SocketAddress; import java.net.URI; import java.util.ArrayList; @@ -29,6 +27,7 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -48,7 +47,6 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.ChannelPipeline; @@ -69,7 +67,6 @@ import io.netty.handler.codec.http.HttpUtil; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.proxy.HttpProxyHandler; -import io.netty.handler.proxy.ProxyConnectionEvent; import io.netty.handler.proxy.ProxyHandler; import io.netty.handler.ssl.ApplicationProtocolConfig; import io.netty.handler.ssl.ClientAuth; @@ -80,10 +77,12 @@ import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import io.netty.handler.timeout.IdleStateHandler; +import io.netty.resolver.NoopAddressResolverGroup; import io.netty.util.concurrent.GenericFutureListener; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; +import org.glassfish.jersey.client.innate.ClientProxy; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; import org.glassfish.jersey.message.internal.OutboundMessageContext; @@ -235,6 +234,18 @@ if (chan == null) { Bootstrap b = new Bootstrap(); + + // http proxy + Optional<ClientProxy> proxy = ClientProxy.proxyFromRequest(jerseyRequest); + if (!proxy.isPresent()) { + proxy = ClientProxy.proxyFromProperties(requestUri); + } + proxy.ifPresent(clientProxy -> { + b.resolver(NoopAddressResolverGroup.INSTANCE); // request hostname resolved by the HTTP proxy + }); + + final Optional<ClientProxy> handlerProxy = proxy; + b.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @@ -245,41 +256,14 @@ Configuration config = jerseyRequest.getConfiguration(); // http proxy - final Object proxyUri = config.getProperties().get(ClientProperties.PROXY_URI); - if (proxyUri != null) { - final URI u = getProxyUri(proxyUri); - - final String userName = ClientProperties.getValue( - config.getProperties(), ClientProperties.PROXY_USERNAME, String.class); - final String password = ClientProperties.getValue( - config.getProperties(), ClientProperties.PROXY_PASSWORD, String.class); - + handlerProxy.ifPresent(clientProxy -> { + final URI u = clientProxy.uri(); InetSocketAddress proxyAddr = new InetSocketAddress(u.getHost(), - u.getPort() == -1 ? 8080 : u.getPort()); - ProxyHandler proxy = createProxyHandler(jerseyRequest, proxyAddr, userName, password, connectTimeout); - p.addLast(proxy); - } else { - ProxySelector sel = ProxySelector.getDefault(); - for (Proxy proxy: sel.select(requestUri)) { - if (Proxy.Type.HTTP.equals(proxy.type())) { - SocketAddress proxyAddress = proxy.address(); - if (InetSocketAddress.class.isInstance(proxy.address())) { - InetSocketAddress proxyAddr = (InetSocketAddress) proxyAddress; - if (proxyAddr.isUnresolved() - && proxyAddr.getHostName() != null - && proxyAddr.getHostName().startsWith("http://")) { - proxyAddress = new InetSocketAddress( - proxyAddr.getHostString().substring(7), proxyAddr.getPort() - ); - } - } - ProxyHandler proxyHandler - = createProxyHandler(jerseyRequest, proxyAddress, null, null, connectTimeout); - p.addLast(proxyHandler); - break; - } - } - } + u.getPort() == -1 ? 8080 : u.getPort()); + ProxyHandler proxy1 = createProxyHandler(jerseyRequest, proxyAddr, + clientProxy.userName(), clientProxy.password(), connectTimeout); + p.addLast(proxy1); + }); // Enable HTTPS if necessary. if ("https".equals(requestUri.getScheme())) { @@ -471,17 +455,6 @@ executorService.shutdown(); } - @SuppressWarnings("ChainOfInstanceofChecks") - private static URI getProxyUri(final Object proxy) { - if (proxy instanceof URI) { - return (URI) proxy; - } else if (proxy instanceof String) { - return URI.create((String) proxy); - } else { - throw new ProcessingException(LocalizationMessages.WRONG_PROXY_URI_TYPE(ClientProperties.PROXY_URI)); - } - } - protected static class PruneIdlePool extends ChannelDuplexHandler { HashMap<String, ArrayList<Channel>> connections; String key;
diff --git a/connectors/netty-connector/src/main/resources/org/glassfish/jersey/netty/connector/localization.properties b/connectors/netty-connector/src/main/resources/org/glassfish/jersey/netty/connector/localization.properties index 9055d62..ba91c4f 100644 --- a/connectors/netty-connector/src/main/resources/org/glassfish/jersey/netty/connector/localization.properties +++ b/connectors/netty-connector/src/main/resources/org/glassfish/jersey/netty/connector/localization.properties
@@ -14,7 +14,6 @@ # SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 # -wrong.proxy.uri.type=The proxy URI ("{0}") property MUST be an instance of String or URI. wrong.read.timeout=Unexpected ("{0}") READ_TIMEOUT. wrong.max.pool.size=Unexpected ("{0}") maximum number of connections per destination. wrong.max.pool.total=Unexpected ("{0}") maximum number of connections total.
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java index 411100b..909af8d 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022 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
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java index 5a07bc1..056f474 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022 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,6 +18,7 @@ import java.io.IOException; import java.net.HttpURLConnection; +import java.net.Proxy; import java.net.URL; import java.util.Map; import java.util.logging.Logger; @@ -267,6 +268,23 @@ * @throws java.io.IOException in case the connection cannot be provided. */ public HttpURLConnection getConnection(URL url) throws IOException; + + /** + * Get a {@link java.net.HttpURLConnection} for a given URL. + * <p> + * Implementation of the method MUST be thread-safe and MUST ensure that + * a dedicated {@link java.net.HttpURLConnection} instance is returned for concurrent + * requests. + * </p> + * + * @param url the endpoint URL. + * @param proxy the configured proxy or null. + * @return the {@link java.net.HttpURLConnection}. + * @throws java.io.IOException in case the connection cannot be provided. + */ + default HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException { + return (proxy == null) ? getConnection(url) : (HttpURLConnection) url.openConnection(proxy); + } } private static class DefaultConnectionFactory implements ConnectionFactory {
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/ClientProxy.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/ClientProxy.java new file mode 100644 index 0000000..68ab324 --- /dev/null +++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/ClientProxy.java
@@ -0,0 +1,212 @@ +/* + * Copyright (c) 2022 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; + +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.ClientRequest; +import org.glassfish.jersey.client.internal.LocalizationMessages; + +import jakarta.ws.rs.ProcessingException; +import jakarta.ws.rs.core.Configuration; +import jakarta.ws.rs.core.MultivaluedMap; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.SocketAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Base64; +import java.util.Locale; +import java.util.Optional; + +/** + * Default client Proxy information internal object. It is used for parsing the proxy information in all connectors. + */ +public abstract class ClientProxy { + + private ClientProxy() { + // do not instantiate + }; + + public static Optional<ClientProxy> proxyFromRequest(ClientRequest request) { + return getProxy(request); + } + + public static Optional<ClientProxy> proxyFromProperties(URI requestUri) { + return getSystemPropertiesProxy(requestUri); + } + + public static Optional<ClientProxy> proxyFromConfiguration(Configuration configuration) { + return getProxy(configuration); + } + + public static ClientProxy proxy(Proxy proxy) { + return new ProxyClientProxy(proxy); + } + + public static void setBasicAuthorizationHeader(MultivaluedMap<String, Object> headers, ClientProxy proxy) { + if (proxy.userName() != null) { + StringBuilder auth = new StringBuilder().append(proxy.userName()).append(":"); + if (proxy.password() != null) { + auth.append(proxy.password()); + } + String encoded = "Basic " + Base64.getEncoder().encodeToString(auth.toString().getBytes()); + headers.put("Proxy-Authorization", Arrays.asList(encoded)); + } + } + + protected String userName; + protected String password; + + private static ClientProxy toProxy(Object proxy) { + if (proxy instanceof String) { + return new UriClientProxy(URI.create((String) proxy)); + } else if (proxy instanceof URI) { + return new UriClientProxy((URI) proxy); + } else if (Proxy.class.isInstance(proxy)) { + Proxy netProxy = Proxy.class.cast(proxy); + if (Proxy.Type.HTTP.equals(netProxy.type())) { + return new ProxyClientProxy(Proxy.class.cast(proxy)); + } else { + return null; + } + } else { + throw new ProcessingException(LocalizationMessages.WRONG_PROXY_URI_TYPE(ClientProperties.PROXY_URI)); + } + } + + public abstract Proxy proxy(); + + public abstract URI uri(); + + public abstract Proxy.Type type(); + + public String password() { + return password; + } + + public String userName() { + return userName; + }; + + private static Optional<ClientProxy> getProxy(ClientRequest request) { + Object proxyUri = request.resolveProperty(ClientProperties.PROXY_URI, Object.class); + if (proxyUri != null) { + ClientProxy proxy = toProxy(proxyUri); + if (proxy != null) { + proxy.userName = request.resolveProperty(ClientProperties.PROXY_USERNAME, String.class); + proxy.password = request.resolveProperty(ClientProperties.PROXY_PASSWORD, String.class); + return Optional.of(proxy); + } else { + return Optional.empty(); + } + } + return Optional.empty(); + } + + private static Optional<ClientProxy> getProxy(Configuration config) { + Object proxyUri = config.getProperties().get(ClientProperties.PROXY_URI); + if (proxyUri != null) { + ClientProxy proxy = toProxy(proxyUri); + if (proxy != null) { + proxy.userName = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_USERNAME, String.class); + proxy.password = ClientProperties.getValue(config.getProperties(), ClientProperties.PROXY_PASSWORD, String.class); + return Optional.of(proxy); + } else { + return Optional.empty(); + } + } + return Optional.empty(); + } + + private static Optional<ClientProxy> getSystemPropertiesProxy(URI requestUri) { + ProxySelector sel = ProxySelector.getDefault(); + for (Proxy proxy: sel.select(requestUri)) { + if (Proxy.Type.HTTP.equals(proxy.type())) { + return Optional.of(new ProxyClientProxy(proxy)); + } + } + return Optional.empty(); + } + + private static final class ProxyClientProxy extends ClientProxy { + + private final Proxy proxy; + + private ProxyClientProxy(Proxy proxy) { + this.proxy = proxy; + } + + @Override + public Proxy proxy() { + return proxy; + } + + @Override + public Proxy.Type type() { + return proxy.type(); + } + + @Override + public URI uri() { + URI uri = null; + if (Proxy.Type.HTTP.equals(proxy.type())) { + SocketAddress proxyAddress = proxy.address(); + if (InetSocketAddress.class.isInstance(proxy.address())) { + InetSocketAddress proxyAddr = (InetSocketAddress) proxyAddress; + try { + if (proxyAddr.isUnresolved() + && proxyAddr.getHostName() != null + && proxyAddr.getHostName().toLowerCase(Locale.ROOT).startsWith("http://")) { + String hostString = proxyAddr.getHostString().substring(7); + uri = new URI("http", null, hostString, proxyAddr.getPort(), null, null, null); + } else { + uri = new URI("http", null, proxyAddr.getHostString(), proxyAddr.getPort(), null, null, null); + } + } catch (URISyntaxException e) { + throw new ProcessingException(e); + } + } + } + return uri; + } + } + + private static final class UriClientProxy extends ClientProxy { + private final URI uri; + + private UriClientProxy(URI uri) { + this.uri = uri; + } + + @Override + public Proxy proxy() { + return new Proxy(type(), new InetSocketAddress(uri.getHost(), uri.getPort())); + } + + @Override + public Proxy.Type type() { + return Proxy.Type.HTTP; + } + + @Override + public URI uri() { + return uri; + } + } +} +
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/package-info.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/package-info.java new file mode 100644 index 0000000..016eea7 --- /dev/null +++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/package-info.java
@@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 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 classes/interfaces. + * Shall not be used outside of Jersey. + */ +package org.glassfish.jersey.client.innate; \ No newline at end of file
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 10f2387..31a3583 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, 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022 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,6 +32,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; @@ -39,21 +40,21 @@ import java.util.logging.Logger; import java.util.stream.Collectors; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSocketFactory; import jakarta.ws.rs.ProcessingException; import jakarta.ws.rs.client.Client; import jakarta.ws.rs.core.MultivaluedMap; import jakarta.ws.rs.core.Response; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSocketFactory; - import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.ClientRequest; import org.glassfish.jersey.client.ClientResponse; import org.glassfish.jersey.client.HttpUrlConnectorProvider; import org.glassfish.jersey.client.JerseyClient; import org.glassfish.jersey.client.RequestEntityProcessing; +import org.glassfish.jersey.client.innate.ClientProxy; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; import org.glassfish.jersey.internal.util.PropertiesHelper; @@ -316,8 +317,9 @@ private ClientResponse _apply(final ClientRequest request) throws IOException { final HttpURLConnection uc; - - uc = this.connectionFactory.getConnection(request.getUri().toURL()); + Optional<ClientProxy> proxy = ClientProxy.proxyFromRequest(request); + proxy.ifPresent(clientProxy -> ClientProxy.setBasicAuthorizationHeader(request.getHeaders(), proxy.get())); + uc = this.connectionFactory.getConnection(request.getUri().toURL(), proxy.isPresent() ? proxy.get().proxy() : null); uc.setDoInput(true); final String httpMethod = request.getMethod();
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 4bc0ae8..e66ceab 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, 2019 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2022 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 @@ -84,3 +84,5 @@ error.listener.init=ClientLifecycleListener {0} failed to initialize properly. error.listener.close=ClientLifecycleListener {0} failed to close properly. error.shutdownhook.close=Client shutdown hook {0} failed. +# {0} - property name - jersey.config.client.httpclient.proxyUri +wrong.proxy.uri.type=The proxy URI ("{0}") property MUST be an instance of String or URI.
diff --git a/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java b/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java index 5204144..7a00f1f 100644 --- a/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java +++ b/core-client/src/test/java/org/glassfish/jersey/client/HttpUrlConnectorTest.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022 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
diff --git a/core-common/src/main/java/org/glassfish/jersey/ExternalProperties.java b/core-common/src/main/java/org/glassfish/jersey/ExternalProperties.java index 04ef1bd..a8f6ec6 100644 --- a/core-common/src/main/java/org/glassfish/jersey/ExternalProperties.java +++ b/core-common/src/main/java/org/glassfish/jersey/ExternalProperties.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 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,12 +32,22 @@ public static final String HTTP_PROXY_PORT = "http.proxyPort"; /** - * Property used to indicates the hosts that should be accessed + * Property used to indicate the hosts that should be accessed * without going through the proxy. */ public static final String HTTP_NON_PROXY_HOSTS = "http.nonProxyHosts"; /** + * Property used to specify the user name to authenticate with the proxy. + */ + public static final String HTTP_PROXY_USER = "http.proxyUser"; + + /** + * Property used to specify the password to authenticate with the proxy. + */ + public static final String HTTP_PROXY_PASSWORD = "http.proxyPassword"; + + /** * Prevent instantiation. */ private ExternalProperties() {
diff --git a/media/json-gson/pom.xml b/media/json-gson/pom.xml new file mode 100644 index 0000000..8b2c2c5 --- /dev/null +++ b/media/json-gson/pom.xml
@@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2022 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.media</groupId> + <artifactId>project</artifactId> + <version>3.1.0-SNAPSHOT</version> + </parent> + + <artifactId>jersey-media-json-gson</artifactId> + <packaging>jar</packaging> + <name>jersey-media-json-gson</name> + + <description> + Jersey GSON support module. + </description> + + <build> + <plugins> + <plugin> + <groupId>com.sun.istack</groupId> + <artifactId>istack-commons-maven-plugin</artifactId> + <inherited>true</inherited> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <inherited>true</inherited> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <inherited>true</inherited> + <extensions>true</extensions> + <configuration> + <instructions> + <Export-Package>org.glassfish.jersey.gson.*</Export-Package> + <Import-Package>${javax.annotation.osgi.version},*</Import-Package> + </instructions> + <unpackBundle>true</unpackBundle> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> \ No newline at end of file
diff --git a/media/json-gson/src/main/java/org/glassfish/jersey/gson/JsonGsonFeature.java b/media/json-gson/src/main/java/org/glassfish/jersey/gson/JsonGsonFeature.java new file mode 100644 index 0000000..498f958 --- /dev/null +++ b/media/json-gson/src/main/java/org/glassfish/jersey/gson/JsonGsonFeature.java
@@ -0,0 +1,75 @@ +/* + * Copyright (c) 2022 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.gson; + +import jakarta.ws.rs.core.Configuration; +import jakarta.ws.rs.core.Feature; +import jakarta.ws.rs.core.FeatureContext; + +import org.glassfish.jersey.CommonProperties; +import org.glassfish.jersey.gson.internal.JsonGsonAutoDiscoverable; +import org.glassfish.jersey.gson.internal.JsonGsonProvider; +import org.glassfish.jersey.internal.InternalProperties; +import org.glassfish.jersey.internal.util.PropertiesHelper; +/** + * Feature used to register Gson providers. + * <p> + * The Feature is automatically enabled when {@link JsonGsonAutoDiscoverable} is on classpath. + * Default GSON configuration obtained by calling {@code GsonBuilder.create()} is used. + * <p> + * Custom configuration, if required, can be achieved by implementing custom {@link jakarta.ws.rs.ext.ContextResolver} and + * registering it as a provider into JAX-RS runtime: + * <pre> + * @Provider + * @class GsonContextResolver implements ContextResolver<Gson> { + * @Override + * public Gson getContext(Class<?> type) { + * GsonBuilder builder = new GsonBuilder(); + * // add custom configuration + * return builder.create(); + * } + * } + * </pre> + * + */ +public class JsonGsonFeature implements Feature { + + private static final String JSON_FEATURE = JsonGsonFeature.class.getSimpleName(); + + @Override + public boolean configure(final FeatureContext context) { + final Configuration config = context.getConfiguration(); + + final String jsonFeature = CommonProperties.getValue( + config.getProperties(), + config.getRuntimeType(), + InternalProperties.JSON_FEATURE, JSON_FEATURE, String.class); + + // Other JSON providers registered. + if (!JSON_FEATURE.equalsIgnoreCase(jsonFeature)) { + return false; + } + + // Disable other JSON providers. + context.property(PropertiesHelper.getPropertyNameForRuntime( + InternalProperties.JSON_FEATURE, config.getRuntimeType()), JSON_FEATURE); + + context.register(JsonGsonProvider.class); + + return true; + } +}
diff --git a/media/json-gson/src/main/java/org/glassfish/jersey/gson/internal/JsonGsonAutoDiscoverable.java b/media/json-gson/src/main/java/org/glassfish/jersey/gson/internal/JsonGsonAutoDiscoverable.java new file mode 100644 index 0000000..f532953 --- /dev/null +++ b/media/json-gson/src/main/java/org/glassfish/jersey/gson/internal/JsonGsonAutoDiscoverable.java
@@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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.gson.internal; + +import jakarta.annotation.Priority; +import jakarta.ws.rs.core.FeatureContext; + +import org.glassfish.jersey.gson.JsonGsonFeature; +import org.glassfish.jersey.internal.spi.AutoDiscoverable; +import org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable; + +/** + * {@link ForcedAutoDiscoverable} registering {@link JsonGsonFeature} if the feature is not already registered. + * <p> + * + * @see JsonGsonFeature + */ +@Priority(AutoDiscoverable.DEFAULT_PRIORITY) +public class JsonGsonAutoDiscoverable implements ForcedAutoDiscoverable { + + @Override + public void configure(FeatureContext context) { + if (!context.getConfiguration().isRegistered(JsonGsonFeature.class)) { + context.register(JsonGsonFeature.class); + } + } +}
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 new file mode 100644 index 0000000..a35dfad --- /dev/null +++ b/media/json-gson/src/main/java/org/glassfish/jersey/gson/internal/JsonGsonProvider.java
@@ -0,0 +1,139 @@ +/* + * Copyright (c) 2022 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.gson.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +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; +import jakarta.ws.rs.ext.ContextResolver; +import jakarta.ws.rs.ext.Provider; +import jakarta.ws.rs.ext.Providers; + +import org.glassfish.jersey.gson.LocalizationMessages; +import org.glassfish.jersey.message.internal.AbstractMessageReaderWriterProvider; +import org.glassfish.jersey.message.internal.EntityInputStream; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +/** + * Entity provider (reader and writer) for Gson. + * + */ +@Provider +@Produces({"application/json", "text/json", "*/*"}) +@Consumes({"application/json", "text/json", "*/*"}) +public class JsonGsonProvider extends AbstractMessageReaderWriterProvider<Object> { + + private static final String JSON = "json"; + private static final String PLUS_JSON = "+json"; + + private Providers providers; + + public JsonGsonProvider(@Context Providers providers) { + this.providers = providers; + } + + @Override + public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return supportsMediaType(mediaType); + } + + @Override + public Object readFrom(Class<Object> type, Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap<String, String> httpHeaders, + InputStream entityStream) throws IOException, WebApplicationException { + EntityInputStream entityInputStream = new EntityInputStream(entityStream); + entityStream = entityInputStream; + if (entityInputStream.isEmpty()) { + throw new NoContentException(LocalizationMessages.ERROR_GSON_EMPTYSTREAM()); + } + Gson gson = getGson(type); + try { + return gson.fromJson(new InputStreamReader(entityInputStream, + AbstractMessageReaderWriterProvider.getCharset(mediaType)), genericType); + } catch (Exception e) { + throw new ProcessingException(LocalizationMessages.ERROR_GSON_DESERIALIZATION(), e); + } + } + + @Override + public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return supportsMediaType(mediaType); + } + + @Override + public void writeTo(Object o, Class<?> type, Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap<String, Object> httpHeaders, + OutputStream entityStream) throws IOException, WebApplicationException { + Gson gson = getGson(type); + try { + entityStream.write(gson.toJson(o).getBytes(AbstractMessageReaderWriterProvider.getCharset(mediaType))); + entityStream.flush(); + } catch (Exception e) { + throw new ProcessingException(LocalizationMessages.ERROR_GSON_SERIALIZATION(), e); + } + } + + private Gson getGson(Class<?> type) { + final ContextResolver<Gson> contextResolver = providers.getContextResolver(Gson.class, MediaType.APPLICATION_JSON_TYPE); + if (contextResolver != null) { + return contextResolver.getContext(type); + } else { + return GsonSingleton.INSTANCE.getInstance(); + } + } + + /** + * @return true for all media types of the pattern */json and + * */*+json. + */ + private static boolean supportsMediaType(final MediaType mediaType) { + return mediaType.getSubtype().equals(JSON) || mediaType.getSubtype().endsWith(PLUS_JSON); + } + + private enum GsonSingleton { + INSTANCE; + + // Thread-safe + private Gson gsonInstance; + + Gson getInstance() { + return gsonInstance; + } + + GsonSingleton() { + this.gsonInstance = new GsonBuilder().create(); + } + } +}
diff --git a/media/json-gson/src/main/java/org/glassfish/jersey/gson/package-info.java b/media/json-gson/src/main/java/org/glassfish/jersey/gson/package-info.java new file mode 100644 index 0000000..12e6b90 --- /dev/null +++ b/media/json-gson/src/main/java/org/glassfish/jersey/gson/package-info.java
@@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022 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 classes supporting JSON marshalling and unmarshalling using GSON. + */ +package org.glassfish.jersey.gson;
diff --git a/media/json-gson/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable b/media/json-gson/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable new file mode 100644 index 0000000..7f4e0ee --- /dev/null +++ b/media/json-gson/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable
@@ -0,0 +1 @@ +org.glassfish.jersey.gson.internal.JsonGsonAutoDiscoverable
diff --git a/media/json-gson/src/main/resources/org/glassfish/jersey/gson/localization.properties b/media/json-gson/src/main/resources/org/glassfish/jersey/gson/localization.properties new file mode 100644 index 0000000..b2ea26a --- /dev/null +++ b/media/json-gson/src/main/resources/org/glassfish/jersey/gson/localization.properties
@@ -0,0 +1,19 @@ +# +# Copyright (c) 2022 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 +# + +error.gson.serialization=Error writing GSON serialized object. +error.gson.deserialization=Error deserializing object from entity stream. +error.gson.emptystream=GSON cannot parse empty input stream.
diff --git a/media/json-gson/src/test/java/org/glassfish/jersey/gson/internal/JsonGsonProviderTest.java b/media/json-gson/src/test/java/org/glassfish/jersey/gson/internal/JsonGsonProviderTest.java new file mode 100644 index 0000000..7aa403e --- /dev/null +++ b/media/json-gson/src/test/java/org/glassfish/jersey/gson/internal/JsonGsonProviderTest.java
@@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022 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.gson.internal; + +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON_TYPE; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedHashMap; +import jakarta.ws.rs.core.NoContentException; +import jakarta.ws.rs.ext.ContextResolver; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.MessageBodyReader; +import jakarta.ws.rs.ext.MessageBodyWriter; +import jakarta.ws.rs.ext.Providers; + +import org.junit.Test; + +public class JsonGsonProviderTest { + + @Test(expected = NoContentException.class) + public void shouldThrowNoContentException() throws IOException { + Providers providers = new EmptyProviders(); + MessageBodyReader<Foo> mbr = (MessageBodyReader) new JsonGsonProvider(providers); + mbr.readFrom(Foo.class, Foo.class, new Annotation[0], APPLICATION_JSON_TYPE, + new MultivaluedHashMap<>(), new ByteArrayInputStream(new byte[0])); + } + + private static final class Foo { + // no members + } + + private static final class EmptyProviders implements Providers { + + @Override + public final <T> MessageBodyReader<T> getMessageBodyReader(final Class<T> type, final Type genericType, + final Annotation[] annotations, final MediaType mediaType) { + return null; + } + + @Override + public final <T> MessageBodyWriter<T> getMessageBodyWriter(final Class<T> type, final Type genericType, + final Annotation[] annotations, final MediaType mediaType) { + return null; + } + + @Override + public final <T extends Throwable> ExceptionMapper<T> getExceptionMapper(final Class<T> type) { + return null; + } + + @Override + public final <T> ContextResolver<T> getContextResolver(final Class<T> contextType, final MediaType mediaType) { + return null; + } + + } + +}
diff --git a/media/pom.xml b/media/pom.xml index 68daa76..e738eb1 100644 --- a/media/pom.xml +++ b/media/pom.xml
@@ -38,6 +38,7 @@ <modules> <module>jaxb</module> <module>json-binding</module> + <module>json-gson</module> <module>json-jackson</module> <module>json-jettison</module> <module>json-processing</module>
diff --git a/pom.xml b/pom.xml index 7de8ef3..9469a2c 100644 --- a/pom.xml +++ b/pom.xml
@@ -2046,6 +2046,12 @@ </dependency> <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>${gson.version}</version> + </dependency> + + <dependency> <groupId>io.opentracing</groupId> <artifactId>opentracing-api</artifactId> <version>${opentracing.version}</version> @@ -2164,6 +2170,7 @@ <spring6.version>6.0.0-M3</spring6.version> <surefire.version>3.0.0-M6</surefire.version> <validation.impl.version>6.2.0.Final</validation.impl.version> + <gson.version>2.9.0</gson.version> <!-- Jakartified, eligible for CQ --> <weld.version>4.0.2.Final</weld.version>
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java index 1741a66..91ea1b1 100644 --- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java +++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxySelectorTest.java
@@ -61,9 +61,8 @@ @Parameterized.Parameters(name = "{index}: {0}") public static List<Object[]> testData() { return Arrays.asList(new Object[][]{ -// {ApacheConnectorProvider.class}, -// {Apache5ConnectorProvider.class}, -// {JettyConnectorProvider.class}, + // Apache, Grizzly, Jetty have the proxy set on constructor, i.e. ProxySelector cannot choose based on URI. + // HttpUrlConnector ignores proxy on localhost. {NettyConnectorProvider.class}, }); }
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java index 1ae437b..f3006e2 100644 --- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java +++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/proxy/ProxyTest.java
@@ -25,7 +25,9 @@ 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.grizzly.connector.GrizzlyConnectorProvider; import org.glassfish.jersey.jetty.connector.JettyConnectorProvider; import org.glassfish.jersey.netty.connector.NettyConnectorProvider; import org.junit.AfterClass; @@ -70,8 +72,10 @@ return Arrays.asList(new Object[][]{ {ApacheConnectorProvider.class}, {Apache5ConnectorProvider.class}, + {GrizzlyConnectorProvider.class}, {JettyConnectorProvider.class}, {NettyConnectorProvider.class}, + {HttpUrlConnectorProvider.class}, }); } @@ -96,9 +100,11 @@ @Test public void testGet407() { + // Grizzly sends (String)null password and username + int expected = GrizzlyConnectorProvider.class.isInstance(connectorProvider) ? 400 : 407; client().property(ClientProperties.PROXY_URI, ProxyTest.PROXY_URI); try (Response response = target("proxyTest").request().get()) { - assertEquals(407, response.getStatus()); + assertEquals(expected, response.getStatus()); } catch (ProcessingException pe) { Assert.assertTrue(pe.getMessage().contains("407")); // netty } @@ -110,7 +116,8 @@ client().property(ClientProperties.PROXY_USERNAME, ProxyTest.PROXY_USERNAME); client().property(ClientProperties.PROXY_PASSWORD, ProxyTest.PROXY_PASSWORD); Response response = target("proxyTest").request().get(); - assertEquals(200, response.getStatus()); + response.bufferEntity(); + assertEquals(response.readEntity(String.class), 200, response.getStatus()); } private static Server server;
diff --git a/tests/e2e-server/pom.xml b/tests/e2e-server/pom.xml index aca4fa5..51408e2 100644 --- a/tests/e2e-server/pom.xml +++ b/tests/e2e-server/pom.xml
@@ -95,6 +95,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-json-gson</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.glassfish.jersey.ext</groupId> <artifactId>jersey-bean-validation</artifactId> <scope>test</scope>
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GsonCustomTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GsonCustomTest.java new file mode 100644 index 0000000..a967dc7 --- /dev/null +++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GsonCustomTest.java
@@ -0,0 +1,75 @@ +/* + * Copyright (c) 2022 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.server; + +import static org.junit.Assert.assertEquals; + +import java.util.Date; + +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ContextResolver; +import jakarta.ws.rs.ext.Provider; + +import org.glassfish.jersey.gson.JsonGsonFeature; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Test; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class GsonCustomTest extends JerseyTest { + + private static final Date date = new Date(0); + + @Path("/test") + public static class Resource { + + @GET + @Consumes("application/json") + public Date get() { + return date; + } + } + + @Override + protected Application configure() { + return new ResourceConfig(Resource.class).register(JsonGsonFeature.class).register(GsonContextResolver.class); + } + + @Test + public void get() { + Response response = target("/test").request().get(); + assertEquals(200, response.getStatus()); + String obj = response.readEntity(String.class); + assertEquals("\"1970\"", obj); + } + + @Provider + public static class GsonContextResolver implements ContextResolver<Gson> { + @Override + public Gson getContext(Class<?> type) { + GsonBuilder builder = new GsonBuilder(); + builder.setDateFormat("yyyy"); + return builder.create(); + } + } +}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GsonDefaultTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GsonDefaultTest.java new file mode 100644 index 0000000..0d0dad5 --- /dev/null +++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/GsonDefaultTest.java
@@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 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.server; + +import static org.junit.Assert.assertEquals; + +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.Response; + +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.gson.JsonGsonFeature; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Test; + +public class GsonDefaultTest extends JerseyTest { + + @Path("/test") + public static class Resource { + + @POST + @Consumes("application/json") + @Produces("application/json") + public Obj post(Obj entity) { + entity.setValue("bar"); + return entity; + } + + @GET + @Consumes("application/json") + public Obj get() { + Obj entity = new Obj(); + entity.setValue("get"); + return entity; + } + } + + @Override + protected Application configure() { + return new ResourceConfig(Resource.class) + .register(JsonGsonFeature.class); + } + + @Override + protected void configureClient(ClientConfig config) { + config.register(JsonGsonFeature.class); + } + + @Test + public void get() { + Response response = target("/test").request().get(); + assertEquals(200, response.getStatus()); + Obj obj = response.readEntity(Obj.class); + assertEquals("get", obj.getValue()); + } + + @Test + public void post() { + Obj obj = new Obj(); + obj.setValue("foo"); + Response response = target("/test").request().post(Entity.json(obj)); + assertEquals(200, response.getStatus()); + obj = response.readEntity(Obj.class); + assertEquals("bar", obj.getValue()); + } + + public static class Obj { + private String value; + + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + } +}
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 10a5703..7e79571 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 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 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
diff --git a/tests/integration/jersey-4003/src/test/java/org/glassfish/jersey/tests/integration/jersey4003/LostResponseTest.java b/tests/integration/jersey-4003/src/test/java/org/glassfish/jersey/tests/integration/jersey4003/LostResponseTest.java index 710ff81..059e450 100644 --- a/tests/integration/jersey-4003/src/test/java/org/glassfish/jersey/tests/integration/jersey4003/LostResponseTest.java +++ b/tests/integration/jersey-4003/src/test/java/org/glassfish/jersey/tests/integration/jersey4003/LostResponseTest.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022 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 @@ -59,7 +59,7 @@ HttpUrlConnectorProvider.ConnectionFactory connectionFactory = Mockito.mock(HttpUrlConnectorProvider.ConnectionFactory.class); HttpURLConnection connection = Mockito.mock(HttpURLConnection.class); - Mockito.when(connectionFactory.getConnection(Mockito.any(URL.class))).thenReturn(connection); + Mockito.when(connectionFactory.getConnection(Mockito.any(URL.class), Mockito.any())).thenReturn(connection); OutputStream outputStream = Mockito.mock(OutputStream.class); Mockito.when(connection.getOutputStream()).thenReturn(outputStream);