public class FilterLoader {
final static FilterLoader INSTANCE = new FilterLoader();
private static final Logger LOG = LoggerFactory.getLogger(FilterLoader.class);
private final ConcurrentHashMap<String, Long> filterClassLastModified = new ConcurrentHashMap<String, Long>();
private final ConcurrentHashMap<String, String> filterClassCode = new ConcurrentHashMap<String, String>();
private final ConcurrentHashMap<String, String> filterCheck = new ConcurrentHashMap<String, String>();
private final ConcurrentHashMap<String, List<ZuulFilter>> hashFiltersByType = new ConcurrentHashMap<String, List<ZuulFilter>>();
private FilterRegistry filterRegistry = FilterRegistry.instance();
static DynamicCodeCompiler COMPILER;
static FilterFactory FILTER_FACTORY = new DefaultFilterFactory();
* Sets a Dynamic Code Compiler
*
* @param compiler
*/
public void setCompiler(DynamicCodeCompiler compiler) {
COMPILER = compiler;
}
public void setFilterRegistry(FilterRegistry r) {
this.filterRegistry = r;
}
* Sets a FilterFactory
*
* @param factory
*/
public void setFilterFactory(FilterFactory factory) {
FILTER_FACTORY = factory;
}
* @return Singleton FilterLoader
*/
public static FilterLoader getInstance() {
return INSTANCE;
}
* Given source and name will compile and store the filter if it detects that the filter code has changed or
* the filter doesn't exist. Otherwise it will return an instance of the requested ZuulFilter
*
* @param sCode source code
* @param sName name of the filter
* @return the ZuulFilter
* @throws IllegalAccessException
* @throws InstantiationException
*/
public ZuulFilter getFilter(String sCode, String sName) throws Exception {
if (filterCheck.get(sName) == null) {
filterCheck.putIfAbsent(sName, sName);
if (!sCode.equals(filterClassCode.get(sName))) {
LOG.info("reloading code " + sName);
filterRegistry.remove(sName);
}
}
ZuulFilter filter = filterRegistry.get(sName);
if (filter == null) {
Class clazz = COMPILER.compile(sCode, sName);
if (!Modifier.isAbstract(clazz.getModifiers())) {
filter = (ZuulFilter) FILTER_FACTORY.newInstance(clazz);
}
}
return filter;
}
* @return the total number of Zuul filters
*/
public int filterInstanceMapSize() {
return filterRegistry.size();
}
* From a file this will read the ZuulFilter source code, compile it, and add it to the list of current filters
* a true response means that it was successful.
*
* @param file
* @return true if the filter in file successfully read, compiled, verified and added to Zuul
* @throws IllegalAccessException
* @throws InstantiationException
* @throws IOException
*/
public boolean putFilter(File file) throws Exception {
String sName = file.getAbsolutePath() + file.getName();
if (filterClassLastModified.get(sName) != null && (file.lastModified() != filterClassLastModified.get(sName))) {
LOG.debug("reloading filter " + sName);
filterRegistry.remove(sName);
}
ZuulFilter filter = filterRegistry.get(sName);
if (filter == null) {
Class clazz = COMPILER.compile(file);
if (!Modifier.isAbstract(clazz.getModifiers())) {
filter = (ZuulFilter) FILTER_FACTORY.newInstance(clazz);
List<ZuulFilter> list = hashFiltersByType.get(filter.filterType());
if (list != null) {
hashFiltersByType.remove(filter.filterType());
}
filterRegistry.put(file.getAbsolutePath() + file.getName(), filter);
filterClassLastModified.put(sName, file.lastModified());
return true;
}
}
return false;
}
* 根据Filter类型返回同一类型的Filter
*
* @param filterType
* @return a List<ZuulFilter>
*/
public List<ZuulFilter> getFiltersByType(String filterType) {
List<ZuulFilter> list = hashFiltersByType.get(filterType);
if (list != null) return list;
list = new ArrayList<ZuulFilter>();
Collection<ZuulFilter> filters = filterRegistry.getAllFilters();
for (Iterator<ZuulFilter> iterator = filters.iterator(); iterator.hasNext(); ) {
ZuulFilter filter = iterator.next();
if (filter.filterType().equals(filterType)) {
list.add(filter);
}
}
Collections.sort(list);
hashFiltersByType.putIfAbsent(filterType, list);
return list;
}
}