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 }