Skip to content

Commit b3d0bd1

Browse files
authored
Merge pull request #36 from hankem/DoNotLogValue
@DoNotLogValue annotation to prevent values such as sensitive passwords from being logged
2 parents 607102a + 713b0a4 commit b3d0bd1

File tree

69 files changed

+774
-1087
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+774
-1087
lines changed

README.md

Lines changed: 69 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,81 @@
11
Java Config-Builder [![Build Status](https://travis-ci.org/TNG/config-builder.svg?branch=master)](https://travis-ci.org/TNG/config-builder) [![Coverage Status](https://coveralls.io/repos/TNG/config-builder/badge.svg?branch=master&service=github)](https://coveralls.io/github/TNG/config-builder?branch=master) [![Dependency Status](https://www.versioneye.com/user/projects/56989a13af789b002e000b72/badge.svg?style=flat)](https://www.versioneye.com/user/projects/56989a13af789b002e000b72) [![MavenCentral](https://img.shields.io/maven-central/v/com.tngtech.java/config-builder.svg)](http://search.maven.org/#artifactdetails|com.tngtech.java|config-builder|1.3.1|jar) [![Stories in Ready](https://badge.waffle.io/TNG/config-builder.png?label=ready&title=Ready)](http://waffle.io/TNG/config-builder)
2-
==================
2+
===================
33

44
#### Table of Contents
5-
[What It Is](#what-is-it)
6-
[Motivation](#motivation)
5+
[What It Is](#what-it-is)
6+
[Motivation](#motivation)
77
[How To Build Your Config](#how-to-build-your-config)
8-
[How To Merge With An Existing Config](#how-to-merge-with-an-existing-config)
8+
[How To Import An Existing Config](#how-to-import-an-existing-config)
99
[Usage example](#usage-example)
10+
[Presentation](#presentation)
1011
[Java Doc](#java-doc)
1112

1213
What It Is
1314
----------
15+
The Config-Builder makes use of annotations and reflections in order to build configured instances of custom classes.
1416

15-
The ConfigBuilder makes use of annotations and reflections in order to build configured instances of custom classes.
16-
17-
Its features include
17+
Its features include
1818
1. defining default values and loading of values from properties files, system properties, the command line and others
1919
2. configuring of not only String values, but fields of arbitrary types
20-
3. configuring of collection fields
21-
4. merging configs
20+
3. configuring of collection fields
21+
4. merging configs
2222
5. JSR303 validation of the instances it builds.
2323

2424
Motivation
2525
----------
26-
27-
Many Java Projects include one or more classes that store configuration values and objects. Often, these come from
26+
Many Java projects include one or more classes that store configuration values and objects. These often come from
2827
properties files, system properties and environment variables or command line arguments, which requires the developer
2928
to implement the finding and loading of files, parsing the values etc. for every new project.
3029

3130
This is is a time-consuming process, so why not spare this time and get started much faster? Although there are libraries
32-
that implement the loading of properties files and some possibilities of building configured objects e.g. in Spring,
31+
that implement the loading of properties files and some possibilities of building configured objects e.g. in Spring,
3332
there hasn't been a really easy-yet-powerful solution so far.
3433

35-
This is where the Config Builder comes in. It doesn't require any additional classes besides the config itself.
36-
Instead of manually implementing the loading of values from files etc., building a config can now be easily done
34+
This is where the Config-Builder comes in. It doesn't require any additional classes besides the config itself.
35+
Instead of manually implementing the loading of values from files etc., building a config can now be easily done
3736
by using annotations.
3837

3938
How To Build Your Config
4039
------------------------
41-
42-
####1. Create your class:
40+
#### 1. Create your class:
4341
```java
4442
public class Config {
4543
private String someNumber;
4644
private Collection<PidFix> stringCollection;
47-
...
45+
// ...
4846
}
4947
```
50-
####2. Annotate the class (configure the loading of properties files)
5148

52-
If you want the ConfigBuilder to get values from properties files,
53-
you can specify the files' basenames (no file extension or path) by
54-
annotating your config class with the @PropertiesFiles annotation.
55-
You can specify multiple basenames like this:
49+
#### 2. Annotate the class (configure the loading of properties files)
50+
If you want the Config-Builder to get values from properties files,
51+
you can specify the files' basenames (no file extension or path) by
52+
annotating your config class with the `@PropertiesFiles` annotation.
53+
You can specify multiple basenames like this:
5654
```java
5755
@PropertiesFiles({file1,file2,...})
5856
```
5957

60-
By default, properties files are loaded using the PropertyLoader's default config, which
58+
By default, properties files are loaded using the `PropertyLoader`'s default config, which
6159
searches for files in the current directory, the ContextClassLoader and the user's home directory.
62-
You can manually specify the search locations by annotating your config class with the @PropertyLocations annotation, e.g.
60+
You can manually specify the search locations by annotating your config class with the `@PropertyLocations` annotation, e.g.
6361
```java
6462
@PropertyLocations(directories = {"/home/user"}, resourcesForClasses={MyApp.class}, contextClassLoader = true)
6563
```
6664

67-
The PropertyLoader also searches for files with the default suffixes, i.e. the user name, local host names and 'override'.
68-
You can manually set the suffixes by annotating your config class with the @PropertySuffixes annotation like this:
65+
The `PropertyLoader` also searches for files with the default suffixes, i.e. the user name, local host names and 'override'.
66+
You can manually set the suffixes by annotating your config class with the `@PropertySuffixes` annotation like this:
6967
```java
7068
@PropertySuffixes(extraSuffixes = {"tngtech","myname"}, hostNames = true)
7169
```
7270

73-
The default file extensions are .properties and .xml. You can replace the .properties file extension with your own
74-
by annotating your config class with
71+
The default file extensions are `.properties` and `.xml`. You can replace the .properties file extension with your own
72+
by annotating your config class with
7573
```java
7674
@PropertyExtension("fileextension")
7775
```
7876

79-
####3. Annotate the fields
80-
81-
#####3.1 Get the String value
77+
#### 3. Annotate the fields
78+
##### 3.1 Get the String value
8279
There are five annotations that specify where the String value that configures a field comes from:
8380
```java
8481
@DefaultValue("value")
@@ -89,61 +86,63 @@ There are five annotations that specify where the String value that configures a
8986
```
9087

9188
By default, when parsing the annotations, priority is as above, i.e. any value found on the command line overwrites a value found in properties, which in turn overwrites the environment variable value and so on.
92-
This order can be customized, see [4.](#4-change-the-order-in-which-annotations-are-processed-and-use-your-own-error-messages).
89+
This order can be customized, see [§5 (Change the order in which annotations are processed)](#5-change-the-order-in-which-annotations-are-processed).
9390

94-
#####3.2 Transform it to any object or a collection
91+
##### 3.2 Transform it to any object or a collection
9592
Fields don't have to be Strings. You can configure collection fields or even any type you wish (or a collection of that type).
9693

9794
Some simple transformers are included and used by default, e.g. a String will automatically be converted to an integer, a
9895
boolean value or even a collection as needed.
9996

100-
If you need more complex transformers, you can also implement your own by extending the TypeTransformer class, and specifying them in the ```@TypeTransformers``` annotation.
101-
102-
Finally, the original value may not always be a String. To support this case, the annotation takes a list of possible transformers, and the one with the right
103-
source and target types is automatically detected and used.
104-
105-
####4. Add JSR validation annotations and/or define a custom validation method
97+
If you need more complex transformers, you can also implement your own by extending the `TypeTransformer` class, and specifying them in the `@TypeTransformers` annotation.
98+
99+
Finally, the original value may not always be a String. To support this case, the annotation takes a list of possible transformers, and the one with the right
100+
source and target types is automatically detected and used.
106101

102+
##### 3.3 Prevent sensitive data from being logged
103+
Resolved values are usually logged at debug level.
104+
If this is not desired, just add the `@DoNotLogValue` annotation to the field containing your sensitive data.
105+
106+
#### 4. Add JSR validation annotations and/or define a custom validation method
107107
After an instance of your config is built, it is automatically validated. You can either use JSR validation annotations
108-
(@NotNull,...) or define a custom validation method:
108+
(`@NotNull`, ...) or define a custom validation method:
109109

110110
```java
111111
@Validation
112112
private void validate() {
113-
<...>
113+
// ...
114114
}
115115
```
116116

117-
####5. Change the order in which annotations are processed and use your own error messages
118-
117+
#### 5. Change the order in which annotations are processed
119118
You can change the order in which annotations are processed globally or individually for each field.
120-
To specify a global order for parsing ValueExtractorAnnotation annotations, annotate the class with the
121-
@LoadingOrder annotation. To change the order for a certain field, annotate the field.
122-
The order may only contain ValueExtractorAnnotations, i.e.
123-
CommandLineValue.class, PropertyValue.class and DefaultValue.class. Example:
119+
To specify a global order for parsing `ValueExtractorAnnotation` annotations, annotate the class with the
120+
`@LoadingOrder` annotation. To change the order for a certain field, annotate the field.
121+
The `@LoadingOrder` may only contain the following values:
124122
```java
125-
@LoadingOrder({PropertyValue.class, EnvironmentVariableValue.class, SystemPropertyValue.class, CommandLineValue.class, DefaultValue.class})
123+
@LoadingOrder({PropertyValue.class, EnvironmentVariableValue.class, SystemPropertyValue.class, CommandLineValue.class, ImportedValue.class, DefaultValue.class})
126124
```
127125

128-
To specify your own error messages file (which is loaded by the PropertyLoader with the same settings as other the properties files),
129-
annotate the class with the @ErrorMessageFile annotation:
126+
#### 6. Use your own error messages
127+
To specify your own error messages file (which is loaded by the `PropertyLoader` with the same settings as other the properties files),
128+
annotate the class with the `@ErrorMessageFile` annotation:
130129
```java
131130
@ErrorMessageFile("myErrorMessages")
132131
```
133132

134-
####6. Build an instance of your class
133+
#### 7. Build an instance of your class
135134
```java
136-
Config myConfig = new ConfigBuilder<Config>(Config.class).withCommandLineArgs(args).build();
135+
Config myConfig = ConfigBuilder.on(Config.class).withCommandLineArgs(args).build();
137136
```
138-
How To Merge With An Existing Config
139-
------------------------------------
140137

141-
If you already have an instance of your config class and want to only configure the fields which are not null, use
138+
How To Import An Existing Config
139+
--------------------------------
140+
If you already have an instance of your config class and want to only configure the fields which are not `null`, use
142141
```java
143-
newConfig = new ConfigBuilder<Config>(Config.class).withCommandLineArgs(args).merge(existingConfig);
142+
Config newConfig = ConfigBuilder.on(Config.class).withCommandLineArgs(args).withImportedConfiguration(existingConfig).build();
144143
```
145-
<b>Note that primitive type fields are always overwritten!</b>
146-
Since primitive types can not be checked for 'null', it is not possible to check whether primitive fields of an existing config
144+
<b>Note that primitive type fields are always overwritten!</b>
145+
Since primitive types can not be checked for `null`, it is not possible to check whether primitive fields of an existing config
147146
have already been set. Hence, for the moment, primitives are always overwritten.
148147

149148
Usage example
@@ -158,39 +157,40 @@ public class Config {
158157
public static class StringToPidFixTransformer extends TypeTransformer<String,PidFix> {
159158
@Override
160159
public PidFix transform(String input) {
161-
<...>
160+
// ...
162161
}
163162
}
164-
163+
165164
@DefaultValue("false") // values are automatically be converted to primitive types
166165
@CommandLineValue(shortOpt="t", longOpt="test", hasArg=false) // this is a flag argument
167166
private boolean runInTestMode;
168-
167+
169168
@DefaultValue("3")
170169
@CommandLineValue(shortOpt="rl", longOpt="runLevel", hasArg=true)
171170
private int runLevel;
172-
171+
173172
@EnvironmentVariableValue("PATH")
174173
@PropertyValue("path") // maps to the key "path" in the properties file
175174
private String path;
176-
175+
177176
@SystemPropertyValue("user.name") // maps to the field "user.name" in the system properties
178177
@NotEmpty("username.notEmpty") // JSR-303 validation (Field should not be empty)
179178
private String userName;
180-
179+
181180
@TypeTransformers(StringToPidFixTransformer.class)
182181
@CommandLineValue(shortOpt="pc", longOpt="pidFixCollection", hasArg=true)
183182
private Collection<PidFix> pidFixCollection;
184-
183+
185184
@TypeTransformers(StringToPidFixTransformer.class)
186185
@CommandLineValue(shortOpt="p", longOpt="pidFix", hasArg=true)
187186
private PidFix pidFix;
188-
187+
189188
@Validation
190189
private void validate() {
191-
<...>
190+
// ...
192191
}
193-
...
192+
193+
//...
194194
}
195195
```
196196
To build a configured instance, simply call
@@ -199,12 +199,9 @@ Config myConfig = ConfigBuilder.on(Config.class).withCommandLineArgs(args).build
199199
```
200200

201201
Presentation
202-
--------
203-
202+
------------
204203
A sample presentation can be found at http://tng.github.io/config-builder
205204

206-
207205
Java Doc
208206
--------
209-
210207
Full javadoc of the code can be found here http://tng.github.io/config-builder/javadoc

pom.xml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
</developers>
4242
<organization>
4343
<name>TNG Technology Consulting</name>
44-
<url>http://www.tngtech.com/</url>
44+
<url>https://www.tngtech.com/</url>
4545
</organization>
4646

4747
<parent>
@@ -134,13 +134,11 @@
134134
</profiles>
135135

136136
<dependencies>
137-
138137
<dependency>
139138
<groupId>com.tngtech.java</groupId>
140139
<artifactId>property-loader</artifactId>
141140
<version>1.3.1</version>
142141
</dependency>
143-
144142
<dependency>
145143
<groupId>junit</groupId>
146144
<artifactId>junit</artifactId>
@@ -156,13 +154,7 @@
156154
<dependency>
157155
<groupId>org.assertj</groupId>
158156
<artifactId>assertj-core</artifactId>
159-
<version>2.5.0</version>
160-
<scope>test</scope>
161-
</dependency>
162-
<dependency>
163-
<groupId>org.unitils</groupId>
164-
<artifactId>unitils-core</artifactId>
165-
<version>3.4.6</version>
157+
<version>2.6.0</version>
166158
<scope>test</scope>
167159
</dependency>
168160
<dependency>

src/main/java/com/tngtech/configbuilder/ConfigBuilder.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import com.tngtech.configbuilder.annotation.propertyloaderconfiguration.ErrorMessageFile;
66
import com.tngtech.configbuilder.configuration.BuilderConfiguration;
77
import com.tngtech.configbuilder.configuration.ErrorMessageSetup;
8-
import com.tngtech.configbuilder.util.ConfigBuilderFactory;
98
import com.tngtech.configbuilder.util.*;
109
import com.tngtech.propertyloader.PropertyLoader;
1110
import com.tngtech.propertyloader.impl.DefaultPropertyFilterContainer;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.tngtech.configbuilder.annotation.configuration;
2+
3+
import com.tngtech.configbuilder.ConfigBuilder;
4+
5+
import java.lang.annotation.ElementType;
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.RetentionPolicy;
8+
import java.lang.annotation.Target;
9+
10+
/**
11+
* This annotation can be used to prevent a field's value from being logged
12+
* when {@link ConfigBuilder#build(Object...)} builds a config instance.
13+
*/
14+
@Target(ElementType.FIELD)
15+
@Retention(RetentionPolicy.RUNTIME)
16+
public @interface DoNotLogValue {
17+
}

src/main/java/com/tngtech/configbuilder/annotation/configuration/LoadingOrder.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,25 @@
22

33
import com.tngtech.configbuilder.annotation.valueextractor.CommandLineValue;
44
import com.tngtech.configbuilder.annotation.valueextractor.DefaultValue;
5+
import com.tngtech.configbuilder.annotation.valueextractor.EnvironmentVariableValue;
6+
import com.tngtech.configbuilder.annotation.valueextractor.ImportedValue;
57
import com.tngtech.configbuilder.annotation.valueextractor.PropertyValue;
8+
import com.tngtech.configbuilder.annotation.valueextractor.SystemPropertyValue;
9+
import com.tngtech.configbuilder.annotation.valueextractor.ValueExtractorAnnotation;
610

711
import java.lang.annotation.*;
812

913
/**
10-
* This annotation is used to specify the order in which the annotations CommandLineValue, PropertyValue and DefaultValue are processed.
14+
* This annotation is used to specify the order in which the {@link ValueExtractorAnnotation} annotations
15+
* {@link CommandLineValue}, {@link PropertyValue}, {@link EnvironmentVariableValue},
16+
* {@link SystemPropertyValue}, {@link ImportedValue} and {@link DefaultValue} are processed.
1117
* It can specify the order for a certain field if placed on the field, or a global order if placed on the config class.
1218
* The annotations are processed top-down until a string value is found, i.e. the order is from the most important to the least important.
13-
* The order may only contain ValueExtractorAnnotations, i.e. CommandLineValue.class, PropertyValue.class and DefaultValue.class.<br>
19+
* The {@code LoadingOrder} may only contain the aforementioned {@link ValueExtractorAnnotation} classes.<br>
1420
* <b>Usage:</b> <code>@LoadingOrder(value = {PropertyValue.class, CommandLineValue.class, DefaultValue.class})</code>
1521
*/
1622
@Target({ElementType.TYPE, ElementType.FIELD})
1723
@Retention(RetentionPolicy.RUNTIME)
1824
public @interface LoadingOrder {
19-
public Class<? extends Annotation>[] value() default {CommandLineValue.class, PropertyValue.class, DefaultValue.class};
20-
25+
Class<? extends Annotation>[] value() default {CommandLineValue.class, PropertyValue.class, DefaultValue.class};
2126
}
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package com.tngtech.configbuilder.annotation.configuration;
22

3-
import com.tngtech.configbuilder.annotation.valueextractor.CommandLineValue;
4-
import com.tngtech.configbuilder.annotation.valueextractor.DefaultValue;
5-
import com.tngtech.configbuilder.annotation.valueextractor.PropertyValue;
6-
73
import java.lang.annotation.*;
84

95
/**
@@ -13,6 +9,5 @@
139
@Target({ElementType.TYPE})
1410
@Retention(RetentionPolicy.RUNTIME)
1511
public @interface PropertyNamePrefix {
16-
public String[] value() default {""};
17-
12+
String[] value() default {""};
1813
}

src/main/java/com/tngtech/configbuilder/annotation/propertyloaderconfiguration/PropertyExtension.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@
1313
@Target(ElementType.TYPE)
1414
@Retention(RetentionPolicy.RUNTIME)
1515
public @interface PropertyExtension {
16-
public String value();
16+
String value();
1717
}

0 commit comments

Comments
 (0)