LCOV - code coverage report
Current view: top level - server/project - RefPattern.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 36 44 81.8 %
Date: 2022-11-19 15:00:39 Functions: 10 11 90.9 %

          Line data    Source code
       1             : // Copyright (C) 2016 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.server.project;
      16             : 
      17             : import com.google.common.base.Throwables;
      18             : import com.google.common.cache.CacheBuilder;
      19             : import com.google.common.cache.CacheLoader;
      20             : import com.google.common.cache.LoadingCache;
      21             : import com.google.common.collect.ImmutableMap;
      22             : import com.google.gerrit.common.data.ParameterizedString;
      23             : import com.google.gerrit.entities.AccessSection;
      24             : import com.google.gerrit.exceptions.InvalidNameException;
      25             : import dk.brics.automaton.RegExp;
      26             : import java.util.Map;
      27             : import java.util.concurrent.ExecutionException;
      28             : import java.util.regex.Pattern;
      29             : import java.util.regex.PatternSyntaxException;
      30             : import org.eclipse.jgit.lib.Repository;
      31             : 
      32           0 : public class RefPattern {
      33             :   public static final String USERID_SHARDED = "shardeduserid";
      34             :   public static final String USERNAME = "username";
      35             : 
      36         151 :   private static final LoadingCache<String, String> exampleCache =
      37         151 :       CacheBuilder.newBuilder()
      38         151 :           .maximumSize(4000)
      39         151 :           .build(
      40         151 :               new CacheLoader<String, String>() {
      41             :                 @Override
      42             :                 public String load(String refPattern) {
      43           3 :                   return example(refPattern);
      44             :                 }
      45             :               });
      46             : 
      47             :   public static String shortestExample(String refPattern) {
      48           3 :     if (isRE(refPattern)) {
      49             :       try {
      50           3 :         return exampleCache.get(refPattern);
      51           0 :       } catch (ExecutionException e) {
      52           0 :         Throwables.throwIfUnchecked(e.getCause());
      53           0 :         throw new RuntimeException(e);
      54             :       }
      55           0 :     } else if (refPattern.endsWith("/*")) {
      56           0 :       return refPattern.substring(0, refPattern.length() - 1) + '1';
      57             :     } else {
      58           0 :       return refPattern;
      59             :     }
      60             :   }
      61             : 
      62             :   static String example(String refPattern) {
      63             :     // Since Brics will substitute dot [.] with \0 when generating
      64             :     // shortest example, any usage of dot will fail in
      65             :     // Repository.isValidRefName() if not combined with star [*].
      66             :     // To get around this, we substitute the \0 with an arbitrary
      67             :     // accepted character.
      68           3 :     return toRegExp(refPattern).toAutomaton().getShortestExample(true).replace('\0', '-');
      69             :   }
      70             : 
      71             :   public static boolean isRE(String refPattern) {
      72         145 :     return refPattern.startsWith(AccessSection.REGEX_PREFIX);
      73             :   }
      74             : 
      75             :   public static boolean containsParameters(String refPattern) {
      76         145 :     return refPattern.contains("${");
      77             :   }
      78             : 
      79             :   public static RegExp toRegExp(String refPattern) {
      80           3 :     if (isRE(refPattern)) {
      81           3 :       refPattern = refPattern.substring(1);
      82             :     }
      83           3 :     ParameterizedString template = new ParameterizedString(refPattern);
      84           3 :     String replacement = "_PLACEHOLDER_";
      85           3 :     Map<String, String> params =
      86           3 :         ImmutableMap.of(
      87             :             RefPattern.USERID_SHARDED, replacement,
      88             :             RefPattern.USERNAME, replacement);
      89           3 :     return new RegExp(template.replace(params), RegExp.NONE);
      90             :   }
      91             : 
      92             :   public static void validate(String refPattern) throws InvalidNameException {
      93           9 :     if (refPattern.startsWith(AccessSection.REGEX_PREFIX)) {
      94           3 :       if (!Repository.isValidRefName(shortestExample(refPattern))) {
      95           1 :         throw new InvalidNameException(refPattern);
      96             :       }
      97           9 :     } else if (refPattern.equals(AccessSection.ALL)) {
      98             :       // This is a special case we have to allow, it fails below.
      99           5 :     } else if (refPattern.endsWith("/*")) {
     100           4 :       String prefix = refPattern.substring(0, refPattern.length() - 2);
     101           4 :       if (!Repository.isValidRefName(prefix)) {
     102           0 :         throw new InvalidNameException(refPattern);
     103             :       }
     104           5 :     } else if (!Repository.isValidRefName(refPattern)) {
     105           3 :       throw new InvalidNameException(refPattern);
     106             :     }
     107           9 :     validateRegExp(refPattern);
     108           9 :   }
     109             : 
     110             :   public static void validateRegExp(String refPattern) throws InvalidNameException {
     111             :     try {
     112         151 :       refPattern = refPattern.replace("${" + USERID_SHARDED + "}", "");
     113         151 :       refPattern = refPattern.replace("${" + USERNAME + "}", "");
     114         151 :       Pattern.compile(refPattern);
     115           1 :     } catch (PatternSyntaxException e) {
     116           1 :       throw new InvalidNameException(refPattern + " " + e.getMessage());
     117         151 :     }
     118         151 :   }
     119             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750