Load library jars with javassist - java

I am trying to analyze the code of a java project.
I have the project to be analyzed in a jar that I add to javassist path using insertClassPath function. Everything works fine if I try to access a class form the project.
The problem is that I need to access also the classes from the libraries the project uses.
I tried to add the library to the class path just like i did with the project jar, but I get a NotFoundException so i guess I am not giving the right path.
The code looks like this:
String jarFileName = "C:/Users/diana/Desktop/Test/ckjm.jar";
ClassPool pool = ClassPool.getDefault();
try{
pool.insertClassPath(jarFileName);
pool.insertClassPath("C:/Users/diana/Desktop/Test/ckjm/lib/bcel-5.2.jar");
} catch (NotFoundException e) {
System.out.println("error loading jar!!");
}
I used the harcoded string just for testing purpose. The jar is in the lib folder or the project that was archived to a jar.
I am not sure how can i add a jar that is contained in another jar.
Note: if i keep the library as a separate jar (and give the path like: "C:/Users/diana/Desktop/Test/bcel-5.2.jar") it woks fine
Any help would be appreciated

If your target JAR is inside another JAR, you can use a LoaderClassPath created using a URLClassLoader which is defined using a JarURLConnection URL path of the JAR.
So assume you have a target JAR, inner.jar, embedded inside another JAR, C:/Users/diana/outer.jar.
Let's assume it is in a subdirectory called lib.
The URL of the outer JAR would be file:/C:/Users/diana/outer.jar.
The URL of the inner JAR would be jar:file:/C:/Users/diana/outer.jar!/lib/inner.jar.
You code to load this classpath would be:
URL cpUrl = new URL("jar:file:/C:/Users/diana/outer.jar!/lib/inner.jar");
URLClassLoader cpUrlLoader = new URLClassLoader(new URL[]{cpUrl});
pool.insertClassPath(new LoaderClassPath(cpUrlLoader));

Related

Cannot load resource in jar

I am trying to load a resource in a jar, here is the exported jar:
'main' is the package with all my classes, and in one of those classes I am trying to load the background.png file. In my Eclipse project I put the resources under a "res/" folder, which I added to the build path to include it. When I try to use
new File("background.png");
It can't find the file.
When I use
MyClass.class.getClass().getClassLoader().getResource("background.png");
It still can't find the file.
Files packaged in a jar can't be accessed as File objects.
When you try
MyClass.class.getClass().getClassLoader().getResource("background.png");
you are actually using the ClassLoader of java.lang.Class and not of main.MyClass which may not be able to find the resource (in case it is the system classloader). Try
MyClass.class.getClassLoader().getResource("background.png");
instead.

URLClassLoader in java

I am working on a project which requires loading classes at Runtime, so I did some research and found out that I need to use Custom Class Loader. I implemented my own custom UrlClassloader and provided it with the url of my jar files, it worked correctly and the class files got loaded. I have read the java doc for URLClassLoader and they have mentioned clearly that any URL that ends with "/" is assumed to refer to a directory so does it mean that if I have multiple jar files in the directory my classloader will all load all of them, I tried it but it didn't work. so what's the logic behind that.
please explain I am very much confused. what if I want multiple jars to be loaded at runtime from a directory?
You have to iterate over the files in the directory and add them one by one
List<URL> urls = new ArrayList<>();
try(DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(BASE_DIRECTORY), "*.jar")) {
for (Path path : directoryStream) {
urls.add(path.toUri().toURL());
}
}
URLClassLoader urlClassLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]));
When it ends with "/", would be referring find loading content from that directory. Suppose you have an extracted package in that folder. If you have a class com.abc.Test, to load it form a folder, you would need the file com/abc/Test.class in the folder you are referring to.

Java get folder in same directory as Jar

Say I have an exported Jar file on my Desktop, and then a folder I want to access so my jar file can load files from it. How can I access that folder without hard coding the path?
See here: https://stackoverflow.com/a/6849255/514463
Pick one of your classes that you want the directory of, e.g.: Test:
String path = Test.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
If I clearly understand, you may use relative path when you try to access folder. For example, if you run your jar as a standalone application, relative path "." will be a folder that contains your jar. So, when you place names.txt file next to your jar, you can get access to it with:
new File("./names.txt");
Hope I understood you right way and this will help.
The following code should provide the directory containing the JAR file:
URL url = getClass().getProtectionDomain().getCodeSource().getLocation();
File directory = new File(url.toURI()).getParentFile();
Hmmm...
I heard this question so often, and it always boils down to this: How to load resources at runtime?
The main reason for this type of question is, that one is developping an application and now wants to create a distributable package. This normally ends in something like that:
... / my-application-folder
| -- lib / *.jar
| -- main.jar
| -- config.properties
There could be several configuration files. A configuration for the application itself, a configuration for a logging framework that is used, etc. It does not matter. If you want to access such resources, you should do it in two steps:
1) Make sure all folders containing your resources (such configuration files are resources) are part of the classpath. If you run your JAR file (here main.jar) with a java -jar main.jar command, this JAR file should contain a manifest file containing the directory . and all needed library JARs in the class-path entry. [Alternative: Maybe all your config files are located in a config/ subfolder. Then this folder must be part of the class-path.]
2) Inside your application you access such resources with a class loader:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
URL url = loader.getResource(neededResource);
// do something with url, e.g. open stream, read from it, and close stream
If you have a user customizable path, there are several possibilities. You could for example pass a system property to the application, as Reddy suggested in his comment. You could also have a property in a configuration file, which you are loading in the beginning part of your application. However, you have the path to this customizable folder in hand (at runtime). Then you do the following:
String customizablePath = getCustomizablePath();
URL customizablePathURL = new File(customizablePath).toURI().toURL();
ClassLoader loader = new URLClassLoader(new URL[] {customizablePathURL});
Then you can continue like above.
File f = new File("Folder")
This File object points to "Folder" directory in the the working directory of the Jar.

Java Build Path

I have a quick question about altering the build path as the code is running.
For example, I have a class which downloads a .jar file from the internet and then into the same directory as the code is running from. How, if possible, could I load the jar into the build path to access the classes within the .jar file?
Some suggested amendments / comments:
Remove the jar: prefix and the !/ suffix - these are note required and are probably confusing the matter
Can you verify the jar file exists:
System.out.println(new File(new URL("file://test.jar")).exists());
Amend your class declaration to the following (get the File object to generate the URL for you, to avoid problems):
URL[] classes = new URL[] { new File("test.jar").toURI().toURL() };
This worked for my test example, using commons-codec as the jar, and loading the Base64 class

Loading a resource in a JAR file

I have a Java project in Netbeans. It runs fine with Maven. So I assembled it. It contains the following code to load a file that is in the JAR:
ClassLoader loader = MyClass.class.getClassLoader();
SERVICE_URL = loader.getResource("my.wsdl");
This returns a URL like:
jar:file:/path/to/my/file/MyClass-1.0-SNAPSHOT-jar-with-dependencies.jar!/my.wsdl
but the library that needs this parameter doesn't appear to be able to use it.
Is there any way this file can be in the JAR and be referred to from the code like this?
You may have to use ClassLoader.getResourceAsStream(), copy it to a temporary file, and then create a URL with File.toURI().toURL()

Categories

Resources