1414import java .util .Map ;
1515import java .util .Objects ;
1616import java .util .Optional ;
17+ import java .util .concurrent .atomic .AtomicInteger ;
1718import lombok .RequiredArgsConstructor ;
1819import lombok .extern .slf4j .Slf4j ;
1920import org .xbill .DNS .Address ;
@@ -37,6 +38,7 @@ public final class HostsFileParser {
3738 private final boolean clearCacheOnChange ;
3839 private Instant lastFileReadTime = Instant .MIN ;
3940 private boolean isEntireFileParsed ;
41+ private boolean hostsFileWarningLogged = false ;
4042
4143 /**
4244 * Creates a new instance based on the current OS's default. Unix and alike (or rather everything
@@ -116,9 +118,11 @@ public synchronized Optional<InetAddress> getAddressForHost(Name name, int type)
116118 private void parseEntireHostsFile () throws IOException {
117119 String line ;
118120 int lineNumber = 0 ;
121+ AtomicInteger addressFailures = new AtomicInteger (0 );
122+ AtomicInteger nameFailures = new AtomicInteger (0 );
119123 try (BufferedReader hostsReader = Files .newBufferedReader (path , StandardCharsets .UTF_8 )) {
120124 while ((line = hostsReader .readLine ()) != null ) {
121- LineData lineData = parseLine (++lineNumber , line );
125+ LineData lineData = parseLine (++lineNumber , line , addressFailures , nameFailures );
122126 if (lineData != null ) {
123127 for (Name lineName : lineData .names ) {
124128 InetAddress lineAddress =
@@ -129,15 +133,26 @@ private void parseEntireHostsFile() throws IOException {
129133 }
130134 }
131135
136+ if (!hostsFileWarningLogged && (addressFailures .get () > 0 || nameFailures .get () > 0 )) {
137+ log .warn (
138+ "Failed to parse entire hosts file {}, address failures={}, name failures={}" ,
139+ path ,
140+ addressFailures .get (),
141+ nameFailures );
142+ hostsFileWarningLogged = true ;
143+ }
144+
132145 isEntireFileParsed = true ;
133146 }
134147
135148 private void searchHostsFileForEntry (Name name , int type ) throws IOException {
136149 String line ;
137150 int lineNumber = 0 ;
151+ AtomicInteger addressFailures = new AtomicInteger (0 );
152+ AtomicInteger nameFailures = new AtomicInteger (0 );
138153 try (BufferedReader hostsReader = Files .newBufferedReader (path , StandardCharsets .UTF_8 )) {
139154 while ((line = hostsReader .readLine ()) != null ) {
140- LineData lineData = parseLine (++lineNumber , line );
155+ LineData lineData = parseLine (++lineNumber , line , addressFailures , nameFailures );
141156 if (lineData != null ) {
142157 for (Name lineName : lineData .names ) {
143158 boolean isSearchedEntry = lineName .equals (name );
@@ -151,6 +166,16 @@ private void searchHostsFileForEntry(Name name, int type) throws IOException {
151166 }
152167 }
153168 }
169+
170+ if (!hostsFileWarningLogged && (addressFailures .get () > 0 || nameFailures .get () > 0 )) {
171+ log .warn (
172+ "Failed to find {} in hosts file {}, address failures={}, name failures={}" ,
173+ name ,
174+ path ,
175+ addressFailures .get (),
176+ nameFailures );
177+ hostsFileWarningLogged = true ;
178+ }
154179 }
155180
156181 @ RequiredArgsConstructor
@@ -160,7 +185,8 @@ private static final class LineData {
160185 final Iterable <? extends Name > names ;
161186 }
162187
163- private LineData parseLine (int lineNumber , String line ) {
188+ private LineData parseLine (
189+ int lineNumber , String line , AtomicInteger addressFailures , AtomicInteger nameFailures ) {
164190 String [] lineTokens = getLineTokens (line );
165191 if (lineTokens .length < 2 ) {
166192 return null ;
@@ -174,24 +200,26 @@ private LineData parseLine(int lineNumber, String line) {
174200 }
175201
176202 if (lineAddressBytes == null ) {
177- log .warn ("Could not decode address {}, {}#L{}" , lineTokens [0 ], path , lineNumber );
203+ log .debug ("Could not decode address {}, {}#L{}" , lineTokens [0 ], path , lineNumber );
204+ addressFailures .incrementAndGet ();
178205 return null ;
179206 }
180207
181208 Iterable <? extends Name > lineNames =
182209 Arrays .stream (lineTokens )
183210 .skip (1 )
184- .map (lineTokenName -> safeName (lineTokenName , lineNumber ))
211+ .map (lineTokenName -> safeName (lineTokenName , lineNumber , nameFailures ))
185212 .filter (Objects ::nonNull )
186213 ::iterator ;
187214 return new LineData (lineAddressType , lineAddressBytes , lineNames );
188215 }
189216
190- private Name safeName (String name , int lineNumber ) {
217+ private Name safeName (String name , int lineNumber , AtomicInteger nameFailures ) {
191218 try {
192219 return Name .fromString (name , Name .root );
193220 } catch (TextParseException e ) {
194- log .warn ("Could not decode name {}, {}#L{}, skipping" , name , path , lineNumber );
221+ log .debug ("Could not decode name {}, {}#L{}, skipping" , name , path , lineNumber );
222+ nameFailures .incrementAndGet ();
195223 return null ;
196224 }
197225 }
0 commit comments