blob: c818d8f0f39d8f752e44431e5f07b76a13946f60 [file] [log] [blame]
package freemarker.core;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import freemarker.template.utility.ClassUtil;
import freemarker.template.utility.UndeclaredThrowableException;
/**
* For internal usage only; don't depend on this!
* Creates {@code java.util.concurrent.ConcurrentMap}-s on J2SE 5 or later,
* plain maps otherwise. This is used for avoiding linking-time J2SE 5
* dependency.
*
* This class will be removed when J2SE 5 becomes the required
* minimum for FreeMarker, so don't use it unless you are developing
* FreeMarker itself.
*/
public class _ConcurrentMapFactory {
private static final Class concurrentMapClass = getConcurrentMapClass();
private static final Class bestHashMapClass = getBestHashMapClass();
static public Map newMaybeConcurrentHashMap() {
try {
return (Map) bestHashMapClass.newInstance();
} catch(Exception e) {
throw new UndeclaredThrowableException(e);
}
}
/**
* Returns an instance of the "best" thread-safe {@link Map} available in
* the current runtime environment.
*/
public static Map newThreadSafeMap() {
Map map = newMaybeConcurrentHashMap();
return isConcurrent(map) ? map : Collections.synchronizedMap(map);
}
static public boolean concurrentMapsAvailable() {
return concurrentMapClass != null;
}
/**
* Checks if the map is concurrent; safe to call before J2SE 5.
*/
static public boolean isConcurrent(Map map) {
return concurrentMapClass != null && concurrentMapClass.isInstance(map);
}
private static Class getConcurrentMapClass() {
try {
return ClassUtil.forName("java.util.concurrent.ConcurrentMap");
} catch(ClassNotFoundException e) {
return null;
}
}
private static Class getBestHashMapClass() {
try {
return ClassUtil.forName("java.util.concurrent.ConcurrentHashMap");
} catch(ClassNotFoundException e) {
return HashMap.class;
}
}
}