Property File Outisde of .WAR file - java

I need to be able to read in a property file, that lives outside of my war. My problem is that a need a solution that will allow me to tell my war file where my property file is located. Can this be done through bashrc variables and windows env variables?
I need to do this because I need to be able to drop the property file in different locations that could be away from the war file.
I am struggling to come up with a solution.

This will very much depends what the property file is for. Some libraries will have have the possibility of setting it on the command-line and others will allow you to explicitly load them in code.
In case of the latter, System.getProperties() can prove helpful, since it allows you to read properties passed to the JVM using the '-D' flag. For example
java -jar -Dfilelocation="yourfilelocation" yourapp.jar
would populate the system property 'filelocation' with the string 'yourfilelocation'. This could then be used in your code to load the property file (or whatever you want to do with it).
Since you are running inside some sort of application server, there are different ways you can accomblish this. For jetty you can put them in start.ini (or simply pass them on the command-line when you start jetty)
where tomcat uses an enviroment variable called JAVA_OPTS, so
JAVA_OPTS='-Dfilelocation=yourfilelocation' start.sh
would set the system property when you start tomcat.

one way is to provide specific location by passing java argument or setting up environment varialble and read it from app to determine the location
and as a fallback (default) app should be announcing to look at
${user.home}/appname/some.peroperties

You could defines a list of possible directories ... and try to read each one ...
I have a solution that read a property file in the file system using a default directory structure.
Eg: c:\properties\code-suit\prd\application.properties
Where:
code-suit is a variable defined by application name;
prd is a environment that I will use
Good luck

Related

Windows AppLocker Path Wildcards for Files and Folders

I have a Java Application which generates a temporary JNA folder and a temporary DLL file to the following location in the users' profile:
%OSDRIVE%\Users\ABC-<SOME-USER-ID>\AppData\Local\Temp\jna--881477353\jna7513918229606912988.dll
(the JNA folder and file names contain random numbers as suffix and with prefix "jna--" , "jna" respectively)
The JNA DLL file "Path" needs to be made an exception in Application Control Policies, specifically in AppLocker -> DLL Rules -> [Users] -> Exceptions in order for the Java app to function properly. At the moment, it is blocked by the AppLocker, however, if I add this path to the AppLocker, it will work for the current user.
Now, this is achievable for 1 user, but I have many users with the prefix as "ABC-" and the suffix "SOME-USER-ID" contains a random string with numbers and letters, i.e. many users who have prefix "ABC-" should be able to use this application without the need for manually adding every users' profile path into the AppLocker configuration.
Is there a way I can "Wildcard" this path into the AppLocker configuration?
For example, something like this:
%OSDRIVE%\Users\ABC-<WILDCARD>\AppData\Local\Temp\jna--<WILDCARD>\jna<WILDCARD>.dll
or even:
%OSDRIVE%\Users\ABC-<WILDCARD>\AppData\Local\Temp\jna--<WILDCARD>\*
Is there a realistic way of achieving this via Wildcards?
I do not wish to use "*" inside the path because it will then allow ALL users to be exempted from the AppLocker settings.
Any help is appreciated.
Thanks in advance!
Based on the available documentation I could find, it appears that a wildcard (*) character is only supported in AppLocker at the beginning or end of a path, but not in the middle. So your proposed solution is impossible.
However, rather than using a wildcard in the path for AppLocker, you can pre-extract the JNA native library to a known location for all users. This is a relatively common need for security purposes (exactly your intent), sometimes related to temp directory access permissions or sometimes related to signing binaries.
From the JNA API Overview Loading JNA:
JNA includes a small, platform-specific shared library which enables all native access. When the Native class is first accessed, JNA will first attempt to load this library from the directories specified in jna.boot.library.path. If that fails and jna.nosys=false is set, it will fall back to loading from the system library paths. Finally it will attempt to extract the stub library from from the JNA jar file, and load it.
This gives you two options to avoid the randomly-named temporary file. Copy it to:
a directory of your choice, and either pass -Djna.boot.library.path=C:\your\path on the java command line, or before loading JNA call System.setProperty("jna.boot.library.path", "C:\your\path") in your program.
a system directory on the PATH, e.g. System32, and set jna.nosys=false. (You can also set jna.nounpack=true to prevent the temp file unpacking.)
In addition, the JNA native library will be in a subdirectory of the Java temporary directory specified by the java.io.tmpdir system property. See this SO question: Environment variable to control java.io.tmpdir?
Answers to that question include using the _JAVA_OPTIONS environment variable as a possible means to change the tmpdir even if you're running an executable rather than Java command line.

Java : How to modify config.properties in runtime?

I have a key which has a value.
autoFixBasePath=C:/myTest
I would like the autoFixBasePath to be appended to some of the keys declared down:
So I am trying to set the value of autoFixBasePath at the start and then modify the config file :
try {
PropertiesConfiguration config = new PropertiesConfiguration("config.properties");
config.setProperty("autoFixBasePath", args[2]);
config.save();
}catch (Exception exception){
}
This works locally, but when using maven assembly plugin, I have put the config file inside jar, there it fails.
How can I do this?
Read the properties file from, for example, %USER_PROFILE%\AppData\Local\YourApp\config.properties (on Windows) or ~/.yourapp/config.properties (on Unix). If that file does not exist at app startup, copy the default settings file from within your JAR to the location named above.
(Although I question how good your approach is. Users of command line tools generally expect that the tool will default to a certain behaviour, and that any command line parameters passed to it will only take effect on that single invocation of the tool. But hey, that's your choice.)
You could also use the Preferences API, documented here: https://docs.oracle.com/javase/8/docs/technotes/guides/preferences/overview.html - which takes care of OS-specific paths and changes at runtime in a way that Properties do not (because those are intended to be passed to the program at startup, and to be immutable from there on.)

Access property/environment variables without launching Eclipse?

I want to set the log4j configuration file path/other folder paths that can be used across other class files, without hard-coding the folder path.
Rightnow, I have set the variables as Environment variable. But It can only be modified if I launch Eclipse. How do I set this variable in such away that anyone (doesn't want to launch Eclipse) can modify it, from outside. Also, it will be used in test configurations. So it's better to not hard-code it and have all the file paths etc. easy to refactor.
final static String log4jpath = System.getenv("LOG4J_PATH");
Paraphrasing a comment:
[How to get value from] outside of the Java program such as a separate file, that contains all other filepaths?
That is called a configuration file.
It is often a properties file, similar to a Log4j configuration file, but it can be any types of file, e.g. XML, JSON, YAML, ...
To identify a single such file, you can use:
An environment variable (like you are right now)
A system property (more common)
A specifically named file in the current directory
...
The entries in that file will identify all the values you really want.
For example, Spring, which is a populate Java framework, will look for configuration values in many places. See 24. Externalized Configuration for full detail, but here is a summary of the most common ones:
Command line arguments, e.g. java -jar MyApp.jar --foo=bar
Java System properties, e.g. set using -Dfoo=bar on the command-line
OS environment variables, e.g. SET foo=bar (Windows) or export foo=bar (Linux)
Application properties outside of your packaged jar, i.e. relative to current directory.
Name and location can be overridden on command-line.
config/application.properties
config/application.yaml
application.properties
application.yaml
Soni, If you want to put the log4j configuration file in one place so that everybody can access. Follow the steps.
Create a project with some name and inside src/main/resources folder keep the log4j configuration file.
Create a jar file which must contain this log4j configuration file.
Use this created jar file wherever it is required. Log4j will automatically use the configuration for desired logging. If you want, you can distribute this jar file to anybody who wants to use it.
The above option is if you do not want to change the configuration file.
Now if there is a situation where someone wants to modify the configuration file.
In this case, simply put the configuration in any project classpath, means inside resource folder. As long as log4j jar files are there in the classpath and configuration files. It will log everything.
However, if you want, you can extend the functionality of Log4j by passing configuration as an object. You can refer below the link to access pro grammatically.
https://howtodoinjava.com/log4j/how-to-programmatically-configure-appenders-in-log4j/
I have added all file and folder paths inside the properties file (example config.properties) and then used it inside the testsetup method by InputStream input = new FileInputStream("Path to//config.properties");
Properties prop = new Properties();
prop.load(input);
System.setProperty("log4j2.configurationFile", prop.getProperty("log4j.path"));
this way, all files/folder paths can be modifies from outside and there's no need to set environment variable from inside the project.

What's the defference between "-Dorg.gradle.project.env=demo" and "-Denv=demo" in gradle?

Today I'm trying to use the system property in my code .When I enter ./gradlew -Dorg.gradle.project.env=demo test ,the NullPointExcepetion happens,though I println env in script successfully!Then I try another way , entering ./gradlew -Denv=demo test and my code get the env set in command line successfully .So my question is What's the defference between "-Dorg.gradle.project.env=demo" and "-Denv=demo" in gradle?P.s. This link(12.2. Gradle properties and system properties in https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_properties_and_system_properties) told me to use org.gradle.project to set system property.I guess when you use org.gradle.project, you should use another method to get system property ,not using
System.getProperty("env")
I guess when you use org.gradle.project, you should use another method to get system property, not using System.getProperty("env")
You're right. This two syntaxes are different and serve different purposes.
The latter one, -Denv is a standard way of passing system properties in Java world. If you run java -help you'll see:
-D<name>=<value> set a system property
So, when you use it, env system property becomes available via System.getProperty("env") and it's value will be demo.
The first one -Dorg.gradle.project.env is actually a system property too! It's obvious after reading the lines above. However, it sets a system property named org.gradle.project.env, not just env. So, unless your test expect this name, it won't work. And your tests must no expect this name, because they should, generally, be unaware of the build tool.
What Gradle docs says is:
Gradle offers a variety of ways to add properties to your build. With the -D command line option you can pass a system property to the JVM which runs Gradle. The -D option of the gradle command has the same effect as the -D option of the java command.
Gradle can also set project properties when it sees specially-named system properties or environment variables. This feature is very useful when you don’t have admin rights to a continuous integration server and you need to set property values that should not be easily visible, typically for security reasons. In that situation, you can’t use the -P option, and you can’t change the system-level configuration files. The correct strategy is to change the configuration of your continuous integration build job, adding an environment variable setting that matches an expected pattern. This won’t be visible to normal users on the system.
If the environment variable name looks like ORG_GRADLE_PROJECT_prop=somevalue, then Gradle will set a prop property on your project object, with the value of somevalue. Gradle also supports this for system properties, but with a different naming pattern, which looks like org.gradle.project.prop.
Differently saying, Gradle allows you to set project proprties by providing system properties with special names, and that is what you did. You've set a Project's property named env to a value demo by providing a system property with a name org.gradle.project.env. This property is available in you build script via project.env and can be used to tweak builds in various ways.

How to get the path to the executable when using launch4j?

I'm using launch4j to wrap an executable jar file in my Windows application, but I need to pass references to some of its libraries in through the JVM arguments. The libraries in question reside in the application install directory, and are always located in the same place, relative to the executable.
I'd like to tell launch4j to use executable-relative paths in the JVM options. I know this information is available at the Windows batch script level, but how do you configure launch4j to fetch it?
Edit for clarification: I'm looking specifically for how to make the paths relative to the binary itself, not how to make them relative to the current working directory. The two aren't necessarily the same.
You might add to your launch4j configuration
...
<jre>
...
<opt>-Djna.library.path="%EXEDIR%\\path\\to\\lib"</opt>
<opt>-Djava.library.path="%EXEDIR%\\path\\to\\lib"</opt>
...
</jre>
...
If you need more then a you might seperate several paths by a semikolon as usual.
< opt> Optional, accepts everything you would normally pass to
java/javaw launcher: assertion options, system properties and X
options. Here you can map environment and special variables EXEDIR
(exe's runtime directory), EXEFILE (exe's runtime full file path) to
system properties. All variable references must be surrounded with
percentage signs and quoted.
Source: http://launch4j.sourceforge.net/docs.html
Set -Djna.library.path=<relative path of native libraries> (if using JNA) and -Djava.library.path=<relative path of native libraries>.
Alternatively, this can be done in Java code as: System.setProperty("jna.library.path","<relative path of native libraries>") and System.setProperty("java.library.path","<relative path of native libraries>"). You can append as many paths to refer to. In Windows, use ; to separate the paths.
This setup only has its effect on the JVM runtime of that Java application (not globally like LD_LIBRARY_PATH in Linux.)
Or, you can put this in Launch4J JVM options list under JRE tab. This is what I do in my projects.
One of the options in configuration is to allow a change directory chdir to the executables directory. This will set user.dir to same directory as exe, which you could use to find other application paths.
<chdir>
Optional. Change current directory to an arbitrary path relative to the executable. If you omit this property or leave it blank it will have no effect.
Setting it to . will change the current dir to the same directory as the executable. .. will change it to the parent directory, and so on.
<chdir>.</chdir>
<chdir>../somedir</chdir>
The code which find the actual path to executable will be dependent on OS (readlink, GetModuleFileName etc). Make sure you really test on target OSes..
If I understand your question correct, you have a launch4j executable and a native library within your installation directory:
/launch.exe
/bin/lib.dll
/lib/app.jar
Now you want to start you app.jar with the generated launcher (launch.exe). You app loads the lib.dll.
You can embed a file into your app.jar (marker.txt). Now you can use the ClassLoader
http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)
getResource("marker.txt);
This will give you something like:
file://c://installdir/lib/app.jar!marker.txt
This String can be parsed. But in fact, I think there should be a better solution for this problem.
You can simply include the directory (e.g. ..\lib) where the libraries are located in the classpath tab in Launch4j. At least that worked for me.

Categories

Resources