CodeLocations.java
package org.jbehave.core.io;
import static org.apache.commons.lang3.StringUtils.removeEnd;
import static org.apache.commons.lang3.StringUtils.removeStart;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
/**
* Collection of utility methods to create code location URLs
*/
public class CodeLocations {
/**
* Creates a code location URL from a class
*
* @param codeLocationClass the class
* @return A URL created from Class
* @throws InvalidCodeLocation if URL creation fails
*/
public static URL codeLocationFromClass(Class<?> codeLocationClass) {
String pathOfClass = codeLocationClass.getName().replace(".", "/") + ".class";
URL classResource = codeLocationClass.getClassLoader().getResource(pathOfClass);
String codeLocationPath = removeEnd(getPathFromURL(classResource), pathOfClass);
if (codeLocationPath.endsWith(".jar!/")) {
codeLocationPath = removeEnd(codeLocationPath, "!/");
}
return codeLocationFromPath(codeLocationPath);
}
/**
* Creates a code location URL from a file path
*
* @param filePath the file path
* @return A URL created from File
* @throws InvalidCodeLocation if URL creation fails
*/
public static URL codeLocationFromPath(String filePath) {
try {
return new File(filePath).toURI().toURL();
} catch (Exception e) {
throw new InvalidCodeLocation(filePath);
}
}
/**
* Creates a code location URL from a URL
*
* @param url the URL external form
* @return A URL created from URL
* @throws InvalidCodeLocation if URL creation fails
*/
public static URL codeLocationFromURL(String url) {
try {
return new URL(url);
} catch (Exception e) {
throw new InvalidCodeLocation(url);
}
}
@SuppressWarnings("serial")
public static class InvalidCodeLocation extends RuntimeException {
public InvalidCodeLocation(String path) {
super(path);
}
}
/**
* Get absolute path from URL objects starting with file:
* This method takes care of decoding %-encoded chars, e.g. %20 -> space etc
* Since we do not use a File object, the system specific path encoding
* is not used (e.g. C:\ on Windows). This is necessary to facilitate
* the removal of a class file with path in codeLocationFromClass
*
* @param url the file-URL
* @return String absolute decoded path
* @throws InvalidCodeLocation if URL contains format errors
*/
public static String getPathFromURL(URL url) {
URI uri;
try {
uri = url.toURI();
} catch (URISyntaxException e) {
// this will probably not happen since the url was created
// from a filename beforehand
throw new InvalidCodeLocation(e.toString());
}
if (uri.toString().startsWith("file:") || uri.toString().startsWith("jar:")) {
return removeStart(uri.getSchemeSpecificPart(),"file:");
} else {
// this is wrong, but should at least give a
// helpful error when trying to open the file later
return uri.toString();
}
}
}