| /* |
| * Copyright 2009 Mike Cumings |
| * |
| * 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.kenai.jbosh; |
| |
| import java.net.URI; |
| import javax.net.ssl.SSLContext; |
| |
| /** |
| * BOSH client configuration information. Instances of this class contain |
| * all information necessary to establish connectivity with a remote |
| * connection manager. |
| * <p/> |
| * Instances of this class are immutable, thread-safe, |
| * and can be re-used to configure multiple client session instances. |
| */ |
| public final class BOSHClientConfig { |
| |
| /** |
| * Connection manager URI. |
| */ |
| private final URI uri; |
| |
| /** |
| * Target domain. |
| */ |
| private final String to; |
| |
| /** |
| * Client ID of this station. |
| */ |
| private final String from; |
| |
| /** |
| * Default XML language. |
| */ |
| private final String lang; |
| |
| /** |
| * Routing information for messages sent to CM. |
| */ |
| private final String route; |
| |
| /** |
| * Proxy host. |
| */ |
| private final String proxyHost; |
| |
| /** |
| * Proxy port. |
| */ |
| private final int proxyPort; |
| |
| /** |
| * SSL context. |
| */ |
| private final SSLContext sslContext; |
| |
| /** |
| * Flag indicating that compression should be attempted, if possible. |
| */ |
| private final boolean compressionEnabled; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // Classes: |
| |
| /** |
| * Class instance builder, after the builder pattern. This allows each |
| * {@code BOSHClientConfig} instance to be immutable while providing |
| * flexibility when building new {@code BOSHClientConfig} instances. |
| * <p/> |
| * Instances of this class are <b>not</b> thread-safe. If template-style |
| * use is desired, see the {@code create(BOSHClientConfig)} method. |
| */ |
| public static final class Builder { |
| // Required args |
| private final URI bURI; |
| private final String bDomain; |
| |
| // Optional args |
| private String bFrom; |
| private String bLang; |
| private String bRoute; |
| private String bProxyHost; |
| private int bProxyPort; |
| private SSLContext bSSLContext; |
| private Boolean bCompression; |
| |
| /** |
| * Creates a new builder instance, used to create instances of the |
| * {@code BOSHClientConfig} class. |
| * |
| * @param cmURI URI to use to contact the connection manager |
| * @param domain target domain to communicate with |
| */ |
| private Builder(final URI cmURI, final String domain) { |
| bURI = cmURI; |
| bDomain = domain; |
| } |
| |
| /** |
| * Creates a new builder instance, used to create instances of the |
| * {@code BOSHClientConfig} class. |
| * |
| * @param cmURI URI to use to contact the connection manager |
| * @param domain target domain to communicate with |
| * @return builder instance |
| */ |
| public static Builder create(final URI cmURI, final String domain) { |
| if (cmURI == null) { |
| throw(new IllegalArgumentException( |
| "Connection manager URI must not be null")); |
| } |
| if (domain == null) { |
| throw(new IllegalArgumentException( |
| "Target domain must not be null")); |
| } |
| String scheme = cmURI.getScheme(); |
| if (!("http".equals(scheme) || "https".equals(scheme))) { |
| throw(new IllegalArgumentException( |
| "Only 'http' and 'https' URI are allowed")); |
| } |
| return new Builder(cmURI, domain); |
| } |
| |
| /** |
| * Creates a new builder instance using the existing configuration |
| * provided as a starting point. |
| * |
| * @param cfg configuration to copy |
| * @return builder instance |
| */ |
| public static Builder create(final BOSHClientConfig cfg) { |
| Builder result = new Builder(cfg.getURI(), cfg.getTo()); |
| result.bFrom = cfg.getFrom(); |
| result.bLang = cfg.getLang(); |
| result.bRoute = cfg.getRoute(); |
| result.bProxyHost = cfg.getProxyHost(); |
| result.bProxyPort = cfg.getProxyPort(); |
| result.bSSLContext = cfg.getSSLContext(); |
| result.bCompression = cfg.isCompressionEnabled(); |
| return result; |
| } |
| |
| /** |
| * Set the ID of the client station, to be forwarded to the connection |
| * manager when new sessions are created. |
| * |
| * @param id client ID |
| * @return builder instance |
| */ |
| public Builder setFrom(final String id) { |
| if (id == null) { |
| throw(new IllegalArgumentException( |
| "Client ID must not be null")); |
| } |
| bFrom = id; |
| return this; |
| } |
| |
| /** |
| * Set the default language of any human-readable content within the |
| * XML. |
| * |
| * @param lang XML language ID |
| * @return builder instance |
| */ |
| public Builder setXMLLang(final String lang) { |
| if (lang == null) { |
| throw(new IllegalArgumentException( |
| "Default language ID must not be null")); |
| } |
| bLang = lang; |
| return this; |
| } |
| |
| /** |
| * Sets the destination server/domain that the client should connect to. |
| * Connection managers may be configured to enable sessions with more |
| * that one server in different domains. When requesting a session with |
| * such a "proxy" connection manager, a client should use this method to |
| * specify the server with which it wants to communicate. |
| * |
| * @param protocol connection protocol (e.g, "xmpp") |
| * @param host host or domain to be served by the remote server. Note |
| * that this is not necessarily the host name or domain name of the |
| * remote server. |
| * @param port port number of the remote server |
| * @return builder instance |
| */ |
| public Builder setRoute( |
| final String protocol, |
| final String host, |
| final int port) { |
| if (protocol == null) { |
| throw(new IllegalArgumentException("Protocol cannot be null")); |
| } |
| if (protocol.contains(":")) { |
| throw(new IllegalArgumentException( |
| "Protocol cannot contain the ':' character")); |
| } |
| if (host == null) { |
| throw(new IllegalArgumentException("Host cannot be null")); |
| } |
| if (host.contains(":")) { |
| throw(new IllegalArgumentException( |
| "Host cannot contain the ':' character")); |
| } |
| if (port <= 0) { |
| throw(new IllegalArgumentException("Port number must be > 0")); |
| } |
| bRoute = protocol + ":" + host + ":" + port; |
| return this; |
| } |
| |
| /** |
| * Specify the hostname and port of an HTTP proxy to connect through. |
| * |
| * @param hostName proxy hostname |
| * @param port proxy port number |
| * @return builder instance |
| */ |
| public Builder setProxy(final String hostName, final int port) { |
| if (hostName == null || hostName.length() == 0) { |
| throw(new IllegalArgumentException( |
| "Proxy host name cannot be null or empty")); |
| } |
| if (port <= 0) { |
| throw(new IllegalArgumentException( |
| "Proxy port must be > 0")); |
| } |
| bProxyHost = hostName; |
| bProxyPort = port; |
| return this; |
| } |
| |
| /** |
| * Set the SSL context to use for this session. This can be used |
| * to configure certificate-based authentication, etc.. |
| * |
| * @param ctx SSL context |
| * @return builder instance |
| */ |
| public Builder setSSLContext(final SSLContext ctx) { |
| if (ctx == null) { |
| throw(new IllegalArgumentException( |
| "SSL context cannot be null")); |
| } |
| bSSLContext = ctx; |
| return this; |
| } |
| |
| /** |
| * Set whether or not compression of the underlying data stream |
| * should be attempted. By default, compression is disabled. |
| * |
| * @param enabled set to {@code true} if compression should be |
| * attempted when possible, {@code false} to disable compression |
| * @return builder instance |
| */ |
| public Builder setCompressionEnabled(final boolean enabled) { |
| bCompression = Boolean.valueOf(enabled); |
| return this; |
| } |
| |
| /** |
| * Build the immutable object instance with the current configuration. |
| * |
| * @return BOSHClientConfig instance |
| */ |
| public BOSHClientConfig build() { |
| // Default XML language |
| String lang; |
| if (bLang == null) { |
| lang = "en"; |
| } else { |
| lang = bLang; |
| } |
| |
| // Default proxy port |
| int port; |
| if (bProxyHost == null) { |
| port = 0; |
| } else { |
| port = bProxyPort; |
| } |
| |
| // Default compression |
| boolean compression; |
| if (bCompression == null) { |
| compression = false; |
| } else { |
| compression = bCompression.booleanValue(); |
| } |
| |
| return new BOSHClientConfig( |
| bURI, |
| bDomain, |
| bFrom, |
| lang, |
| bRoute, |
| bProxyHost, |
| port, |
| bSSLContext, |
| compression); |
| } |
| |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // Constructor: |
| |
| /** |
| * Prevent direct construction. |
| * |
| * @param cURI URI of the connection manager to connect to |
| * @param cDomain the target domain of the first stream |
| * @param cFrom client ID |
| * @param cLang default XML language |
| * @param cRoute target route |
| * @param cProxyHost proxy host |
| * @param cProxyPort proxy port |
| * @param cSSLContext SSL context |
| * @param cCompression compression enabled flag |
| */ |
| private BOSHClientConfig( |
| final URI cURI, |
| final String cDomain, |
| final String cFrom, |
| final String cLang, |
| final String cRoute, |
| final String cProxyHost, |
| final int cProxyPort, |
| final SSLContext cSSLContext, |
| final boolean cCompression) { |
| uri = cURI; |
| to = cDomain; |
| from = cFrom; |
| lang = cLang; |
| route = cRoute; |
| proxyHost = cProxyHost; |
| proxyPort = cProxyPort; |
| sslContext = cSSLContext; |
| compressionEnabled = cCompression; |
| } |
| |
| /** |
| * Get the URI to use to contact the connection manager. |
| * |
| * @return connection manager URI. |
| */ |
| public URI getURI() { |
| return uri; |
| } |
| |
| /** |
| * Get the ID of the target domain. |
| * |
| * @return domain id |
| */ |
| public String getTo() { |
| return to; |
| } |
| |
| /** |
| * Get the ID of the local client. |
| * |
| * @return client id, or {@code null} |
| */ |
| public String getFrom() { |
| return from; |
| } |
| |
| /** |
| * Get the default language of any human-readable content within the |
| * XML. Defaults to "en". |
| * |
| * @return XML language ID |
| */ |
| public String getLang() { |
| return lang; |
| } |
| |
| /** |
| * Get the routing information for messages sent to the CM. |
| * |
| * @return route attribute string, or {@code null} if no routing |
| * info was provided. |
| */ |
| public String getRoute() { |
| return route; |
| } |
| |
| /** |
| * Get the HTTP proxy host to use. |
| * |
| * @return proxy host, or {@code null} if no proxy information was specified |
| */ |
| public String getProxyHost() { |
| return proxyHost; |
| } |
| |
| /** |
| * Get the HTTP proxy port to use. |
| * |
| * @return proxy port, or 0 if no proxy information was specified |
| */ |
| public int getProxyPort() { |
| return proxyPort; |
| } |
| |
| /** |
| * Get the SSL context to use for this session. |
| * |
| * @return SSL context instance to use, or {@code null} if no |
| * context instance was provided. |
| */ |
| public SSLContext getSSLContext() { |
| return sslContext; |
| } |
| |
| /** |
| * Determines whether or not compression of the underlying data stream |
| * should be attempted/allowed. Defaults to {@code false}. |
| * |
| * @return {@code true} if compression should be attempted, {@code false} |
| * if compression is disabled or was not specified |
| */ |
| boolean isCompressionEnabled() { |
| return compressionEnabled; |
| } |
| |
| } |