in poi-ooxml/src/main/java/org/apache/poi/openxml4j/opc/PackagingURIHelper.java [269:384]
public static URI relativizeURI(URI sourceURI, URI targetURI, boolean msCompatible) {
StringBuilder retVal = new StringBuilder();
String[] segmentsSource = sourceURI.getPath().split("/", -1);
String[] segmentsTarget = targetURI.getPath().split("/", -1);
// If the source URI is empty
if (segmentsSource.length == 0) {
throw new IllegalArgumentException(
"Can't relativize an empty source URI !");
}
// If target URI is empty
if (segmentsTarget.length == 0) {
throw new IllegalArgumentException(
"Can't relativize an empty target URI !");
}
// If the source is the root, then the relativized
// form must actually be an absolute URI
if(sourceURI.toString().equals("/")) {
String path = targetURI.getPath();
if(msCompatible && path.length() > 0 && path.charAt(0) == '/') {
try {
targetURI = new URI(path.substring(1));
} catch (Exception e) {
LOG.atWarn().withThrowable(e).log("Failed to relativize");
return null;
}
}
return targetURI;
}
// Relativize the source URI against the target URI.
// First up, figure out how many steps along we can go
// and still have them be the same
int segmentsTheSame = 0;
for (int i = 0; i < segmentsSource.length && i < segmentsTarget.length; i++) {
if (segmentsSource[i].equals(segmentsTarget[i])) {
// Match so far, good
segmentsTheSame++;
} else {
break;
}
}
// If we didn't have a good match or at least except a first empty element
if ((segmentsTheSame == 0 || segmentsTheSame == 1) &&
segmentsSource[0].isEmpty() && segmentsTarget[0].isEmpty()) {
for (int i = 0; i < segmentsSource.length - 2; i++) {
retVal.append("../");
}
for (int i = 0; i < segmentsTarget.length; i++) {
if (segmentsTarget[i].isEmpty())
continue;
retVal.append(segmentsTarget[i]);
if (i != segmentsTarget.length - 1)
retVal.append("/");
}
try {
return new URI(retVal.toString());
} catch (Exception e) {
LOG.atWarn().withThrowable(e).log("Failed to relativize");
return null;
}
}
// Special case for where the two are the same
if (segmentsTheSame == segmentsSource.length
&& segmentsTheSame == segmentsTarget.length) {
if(sourceURI.equals(targetURI)){
// if source and target are the same they should be resolved to the last segment,
// Example: if a slide references itself, e.g. the source URI is
// "/ppt/slides/slide1.xml" and the targetURI is "slide1.xml" then
// this it should be relativized as "slide1.xml", i.e. the last segment.
retVal.append(segmentsSource[segmentsSource.length - 1]);
}
} else {
// Matched for so long, but no more
// Do we need to go up a directory or two from
// the source to get here?
// (If it's all the way up, then don't bother!)
if (segmentsTheSame == 1) {
retVal.append("/");
} else {
for (int j = segmentsTheSame; j < segmentsSource.length - 1; j++) {
retVal.append("../");
}
}
// Now go from here on down
for (int j = segmentsTheSame; j < segmentsTarget.length; j++) {
if (retVal.length() > 0
&& retVal.charAt(retVal.length() - 1) != '/') {
retVal.append("/");
}
retVal.append(segmentsTarget[j]);
}
}
// if the target had a fragment then append it to the result
String fragment = targetURI.getRawFragment();
if (fragment != null) {
retVal.append("#").append(fragment);
}
try {
return new URI(retVal.toString());
} catch (Exception e) {
LOG.atWarn().withThrowable(e).log("Failed to relativize");
return null;
}
}