aboutsummaryrefslogtreecommitdiff
path: root/src/com/kenai/jbosh/BOSHClientConfig.java
blob: 23915b6cc4e8946ba612c84692215283f0c30c3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
/*
 * 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;
    }

}