4343import java .lang .ref .ReferenceQueue ;
4444import java .lang .ref .WeakReference ;
4545import java .net .URI ;
46+ import java .util .Iterator ;
4647import java .util .Map ;
4748import java .util .concurrent .LinkedBlockingDeque ;
4849import java .util .concurrent .atomic .AtomicBoolean ;
4950import java .util .logging .Level ;
5051import java .util .logging .Logger ;
5152
52- import javax .net .ssl .HostnameVerifier ;
53- import javax .net .ssl .SSLContext ;
5453import javax .ws .rs .core .Configuration ;
5554import javax .ws .rs .core .Link ;
5655import javax .ws .rs .core .UriBuilder ;
5756
57+ import javax .net .ssl .HostnameVerifier ;
58+ import javax .net .ssl .SSLContext ;
59+
5860import org .glassfish .jersey .SslConfigurator ;
5961import org .glassfish .jersey .client .internal .LocalizationMessages ;
62+ import org .glassfish .jersey .client .spi .DefaultSslContextProvider ;
63+ import org .glassfish .jersey .internal .ServiceFinder ;
6064import org .glassfish .jersey .internal .util .collection .UnsafeValue ;
6165import org .glassfish .jersey .internal .util .collection .Values ;
6266
7276public class JerseyClient implements javax .ws .rs .client .Client , Initializable <JerseyClient > {
7377 private static final Logger LOG = Logger .getLogger (JerseyClient .class .getName ());
7478
79+ private static final DefaultSslContextProvider DEFAULT_SSL_CONTEXT_PROVIDER = new DefaultSslContextProvider () {
80+ @ Override
81+ public SSLContext getDefaultSslContext () {
82+ return SslConfigurator .getDefaultContext ();
83+ }
84+ };
85+
7586 private final AtomicBoolean closedFlag = new AtomicBoolean (false );
87+ private final boolean isDefaultSslContext ;
7688 private final ClientConfig config ;
7789 private final HostnameVerifier hostnameVerifier ;
7890 private final UnsafeValue <SSLContext , IllegalStateException > sslContext ;
@@ -83,7 +95,7 @@ public class JerseyClient implements javax.ws.rs.client.Client, Initializable<Je
8395 /**
8496 * Client instance shutdown hook.
8597 */
86- static interface ShutdownHook {
98+ interface ShutdownHook {
8799 /**
88100 * Invoked when the client instance is closed.
89101 */
@@ -94,7 +106,7 @@ static interface ShutdownHook {
94106 * Create a new Jersey client instance using a default configuration.
95107 */
96108 protected JerseyClient () {
97- this (null , (UnsafeValue <SSLContext , IllegalStateException >) null , null );
109+ this (null , (UnsafeValue <SSLContext , IllegalStateException >) null , null , null );
98110 }
99111
100112 /**
@@ -107,7 +119,24 @@ protected JerseyClient() {
107119 protected JerseyClient (final Configuration config ,
108120 final SSLContext sslContext ,
109121 final HostnameVerifier verifier ) {
110- this (config , Values .<SSLContext , IllegalStateException >unsafe (sslContext ), verifier );
122+
123+ this (config , sslContext , verifier , null );
124+ }
125+
126+ /**
127+ * Create a new Jersey client instance.
128+ *
129+ * @param config jersey client configuration.
130+ * @param sslContext jersey client SSL context.
131+ * @param verifier jersey client host name verifier.
132+ * @param defaultSslContextProvider default SSL context provider.
133+ */
134+ protected JerseyClient (final Configuration config ,
135+ final SSLContext sslContext ,
136+ final HostnameVerifier verifier ,
137+ final DefaultSslContextProvider defaultSslContextProvider ) {
138+ this (config , sslContext == null ? null : Values .<SSLContext , IllegalStateException >unsafe (sslContext ), verifier ,
139+ defaultSslContextProvider );
111140 }
112141
113142 /**
@@ -120,18 +149,49 @@ protected JerseyClient(final Configuration config,
120149 protected JerseyClient (final Configuration config ,
121150 final UnsafeValue <SSLContext , IllegalStateException > sslContextProvider ,
122151 final HostnameVerifier verifier ) {
123- this .config = config == null ? new ClientConfig (this ) : new ClientConfig (this , config );
124- this .sslContext = Values .lazy (sslContextProvider != null ? sslContextProvider : createSslContextProvider ());
125- this .hostnameVerifier = verifier ;
152+ this (config , sslContextProvider , verifier , null );
126153 }
127154
128- private UnsafeValue <SSLContext , IllegalStateException > createSslContextProvider () {
129- return new UnsafeValue <SSLContext , IllegalStateException >() {
130- @ Override
131- public SSLContext get () {
132- return SslConfigurator .getDefaultContext ();
155+ /**
156+ * Create a new Jersey client instance.
157+ *
158+ * @param config jersey client configuration.
159+ * @param sslContextProvider jersey client SSL context provider. Non {@code null} provider is expected to
160+ * return non-default value.
161+ * @param verifier jersey client host name verifier.
162+ * @param defaultSslContextProvider default SSL context provider.
163+ */
164+ protected JerseyClient (final Configuration config ,
165+ final UnsafeValue <SSLContext , IllegalStateException > sslContextProvider ,
166+ final HostnameVerifier verifier ,
167+ final DefaultSslContextProvider defaultSslContextProvider ) {
168+ this .config = config == null ? new ClientConfig (this ) : new ClientConfig (this , config );
169+
170+ if (sslContextProvider == null ) {
171+ this .isDefaultSslContext = true ;
172+
173+ if (defaultSslContextProvider != null ) {
174+ this .sslContext = createLazySslContext (defaultSslContextProvider );
175+ } else {
176+ final DefaultSslContextProvider lookedUpSslContextProvider ;
177+
178+ final Iterator <DefaultSslContextProvider > iterator =
179+ ServiceFinder .find (DefaultSslContextProvider .class ).iterator ();
180+
181+ if (iterator .hasNext ()) {
182+ lookedUpSslContextProvider = iterator .next ();
183+ } else {
184+ lookedUpSslContextProvider = DEFAULT_SSL_CONTEXT_PROVIDER ;
185+ }
186+
187+ this .sslContext = createLazySslContext (lookedUpSslContextProvider );
133188 }
134- };
189+ } else {
190+ this .isDefaultSslContext = false ;
191+ this .sslContext = Values .lazy (sslContextProvider );
192+ }
193+
194+ this .hostnameVerifier = verifier ;
135195 }
136196
137197 @ Override
@@ -145,7 +205,7 @@ private void release() {
145205 Reference <ShutdownHook > listenerRef ;
146206 while ((listenerRef = shutdownHooks .pollFirst ()) != null ) {
147207 JerseyClient .ShutdownHook listener = listenerRef .get ();
148- if (listener != null ){
208+ if (listener != null ) {
149209 try {
150210 listener .onShutdown ();
151211 } catch (Throwable t ) {
@@ -155,6 +215,15 @@ private void release() {
155215 }
156216 }
157217
218+ private UnsafeValue <SSLContext , IllegalStateException > createLazySslContext (final DefaultSslContextProvider provider ) {
219+ return Values .lazy (new UnsafeValue <SSLContext , IllegalStateException >() {
220+ @ Override
221+ public SSLContext get () {
222+ return provider .getDefaultSslContext ();
223+ }
224+ });
225+ }
226+
158227 /**
159228 * Register a new client shutdown hook.
160229 *
@@ -204,6 +273,16 @@ void checkNotClosed() {
204273 checkState (!closedFlag .get (), LocalizationMessages .CLIENT_INSTANCE_CLOSED ());
205274 }
206275
276+ /**
277+ * Get information about used {@link SSLContext}.
278+ *
279+ * @return {@code true} when used {@code SSLContext} is acquired from {@link SslConfigurator#getDefaultContext()},
280+ * {@code false} otherwise.
281+ */
282+ public boolean isDefaultSslContext () {
283+ return isDefaultSslContext ;
284+ }
285+
207286 @ Override
208287 public JerseyWebTarget target (final String uri ) {
209288 checkNotClosed ();
0 commit comments