PathUtils.java
// 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.doris.common.util;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Objects;
public class PathUtils {
/**
* Compares two URI strings for equality with special handling for the "s3" scheme.
* <p>
* The comparison rules are:
* - If both URIs have the same scheme, compare the full URI strings (case-insensitive).
* - If the schemes differ, but one of them is "s3", then compare only the authority and path parts,
* ignoring the scheme.
* - Otherwise, consider the URIs as not equal.
* <p>
* This is useful in scenarios where "s3" URIs should be treated as equivalent to other schemes
* if the host and path match, ignoring scheme differences.
*
* @param p1 the first URI string to compare
* @param p2 the second URI string to compare
* @return true if the URIs are considered equal under the above rules, false otherwise
*/
public static boolean equalsIgnoreSchemeIfOneIsS3(String p1, String p2) {
if (p1 == null || p2 == null) {
return p1 == null && p2 == null;
}
try {
URI uri1 = new URI(p1);
URI uri2 = new URI(p2);
String scheme1 = uri1.getScheme();
String scheme2 = uri2.getScheme();
// If schemes are equal, compare the full URI strings ignoring case
if (scheme1 != null && scheme1.equalsIgnoreCase(scheme2)) {
return p1.equalsIgnoreCase(p2);
}
// If schemes differ but one is "s3", compare only authority and path ignoring scheme
if ("s3".equalsIgnoreCase(scheme1) || "s3".equalsIgnoreCase(scheme2)) {
String auth1 = normalize(uri1.getAuthority());
String auth2 = normalize(uri2.getAuthority());
String path1 = normalize(uri1.getPath());
String path2 = normalize(uri2.getPath());
return Objects.equals(auth1, auth2) && Objects.equals(path1, path2);
}
// Otherwise, URIs are not equal
return false;
} catch (URISyntaxException e) {
// If URI parsing fails, fallback to simple case-insensitive string comparison
return p1.equalsIgnoreCase(p2);
}
}
/**
* Normalizes a URI component by converting null to empty string and
* removing trailing slashes.
*
* @param s the string to normalize
* @return normalized string without trailing slashes
*/
private static String normalize(String s) {
if (s == null) {
return "";
}
// Remove trailing slashes for consistent comparison
String trimmed = s.replaceAll("/+$", "");
return trimmed.isEmpty() ? "" : trimmed;
}
}