01: /**
02: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
03: * notice. All rights reserved.
04: */package com.tc.util;
05:
06: import com.tc.net.EphemeralPorts;
07: import com.tc.net.EphemeralPorts.Range;
08:
09: import java.io.IOException;
10: import java.net.BindException;
11: import java.net.ServerSocket;
12: import java.util.HashSet;
13: import java.util.Random;
14: import java.util.Set;
15:
16: public final class PortChooser {
17: public static final int MAX = 65535;
18:
19: private static final Object VM_WIDE_LOCK = (PortChooser.class
20: .getName() + "LOCK").intern();
21: private static final Set chosen = new HashSet();
22: private static final Random random = new Random();
23: private static final Range exclude = EphemeralPorts.getRange();
24:
25: public int chooseRandomPort() {
26: synchronized (VM_WIDE_LOCK) {
27: return choose();
28: }
29: }
30:
31: public boolean isPortUsed(int portNum) {
32: final Integer port = new Integer(portNum);
33: if (chosen.contains(port))
34: return true;
35: return !canBind(portNum);
36: }
37:
38: private boolean canBind(int portNum) {
39: ServerSocket ss = null;
40: boolean isFree = false;
41: try {
42: ss = new ServerSocket(portNum);
43: isFree = true;
44: } catch (BindException be) {
45: isFree = false; // port in use,
46: } catch (IOException e) {
47: throw new RuntimeException(e);
48: } finally {
49: if (ss != null) {
50: while (!ss.isClosed()) {
51: try {
52: ss.close();
53: } catch (IOException e) {
54: // ignore
55: }
56: }
57: }
58: }
59: return isFree;
60: }
61:
62: private int choose() {
63: while (true) {
64: final Integer attempt = new Integer(getNonEphemeralPort());
65: boolean added = chosen.add(attempt);
66: if (!added) {
67: continue; // already picked at some point, try again
68: }
69: if (canBind(attempt.intValue()))
70: return (attempt.intValue());
71: }
72: }
73:
74: private static int getNonEphemeralPort() {
75: while (true) {
76: int p = random.nextInt(MAX - 1024) + 1024;
77: if (p < exclude.getLower() || p > exclude.getUpper()) {
78: return p;
79: }
80: }
81: }
82:
83: }
|