1

I have a web application running under tomcat 7, and in one of the class, Im trying to read a file in one of the jar under WEB-INF/lib folder.

URL resourceURL = MyClass.class.getClassLoader().getResource("xml/xslt/master.xsl");
File xslfile = new File(resourceURL.getPath());
AssertUtil.assertTrue(xslfile.exists(),"xsl file not found");

Both MyClass and master.xsl resides in the same jar and there is no issue with packaging. But above snippet fails in the assertion statement as xslfile.exists returns false. The URL correctly resolves to the location of the file inside the jar as given below

file:/<MY_WEBAPP_LOCATION>/MyApp/WEB-INF/lib/MyComponent.jar!/xml/xslt/master.xsl

where MY_WEBAPP_LOCATION corresponds to the absolute path to my tomcat servers webapp directory.

But if I rewrite the code as below to read as inputstream, it works fine.

InputStream xslFile = MyClass.class.getClassLoader().getResourceAsStream("xml/xslt/master.xsl");

Can anyone explain what is preventing the creation of File from the jar resource, whereas the inputstream creation is working perfectly fine. Is there any additional permission settings needed from tomcat side, to read a file inside jar ?

EDIT: One more observation, if the file is placed under WEB-INF/classes, creation of File with above code works fine. Issue is only when it is placed in a jar under WEB-INF/lib

Bibin
  • 434
  • 2
  • 5
  • 20
  • Can you please clarify whether the master.xsl file is in the same directory structure of MyClass? if the getResource(...) path doesn't start with a "/" then it will simply append the MyClass file package path to the xls path that you have mentioned. – Subba Jan 28 '13 at 09:49
  • In the above code, If I add a leading slash, MyClass.class.getClassLoader().getResource("/xml/xslt/master.xsl"), it returns me a null URL object – Bibin Jan 28 '13 at 10:12

3 Answers3

0

Be careful it seems that ClassLoader.getResource does not handle relative path. See this.

GetResourceAsStream happens to take the path relative to the ClassLoader (and not the class !!). I think you're lucky enough that there are the same here.

Community
  • 1
  • 1
autra
  • 895
  • 6
  • 21
  • If I change this to MyClass.class.getResource("/xml/xslt/master.xsl"), (only change is to add a leading slash to denote absolute path), I get the same URL mentioned above and still not able to read the file. After all, the URL location which it returns is absolutely fine – Bibin Jan 28 '13 at 10:01
0

If it is a Desktop application getResource() will work But as this is a web application the resource needs to be extracted from Context , hence getResoruceAsStream()

TheWhiteRabbit
  • 15,480
  • 4
  • 33
  • 57
  • Does that mean, I would never be able to read it as file ? If you see the URL (returned by resourceURL.getPath)mentioned in the question, its the valid location of the resource inside jar. So java should be able to create a file out of the location – Bibin Jan 28 '13 at 10:08
0

It is not a permission problem, but the use of java.io.File API - in particular constructor http://docs.oracle.com/javase/7/docs/api/java/io/File.html#File%28java.lang.String%29

When you are constructing File object using

File xslfile = new File(resourceURL.getPath());

you are using java.io.File#File(String) method which expects an "abstract pathname". What is an acceptable/valid pathname is described by javadoc of the File class: http://docs.oracle.com/javase/7/docs/api/java/io/File.html

String value that your are getting from getPath() method:

file:/<MY_WEBAPP_LOCATION>/MyApp/WEB-INF/lib/MyComponent.jar!/xml/xslt/master.xsl

simply does not constitute a valid "abstract pathname" - it is a URL that is converted to a java.lang.String (and IMHO should be returned with URL scheme of "jar" and not "file"). Therefore a call to

isExist() 

returns false as there is no file with such name on your disk. On the other hand if the resource is outside of a jar (e.g. under WEB-INF/classes directory) resourceURL.getPath() will return a value that presents a valid abstract pathname as the resource in question is indeed a simple file.

When you use java.lang.ClassLoader#getResourceAsStream(java.lang.String) the method streams out the resource directly into a java.lang.InputStream and might not even use File class in its implementation.

Nenad
  • 257
  • 3
  • 9