rocks.xmpp.core.session.ConnectionConfiguration Maven / Gradle / Ivy
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2016 Christian Schudt
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package rocks.xmpp.core.session;
import rocks.xmpp.extensions.compress.CompressionMethod;
import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.net.Proxy;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* A base class for connection configurations.
*
* All connection methods have a few properties in common, which are abstracted in this class.
* Among these common properties are hostname, port, proxy, security settings and a timeout.
*
* @author Christian Schudt
* @see Connection
*/
public abstract class ConnectionConfiguration {
private final String hostname;
private final int port;
private final Proxy proxy;
private final boolean secure;
private final SSLContext sslContext;
private final HostnameVerifier hostnameVerifier;
private final int connectTimeout;
private final List compressionMethods;
protected ConnectionConfiguration(Builder extends Builder> builder) {
this.hostname = builder.hostname;
this.port = builder.port;
this.proxy = builder.proxy;
this.secure = builder.secure;
this.sslContext = builder.sslContext;
this.hostnameVerifier = builder.hostnameVerifier;
this.connectTimeout = builder.connectTimeout;
this.compressionMethods = builder.compressionMethods;
}
/**
* A factory method to create the connection.
*
* @param xmppSession The XMPP session, which is associated with the connection.
* @return The connection.
*/
public abstract Connection createConnection(XmppSession xmppSession);
/**
* Gets the hostname.
*
* @return The hostname.
*/
public final String getHostname() {
return hostname;
}
/**
* Gets the port.
*
* @return The port.
*/
public final int getPort() {
return port;
}
/**
* Gets the proxy.
*
* @return The proxy.
*/
public final Proxy getProxy() {
return proxy;
}
/**
* Indicates whether the connection is secured by SSL.
*
* @return If the connection is to be secured.
* @see Builder#secure(boolean)
*/
public final boolean isSecure() {
return secure;
}
/**
* Gets the SSL context.
*
* @return The SSL context.
*/
public final SSLContext getSSLContext() {
return sslContext;
}
/**
* Gets the hostname verifier.
*
* @return The hostname verifier.
*/
public final HostnameVerifier getHostnameVerifier() {
return hostnameVerifier;
}
/**
* Gets the timeout for connection establishment.
*
* @return The timeout.
*/
public final int getConnectTimeout() {
return connectTimeout;
}
/**
* Gets the compression methods.
*
* @return The compression methods.
*/
public final List getCompressionMethods() {
return compressionMethods;
}
@Override
public String toString() {
return hostname + ':' + port;
}
/**
* An abstract builder class for building immutable configuration objects.
*
* @param The concrete builder class.
*/
public abstract static class Builder> {
protected String hostname;
protected int port;
protected Proxy proxy;
protected boolean secure;
protected SSLContext sslContext;
protected HostnameVerifier hostnameVerifier;
protected int connectTimeout;
protected List compressionMethods = Collections.emptyList();
protected Builder() {
}
/**
* Returns an instance of the concrete builder.
*
* @return The concrete builder.
*/
protected abstract T self();
/**
* Sets the hostname.
*
* @param hostname The hostname.
* @return The builder.
*/
public final T hostname(String hostname) {
this.hostname = hostname;
return self();
}
/**
* Sets the port.
*
* @param port The port.
* @return The builder.
*/
public final T port(int port) {
this.port = port;
return self();
}
/**
* Sets the proxy, e.g. if you are behind a HTTP proxy and use a BOSH connection.
*
* @param proxy The proxy.
* @return The builder.
*/
public final T proxy(Proxy proxy) {
this.proxy = proxy;
return self();
}
/**
* Sets whether the connection is secured via SSL.
*
* A standard TCP connection starts with a plain socket and negotiates a secure SSL connection during stream negotiation via 'StartTLS'.
* Hence, setting {@code secure(true)} means, you start with a plain socket and upgrade it to a secure socket during XMPP negotiation.
*
* Setting {@code secure(false)} means, you start with plain socket and won't upgrade to a secure socket.
* However, some servers require that the client secures the connection, in which case an exception is thrown during connecting.
*
* If your server expects the connection to be secured immediately (often on port 5223), you should {@linkplain rocks.xmpp.core.session.TcpConnectionConfiguration.Builder#socketFactory(SocketFactory) set a custom SSL socket factory}.
*
* See RFC 6120 § 5. STARTTLS Negotiation for further information.
*
* HTTP (BOSH) and WebSocket connections provide TLS outside of the XMPP layer, i.e. it's not negotiated in XMPP.
* Setting {@code secure(true)} for these connection methods means the connection connects via {@code https} or {@code wss} respectively.
*
* If you set this to {@code true}, you should also {@linkplain #sslContext(SSLContext) set} an {@link SSLContext}. Otherwise {@code SSLContext.getDefault()} is used.
*
* @param secure If the connection is secured via SSL.
* @return The builder.
* @see #sslContext(SSLContext)
*/
public final T secure(boolean secure) {
this.secure = secure;
return self();
}
/**
* Sets a custom SSL context, used to secure the connection.
* This SSL context only takes effect, when setting {@code secure(true)}.
*
* @param sslContext The SSL context.
* @return The builder.
* @see #secure(boolean)
*/
public final T sslContext(SSLContext sslContext) {
this.sslContext = sslContext;
return self();
}
/**
* Sets an optional hostname verifier, used to verify the hostname in the certificate presented by the server.
* If no verifier is set, the hostname is verified nonetheless using the default.
*
* @param hostnameVerifier The hostname verifier.
* @return The builder.
*/
public final T hostnameVerifier(HostnameVerifier hostnameVerifier) {
this.hostnameVerifier = hostnameVerifier;
return self();
}
/**
* Sets a timeout for the connection establishment.
*
* Connecting to a XMPP server involves multiple steps:
*
* - DNS lookup
* - Connection establishment of the underlying transport (e.g. TCP or HTTP)
* - XMPP stream negotiation
*
* This timeout is only used for DNS lookup (which is not used in all cases) and for connection establishment of the underlying transport (e.g. for a socket connection), but not for stream negotiation.
* Therefore it does not reflect how long the whole connection process may take, but should be understood as hint for establishing the underlying XMPP transport.
*
* XMPP stream negotiation is configured via {@link rocks.xmpp.core.session.XmppSessionConfiguration.Builder#defaultResponseTimeout(java.time.Duration)}
*
* @param connectTimeout The timeout in milliseconds.
* @return The builder.
* @throws IllegalArgumentException If the timeout is negative.
* @see XmppSession#connect()
*/
public final T connectTimeout(int connectTimeout) {
if (connectTimeout < 0) {
throw new IllegalArgumentException("connectionTimeout cannot be negative.");
}
this.connectTimeout = connectTimeout;
return self();
}
/**
* Sets the compression method.
*
* @param compressionMethods The compression methods.
* @return The builder.
* @see CompressionMethod#ZLIB
* @see CompressionMethod#GZIP
* @see CompressionMethod#DEFLATE
*/
public final T compressionMethods(CompressionMethod... compressionMethods) {
this.compressionMethods = Arrays.asList(compressionMethods);
return self();
}
/**
* Builds the connection configuration.
*
* @return The concrete connection configuration.
*/
public abstract ConnectionConfiguration build();
}
}