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   * <p>
46   * <p>
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       * <p>
99       * @exception 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      * <p>
118      * @param port The port to use for the socket.
119      * @exception 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      * <p>
139      * @param port The port to use for the socket.
140      * @param laddr  The local address to use.
141      * @exception 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      * If you call this method when the client socket is not open,
159      * a NullPointerException is thrown.
160      ***/
161     public void close()
162     {
163         if (_socket_ != null) {
164             _socket_.close();
165         }
166         _socket_ = null;
167         _isOpen_ = false;
168     }
169 
170 
171     /***
172      * Returns true if the client has a currently open socket.
173      * <p>
174      * @return True if the client has a curerntly open socket, false otherwise.
175      ***/
176     public boolean isOpen()
177     {
178         return _isOpen_;
179     }
180 
181 
182     /***
183      * Set the default timeout in milliseconds to use when opening a socket.
184      * After a call to open, the timeout for the socket is set using this value.
185      * This method should be used prior to a call to {@link #open open()}
186      * and should not be confused with {@link #setSoTimeout setSoTimeout()}
187      * which operates on the currently open socket.  _timeout_ contains
188      * the new timeout value.
189      * <p>
190      * @param timeout  The timeout in milliseconds to use for the datagram socket
191      *                 connection.
192      ***/
193     public void setDefaultTimeout(int timeout)
194     {
195         _timeout_ = timeout;
196     }
197 
198 
199     /***
200      * Returns the default timeout in milliseconds that is used when
201      * opening a socket.
202      * <p>
203      * @return The default timeout in milliseconds that is used when
204      *         opening a socket.
205      ***/
206     public int getDefaultTimeout()
207     {
208         return _timeout_;
209     }
210 
211 
212     /***
213      * Set the timeout in milliseconds of a currently open connection.
214      * Only call this method after a connection has been opened
215      * by {@link #open open()}.
216      * <p>
217      * @param timeout  The timeout in milliseconds to use for the currently
218      *                 open datagram socket connection.
219      ***/
220     public void setSoTimeout(int timeout) throws SocketException
221     {
222         _socket_.setSoTimeout(timeout);
223     }
224 
225 
226     /***
227      * Returns the timeout in milliseconds of the currently opened socket.
228      * If you call this method when the client socket is not open,
229      * a NullPointerException is thrown.
230      * <p>
231      * @return The timeout in milliseconds of the currently opened socket.
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      * <p>
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      * <p>
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      * <p>
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 }