8000 config: resolve environment variables in include · log4cplus/log4cplus@f4f0391 · GitHub
[go: up one dir, main page]

Skip to content

Commit f4f0391

Browse files
author
Martin Engelmann
committed
config: resolve environment variables in include
Enable resolving environment variables in the include statement of configuration files. The path of the included file may contain environment variables. Example: include ${PATH}/included-file
1 parent d412803 commit f4f0391

File tree

3 files changed

+122
-112
lines changed

3 files changed

+122
-112
lines changed

include/log4cplus/helpers/property.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,15 @@ namespace log4cplus {
155155
bool get_type_val_worker (ValType & val,
156156
log4cplus::tstring const & key) const;
157157
};
158+
159+
160+
class LogLog;
161+
162+
163+
bool
164+
substVars (tstring & dest, const tstring & val,
165+
Properties const & props, LogLog& loglog,
166+
unsigned flags);
158167
} // end namespace helpers
159168

160169
}

src/configurator.cxx

Lines changed: 2 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -61,114 +61,6 @@ void initializeLog4cplus();
6161

6262
namespace
6363
{
64-
static tchar const DELIM_START[] = LOG4CPLUS_TEXT("${");
65-
static tchar const DELIM_STOP[] = LOG4CPLUS_TEXT("}");
66-
static std::size_t const DELIM_START_LEN = 2;
67-
static std::size_t const DELIM_STOP_LEN = 1;
68-
69-
70-
/**
71-
* Perform variable substitution in string <code>val</code> from
72-
* environment variables.
73-
*
74-
* <p>The variable substitution delimeters are <b>${</b> and <b>}</b>.
75-
*
76-
* <p>For example, if the System properties contains "key=value", then
77-
* the call
78-
* <pre>
79-
* string s;
80-
* substEnvironVars(s, "Value of key is ${key}.");
81-
* </pre>
82-
*
83-
* will set the variable <code>s</code> to "Value of key is value.".
84-
*
85-
* <p>If no value could be found for the specified key, then
86-
* substitution defaults to the empty string.
87-
*
88-
* <p>For example, if there is no environment variable "inexistentKey",
89-
* then the call
90-
*
91-
* <pre>
92-
* string s;
93-
* substEnvironVars(s, "Value of inexistentKey is [${inexistentKey}]");
94-
* </pre>
95-
* will set <code>s</code> to "Value of inexistentKey is []"
96-
*
97-
* @param val The string on which variable substitution is performed.
98-
* @param dest The result.
99-
*/
100-
static
101-
bool
102-
substVars (tstring & dest, const tstring & val,
103-
helpers::Properties const & props, helpers::LogLog& loglog,
104-
unsigned flags)
105-
{
106-
tstring::size_type i = 0;
107-
tstring::size_type var_start, var_end;
108-
tstring pattern (val);
109-
tstring key;
110-
tstring replacement;
111-
bool changed = false;
112-
bool const empty_vars
113-
= !! (flags & PropertyConfigurator::fAllowEmptyVars);
114-
bool const shadow_env
115-
= !! (flags & PropertyConfigurator::fShadowEnvironment);
116-
bool const rec_exp
117-
= !! (flags & PropertyConfigurator::fRecursiveExpansion);
118-
119-
while (true)
120-
{
121-
// Find opening paren of variable substitution.
122-
var_start = pattern.find(DELIM_START, i);
123-
if (var_start == tstring::npos)
124-
{
125-
dest = pattern;
126-
return changed;
127-
}
128-
129-
// Find closing paren of variable substitution.
130-
var_end = pattern.find(DELIM_STOP, var_start);
131-
if (var_end == tstring::npos)
132-
{
133-
tostringstream buffer;
134-
buffer << '"' << pattern
135-
<< "\" has no closing brace. "
136-
<< "Opening brace at position " << var_start << ".";
137-
loglog.error(buffer.str());
138-
dest = val;
139-
return false;
140-
}
141-
142-
key.assign (pattern, var_start + DELIM_START_LEN,
143-
var_end - (var_start + DELIM_START_LEN));
144-
replacement.clear ();
145-
if (shadow_env)
146-
replacement = props.getProperty (key);
147-
if (! shadow_env || (! empty_vars && replacement.empty ()))
148-
internal::get_env_var (replacement, key);
149-
150-
if (empty_vars || ! replacement.empty ())
151-
{
152-
// Substitute the variable with its value in place.
153-
pattern.replace (var_start, var_end - var_start + DELIM_STOP_LEN,
154-
replacement);
155-
changed = true;
156-
if (rec_exp)
157-
// Retry expansion on the same spot.
158-
continue;
159-
else
160-
// Move beyond the just substituted part.
161-
i = var_start + replacement.size ();
162-
}
163-
else
164-
// Nothing has been subtituted, just move beyond the
165-
// unexpanded variable.
166-
i = var_end + DELIM_STOP_LEN;
167-
} // end while loop
168-
169-
} // end substVars()
170-
171-
17264
//! Translates encoding in ProtpertyConfigurator::PCFlags
17365
//! to helpers::Properties::PFlags
17466
static
@@ -369,15 +261,15 @@ PropertyConfigurator::replaceEnvironVariables()
369261
val = properties.getProperty(key);
370262

371263
subKey.clear ();
372-
if (substVars(subKey, key, properties, helpers::getLogLog(), flags))
264+
if (helpers::substVars(subKey, key, properties, helpers::getLogLog(), flags))
373265
{
374266
properties.removeProperty(key);
375267
properties.setProperty(subKey, val);
376268
changed = true;
377269
}
378270

379271
subVal.clear ();
380-
if (substVars(subVal, val, properties, helpers::getLogLog(), flags))
272+
if (helpers::substVars(subVal, val, properties, helpers::getLogLog(), flags))
381273
{
382274
properties.setProperty(subKey, subVal);
383275
changed = true;

src/property.cxx

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <log4cplus/internal/env.h>
4444
#include <log4cplus/helpers/loglog.h>
4545
#include <log4cplus/exception.h>
46+
#include <log4cplus/configurator.h>
4647

4748
#if defined (LOG4CPLUS_WITH_UNIT_TESTS)
4849
#include <catch.hpp>
@@ -188,6 +189,111 @@ imbue_file_from_flags (tistream & file, unsigned flags)
188189
} // namespace
189190

190191

192+
/**
193+
* Perform variable substitution in string <code>val</code> from
194+
* environment variables.
195+
*
196+
* <p>The variable substitution delimeters are <b>${</b> and <b>}</b>.
197+
*
198+
* <p>For example, if the System properties contains "key=value", then
199+
* the call
200+
* <pre>
201+
* string s;
202+
* substEnvironVars(s, "Value of key is ${key}.");
203+
* </pre>
204+
*
205+
* will set the variable <code>s</code> to "Value of key is value.".
206+
*
207+
* <p>If no value could be found for the specified key, then
208+
* substitution defaults to the empty string.
209+
*
210+
* <p>For example, if there is no environment variable "inexistentKey",
211+
* then the call
212+
*
213+
* <pre>
214+
* string s;
215+
* substEnvironVars(s, "Value of inexistentKey is [${inexistentKey}]");
216+
* </pre>
217+
* will set <code>s</code> to "Value of inexistentKey is []"
218+
*
219+
* @param val The string on which variable substitution is performed.
220+
* @param dest The result.
221+
*/
222+
bool
223+
substVars (tstring & dest, const tstring & val,
224+
helpers::Properties const & props, helpers::LogLog& loglog,
225+
unsigned flags)
226+
{
227+
static tchar const DELIM_START[] = LOG4CPLUS_TEXT("${");
228+
static tchar const DELIM_STOP[] = LOG4CPLUS_TEXT("}");
229+
static std::size_t const DELIM_START_LEN = 2;
230+
static std::size_t const DELIM_STOP_LEN = 1;
231+
232+
tstring::size_type i = 0;
233+
tstring::size_type var_start, var_end;
234+
tstring pattern (val);
235+
tstring key;
236+
tstring replacement;
237+
bool changed = false;
238+
bool const empty_vars
239+
= !! (flags & PropertyConfigurator::fAllowEmptyVars);
240+
bool const shadow_env
241+
= !! (flags & PropertyConfigurator::fShadowEnvironment);
242+
bool const rec_exp
243+
= !! (flags & PropertyConfigurator::fRecursiveExpansion);
244+
245+
while (true)
246+
{
247+
// Find opening paren of variable substitution.
248+
var_start = pattern.find(DELIM_START, i);
249+
if (var_start == tstring::npos)
250+
{
251+
dest = pattern;
252+
return changed;
253+
}
254+
255+
// Find closing paren of variable substitution.
256+
var_end = pattern.find(DELIM_STOP, var_start);
257+
if (var_end == tstring::npos)
258+
{
259+
tostringstream buffer;
260+
buffer << '"' << pattern
261+
<< "\" has no closing brace. "
262+
<< "Opening brace at position " << var_start << ".";
263+
loglog.error(buffer.str());
264+
dest = val;
265+
return false;
266+
}
267+
268+
key.assign (pattern, var_start + DELIM_START_LEN,
269+
var_end - (var_start + DELIM_START_LEN));
270+
replacement.clear ();
271+
if (shadow_env)
272+
replacement = props.getProperty (key);
273+
if (! shadow_env || (! empty_vars && replacement.empty ()))
274+
internal::get_env_var (replacement, key);
275+
276+
if (empty_vars || ! replacement.empty ())
277+
{
278+
// Substitute the variable with its value in place.
279+
pattern.replace (var_start, var_end - var_start + DELIM_STOP_LEN,
280+
replacement);
281+
changed = true;
282+
if (rec_exp)
283+
// Retry expansion on the same spot.
284+
continue;
285+
else
286+
// Move beyond the just substituted part.
287+
i = var_start + replacement.size ();
288+
}
289+
else
290+
// Nothing has been subtituted, just move beyond the
291+
// unexpanded variable.
292+
i = var_end + DELIM_STOP_LEN;
293+
} // end while loop
294+
295+
} // end substVars()
296+
191297

192298
///////////////////////////////////////////////////////////////////////////////
193299
// Properties ctors and dtor
@@ -256,14 +362,17 @@ Properties::init(tistream& input)
256362
tstring included (buffer, 8) ;
257363
trim_ws (included);
258364

365+
tstring subIncluded;
366+
helpers::substVars(subIncluded, included, *this, helpers::getLogLog(), 0);
367+
259368
tifstream file;
260369
imbue_file_from_flags (file, flags);
261370

262-
file.open (LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(included).c_str(),
371+
file.open (LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(subIncluded).c_str(),
263372
std::ios::binary);
264373
if (! file.good ())
265374
helpers::getLogLog ().error (
266-
LOG4CPLUS_TEXT ("could not open file ") + included);
375+
LOG4CPLUS_TEXT ("could not open file ") + subIncluded);
267376

268377
init (file);
269378
}

0 commit comments

Comments
 (0)
0