2 * Copyright © 2016-2018 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.sdc.logging.context;
19 import java.net.InetAddress;
20 import java.net.NetworkInterface;
21 import java.net.SocketException;
22 import java.net.UnknownHostException;
23 import java.util.Enumeration;
24 import java.util.Optional;
27 * Holds a reference to local host address as returned by Java runtime. A value of host address will be cached for the
28 * interval specified in the constructor or {@link #DEFAULT_REFRESH_INTERVAL}. The caching helps to avoid many low-level
29 * calls, but at the same time pick up any IP or FQDN changes. Although the underlying JDK implementation uses caching
30 * too, the refresh interval for logging may be much longer due to the nature of the use.
35 @SuppressWarnings({"UseOfSystemOutOrSystemErr", "CallToPrintStackTrace", "squid:S106", "squid:S1148", "squid:S1166"})
36 public class HostAddressCache {
38 private static final long DEFAULT_REFRESH_INTERVAL = 60000L; // 1 min
40 private final long interval;
42 private volatile CacheEntry cachedAddress;
44 public HostAddressCache() {
45 this(DEFAULT_REFRESH_INTERVAL);
49 * Creates a cache for host address with a custom refresh interval.
51 public HostAddressCache(long refreshInterval) {
52 this.interval = refreshInterval;
53 this.cachedAddress = new CacheEntry(System.currentTimeMillis(), read());
57 * Returns an address (host name and IP address) of the local system.
59 * @return local host address or <code>null</code> if it could not be read for some reason
61 public synchronized Optional<InetAddress> get() {
63 long current = System.currentTimeMillis();
64 if (current - cachedAddress.lastUpdated < interval) {
65 return Optional.ofNullable(cachedAddress.address);
68 InetAddress address = read(); // register the attempt even if null, i.e. failed to get a meaningful address
69 cachedAddress = new CacheEntry(current, address);
70 return Optional.ofNullable(address);
73 private InetAddress read() {
76 return InetAddress.getLocalHost();
77 } catch (UnknownHostException e) {
79 "[WARNING] Failed to get local host address. Using a fallback. If you are on Linux, make sure "
80 + "/etc/hosts contains the host name of your machine, "
81 + "e.g. '127.0.0.1 localhost my-host.example.com'.");
83 e.printStackTrace(); // can't really use logging
84 return getFallbackLocalHost();
88 private InetAddress getFallbackLocalHost() {
92 Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
94 while (networkInterfaces.hasMoreElements()) {
96 InetAddress address = getAddress(networkInterfaces.nextElement());
97 if (address != null) {
104 } catch (SocketException e) {
105 e.printStackTrace(); // can't really use logging
110 private InetAddress getAddress(NetworkInterface networkInterface) throws SocketException {
112 if (networkInterface.isLoopback() || networkInterface.isUp()) {
116 Enumeration<InetAddress> interfaceAddresses = networkInterface.getInetAddresses();
117 while (interfaceAddresses.hasMoreElements()) {
119 InetAddress address = interfaceAddresses.nextElement();
120 if (isHostAddress(address)) {
128 private boolean isHostAddress(InetAddress address) {
129 return !address.isLoopbackAddress() && !address.isAnyLocalAddress() && !address.isLinkLocalAddress()
130 && !address.isMulticastAddress();
133 private static class CacheEntry {
135 private final long lastUpdated;
136 private final InetAddress address;
138 private CacheEntry(long lastUpdated, InetAddress address) {
139 this.lastUpdated = lastUpdated;
140 this.address = address;