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