001/* 002 * SonarQube 003 * Copyright (C) 2009-2017 SonarSource SA 004 * mailto:info AT sonarsource DOT com 005 * 006 * This program 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 * This program 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 */ 020package org.sonar.api.batch.fs.internal; 021 022import javax.annotation.concurrent.ThreadSafe; 023 024import org.apache.commons.io.FilenameUtils; 025import org.apache.commons.lang.StringUtils; 026import org.sonar.api.utils.WildcardPattern; 027 028@ThreadSafe 029public abstract class PathPattern { 030 031 final WildcardPattern pattern; 032 033 PathPattern(String pattern) { 034 this.pattern = WildcardPattern.create(pattern); 035 } 036 037 public abstract boolean match(String absolutePath, String relativePath); 038 039 public abstract boolean match(String absolutePath, String relativePath, boolean caseSensitiveFileExtension); 040 041 public static PathPattern create(String s) { 042 String trimmed = StringUtils.trim(s); 043 if (StringUtils.startsWithIgnoreCase(trimmed, "file:")) { 044 return new AbsolutePathPattern(StringUtils.substring(trimmed, "file:".length())); 045 } 046 return new RelativePathPattern(trimmed); 047 } 048 049 public static PathPattern[] create(String[] s) { 050 PathPattern[] result = new PathPattern[s.length]; 051 for (int i = 0; i < s.length; i++) { 052 result[i] = create(s[i]); 053 } 054 return result; 055 } 056 057 private static class AbsolutePathPattern extends PathPattern { 058 private AbsolutePathPattern(String pattern) { 059 super(pattern); 060 } 061 062 @Override 063 public boolean match(String absolutePath, String relativePath) { 064 return match(absolutePath, relativePath, true); 065 } 066 067 @Override 068 public boolean match(String absolutePath, String relativePath, boolean caseSensitiveFileExtension) { 069 String path = absolutePath; 070 if (!caseSensitiveFileExtension) { 071 String extension = sanitizeExtension(FilenameUtils.getExtension(relativePath)); 072 if (StringUtils.isNotBlank(extension)) { 073 path = StringUtils.removeEndIgnoreCase(path, extension); 074 path = path + extension; 075 } 076 } 077 return pattern.match(path); 078 } 079 080 @Override 081 public String toString() { 082 return "file:" + pattern.toString(); 083 } 084 } 085 086 /** 087 * Path relative to module basedir 088 */ 089 private static class RelativePathPattern extends PathPattern { 090 private RelativePathPattern(String pattern) { 091 super(pattern); 092 } 093 094 @Override 095 public boolean match(String absolutePath, String relativePath) { 096 return match(absolutePath, relativePath, true); 097 } 098 099 @Override 100 public boolean match(String absolutePath, String relativePath, boolean caseSensitiveFileExtension) { 101 String path = relativePath; 102 if (!caseSensitiveFileExtension) { 103 String extension = sanitizeExtension(FilenameUtils.getExtension(relativePath)); 104 if (StringUtils.isNotBlank(extension)) { 105 path = StringUtils.removeEndIgnoreCase(path, extension); 106 path = path + extension; 107 } 108 } 109 return path != null && pattern.match(path); 110 } 111 112 @Override 113 public String toString() { 114 return pattern.toString(); 115 } 116 } 117 118 static String sanitizeExtension(String suffix) { 119 return StringUtils.lowerCase(StringUtils.removeStart(suffix, ".")); 120 } 121}