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 }