001/*
002 * #%L
003 * Netarchivesuite - common
004 * %%
005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library,
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023package dk.netarkivet.common.utils;
024
025import java.io.File;
026import java.io.IOException;
027import java.net.BindException;
028import java.net.InetAddress;
029import java.net.ServerSocket;
030import java.net.UnknownHostException;
031import java.util.ArrayList;
032import java.util.Arrays;
033import java.util.List;
034
035import org.slf4j.Logger;
036import org.slf4j.LoggerFactory;
037
038import dk.netarkivet.common.exceptions.IOFailure;
039
040/**
041 * Miscellanous utilities for getting system resources.
042 */
043public class SystemUtils {
044
045    private static final Logger log = LoggerFactory.getLogger(SystemUtils.class);
046
047    /** Hostname for this machine used when no name can be found, or when the actual name doesn't matter. */
048    public static final String LOCALHOST = "localhost";
049
050    /**
051     * Name of standard Java property containing class path. Why these names aren't actually defined as constants
052     * anywhere eludes me.
053     */
054    private static final String CLASS_PATH_PROPERTY = "java.class.path";
055
056    /**
057     * Looks up the IP number of the local host. Note that Java does not guarantee that the result is IPv4 or IPv6.
058     *
059     * @return the found IP; returns "UNKNOWNIP" if it could not be found.
060     */
061    public static String getLocalIP() {
062        String result;
063        try {
064            result = InetAddress.getLocalHost().getHostAddress();
065        } catch (UnknownHostException e) {
066            result = "UNKNOWNIP";
067        }
068        return result;
069    }
070
071    /**
072     * Get the first hostname available for this machine, or "localhost" if none are available.
073     *
074     * @return A hostname, as returned by InetAddress.getLocalHost().getCanonicalHostName()()
075     */
076    public static String getLocalHostName() {
077        String hostname = LOCALHOST;
078        try {
079            InetAddress localhost = InetAddress.getLocalHost();
080            String localhostName = localhost.getCanonicalHostName();
081            return localhostName;
082        } catch (UnknownHostException e) {
083            // If no interfaces, use default;
084            log.warn("Unable to resolve localhostname. Returning the default '{}'", LOCALHOST);
085        }
086        return hostname;
087    }
088
089    /**
090     * Check that a given port is not in use. If this method returns normally, the port is safe to bind.
091     *
092     * @param port Port to check
093     * @throws IOFailure if the port cannot be bound.
094     */
095    public static void checkPortNotUsed(int port) {
096        try {
097            ServerSocket s = new ServerSocket(port, 1);
098            s.close();
099        } catch (BindException e) {
100            throw new IOFailure("Port " + port + " already in use, or port is out of range", e);
101        } catch (IOException e) {
102            throw new IOFailure("IO error testing port " + port, e);
103        }
104    }
105
106    /**
107     * Get the current class path entries. Note that this does not work if we've been invoked with java -jar, as that
108     * option silently ignores classpaths.
109     *
110     * @return List of directories/jar files in the current class path.
111     */
112    public static List<String> getCurrentClasspath() {
113        String propertyValue = System.getProperty(CLASS_PATH_PROPERTY);
114        if (propertyValue != null) {
115            final String[] pathArray = propertyValue.split(File.pathSeparator);
116            return new ArrayList<String>(Arrays.asList(pathArray));
117        } else {
118            return new ArrayList<String>();
119        }
120    }
121
122}