summaryrefslogtreecommitdiffstats
path: root/java/com/google/gerrit/server/project/RefPattern.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/google/gerrit/server/project/RefPattern.java')
-rw-r--r--java/com/google/gerrit/server/project/RefPattern.java107
1 files changed, 107 insertions, 0 deletions
diff --git a/java/com/google/gerrit/server/project/RefPattern.java b/java/com/google/gerrit/server/project/RefPattern.java
new file mode 100644
index 0000000000..72face2fb6
--- /dev/null
+++ b/java/com/google/gerrit/server/project/RefPattern.java
@@ -0,0 +1,107 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.project;
+
+import com.google.common.base.Throwables;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.gerrit.common.data.AccessSection;
+import com.google.gerrit.common.data.RefConfigSection;
+import com.google.gerrit.common.errors.InvalidNameException;
+import dk.brics.automaton.RegExp;
+import java.util.concurrent.ExecutionException;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import org.eclipse.jgit.lib.Repository;
+
+public class RefPattern {
+ public static final String USERID_SHARDED = "shardeduserid";
+ public static final String USERNAME = "username";
+
+ private static final LoadingCache<String, String> exampleCache =
+ CacheBuilder.newBuilder()
+ .maximumSize(4000)
+ .build(
+ new CacheLoader<String, String>() {
+ @Override
+ public String load(String refPattern) {
+ return example(refPattern);
+ }
+ });
+
+ public static String shortestExample(String refPattern) {
+ if (isRE(refPattern)) {
+ try {
+ return exampleCache.get(refPattern);
+ } catch (ExecutionException e) {
+ Throwables.throwIfUnchecked(e.getCause());
+ throw new RuntimeException(e);
+ }
+ } else if (refPattern.endsWith("/*")) {
+ return refPattern.substring(0, refPattern.length() - 1) + '1';
+ } else {
+ return refPattern;
+ }
+ }
+
+ static String example(String refPattern) {
+ // Since Brics will substitute dot [.] with \0 when generating
+ // shortest example, any usage of dot will fail in
+ // Repository.isValidRefName() if not combined with star [*].
+ // To get around this, we substitute the \0 with an arbitrary
+ // accepted character.
+ return toRegExp(refPattern).toAutomaton().getShortestExample(true).replace('\0', '-');
+ }
+
+ public static boolean isRE(String refPattern) {
+ return refPattern.startsWith(AccessSection.REGEX_PREFIX);
+ }
+
+ public static RegExp toRegExp(String refPattern) {
+ if (isRE(refPattern)) {
+ refPattern = refPattern.substring(1);
+ }
+ return new RegExp(refPattern, RegExp.NONE);
+ }
+
+ public static void validate(String refPattern) throws InvalidNameException {
+ if (refPattern.startsWith(RefConfigSection.REGEX_PREFIX)) {
+ if (!Repository.isValidRefName(shortestExample(refPattern))) {
+ throw new InvalidNameException(refPattern);
+ }
+ } else if (refPattern.equals(RefConfigSection.ALL)) {
+ // This is a special case we have to allow, it fails below.
+ } else if (refPattern.endsWith("/*")) {
+ String prefix = refPattern.substring(0, refPattern.length() - 2);
+ if (!Repository.isValidRefName(prefix)) {
+ throw new InvalidNameException(refPattern);
+ }
+ } else if (!Repository.isValidRefName(refPattern)) {
+ throw new InvalidNameException(refPattern);
+ }
+ validateRegExp(refPattern);
+ }
+
+ public static void validateRegExp(String refPattern) throws InvalidNameException {
+ try {
+ refPattern = refPattern.replace("${" + USERID_SHARDED + "}", "");
+ refPattern = refPattern.replace("${" + USERNAME + "}", "");
+ Pattern.compile(refPattern);
+ } catch (PatternSyntaxException e) {
+ throw new InvalidNameException(refPattern + " " + e.getMessage());
+ }
+ }
+}