Velocity's FileResourceLoader can't find resources - java

I use Velocity in order to load email templates. Those templates are first downloaded from the FTP server and then saved as temporary files.
However, when I try to load the template I get an exception:
org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource 'C:\Users\someUsername\AppData\Local\Temp\template1526050996884865454.html'
And I'm sure the file is there and it's not damaged.
That's how I try to load the template:
template = velocityEngine.getTemplate(tempFile.getCanonicalPath());
Here's the velocity.properties file that I load (and I've checked that the properties are properly initialized!)
file.resource.loader.class=org.apache.velocity.runtime.resource.loader.FileResourceLoader
file.resource.loader=file
file.resource.loader.path=.
So where lies the problem? Is it because AppData folder is hidden by default?

I think there's a design flaw in the Velocity FileResourceLoader. Basically if your file.resource.loader.path is anything other than an empty string, it'll mangle any absolute paths handed to it as the file. Additionally it has Unix/Linux-specific code to "nip off" (paraphrasing the actual code comment) an absolute file-path handed to it (Giving a broken absolute path re-rooted to the current path setting).
Solution 1:
Set the file.resource.loader.path to an empty string (prior to init()) and use absolute file-paths as the file parameter
ve.setProperty("file.resource.loader.path", "");
ve.init();
Template template = ve.getTemplate("C:\\Users\\someUsername\\AppData\\Local\\Temp\\template1526050996884865454.html");
Solution 2: Set the path to be the common root for your temp files and only hand it paths relative to that:
ve.setProperty("file.resource.loader.path", "C:\\Users\\someUsername\\AppData\\Local\\Temp");
ve.init();
Template template = ve.getTemplate("template1526050996884865454.html");
Ultimately I think the FileResourceLoader class would be better if it detected any absolute path handed to it as a file-name and not try to mash the path setting into it.

In addition to #MOles's answer, there is a third solution.
Solution 3: Configure more than one file resource loader: one for absolute resources and one for relative ones. Something like this:
resource.loader=absolute-file, relative-file
absolute-file.resource.loader.class=org.apache.velocity.runtime.resource.loader.FileResourceLoader
absolute-file.resource.loader.path=
relative-file.resource.loader.class=org.apache.velocity.runtime.resource.loader.FileResourceLoader
relative-file.resource.loader.path=.
This will allow files to be loaded either relatively or absolutely, since FileResourceLoader evidently gets confused when you try to use a single instance for either type of path.

Related

How to get the actual source path in Struts 2?

I have a little problem with Struts 2 when I try to get the context path :
ServletActionContext.getServletContext().getRealPath("\\WebContent\\resources\\img\\");
I got this path:
C:\Users\killian\workspace.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\SiteWebAdministrable\WebContent\resources\imgicone.jpg
Why the exact source path ?
Because i need to upload and save images for an admin website to control background and without the actual path i cannot save images in the resources path...
So i save the path with the name and extension in the database (no problem), and i need to save the image in the resource directory (image problem...)
Can someone help me please ? Did i forgot something ?
This question is the answer ?
How do you get the project path in Struts 2?
servletContext.getServletContext().getRealPath("/resources/img/name_of_image.png")
So, passing the "/" to getRealPath() would return you the absolute disk file system path of the /web folder of the expanded WAR file of the project. Something like /path/to/server/work/folder/demo.war/ which you should be able to further use in File or FileInputStream.
Note that most starters don't seem to see/realize that you can actually pass the whole web content path to it and that they often use
String absolutePathToIndexJSP = servletContext.getRealPath("/") + "demo.png";
instead of
String absolutePathToIndexJSP = servletContext.getRealPath("/demo.png");
getRealPath() is unportable; you'd better never use it
Use getRealPath() carefully.
If all you actually need is to get an InputStream of the web resource, better use ServletContext#getResourceAsStream() instead, this will work regardless of the way how the WAR is expanded. So, if you for example want an InputStream of index.jsp, then do not do:
InputStream input = new FileInputStream(servletContext.getRealPath("/demo.png")); // Wrong!
But instead do:
InputStream input = servletContext.getResourceAsStream("/demo.png"); // Right!
Or if you intend to obtain a list of all available web resource paths, use ServletContext#getResourcePaths() instead.
Set<String> resourcePaths = servletContext.getResourcePaths("/");

adding image in java swing [duplicate]

I need to get a resource image file in a java project. What I'm doing is:
URL url = TestGameTable.class.getClass().
getClassLoader().getResource("unibo.lsb.res/dice.jpg");
The directory structure is the following:
unibo/
lsb/
res/
dice.jpg
test/
..../ /* other packages */
The fact is that I always get as the file doesn't exist. I have tried many different paths, but I couldn't solve the issue.
Any hint?
TestGameTable.class.getResource("/unibo/lsb/res/dice.jpg");
leading slash to denote the root of the classpath
slashes instead of dots in the path
you can call getResource() directly on the class.
Instead of explicitly writing the class name you could use
this.getClass().getResource("/unibo/lsb/res/dice.jpg");
if you are calling from static method, use :
TestGameTable.class.getClassLoader().getResource("dice.jpg");
One thing to keep in mind is that the relevant path here is the path relative to the file system location of your class... in your case TestGameTable.class. It is not related to the location of the TestGameTable.java file.
I left a more detailed answer here... where is resource actually located

Loading an image from the Resource Folder

The code I am using to load the image is:
ImageIO.read(SpriteSheet.class.getResource(path));
The path being the path to the resource. But it would error with IllegalArgumentException. I wondered what might be causing and came to the conclusion that the resource should be added into the same path as the class.
Is it possible to load the image from another folder, like a res folder outside of the bin folder? (folder holding compiled classes)
EDIT:
So i messed around with a few things, and came to a solution. But now I have another problem. Here is my code
File sheet = new File(SpriteSheet.class.getProtectionDomain().getCodeSource().getLocation().getPath());
URI uri = sheet.toURI();
BufferedImage image = ImageIO.read(uri.toURL());
When I try to run it, it gives me an IIOException: Can't read Input File
This means that I can never actually get it work. I tried debugging by prining the URL to the console and this is the URL.
C:\Users\Amma\Abhijeet\Eclipse%20Workspace1\Test%20Game\bin
The %20 comes in the middle. Meaning that the file is and never can be acceesed. Is there anyway I can fix this?
Thanks.
Class.getResource will return null if the resource could not be found or the invoker doesn't have adequate privileges to get the resource.
All variants of ImageIO.read will throw an IllegalArgumentException if they receive a null input.
Take a look at the documentation of the getResource to understand how an absolute resource name is constructed from the given resource named and what are the rules for searching resources.
You can read images from any location as long as you have permissions to do so, the ImageIO.read method accepts a File, URL or InputStream so you have many option to do it.

Determine if a resource from the ServletContext is a file or directory

Given that we use the code below
Set paths = servletCtxt.getResourcePaths("/app/themes");
How can we tell if the path in paths is directory or a actual file?
This would usually be in an zipped war.
What I did find is this, but I am betting it isn't reliable:
When it is a file
servletCtxt.getResource(dir).getContent()
returned (java.io.ByteArrayInputStream) java.io.ByteArrayInputStream#5a645a64
When it is a directory it returned:
(org.apache.naming.resources.FileDirContext) org.apache.naming.resources.FileDirContext#57155715
Is it safe to say that I could use a instanceof with InputStream on what is returned by getContent?
Thanks
Without testing I see the following in the JavaDoc of getResourcePaths():
Paths indicating subdirectory paths end with a /.
[...]
For example, for a web application containing:
/welcome.html
/catalog/index.html
/catalog/products.html
/catalog/offers/books.html
/catalog/offers/music.html
/customer/login.jsp
/WEB-INF/web.xml
/WEB-INF/classes/com.example.OrderServlet.class
/WEB-INF/lib/catalog.jar!/META-INF/resources/catalog/moreOffers/books.html
getResourcePaths("/") would return {"/welcome.html", "/catalog/", "/customer/", "/WEB-INF/"}, and getResourcePaths("/catalog/") would return {"/catalog/index.html", "/catalog/products.html", "/catalog/offers/", "/catalog/moreOffers/"}.
Seems like you can simply rely on the last character of the path.

ServletContext not giving me real path when i want to go up level directory up

Why does ServletContext#getRealPath() not return me correct path if i use ../
This code works :-
System.out.println(context.getRealPath("/"));
This one doesn't :-
System.out.println(context.getRealPath("/.."));
How can i get one level up directory from getRealPath()?
Why does ServletContext#getRealPath() not return me correct path if i use "../":
To help protect you against requests that use ".." tricks to fetch content that they are not supposed to see; e.g. something like "../../../../../etc/passwd".
If you want to refer to a directory outside of the servlet context, you will need to create the path another way.

Categories

Resources