View Javadoc
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  import java.nio.charset.Charset;
24  
25  /***
26   * The DatagramSocketClient provides the basic operations that are required
27   * of client objects accessing datagram sockets.  It is meant to be
28   * subclassed to avoid having to rewrite the same code over and over again
29   * to open a socket, close a socket, set timeouts, etc.  Of special note
30   * is the {@link #setDatagramSocketFactory  setDatagramSocketFactory }
31   * method, which allows you to control the type of DatagramSocket the
32   * DatagramSocketClient creates for network communications.  This is
33   * especially useful for adding things like proxy support as well as better
34   * support for applets.  For
35   * example, you could create a
36   * {@link org.apache.commons.net.DatagramSocketFactory}
37   *  that
38   * requests browser security capabilities before creating a socket.
39   * All classes derived from DatagramSocketClient should use the
40   * {@link #_socketFactory_  _socketFactory_ } member variable to
41   * create DatagramSocket instances rather than instantiating
42   * them by directly invoking a constructor.  By honoring this contract
43   * you guarantee that a user will always be able to provide his own
44   * Socket implementations by substituting his own SocketFactory.
45   *
46   *
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      /**
60       * Charset to use for byte IO.
61       */
62      private Charset charset = Charset.defaultCharset();
63  
64      /*** The timeout to use after opening a socket. ***/
65      protected int _timeout_;
66  
67      /*** The datagram socket used for the connection. ***/
68      protected DatagramSocket _socket_;
69  
70      /***
71       * A status variable indicating if the client's socket is currently open.
72       ***/
73      protected boolean _isOpen_;
74  
75      /*** The datagram socket's DatagramSocketFactory. ***/
76      protected DatagramSocketFactory _socketFactory_;
77  
78      /***
79       * Default constructor for DatagramSocketClient.  Initializes
80       * _socket_ to null, _timeout_ to 0, and _isOpen_ to false.
81       ***/
82      public DatagramSocketClient()
83      {
84          _socket_ = null;
85          _timeout_ = 0;
86          _isOpen_ = false;
87          _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
88      }
89  
90  
91      /***
92       * Opens a DatagramSocket on the local host at the first available port.
93       * Also sets the timeout on the socket to the default timeout set
94       * by {@link #setDefaultTimeout  setDefaultTimeout() }.
95       * <p>
96       * _isOpen_ is set to true after calling this method and _socket_
97       * is set to the newly opened socket.
98       *
99       * @throws SocketException If the socket could not be opened or the
100      *   timeout could not be set.
101      ***/
102     public void open() throws SocketException
103     {
104         _socket_ = _socketFactory_.createDatagramSocket();
105         _socket_.setSoTimeout(_timeout_);
106         _isOpen_ = true;
107     }
108 
109 
110     /***
111      * Opens a DatagramSocket on the local host at a specified port.
112      * Also sets the timeout on the socket to the default timeout set
113      * by {@link #setDefaultTimeout  setDefaultTimeout() }.
114      * <p>
115      * _isOpen_ is set to true after calling this method and _socket_
116      * is set to the newly opened socket.
117      *
118      * @param port The port to use for the socket.
119      * @throws SocketException If the socket could not be opened or the
120      *   timeout could not be set.
121      ***/
122     public void open(int port) throws SocketException
123     {
124         _socket_ = _socketFactory_.createDatagramSocket(port);
125         _socket_.setSoTimeout(_timeout_);
126         _isOpen_ = true;
127     }
128 
129 
130     /***
131      * Opens a DatagramSocket at the specified address on the local host
132      * at a specified port.
133      * Also sets the timeout on the socket to the default timeout set
134      * by {@link #setDefaultTimeout  setDefaultTimeout() }.
135      * <p>
136      * _isOpen_ is set to true after calling this method and _socket_
137      * is set to the newly opened socket.
138      *
139      * @param port The port to use for the socket.
140      * @param laddr  The local address to use.
141      * @throws SocketException If the socket could not be opened or the
142      *   timeout could not be set.
143      ***/
144     public void open(int port, InetAddress laddr) throws SocketException
145     {
146         _socket_ = _socketFactory_.createDatagramSocket(port, laddr);
147         _socket_.setSoTimeout(_timeout_);
148         _isOpen_ = true;
149     }
150 
151 
152 
153     /***
154      * Closes the DatagramSocket used for the connection.
155      * You should call this method after you've finished using the class
156      * instance and also before you call {@link #open open() }
157      * again.   _isOpen_ is set to false and  _socket_ is set to null.
158      ***/
159     public void close()
160     {
161         if (_socket_ != null) {
162             _socket_.close();
163         }
164         _socket_ = null;
165         _isOpen_ = false;
166     }
167 
168 
169     /***
170      * Returns true if the client has a currently open socket.
171      *
172      * @return True if the client has a currently open socket, false otherwise.
173      ***/
174     public boolean isOpen()
175     {
176         return _isOpen_;
177     }
178 
179 
180     /***
181      * Set the default timeout in milliseconds to use when opening a socket.
182      * After a call to open, the timeout for the socket is set using this value.
183      * This method should be used prior to a call to {@link #open open()}
184      * and should not be confused with {@link #setSoTimeout setSoTimeout()}
185      * which operates on the currently open socket.  _timeout_ contains
186      * the new timeout value.
187      *
188      * @param timeout  The timeout in milliseconds to use for the datagram socket
189      *                 connection.
190      ***/
191     public void setDefaultTimeout(int timeout)
192     {
193         _timeout_ = timeout;
194     }
195 
196 
197     /***
198      * Returns the default timeout in milliseconds that is used when
199      * opening a socket.
200      *
201      * @return The default timeout in milliseconds that is used when
202      *         opening a socket.
203      ***/
204     public int getDefaultTimeout()
205     {
206         return _timeout_;
207     }
208 
209 
210     /***
211      * Set the timeout in milliseconds of a currently open connection.
212      * Only call this method after a connection has been opened
213      * by {@link #open open()}.
214      *
215      * @param timeout  The timeout in milliseconds to use for the currently
216      *                 open datagram socket connection.
217      * @throws SocketException if an error setting the timeout
218      ***/
219     public void setSoTimeout(int timeout) throws SocketException
220     {
221         _socket_.setSoTimeout(timeout);
222     }
223 
224 
225     /***
226      * Returns the timeout in milliseconds of the currently opened socket.
227      * If you call this method when the client socket is not open,
228      * a NullPointerException is thrown.
229      *
230      * @return The timeout in milliseconds of the currently opened socket.
231      * @throws SocketException if an error getting the timeout
232      ***/
233     public int getSoTimeout() throws SocketException
234     {
235         return _socket_.getSoTimeout();
236     }
237 
238 
239     /***
240      * Returns the port number of the open socket on the local host used
241      * for the connection.  If you call this method when the client socket
242      * is not open, a NullPointerException is thrown.
243      *
244      * @return The port number of the open socket on the local host used
245      *         for the connection.
246      ***/
247     public int getLocalPort()
248     {
249         return _socket_.getLocalPort();
250     }
251 
252 
253     /***
254      * Returns the local address to which the client's socket is bound.
255      * If you call this method when the client socket is not open, a
256      * NullPointerException is thrown.
257      *
258      * @return The local address to which the client's socket is bound.
259      ***/
260     public InetAddress getLocalAddress()
261     {
262         return _socket_.getLocalAddress();
263     }
264 
265 
266     /***
267      * Sets the DatagramSocketFactory used by the DatagramSocketClient
268      * to open DatagramSockets.  If the factory value is null, then a default
269      * factory is used (only do this to reset the factory after having
270      * previously altered it).
271      *
272      * @param factory  The new DatagramSocketFactory the DatagramSocketClient
273      * should use.
274      ***/
275     public void setDatagramSocketFactory(DatagramSocketFactory factory)
276     {
277         if (factory == null) {
278             _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
279         } else {
280             _socketFactory_ = factory;
281         }
282     }
283 
284     /**
285      * Gets the charset name.
286      *
287      * @return the charset name.
288      * @since 3.3
289      * TODO Will be deprecated once the code requires Java 1.6 as a mininmum
290      */
291     public String getCharsetName() {
292         return charset.name();
293     }
294 
295     /**
296      * Gets the charset.
297      *
298      * @return the charset.
299      * @since 3.3
300      */
301     public Charset getCharset() {
302         return charset;
303     }
304 
305     /**
306      * Sets the charset.
307      *
308      * @param charset the charset.
309      * @since 3.3
310      */
311     public void setCharset(Charset charset) {
312         this.charset = charset;
313     }
314 }