/* * Copyright 2015 LINE Corporation * * LINE Corporation 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 com.linecorp.armeria.server; import static java.util.Objects.requireNonNull; import java.util.Optional; final class PathManipulators { abstract static class PathMappingWrapper extends AbstractPathMapping { private final PathMapping mapping; PathMappingWrapper(PathMapping mapping) { requireNonNull(mapping, "mapping"); this.mapping = mapping; } PathMapping mapping() { return mapping; } @Override public String loggerName() { return mapping.loggerName(); } @Override public String metricName() { return mapping.metricName(); } @Override public Optional<String> exactPath() { return mapping.exactPath(); } } static final class StripPrefixByNumPathComponents extends PathMappingWrapper { private final int numPathComponents; StripPrefixByNumPathComponents(PathMapping mapping, int numPathComponents) { super(mapping); if (numPathComponents <= 0) { throw new IllegalArgumentException( "numPathComponents: " + numPathComponents + " (expected: > 0)"); } this.numPathComponents = numPathComponents; } @Override protected String doApply(String path) { path = mapping().apply(path); if (path == null) { return null; } final int numPathComponents = this.numPathComponents; int i = 1; // Skip the first slash. int strips = 0; for (;;) { int nextI = path.indexOf('/', i); if (nextI < 0) { return null; } strips++; if (strips == numPathComponents) { return path.substring(nextI); } } } @Override public String toString() { return "stripPrefix(" + numPathComponents + ", " + mapping() + ')'; } } static class StripPrefixByPathPrefix extends PathMappingWrapper { private final String pathPrefix; StripPrefixByPathPrefix(PathMapping mapping, String pathPrefix) { super(mapping); ensureAbsolutePath(pathPrefix, "pathPrefix"); if (pathPrefix.endsWith("/")) { this.pathPrefix = pathPrefix; } else { this.pathPrefix = pathPrefix + '/'; } } @Override protected String doApply(String path) { path = mapping().apply(path); if (path == null || !path.startsWith(pathPrefix)) { return null; } return path.substring(pathPrefix.length() - 1); } @Override public String toString() { return "stripPrefix(" + pathPrefix + ", " + mapping() + ')'; } } static class StripParents extends PathMappingWrapper { StripParents(PathMapping mapping) { super(mapping); } @Override protected String doApply(String path) { path = mapping().apply(path); if (path == null) { return null; } if (path.isEmpty()) { throw new IllegalStateException("mapped path is not an absolute path: <empty>"); } // Start from (length - 1) to skip the last slash. final int lastSlashPos = path.lastIndexOf('/', path.length() - 1); return lastSlashPos >= 0 ? path.substring(lastSlashPos) : path; } @Override public String toString() { return "stripParents(" + mapping() + ')'; } } static class Prepend extends PathMappingWrapper { private final String pathPrefix; Prepend(PathMapping mapping, String pathPrefix) { super(mapping); ensureAbsolutePath(pathPrefix, "pathPrefix"); if (pathPrefix.endsWith("/")) { this.pathPrefix = pathPrefix.substring(0, pathPrefix.length() - 1); } else { this.pathPrefix = pathPrefix; } } @Override protected String doApply(String path) { path = mapping().apply(path); if (path == null) { return null; } return pathPrefix + path; } @Override public String toString() { return "prepend(" + pathPrefix + ", " + mapping() + ')'; } } private PathManipulators() {} }