/* * This file is part of ReadonlyREST. * * ReadonlyREST is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ReadonlyREST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ReadonlyREST. If not, see http://www.gnu.org/licenses/ */ package org.elasticsearch.plugin.readonlyrest.acl.domain; import com.google.common.base.Strings; import com.google.common.collect.Sets; import java.util.HashSet; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Created by sscarduzio on 02/04/2016. */ public class MatcherWithWildcards { private static Set<String> empty = new HashSet<>(0); private final Set<String> allMatchers = Sets.newHashSet(); private final Set<Pattern> wildcardMatchers = Sets.newHashSet(); public MatcherWithWildcards(Set<String> matchers) { for (String a : matchers) { a = normalizePlusAndMinusIndex(a); if (Strings.isNullOrEmpty(a)) { continue; } if (a.contains("*")) { // Patch the simple star wildcard to become a regex: ("*" -> ".*") String regex = "^" + ("\\Q" + a + "\\E").replace("*", "\\E.*\\Q") + "$"; // Pre-compile the regex pattern matcher to validate the regex // AND faster matching later on. wildcardMatchers.add(Pattern.compile(regex)); // Let's match this also literally allMatchers.add(a); } else { // A plain word can be matched as string allMatchers.add(a.trim()); } } } /** * Returns null if the matchable is not worth processing because it's invalid or starts with "-" */ private String normalizePlusAndMinusIndex(String s) { if (Strings.isNullOrEmpty(s)) { return null; } // Ignore the excluded indices if (s.startsWith("-")) { return null; } // Call included indices with their name if (s.startsWith("+")) { if (s.length() == 1) { return null; } return s.substring(1, s.length()); } return s; } public Set<String> getMatchers() { return allMatchers; } public String matchWithResult(String matchable) { matchable = normalizePlusAndMinusIndex(matchable); if (matchable == null) { return null; } // Try to match plain strings first if (allMatchers.contains(matchable)) { return matchable; } for (Pattern p : wildcardMatchers) { Matcher m = p.matcher(matchable); if (m == null) { continue; } if (m.find()) { return matchable; } } return null; } public boolean match(String s) { return matchWithResult(s) != null; } public Set<String> filter(Set<String> haystack) { if (haystack.isEmpty()) return empty; Set<String> res = Sets.newHashSet(); for (String s : haystack) { if (match(s)) { res.add(s); } } return res; } }