blob: d6b15159d21619f217cc414a78d6e4425c13193a [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 java.net;
import java.security.AccessController;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.harmony.luni.util.PriviAction;
/**
* This class is used to maintain the negative name lookup cache, which caches
* host names which could not be resolved, as a security feature.
*
* @see NegCacheElement
*/
class NegativeCache {
// maximum number of entries in the cache
private static final int MAX_NEGATIVE_ENTRIES = 5;
// the loading for the cache
private static final float LOAD_FACTOR = 0.75F;
private static final Map<String, NegCacheElement> negCache
= new LinkedHashMap<String, NegCacheElement>(
2 * MAX_NEGATIVE_ENTRIES, LOAD_FACTOR, true) {
/**
* Returns whether the eldest entry should be removed. It is removed if
* the size has grown beyond the maximum size allowed for the cache.
*
* @param eldest
* the LRU entry, which will be deleted if we return true.
*/
@Override protected boolean removeEldestEntry(
Entry<String, NegCacheElement> eldest) {
return size() > MAX_NEGATIVE_ENTRIES;
}
};
/** Ensures non-instantiability */
private NegativeCache() {
}
/**
* Adds the host name and the corresponding name lookup fail message to the
* cache.
*
* @param hostName
* the name of the host for which the lookup failed.
* @param failedMessage
* the message returned when the lookup fails.
*/
static synchronized void put(String hostName, String failedMessage) {
negCache.put(hostName, new NegCacheElement(failedMessage));
}
/**
* Returns the message of the negative cache if the entry has not yet
* expired.
*
* @param hostName
* the name of the host for which we look up the entry.
* @return the message which was returned when the host lookup failed if the
* entry has not yet expired.
*/
static synchronized String getFailedMessage(String hostName) {
NegCacheElement element = negCache.get(hostName);
if (element != null) {
// check if element is still valid
String ttlValue = AccessController
.doPrivileged(new PriviAction<String>(
"networkaddress.cache.negative.ttl")); //$NON-NLS-1$
int ttl = 10;
try {
if (ttlValue != null) {
ttl = Integer.decode(ttlValue);
}
} catch (NumberFormatException e) {
// If exception, go with ttl == 10
}
if (ttl == 0) {
negCache.clear();
element = null;
} else if (ttl != -1) {
// BEGIN android-changed
long delta = System.nanoTime() - element.nanoTimeAdded;
if (delta > secondsToNanos(ttl)) {
// remove the element from the cache and return null
negCache.remove(hostName);
element = null;
}
// END android-changed
}
}
if (element != null) {
return element.failedMessage;
}
return null;
}
// BEGIN android-added
/**
* Multiplies value by 1 billion.
*/
private static int secondsToNanos(int ttl) {
return ttl * 1000000000;
}
// END android-added
}