View Javadoc

1   /*
2    *   @(#) $Id: AvailablePortFinder.java 210062 2005-07-11 03:52:38Z trustin $
3    * 
4    *   Copyright 2004 The Apache Software Foundation
5    *
6    *   Licensed under the Apache License, Version 2.0 (the "License");
7    *   you may not use this file except in compliance with the License.
8    *   You may obtain a copy of the License at
9    *
10   *       http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing, software
13   *   distributed under the License is distributed on an "AS IS" BASIS,
14   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *   See the License for the specific language governing permissions and
16   *   limitations under the License.
17   *
18   */
19  package org.apache.mina.util;
20  
21  import java.io.IOException;
22  import java.net.DatagramSocket;
23  import java.net.ServerSocket;
24  import java.util.NoSuchElementException;
25  import java.util.Set;
26  import java.util.TreeSet;
27  
28  
29  /***
30   * Finds currently available server ports.
31   *
32   * @author The Apache Directory Project
33   * @version $Rev: 210062 $
34   * @see <a href="http://www.iana.org/assignments/port-numbers">IANA.org</a>
35   */
36  public class AvailablePortFinder
37  {
38      /***
39       * The minimum number of server port number.
40       */
41      public static final int MIN_PORT_NUMBER = 1;
42  
43      /***
44       * The maximum number of server port number.
45       */
46      public static final int MAX_PORT_NUMBER = 49151;
47  
48      /***
49       * Creates a new instance.
50       */
51      private AvailablePortFinder()
52      {
53      }
54  
55      /***
56       * Returns the {@link Set} of currently available port numbers
57       * ({@link Integer}).  This method is identical to
58       * <code>getAvailablePorts(MIN_PORT_NUMBER, MAX_PORT_NUMBER)</code>.
59       *
60       * WARNING: this can take a very long time.
61       */
62      public static Set getAvailablePorts()
63      {
64          return getAvailablePorts(MIN_PORT_NUMBER, MAX_PORT_NUMBER);
65      }
66  
67      /***
68       * Gets the next available port starting at the lowest port number.
69       *
70       * @throws NoSuchElementException if there are no ports available
71       */
72      public static int getNextAvailable()
73      {
74          return getNextAvailable(MIN_PORT_NUMBER);
75      }
76  
77      /***
78       * Gets the next available port starting at a port.
79       *
80       * @param fromPort the port to scan for availability
81       * @throws NoSuchElementException if there are no ports available
82       */
83      public static int getNextAvailable(int fromPort)
84      {
85          if ((fromPort < MIN_PORT_NUMBER) || (fromPort > MAX_PORT_NUMBER))
86          {
87              throw new IllegalArgumentException("Invalid start port: "
88                                                 + fromPort);
89          }
90  
91          for (int i = fromPort; i <= MAX_PORT_NUMBER; i++)
92          {
93              ServerSocket ss = null;
94              DatagramSocket ds = null;
95              try
96              {
97                  ss = new ServerSocket(i);
98                  ds = new DatagramSocket(i);
99                  return i;
100             }
101             catch (IOException e)
102             {
103             }
104             finally
105             {
106                 if (ds != null)
107                 {
108                     ds.close();
109                 }
110 
111                 if (ss != null)
112                 {
113                     try
114                     {
115                         ss.close();
116                     }
117                     catch (IOException e)
118                     {
119                         /* should not be thrown */
120                     }
121                 }
122             }
123         }
124 
125         throw new NoSuchElementException("Could not find an available port "
126                                          + "above " + fromPort);
127     }
128 
129     /***
130      * Checks to see if a specific port is available.
131      *
132      * @param port the port to check for availability
133      */
134     public static boolean available( int port )
135     {
136         if ( ( port < MIN_PORT_NUMBER) || ( port > MAX_PORT_NUMBER ) )
137         {
138             throw new IllegalArgumentException( "Invalid start port: " + port );
139         }
140 
141         ServerSocket s = null;
142         try
143         {
144             s = new ServerSocket( port );
145             return true;
146         }
147         catch ( IOException e )
148         {
149             return false;
150         }
151         finally
152         {
153             if ( s != null )
154             {
155                 try
156                 {
157                     s.close();
158                 }
159                 catch (IOException e)
160                 {
161                     /* should not be thrown */
162                 }
163             }
164         }
165     }
166 
167     /***
168      * Returns the {@link Set} of currently avaliable port numbers ({@link Integer})
169      * between the specified port range.
170      *
171      * @throws IllegalArgumentException if port range is not between
172      * {@link #MIN_PORT_NUMBER} and {@link #MAX_PORT_NUMBER} or
173      * <code>fromPort</code> if greater than <code>toPort</code>.
174      */
175     public static Set getAvailablePorts(int fromPort, int toPort)
176     {
177         if (
178             (fromPort < MIN_PORT_NUMBER) || (toPort > MAX_PORT_NUMBER)
179                 || (fromPort > toPort))
180         {
181             throw new IllegalArgumentException("Invalid port range: "
182                                                + fromPort + " ~ " + toPort);
183         }
184 
185         Set result = new TreeSet();
186 
187         for (int i = fromPort; i <= toPort; i++)
188         {
189             ServerSocket s = null;
190 
191             try
192             {
193                 s = new ServerSocket(i);
194                 result.add(new Integer(i));
195             }
196             catch (IOException e)
197             {
198             }
199             finally
200             {
201                 if (s != null)
202                 {
203                     try
204                     {
205                         s.close();
206                     }
207                     catch (IOException e)
208                     {
209                         /* should not be thrown */
210                     }
211                 }
212             }
213         }
214 
215         return result;
216     }
217 }