package com.zendesk.maxwell;
import org.apache.commons.lang.StringUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
/*
filters compile down to:
(includeDatabases.nil? || includeDatabases.include?()
*/
public class MaxwellFilter {
private static final List<Pattern> emptyList = Collections.unmodifiableList(new ArrayList<Pattern>());
private final ArrayList<Pattern> includeDatabases = new ArrayList<>();
private final ArrayList<Pattern> excludeDatabases = new ArrayList<>();
private final ArrayList<Pattern> includeTables = new ArrayList<>();
private final ArrayList<Pattern> excludeTables = new ArrayList<>();
private final ArrayList<Pattern> blacklistDatabases = new ArrayList<>();
private final ArrayList<Pattern> blacklistTables = new ArrayList<>();
public MaxwellFilter() { }
public MaxwellFilter(String includeDatabases,
String excludeDatabases,
String includeTables,
String excludeTables,
String blacklistDatabases,
String blacklistTables) throws MaxwellInvalidFilterException {
if ( includeDatabases != null ) {
for (String s : includeDatabases.split(","))
includeDatabase(s);
}
if ( excludeDatabases != null ) {
for (String s : excludeDatabases.split(","))
excludeDatabase(s);
}
if ( includeTables != null ) {
for ( String s : includeTables.split(",") )
includeTable(s);
}
if ( excludeTables != null ) {
for (String s : excludeTables.split(","))
excludeTable(s);
}
if ( blacklistDatabases != null ) {
for ( String s : blacklistDatabases.split(",") )
blacklistDatabases(s);
}
if ( blacklistTables != null ) {
for ( String s : blacklistTables.split(",") )
blacklistTable(s);
}
}
public void includeDatabase(String name) throws MaxwellInvalidFilterException {
includeDatabases.add(compile(name));
}
public void excludeDatabase(String name) throws MaxwellInvalidFilterException {
excludeDatabases.add(compile(name));
}
public void includeTable(String name) throws MaxwellInvalidFilterException {
includeTables.add(compile(name));
}
public void excludeTable(String name) throws MaxwellInvalidFilterException {
excludeTables.add(compile(name));
}
public void blacklistDatabases(String name) throws MaxwellInvalidFilterException {
blacklistDatabases.add(compile(name));
}
public void blacklistTable(String name) throws MaxwellInvalidFilterException {
blacklistTables.add(compile(name));
}
public boolean isDatabaseWhitelist() {
return !includeDatabases.isEmpty();
}
public boolean isTableWhitelist() {
return !includeTables.isEmpty();
}
private Pattern compile(String name) throws MaxwellInvalidFilterException {
return MaxwellConfig.compileStringToPattern(name);
}
private boolean filterListsInclude(List<Pattern> includeList, List<Pattern> excludeList, String name) {
if ( includeList.size() > 0 ) {
boolean found = false;
for ( Pattern p : includeList ) {
found = p.matcher(name).find();
if ( found )
break;
}
if ( !found )
return false;
}
for ( Pattern p : excludeList ) {
if ( p.matcher(name).find() )
return false;
}
return true;
}
private boolean matchesDatabase(String dbName) {
return filterListsInclude(includeDatabases, excludeDatabases, dbName);
}
private boolean matchesTable(String tableName) {
return filterListsInclude(includeTables, excludeTables, tableName);
}
public boolean matches(String database, String table) {
return matchesDatabase(database) && matchesTable(table);
}
public boolean isDatabaseBlacklisted(String databaseName) {
return ! filterListsInclude(emptyList, blacklistDatabases, databaseName);
}
public boolean isTableBlacklisted(String databaseName, String tableName) {
return isSystemBlacklisted(databaseName, tableName)
|| isDatabaseBlacklisted(databaseName)
|| !filterListsInclude(emptyList, blacklistTables, tableName);
}
public static boolean isSystemBlacklisted(String databaseName, String tableName) {
return "mysql".equals(databaseName) &&
("ha_health_check".equals(tableName) || StringUtils.startsWith(tableName, "rds_heartbeat"));
}
public static boolean matches(MaxwellFilter filter, String database, String table) {
if (filter == null) {
return true;
} else {
return filter.matches(database, table);
}
}
}