blob: e5606c48a5e3f2165ac2b1b7f41d6cf0e128abb1 [file] [log] [blame]
package org.apache.lenya.cms.linking;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.lenya.util.StringUtil;
public class UriUtil {
public static String getRelativeUri(String sourceUri, String targetUri) {
final boolean empty = targetUri.equals("");
if (empty) {
targetUri = "/";
}
final String baseUri = sourceUri.substring(0, sourceUri.lastIndexOf('/') + 1);
final Path basePath = new Path(baseUri);
final Path targetPath = new Path(targetUri);
while (!basePath.isEmpty() && targetPath.size() > 1
&& basePath.first().equals(targetPath.first())) {
basePath.removeFirst();
targetPath.removeFirst();
}
String prefix = basePath.isEmpty() ? "" : generateUpDots(basePath.getSteps().size() - 1);
String targetString = prefix + targetPath;
if (empty) {
if (!targetString.endsWith("/")) {
throw new IllegalStateException("Target URI " + targetString
+ " doesn't end with a slash!");
}
targetString = targetString.substring(0, targetString.length() - 1);
}
try {
return new URI(targetString).normalize().toString();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
protected static String getLastStep(String url) {
return url.substring(url.lastIndexOf("/") + 1);
}
protected static String generateUpDots(int length) {
if (length == 0) {
return "./";
}
final String[] upDotsArray = new String[length];
Arrays.fill(upDotsArray, "..");
return StringUtil.join(upDotsArray, "/") + (upDotsArray.length == 0 ? "" : "/");
}
protected static class Path {
private List<String> steps = new ArrayList<String>();
public Path(final String path) {
if (!path.startsWith("/")) {
throw new IllegalArgumentException("Path " + path + " must start with a slash.");
}
this.steps.addAll(Arrays.asList(path.substring(1).split("/", -1)));
}
public int size() {
return this.steps.size();
}
public String removeFirst() {
return this.steps.remove(0);
}
public String toString() {
return StringUtil.join(this.steps.toArray(new String[this.steps.size()]), "/");
}
public String debug() {
final StringBuffer buf = new StringBuffer();
for (final String step : this.steps) {
buf.append("[" + step + "]");
}
return buf.toString();
}
public List<String> getSteps() {
return Collections.unmodifiableList(this.steps);
}
public boolean isEmpty() {
return this.steps.isEmpty();
}
public String first() {
return this.steps.get(0);
}
public String last() {
return this.steps.get(this.steps.size() - 1);
}
}
}