How to Reference Local XSD File By Relative Path - java

This is a follow up on How to Configure Eclipse to Work with `ehcache` and there is an example of absolute path in How to reference a local XML Schema file correctly?
Since the xsd file is not longer being hosted, I downloaded a copy of it from the archive. I've put the file in my resource directory and would like to reference it in my xsi:schemaLocation from a relative path of my project. We have both windows and mac developers, so an absolute path convention like file:///c:/project/foo won't work.
Another alternative to relative path would be if there is a way to reference system properties for both windows and mac, then I could do 2 entries like file:///$HOME/workspace/foo.
My project on my mac exists in ~/workspace/foo and echo of $HOME gives my home path.
My spring-cache.xml exists in ./src/main/webapp/WEB-INF/spring/
My ehcache-spring-1.2.xsd exists in ./src/main/resources/
The following are some that I've tried without success:
file:///$HOME/workspace/foo/src/main/resources/ehcache-spring-1.2.xsd
file:///./src/main/resources/ehcache-spring-1.2.xsd
file:///../../../../resources/ehcache-spring-1.2.xsd
file:///../../../../resources/ehcache-spring-1.2.xsd
../../../../resources/ehcache-spring-1.2.xsd
file://../../../../resources/ehcache-spring-1.2.xsd
file://$HOME/workspace/foo/src/main/resources/ehcache-spring-1.2.xsd
file://./src/main/resources/ehcache-spring-1.2.xsd
file://../../../../resources/ehcache-spring-1.2.xsd
I also seem to have issues getting it to reference the file from absolute path too, so perhaps there is a different way to reference the file on mac? e.g. The following did not work:
file:///Users/me/workspace/foo/src/main/resources/ehcache-spring-1.2.xsd
file:////Users/me/workspace/foo/src/main/resources/ehcache-spring-1.2.xsd
file://Users/me/workspace/foo/src/main/resources/ehcache-spring-1.2.xsd

Think my issue was that the webapp dir may not have visibility to the resources folder.
I say this because based on the reading of the following stack overflow questions, it looks like the relative path stuff should be pretty straigh forward: XML File with local copy of XML Schema and How to use Schema that is on local machine in XML document
I then tried to brute force the references, in case it was something with deploy directory or class path, and all of the following failed:
../../../../resources/ehcache-spring-1.2.xsd
../../../resources/ehcache-spring-1.2.xsd
../../resources/ehcache-spring-1.2.xsd
../resources/ehcache-spring-1.2.xsd
./resources/ehcache-spring-1.2.xsd
../ehcache-spring-1.2.xsd
./ehcache-spring-1.2.xsd
The solution:
However by moving the xsd file from ./src/main/resources/ to ./src/main/webapp/WEB-INF/spring/ I was then able to reference it correctly/easily by just ehcache-spring-1.2.xsd

Related

Specifying relative path to binary file inside java library

I am writing a library that contains references to a few non-java binary files. (The java library is used to make sub-proc calls to these).
I has specified the path to the folder containing these files using this line of code:
String binaryFolder = System.getProperty("user.dir") + "/externalbinaries/";
Of course this path does not hold when the library is included in another java application.
Is there a way to specify the path relative to the project root?
I have seen answers using the classloader:
binaryFolder = classLoader.getResource("bin/ext/").getPath();
but this path to the resource folder also does not hold when imported as a .jar library in an application.
I am using java 1.8.
Any ideas?
what you describe with the user.dir is not really a relative path, because the result of that statement is actually an absolute path, but it is not a "fixed" path because the user working directory can change, i assume thats what you meant with "relative"?
what about user.home instead, that should be a fixed path?

Relative path using Level hierarchy(../../)

I want to use the relative path in xml files in our project. I have the files in the following location.
D:/SDC-Builds/SRDM2.3.0/SRDM/Svr/IdP/IdPserver/conf/attribute-r.xml
I have other xml file which needs to ref the above location, I use the following relative path to be independent of machines and folder names.
In D:/SDC-Builds/SRDM2.3.0/SRDM/Svr/IdP/IdPserver/others/service.xml, i am using the code like below
service.xml
<srv:ConfigurationResource="../../../../../../IdP/IdPserver/conf/attribute-r.xml">
</srv>
Please tell me am i using proper convention to refer the attribute-r.xml ?
If your Project Root Directory is SRDM, then you need to get back from your executable path.
Say you have your exe file at SRDM/Svr/bin/EXECUTABLE.exe then,
you need to mention in xml as
<srv:ConfigurationResource="../IdP/IdPserver/conf/attribute-r.xml"></srv>
ie. Current working directory is SRDM/Svr/bin/ and from that you need to get back up to common junction[Svr] in your case.

cloudbees & ESAPI - how do I point to the ESAPI directory?

I'm using ESAPI for my project, and added the ESAPI configuration directory to src/main/resources so it is copied to my WAR file (I downloaded the WAR from cloudbees, I can see it was put in WEB-INF/classes/esapi/ directory)
Locally, I just point to where the directory is and all works fine, but on cloudbees it just doesn't work for me.
In order to access its properties, ESAPI project tries all kinds of stuff, including checking the org.owasp.esapi.resources system property, so I've added the following code to cloudbees-web.xml:
<sysprop name="org.owasp.esapi.resources" value="WEB-INF/classes/esapi/" />
and I can see that the system property value is found because of the following error in the logs:
Not found in 'org.owasp.esapi.resources' directory or file not readable: /var/genapp/apps/akld3873/WEB-INF/classes/esapi/ESAPI.properties
so it finds the system property (because the path is like I've specified), but when it looks for the actual directory and files in it, I guess the directory is either not there or not readable.
Do I need to move it somewhere else? Inside the WEB-INF directory maybe? Is the setting not right? I've read that others solved similar issues by building a JAR just for this directory, but this doesn't seem like a good solution, there must be a simple setup that will work for cloudbees.
Design for ESAPI lib to require a directory access to configuration is not very flexible.
A general purpose option is to use ServletContext.getRealPath to resolve the absolute filesystem path to this directory and pass it to ESAPI.
Another option is for you to have some init code to copy WEB-INF/classes/esapi content in a temporary directory (using java.io.temp system property to point to the currently configured temp dir for your app) and point ESAPI lib to this path.
Ok so after searching and testing, I finally figured it out.
Cloudbees deploys your web app to the following directory:
staxcat/install/webapp.war/
notice that this is a relative path, with prefix of this path attached it looks something like this:
/var/genapp/apps/xxxxxxxx/staxcat/install/webapp.war/WEB-INF/esapi/ESAPI.properties
so, in order to get ESAPI to work, I had to set the following in cloudbees-web.xml:
<sysprop name="org.owasp.esapi.resources" value="staxcat/install/webapp.war/WEB-INF/esapi" />
this will enable ESAPI to find the directory if in your project it is located under:
src/main/webapp/WEB-INF/esapi
and you should get the following log line:
Found in 'org.owasp.esapi.resources' directory: /var/genapp/apps/xxxxxxxxx/staxcat/install/webapp.war/WEB-INF/esapi/ESAPI.properties

Java (maven web app), getting full file path for file in resources folder?

I'm working with a project that is setup using the standard Maven directory structure so I have a folder called "resources" and within this I have made a folder called "fonts" and then put a file in it. I need to pass in the full String file path (of a file that is located, within my project structure, at resources/fonts/somefont.ttf) to an object I am using, from a 3rd party library, as below, I have searched on this for a while but have become a bit confused as to the proper way to do this. I have tried as below but it isn't able to find it. I looked at using ResourceBundle but that seemed to involve making an actual File object when I just need the path to pass into a method like the one below (don't have the actual method call in front of me so just giving an example from my memory):
FontFactory.somemethod("resources/fonts/somefont.ttf");
I had thought there was a way, with a project with standard Maven directory structure to get a file from the resource folder without having to use the full relative path from the class / package. Any advice on this is greatly appreciated.
I don't want to use a hard-coded path since different developers who work on the project have different setups and I want to include this as part of the project so that they get it directly when they checkout the project source.
This is for a web application (Struts 1.3 app) and when I look into the exploded WAR file (which I am running the project off of through Tomcat), the file is at:
<Exploded war dir>/resources/fonts/somefont.ttf
Code:
import java.io.File;
import org.springframework.core.io.*;
public String getFontFilePath(String classpathRelativePath) {
Resource rsrc = new ClassPathResource(classpathRelativePath);
return rsrc.getFile().getAbsolutePath();
}
In your case, classpathRelativePath would be something like "/resources/fonts/somefont.ttf".
You can use the below mentioned to get the path of the file:
String fileName = "/filename.extension"; //use forward slash to recognize your file
String path = this.getClass().getResource(fileName).toString();
use/pass the path to your methods.
If your resources directory is in the root of your war, that means resources/fonts/somefont.ttf would be a "virtual path" where that file is available. You can get the "real path"--the absolute file system path--from the ServletContext. Note (in the docs) that this only works if the WAR is exploded. If your container runs the app from the war file without expanding it, this method won't work.
You can look up the answer to the question on similar lines which I had
Loading XML Files during Maven Test run
The answer given by BobG should work. Though you need to keep in mind that path for the resource file is relative to path of the current class. Both resources and java source files are in classpath

Absolute Path of Project's folder in Java

Lots of confusion in this topic. Several Questions have been asked. Things still seem unclear.
ClassLoader, Absolute File Paths etc etc
Suppose I have a project directory structure as,
MyProject--
--dist
--lib
--src
--test
I have a resource say "txtfile.txt" in "lib/txt" directory. I want to access it in a system independent way. I need the absolute path of the project.
So I can code the path as abspath+"/lib/Dictionary/txtfile.txt"
Suppose I do this
java.io.File file = new java.io.File(""); //Dummy file
String abspath=file.getAbsolutePath();
I get the current working directory which is not necessarily project root.
Suppose I execute the final 'prj.jar' from the 'dist' folder which also contains "lib/txt/txtfile.txt" directory structure and resource,It should work here too. I should absolute path of dist folder.
Hope the problem is clear.
You should really be using getResource() or getResourceAsStream() using your class loader for this sort of thing. In particular, these methods use your ClassLoader to determine the search context for resources within your project.
Specify something like getClass().getResource("lib/txtfile.txt") in order to pick up the text file.
To clarify: instead of thinking about how to get the path of the resource you ought to be thinking about getting the resource -- in this case a file in a directory somewhere (possibly inside your JAR). It's not necessary to know some absolute path in this case, only some URL to get at the file, and the ClassLoader will return this URL for you. If you want to open a stream to the file you can do this directly without messing around with a URL using getResourceAsStream.
The resources you're trying to access through the ClassLoader need to be on the Class-Path (configured in the Manifest of your JAR file). This is critical! The ClassLoader uses the Class-Path to find the resources, so if you don't provide enough context in the Class-Path it won't be able to find anything. If you add . the ClassLoader should resolve anything inside or outside of the JAR depending on how you refer to the resource, though you can certainly be more specific.
Referring to the resource prefixed with a . will cause the ClassLoader to also look for files outside of the JAR, while not prefixing the resource path with a period will direct the ClassLoader to look only inside the JAR file.
That means if you have some file inside the JAR in a directory lib with name foo.txt and you want to get the resource then you'd run getResource("lib/foo.txt");
If the same resource were outside the JAR you'd run getResource("./lib/foo.txt");
First, make sure the lib directory is in your classpath. You can do this by adding the command line parameter in your startup script:
$JAVA_HOME/bin/java -classpath .:lib com.example.MyMainClass
save this as MyProject/start.sh or any os dependent script.
Then you can access the textfile.txt (as rightly mentioned by Mark) as:
// if you want this as a File
URL res = getClass().getClassLoader().getResource("text/textfile.txt");
File f = new File(res.getFile());
// As InputStream
InputStream in = getClass().getClassLoader()
.getResourceAsStream("text/textfile.txt");
#Mark is correct. That is by far the simplest and most robust approach.
However, if you really have to have a File, then your best bet is to try the following:
turn the contents of the System property "java.class.path" into a list of pathnames,
identify the JAR pathname in the list based on its filename,
figure out what "../.." is relative to the JAR pathname to give you the "project" directory, and
build your target path relative to the project directory.
Another alternative is to embed the project directory name in a wrapper script and set it as a system property using a -D option. It is also possible to have a wrapper script figure out its own absolute pathname; e.g. using whence.

Categories