Reputation: 14317
In my properties file I am using system variable like this:
log4j.appender.RollingFile.File=${workspace.logs}/my.log
I am reading the property like this:
Properties p = new Properties();
p.load(new FileInputStream("logger.properties"));
String label = (String) p.get("log4j.appender.RollingFile.File");
System.out.println(label);
The result is:
${workspace.logs}/my.log
How can I print the result with the evaluated variable? e.g.
C:/logs/my.log
?
EDITED
I believe that I can do it in regex - as some suggested - so the perfect solution will be how to replace ${..} content with System.property
Upvotes: 1
Views: 1682
Reputation: 4554
First we have to find what is inside ${ }. after extracting it, replace the whole thing to the value from environment property(hoping that the workspace.logs is a Env Variable
)... to get that we can use
System.getenv()
and then we can just replace the same using replace method. And this should be done in a loop in case there are multiple env_variable Occurrences
Properties p = new Properties();
p.load(new FileInputStream("c:\\log4j.properties"));
String label = (String) p.get("log4j.appender.RollingFile.File");
int firstIndex=label.indexOf("${");
int lastIndex=label.indexOf("}");
String tempKey =label.substring(firstIndex+2,lastIndex);
String tempValue =System.getenv(tempKey);
label=label.replaceFirst("\\$\\{((?s).*)\\}",tempValue);
System.out.println(label);
Will give you output as
c:/log/my.log
Upvotes: 1
Reputation: 4554
If the you have set the system variable properly,then You would be able to use just
${sys:workspace.logs}
to get the expected output.
Mentioned in http://logging.apache.org/log4j/2.x/manual/lookups.html
So Actually you need to write log4j.appender.RollingFile.File=${sys:workspace.logs}/my.log
and problem solved.
Upvotes: 0
Reputation: 4476
Java doesn't do this replacement automatically, they are just treated as strings. You will have to do the variable replace by System.getenv()
.
Before that you will have to recognise and take the variable out using regex or some other mechanism.
Pattern p = Pattern.compile("\\$\\{([0-9a-zA-Z.@]+)}");
Matcher m = p.matcher(label);
if(m.find())
{
String var = m.group();
String envVar = var.replace("${","").replace("}","");
label = label.replace(var,System.getenv(envVar));
}
Please note that above code assumes you have only one variable in a line other wise you will have to use a while loop instead of if. Also note that above code may not be syntactically right as I don't have any java IDE with me.
Upvotes: 0
Reputation: 20885
For a very quick and dirty solution you can even use a replacement loop, but that won't account for escaping the placeholder delimiters (what if you someday come up with a literal ${foo}
in your values?). I wrote a simple Lexer/Parser couple by hand to solve a similar issue and it's not a very complex task.
However I suggest you encapsulate the first stage in a template engine in order to play with different implementations. The template engine must be used to create an intermediate text that you will then use like this:
// Load the bindings from your configuration
Map<String, Object> bindings = loadBindings();
Template tpl = new Template("log4j.properties");
tpl.bind(bindings);
tpl.compile();
Properties resolvedConfiguration = new Properties();
Reader in = new StringReader(tpl.getText());
resolvedConfiguration.load(in);
Unfortunately I was not able to find a template engine configurable enough to be adapted to my needs for placeholder delimiters and variables resolution, and had to write my own, but was an easy task (a couple hours of work) because the language is not complex.
Upvotes: 0