Resolving classpath-relative paths for non-existing files - java

I have a project where I'm compiling files to locations relative to getClass().getResource("/"). How can I get File objects for these locations?
When I try getClass().getResource("/nonExisting"), they return null. How can I resolve the paths?

There's no reason to expect existent resources to be normal files; they could be buried inside a jar-file somewhere on your classpath.
With non-existent resources, the situation is even worse; even if you could guarantee in the abstract that it is a non-existent normal file, it could be a non-existent normal file in any of the top-level directories in your classpath; there's no sensible way to decide which directory it would have been in, had it existed. (For example, if your classpath contains both classes and testClasses, then /nonExisting could be either classes/nonExisting or testClasses/nonExisting.)

Related

Can't enumerate `class` files with ClassLoader#getResources()

I am trying to enumerate classes in the package with
Enumeration<URL> resourceUrls = myObject.getClassLoader().getResources("path/to/my/package/");
while (resourceUrls.hasMoreElements()) {
...
Unfortunately it returns nothing. Why?
Assuming path is correct. Path starts with no slash and ends with slash. There are several public classes under path.to.my.package package.
I took this code from Spring.
You cannot walk a class path like you can walk a file path. Walking a file path is done on the file system, which does not apply to a class path.
While a java class path entries are formed like file paths and usually are folders and files (either on the file system or inside a JAR archive), it does not necessarily have to be that way. In fact, the classes of one single package may originate from various locations of differing nature: one might be loaded from a local JAR file while another one might be loaded from a remote URL.
The method ClassLoader.getResources() exists to provide access to all "occurrences" of a resource if it has the same name in different JAR files (or other locations). For example you can use
ClassLoader.getSystemClassLoader().getResources("META-INF/MANIFEST.MF");
to access the manifest file of each JAR file in your class path.
Try with
Enumeration<URL> urls = ClassLoader.getSystemClassLoader().getResources("path/to/my/package");
while (urls.hasMoreElements()) {
System.out.println(urls.nextElement());
}

Using relative path in a maven project

I have a maven project with these standard directory structures:
src/main/java
src/main/java/pdf/Pdf.java
src/test/resources
src/test/resources/files/x.pdf
In my Pdf.java,
File file = new File("../../../test/resources/files/x.pdf");
Why does it report "No such file or dirctory"? The relative path should work. Right?
Relative paths work relative to the current working directory. Maven does not set it, so it is inherited from whatever value it had in the Java process your code is executing in.
The only reliable way is to figure it out in your own code. Depending on how you do things, there are several ways to do so. See How to get the real path of Java application at runtime? for suggestions. You are most likely looking at this.getClass().getProtectionDomain().getCodeSource().getLocation() and then you know where the class file is and can navigate relative to that.
Why does it report "No such file or dirctory"? The relative path should work. Right?
wrong.
Your classes are compiled to $PROJECT_ROOT/target/classes
and your resources are copied to the same folder keeping their relative paths below src/main/resources.
The file will be located relative to the classpath of which the root is $PROJECT_ROOT/target/classes. Therefore you have to write in your Pdf.java:
File file = new File("/files/x.pdf");
Your relative path will be evaluated from the projects current working directory which is $PROJECT_ROOT (AFAIR).
But it does not matter because you want that to work in your final application and not only in your build environment. Therefore you should access the file with getClass().getResource("/path/to/file/within/classpath") which searches the file in the class path of which the root is $PROJECT_ROOT/target/classes.
No the way you are referencing the files is according to your file system. Java knows about the classpath not the file system if you want to reference something like that you have to use the fully qualified name of the file.
Also I do not know if File constructor works with the classpath since it's an abstraction to manage the file system it will depend where the application is run from. Say it is run from the target directory at the same level as source in that case you have to go one directory up and then on src then test the resources the files and finally in x.pdf.
Since you are using a resources folder I think you want the file to be on the classpath and then you can load a resource with:
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream("<path in classpath>");
Then you can create a FileInputStream or something to wrap around the file. Otherwise use the fully qualiefied name and put it somewere like /home/{user}/files/x.pdf.

getting null pointer when reading the properties file

when reading the properties file, iam getting nullpointer exception.
faceConfig.load(ReadPropertyFile.class.getClassLoader().getResourceAsStream("/resources/faces.properties"));
below is the path of properties file facedetections/src/main/resources/faces.properties
i tried in different combinations as my class file that reads in below path /facedetections/src/main/java/com/facial/facedetection/utils/ReadPropertyFile.java
combinations are ../../../../../resource/faces.properties , /resource/faces.properties and
../../../resource/faces.properties
Please suggest what is the correct path i can provide for this.
Edit :
I extracted the war file and providing its path below.
looks your property file under class folder not in resource.
as your screen shot cant find resource folder under class folder.
So just use
ReadPropertyFile.class.getClassLoader().getResourceAsStream("faces.properties")
The path is relative to the point where the object (.class) files are located. Are you sure you have configured your build/test tool to copy the resource file into that structure? Exactly where? That's what counts, not the position of the sources.
Additionally, my understanding is that getResourceAsStream() of most ClassLoaders do not support .. notation.
The position where your resource file is currently located is out of reach of the ClassLoader. If you move your file to /facedetections/src/main/java/resources/faces.properties, then you will be able to use the current code
getResourceAsStream("resources/faces.properties")
I'm making assumptions about your environment. In particular, this is entirely dependent on classloaders. If this doesn't help, please provide object file location, not sources (unless it is the same, but state it).
Since it is unlikely that you get a NPE when the file is not found I assume that faceConfig is null when you execute that line.

How to use ClassLoader.getResources() in jar file

Problem statement:
I have a jar file with a set of configuration files in a package mycompany/configuration/file/.
I don't know the file names.
My intention is to load the file names at runtime from the jar file in which they are packaged and then use it in my application.
As far as I understood:
When I use the ClassLoader.getResources("mycompany/configuration/file/") I should be getting all the configuration files as URLs.
However, this is what is happening:
I get one URL object with URL like jar:file:/C:/myJarName.jar!mycompany/configuration/file/
Could you please let me know what I am doing wrong ?
For what you are trying to do I don't think it is possible.
getResource and getResources are about finding named resources within the classloader's classpath, not listing values beneath a directory or folder.
So for example ClassLoader.getResources("mycompany/configuration/file/Config.cfg") would return all the files named Config.cfg that existed in the mycompany/configuration/file path within the class loader's class path (I find this especially useful for loading version information personally).
In your case I think you might almost have half a solution. The URL you are getting back contains the source jar file (jar:file:/C:/myJarName.jar). You could use this information to crack open the jar file a read a listing of the entries, filtering those entries whose name starts with "mycompany/configuration/file/".
From there, you could then fall back on the getResource method to load a reference to each one (now that you have the name and path)

How should I use getResource() in Java?

This question is asked in numerous places, with myriad small variations. (Such as Java - getClassLoader().getResource() driving me bonkers among others.) I still can't make it work.
Here's a code snippet:
String clipName = "Chook.wav";
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// URL url = classLoader.getResource(clipName);
URL url = new URL("file:///Users/chap/Documents/workspace/the1620/bin/ibm1620/" + clipName);
ais = AudioSystem.getAudioInputStream(url);
This works -- note that I've hard-coded the path to the directory containing the clip file, which is there, and is in the same directory as my .class file. Alas, the commented-out code just returns a null value for url.
Most other posts seem to deal with getResourceAsStream(). I think I'm supposed to be using getResource(). Is that making the difference?
It just can't be this hard. Any clues?
String clipName = "Chook.wav";
When using getResource, the string you pass in must be either an absolute name or be valid relative to a certain class. Since you're using ClassLoader.getResource() and not Class.getResource(), it must be an absolute path.
Without seeing your actual file hierarchy, I can only guess that "bin" is the root of your compiled classes and resources, and "ibm1260" is a package/folder within that path, and "Chook.wav" exists in that folder. If that's the case, then you need to use /ibm1260/Chook.wav (or potentially ibm1260/Chook.wav, I don't typically use the class loader for resource lookups) as the name of the file that you pass in to getResource().
Either way, you need to make sure that the file is copied into the location of your compiled code and that the root folder is on the classpath.
The getResource and getResourceAsStream methods are for accessing resources on the classpath. You seem to be trying to access some resource that is not on the classpath.
The logic that getResource and getResourceAsStream use to locate resources is essentially the same. The difference between the methods is that one returns a URL, and the other an InputStream.
It just can't be this hard. Any clues?
This is not that hard at all. You just need to understand how classpaths work ... and make sure that you use a resource name that resolves to a resource that you've put in the correct location in one of the directories or JAR files on the classpath.
Or if the resource is not "part of" your application, don't access it this way.

Categories

Resources