All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.flink.runtime.rest.handler.router.PathPattern Maven / Gradle / Ivy

There is a newer version: 1.13.6
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.flink.runtime.rest.handler.router;

import java.util.Map;

import static org.apache.flink.util.Preconditions.checkNotNull;

/**
 * This is adopted and simplified code from tv.cntt:netty-router library. For more information check {@link Router}.
 * Original code:
 * https://github.com/sinetja/netty-router/blob/2.2.0/src/main/java/io/netty/handler/codec/http/router/PathPattern.java
 *
 * 

The pattern can contain constants or placeholders, example: * {@code constant1/:placeholder1/constant2/:*}. * *

{@code :*} is a special placeholder to catch the rest of the path * (may include slashes). If exists, it must appear at the end of the path. * *

The pattern must not contain query, example: * {@code constant1/constant2?foo=bar}. * *

The pattern will be broken to tokens, example: * {@code ["constant1", ":variable", "constant2", ":*"]} */ final class PathPattern { private final String pattern; //-------------------------------------------------------------------------- private final String[] tokens; /** * The pattern must not contain query, example: * {@code constant1/constant2?foo=bar}. * *

The pattern will be stored without slashes at both ends. */ public PathPattern(String pattern) { if (pattern.contains("?")) { throw new IllegalArgumentException("Path pattern must not contain query"); } this.pattern = removeSlashesAtBothEnds(checkNotNull(pattern, "pattern")); this.tokens = this.pattern.split("/"); } public static String removeSlashesAtBothEnds(String path) { checkNotNull(path, "path"); if (path.isEmpty()) { return path; } int beginIndex = 0; while (beginIndex < path.length() && path.charAt(beginIndex) == '/') { beginIndex++; } if (beginIndex == path.length()) { return ""; } int endIndex = path.length() - 1; while (endIndex > beginIndex && path.charAt(endIndex) == '/') { endIndex--; } return path.substring(beginIndex, endIndex + 1); } /** * Returns the pattern given at the constructor, without slashes at both ends. */ public String pattern() { return pattern; } /** * Returns the pattern given at the constructor, without slashes at both ends, * and split by {@code '/'}. */ public String[] tokens() { return tokens; } //-------------------------------------------------------------------------- // Instances of this class can be conveniently used as Map keys. @Override public int hashCode() { return pattern.hashCode(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof PathPattern)) { return false; } PathPattern otherPathPattern = (PathPattern) o; return pattern.equals(otherPathPattern.pattern); } //-------------------------------------------------------------------------- /** * {@code params} will be updated with params embedded in the request path. * *

This method signature is designed so that {@code requestPathTokens} and {@code params} * can be created only once then reused, to optimize for performance when a * large number of path patterns need to be matched. * * @return {@code false} if not matched; in this case params should be reset */ public boolean match(String[] requestPathTokens, Map params) { if (tokens.length == requestPathTokens.length) { for (int i = 0; i < tokens.length; i++) { String key = tokens[i]; String value = requestPathTokens[i]; if (key.length() > 0 && key.charAt(0) == ':') { // This is a placeholder params.put(key.substring(1), value); } else if (!key.equals(value)) { // This is a constant return false; } } return true; } if (tokens.length > 0 && tokens[tokens.length - 1].equals(":*") && tokens.length <= requestPathTokens.length) { // The first part for (int i = 0; i < tokens.length - 2; i++) { String key = tokens[i]; String value = requestPathTokens[i]; if (key.length() > 0 && key.charAt(0) == ':') { // This is a placeholder params.put(key.substring(1), value); } else if (!key.equals(value)) { // This is a constant return false; } } // The last :* part StringBuilder b = new StringBuilder(requestPathTokens[tokens.length - 1]); for (int i = tokens.length; i < requestPathTokens.length; i++) { b.append('/'); b.append(requestPathTokens[i]); } params.put("*", b.toString()); return true; } return false; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy