001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.net;
005:
006: import com.tc.exception.TCRuntimeException;
007: import com.tc.net.core.ConnectionInfo;
008: import com.tc.util.Assert;
009:
010: import java.net.InetAddress;
011: import java.net.UnknownHostException;
012:
013: /**
014: * An emulation (incomplete) of the java.net.InetSocketAddress class (which happens to only be available in 1.4
015: * runtimes) In the TC world, this class is used to describe a location (address + port) to connnect to, and/or listen
016: * on
017: *
018: * @author teck
019: */
020: public class TCSocketAddress {
021: /**
022: * Bytes for IPv4 wildcard address (ie. 0.0.0.0). This address is used to bind a listening socket to all available
023: * interfaces
024: */
025: private static final byte[] WILDCARD_BYTES = new byte[] { (byte) 0,
026: (byte) 0, (byte) 0, (byte) 0 };
027:
028: /**
029: * Bytes for the loopback adapator (ie. 127.0.0.1)
030: */
031: private static final byte[] LOOPBACK_BYTES = new byte[] {
032: (byte) 127, (byte) 0, (byte) 0, (byte) 1 };
033:
034: /**
035: * String form the loopback adaptor address (ie. 127.0.0.1)
036: */
037: public static final String LOOPBACK_IP = "127.0.0.1";
038:
039: /**
040: * String form of the wildcard IP address (ie. 0.0.0.0)
041: */
042: public static final String WILDCARD_IP = "0.0.0.0";
043:
044: /**
045: * java.net.InetAddress form of the wildcard IP address (ie. 0.0.0.0)
046: */
047: public static final InetAddress WILDCARD_ADDR;
048:
049: /**
050: * java.net.InetAddress form of the wildcard IP address (ie. 127.0.0.1)
051: */
052: public static final InetAddress LOOPBACK_ADDR;
053:
054: static {
055: try {
056: WILDCARD_ADDR = InetAddress.getByName(WILDCARD_IP);
057: } catch (UnknownHostException e) {
058: throw new TCRuntimeException(
059: "Cannot create InetAddress instance for "
060: + WILDCARD_IP);
061: }
062:
063: try {
064: LOOPBACK_ADDR = InetAddress.getByName(LOOPBACK_IP);
065: } catch (UnknownHostException e) {
066: throw new TCRuntimeException(
067: "Cannot create InetAddress instance for "
068: + LOOPBACK_IP);
069: }
070: }
071:
072: public static byte[] getLoopbackBytes() {
073: return (byte[]) LOOPBACK_BYTES.clone();
074: }
075:
076: public static byte[] getWilcardBytes() {
077: return (byte[]) WILDCARD_BYTES.clone();
078: }
079:
080: // TODO: add a constructor that takes the output of toStringForm() and
081: // reconsitutes a TCSocketAddress instance
082:
083: public TCSocketAddress(ConnectionInfo connInfo)
084: throws UnknownHostException {
085: this (connInfo.getHostname(), connInfo.getPort());
086: }
087:
088: /**
089: * Creates an address for localhost on the given port
090: *
091: * @param port the port number, can be zero
092: * @throws IllegalArgumentException if port is out of range (0 - 65535)
093: */
094: public TCSocketAddress(int port) {
095: this (LOOPBACK_ADDR, port);
096: }
097:
098: /**
099: * Creates an address for localhost on the given port
100: *
101: * @param port the port number, can be zero
102: * @throws UnknownHostException
103: * @throws IllegalArgumentException if port is out of range (0 - 65535)
104: * @throws UnknownHostException if the host name provided can not be resolved
105: */
106: public TCSocketAddress(String host, int port)
107: throws UnknownHostException {
108: this (InetAddress.getByName(host), port);
109: }
110:
111: /**
112: * Create an TCSocketAdress instance for the gven address on the given port
113: *
114: * @param addr the address to connect to. If null, this constructor behaves exactly like
115: * <code>TCSocketAddress(int port)</code>
116: * @param port the port number, can be zero
117: * @throws IllegalArgumentException if port is out of range (0 - 65535)
118: */
119: public TCSocketAddress(InetAddress addr, int port) {
120: if (!isValidPort(port)) {
121: throw new IllegalArgumentException("port (" + port
122: + ") is out of range (0 - 0xFFFF)");
123: }
124:
125: if (addr == null) {
126: try {
127: addr = InetAddress.getLocalHost();
128: } catch (UnknownHostException e) {
129: addr = LOOPBACK_ADDR;
130: }
131: }
132:
133: this .addr = addr;
134: this .port = port;
135:
136: Assert.eval(this .addr != null);
137: }
138:
139: public InetAddress getAddress() {
140: return addr;
141: }
142:
143: public int getPort() {
144: return port;
145: }
146:
147: public byte[] getAddressBytes() {
148: return addr.getAddress();
149: }
150:
151: public boolean equals(Object obj) {
152: if (obj instanceof TCSocketAddress) {
153: TCSocketAddress other = (TCSocketAddress) obj;
154: return ((this .port == other.port) && this .addr
155: .equals(other.addr));
156: }
157: return false;
158: }
159:
160: public int hashCode() {
161: if (addr == null) {
162: return super .hashCode();
163: }
164:
165: return addr.hashCode() + port;
166: }
167:
168: public String toString() {
169: return getStringForm();
170: }
171:
172: /**
173: * Returns a string description of this address instance in the following format: X.X.X.X:port where "X.X.X.X" is the
174: * IP address and "port" is the port number The only purpose of this method is to document the specific format as a
175: * contract. <code>toString()</code> is <b>not </b> required follow the same format
176: *
177: * @return string form of this address
178: */
179: public String getStringForm() {
180: StringBuffer buf = new StringBuffer();
181: buf.append(addr.getHostAddress()).append(":").append(port);
182: return buf.toString();
183: }
184:
185: public static boolean isValidPort(int port) {
186: return ((port >= 0) && (port <= 0xFFFF));
187: }
188:
189: private final InetAddress addr;
190: private final int port;
191: }
|