/* * Copyright 2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.gradle.internal.remote.internal.inet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; /** * Provides information on how two processes on this machine can communicate via IP addresses */ public class InetAddressFactory { private final Logger logger = LoggerFactory.getLogger(getClass()); private final Object lock = new Object(); private List<InetAddress> communicationAddresses; private InetAddress localBindingAddress; private InetAddresses inetAddresses; private boolean initialized; private String hostName; public String getHostname() { synchronized (lock) { if (hostName == null) { try { hostName = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { hostName = getCommunicationAddresses().get(0).toString(); } } return hostName; } } /** * Determines if the IP address can be used for communication with this machine */ public boolean isCommunicationAddress(InetAddress address) { try { synchronized (lock) { init(); return communicationAddresses.contains(address); } } catch (Exception e) { throw new RuntimeException("Could not determine the IP addresses for this machine.", e); } } /** * Locates the possible IP addresses which can be used to communicate with this machine. * * Loopback addresses are preferred. */ public List<InetAddress> getCommunicationAddresses() { try { synchronized (lock) { init(); return communicationAddresses; } } catch (Exception e) { throw new RuntimeException("Could not determine the local IP addresses for this machine.", e); } } public InetAddress getLocalBindingAddress() { try { synchronized (lock) { init(); return localBindingAddress; } } catch (Exception e) { throw new RuntimeException("Could not determine a usable local IP for this machine.", e); } } private void init() throws Exception { if (initialized) { return; } initialized = true; if (inetAddresses == null) { // For testing inetAddresses = new InetAddresses(); } localBindingAddress = new InetSocketAddress(0).getAddress(); findCommunicationAddresses(); handleOpenshift(); } private void handleOpenshift() { InetAddress openshiftBindAddress = findOpenshiftAddresses(); if (openshiftBindAddress != null) { localBindingAddress = openshiftBindAddress; communicationAddresses.add(openshiftBindAddress); } } private InetAddress findOpenshiftAddresses() { for (String key : System.getenv().keySet()) { if (key.startsWith("OPENSHIFT_") && key.endsWith("_IP")) { String ipAddress = System.getenv(key); logger.debug("OPENSHIFT IP environment variable {} detected. Using IP address {}.", key, ipAddress); try { return InetAddress.getByName(ipAddress); } catch (UnknownHostException e) { throw new RuntimeException(String.format("Unable to use OPENSHIFT IP - invalid IP address '%s' specified in environment variable %s.", ipAddress, key), e); } } } return null; } private void findCommunicationAddresses() throws UnknownHostException { communicationAddresses = new ArrayList<InetAddress>(); if (inetAddresses.getLoopback().isEmpty()) { if (inetAddresses.getRemote().isEmpty()) { InetAddress fallback = InetAddress.getByName(null); logger.debug("No loopback addresses, using fallback {}", fallback); communicationAddresses.add(fallback); } else { logger.debug("No loopback addresses, using remote addresses instead."); communicationAddresses.addAll(inetAddresses.getRemote()); } } else { communicationAddresses.addAll(inetAddresses.getLoopback()); } } }