Line data Source code
1 : // Copyright (C) 2014 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.entities; 16 : 17 : import com.google.auto.value.AutoValue; 18 : import com.google.common.collect.ImmutableList; 19 : import com.google.common.flogger.FluentLogger; 20 : import java.util.Objects; 21 : import java.util.Set; 22 : import java.util.regex.Pattern; 23 : import java.util.regex.PatternSyntaxException; 24 : import org.eclipse.jgit.annotations.Nullable; 25 : import org.eclipse.jgit.errors.InvalidPatternException; 26 : import org.eclipse.jgit.fnmatch.FileNameMatcher; 27 : import org.eclipse.jgit.lib.Config; 28 : 29 : @AutoValue 30 152 : public abstract class ConfiguredMimeTypes { 31 152 : private static final FluentLogger logger = FluentLogger.forEnclosingClass(); 32 : 33 : private static final String MIMETYPE = "mimetype"; 34 : private static final String KEY_PATH = "path"; 35 : 36 : public abstract ImmutableList<TypeMatcher> matchers(); 37 : 38 : public static ConfiguredMimeTypes create(String projectName, Config rc) { 39 151 : Set<String> types = rc.getSubsections(MIMETYPE); 40 151 : ImmutableList.Builder<TypeMatcher> matchers = ImmutableList.builder(); 41 151 : if (!types.isEmpty()) { 42 0 : for (String typeName : types) { 43 0 : for (String path : rc.getStringList(MIMETYPE, typeName, KEY_PATH)) { 44 : try { 45 0 : if (path.startsWith("^")) { 46 0 : matchers.add(new ReType(typeName, path)); 47 : } else { 48 0 : matchers.add(new FnType(typeName, path)); 49 : } 50 0 : } catch (PatternSyntaxException | InvalidPatternException e) { 51 0 : logger.atWarning().log( 52 : "Ignoring invalid %s.%s.%s = %s in project %s: %s", 53 0 : MIMETYPE, typeName, KEY_PATH, path, projectName, e.getMessage()); 54 0 : } 55 : } 56 0 : } 57 : } 58 151 : return new AutoValue_ConfiguredMimeTypes(matchers.build()); 59 : } 60 : 61 : public static ConfiguredMimeTypes create(ImmutableList<TypeMatcher> matchers) { 62 16 : return new AutoValue_ConfiguredMimeTypes(matchers); 63 : } 64 : 65 : @Nullable 66 : public String getMimeType(String path) { 67 20 : for (TypeMatcher m : matchers()) { 68 0 : if (m.matches(path)) { 69 0 : return m.type; 70 : } 71 0 : } 72 20 : return null; 73 : } 74 : 75 : public abstract static class TypeMatcher { 76 : private final String type; 77 : private final String pattern; 78 : 79 1 : private TypeMatcher(String type, String pattern) { 80 1 : this.type = type; 81 1 : this.pattern = pattern; 82 1 : } 83 : 84 : public String getPattern() { 85 1 : return pattern; 86 : } 87 : 88 : public String getType() { 89 1 : return type; 90 : } 91 : 92 : protected abstract boolean matches(String path); 93 : } 94 : 95 : public static class FnType extends TypeMatcher { 96 : private final FileNameMatcher matcher; 97 : 98 : public FnType(String type, String pattern) throws InvalidPatternException { 99 1 : super(type, pattern); 100 1 : this.matcher = new FileNameMatcher(pattern, null); 101 1 : } 102 : 103 : @Override 104 : protected boolean matches(String input) { 105 0 : FileNameMatcher m = new FileNameMatcher(matcher); 106 0 : m.append(input); 107 0 : return m.isMatch(); 108 : } 109 : 110 : @Override 111 : public boolean equals(Object o) { 112 1 : if (!(o instanceof FnType)) { 113 0 : return false; 114 : } 115 1 : FnType other = (FnType) o; 116 1 : return Objects.equals(other.getType(), getType()) 117 1 : && Objects.equals(other.getPattern(), getPattern()); 118 : } 119 : 120 : @Override 121 : public int hashCode() { 122 0 : return Objects.hash(getType(), getPattern()); 123 : } 124 : } 125 : 126 : public static class ReType extends TypeMatcher { 127 : private final Pattern re; 128 : 129 : public ReType(String type, String pattern) throws PatternSyntaxException { 130 1 : super(type, pattern); 131 1 : this.re = Pattern.compile(pattern); 132 1 : } 133 : 134 : @Override 135 : protected boolean matches(String input) { 136 0 : return re.matcher(input).matches(); 137 : } 138 : 139 : @Override 140 : public boolean equals(Object o) { 141 1 : if (!(o instanceof ReType)) { 142 0 : return false; 143 : } 144 1 : ReType other = (ReType) o; 145 1 : return Objects.equals(other.getType(), getType()) 146 1 : && Objects.equals(other.getPattern(), getPattern()); 147 : } 148 : 149 : @Override 150 : public int hashCode() { 151 0 : return Objects.hash(getType(), getPattern()); 152 : } 153 : } 154 : }