io.netty.resolver.HostsFileParser Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including
all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and
Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you 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 io.netty.resolver;
import io.netty.util.NetUtil;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.UnstableApi;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import static io.netty.util.internal.ObjectUtil.*;
/**
* A parser for hosts files.
*/
@UnstableApi
public final class HostsFileParser {
private static final String WINDOWS_DEFAULT_SYSTEM_ROOT = "C:\\Windows";
private static final String WINDOWS_HOSTS_FILE_RELATIVE_PATH = "\\system32\\drivers\\etc\\hosts";
private static final String X_PLATFORMS_HOSTS_FILE_PATH = "/etc/hosts";
private static final Pattern WHITESPACES = Pattern.compile("[ \t]+");
private static final InternalLogger logger = InternalLoggerFactory.getInstance(HostsFileParser.class);
private static File locateHostsFile() {
File hostsFile;
if (PlatformDependent.isWindows()) {
hostsFile = new File(System.getenv("SystemRoot") + WINDOWS_HOSTS_FILE_RELATIVE_PATH);
if (!hostsFile.exists()) {
hostsFile = new File(WINDOWS_DEFAULT_SYSTEM_ROOT + WINDOWS_HOSTS_FILE_RELATIVE_PATH);
}
} else {
hostsFile = new File(X_PLATFORMS_HOSTS_FILE_PATH);
}
return hostsFile;
}
/**
* Parse hosts file at standard OS location using the systems default {@link Charset} for decoding.
*
* @return a {@link HostsFileEntries}
*/
public static HostsFileEntries parseSilently() {
return parseSilently(Charset.defaultCharset());
}
/**
* Parse hosts file at standard OS location using the given {@link Charset}s one after each other until
* we were able to parse something or none is left.
*
* @param charsets the {@link Charset}s to try as file encodings when parsing.
* @return a {@link HostsFileEntries}
*/
public static HostsFileEntries parseSilently(Charset... charsets) {
File hostsFile = locateHostsFile();
try {
return parse(hostsFile, charsets);
} catch (IOException e) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to load and parse hosts file at " + hostsFile.getPath(), e);
}
return HostsFileEntries.EMPTY;
}
}
/**
* Parse hosts file at standard OS location using the system default {@link Charset} for decoding.
*
* @return a {@link HostsFileEntries}
* @throws IOException file could not be read
*/
public static HostsFileEntries parse() throws IOException {
return parse(locateHostsFile());
}
/**
* Parse a hosts file using the system default {@link Charset} for decoding.
*
* @param file the file to be parsed
* @return a {@link HostsFileEntries}
* @throws IOException file could not be read
*/
public static HostsFileEntries parse(File file) throws IOException {
return parse(file, Charset.defaultCharset());
}
/**
* Parse a hosts file.
*
* @param file the file to be parsed
* @param charsets the {@link Charset}s to try as file encodings when parsing.
* @return a {@link HostsFileEntries}
* @throws IOException file could not be read
*/
public static HostsFileEntries parse(File file, Charset... charsets) throws IOException {
checkNotNull(file, "file");
checkNotNull(charsets, "charsets");
if (file.exists() && file.isFile()) {
for (Charset charset: charsets) {
HostsFileEntries entries = parse(new BufferedReader(new InputStreamReader(
new FileInputStream(file), charset)));
if (entries != HostsFileEntries.EMPTY) {
return entries;
}
}
}
return HostsFileEntries.EMPTY;
}
/**
* Parse a reader of hosts file format.
*
* @param reader the file to be parsed
* @return a {@link HostsFileEntries}
* @throws IOException file could not be read
*/
public static HostsFileEntries parse(Reader reader) throws IOException {
checkNotNull(reader, "reader");
BufferedReader buff = new BufferedReader(reader);
try {
Map ipv4Entries = new HashMap();
Map ipv6Entries = new HashMap();
String line;
while ((line = buff.readLine()) != null) {
// remove comment
int commentPosition = line.indexOf('#');
if (commentPosition != -1) {
line = line.substring(0, commentPosition);
}
// skip empty lines
line = line.trim();
if (line.isEmpty()) {
continue;
}
// split
List lineParts = new ArrayList();
for (String s: WHITESPACES.split(line)) {
if (!s.isEmpty()) {
lineParts.add(s);
}
}
// a valid line should be [IP, hostname, alias*]
if (lineParts.size() < 2) {
// skip invalid line
continue;
}
byte[] ipBytes = NetUtil.createByteArrayFromIpAddressString(lineParts.get(0));
if (ipBytes == null) {
// skip invalid IP
continue;
}
// loop over hostname and aliases
for (int i = 1; i < lineParts.size(); i ++) {
String hostname = lineParts.get(i);
String hostnameLower = hostname.toLowerCase(Locale.ENGLISH);
InetAddress address = InetAddress.getByAddress(hostname, ipBytes);
if (address instanceof Inet4Address) {
Inet4Address previous = ipv4Entries.put(hostnameLower, (Inet4Address) address);
if (previous != null) {
// restore, we want to keep the first entry
ipv4Entries.put(hostnameLower, previous);
}
} else {
Inet6Address previous = ipv6Entries.put(hostnameLower, (Inet6Address) address);
if (previous != null) {
// restore, we want to keep the first entry
ipv6Entries.put(hostnameLower, previous);
}
}
}
}
return ipv4Entries.isEmpty() && ipv6Entries.isEmpty() ?
HostsFileEntries.EMPTY :
new HostsFileEntries(ipv4Entries, ipv6Entries);
} finally {
try {
buff.close();
} catch (IOException e) {
logger.warn("Failed to close a reader", e);
}
}
}
/**
* Can't be instantiated.
*/
private HostsFileParser() {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy