001/*
002 * Copyright 2012-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2012-2024 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2012-2024 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.util;
037
038
039
040import java.io.IOException;
041import java.net.InetAddress;
042import java.net.Socket;
043import javax.net.ssl.SSLSocketFactory;
044
045
046
047/**
048 * This class provides an implementation of a Java socket factory that will
049 * wrap a provided socket factory but will synchronize on each use of that
050 * factory to ensure that only a single thread may use that factory to create
051 * a socket at any given time.
052 */
053@NotMutable()
054@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
055public final class SynchronizedSSLSocketFactory
056       extends SSLSocketFactory
057{
058  // The wrapped SSL socket factory.
059  @NotNull private final SSLSocketFactory factory;
060
061
062
063  /**
064   * Creates a new synchronous socket factory instance that will wrap the
065   * provided socket factory.
066   *
067   * @param  factory  The socket factory to be wrapped.
068   */
069  public SynchronizedSSLSocketFactory(@NotNull final SSLSocketFactory factory)
070  {
071    this.factory = factory;
072  }
073
074
075
076  /**
077   * Retrieves the {@code SSLSocketFactory} instance wrapped by this
078   * synchronized SSL socket factory.
079   *
080   * @return  The {@code SSLSocketFactory} instance wrapped by this synchronized
081   *          SSL socket factory.
082   */
083  @NotNull()
084  public SSLSocketFactory getWrappedSocketFactory()
085  {
086    return factory;
087  }
088
089
090
091  /**
092   * Creates a new SSL socket to the specified server.
093   *
094   * @param  host  The host to which the connection should be established.
095   * @param  port  The port to which the connection should be established.
096   *
097   * @return  The SSL socket that was created.
098   *
099   * @throws  IOException  If a problem occurs while creating the socket.
100   */
101  @Override()
102  @NotNull()
103  public Socket createSocket(@NotNull final String host, final int port)
104         throws IOException
105  {
106    synchronized (factory)
107    {
108      return factory.createSocket(host, port);
109    }
110  }
111
112
113
114  /**
115   * Creates a new SSL socket to the specified server.
116   *
117   * @param  host          The host to which the connection should be
118   *                       established.
119   * @param  port          The port to which the connection should be
120   *                       established.
121   * @param  localAddress  The local address to use for the connection.
122   * @param  localPort     The local port to use for the connection.
123   *
124   * @return  The SSL socket that was created.
125   *
126   * @throws  IOException  If a problem occurs while creating the socket.
127   */
128  @Override()
129  @NotNull()
130  public Socket createSocket(@NotNull final String host, final int port,
131                             @NotNull final InetAddress localAddress,
132                             final int localPort)
133         throws IOException
134  {
135    synchronized (factory)
136    {
137      return factory.createSocket(host, port, localAddress, localPort);
138    }
139  }
140
141
142
143  /**
144   * Creates a new SSL socket to the specified server.
145   *
146   * @param  address  The address to which the connection should be established.
147   * @param  port     The port to which the connection should be established.
148   *
149   * @return  The SSL socket that was created.
150   *
151   * @throws  IOException  If a problem occurs while creating the socket.
152   */
153  @Override()
154  @NotNull()
155  public Socket createSocket(@NotNull final InetAddress address, final int port)
156         throws IOException
157  {
158    synchronized (factory)
159    {
160      return factory.createSocket(address, port);
161    }
162  }
163
164
165
166  /**
167   * Creates a new SSL socket to the specified server.
168   *
169   * @param  address       The address to which the connection should be
170   *                       established.
171   * @param  port          The port to which the connection should be
172   *                       established.
173   * @param  localAddress  The local address to use for the connection.
174   * @param  localPort     The local port to use for the connection.
175   *
176   * @return  The SSL socket that was created.
177   *
178   * @throws  IOException  If a problem occurs while creating the socket.
179   */
180  @Override()
181  @NotNull()
182  public Socket createSocket(@NotNull final InetAddress address, final int port,
183                             @NotNull final InetAddress localAddress,
184                             final int localPort)
185         throws IOException
186  {
187    synchronized (factory)
188    {
189      return factory.createSocket(address, port, localAddress, localPort);
190    }
191  }
192
193
194
195  /**
196   * Creates a new SSL socket that wraps the provided socket.
197   *
198   * @param  s          The existing socket to be wrapped to create an SSL
199   *                    socket.
200   * @param  host       The host to which the connection is established.
201   * @param  port       The port to which the connection is established.
202   * @param  autoClose  Indicates whether the provided socket should be closed
203   *                    when the created SSL socket is closed.
204   *
205   * @return  The SSL socket that was created.
206   *
207   * @throws  IOException  If a problem occurs while creating the socket.
208   */
209  @Override()
210  @NotNull()
211  public Socket createSocket(@NotNull final Socket s,
212                             @NotNull final String host, final int port,
213                             final boolean autoClose)
214         throws IOException
215  {
216    synchronized (factory)
217    {
218      return factory.createSocket(s, host, port, autoClose);
219    }
220  }
221
222
223
224  /**
225   * Retrieves the set of cipher suites which are enabled by default.
226   *
227   * @return  The set of cipher suites which are enabled by default.
228   */
229  @Override()
230  @NotNull()
231  public String[] getDefaultCipherSuites()
232  {
233    synchronized (factory)
234    {
235      return factory.getDefaultCipherSuites();
236    }
237  }
238
239
240
241  /**
242   * Retrieves the entire set of cipher suites that could be used.
243   *
244   * @return  The entire set of cipher suites that could be used.
245   */
246  @Override()
247  @NotNull()
248  public String[] getSupportedCipherSuites()
249  {
250    synchronized (factory)
251    {
252      return factory.getSupportedCipherSuites();
253    }
254  }
255}