7
7
import org .slf4j .Logger ;
8
8
import org .slf4j .LoggerFactory ;
9
9
10
+ import java .io .File ;
10
11
import java .io .IOException ;
11
12
import java .net .URL ;
13
+ import java .nio .file .Path ;
14
+ import java .nio .file .Paths ;
12
15
import java .util .ArrayList ;
13
16
import java .util .List ;
14
17
import restx .common .ConfigElement ;
15
18
import restx .common .RestxConfig ;
16
19
import restx .common .StdRestxConfig ;
17
20
21
+ import static com .google .common .io .Files .asCharSource ;
22
+
18
23
/**
19
24
* User: xavierhanin
20
25
* Date: 9/24/13
@@ -34,7 +39,11 @@ public ConfigLoader(Optional<String> env) {
34
39
*
35
40
* The name of the resource provided must not contain the extension, which must be .properties
36
41
*
37
- * The loader will first try to load an env specific resource named [resource].[env].properties.
42
+ * The loader will first try to load config from a file which location is provided by a system
43
+ * property, the name of the property being the name returned by #locationKeyForResource.
44
+ *
45
+ * Then it will try to load an env specific resource named [resource].[env].properties.
46
+ *
38
47
* Then it will load a resource named [resource].properties.
39
48
*
40
49
* @param resource the path of the resource to load, without extension.
@@ -46,14 +55,107 @@ public ConfigSupplier fromResource(final String resource) {
46
55
@ Override
47
56
public RestxConfig get () {
48
57
List <ConfigElement > elements = new ArrayList <>();
49
- loadResourceInto (resource + "." + env + ".properties" , elements );
50
- loadResourceInto (resource + ".properties" , elements );
58
+
59
+ loadAllFromResource (elements , resource );
60
+
61
+ return StdRestxConfig .of (elements );
62
+ }
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Provides a ConfigSupplier loading config from a file.
68
+ *
69
+ * The loader will first try to load an env specific file named [path].[env].properties.
70
+ *
71
+ * Then it will try to load a file named [path].properties.
72
+ *
73
+ * Then it will try to load a file named [path] (without extension).
74
+ *
75
+ * @param path the path of the file to load config from.
76
+ *
77
+ * @return a ConfigSupplier ready to load corresponding file.
78
+ */
79
+ public ConfigSupplier fromFile (final String path ) {
80
+ return new ConfigSupplier () {
81
+ @ Override
82
+ public RestxConfig get () {
83
+ List <ConfigElement > elements = new ArrayList <>();
84
+
85
+ loadAllFromFile (elements , path );
86
+
51
87
return StdRestxConfig .of (elements );
52
88
}
53
89
};
54
90
}
55
91
56
- private void loadResourceInto (String name , List <ConfigElement > elements ) {
92
+ /**
93
+ * Gives the name of the system property that can be used to provide a file location
94
+ * to load to override settings for a particular resource.
95
+ *
96
+ * By defaut the name is equal to the resource name where slashes `/` are replaced by dots `.`,
97
+ * with `.location` suffix.
98
+ *
99
+ * Eg.
100
+ * `myapp/settings` becomes `myapp.settings.location`
101
+ *
102
+ * @param resource the resource for which the system property name should be provided.
103
+ *
104
+ * @return the system property name.
105
+ */
106
+ public String locationKeyForResource (String resource ) {
107
+ return resource .replace ('/' , '.' ) + ".location" ;
108
+ }
109
+
110
+ protected void loadAllFromResource (List <ConfigElement > elements , String resource ) {
111
+ String locationKey = locationKeyForResource (resource );
112
+ String location = System .getProperty (locationKey );
113
+ if (location != null ) {
114
+ Path path = Paths .get (location ).toAbsolutePath ();
115
+ logger .info ("loading {} settings from {}" , resource , path );
116
+ loadFileInto (path , elements );
117
+ } else {
118
+ logger .debug ("system property `{}` is not set, no file to load to override settings from {}" ,
119
+ locationKey , resource );
120
+ }
121
+
122
+ loadResourceInto (resource + "." + env + ".properties" , elements );
123
+ loadResourceInto (resource + ".properties" , elements );
124
+ }
125
+
126
+ protected void loadAllFromFile (List <ConfigElement > elements , String path ) {
127
+ if (!path .endsWith (".properties" )) {
128
+ loadFileInto (Paths .get (path + "." + env + ".properties" ), elements );
129
+ loadFileInto (Paths .get (path + ".properties" ), elements );
130
+ }
131
+
132
+ loadFileInto (Paths .get (path ), elements );
133
+ }
134
+
135
+ protected void loadFileInto (Path path , List <ConfigElement > elements ) {
136
+ File file = path .toFile ().getAbsoluteFile ();
137
+ if (!file .exists ()) {
138
+ logger .debug ("no settings loaded from {}: file not available" , file );
139
+ return ;
140
+ }
141
+
142
+ if (!file .isFile ()) {
143
+ logger .warn ("no settings loaded from {}: this is not a file" , file );
144
+ return ;
145
+ }
146
+
147
+ try {
148
+ Iterable <ConfigElement > loadedElements = StdRestxConfig .parse ("file://" + file ,
149
+ asCharSource (file , Charsets .UTF_8 )).elements ();
150
+ Iterables .addAll (elements , loadedElements );
151
+ logger .debug ("loaded {} elements from {}" , Iterables .size (loadedElements ), file );
152
+ } catch (IOException e ) {
153
+ logger .warn ("can't load " + file + ": " + e .getMessage (), e );
154
+ }
155
+
156
+ }
157
+
158
+ protected void loadResourceInto (String name , List <ConfigElement > elements ) {
57
159
URL r ;
58
160
r = Thread .currentThread ().getContextClassLoader ().getResource (name );
59
161
if (r != null ) {
0 commit comments