001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2013 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * SonarQube 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     * SonarQube 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 License
017     * along with this program; if not, write to the Free Software Foundation,
018     * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019     */
020    package org.sonar.api.batch.fs.internal;
021    
022    import org.apache.commons.io.FilenameUtils;
023    import org.apache.commons.lang.StringUtils;
024    import org.sonar.api.batch.fs.InputFile;
025    import org.sonar.api.utils.PathUtils;
026    import org.sonar.api.utils.WildcardPattern;
027    
028    import java.io.File;
029    
030    public abstract class PathPattern {
031    
032      final WildcardPattern pattern;
033    
034      PathPattern(String pattern) {
035        this.pattern = WildcardPattern.create(pattern);
036      }
037    
038      public abstract boolean match(InputFile inputFile);
039    
040      public abstract boolean match(File ioFile, String relativePathFromBasedir);
041    
042      public abstract boolean match(InputFile inputFile, boolean caseSensitiveFileExtension);
043    
044      public static PathPattern create(String s) {
045        String trimmed = StringUtils.trim(s);
046        if (StringUtils.startsWithIgnoreCase(trimmed, "file:")) {
047          return new AbsolutePathPattern(StringUtils.substring(trimmed, "file:".length()));
048        }
049        return new RelativePathPattern(trimmed);
050      }
051    
052      public static PathPattern[] create(String[] s) {
053        PathPattern[] result = new PathPattern[s.length];
054        for (int i = 0; i < s.length; i++) {
055          result[i] = create(s[i]);
056        }
057        return result;
058      }
059    
060      private static class AbsolutePathPattern extends PathPattern {
061        private AbsolutePathPattern(String pattern) {
062          super(pattern);
063        }
064    
065        @Override
066        public boolean match(File ioFile, String relativePathFromBasedir) {
067          String path = PathUtils.sanitize(ioFile.getAbsolutePath());
068          return pattern.match(path);
069        }
070    
071        @Override
072        public boolean match(InputFile inputFile) {
073          return match(inputFile, true);
074        }
075    
076        @Override
077        public boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) {
078          String path = inputFile.absolutePath();
079          if (!caseSensitiveFileExtension) {
080            String extension = sanitizeExtension(FilenameUtils.getExtension(inputFile.file().getName()));
081            if (StringUtils.isNotBlank(extension)) {
082              path = StringUtils.removeEndIgnoreCase(path, extension);
083              path = path + extension;
084            }
085          }
086          return pattern.match(path);
087        }
088    
089        @Override
090        public String toString() {
091          return "file:" + pattern.toString();
092        }
093      }
094    
095      /**
096       * Path relative to module basedir
097       */
098      private static class RelativePathPattern extends PathPattern {
099        private RelativePathPattern(String pattern) {
100          super(pattern);
101        }
102    
103        @Override
104        public boolean match(File ioFile, String relativePathFromBasedir) {
105          return relativePathFromBasedir != null && pattern.match(relativePathFromBasedir);
106        }
107    
108        @Override
109        public boolean match(InputFile inputFile) {
110          return match(inputFile, true);
111        }
112    
113        @Override
114        public boolean match(InputFile inputFile, boolean caseSensitiveFileExtension) {
115          String path = inputFile.relativePath();
116          if (!caseSensitiveFileExtension) {
117            String extension = sanitizeExtension(FilenameUtils.getExtension(inputFile.file().getName()));
118            if (StringUtils.isNotBlank(extension)) {
119              path = StringUtils.removeEndIgnoreCase(path, extension);
120              path = path + extension;
121            }
122          }
123          return path != null && pattern.match(path);
124        }
125    
126        @Override
127        public String toString() {
128          return pattern.toString();
129        }
130      }
131    
132      static String sanitizeExtension(String suffix) {
133        return StringUtils.lowerCase(StringUtils.removeStart(suffix, "."));
134      }
135    }