    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     * @see DatagramSocketFactory
    047     ***/
    048
    049    public abstract class DatagramSocketClient
    050    {
    051        /***
    052         * The default DatagramSocketFactory shared by all DatagramSocketClient
    053         * instances.
    054         ***/
    055        private static final DatagramSocketFactory __DEFAULT_SOCKET_FACTORY =
    056            new DefaultDatagramSocketFactory();
    057
    058        /*** The timeout to use after opening a socket. ***/
    059        protected int _timeout_;
    060
    061        /*** The datagram socket used for the connection. ***/
    062        protected DatagramSocket _socket_;
    063
    064        /***
    065         * A status variable indicating if the client's socket is currently open.
    066         ***/
    067        protected boolean _isOpen_;
    068
    069        /*** The datagram socket's DatagramSocketFactory. ***/
    070        protected DatagramSocketFactory _socketFactory_;
    071
    072        /***
    073         * Default constructor for DatagramSocketClient.  Initializes
    074         * _socket_ to null, _timeout_ to 0, and _isOpen_ to false.
    075         ***/
    076        public DatagramSocketClient()
    077        {
    078            _socket_ = null;
    079            _timeout_ = 0;
    080            _isOpen_ = false;
    081            _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
    082        }
    083
    084
    085        /***
    086         * Opens a DatagramSocket on the local host at the first available port.
    087         * Also sets the timeout on the socket to the default timeout set
    088         * by {@link #setDefaultTimeout  setDefaultTimeout() }.
    089         * <p>
    090         * _isOpen_ is set to true after calling this method and _socket_
    091         * is set to the newly opened socket.
    092         * <p>
    093         * @exception SocketException If the socket could not be opened or the
    094         *   timeout could not be set.
    095         ***/
    096        public void open() throws SocketException
    097        {
    098            _socket_ = _socketFactory_.createDatagramSocket();
    099            _socket_.setSoTimeout(_timeout_);
    100            _isOpen_ = true;
    101        }
    102
    103
    104        /***
    105         * Opens a DatagramSocket on the local host at a specified port.
    106         * Also sets the timeout on the socket to the default timeout set
    107         * by {@link #setDefaultTimeout  setDefaultTimeout() }.
    108         * <p>
    109         * _isOpen_ is set to true after calling this method and _socket_
    110         * is set to the newly opened socket.
    111         * <p>
    112         * @param port The port to use for the socket.
    113         * @exception SocketException If the socket could not be opened or the
    114         *   timeout could not be set.
    115         ***/
    116        public void open(int port) throws SocketException
    117        {
    118            _socket_ = _socketFactory_.createDatagramSocket(port);
    119            _socket_.setSoTimeout(_timeout_);
    120            _isOpen_ = true;
    121        }
    122
    123
    124        /***
    125         * Opens a DatagramSocket at the specified address on the local host
    126         * at a specified port.
    127         * Also sets the timeout on the socket to the default timeout set
    128         * by {@link #setDefaultTimeout  setDefaultTimeout() }.
    129         * <p>
    130         * _isOpen_ is set to true after calling this method and _socket_
    131         * is set to the newly opened socket.
    132         * <p>
    133         * @param port The port to use for the socket.
    134         * @param laddr  The local address to use.
    135         * @exception SocketException If the socket could not be opened or the
    136         *   timeout could not be set.
    137         ***/
    138        public void open(int port, InetAddress laddr) throws SocketException
    139        {
    140            _socket_ = _socketFactory_.createDatagramSocket(port, laddr);
    141            _socket_.setSoTimeout(_timeout_);
    142            _isOpen_ = true;
    143        }
    144
    145
    146
    147        /***
    148         * Closes the DatagramSocket used for the connection.
    149         * You should call this method after you've finished using the class
    150         * instance and also before you call {@link #open open() }
    151         * again.   _isOpen_ is set to false and  _socket_ is set to null.
    152         * If you call this method when the client socket is not open,
    153         * a NullPointerException is thrown.
    154         ***/
    155        public void close()
    156        {
    157            if (_socket_ != null) {
    158                _socket_.close();
    159            }
    160            _socket_ = null;
    161            _isOpen_ = false;
    162        }
    163
    164
    165        /***
    166         * Returns true if the client has a currently open socket.
    167         * <p>
    168         * @return True if the client has a curerntly open socket, false otherwise.
    169         ***/
    170        public boolean isOpen()
    171        {
    172            return _isOpen_;
    173        }
    174
    175
    176        /***
    177         * Set the default timeout in milliseconds to use when opening a socket.
    178         * After a call to open, the timeout for the socket is set using this value.
    179         * This method should be used prior to a call to {@link #open open()}
    180         * and should not be confused with {@link #setSoTimeout setSoTimeout()}
    181         * which operates on the currently open socket.  _timeout_ contains
    182         * the new timeout value.
    183         * <p>
    184         * @param timeout  The timeout in milliseconds to use for the datagram socket
    185         *                 connection.
    186         ***/
    187        public void setDefaultTimeout(int timeout)
    188        {
    189            _timeout_ = timeout;
    190        }
    191
    192
    193        /***
    194         * Returns the default timeout in milliseconds that is used when
    195         * opening a socket.
    196         * <p>
    197         * @return The default timeout in milliseconds that is used when
    198         *         opening a socket.
    199         ***/
    200        public int getDefaultTimeout()
    201        {
    202            return _timeout_;
    203        }
    204
    205
    206        /***
    207         * Set the timeout in milliseconds of a currently open connection.
    208         * Only call this method after a connection has been opened
    209         * by {@link #open open()}.
    210         * <p>
    211         * @param timeout  The timeout in milliseconds to use for the currently
    212         *                 open datagram socket connection.
    213         ***/
    214        public void setSoTimeout(int timeout) throws SocketException
    215        {
    216            _socket_.setSoTimeout(timeout);
    217        }
    218
    219
    220        /***
    221         * Returns the timeout in milliseconds of the currently opened socket.
    222         * If you call this method when the client socket is not open,
    223         * a NullPointerException is thrown.
    224         * <p>
    225         * @return The timeout in milliseconds of the currently opened socket.
    226         ***/
    227        public int getSoTimeout() throws SocketException
    228        {
    229            return _socket_.getSoTimeout();
    230        }
    231
    232
    233        /***
    234         * Returns the port number of the open socket on the local host used
    235         * for the connection.  If you call this method when the client socket
    236         * is not open, a NullPointerException is thrown.
    237         * <p>
    238         * @return The port number of the open socket on the local host used
    239         *         for the connection.
    240         ***/
    241        public int getLocalPort()
    242        {
    243            return _socket_.getLocalPort();
    244        }
    245
    246
    247        /***
    248         * Returns the local address to which the client's socket is bound.
    249         * If you call this method when the client socket is not open, a
    250         * NullPointerException is thrown.
    251         * <p>
    252         * @return The local address to which the client's socket is bound.
    253         ***/
    254        public InetAddress getLocalAddress()
    255        {
    256            return _socket_.getLocalAddress();
    257        }
    258
    259
    260        /***
    261         * Sets the DatagramSocketFactory used by the DatagramSocketClient
    262         * to open DatagramSockets.  If the factory value is null, then a default
    263         * factory is used (only do this to reset the factory after having
    264         * previously altered it).
    265         * <p>
    266         * @param factory  The new DatagramSocketFactory the DatagramSocketClient
    267         * should use.
    268         ***/
    269        public void setDatagramSocketFactory(DatagramSocketFactory factory)
    270        {
    271            if (factory == null) {
    272                _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
    273            } else {
    274                _socketFactory_ = factory;
    275            }
    276        }
    277    }