1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.util;
21
22 import java.io.IOException;
23 import java.net.ServerSocket;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.Random;
29 import java.util.StringTokenizer;
30
31 /***
32 * Provides a data container for port ranges. All methods make sure
33 * that only valid ports are added.
34 *
35 * @see xnap.util.prefs.PortRangeValidator
36 */
37 public class PortRange {
38
39
40
41 public static final int MIN_PORT = 1;
42 public static final int MAX_PORT = 65535;
43
44
45
46 /***
47 * A set of {@link Integer} objects.
48 */
49 private HashSet list = new HashSet();
50
51
52
53 public PortRange(int first, int last)
54 {
55 add(first, last);
56 }
57
58 public PortRange(String range)
59 {
60 add(range);
61 }
62
63 public PortRange()
64 {
65 }
66
67
68
69 /***
70 * Adds all ports that are <code>first</code> <= port <= <code>last</code>.
71 */
72 public void add(int first, int last)
73 {
74 for (int i = Math.max(first, MIN_PORT); i <= last && i <= MAX_PORT;
75 i++) {
76 list.add(new Integer(i));
77 }
78 }
79
80 /***
81 * Adds <code>port</code> to the range.
82 */
83 public void add(int port)
84 {
85 if (port >= MIN_PORT && port <= MAX_PORT) {
86 list.add(new Integer(port));
87 }
88 }
89
90 /***
91 * Adds a range as a string.
92 *
93 * @see xnap.util.prefs.PortRangeValidator
94 */
95 public void add(String range)
96 {
97 StringTokenizer t = new StringTokenizer(range, ";");
98 while (t.hasMoreTokens()) {
99 String ports = t.nextToken().trim();
100
101 if (ports.length() == 0) {
102 continue;
103 }
104
105 try {
106 if (ports.indexOf("-") != -1) {
107 StringTokenizer u = new StringTokenizer(ports, "-");
108 if (u.countTokens() == 2) {
109 add(Integer.parseInt(u.nextToken()),
110 Integer.parseInt(u.nextToken()));
111 }
112 }
113 else {
114 add(Integer.parseInt(ports));
115 }
116 }
117 catch (NumberFormatException e) {
118 }
119 }
120 }
121
122 /***
123 * Tries to bind random ports from the range and returns the
124 * {@link ServerSocket} object if successful.
125 *
126 * @return null, if no port could be bound
127 */
128 public ServerSocket bindRandom()
129 {
130
131 for (PortRange.IntIterator i = random(); i.hasNext();) {
132 try {
133 return new ServerSocket(i.next());
134 }
135 catch (IOException e) {
136 }
137 }
138
139 return null;
140 }
141
142 /***
143 * Returns true, if port is in the range.
144 */
145 public boolean contains(int port)
146 {
147 return list.contains(new Integer(port));
148 }
149
150 /***
151 * Returns a random port from the range.
152 *
153 * @param defaultPort a default port
154 * @return default, if range is empty
155 */
156 public int getRandom(int defaultPort)
157 {
158 if (size() > 0) {
159 ArrayList copy = new ArrayList(list);
160 int index = (new Random()).nextInt(copy.size());
161 return ((Integer)copy.get(index)).intValue();
162 }
163
164 return defaultPort;
165 }
166
167 /***
168 * Returns an iterator over all contained ports.
169 */
170 public Iterator iterator()
171 {
172 return list.iterator();
173 }
174
175 /***
176 * Returns an iterator over a shuffeled instance.
177 */
178 public IntIterator random()
179 {
180 ArrayList copy = new ArrayList(list);
181 Collections.shuffle(copy);
182 return new IntIterator(copy.iterator());
183 }
184
185 /***
186 * Returns the number of ports.
187 */
188 public int size()
189 {
190 return list.size();
191 }
192
193 /***
194 * Returns an ordered string representation.
195 */
196 public String toString()
197 {
198 StringBuffer sb = new StringBuffer();
199
200 ArrayList copy = new ArrayList(list);
201 Collections.sort(copy);
202
203 int start = 0;
204 int last = -1;
205 for (IntIterator i = new IntIterator(copy.iterator()); i.hasNext();) {
206 int current = i.next();
207 if (last == -1) {
208 start = current;
209 }
210 else if (current - last > 1) {
211 sb.append(start);
212 if (start != last) {
213 sb.append("-");
214 sb.append(last);
215 }
216 sb.append(";");
217 start = current;
218 }
219 last = current;
220 }
221
222 if (last != -1) {
223 sb.append(start);
224 if (start != last) {
225 sb.append("-");
226 sb.append(last);
227 }
228 sb.append(";");
229 }
230
231 return sb.toString();
232 }
233
234
235
236 /***
237 * An iterator over Integer objects.
238 */
239 public static class IntIterator
240 {
241
242 Iterator iterator;
243
244 public IntIterator(Iterator iterator)
245 {
246 this.iterator = iterator;
247 }
248
249 public boolean hasNext()
250 {
251 return iterator.hasNext();
252 }
253
254 public int next()
255 {
256 return ((Integer)iterator.next()).intValue();
257 }
258
259 public void remove()
260 {
261 iterator.remove();
262 }
263
264 }
265
266 }
267
268