001 /* 002 * Copyright 2001-2005 The Apache Software Foundation 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.apache.commons.net; 017 018 import java.net.DatagramSocket; 019 import java.net.InetAddress; 020 import java.net.SocketException; 021 022 /*** 023 * The DatagramSocketClient provides the basic operations that are required 024 * of client objects accessing datagram sockets. It is meant to be 025 * subclassed to avoid having to rewrite the same code over and over again 026 * to open a socket, close a socket, set timeouts, etc. Of special note 027 * is the {@link #setDatagramSocketFactory setDatagramSocketFactory } 028 * method, which allows you to control the type of DatagramSocket the 029 * DatagramSocketClient creates for network communications. This is 030 * especially useful for adding things like proxy support as well as better 031 * support for applets. For 032 * example, you could create a 033 * {@link org.apache.commons.net.DatagramSocketFactory} 034 * that 035 * requests browser security capabilities before creating a socket. 036 * All classes derived from DatagramSocketClient should use the 037 * {@link #_socketFactory_ _socketFactory_ } member variable to 038 * create DatagramSocket instances rather than instantiating 039 * them by directly invoking a constructor. By honoring this contract 040 * you guarantee that a user will always be able to provide his own 041 * Socket implementations by substituting his own SocketFactory. 042 * <p> 043 * <p> 044 * @author Daniel F. Savarese 045 * @see DatagramSocketFactory 046 ***/ 047 048 public abstract class DatagramSocketClient 049 { 050 /*** 051 * The default DatagramSocketFactory shared by all DatagramSocketClient 052 * instances. 053 ***/ 054 private static final DatagramSocketFactory __DEFAULT_SOCKET_FACTORY = 055 new DefaultDatagramSocketFactory(); 056 057 /*** The timeout to use after opening a socket. ***/ 058 protected int _timeout_; 059 060 /*** The datagram socket used for the connection. ***/ 061 protected DatagramSocket _socket_; 062 063 /*** 064 * A status variable indicating if the client's socket is currently open. 065 ***/ 066 protected boolean _isOpen_; 067 068 /*** The datagram socket's DatagramSocketFactory. ***/ 069 protected DatagramSocketFactory _socketFactory_; 070 071 /*** 072 * Default constructor for DatagramSocketClient. Initializes 073 * _socket_ to null, _timeout_ to 0, and _isOpen_ to false. 074 ***/ 075 public DatagramSocketClient() 076 { 077 _socket_ = null; 078 _timeout_ = 0; 079 _isOpen_ = false; 080 _socketFactory_ = __DEFAULT_SOCKET_FACTORY; 081 } 082 083 084 /*** 085 * Opens a DatagramSocket on the local host at the first available port. 086 * Also sets the timeout on the socket to the default timeout set 087 * by {@link #setDefaultTimeout setDefaultTimeout() }. 088 * <p> 089 * _isOpen_ is set to true after calling this method and _socket_ 090 * is set to the newly opened socket. 091 * <p> 092 * @exception SocketException If the socket could not be opened or the 093 * timeout could not be set. 094 ***/ 095 public void open() throws SocketException 096 { 097 _socket_ = _socketFactory_.createDatagramSocket(); 098 _socket_.setSoTimeout(_timeout_); 099 _isOpen_ = true; 100 } 101 102 103 /*** 104 * Opens a DatagramSocket on the local host at a specified port. 105 * Also sets the timeout on the socket to the default timeout set 106 * by {@link #setDefaultTimeout setDefaultTimeout() }. 107 * <p> 108 * _isOpen_ is set to true after calling this method and _socket_ 109 * is set to the newly opened socket. 110 * <p> 111 * @param port The port to use for the socket. 112 * @exception SocketException If the socket could not be opened or the 113 * timeout could not be set. 114 ***/ 115 public void open(int port) throws SocketException 116 { 117 _socket_ = _socketFactory_.createDatagramSocket(port); 118 _socket_.setSoTimeout(_timeout_); 119 _isOpen_ = true; 120 } 121 122 123 /*** 124 * Opens a DatagramSocket at the specified address on the local host 125 * at a specified port. 126 * Also sets the timeout on the socket to the default timeout set 127 * by {@link #setDefaultTimeout setDefaultTimeout() }. 128 * <p> 129 * _isOpen_ is set to true after calling this method and _socket_ 130 * is set to the newly opened socket. 131 * <p> 132 * @param port The port to use for the socket. 133 * @param laddr The local address to use. 134 * @exception SocketException If the socket could not be opened or the 135 * timeout could not be set. 136 ***/ 137 public void open(int port, InetAddress laddr) throws SocketException 138 { 139 _socket_ = _socketFactory_.createDatagramSocket(port, laddr); 140 _socket_.setSoTimeout(_timeout_); 141 _isOpen_ = true; 142 } 143 144 145 146 /*** 147 * Closes the DatagramSocket used for the connection. 148 * You should call this method after you've finished using the class 149 * instance and also before you call {@link #open open() } 150 * again. _isOpen_ is set to false and _socket_ is set to null. 151 * If you call this method when the client socket is not open, 152 * a NullPointerException is thrown. 153 ***/ 154 public void close() 155 { 156 _socket_.close(); 157 _socket_ = null; 158 _isOpen_ = false; 159 } 160 161 162 /*** 163 * Returns true if the client has a currently open socket. 164 * <p> 165 * @return True if the client has a curerntly open socket, false otherwise. 166 ***/ 167 public boolean isOpen() 168 { 169 return _isOpen_; 170 } 171 172 173 /*** 174 * Set the default timeout in milliseconds to use when opening a socket. 175 * After a call to open, the timeout for the socket is set using this value. 176 * This method should be used prior to a call to {@link #open open()} 177 * and should not be confused with {@link #setSoTimeout setSoTimeout()} 178 * which operates on the currently open socket. _timeout_ contains 179 * the new timeout value. 180 * <p> 181 * @param timeout The timeout in milliseconds to use for the datagram socket 182 * connection. 183 ***/ 184 public void setDefaultTimeout(int timeout) 185 { 186 _timeout_ = timeout; 187 } 188 189 190 /*** 191 * Returns the default timeout in milliseconds that is used when 192 * opening a socket. 193 * <p> 194 * @return The default timeout in milliseconds that is used when 195 * opening a socket. 196 ***/ 197 public int getDefaultTimeout() 198 { 199 return _timeout_; 200 } 201 202 203 /*** 204 * Set the timeout in milliseconds of a currently open connection. 205 * Only call this method after a connection has been opened 206 * by {@link #open open()}. 207 * <p> 208 * @param timeout The timeout in milliseconds to use for the currently 209 * open datagram socket connection. 210 ***/ 211 public void setSoTimeout(int timeout) throws SocketException 212 { 213 _socket_.setSoTimeout(timeout); 214 } 215 216 217 /*** 218 * Returns the timeout in milliseconds of the currently opened socket. 219 * If you call this method when the client socket is not open, 220 * a NullPointerException is thrown. 221 * <p> 222 * @return The timeout in milliseconds of the currently opened socket. 223 ***/ 224 public int getSoTimeout() throws SocketException 225 { 226 return _socket_.getSoTimeout(); 227 } 228 229 230 /*** 231 * Returns the port number of the open socket on the local host used 232 * for the connection. If you call this method when the client socket 233 * is not open, a NullPointerException is thrown. 234 * <p> 235 * @return The port number of the open socket on the local host used 236 * for the connection. 237 ***/ 238 public int getLocalPort() 239 { 240 return _socket_.getLocalPort(); 241 } 242 243 244 /*** 245 * Returns the local address to which the client's socket is bound. 246 * If you call this method when the client socket is not open, a 247 * NullPointerException is thrown. 248 * <p> 249 * @return The local address to which the client's socket is bound. 250 ***/ 251 public InetAddress getLocalAddress() 252 { 253 return _socket_.getLocalAddress(); 254 } 255 256 257 /*** 258 * Sets the DatagramSocketFactory used by the DatagramSocketClient 259 * to open DatagramSockets. If the factory value is null, then a default 260 * factory is used (only do this to reset the factory after having 261 * previously altered it). 262 * <p> 263 * @param factory The new DatagramSocketFactory the DatagramSocketClient 264 * should use. 265 ***/ 266 public void setDatagramSocketFactory(DatagramSocketFactory factory) 267 { 268 if (factory == null) 269 _socketFactory_ = __DEFAULT_SOCKET_FACTORY; 270 else 271 _socketFactory_ = factory; 272 } 273 }