View Javadoc

1   /*
2   Copyright (C) 2000 - 2007 Grid Systems, S.A.
3   
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License, version 2, as
6   published by the Free Software Foundation.
7   
8   This program is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12  
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  */
17  package com.gridsystems.utils;
18  
19  import java.io.BufferedReader;
20  import java.io.ByteArrayInputStream;
21  import java.io.ByteArrayOutputStream;
22  import java.io.IOException;
23  import java.io.InputStreamReader;
24  import java.net.InetAddress;
25  import java.net.NetworkInterface;
26  import java.net.ServerSocket;
27  import java.net.SocketException;
28  import java.net.UnknownHostException;
29  import java.util.Collections;
30  import java.util.Enumeration;
31  import java.util.TreeSet;
32  import java.util.regex.Pattern;
33  
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  
37  /**
38   * Network utilities.
39   *
40   * @author dsanchez
41   * @author Xmas
42   */
43  public final class NetUtils {
44  
45    /**
46     * Class logger.
47     */
48    private static Log log = LogFactory.getLog("NetUtils");
49  
50    /**
51     * Private constructor.
52     */
53    private NetUtils() { }
54  
55    /**
56     * Checks whether a port is available for opening.
57     * @param portNumber the port number
58     * @return true if the port is available, false otherwise
59     */
60    public static boolean checkPort(int portNumber) {
61      return areFreePorts(new int[]{portNumber});
62    }
63  
64    /**
65     * Checks whether a port is available for opening using ServerSocket class.
66     * @param port the port number
67     * @return true if the port is available, false otherwise
68     */
69    private static boolean checkServerSocketFreePort(int port) {
70      try {
71        ServerSocket s1 = new ServerSocket(port, 0, null);
72        s1.close();
73  
74        ServerSocket s2 = new ServerSocket(port);
75        s2.close();
76  
77        String[] ips = getAllIPs();
78        for (int i = 0; i < ips.length; i++) {
79          ServerSocket s3;
80          s3 = new ServerSocket(port, -1 , InetAddress.getByName(ips[i]));
81          s3.close();
82        }
83  
84        ServerSocket s4 = new ServerSocket(port, -1, InetAddress.getLocalHost());
85        s4.close();
86  
87        ServerSocket s5 = new ServerSocket(port, -1, InetAddress.getByName("0.0.0.0"));
88        s5.close();
89  
90        ServerSocket s6 = new ServerSocket(port, -1, InetAddress.getByName("localhost"));
91        s6.close();
92  
93        ServerSocket s7 = new ServerSocket(port, -1, InetAddress.getByName("127.0.0.1"));
94        s7.close();
95  
96        return true;
97      } catch (IOException ioe) {
98        //System.out.println("IO exception: " + ioe);
99        //ioe.printStackTrace();
100       return false;
101     } catch (Exception e) {
102       //System.out.println("EException: " + e);
103       //e.printStackTrace();
104       return false;
105     }
106   }
107 
108   /**
109    *
110    * @return All IPs of this machine.
111    */
112   public static String[] getAllIPs() {
113     Enumeration<NetworkInterface> nets = null;
114     try {
115       nets = NetworkInterface.getNetworkInterfaces();
116     } catch (SocketException se) {
117       // No network interfaces could be found on this machine
118       return new String[]{};
119     }
120 
121     // Get the list of interfaces
122     TreeSet<String> ipList = new TreeSet<String>();
123     for (NetworkInterface netint : Collections.list(nets)) {
124       Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
125 
126       // For each interface, iterate along the IP addresses
127       for (InetAddress inetAddress : Collections.list(inetAddresses)) {
128 
129         //  Discard the loopback and multicast addresses
130         if (inetAddress.isLoopbackAddress()) {
131           continue;
132         }
133         if (inetAddress.isMulticastAddress()) {
134           continue;
135         }
136         String ip = inetAddress.getHostAddress().trim();
137         if (ip.length() > 0) {
138           ipList.add(ip);
139         }
140       }
141     }
142     return ipList.toArray(new String[ipList.size()]);
143   }
144 
145   /**
146    * @return Return best IP for this machine.
147    */
148   public static String getMachineIP() {
149     String[] ips = getAllIPs();
150     // 1.- Select a ip4 if exists
151     final String ipRegex = "[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}";
152     Pattern ipPat = Pattern.compile(ipRegex);
153     for (int i = 0; i < ips.length; i++) {
154       if (ipPat.matcher(ips[i]).matches()) {
155         log.info("Found Ip4: " + ips[i]);
156         return ips[i];
157       }
158       log.error("No match Ip4: " + ips[i]);
159     }
160     // 2.- Select localhost IP if exists
161     String ip = null;
162     try {
163       InetAddress localHost = InetAddress.getLocalHost();
164       if (localHost.isLoopbackAddress()) {
165         log.error("The localhost returns the loopback address!");
166       } else {
167         ip = InetAddress.getLocalHost().getHostAddress();
168       }
169     } catch (UnknownHostException uhe) {
170       if (ip == null) {
171         // Show message only when the ip has not been defined!
172         log.error("COULD NOT FIND THE LOCAL HOST! " + uhe.getMessage());
173       }
174     } catch (Exception e) {
175       if (ip == null) {
176         // Show message only when the ip has not been defined!
177         log.error("EXCEPTION LOOKING FOR THE LOCAL IP! " + e.getMessage());
178       }
179     }
180     // 3.- Select ip6 IP
181     if (ip == null && ips.length > 0) {
182       return ips[ips.length - 1];
183     }
184     // 4.- Return none IP
185     return "";
186   }
187 
188   /**
189    * Helper method to know if certain server ip or server name
190    * is our machine or not.
191    *
192    * @param host The host name to test
193    * @return true if host is (or is an alias to) localhost
194    */
195   public static boolean serverIsLocal(String host) {
196     try {
197       // Recogemos las ip's locales
198       InetAddress[] addr = InetAddress.getAllByName(host);
199       InetAddress localhost = InetAddress.getLocalHost();
200       InetAddress localhost2 = InetAddress.getByName("localhost");
201       // Las comparamos con la direccion pasada por parametro
202       for (int i = 0; i < addr.length; i++) {
203         if (addr[i].equals(localhost) || addr[i].equals(localhost2)) {
204           return true;
205         }
206       }
207     } catch (Exception ex)  {
208       log.error("CopierUtils::serverIsLocal() -> Unknow error: " + ex.toString(), ex);
209     }
210     return false;
211   }
212 
213   /**
214    * Check if a list of ports are free.
215    *
216    * @param ports The port numbers to test
217    * @return true if all ports are free in this host
218    *
219    */
220   public static boolean areFreePorts(int[] ports) {
221     if ((ports == null) || (ports.length == 0)) {
222       return true;
223     }
224 
225     for (int i = 0; i < ports.length; i++) {
226       if (ports[i] > 0) {
227         if (!checkServerSocketFreePort(ports[i])) {
228           return false;
229         }
230       }
231     }
232 
233     ByteArrayOutputStream baos = new ByteArrayOutputStream();
234     final String cmd = "netstat -na";
235     Integer exitCode = SystemUtils.execAndSaveOutput(cmd, null, null, baos);
236 
237     if (exitCode == null) {
238       log.error(I18n.translate("error.commandexecution", cmd));
239       return true;
240     }
241 
242     // Netstat separator is different for Linux
243     ByteArrayInputStream is = new ByteArrayInputStream(baos.toString().getBytes());
244     BufferedReader buf = new BufferedReader(new InputStreamReader(is));
245     String line = null;
246 
247     try {
248       while ((line = buf.readLine()) != null) {
249         line = line.replace(':', '.'); // in windows the separator is ':'
250         for (int i = 0; i < ports.length; i++) {
251           if (line.indexOf("."  + ports[i] + " ") != -1) {
252             if ((line.indexOf(" ESTABLISHED") != -1)
253               || (line.indexOf(" LISTEN") != -1)) {
254               return false;
255             }
256           }
257         }
258       }
259     } catch (Exception e) {
260       log.error("Error processing output of 'netstat -an' command execution.", e);
261       return false; // I don't know if port is free
262     }
263     // Not found occupied port
264     return true;
265   }
266 
267   /**
268    * Utility application.
269    * @param args Arguments
270    */
271   public static void main(String[] args) {
272     final String usage = "java com.gridsystems.utils.NetUtils [portNumber]";
273     if (args.length != 1) {
274       System.err.println(usage);
275       System.exit(-1);
276     }
277     int port;
278     try {
279       port = Integer.parseInt(args[0]);
280     } catch (Exception e) {
281       System.err.println("Port format error: " + e.getMessage());
282       System.err.println(usage);
283       System.exit(-1);
284       return;
285     }
286     try {
287       boolean isFree = checkPort(port);
288       System.out.println(" Port " + port + " is " + (isFree ? "free" : "occupied"));
289       System.exit(isFree ? 0 : 1);
290     } catch (Exception e) {
291       System.err.println("Error checking port " + port + ":" + e.getMessage());
292       e.printStackTrace();
293       System.exit(-1);
294     }
295   }
296 
297 }