1 | /* |
2 | * @(#) $Id: AvailablePortFinder.java 164162 2005-04-22 02:50:31Z 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: 164162 $ |
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 | } |