Java tutorial
/* * Copyright 2002-2019 the original author or authors. * * 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 * * https://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.springframework.http.server; import java.util.List; import org.springframework.util.MultiValueMap; /** * Structured representation of a URI path parsed via {@link #parsePath(String)} * into a sequence of {@link Separator} and {@link PathSegment} elements. * * <p>Each {@link PathSegment} exposes its content in decoded form and with path * parameters removed. This makes it safe to match one path segment at a time * without the risk of decoded reserved characters altering the structure of * the path. * * @author Rossen Stoyanchev * @since 5.0 */ public interface PathContainer { /** * The original path from which this instance was parsed. */ String value(); /** * The contained path elements, either {@link Separator} or {@link PathSegment}. */ List<Element> elements(); /** * Extract a sub-path from the given offset into the elements list. * @param index the start element index (inclusive) * @return the sub-path */ default PathContainer subPath(int index) { return subPath(index, elements().size()); } /** * Extract a sub-path from the given start offset into the element list * (inclusive) and to the end offset (exclusive). * @param startIndex the start element index (inclusive) * @param endIndex the end element index (exclusive) * @return the sub-path */ default PathContainer subPath(int startIndex, int endIndex) { return DefaultPathContainer.subPath(this, startIndex, endIndex); } /** * Parse the path value into a sequence of {@code "/"} {@link Separator Separator} * and {@link PathSegment PathSegment} elements. * @param path the encoded, raw path value to parse * @return the parsed path */ static PathContainer parsePath(String path) { return DefaultPathContainer.createFromUrlPath(path, Options.HTTP_PATH); } /** * Parse the path value into a sequence of {@link Separator Separator} and * {@link PathSegment PathSegment} elements. * @param path the encoded, raw path value to parse * @param options to customize parsing * @return the parsed path * @since 5.2 */ static PathContainer parsePath(String path, Options options) { return DefaultPathContainer.createFromUrlPath(path, options); } /** * A path element, either separator or path segment. */ interface Element { /** * The unmodified, original value of this element. */ String value(); } /** * Path separator element. */ interface Separator extends Element { } /** * Path segment element. */ interface PathSegment extends Element { /** * Return the path segment value, decoded and sanitized, for path matching. */ String valueToMatch(); /** * Expose {@link #valueToMatch()} as a character array. */ char[] valueToMatchAsChars(); /** * Path parameters associated with this path segment. */ MultiValueMap<String, String> parameters(); } /** * Options to customize parsing based on the type of input path. * @since 5.2 */ class Options { /** * Options for HTTP URL paths: * <p>Separator '/' with URL decoding and parsing of path params. */ public final static Options HTTP_PATH = Options.create('/', true); /** * Options for a message route: * <p>Separator '.' without URL decoding nor parsing of params. Escape * sequences for the separator char in segment values are still decoded. */ public final static Options MESSAGE_ROUTE = Options.create('.', false); private final char separator; private final boolean decodeAndParseSegments; private Options(char separator, boolean decodeAndParseSegments) { this.separator = separator; this.decodeAndParseSegments = decodeAndParseSegments; } public char separator() { return this.separator; } public boolean shouldDecodeAndParseSegments() { return this.decodeAndParseSegments; } /** * Create an {@link Options} instance with the given settings. * @param separator the separator for parsing the path into segments; * currently this must be slash or dot. * @param decodeAndParseSegments whether to URL decode path segment * values and parse path parameters. If set to false, only escape * sequences for the separator char are decoded. */ public static Options create(char separator, boolean decodeAndParseSegments) { return new Options(separator, decodeAndParseSegments); } } }