blob: c97c7fe928c20d636ec5224b4e166277d6628397 [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<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 1L;
private static NegativeCache<String, NegCacheElement> negCache;
// maximum number of entries in the cache
private static final int MAX_NEGATIVE_ENTRIES = 5;
// the loading for the cache
private static final float LOADING = 0.75F;
/**
* Constructs a negative cache for name lookups.
*
* @param initialCapacity
* the initial size of the cache.
* @param loadFactor
* the load factor of the backing map.
* @param accessOrder
* if {@code true} indicates that traversal order should begin
* with most recently accessed element.
*/
NegativeCache(int initialCapacity, float loadFactor, boolean accessOrder) {
super(initialCapacity, loadFactor, accessOrder);
}
/**
* Returns whether the eldest entry should be removed. It is removed if the
* size has grown beyond the maximum size allowed for the cache. A {@code
* LinkedHashMap} is created such that the least recently used entry is
* deleted.
*
* @param eldest
* the map entry which will be deleted if we return {@code true}.
*/
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > MAX_NEGATIVE_ENTRIES;
}
/**
* 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) {
checkCacheExists();
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) {
checkCacheExists();
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).intValue();
}
} catch (NumberFormatException e) {
}
if (ttl == 0) {
negCache.clear();
element = null;
} else if (ttl != -1) {
if (element.timeAdded + (ttl * 1000) < System
.currentTimeMillis()) {
// remove the element from the cache and return null
negCache.remove(hostName);
element = null;
}
}
}
if (element != null) {
return element.hostName;
}
return null;
}
/**
* This method checks if we have created the cache and if not creates it
*/
static synchronized void checkCacheExists() {
if (negCache == null) {
/*
* Create with the access order set so ordering is based on when the
* entries were last accessed. We make the default cache size one
* greater than the maximum number of entries as we will grow to one
* larger and then delete the LRU entry
*/
negCache = new NegativeCache<String, NegCacheElement>(
MAX_NEGATIVE_ENTRIES + 1, LOADING, true);
}
}
}