001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.eclipse.aether.util;
020
021import java.util.Collections;
022import java.util.HashMap;
023import java.util.Map;
024
025import static java.util.Objects.requireNonNull;
026
027/**
028 * A reusable utility class for file paths.
029 *
030 * @since 2.0.13
031 */
032public final class PathUtils {
033    private PathUtils() {
034        // hide constructor
035    }
036
037    private static final Map<String, String> ILLEGAL_PATH_SEGMENT_REPLACEMENTS;
038
039    static {
040        HashMap<String, String> illegalPathSegmentReplacements = new HashMap<>();
041        illegalPathSegmentReplacements.put("\\", "-BACKSLASH-");
042        illegalPathSegmentReplacements.put("/", "-SLASH-");
043        illegalPathSegmentReplacements.put(":", "-COLON-");
044        illegalPathSegmentReplacements.put("\"", "-QUOTE-");
045        illegalPathSegmentReplacements.put("<", "-LT-");
046        illegalPathSegmentReplacements.put(">", "-GT-");
047        illegalPathSegmentReplacements.put("|", "-PIPE-");
048        illegalPathSegmentReplacements.put("?", "-QMARK-");
049        illegalPathSegmentReplacements.put("*", "-ASTERISK-");
050        ILLEGAL_PATH_SEGMENT_REPLACEMENTS = Collections.unmodifiableMap(illegalPathSegmentReplacements);
051    }
052
053    /**
054     * Method that makes sure that passed in string is valid "path segment" string. It achieves it by potentially
055     * changing it, replacing illegal characters in it with legal ones.
056     * <p>
057     * Note: this method considers empty string as "valid path segment", it is caller duty to ensure empty string
058     * is not used as path segment alone.
059     * <p>
060     * This method is simplistic on purpose, and if frequently used, best if results are cached (per session)
061     */
062    public static String stringToPathSegment(String string) {
063        requireNonNull(string);
064        StringBuilder result = new StringBuilder(string);
065        for (Map.Entry<String, String> entry : ILLEGAL_PATH_SEGMENT_REPLACEMENTS.entrySet()) {
066            String illegal = entry.getKey();
067            int pos = result.indexOf(illegal);
068            while (pos >= 0) {
069                result.replace(pos, pos + illegal.length(), entry.getValue());
070                pos = result.indexOf(illegal);
071            }
072        }
073        return result.toString();
074    }
075}