Skip to content

Commit 5ec00d9

Browse files
authored
SYM-7173: Save hostname on startup and log how it was obtained (#478)
1 parent d39b14e commit 5ec00d9

File tree

1 file changed

+100
-29
lines changed

1 file changed

+100
-29
lines changed

symmetric-util/src/main/java/org/jumpmind/util/AppUtils.java

Lines changed: 100 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
package org.jumpmind.util;
2222

2323
import static org.apache.commons.lang3.StringUtils.isBlank;
24-
import static org.apache.commons.lang3.StringUtils.isNotBlank;
2524

2625
import java.io.File;
2726
import java.io.FileOutputStream;
@@ -51,10 +50,15 @@
5150
* General application utility methods
5251
*/
5352
public class AppUtils {
54-
public final static String SYSPROP_HOST_NAME = "host.name";
55-
public final static String SYSPROP_PORT_NUMBER = "port.number";
56-
public final static String SYSPROP_IP_ADDRESS = "ip.address";
53+
public static final String SYSPROP_HOST_NAME = "host.name";
54+
public static final String SYSPROP_PORT_NUMBER = "port.number";
55+
public static final String SYSPROP_IP_ADDRESS = "ip.address";
56+
public static final String ENV_VAR_HOSTNAME = "HOSTNAME";
57+
public static final String ENV_VAR_COMPUTERNAME = "COMPUTERNAME";
58+
public static final String OS_COMMAND_HOSTNAME = "hostname";
5759
private static String UNKNOWN = "unknown";
60+
private static String DEFAULT_LOCALHOST = "localhost";
61+
static String hostName = DEFAULT_LOCALHOST;
5862
private static Logger log = LoggerFactory.getLogger(AppUtils.class);
5963
private static FastDateFormat timezoneFormatter = FastDateFormat.getInstance("Z");
6064
private static Properties implProp = new Properties();
@@ -68,13 +72,15 @@ private static void loadProperties(Properties prop, String resourceName) {
6872
try (InputStream fis = url.openStream()) {
6973
prop.load(fis);
7074
} catch (IOException ex) {
75+
log.debug("Failed to load properties from url ({}): {}", resourceName, ex.getMessage());
7176
}
7277
} else {
7378
url = AppUtils.class.getResource(resourceName);
7479
if (url != null) {
7580
try (InputStream fis = url.openStream()) {
7681
prop.load(fis);
7782
} catch (IOException ex) {
83+
log.debug("Failed to load properties from resource ({}): {}", resourceName, ex.getMessage());
7884
}
7985
}
8086
}
@@ -96,33 +102,98 @@ public static String getCanonicalSymHome(String dirName) {
96102
}
97103

98104
public static String getHostName() {
99-
String hostName = System.getProperty(SYSPROP_HOST_NAME, UNKNOWN);
100-
if (UNKNOWN.equals(hostName)) {
101-
try {
102-
hostName = System.getenv("HOSTNAME");
103-
if (isBlank(hostName)) {
104-
hostName = System.getenv("COMPUTERNAME");
105-
}
106-
if (isBlank(hostName)) {
107-
try {
108-
hostName = IOUtils.toString(Runtime.getRuntime().exec("hostname").getInputStream(), Charset.defaultCharset());
109-
} catch (Exception ex) {
110-
}
111-
}
112-
if (isBlank(hostName)) {
113-
hostName = InetAddress.getByName(
114-
InetAddress.getLocalHost().getHostAddress()).getHostName();
115-
}
116-
if (isNotBlank(hostName)) {
117-
hostName = hostName.trim();
118-
}
119-
} catch (Exception ex) {
120-
log.info("Unable to lookup hostname: " + ex.getMessage());
105+
if (!isBlank(hostName) && !DEFAULT_LOCALHOST.equals(hostName)) {
106+
if (log.isDebugEnabled()) {
107+
log.debug("Hostname is already set to {}", hostName);
108+
}
109+
return hostName;
110+
}
111+
try {
112+
String osHostName = fetchHostNameFromJvm();
113+
osHostName = isBlank(osHostName) ? fetchHostNameFromEnvironmentVariable(ENV_VAR_HOSTNAME) : osHostName;
114+
osHostName = isBlank(osHostName) ? fetchHostNameFromEnvironmentVariable(ENV_VAR_COMPUTERNAME) : osHostName;
115+
osHostName = isBlank(osHostName) ? fetchHostNameFromOsCommand() : osHostName;
116+
osHostName = isBlank(osHostName) ? fetchHostNameFromInetAddress() : osHostName;
117+
if (isBlank(osHostName)) {
118+
log.error("Unable to identify hostname! Using " + DEFAULT_LOCALHOST
119+
+ " instead. Report this incident to server/system administrator as it can break network communication!");
120+
} else {
121+
hostName = osHostName;
121122
}
123+
} catch (Exception ex) {
124+
log.error("Failed to identify hostname (using " + DEFAULT_LOCALHOST + " instead): " + ex.getMessage());
122125
}
123126
return hostName;
124127
}
125128

129+
public static String fetchHostNameFromJvm() {
130+
try {
131+
// Note: Embedded deployments or unit tests might not define this JVM property.
132+
String jvmHostName = System.getProperty(SYSPROP_HOST_NAME, UNKNOWN);
133+
if (isBlank(jvmHostName) || UNKNOWN.equals(jvmHostName)) {
134+
log.info("Skipping undefined JVM system property: {}", SYSPROP_HOST_NAME);
135+
jvmHostName = "";
136+
} else {
137+
jvmHostName = jvmHostName.trim();
138+
log.info("Hostname from JVM system property {}={}", SYSPROP_HOST_NAME, jvmHostName);
139+
}
140+
return jvmHostName;
141+
} catch (Exception ex) {
142+
log.warn("Failed to get hostname from JVM system property " + SYSPROP_HOST_NAME, ex);
143+
return "";
144+
}
145+
}
146+
147+
public static String fetchHostNameFromEnvironmentVariable(String environmentVariableName) {
148+
try {
149+
// Note: In many Linux shells, HOSTNAME is a variable set by the shell itself (e.g., Bash) but is not automatically available in child processes.
150+
String osHostName = System.getenv(environmentVariableName);
151+
if (isBlank(osHostName)) {
152+
log.info("Skipping undefined environment variable: {}", environmentVariableName);
153+
} else {
154+
osHostName = osHostName.trim();
155+
log.info("Hostname from environment variable {}={}", environmentVariableName, osHostName);
156+
}
157+
return osHostName;
158+
} catch (Exception ex) {
159+
log.warn("Failed to get hostname from the " + environmentVariableName + " environment variable", ex);
160+
return "";
161+
}
162+
}
163+
164+
public static String fetchHostNameFromOsCommand() {
165+
try {
166+
// Note: This requires permissions to run an external process and capture it's output.
167+
String osHostName = IOUtils.toString(Runtime.getRuntime().exec(OS_COMMAND_HOSTNAME).getInputStream(), Charset.defaultCharset());
168+
if (isBlank(osHostName)) {
169+
log.warn("Got blank hostname value from the {} OS command!", OS_COMMAND_HOSTNAME);
170+
} else {
171+
osHostName = osHostName.trim();
172+
log.info("Hostname from the {} OS command={}", OS_COMMAND_HOSTNAME, osHostName);
173+
}
174+
return osHostName;
175+
} catch (Exception ex) {
176+
log.error("Failed to execute the " + OS_COMMAND_HOSTNAME + " OS command: " + ex.getMessage());
177+
return "";
178+
}
179+
}
180+
181+
public static String fetchHostNameFromInetAddress() {
182+
try {
183+
// Note: This fails if hostname isn't resolvable through DNS due to broken network configuration.
184+
String osHostName = InetAddress.getByName(InetAddress.getLocalHost().getHostAddress()).getHostName();
185+
if (isBlank(osHostName)) {
186+
log.warn("Got blank hostname value from InetAddress");
187+
} else {
188+
log.info("Hostname from InetAddress={}", osHostName);
189+
}
190+
return osHostName;
191+
} catch (Exception ex) {
192+
log.error("Failed to get hostname from InetAddress: " + ex.getMessage());
193+
return "";
194+
}
195+
}
196+
126197
public static String getPortNumber() {
127198
String httpPort = System.getProperty(SYSPROP_PORT_NUMBER, System.getProperty("http.port"));
128199
String port = httpPort == null ? "31415" : httpPort;
@@ -159,15 +230,15 @@ public static String getIpAddress() {
159230
}
160231
}
161232
} catch (Exception ex) {
162-
log.warn("", ex);
233+
log.warn("Failed to get IP from NetworkInterfaces: ", ex);
163234
} finally {
164235
}
165236
}
166237
if (UNKNOWN.equals(ipAddress)) {
167238
try {
168239
ipAddress = InetAddress.getLocalHost().getHostAddress();
169240
} catch (UnknownHostException ex) {
170-
log.warn("", ex);
241+
log.warn("Failed to get IP from InetAddress: ", ex);
171242
ipAddress = "127.0.0.1";
172243
}
173244
}
@@ -301,7 +372,7 @@ public static <T> T newInstance(Class<T> clazz, Class<?> defaultClass, Object[]
301372
try {
302373
Constructor<T> cons = (Constructor<T>) Class.forName(className).getDeclaredConstructor(argTypes);
303374
cons.setAccessible(true);
304-
instance = (T) cons.newInstance(args);
375+
instance = cons.newInstance(args);
305376
} catch (Exception e) {
306377
throw new RuntimeException(e);
307378
}

0 commit comments

Comments
 (0)