source: gli/trunk/src/org/greenstone/gatherer/util/PortFinder.java@ 18987

Last change on this file since 18987 was 18987, checked in by ak19, 15 years ago

Updated several files such that the Server2 code in server.jar can interact with GLI code so that the local GS2 server for Linux works the same way as the GS2 Local Library Server on windows.

File size: 4.1 KB
Line 
1package org.greenstone.gatherer.util;
2
3/** Verbatim copy of what's in GS3's org.greenstone.server */
4
5import java.io.IOException;
6import java.net.ServerSocket;
7import java.net.BindException;
8
9// When needing to use sockets, this class can be used to find an available port
10public class PortFinder {
11
12 // Port numbers range from 0 to 65,535. RESERVED PORTS are below 1025
13 // see http://www.gnu.org/software/hello/manual/libc/Ports.html
14 public static final int MAX_PORT = 65535;
15 public static final int PORTS_RESERVED = 1024;
16
17 // Considering a limited range of ports that will be reused (circular buffer)
18 public final int PORT_BASE;
19 public final int PORT_BLOCK_SIZE;
20
21 // Keep track of what port numbers we have checked for availability
22 private int nextFreePort;
23
24 // The socket port number that we will use
25 private int port = -1;
26
27
28 public PortFinder() {
29 this( PORTS_RESERVED+1, (MAX_PORT - PORTS_RESERVED) );
30 }
31
32 public PortFinder(int base, int blocksize) {
33 PORT_BASE = base;
34 PORT_BLOCK_SIZE = blocksize;
35
36 nextFreePort = PORT_BASE;
37 }
38
39 /** Circular buffer. Modifies the value of nextFreePort (the buffer index). */
40 private void incrementNextFreePort() {
41 int offset = nextFreePort - PORT_BASE;
42 offset = (offset + 1) % PORT_BLOCK_SIZE;
43 nextFreePort = PORT_BASE + offset;
44 }
45
46 /** Finds the first available port in the range specified during Constructor call.
47 * @return the number of an available port.
48 */
49 public int findPortInRange() throws Exception {
50 try {
51 boolean foundFreePort = false;
52 for(int i = 0; i < PORT_BLOCK_SIZE; i++) {
53
54 if(isPortAvailable(nextFreePort)) {
55 foundFreePort = true;
56 break;
57
58 } else {
59 incrementNextFreePort();
60 }
61 }
62
63 if(foundFreePort) {
64 // Free port number currently found becomes the port number of the socket
65 // that will be used
66 this.port = nextFreePort;
67 incrementNextFreePort();
68
69 } else {
70 throw new Exception("Cannot find an available port in the range "
71 + PORT_BASE + "-" + (PORT_BASE+PORT_BLOCK_SIZE)
72 + "\nwhich is necessary for forcibly terminating wget.");
73 }
74
75 }catch(IOException e) {
76 System.err.println("Error when trying to find an available port. In PortFinder.findPort() " + e);
77 }
78 return port;
79 }
80
81 /** @return true if the portnumber is in the valid range. */
82 public static boolean isValidPortNumber(int portNum) {
83 return (portNum >= 0 && portNum <= MAX_PORT);
84 }
85
86 /** @return true if the portnumber is in the useable range. */
87 public static boolean isAssignablePortNumber(int portNum) {
88 return (portNum > PORTS_RESERVED && portNum <= MAX_PORT);
89 }
90
91 /** Finds an available port.
92 * @return the number of an available port.
93 */
94 public static int findAnyFreePort() throws Exception {
95 ServerSocket tmpSocket = null;
96 int portNumber = -1;
97 try {
98 // Creates a server socket, bound to the specified port.
99 // A port of 0 creates a socket on any free port.
100 tmpSocket = new ServerSocket(0);
101 portNumber = tmpSocket.getLocalPort();
102 tmpSocket.close();
103 } catch(Exception e) {
104 System.err.println("Unable to find a free port or close it. Got Exception: " + e);
105 tmpSocket = null;
106 }
107 return portNumber;
108 }
109
110 /** @return true if the portnum is available for use */
111 public static boolean isPortAvailable(int portnum) {
112 ServerSocket tmpSocket = null;
113 try {
114 tmpSocket = new ServerSocket(portnum);
115 tmpSocket.close();
116 //System.err.println("Port " + portnum + " not yet in use.");
117 return true;
118
119 } catch(BindException ex){
120 // "Signals that an error occurred while attempting to bind a
121 // socket to a local address and port. Typically, the port is
122 // in use, or the requested local address could not be assigned."
123 System.err.println("Port " + portnum + " already in use or can't be assigned.");
124 tmpSocket = null;
125 return false;
126 } catch(Exception ex) {
127 // Some other problem creating or closing the server socket
128 System.err.println("Problem creating or closing server socket at port " + portnum);
129 tmpSocket = null;
130 return false;
131 }
132 }
133}
Note: See TracBrowser for help on using the repository browser.