org.rundeck.storage.api.PathUtil Maven / Gradle / Ivy
/*
* Copyright 2016 SimplifyOps, Inc. (http://simplifyops.com)
*
* 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
*
* 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.rundeck.storage.api;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* Utility methods for paths
*/
public class PathUtil {
public static final String SEPARATOR = "/";
public static final Path ROOT = asPath(SEPARATOR);
public static class PathImpl implements Path {
String pathString;
private String name;
public PathImpl(String pathString) {
this.pathString = pathString;
name = pathName(pathString);
}
@Override
public String getPath() {
return pathString;
}
@Override
public String toString() {
return pathString;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PathImpl)) return false;
PathImpl path = (PathImpl) o;
if (!pathString.equals(path.pathString)) return false;
return true;
}
@Override
public int hashCode() {
return pathString.hashCode();
}
}
public static Path asPath(String path) {
if (null == path) {
return null;
}
return new PathImpl(cleanPath(path));
}
/**
* create a path from an array of components
* @param components path components strings
* @return a path
*/
public static Path pathFromComponents(String[] components) {
if (null == components || components.length == 0) {
return null;
}
return new PathImpl(pathStringFromComponents(components));
}
/**
* create a path from an array of components
* @param components path components strings
* @return a path string
*/
public static String pathStringFromComponents(String[] components) {
if (null == components || components.length == 0) {
return null;
}
return cleanPath(join(components, SEPARATOR));
}
/**
* @param path path
* @return path components
*/
public static String[] componentsFromPath(final Path path) {
return componentsFromPathString(path.getPath());
}
/**
* @param path path string
* @return path components
*/
public static String[] componentsFromPathString(final String path) {
return cleanPath(path).split(SEPARATOR);
}
private static String join(String[] components, String sep) {
StringBuilder sb = new StringBuilder();
for (String component : components) {
if (sb.length() > 0) {
sb.append(sep);
}
sb.append(component);
}
return sb.toString();
}
/**
* @return true if the given path starts with the given root
*
* @param path test path
* @param root root
*
*/
public static boolean hasRoot(Path path, Path root) {
return hasRoot(path.getPath(), root.getPath());
}
/**
* @return true if the given path starts with the given root
*
* @param path test path
* @param root root
*/
public static boolean hasRoot(String path, String root) {
String p = cleanPath(path);
String r = cleanPath(root);
return p.equals(r)
|| r.equals(cleanPath(ROOT.getPath()))
|| p.startsWith(r + SEPARATOR);
}
public static Path parentPath(Path path) {
return asPath(parentPathString(path.getPath()));
}
/**
* @return true if the path is the root
*
* @param path path string
*/
public static boolean isRoot(String path) {
return isRoot(asPath(path));
}
/**
* @return true if the path is the root
* @param path path
*/
public static boolean isRoot(Path path) {
return path.equals(ROOT);
}
/**
* @param patha path A
* @param pathb path B
* @return true if the paths are equal
*/
public static boolean equals(Path patha, Path pathb) {
return cleanPath(patha.getPath()).equals(cleanPath(pathb.getPath()));
}
/**
* Return the string representing the parent of the given path
* @param path path string
* @return parent path string
*/
public static String parentPathString(String path) {
String[] split = componentsFromPathString(path);
if (split.length > 1) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < split.length - 1; i++) {
if (i > 0) {
stringBuilder.append(SEPARATOR);
}
stringBuilder.append(split[i]);
}
return stringBuilder.toString();
}
return "";
}
/**
* Clean the path string by removing leading and trailing slashes and removing duplicate slashes.
* @param path input path
* @return cleaned path string
*/
public static String cleanPath(String path) {
if (path.endsWith(SEPARATOR)) {
path = path.replaceAll(SEPARATOR + "+$", "");
}
if (path.startsWith(SEPARATOR)) {
path = path.replaceAll("^" + SEPARATOR + "+", "");
}
return path.replaceAll("/+", SEPARATOR);
}
public static String pathName(String path) {
String[] split = componentsFromPathString(path);
if (split.length > 0) {
return split[split.length - 1];
}
return null;
}
public static String removePrefix(String rootPath, String extpath) {
if (!hasRoot(extpath, rootPath)) {
return extpath;
}
return cleanPath(cleanPath(extpath).substring(cleanPath(rootPath).length()));
}
/**
* Append one path to another
*
* @param prefix prefix
* @param subpath sub path
*
* @return sub path appended to the prefix
*/
public static Path appendPath(Path prefix, String subpath) {
return asPath(appendPath(prefix.getPath(), subpath));
}
/**
* Append one path to another
*
* @param prefixPath prefix
* @param subpath sub path
*
* @return sub path appended to the prefix
*/
public static String appendPath(String prefixPath, String subpath) {
return cleanPath(prefixPath) + SEPARATOR + cleanPath(subpath);
}
/**
* @return A Path selector that matches the given root path and any resource below it.
*
* @param rootPath path to match
*
*/
public static PathSelector subpathSelector(final Path rootPath) {
return new PathSelector() {
@Override
public boolean matchesPath(Path path) {
return path.equals(rootPath) || PathUtil.hasRoot(path, rootPath);
}
};
}
public static PathSelector allpathSelector() {
return new PathSelector() {
@Override
public boolean matchesPath(Path path) {
return true;
}
};
}
/**
* A resource selector which requires metadata values to be equal to some required strings
*
* @param required required metadata strings
* @param requireAll if true, require all values are equal, otherwise require one value to be equal
* @param content type
*
* @return selector for resources with all or some required metadata values
*/
public static ResourceSelector exactMetadataResourceSelector(final Map required, final boolean requireAll) {
return new ResourceSelector() {
@Override
public boolean matchesContent(T content) {
for (String key : required.keySet()) {
String expect = required.get(key);
String test = content.getMeta().get(key);
if (null != test && expect.equals(test)) {
if (!requireAll) {
return true;
}
} else if (requireAll) {
return false;
}
}
return requireAll;
}
};
}
/**
* A resource selector which requires metadata values to match regexes
*
* @param required required metadata regexes
* @param requireAll if true, require all values match regexes, otherwise require one value to match the regex
* @param content type
*
* @return selector for resources with all or some matching metadata values
*/
public static ResourceSelector regexMetadataResourceSelector(final Map required, final boolean requireAll) {
return new ResourceSelector() {
Map patternMap = new HashMap();
private Pattern forString(String regex) {
if (null == patternMap.get(regex)) {
Pattern compile = null;
try {
compile = Pattern.compile(regex);
} catch (PatternSyntaxException ignored) {
return null;
}
patternMap.put(regex, compile);
}
return patternMap.get(regex);
}
@Override
public boolean matchesContent(T content) {
for (String key : required.keySet()) {
Pattern pattern = forString(required.get(key));
String test = content.getMeta().get(key);
if (null != test && null != pattern && pattern.matcher(test).matches()) {
if (!requireAll) {
return true;
}
} else if (requireAll) {
return false;
}
}
return requireAll;
}
};
}
/**
* compose two selectors
*
* @param a selector 1
* @param b selector 2
* @param and true indicates AND, otherwise OR
* @param resource type
*
* @return new selector appyling the operator to the selector
*/
public static ResourceSelector composeSelector(final ResourceSelector a,
final ResourceSelector b, final boolean and) {
return new ResourceSelector() {
@Override
public boolean matchesContent(T content) {
boolean a1 = a.matchesContent(content);
if (a1 && !and || !a1 && and) {
return a1;
}
return b.matchesContent(content);
}
};
}
/**
* A resource selector which always matches
*
* @param content type
*
* @return selector
*/
public static ResourceSelector allResourceSelector() {
return new ResourceSelector() {
@Override
public boolean matchesContent(T content) {
return true;
}
};
}
/**
* Return a {@link ResourceSelector} constructed using this selector syntax:
*
* key OP value [; key OP value]*
*
* OP can be "=" (exact match) or "=~" (regular expression match).
*
* The returned selector effectively "AND"s the match requirements.
*
* The special string "*" equates to {@link #allResourceSelector()}
*
* @param selector the selector syntax string to parse, not null
* @param resource type
*
* @return a resource selector corresponding to the parsed selector string
*/
public static ResourceSelector resourceSelector(String selector) {
if (null == selector) {
throw new NullPointerException();
}
if("*".equals(selector)) {
return allResourceSelector();
}
String[] split = selector.split(";");
Map values = new HashMap();
Map regexes = new HashMap();
for (int i = 0; i < split.length; i++) {
String s = split[i].trim();
String[] split1 = s.split("=", 2);
if (split1.length == 2) {
String key = split1[0].trim();
String value = split1[1];
if (value.startsWith("~")) {
//regex
regexes.put(key, value.substring(1).trim());
} else {
values.put(key, value.trim());
}
}
}
ResourceSelector equalsSelector = null;
ResourceSelector regexSelector = null;
if (values.size() > 0) {
equalsSelector = PathUtil.exactMetadataResourceSelector(values, true);
}
if (regexes.size() > 0) {
regexSelector = PathUtil.regexMetadataResourceSelector(regexes, true);
}
if (null == equalsSelector) {
return regexSelector;
}
if (null == regexSelector) {
return equalsSelector;
}
return PathUtil.composeSelector(equalsSelector, regexSelector, true);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy