10
10
import org .slf4j .Logger ;
11
11
import org .slf4j .LoggerFactory ;
12
12
13
- import java .io .File ;
14
- import java .io .FileInputStream ;
15
- import java .io .FileNotFoundException ;
16
13
import java .io .IOException ;
17
14
import java .io .InputStream ;
18
15
import java .util .HashMap ;
106
103
public final class ConfigLoader {
107
104
108
105
private static final Logger LOGGER = LoggerFactory .getLogger (ConfigLoader .class );
109
-
106
+
110
107
/**
111
108
* By default, the optional file {@value} will be loaded from classpath to load initial defaults.
112
109
*/
@@ -131,7 +128,7 @@ public final class ConfigLoader {
131
128
// RESOLVED_PROPERTIES = loadProperties(DEFAULT_CONFIG_FILENAME); <-- not possible
132
129
loadProperties (DEFAULT_CONFIG_FILENAME , false );
133
130
}
134
-
131
+
135
132
/**
136
133
* List of all the properties recognized by Simple Java Mail. Can be used to programmatically get, set or remove default values.
137
134
*
@@ -217,10 +214,10 @@ public String key() {
217
214
return key ;
218
215
}
219
216
}
220
-
217
+
221
218
private ConfigLoader () {
222
219
}
223
-
220
+
224
221
/**
225
222
* @return The value if not null or else the value from config file if provided or else <code>null</code>.
226
223
*/
@@ -236,23 +233,23 @@ public static <T> T valueOrProperty(final @Nullable T value, final Property prop
236
233
public static String valueOrPropertyAsString (@ Nullable final String value , @ NotNull final Property property , @ Nullable final String defaultValue ) {
237
234
return SimpleConversions .convertToString (valueOrProperty (value , property , defaultValue ));
238
235
}
239
-
236
+
240
237
/**
241
238
* See {@link #valueOrProperty(Object, Property, Object)}.
242
239
*/
243
240
@ Nullable
244
241
public static Boolean valueOrPropertyAsBoolean (@ Nullable final Boolean value , @ NotNull final Property property , @ Nullable final Boolean defaultValue ) {
245
242
return SimpleConversions .convertToBoolean (valueOrProperty (value , property , defaultValue ));
246
243
}
247
-
244
+
248
245
/**
249
246
* See {@link #valueOrProperty(Object, Property, Object)}.
250
247
*/
251
248
@ Nullable
252
249
public static Integer valueOrPropertyAsInteger (@ Nullable final Integer value , @ NotNull final Property property , @ Nullable final Integer defaultValue ) {
253
250
return SimpleConversions .convertToInteger (valueOrProperty (value , property , defaultValue ));
254
251
}
255
-
252
+
256
253
/**
257
254
* Returns the given value if not null and not empty, otherwise tries to resolve the given property and if still not found resort to the default value if
258
255
* provided.
@@ -279,13 +276,13 @@ public static <T> T valueOrProperty(@Nullable final T value, @NotNull final Prop
279
276
public static synchronized boolean hasProperty (final Property property ) {
280
277
return !valueNullOrEmpty (RESOLVED_PROPERTIES .get (property ));
281
278
}
282
-
279
+
283
280
@ SuppressWarnings ("unchecked" )
284
281
@ Nullable
285
282
public static synchronized <T > T getProperty (final Property property ) {
286
283
return (T ) RESOLVED_PROPERTIES .get (property );
287
284
}
288
-
285
+
289
286
@ Nullable
290
287
public static synchronized String getStringProperty (final Property property ) {
291
288
return SimpleConversions .convertToString (RESOLVED_PROPERTIES .get (property ));
@@ -312,10 +309,12 @@ public static synchronized Boolean getBooleanProperty(final Property property) {
312
309
public static Map <Property , Object > loadProperties (final String filename , final boolean addProperties ) {
313
310
final InputStream input = ConfigLoader .class .getClassLoader ().getResourceAsStream (filename );
314
311
if (input != null ) {
312
+ LOGGER .debug ("Property file {} found on classpath, loading System properties and environment variables" , filename );
315
313
return loadProperties (input , addProperties );
314
+ } else {
315
+ LOGGER .debug ("Property file not found on classpath, loading System properties and environment variables" );
316
+ return loadProperties (new Properties (), addProperties );
316
317
}
317
- LOGGER .debug ("Property file not found on classpath, skipping config file" );
318
- return new HashMap <>();
319
318
}
320
319
321
320
/**
@@ -333,21 +332,6 @@ public static Map<Property, Object> loadProperties(final Properties properties,
333
332
return unmodifiableMap (RESOLVED_PROPERTIES );
334
333
}
335
334
336
- /**
337
- * Loads properties from property {@link File}, if provided. Calling this method only has effect on new Email and Mailer instances after this.
338
- *
339
- * @param filename Any file reference that holds a properties list.
340
- * @param addProperties Flag to indicate if the new properties should be added or replacing the old properties.
341
- * @return The updated properties map that is used internally.
342
- */
343
- public static Map <Property , Object > loadProperties (final File filename , final boolean addProperties ) {
344
- try {
345
- return loadProperties (new FileInputStream (filename ), addProperties );
346
- } catch (final FileNotFoundException e ) {
347
- throw new IllegalStateException ("error reading properties file from File" , e );
348
- }
349
- }
350
-
351
335
/**
352
336
* Loads properties from {@link InputStream}. Calling this method only has effect on new Email and Mailer instances after this.
353
337
*
@@ -380,33 +364,33 @@ public static synchronized Map<Property, Object> loadProperties(final @Nullable
380
364
}
381
365
382
366
/**
383
- * @return All properties in priority of System property {@code >} File properties.
367
+ * @return All properties in priority of System property {@code >} Environment variable {@code >} File properties.
384
368
*/
385
369
private static Map <Property , Object > readProperties (final @ NotNull Properties fileProperties ) {
386
370
final Properties filePropertiesLeft = new Properties ();
387
371
filePropertiesLeft .putAll (fileProperties );
388
372
final Map <Property , Object > resolvedProps = new HashMap <>();
389
373
for (final Property prop : Property .values ()) {
390
- if (System .getProperty (prop .key ) != null ) {
391
- LOGGER .debug (prop .key + ": " + System .getProperty (prop .key ));
392
- }
393
- final Object asSystemProperty = parsePropertyValue (System .getProperty (prop .key ));
394
- if (asSystemProperty != null ) {
395
- resolvedProps .put (prop , asSystemProperty );
374
+ String systemValue = System .getProperty (prop .key );
375
+ String envValue = System .getenv (prop .key .replace ('.' , '_' ).toUpperCase ());
376
+
377
+ if (!valueNullOrEmpty (systemValue )) {
378
+ LOGGER .debug ("{}: {}" , prop .key , systemValue );
379
+ final Object parsedValue = parsePropertyValue (systemValue );
380
+ resolvedProps .put (prop , parsedValue );
381
+ filePropertiesLeft .remove (prop .key );
382
+ } else if (!valueNullOrEmpty (envValue )) {
383
+ LOGGER .debug ("{}: {}" , prop .key , envValue );
384
+ final Object parsedValue = parsePropertyValue (envValue );
385
+ resolvedProps .put (prop , parsedValue );
396
386
filePropertiesLeft .remove (prop .key );
397
387
} else {
398
- final Object asEnvProperty = parsePropertyValue (System .getenv ().get (prop .key ));
399
- if (asEnvProperty != null ) {
400
- resolvedProps .put (prop , asEnvProperty );
401
- filePropertiesLeft .remove (prop .key );
402
- } else {
403
- final Object rawValue = filePropertiesLeft .remove (prop .key );
404
- if (rawValue != null ) {
405
- if (rawValue instanceof String ) {
406
- resolvedProps .put (prop , parsePropertyValue ((String ) rawValue ));
407
- } else {
408
- resolvedProps .put (prop , rawValue );
409
- }
388
+ final Object rawValue = filePropertiesLeft .remove (prop .key );
389
+ if (rawValue != null ) {
390
+ if (rawValue instanceof String ) {
391
+ resolvedProps .put (prop , parsePropertyValue ((String ) rawValue ));
392
+ } else {
393
+ resolvedProps .put (prop , rawValue );
410
394
}
411
395
}
412
396
}
@@ -420,7 +404,7 @@ private static Map<Property, Object> readProperties(final @NotNull Properties fi
420
404
resolvedProps .put (Property .EXTRA_PROPERTIES , extraProperties );
421
405
422
406
if (!filePropertiesLeft .isEmpty ()) {
423
- throw new IllegalArgumentException ("unknown properties provided " + filePropertiesLeft );
407
+ throw new IllegalStateException ("unknown properties provided " + filePropertiesLeft );
424
408
}
425
409
426
410
return resolvedProps ;
@@ -444,7 +428,7 @@ private static Map<String, String> filterExtraJavaMailProperties(@Nullable final
444
428
}
445
429
446
430
/**
447
- * @return The property value in boolean, integer or as original string value.
431
+ * @return The property value in boolean, integer, enum, or as the original string value.
448
432
*/
449
433
@ Nullable
450
434
static Object parsePropertyValue (final @ Nullable String propertyValue ) {
@@ -459,40 +443,37 @@ static Object parsePropertyValue(final @Nullable String propertyValue) {
459
443
booleanConversionMap .put ("true" , true );
460
444
booleanConversionMap .put ("no" , false );
461
445
booleanConversionMap .put ("yes" , true );
462
- if (booleanConversionMap .containsKey (propertyValue )) {
446
+ if (booleanConversionMap .containsKey (propertyValue . toLowerCase () )) {
463
447
return booleanConversionMap .get (propertyValue .toLowerCase ());
464
448
}
465
449
// read number value
466
450
try {
467
451
return Integer .valueOf (propertyValue );
468
452
} catch (final NumberFormatException nfe ) {
469
- // ok, so not a number
453
+ // Not a number
470
454
}
471
- // read TransportStrategy value
455
+ // read enum values
472
456
try {
473
457
return TransportStrategy .valueOf (propertyValue );
474
458
} catch (final IllegalArgumentException nfe ) {
475
- // ok, so not a TransportStrategy either
459
+ // Not a TransportStrategy
476
460
}
477
- // read ContentTransferEncoding value
478
461
try {
479
462
return ContentTransferEncoding .valueOf (propertyValue );
480
- } catch (final IllegalArgumentException nfe2 ) {
481
- // ok, so not a ContentTransferEncoding either
463
+ } catch (final IllegalArgumentException nfe ) {
464
+ // Not a ContentTransferEncoding
482
465
}
483
- // read ContentTransferEncoding value
484
466
try {
485
467
return DkimConfig .Canonicalization .valueOf (propertyValue );
486
- } catch (final IllegalArgumentException nfe2 ) {
487
- // ok, so not a Canonicalization either
468
+ } catch (final IllegalArgumentException nfe ) {
469
+ // Not a Canonicalization
488
470
}
489
- // read LoadBalancingStrategy value
490
471
try {
491
472
return LoadBalancingStrategy .valueOf (propertyValue );
492
473
} catch (final IllegalArgumentException nfe ) {
493
- // ok, so not a TransportStrategy either
474
+ // Not a LoadBalancingStrategy
494
475
}
495
- // return value as is (which should be string)
476
+ // return value as is (string)
496
477
return propertyValue ;
497
478
}
498
479
}
0 commit comments