get path of a Jar file

P

Philipp Kraus

Hello,

I would like to extract a directory of a Jar file. I read the path of
my Jar file with:

String l_jarfile =
Class.forName("class_within_the_jar").getResource("").toString();
l_jarfile = l_jarfile.substring(9,
l_jarfile.lastIndexOf(".jar!")) + ".jar";

This does not work on MS Windows systems (unix and OSX work correct
with this code).
If the Jar files is stored under a path like "C:\Users\myuser\Java
Files\myjar.jar" (with a space)
the JarFile-Object can't locate the file, because the space within the
directory is changed to %20

I need a solution to detect the location of a Jar File in a class. How
can i Do this in a correct way?

Thx

Phil
 
L

Lew

Philipp said:
I would like to extract a directory of a Jar file. I read the path of
my Jar file with:

String l_jarfile =
Class.forName("class_within_the_jar").getResource("").toString();
l_jarfile = l_jarfile.substring(9,
l_jarfile.lastIndexOf(".jar!")) + ".jar";

This does not work on MS Windows systems (unix and OSX work correct
with this code).
If the Jar files is stored under a path like "C:\Users\myuser\Java
Files\myjar.jar" (with a space)
the JarFile-Object can't locate the file, because the space within the
directory is changed to %20

I need a solution to detect the location of a Jar File in a class. How
can i [sic] Do this in a correct way?

Well, you could look for the "%20" I suppose, but your code looks messy andunnecessary.

Sometimes it pays to take a step back. Just exactly why do you need the JAR file? What does that give you that you cannot get any other way?

'Class.forName()' loads a class. Every time you execute that line, you're attempting to load the class. Why do you need to load the class again and again?

Loading classes usually is only done when the class will be used in the program. It only needs to be done once per class (per classloader).

Your variable names do not conform to the Java conventions for naming. Don't use underscores in non-constant variables; use camel case ("camelCase") to distinguish word parts, with the first letter lower case for non-constant variables and for methods, upper case for types. (Constant variables useALL UPPER case with underscores to separate word parts instead of camel case.)

Your portability problem may be a consequence of your magic constants (9, "..jar!"). I don't know. Are you sure they're the same for Windows?

Have you traced through log statements or a debugger what the various intermediate values are? What are they?

But the real question is what do you want from this information? I am not able to come up with a scenario where knowing the JAR path helps a program,not to retrieve resources or to load classes. However, you seem to want it, so since the JAR is in your classpath, why don't you just look for matching substrings against the JAR names in your classpath?
 
M

Martin Gregorie

On Sat, 22 Oct 2011 11:54:57 +0200, Philipp Kraus wrote:

One obvious thing to do is to get rid of the hex encoding for space
before starting to work on the string:

String jarfile =
Class.forName("class_within_the_jar").getResource("").toString();

jarfile = jarfile.replace("%20", " ");

But using a magic constant like 9 is asking for trouble
jarfile = jarfile.substring(9, jarfile.lastIndexOf(".jar!")) + ".jar";

would be better written as:

static final int START_POINT = 2 /* number of names to skip */

String[] pathPieces = jarfile.split(File.separator);
StringBuilder sb = new StringBuilder();
int last = jarfile.length() - 1;
for (int i = START_POINT; i < last; i++)
sb.append(pathPieces + File.separator);

sb.append(pathPieces[last]);
String relativePath = sb.toString();

which may be longer, but is a lot readable. It may even be portable
between Windows and *NIX systems provided you want a relative path that,
on a *NIX, corresponds to

~/Java\ Files\myjar.jar

but to

myuser\Java Files\myjar.jar

on Windows. Note that my solution uses nothing but String methods. If you
haven't yet installed the SDK documentation where its readily available,
I suggest you do so and get familiar with using it.
I need a solution to detect the location of a Jar File in a class.
...but why do you want a relative path name rather than an absolute one?
Both *NIX and Windows systems are happy with absolute names.
 
S

Steven Simpson

String l_jarfile =
Class.forName("class_within_the_jar").getResource("").toString();
l_jarfile = l_jarfile.substring(9,
l_jarfile.lastIndexOf(".jar!")) + ".jar";

This does not work on MS Windows systems (unix and OSX work correct
with this code).
If the Jar files is stored under a path like "C:\Users\myuser\Java
Files\myjar.jar" (with a space)
the JarFile-Object can't locate the file, because the space within the
directory is changed to %20

Leaving aside the good questions of why, and whether these magic
constants are a good thing, I will address the decoding of % sequences:
Create a java.net.URI from the string, then create a java.io.File from
the URI.

import java.net.*;
import java.io.*;

public class GetPath {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName(args[0]);
URL clazzRes = clazz.getResource("");
String loc = clazzRes.toString();
System.out.println("Resource: " + loc);
URI stripped =
URI.create(loc.substring(4, loc.lastIndexOf(".jar!") + 4));
System.out.println("Stripped: " + stripped);
File result = new File(stripped);
System.out.println("Result: " + result);
}
}

Lots of result checking omitted.
 
P

Philipp Kraus

String l_jarfile =
Class.forName("class_within_the_jar").getResource("").toString();
l_jarfile = l_jarfile.substring(9,
l_jarfile.lastIndexOf(".jar!")) + ".jar";

This does not work on MS Windows systems (unix and OSX work correct
with this code).
If the Jar files is stored under a path like "C:\Users\myuser\Java
Files\myjar.jar" (with a space)
the JarFile-Object can't locate the file, because the space within the
directory is changed to %20

Leaving aside the good questions of why, and whether these magic
constants are a good thing, I will address the decoding of % sequences:
Create a java.net.URI from the string, then create a java.io.File from
the URI.

import java.net.*;
import java.io.*;

public class GetPath {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName(args[0]);
URL clazzRes = clazz.getResource("");
String loc = clazzRes.toString();
System.out.println("Resource: " + loc);
URI stripped =
URI.create(loc.substring(4, loc.lastIndexOf(".jar!") + 4));
System.out.println("Stripped: " + stripped);
File result = new File(stripped);
System.out.println("Result: " + result);
}
}

Lots of result checking omitted.

Thanks, the URI option is imho the best solution

Phil
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top