1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: SocketRequestInfo.java,v 1.8 2005/12/01 13:44:38 tanderson Exp $
44 */
45 package org.exolab.jms.net.socket;
46
47 import java.util.Map;
48
49 import org.exolab.jms.net.connector.URIRequestInfo;
50 import org.exolab.jms.net.connector.ResourceException;
51 import org.exolab.jms.net.uri.URI;
52 import org.exolab.jms.net.uri.URIHelper;
53 import org.exolab.jms.net.uri.InvalidURIException;
54 import org.exolab.jms.net.util.Properties;
55 import org.exolab.jms.net.orb.ORB;
56
57
58 /***
59 * Implementation of the {@link org.exolab.jms.net.connector.ConnectionRequestInfo}
60 * interface that enables socket based connectors to pass data across the
61 * connection request flow.
62 *
63 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
64 * @version $Revision: 1.8 $ $Date: 2005/12/01 13:44:38 $
65 */
66 public class SocketRequestInfo extends URIRequestInfo {
67
68 /***
69 * The alternative host for clients to connect to, if connections to {@link
70 * #getURI} fail. May be <code>null</code>.
71 */
72 private String _alternativeHost;
73
74 /***
75 * The maximum queue size for incoming connection indications (a request to
76 * connect). If a connection indication arrives when the queue is full, the
77 * connection is refused.
78 */
79 private int _connectionRequestQueueSize = 50;
80
81 /***
82 * Determines if connections should be accepted on all addresses, on a
83 * multi-homed host. If <code>true</code>, server sockets will accept
84 * connections on all local addresses. If <code>false</code>, only
85 * connections to a specified address will be accepted.
86 */
87 private boolean _bindAll = true;
88
89 /***
90 * Connection property name to indicate the alternative host to connect
91 * to, if a connection cannot be established to the primary host.
92 */
93 private static final String ALTERNATIVE_HOST = "alt";
94
95 /***
96 * Connection property name to indicate if connections should be accepted
97 * on all addresses, on a multi-homed host.
98 */
99 private static final String BIND_ALL = "bindAll";
100
101
102 /***
103 * Construct a new <code>SocketRequestInfo</code>.
104 *
105 * @param uri the URI
106 * @throws ResourceException if <code>uri</code> has an invalid query string
107 */
108 public SocketRequestInfo(URI uri) throws ResourceException {
109 super(URIHelper.getURISansQuery(uri));
110 init(uri);
111 }
112
113 /***
114 * Construct a new <code>SocketRequestInfo</code>.
115 *
116 * @param uri the URI
117 * @param properties the properties to populate this from
118 * @throws ResourceException if any of the properties are invalid
119 */
120 public SocketRequestInfo(URI uri, Properties properties)
121 throws ResourceException {
122 super(URIHelper.getURISansQuery(uri));
123 setBindAll(properties.getBoolean(BIND_ALL, _bindAll));
124 init(uri);
125 }
126
127 /***
128 * Sets the alternative host. This is used as an alternative address for
129 * clients to connect to, if connections to {@link #getURI} fail.
130 * <p/>
131 * This can be useful if the server is behind a NAT firewall, and clients
132 * need to connect from both outside and inside the firewall.
133 *
134 * @param host the alternative host. May be <code>null</code>
135 */
136 public void setAlternativeHost(String host) {
137 _alternativeHost = host;
138 }
139
140 /***
141 * Returns the alternative host.
142 *
143 * @return the alternative host, or <code>null</code> if none has been set.
144 */
145 public String getAlternativeHost() {
146 return _alternativeHost;
147 }
148
149 /***
150 * Helper to return the alternative URI. This is the URI returned by
151 * {@link #getURI} with the host set to {@link #getAlternativeHost}.
152 *
153 * @return the alternative URI, or <code>null</code> if the alternative
154 * host is not set.
155 * @throws ResourceException if the alternative URI is invalid
156 */
157 public URI getAlternativeURI() throws ResourceException {
158 URI result = null;
159 if (_alternativeHost != null) {
160 result = new URI(getURI());
161 try {
162 result.setHost(_alternativeHost);
163 } catch (URI.MalformedURIException exception) {
164 throw new ResourceException(exception);
165 }
166 }
167 return result;
168 }
169
170 /***
171 * Sets the maximum queue size for incoming connection indications (a
172 * request to connect). If a connection indication arrives when the queue is
173 * full, the connection is refused.
174 *
175 * @param size the queue size
176 */
177 public void setConnectionRequestQueueSize(int size) {
178 _connectionRequestQueueSize = size;
179 }
180
181 /***
182 * Returns the maximum queue size for incoming connection indications.
183 *
184 * @return the maximum queue size for incoming connection indications.
185 */
186 public int getConnectionRequestQueueSize() {
187 return _connectionRequestQueueSize;
188 }
189
190 /***
191 * Sets how socket connections should be accepted, on a multi-homed host.
192 *
193 * @param bindAll if <code>true</code>, server sockets will accept
194 * connections on all local addresses. If <code>false</code>,
195 * only connections to a specified address will be accepted.
196 */
197 public void setBindAll(boolean bindAll) {
198 _bindAll = bindAll;
199 }
200
201 /***
202 * Determines if socket connections should be accepted on all addresses, on
203 * a multi-homed host.
204 *
205 * @return <code>true</code> if server sockets should accept connections on
206 * all local addresses; otherwise <code>false</code>, indicating
207 * that only connections to a specified address will be accepted.
208 */
209 public boolean getBindAll() {
210 return _bindAll;
211 }
212
213 /***
214 * Helper to export this to a {@link Properties} instance.
215 *
216 * @param properties the properties to export to.
217 */
218 public void export(Properties properties) {
219 String uri = getURI().toString();
220 if (_alternativeHost != null) {
221 uri += "?" + ALTERNATIVE_HOST + "=" + _alternativeHost;
222 }
223 properties.set(ORB.PROVIDER_URI, uri);
224 properties.set(BIND_ALL, getBindAll());
225 }
226
227 /***
228 * Checks whether this instance is equal to another.
229 *
230 * @param other the object to compare
231 * @return <code>true</code> if the two instances are equal; otherwise
232 * <code>false</code>
233 */
234 public boolean equals(Object other) {
235 boolean equal = false;
236 if (other instanceof SocketRequestInfo && super.equals(other)) {
237 SocketRequestInfo info = (SocketRequestInfo) other;
238 if (equals(_alternativeHost, info._alternativeHost)
239 && _connectionRequestQueueSize
240 == info._connectionRequestQueueSize
241 && _bindAll == info._bindAll) {
242 equal = true;
243 }
244 }
245 return equal;
246 }
247
248 /***
249 * Helper to compare two objects for equality.
250 *
251 * @param o1 the first object to compare
252 * @param o2 the second object to compare
253 * @return <code>true</code> if the objects are equal, otherwise
254 * <code>false</code>
255 */
256 protected boolean equals(Object o1, Object o2) {
257 boolean equal = (o1 == null && o2 == null);
258 if (!equal) {
259 if (o1 != null && o1.equals(o2)) {
260 equal = true;
261 }
262 }
263 return equal;
264 }
265
266 /***
267 * Initialises this.
268 *
269 * @param uri the uri
270 * @throws ResourceException
271 */
272 private void init(URI uri) throws ResourceException {
273 String query = uri.getQueryString();
274 if (query != null) {
275 Map properties;
276 try {
277 properties = URIHelper.parseQuery(query);
278 } catch (InvalidURIException exception) {
279 throw new ResourceException(exception);
280 }
281 String host = (String) properties.get(ALTERNATIVE_HOST);
282 setAlternativeHost(host);
283 }
284 }
285
286 }