com.neovisionaries.ws.client.ProxySettings Maven / Gradle / Ivy
Show all versions of nv-websocket-client Show documentation
/*
* Copyright (C) 2015-2018 Neo Visionaries Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.neovisionaries.ws.client;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
/**
* Proxy settings.
*
*
* If a proxy server's host name is set (= if {@link #getHost()}
* returns a non-null value), a socket factory that creates a
* socket to communicate with the proxy server is selected based
* on the settings of this {@code ProxySettings} instance. The
* following is the concrete flow to select a socket factory.
*
*
*
*
* -
* If {@link #isSecure()} returns {@code true},
*
* -
* If an {@link SSLContext} instance has been set by {@link
* #setSSLContext(SSLContext)}, the value returned from {@link
* SSLContext#getSocketFactory()} method of the instance is used.
*
-
* Otherwise, if an {@link SSLSocketFactory} instance has been
* set by {@link #setSSLSocketFactory(SSLSocketFactory)}, the
* instance is used.
*
-
* Otherwise, the value returned from {@link SSLSocketFactory#getDefault()}
* is used.
*
* -
* Otherwise (= {@link #isSecure()} returns {@code false}),
*
* -
* If a {@link SocketFactory} instance has been set by {@link
* #setSocketFactory(SocketFactory)}, the instance is used.
*
-
* Otherwise, the value returned from {@link SocketFactory#getDefault()}
* is used.
*
*
*
*
*
* Note that the current implementation supports only Basic Authentication
* for authentication at the proxy server.
*
*
* @see WebSocketFactory#getProxySettings()
*
* @since 1.3
*/
public class ProxySettings
{
private final WebSocketFactory mWebSocketFactory;
private final Map> mHeaders;
private final SocketFactorySettings mSocketFactorySettings;
private boolean mSecure;
private String mHost;
private int mPort;
private String mId;
private String mPassword;
private String[] mServerNames;
ProxySettings(WebSocketFactory factory)
{
mWebSocketFactory = factory;
mHeaders = new TreeMap>(String.CASE_INSENSITIVE_ORDER);
mSocketFactorySettings = new SocketFactorySettings();
reset();
}
/**
* Get the associated {@link WebSocketFactory} instance.
*/
public WebSocketFactory getWebSocketFactory()
{
return mWebSocketFactory;
}
/**
* Reset the proxy settings. To be concrete, parameter values are
* set as shown below.
*
*
*
*
*
* Name
* Value
* Description
*
*
*
*
* Secure
* {@code false}
* Use TLS to connect to the proxy server or not.
*
*
* Host
* {@code null}
* The host name of the proxy server.
*
*
* Port
* {@code -1}
* The port number of the proxy server.
*
*
* ID
* {@code null}
* The ID for authentication at the proxy server.
*
*
* Password
* {@code null}
* The password for authentication at the proxy server.
*
*
* Headers
* Cleared
* Additional HTTP headers passed to the proxy server.
*
*
* Server Names
* {@code null}
* Server names for SNI (Server Name Indication).
*
*
*
*
*
* @return
* {@code this} object.
*/
public ProxySettings reset()
{
mSecure = false;
mHost = null;
mPort = -1;
mId = null;
mPassword = null;
mHeaders.clear();
mServerNames = null;
return this;
}
/**
* Check whether use of TLS is enabled or disabled.
*
* @return
* {@code true} if TLS is used in the communication with
* the proxy server.
*/
public boolean isSecure()
{
return mSecure;
}
/**
* Enable or disable use of TLS.
*
* @param secure
* {@code true} to use TLS in the communication with
* the proxy server.
*
* @return
* {@code this} object.
*/
public ProxySettings setSecure(boolean secure)
{
mSecure = secure;
return this;
}
/**
* Get the host name of the proxy server.
*
*
* The default value is {@code null}. If this method returns
* a non-null value, it is used as the proxy server.
*
*
* @return
* The host name of the proxy server.
*/
public String getHost()
{
return mHost;
}
/**
* Set the host name of the proxy server.
*
*
* If a non-null value is set, it is used as the proxy server.
*
*
* @param host
* The host name of the proxy server.
*
* @return
* {@code this} object.
*/
public ProxySettings setHost(String host)
{
mHost = host;
return this;
}
/**
* Get the port number of the proxy server.
*
*
* The default value is {@code -1}. {@code -1} means that
* the default port number ({@code 80} for non-secure
* connections and {@code 443} for secure connections)
* should be used.
*
*
* @return
* The port number of the proxy server.
*/
public int getPort()
{
return mPort;
}
/**
* Set the port number of the proxy server.
*
*
* If {@code -1} is set, the default port number ({@code 80}
* for non-secure connections and {@code 443} for secure
* connections) is used.
*
*
* @param port
* The port number of the proxy server.
*
* @return
* {@code this} object.
*/
public ProxySettings setPort(int port)
{
mPort = port;
return this;
}
/**
* Get the ID for authentication at the proxy server.
*
*
* The default value is {@code null}. If this method returns
* a non-null value, it is used as the ID for authentication
* at the proxy server. To be concrete, the value is used to
* generate the value of Proxy-Authorization
header.
*
*
* @return
* The ID for authentication at the proxy server.
*/
public String getId()
{
return mId;
}
/**
* Set the ID for authentication at the proxy server.
*
*
* If a non-null value is set, it is used as the ID for
* authentication at the proxy server. To be concrete, the
* value is used to generate the value of Proxy-Authorization
header.
*
*
* @param id
* The ID for authentication at the proxy server.
*
* @return
* {@code this} object.
*/
public ProxySettings setId(String id)
{
mId = id;
return this;
}
/**
* Get the password for authentication at the proxy server.
*
* @return
* The password for authentication at the proxy server.
*/
public String getPassword()
{
return mPassword;
}
/**
* Set the password for authentication at the proxy server.
*
* @param password
* The password for authentication at the proxy server.
*
* @return
* {@code this} object.
*/
public ProxySettings setPassword(String password)
{
mPassword = password;
return this;
}
/**
* Set credentials for authentication at the proxy server.
* This method is an alias of {@link #setId(String) setId}{@code
* (id).}{@link #setPassword(String) setPassword}{@code
* (password)}.
*
* @param id
* The ID.
*
* @param password
* The password.
*
* @return
* {@code this} object.
*/
public ProxySettings setCredentials(String id, String password)
{
return setId(id).setPassword(password);
}
/**
* Set the proxy server by a URI. See the description of
* {@link #setServer(URI)} about how the parameters are updated.
*
* @param uri
* The URI of the proxy server. If {@code null} is given,
* none of the parameters are updated.
*
* @return
* {@code this} object.
*
* @throws IllegalArgumentException
* Failed to convert the given string to a {@link URI} instance.
*/
public ProxySettings setServer(String uri)
{
if (uri == null)
{
return this;
}
return setServer(URI.create(uri));
}
/**
* Set the proxy server by a URL. See the description of
* {@link #setServer(URI)} about how the parameters are updated.
*
* @param url
* The URL of the proxy server. If {@code null} is given,
* none of the parameters are updated.
*
* @return
* {@code this} object.
*
* @throws IllegalArgumentException
* Failed to convert the given URL to a {@link URI} instance.
*/
public ProxySettings setServer(URL url)
{
if (url == null)
{
return this;
}
try
{
return setServer(url.toURI());
}
catch (URISyntaxException e)
{
throw new IllegalArgumentException(e);
}
}
/**
* Set the proxy server by a URI. The parameters are updated as
* described below.
*
*
*
* - Secure
*
* If the URI contains the scheme part and its value is
* either {@code "http"} or {@code "https"} (case-insensitive),
* the {@code secure} parameter is updated to {@code false}
* or to {@code true} accordingly. In other cases, the parameter
* is not updated.
*
* - ID & Password
*
* If the URI contains the userinfo part and the ID embedded
* in the userinfo part is not an empty string, the {@code
* id} parameter and the {@code password} parameter are updated
* accordingly. In other cases, the parameters are not updated.
*
* - Host
*
* The {@code host} parameter is always updated by the given URI.
*
* - Port
*
* The {@code port} parameter is always updated by the given URI.
*
*
*
*
* @param uri
* The URI of the proxy server. If {@code null} is given,
* none of the parameters is updated.
*
* @return
* {@code this} object.
*/
public ProxySettings setServer(URI uri)
{
if (uri == null)
{
return this;
}
String scheme = uri.getScheme();
String userInfo = uri.getUserInfo();
String host = uri.getHost();
int port = uri.getPort();
return setServer(scheme, userInfo, host, port);
}
private ProxySettings setServer(String scheme, String userInfo, String host, int port)
{
setByScheme(scheme);
setByUserInfo(userInfo);
mHost = host;
mPort = port;
return this;
}
private void setByScheme(String scheme)
{
if ("http".equalsIgnoreCase(scheme))
{
mSecure = false;
}
else if ("https".equalsIgnoreCase(scheme))
{
mSecure = true;
}
}
private void setByUserInfo(String userInfo)
{
if (userInfo == null)
{
return;
}
String[] pair = userInfo.split(":", 2);
String id;
String pw;
switch (pair.length)
{
case 2:
id = pair[0];
pw = pair[1];
break;
case 1:
id = pair[0];
pw = null;
break;
default:
return;
}
if (id.length() == 0)
{
return;
}
mId = id;
mPassword = pw;
}
/**
* Get additional HTTP headers passed to the proxy server.
*
* @return
* Additional HTTP headers passed to the proxy server.
* The comparator of the returned map is {@link
* String#CASE_INSENSITIVE_ORDER}.
*/
public Map> getHeaders()
{
return mHeaders;
}
/**
* Add an additional HTTP header passed to the proxy server.
*
* @param name
* The name of an HTTP header (case-insensitive).
* If {@code null} or an empty string is given,
* nothing is added.
*
* @param value
* The value of the HTTP header.
*
* @return
* {@code this} object.
*/
public ProxySettings addHeader(String name, String value)
{
if (name == null || name.length() == 0)
{
return this;
}
List list = mHeaders.get(name);
if (list == null)
{
list = new ArrayList();
mHeaders.put(name, list);
}
list.add(value);
return this;
}
/**
* Get the socket factory that has been set by {@link
* #setSocketFactory(SocketFactory)}.
*
* @return
* The socket factory.
*/
public SocketFactory getSocketFactory()
{
return mSocketFactorySettings.getSocketFactory();
}
/**
* Set a socket factory.
*
* @param factory
* A socket factory.
*
* @return
* {@code this} instance.
*/
public ProxySettings setSocketFactory(SocketFactory factory)
{
mSocketFactorySettings.setSocketFactory(factory);
return this;
}
/**
* Get the SSL socket factory that has been set by {@link
* #setSSLSocketFactory(SSLSocketFactory)}.
*
* @return
* The SSL socket factory.
*/
public SSLSocketFactory getSSLSocketFactory()
{
return mSocketFactorySettings.getSSLSocketFactory();
}
/**
* Set an SSL socket factory.
*
* @param factory
* An SSL socket factory.
*
* @return
* {@code this} instance.
*/
public ProxySettings setSSLSocketFactory(SSLSocketFactory factory)
{
mSocketFactorySettings.setSSLSocketFactory(factory);
return this;
}
/**
* Get the SSL context that has been set by {@link #setSSLContext(SSLContext)}.
*
* @return
* The SSL context.
*/
public SSLContext getSSLContext()
{
return mSocketFactorySettings.getSSLContext();
}
/**
* Set an SSL context to get a socket factory.
*
* @param context
* An SSL context.
*
* @return
* {@code this} instance.
*/
public ProxySettings setSSLContext(SSLContext context)
{
mSocketFactorySettings.setSSLContext(context);
return this;
}
SocketFactory selectSocketFactory()
{
return mSocketFactorySettings.selectSocketFactory(mSecure);
}
/**
* Get server names for SNI (Server Name Indication).
*
* @return
* List of host names.
*
* @since 2.4
*/
public String[] getServerNames()
{
return mServerNames;
}
/**
* Set server names for SNI (Server Name Indication).
*
* If {@code setServerNames(List)} method of
* {@link javax.net.ssl.SSLParameters SSLParameters} class is available
* in the underlying system, the method is called to set up server names
* for SNI (Server Name Indication).
*
* @param serverNames
* List of host names.
*
* @return
* {@code this} object.
*
* @since 2.4
*/
public ProxySettings setServerNames(String[] serverNames)
{
mServerNames = serverNames;
return this;
}
/**
* Set a server name for SNI (Server Name Indication).
*
* This method internally creates a String array of size 1 which
* contains the given {@code serverName} and calls {@link
* #setServerNames(String[])}.
*
* @param serverName
* A host name.
*
* @return
* {@code this} object.
*
* @since 2.4
*/
public ProxySettings setServerName(String serverName)
{
return setServerNames(new String[] { serverName });
}
}