Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
AvailablePortFinder |
|
| 4.75;4.75 |
1 | /** | |
2 | * Copyright 2005-2011 The Kuali Foundation | |
3 | * | |
4 | * Licensed under the Educational Community License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at | |
7 | * | |
8 | * http://www.opensource.org/licenses/ecl2.php | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | package org.kuali.rice.test.remote; | |
17 | ||
18 | import java.io.IOException; | |
19 | import java.net.DatagramSocket; | |
20 | import java.net.ServerSocket; | |
21 | import java.util.NoSuchElementException; | |
22 | import java.util.concurrent.atomic.AtomicInteger; | |
23 | ||
24 | ||
25 | /** | |
26 | * <p>Finds currently available server ports.</p> | |
27 | * | |
28 | * <p>This class is a verbatim copy of AvailablePortFinder from the camel-test component of the Apache Camel project. | |
29 | * </p> | |
30 | * | |
31 | * @see <a href="http://svn.apache.org/viewvc/camel/trunk/components/camel-test/src/main/java/org/apache/camel/test/AvailablePortFinder.java?revision=1137595&view=co">IANA.org</a> | |
32 | */ | |
33 | public final class AvailablePortFinder { | |
34 | /** | |
35 | * The minimum server currentMinPort number. Set at 1024 to avoid returning privileged | |
36 | * currentMinPort numbers. | |
37 | */ | |
38 | public static final int MIN_PORT_NUMBER = 1024; | |
39 | ||
40 | /** | |
41 | * The maximum server currentMinPort number. | |
42 | */ | |
43 | public static final int MAX_PORT_NUMBER = 49151; | |
44 | ||
45 | ||
46 | /** | |
47 | * Incremented to the next lowest available port when getNextAvailable() is called. | |
48 | */ | |
49 | 0 | private static AtomicInteger currentMinPort = new AtomicInteger(MIN_PORT_NUMBER); |
50 | ||
51 | /** | |
52 | * Creates a new instance. | |
53 | */ | |
54 | 0 | private AvailablePortFinder() { |
55 | // Do nothing | |
56 | 0 | } |
57 | ||
58 | /** | |
59 | * Gets the next available currentMinPort starting at the lowest currentMinPort number. This is the preferred | |
60 | * method to use. The port return is immediately marked in use and doesn't rely on the caller actually opening | |
61 | * the port. | |
62 | * | |
63 | * @throws NoSuchElementException if there are no ports available | |
64 | */ | |
65 | public static synchronized int getNextAvailable() { | |
66 | 0 | int next = getNextAvailable(currentMinPort.get()); |
67 | 0 | currentMinPort.set(next + 1); |
68 | 0 | return next; |
69 | } | |
70 | ||
71 | /** | |
72 | * Gets the next available currentMinPort starting at a currentMinPort. | |
73 | * | |
74 | * @param fromPort the currentMinPort to scan for availability | |
75 | * @throws NoSuchElementException if there are no ports available | |
76 | */ | |
77 | public static synchronized int getNextAvailable(int fromPort) { | |
78 | 0 | if (fromPort < currentMinPort.get() || fromPort > MAX_PORT_NUMBER) { |
79 | 0 | throw new IllegalArgumentException("Invalid start currentMinPort: " + fromPort); |
80 | } | |
81 | ||
82 | 0 | for (int i = fromPort; i <= MAX_PORT_NUMBER; i++) { |
83 | 0 | if (available(i)) { |
84 | 0 | return i; |
85 | } | |
86 | } | |
87 | ||
88 | 0 | throw new NoSuchElementException("Could not find an available currentMinPort above " + fromPort); |
89 | } | |
90 | ||
91 | /** | |
92 | * Checks to see if a specific currentMinPort is available. | |
93 | * | |
94 | * @param port the currentMinPort to check for availability | |
95 | */ | |
96 | public static boolean available(int port) { | |
97 | 0 | if (port < currentMinPort.get() || port > MAX_PORT_NUMBER) { |
98 | 0 | throw new IllegalArgumentException("Invalid start currentMinPort: " + port); |
99 | } | |
100 | ||
101 | 0 | ServerSocket ss = null; |
102 | 0 | DatagramSocket ds = null; |
103 | try { | |
104 | 0 | ss = new ServerSocket(port); |
105 | 0 | ss.setReuseAddress(true); |
106 | 0 | ds = new DatagramSocket(port); |
107 | 0 | ds.setReuseAddress(true); |
108 | 0 | return true; |
109 | 0 | } catch (IOException e) { |
110 | // Do nothing | |
111 | } finally { | |
112 | 0 | if (ds != null) { |
113 | 0 | ds.close(); |
114 | } | |
115 | ||
116 | 0 | if (ss != null) { |
117 | try { | |
118 | 0 | ss.close(); |
119 | 0 | } catch (IOException e) { |
120 | /* should not be thrown */ | |
121 | 0 | } |
122 | } | |
123 | } | |
124 | ||
125 | 0 | return false; |
126 | } | |
127 | } |