Java Forum / General / December 2005
How does one locate the java executable and various JAR files in the classpath?
Oliver Wong - 09 Dec 2005 19:58 GMT Note: This post mentions Eclipse to show what parts of the design I have no control over, but I believe you don't actually need to know much about Eclipse development to help contribute a useful answer.
I have a JAR file which does some useful stuff, including generating some files into the "current directory". That is, it creates new File objects using relative paths, and so these files appear relative to the directory from which the JAR was invoked. I can read the source code for this JAR, but I'm pretty much not allowed to make changes to the code in it.
I'm writing a plugin for Eclipse, and one of the functionalities is to invoke this JAR. That is, I want to give the user the ability to right click somewhere in their project hierarchy, and select "Generate files here" from the context menu, and in responce to that, I'll invoke the JAR file, passing it command line arguments based on settings that the user specified earlier.
The cleanest solution, I think, would have been to invoke the static main function in the JAR directly, 'cause then I could catch any exceptions thrown from there and handle them specially, but I think there is no way to set the "current directory" in Java, and so doing this would result in my not being able to control where the files get generated.
The next solution that came to my mind was to use Runtime.exec(String, String[], File)
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Runtime.html#exec(java.lang.St ring,%20java.lang.String[],%20java.io.File)
Thanks to the last argument, I can specify the working directory for the subprocess.
However, I'm not at a lost of how to construct the String for the first parameter. I want to run the "java" interpreter, something of the form: "java -jar myHelper.jar Other Command Line Arguments", but this assumes both that "java" and "myHelper.jar" can be found from the current working directory, which will not nescessarily be the case.
Any advice on how to find both the java executable and the jar file? Or how to programmatically affect the current working directory (so that I may use the original cleaner solution)?
- Oliver
Andrew Thompson - 09 Dec 2005 22:28 GMT > Any advice on how to find both the java executable and the jar file? URL urlToClass = this.getClass().getResource( "get/any/class/in/mysterious/Jar.class" );
I am sure there is also something more specific for classes, just cannot recall it.
 Signature Andrew Thompson physci, javasaver, 1point1c, lensescapes - athompson.info/andrew
Oliver Wong - 09 Dec 2005 22:50 GMT >> Any advice on how to find both the java executable and the jar file? > [quoted text clipped - 3 lines] > I am sure there is also something more specific for classes, > just cannot recall it. I had actually tried:
this.getClass().getClassLoader().getResource("myMysteriousJARFile.jar"); //[1]
... but null was returned. The JAR file is on my classpath at compile time, but I'm not so sure it's there at invocation time when Eclipse invokes my plugin (though I suspect it should be, or else how could I call methods located within that JAR?)
I also strongly suspect that Eclipse uses its own custom classloader for loading plugins. Not sure how that might affect the above code's ability to locate my JAR.
- Oliver
[1]: I want the JAR file, and not any particular class within the JAR, because I want to construct a string to pass to Runtime.exec(). Something like Runtime.exec("java -jar /path/to/jar/myMysteriousJARFile.jar", null, myDesiredWorkingDirectory); I was hoping to take the URL from the classloader, assuming it points to the local filesystem, and then convert it to an absolute path using the File class.
DM McGowan II - 10 Dec 2005 04:01 GMT > [1]: I want the JAR file, and not any particular class within the JAR, > because I want to construct a string to pass to Runtime.exec(). Something > like Runtime.exec("java -jar /path/to/jar/myMysteriousJARFile.jar", null, > myDesiredWorkingDirectory); I was hoping to take the URL from the > classloader, assuming it points to the local filesystem, and then convert > it to an absolute path using the File class. Is it possible to write a class loader then load the JAR rather than take the performance hit of running a separate Java process? Just curious.
Roedy Green - 09 Dec 2005 23:13 GMT On Fri, 09 Dec 2005 22:28:45 GMT, Andrew Thompson <seemysites@www.invalid> wrote, quoted or indirectly quoted someone who said :
>I am sure there is also something more specific for classes, >just cannot recall it. you were thinking of getProctectionDomain?
import java.net.URL; import java.security.CodeSource;
/** * Find out where a class on the classpath will be loaded from. * Fully qualified classname goes on the command line. */ public class Where { /** * main * @param args name of fully qualified class to find, using dots, but no dot class. * e.g. java.exe Where javax.mail.internet.MimeMessage */ public static void main ( String[] args ) { try { String qualifiedClassName = args[0]; Class qc = Class.forName( qualifiedClassName ); CodeSource source = qc.getProtectionDomain().getCodeSource(); if ( source != null ) { URL location = source.getLocation(); System.out.println ( qualifiedClassName + " : " + location ); } else { System.out.println ( qualifiedClassName + " : " + "unknown source, likely rt.jar" ); } } catch ( Exception e ) { System.err.println( "Unable to locate class on command line." ); e.printStackTrace(); } } }
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Andrew Thompson - 09 Dec 2005 23:21 GMT > On Fri, 09 Dec 2005 22:28:45 GMT, Andrew Thompson > <seemysites@www.invalid> wrote, quoted or indirectly quoted someone [quoted text clipped - 4 lines] > > you were thinking of getProctectionDomain? Spot on ..well, without the initial 'c', but yes.
 Signature Andrew Thompson physci, javasaver, 1point1c, lensescapes - athompson.info/andrew
Oliver Wong - 09 Dec 2005 23:56 GMT > import java.net.URL; > import java.security.CodeSource; [quoted text clipped - 38 lines] > } > } Thanks, after embedding your code into my project, I was able to confirm that the JAR I was seeking was not on the classpath at runtime. I've fixed that, and now your code does return the correct path to the JAR file. You've helped me a lot. Thank you.
- Oliver
Oliver Wong - 10 Dec 2005 00:25 GMT > I've fixed that, and now your code does return the correct path to the JAR > file. Just in case anyone is curious, I solved the other problem, of locating Sun's java executable, like this:
System.getProperty("java.home") + "/bin/java";
- Oliver
Rhino - 09 Dec 2005 22:30 GMT > Note: This post mentions Eclipse to show what parts of the design I > have no control over, but I believe you don't actually need to know much [quoted text clipped - 37 lines] > how to programmatically affect the current working directory (so that I > may use the original cleaner solution)? Wouldn't it be more appropriate to ask your questions on a suitable Eclipse forum? (Don't ask me which one: there are lots of them and I always get lost trying to find the right one :-)
Rhino
Oliver Wong - 09 Dec 2005 23:04 GMT > Wouldn't it be more appropriate to ask your questions on a suitable > Eclipse forum? (Don't ask me which one: there are lots of them and I > always get lost trying to find the right one :-) I posted it to eclipse.newcomer on Eclipse.org's usenet server, but since I thought the question doesn't specifically rely on knowledge of eclipse, it might be worth asking it here as well. Hopefully people will excuse the multi-posting as the messages lie on completely detached servers.
- Oliver
Rhino - 10 Dec 2005 00:44 GMT >> Wouldn't it be more appropriate to ask your questions on a suitable >> Eclipse forum? (Don't ask me which one: there are lots of them and I [quoted text clipped - 5 lines] > excuse the multi-posting as the messages lie on completely detached > servers. I'm not complaining :-)
Rhino
Chris Uppal - 10 Dec 2005 14:15 GMT > I have a JAR file which does some useful stuff, including generating > some files into the "current directory". That is, it creates new File > objects using relative paths, and so these files appear relative to the > directory from which the JAR was invoked. [I see that you've already found a workaround, and anyway this is just an observation.]
IMO, any API that /depends/ on the idea of a "current directory" is broken in this day and age. There's nothing wrong with allowing relative filenames to be specified as inputs to the API, but it seems foolish to create files in locations that the user (programmer) can't control.
Perhaps you can encourage the authors of your JAR to un-break the API ?
-- chris
Roedy Green - 10 Dec 2005 22:21 GMT On Sat, 10 Dec 2005 14:15:31 -0000, "Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org> wrote, quoted or indirectly quoted someone who said :
>IMO, any API that /depends/ on the idea of a "current directory" is broken in >this day and age. There's nothing wrong with allowing relative filenames to be >specified as inputs to the API, but it seems foolish to create files in >locations that the user (programmer) can't control. It makes not much sense in a multithread program. Each thread would need its own version of the CWD.
Your problem really is Windows There are so many ways to invoke a program it is easy to get confused what CWD you are giving it.
Some experiments are in order . Just display the CWD first thing on the console, and experiment till you feel confident you have it under control.
See http://mindprod.com/jgloss/file.html
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|