PathRelativizer.java
/**
* Portions of this software was developed by employees of the National Institute
* of Standards and Technology (NIST), an agency of the Federal Government and is
* being made available as a public service. Pursuant to title 17 United States
* Code Section 105, works of NIST employees are not subject to copyright
* protection in the United States. This software may be subject to foreign
* copyright. Permission in the United States and in foreign countries, to the
* extent that NIST may hold copyright, to use, copy, modify, create derivative
* works, and distribute this software and its documentation without fee is hereby
* granted on a non-exclusive basis, provided that this notice and disclaimer
* of warranty appears in all copies.
*
* THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
* EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
* THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
* INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
* SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT
* SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
* INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
* OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
* CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
* OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
*/
package gov.nist.secauto.swid.builder.resource;
import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
public class PathRelativizer {
public static final Pattern URI_SEPERATOR_PATTERN = Pattern.compile("\\/");
public static final String URI_SEPERATOR = "/";
/**
* Creates a relative sequence of path segments by 1) removing common path segments between the base
* and target, 2) using ".." to change the context from the base to the target directory, and 3) use
* of the remaining portion of the target path to complete the path segments.
*
* @param base
* the base path to relativize from
* @param target
* the target path to relativize to
* @return a sequence of relative path segments pointing to the target from the base
*/
public static List<String> relativize(URI base, URI target) {
// Remove path segments within the path having . and .. segments
base = base.normalize();
target = target.normalize();
return relativize(base.getPath(), target.getPath());
}
/**
* Creates a relative sequence of path segments by 1) removing common path segments between the base
* and target, 2) using ".." to change the context from the base to the target directory, and 3) use
* of the remaining portion of the target path to complete the path segments.
*
* @param base
* the base path to relativize from
* @param target
* the target path to relativize to
* @return a sequence of relative path segments pointing to the target from the base
*/
public static List<String> relativize(String base, String target) {
// Based on code from
// http://stackoverflow.com/questions/10801283/get-relative-path-of-two-uris-in-java
// Split paths into segments
String[] baseSegments = URI_SEPERATOR_PATTERN.split(base);
String[] targetSegments = URI_SEPERATOR_PATTERN.split(target);
// Discard trailing segment of base path
if (baseSegments.length > 0 && !base.endsWith("/")) {
baseSegments = Arrays.copyOf(baseSegments, baseSegments.length - 1);
}
// Remove common prefix segments
int segmentIndex = 0;
while (segmentIndex < baseSegments.length && segmentIndex < targetSegments.length
&& baseSegments[segmentIndex].equals(targetSegments[segmentIndex])) {
segmentIndex++;
}
// Construct the relative path
int size = (baseSegments.length - segmentIndex) + (targetSegments.length - segmentIndex);
List<String> retval = new ArrayList<>(size);
for (int j = 0; j < (baseSegments.length - segmentIndex); j++) {
retval.add("..");
}
for (int j = segmentIndex; j < targetSegments.length; j++) {
retval.add(targetSegments[j]);
}
return Collections.unmodifiableList(retval);
}
/**
* Converts a sequence of path segments to a relative URI.
*
* @param relativePath
* the path segments to base the URI on
* @return a relative URI
*/
public static URI toURI(List<String> relativePath) {
StringBuilder retval = new StringBuilder();
for (String segment : relativePath) {
if (retval.length() > 0) {
retval.append("/");
}
retval.append(segment);
}
return URI.create(retval.toString());
}
/**
* Normalizes path separators to '/'.
*
* @param name
* a file name
* @return a file path that has been normalized
*/
public static String normalize(String name) {
// This will normalize the path separators based on OS semantics
File file = new File(name);
String path = file.getPath();
if (!File.pathSeparator.equals("/")) {
// Paths are expected in a relative URI form
path = path.replaceAll("/", "\\/");
path = path.replaceAll("\\\\", "/");
}
return path;
}
/*
* public static void main(String[] args) { String base = "SWIDTAG/swidtag5977492487829604934.swid";
* String target = "lib/xml-resolver-1.2.jar"; URI baseUri = URI.create(base); URI targetUri =
* URI.create(target); System.out.println("Base: " + baseUri); System.out.println("Target: " +
* targetUri); System.out.println(baseUri.relativize(targetUri)); List<String> pathSegments =
* relativize(base, target); System.out.println("Relative(String) segments: " + pathSegments);
* System.out.println("Relative(String) URI: " + toURI(pathSegments)); pathSegments =
* relativize(baseUri, targetUri); System.out.println("Relative(URI) segments: " + pathSegments);
* System.out.println("Relative(URI) URI: " + toURI(pathSegments)); System.out.println("Normal: " +
* PathRelativizer.normalize("bootstrap\\js\\jquery.filtertable.min.js"));
* System.out.println("Normal: " + PathRelativizer.normalize("swidval-0.0.1-SNAPSHOT.jar"));
* System.out.println("Normal: " + PathRelativizer.normalize("lib/core-0.0.1-SNAPSHOT.jar")); }
*/
}