/* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.controller.filtervalve.cors.model; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Maps.immutableEntry; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Match incoming URL with user defined patterns according to servlet specification. * In the Web application deployment descriptor, the following syntax is used to define mappings: * */ public class UrlMatcher { private static final Logger logger = LoggerFactory.getLogger(UrlMatcher.class); // order index for each FILTER is kept as Entry.value private final Map> prefixMap = new HashMap<>(); // contains patterns ending with '/*', '*' is stripped from each key private final Map> suffixMap = new HashMap<>(); // contains patterns starting with '*.' prefix, '*' is stripped from each key private final Map> exactMatchMap = new HashMap<>(); // contains exact matches only /** * @param patternMap order preserving map containing path info pattern as key */ public UrlMatcher(LinkedHashMap patternMap) { int idx = 0; for (Entry entry : patternMap.entrySet()) { idx++; String pattern = checkNotNull(entry.getKey()); FILTER value = entry.getValue(); Entry valueWithIdx = immutableEntry(value, idx); if (pattern.startsWith("/") && pattern.endsWith("/*")) { pattern = pattern.substring(0, pattern.length() - 1); prefixMap.put(pattern, valueWithIdx); } else if (pattern.startsWith("*.")) { pattern = pattern.substring(1); suffixMap.put(pattern, valueWithIdx); } else { exactMatchMap.put(pattern, valueWithIdx); } } } /** * Find filters matching path * * @param pathInfo as returned by request.getPathInfo() * @return list of matching filters */ public List findMatchingFilters(String pathInfo) { checkNotNull(pathInfo); TreeMap sortedMap = new TreeMap<>(); // add matching prefixes for (Entry> prefixEntry : prefixMap.entrySet()) { if (pathInfo.startsWith(prefixEntry.getKey())) { put(sortedMap, prefixEntry.getValue()); } } // add matching suffixes for (Entry> suffixEntry : suffixMap.entrySet()) { if (pathInfo.endsWith(suffixEntry.getKey())) { put(sortedMap, suffixEntry.getValue()); } } // add exact match Entry exactMatch = exactMatchMap.get(pathInfo); if (exactMatch != null) { put(sortedMap, exactMatch); } ArrayList filters = new ArrayList<>(sortedMap.values()); logger.trace("Matching filters for path {} are {}", pathInfo, filters); return filters; } private void put(TreeMap sortedMap, Entry entry) { sortedMap.put(entry.getValue(), entry.getKey()); } }