001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.util; 018 019import org.springframework.lang.Nullable; 020 021/** 022 * Utility methods for simple pattern matching, in particular for 023 * Spring's typical "xxx*", "*xxx" and "*xxx*" pattern styles. 024 * 025 * @author Juergen Hoeller 026 * @since 2.0 027 */ 028public abstract class PatternMatchUtils { 029 030 /** 031 * Match a String against the given pattern, supporting the following simple 032 * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an 033 * arbitrary number of pattern parts), as well as direct equality. 034 * @param pattern the pattern to match against 035 * @param str the String to match 036 * @return whether the String matches the given pattern 037 */ 038 public static boolean simpleMatch(@Nullable String pattern, @Nullable String str) { 039 if (pattern == null || str == null) { 040 return false; 041 } 042 043 int firstIndex = pattern.indexOf('*'); 044 if (firstIndex == -1) { 045 return pattern.equals(str); 046 } 047 048 if (firstIndex == 0) { 049 if (pattern.length() == 1) { 050 return true; 051 } 052 int nextIndex = pattern.indexOf('*', 1); 053 if (nextIndex == -1) { 054 return str.endsWith(pattern.substring(1)); 055 } 056 String part = pattern.substring(1, nextIndex); 057 if (part.isEmpty()) { 058 return simpleMatch(pattern.substring(nextIndex), str); 059 } 060 int partIndex = str.indexOf(part); 061 while (partIndex != -1) { 062 if (simpleMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length()))) { 063 return true; 064 } 065 partIndex = str.indexOf(part, partIndex + 1); 066 } 067 return false; 068 } 069 070 return (str.length() >= firstIndex && 071 pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex)) && 072 simpleMatch(pattern.substring(firstIndex), str.substring(firstIndex))); 073 } 074 075 /** 076 * Match a String against the given patterns, supporting the following simple 077 * pattern styles: "xxx*", "*xxx", "*xxx*" and "xxx*yyy" matches (with an 078 * arbitrary number of pattern parts), as well as direct equality. 079 * @param patterns the patterns to match against 080 * @param str the String to match 081 * @return whether the String matches any of the given patterns 082 */ 083 public static boolean simpleMatch(@Nullable String[] patterns, String str) { 084 if (patterns != null) { 085 for (String pattern : patterns) { 086 if (simpleMatch(pattern, str)) { 087 return true; 088 } 089 } 090 } 091 return false; 092 } 093 094}