Servlet Real Path - java

I am running a webapp under the directory blog. (e.g. www.example.com/blog).
I would like to get the real filesystem path of a request.
e.g. www.example.com/blog/test-file.html ->
/usr/share/tomcat7/webapps/blog/test-file.html
I tried the following:
public String realPath(HttpServletRequest request, ServletContext servletContext){
String requestURI = request.getRequestURI();
String realPath = servletContext.getRealPath(requestURI);
return realPath;
}
However this returns
/usr/share/tomcat7/webapps/blog/blog/test-file.html
What is the correct way to do this?

Short answer
To get the result you want, use HttpServletRequest#getServletPath() method as an argument to getRealPath() method.
This is the closest to what you want to accomplish (read the note below).
Explanation
The reason you're getting such path (with double blog) is that you're using the result returned by the getRequestURI() method.
The getRequestURI() method returns the path starting with application context. In your case it will be:
/blog/test-file.html
What happens then, the getRealPath() method appends the string returned by getRequestURI() method to the real/physical path to the folder, where you application resides on the file system, which in your case is:
/usr/share/tomcat7/webapps/blog/
So the resulting path is:
/usr/share/tomcat7/webapps/blog/blog/test-file.html
That is the reason of your double blog issue.
IMPORTANT NOTE
DISCLAIMER
Maybe the OP is already aware of the information written below, but it is written for the sake of completeness.
The real path you are trying to get does not mean you are getting, well, the real path on your file system. The url-pattern configured in web.xml (or if you're using Servlet 3.0+ in the related annotation) is actually a logical/virtual path, which may or may not relate to the actual, physical path on a file system, i.e. the patterns (paths) specified does not need to exist physically.
Also quote from the ServletContext.getRealPath(String) documentation (emphasis mine):
Gets the real path corresponding to the given virtual path.

Related

Nested jar: URI

The format of the jar: URI scheme is simply defined to be jar:<url>!/[<entry>].
Is it possible to "nest" two such URIs together and refer to a file inside an archive inside an archive this way? Something like:
jar:jar:http://example.com/!/archive!/file
This should designate /file inside an archive jar:http://example.com/!/archive, that is /archive found in a file provided by http://example.com/. However, URL.openConnection throws an exception:
java.net.MalformedURLException: no !/ in spec
I also cannot replace ! with %21 since that makes the jar: URI invalid, and I am not aware of any escaping that could be performed. Is this somehow possible? Or, as a more generic question, is it possible to store a URI with !/ inside <url> so that it is preserved?
As it is stated in the source code java.net.JarURLConnection does not handle nested Jar URIs.
Your example jar:jar:http://example.com/!/archive!/fileis parsed as entry archive!/file in the archive jar:http://example.com/. The latter is not a valid jar URI. You can not either escape the !/ sequences, because the text after jar: and before !/ must be a valid URI without any translation.
You can of course provide your own URLConnection implementation that supports nested Jar URIs.
While the other answer is indeed correct in the case of JarURLConnection, the use of jar: and similar URIs is not restricted to it. Such is the case of the Apache Commons VFS:
jar:// arch-file-uri[! absolute-path]
Where arch-file-uri refers to a file of any supported type, including other zip files. Note: if you would like to use the ! as normal character it must be escaped using %21.
"Normal character" means usage of the character in path to the file inside the archive, not in the inner URI. This makes jar:jar:http://example.com/!/archive!/file valid, as it is the last occurence of ! that should be used as a delimiter.
Note that the inner URI should probably still remain unescaped, thus it is impossible to use # there.

Is the `file://` uri prefix something I can hardcode?

I was wondering if I can hardcore the file:// prefix into one of my functions in android.
The function is supposed to determine whether or not the given link points to an external resource on the web, or an internal resource inside the phone itself
public Uri generate_image_uri(String link)
{
// link can be "1DCHiI2.jpg"
// link can be "file://smiley_face.jpg"
if (!link.startsWith("file://")
return Uri.parse("https://i.imgur.com/" + link);
else
return Uri.parse(link);
}
Is this advisable? Or is there a more "fault tolerant" way of getting file://? maybe some function like getProperFilePrefixForThisAndroidVersion();?
In order to clarify my question:
given the following code
(new File(getFilesDir(), "hello_world.jpg")).toString();
Is it safe to assume within reasonable probability that the resulting string will always start with file:// in all current and future Android versions?
Given:
(new File(getFilesDir(), "hello_world.jpg")).toString();
is it safe to assume within reasonable probability that the resulting string will always start with file:// in all current and future Android versions?
No.
According to the javadoc for File on Android, File.toString returns:
"... the pathname string of this abstract pathname. This is just the string returned by the getPath() method."
Not a "file://" URL.
If you want to get a properly formed "file://" URL, do this:
new File(...).toURI().toString()
Now, technically the protocol for a URL (i.e. "file") is case insensitive:
Is the protocol name in URLs case sensitive?
Which means that "FILE://" or "File://" etc are technically valid alternatives.
However, the probability that above expression would ever emit anything other than the lower-case form of the protocol is (um) vanishingly small1.
1 - It would entail monumentally stupid decision making by a number of people. And they are NOT stupid people.

JSP/Servlet rewrite URL

I'd like to change the URL of some pages in my website in the same way as foursquare is doing:
from www.foursquare.com/v/anystring/venueid
to www.foursquare.com/v/venue-name/venueid
For example central park in new york:
https://foursquare.com/v/writeherewhatyouwant/412d2800f964a520df0c1fe3
becomes
https://foursquare.com/v/central-park/412d2800f964a520df0c1fe3
I'm developing a pure JSP/Servlet app, no frameworks, in a Tomcat container.
I'm thought of using tuckey's urlrewritefilter, but I don't see how can I use dynamic values coming from the servlet itself there (the venue name)
How can I accomplish this?
Off the top of my head, here's something you could try:
1) Create a servlet with a servlet-mapping matching the common (prefix) part of the URL (e.g. for foursquare the pattern would be /v/*).
2) In your servlet, retrieve the remaining part of the URL path using request.getPathInfo(). You can then parse it using regular string utilities and convert it to the new path you'd like.
3) Assuming your updated path is in a variable called newUrl, call response.sendRedirect(newUrl) to tell the browser to update its URL. This will also call your servlet again with the new path, so it needs to handle both cases.
See the javadoc for HttpServletResponse.sendRedirect() for more info about how it handles relative vs absolute paths, etc.

Problem loading java properties

I am trying to load properties from a file (test.properties)
The code I use is as follows:
URL url = getClass().getResource("../resources/test.properties");
properties.load(url.openStream());
But when executing the second line I get a NPE. (null pointer exception)
I'm not sure what's wrong here... I have checked that the file exists at the location where URL points to...
Any help is appreciated....
The javadoc for Class.getResource(String) says:
Returns: a URL object or null if no resource with this name is found
Most likely, the problem is that getResource is not finding the resource it is looking for. I am very suspicious of the use of ".." in the resource name. The javadoc does not say that getResource treats "." or ".." path components as having special meaning.
It is also possible that properties is null ...
I could be wrong, but I don't believe you can use ".." like that in a call to getResource(). I suggest you try an "absolute" resource:
URL url = getClass().getResource("/path/to/resources/test.properties");
Is it perhaps the properties object that is null?
The answer to whether or not getResource will find your file depends on your system classloader. The classloader is called, but before the classloader is called, the following transformation is made on the string you pass in.
From the Class javadoc:
If the name begins with a '/' ('\u002f'), then the absolute name of
the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object
with '/' substituted for '.' ('\u002e').
So, the question becomes: will the classloader you are using be able to resolve modified_package_name/../resources/test.properties?
getClass().getResource() resolves the resource relative to the given class. Try getClass().getClassLoader().getResource().
You can also use Apache's PropertiesConfiguration

Getting the inputstream from a classpath resource (XML file)

In Java web application, Suppose if I want to get the InputStream of an XML file, which is placed in the CLASSPATH (i.e. inside the sources folder), how do I do it?
ClassLoader.getResourceAsStream().
As stated in the comment below, if you are in a multi-ClassLoader environment (such as unit testing, webapps, etc.) you may need to use Thread.currentThread().getContextClassLoader(). See http://stackoverflow.com/questions/2308188/getresourceasstream-vs-fileinputstream/2308388#comment21307593_2308388.
ClassLoader.class.getResourceAsStream("/path/file.ext");
That depends on where exactly the XML file is. Is it in the sources folder (in the "default package" or the "root") or in the same folder as the class?
In for former case, you must use "/file.xml" (note the leading slash) to find the file and it doesn't matter which class you use to try to locate it.
If the XML file is next to some class, SomeClass.class.getResourceAsStream() with just the filename is the way to go.
ClassLoader.class.getResourceAsStream("/path/to/your/xml") and make sure that your compile script is copying the xml file to where in your CLASSPATH.
someClassWithinYourSourceDir.getClass().getResourceAsStream();
Some of the "getResourceAsStream()" options in this answer didn't work for me, but this one did:
SomeClassWithinYourSourceDir.class.getClassLoader().getResourceAsStream("yourResource");
I tried proposed solution and forward slash in the file name did not work for me, example: ...().getResourceAsStream("/my.properties"); null was returned
Removing the slash worked: ....getResourceAsStream("my.properties");
Here is from doc API:
Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Otherwise, the absolute name is of the following form:
modified_package_name/name
Where the modified_package_name is the package name of this object with '/' substituted for '.' ('\u002e').

Categories