001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2011 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * Sonar is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.api.utils;
021    
022    import org.apache.commons.lang.StringUtils;
023    
024    import java.util.HashMap;
025    import java.util.Map;
026    import java.util.regex.Pattern;
027    
028    /**
029     * @since 1.10
030     */
031    public class WildcardPattern {
032    
033      private static final Map<String, WildcardPattern> patterns = new HashMap<String, WildcardPattern>();
034    
035      private Pattern pattern;
036      private String stringRepresentation;
037    
038      protected WildcardPattern(String pattern, String directorySeparator) {
039        this.stringRepresentation = pattern;
040        this.pattern = Pattern.compile(toRegexp(pattern, directorySeparator));
041      }
042    
043      public boolean match(String value) {
044        return pattern.matcher(removeSlahesToIgnore(value)).matches();
045      }
046    
047      private String toRegexp(String wildcardPattern, String directorySeparator) {
048        String patternStr = removeSlahesToIgnore(wildcardPattern);
049        patternStr = StringUtils.replace(patternStr, "**/**", "**");
050        patternStr = StringUtils.replace(patternStr, "**/", "(&/|)");
051        patternStr = StringUtils.replace(patternStr, "/**", "/&");
052        patternStr = StringUtils.replace(patternStr, "**", "&");
053        StringBuilder sb = new StringBuilder();
054    
055        for (char c : patternStr.toCharArray()) {
056          switch (c) {
057            case '&':
058              sb.append(".*");
059              break;
060            case '*':
061              sb.append("[^\\").append(directorySeparator).append("]*");
062              break;
063            case '?':
064              sb.append("[^\\").append(directorySeparator).append("]");
065              break;
066            case '.':
067              sb.append("\\.");
068              break;
069            case '/':
070              sb.append("\\").append(directorySeparator);
071              break;
072            default:
073              sb.append(c);
074          }
075        }
076    
077        return sb.toString();
078      }
079    
080      private String removeSlahesToIgnore(String wildcardPattern) {
081        String patternStr = StringUtils.removeStart(wildcardPattern, "/");
082        return StringUtils.removeEnd(patternStr, "/");
083      }
084    
085      /**
086       * This method is overridden since version 2.5-RC2.
087       */
088      @Override
089      public String toString() {
090        return stringRepresentation;
091      }
092    
093      /**
094       * @since 2.4
095       */
096      public static boolean match(WildcardPattern[] patterns, String value) {
097        for (WildcardPattern pattern : patterns) {
098          if (pattern.match(value)) {
099            return true;
100          }
101        }
102        return false;
103      }
104    
105      public static WildcardPattern create(String pattern) {
106        return create(pattern, "/");
107      }
108    
109      public static WildcardPattern[] create(String[] patterns) {
110        if (patterns == null) {
111          return new WildcardPattern[0];
112        }
113        WildcardPattern[] exclusionPAtterns = new WildcardPattern[patterns.length];
114        for (int i = 0; i < patterns.length; i++) {
115          exclusionPAtterns[i] = create(patterns[i]);
116        }
117        return exclusionPAtterns;
118      }
119    
120      public static WildcardPattern create(String pattern, String directorySeparator) {
121        String key = pattern + directorySeparator;
122        WildcardPattern wildcardPattern = patterns.get(key);
123        if (wildcardPattern == null) {
124          wildcardPattern = new WildcardPattern(pattern, directorySeparator);
125          patterns.put(key, wildcardPattern);
126        }
127        return wildcardPattern;
128      }
129    }