package org.batfish.datamodel; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.batfish.common.util.ComparableStructure; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyDescription; import com.kjetland.jackson.jsonSchema.annotations.JsonSchemaDescription; @JsonSchemaDescription("An AsPathAccessList is used to filter e/iBGP routes according to their AS-path attribute.") public final class AsPathAccessList extends ComparableStructure<String> implements Serializable { private static final String LINES_VAR = "lines"; private static final long serialVersionUID = 1L; private transient Set<AsPath> _deniedCache; private final List<AsPathAccessListLine> _lines; private transient Set<AsPath> _permittedCache; public AsPathAccessList(String name) { super(name); _lines = new ArrayList<>(); } @JsonCreator public AsPathAccessList(@JsonProperty(NAME_VAR) String name, @JsonProperty(LINES_VAR) List<AsPathAccessListLine> lines) { super(name); _lines = lines; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } AsPathAccessList other = (AsPathAccessList) obj; return other._lines.equals(_lines); } @JsonProperty(LINES_VAR) @JsonPropertyDescription("The list of lines against which a route's AS-path will be checked in order.") public List<AsPathAccessListLine> getLines() { return _lines; } private boolean newPermits(AsPath asPath) { boolean accept = false; for (AsPathAccessListLine line : _lines) { String regex = line.getRegex(); Pattern p = Pattern.compile(regex); String asPathString = asPath.getAsPathString(); Matcher matcher = p.matcher(asPathString); boolean match = matcher.find(); if (match) { accept = line.getAction() == LineAction.ACCEPT; break; } } if (accept) { _permittedCache.add(asPath); } else { _deniedCache.add(asPath); } return accept; } public boolean permits(AsPath asPath) { if (_deniedCache.contains(asPath)) { return false; } else if (_permittedCache.contains(asPath)) { return true; } return newPermits(asPath); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); _deniedCache = Collections.newSetFromMap(new ConcurrentHashMap<>()); _permittedCache = Collections.newSetFromMap(new ConcurrentHashMap<>()); } }