简体   繁体   中英

Evaluating property value from properties file java

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? eg

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

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

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM