Nested jar: URI - java

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.

Related

Enrich body with data from a file

My exchange body contains a class with a string attribute with path to file with which the body need to be enriched. There another attribute to hold file after enriched. I failed to find a solution to build a dynamic route that will load a file and return result I could use in Aggregation Strategy.
When you use the file component, you have to specify a path to a directory which can't be dynamic. You can only specify patterns on files in the directory.
Extract from the camel-file doc:
Camel supports only endpoints configured with a starting directory. So
the directoryName must be a directory. If you want to consume a single
file only, you can use the fileName option, e.g. by setting
fileName=thefilename. Also, the starting directory must not contain
dynamic expressions with ${ } placeholders. Again use the fileName
option to specify the dynamic part of the filename
Could you give us more info on what your are trying to achieve, so that we can give you workarounds ?

Merging two relative file URLs

Let' say I have two paths, first can look like folder/ and second like /anotherFolder/image.png. I would like to merge those two paths in some automated fashion and with option for user to omit the last slash in first string and first slash in second string. So all of these
folder/ + /anotherFolder/image.png
folder + anotherFolder/image.png
folder + /anotherFolder/image.png
should give me folder/anotherFolder/image.png
I need to merge two properties in one of my projects and I want it as dummy as possible:)So is there some trick with URL class or do I have to play around with Strings?
You can do this with java.io.File, by using the constructor which takes a File and a String as arguments, will interpret the String as a relative path to the File.
Or with java.net.URL, you can send an URL and a String to the constructur, which will interpret the URL as a context for the String parameter.
I actually used FileUtils.getFile() from Apache Commons IO but Rolf's solution was working too.

Not too sure how a URI works regarding absolute paths to files

Simple question: why am I getting new IllegalArgumentException: Path component should be '/' when trying to create a zip filesystem at the following URI:
file:E:/somedirectory/somefile
But this seems to work: file:/somedirectory/somefile
What if I have the same paths on two different drives and I need to access a specific one? Or am I completely missing the point of URIs in the first place?
For paths that use windows volumes use the following format:
file:///e:/somedirectory/somefile
The triple /// results from omitting the URL hostname for local files. Compare: file://sometherhost/e:/somedirectory/somefile, which is valid according to the URI spec, if not actually useful for accessing files on remote volumes.
1. Backslashes are used to point directories and files
2. Try it this way...
`E:\\somedirectory\\somefile`
Maybe its easier to do it with the URI builder. I always use it:
URIBuilder builder = new URIBuilder();
builder.setSchema("file").setHost("anyhost").setPath("/yourpath/");
URI uri;
uri = builder.build();
you can check your URI:
System.out.println(uri.toString());
I hope this will help you!

Apache VFS resolveFile with regex

If I have a directory called temp with the following files:
a_file1.jpg
a_file2.jpg
b_file1.jpg
b_file2.jpg
It's possible to get all files like this:
VFS.getManager().resolveFile("temp").getChildren();
But, what I actually want to do is get a_file1.jpg and a_file2.jpg. Maybe like:
VFS.getManager().resolveFile("temp/a*").getChildren();
But this throws an exception:
org.apache.commons.vfs.FileSystemException: Could not list the contents of "temp/a*" because it is not a folder.
So, does anyone know how to resolve a set of files based on a regex with VFS?
You could use the findFiles method, with a FileFilterSelector.
You'll need to create your own FileFilter that accepts the files that match your desired regex.

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