I'm trying to achieve a way to obtain the base path of the current classloader when runnning from within a jar.
I mean programatically, I already know it should have the shape of "jarPath+jarFile.jar!/"
Unlike file system's call, getResource(".") or .getResource("/") do not work from inside the jar.
Ideally it should be an abstract solution for any file provider, so something like:
Path BASE_PATH = Paths.get(...getResource("").toURI())
which could return the correct root path for both jars and file system so I can use relative urls to my resources without having to do any conditional statements and url manual string parsing/build.
You should be able to find out the path of the jar and or target folder containing you class or any resource by using this code:
package com.stackoverflow.test;
import java.net.URL;
import java.nio.file.Paths;
public class ClassPathUtils {
public static String getBasePath(String jarPath) {
String path = getJarPathFromClass(jarPath);
if (path == null) {
return null;
}
if (path.startsWith("jar:")) {
path = path.substring("jar:".length());
}
if (path.startsWith("file:")) {
path = path.substring("file:".length());
}
if (path.endsWith(jarPath)) {
path = path.substring(0, path.length()-jarPath.length());
}
return path;
}
public static String getBasePath(Class clazz) {
return getBasePath(classNameDotClass(clazz));
}
private static String classNameDotClass(Class clazz) {
return clazz.getName().replaceAll("\\.", "/") + ".class";
}
private static String getJarPathFromClass(String resource) {
final URL url = ClassPathUtils.class.getClassLoader().getResource(resource);
return url == null ? null : url.toString();
}
public static void main(String[] args) {
//System.out.println(Paths.get(ClassPathUtils.getBasePath("."))); // doesn't work in a jar
System.out.println(Paths.get(ClassPathUtils.getBasePath(ClassPathUtils.class)));
System.out.println(Paths.get(ClassPathUtils.getBasePath("fonts/atcitadelscript.ttf"))); // any classpath resource
System.out.println(Paths.get(ClassPathUtils.getBasePath(String.class))); // actually finds rt.jar
}
}
If you run this code from your IDE, or from maven, it will give you the paths to target/classes for your own resources, or the path to a jar for other resources (E.g. String.class). If you call it from a jar, it will always tell you the path of the jar file.
run from IDE:
/home/alexander/projects/stackoverflow/stuff/target/classes
/home/alexander/projects/stackoverflow/stuff/target/classes
/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar!`
run from JAR:
/home/alexander/projects/stackoverflow/stuff/target/test-stuff-0.1-SNAPSHOT.jar!
/home/alexander/projects/stackoverflow/stuff/target/test-stuff-0.1-SNAPSHOT.jar!
/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar!
Is that what you're looking for?