1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.net;
19
20 import java.net.DatagramSocket;
21 import java.net.InetAddress;
22 import java.net.SocketException;
23
24 /***
25 * The DatagramSocketClient provides the basic operations that are required
26 * of client objects accessing datagram sockets. It is meant to be
27 * subclassed to avoid having to rewrite the same code over and over again
28 * to open a socket, close a socket, set timeouts, etc. Of special note
29 * is the {@link #setDatagramSocketFactory setDatagramSocketFactory }
30 * method, which allows you to control the type of DatagramSocket the
31 * DatagramSocketClient creates for network communications. This is
32 * especially useful for adding things like proxy support as well as better
33 * support for applets. For
34 * example, you could create a
35 * {@link org.apache.commons.net.DatagramSocketFactory}
36 * that
37 * requests browser security capabilities before creating a socket.
38 * All classes derived from DatagramSocketClient should use the
39 * {@link #_socketFactory_ _socketFactory_ } member variable to
40 * create DatagramSocket instances rather than instantiating
41 * them by directly invoking a constructor. By honoring this contract
42 * you guarantee that a user will always be able to provide his own
43 * Socket implementations by substituting his own SocketFactory.
44 * <p>
45 * <p>
46 * @author Daniel F. Savarese
47 * @see DatagramSocketFactory
48 ***/
49
50 public abstract class DatagramSocketClient
51 {
52 /***
53 * The default DatagramSocketFactory shared by all DatagramSocketClient
54 * instances.
55 ***/
56 private static final DatagramSocketFactory __DEFAULT_SOCKET_FACTORY =
57 new DefaultDatagramSocketFactory();
58
59 /*** The timeout to use after opening a socket. ***/
60 protected int _timeout_;
61
62 /*** The datagram socket used for the connection. ***/
63 protected DatagramSocket _socket_;
64
65 /***
66 * A status variable indicating if the client's socket is currently open.
67 ***/
68 protected boolean _isOpen_;
69
70 /*** The datagram socket's DatagramSocketFactory. ***/
71 protected DatagramSocketFactory _socketFactory_;
72
73 /***
74 * Default constructor for DatagramSocketClient. Initializes
75 * _socket_ to null, _timeout_ to 0, and _isOpen_ to false.
76 ***/
77 public DatagramSocketClient()
78 {
79 _socket_ = null;
80 _timeout_ = 0;
81 _isOpen_ = false;
82 _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
83 }
84
85
86 /***
87 * Opens a DatagramSocket on the local host at the first available port.
88 * Also sets the timeout on the socket to the default timeout set
89 * by {@link #setDefaultTimeout setDefaultTimeout() }.
90 * <p>
91 * _isOpen_ is set to true after calling this method and _socket_
92 * is set to the newly opened socket.
93 * <p>
94 * @exception SocketException If the socket could not be opened or the
95 * timeout could not be set.
96 ***/
97 public void open() throws SocketException
98 {
99 _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 }