hocon 0.0.7 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +4 -2
- data/lib/hocon.rb +2 -0
- data/lib/hocon/config.rb +1010 -0
- data/lib/hocon/config_error.rb +32 -2
- data/lib/hocon/config_factory.rb +46 -0
- data/lib/hocon/config_include_context.rb +49 -0
- data/lib/hocon/config_includer_file.rb +27 -0
- data/lib/hocon/config_list.rb +49 -0
- data/lib/hocon/config_mergeable.rb +74 -0
- data/lib/hocon/config_object.rb +144 -1
- data/lib/hocon/config_parse_options.rb +33 -9
- data/lib/hocon/config_parseable.rb +51 -0
- data/lib/hocon/config_render_options.rb +4 -2
- data/lib/hocon/config_resolve_options.rb +31 -0
- data/lib/hocon/config_syntax.rb +5 -2
- data/lib/hocon/config_util.rb +73 -0
- data/lib/hocon/config_value.rb +122 -0
- data/lib/hocon/config_value_factory.rb +66 -2
- data/lib/hocon/config_value_type.rb +5 -2
- data/lib/hocon/impl.rb +2 -0
- data/lib/hocon/impl/abstract_config_node.rb +29 -0
- data/lib/hocon/impl/abstract_config_node_value.rb +11 -0
- data/lib/hocon/impl/abstract_config_object.rb +148 -42
- data/lib/hocon/impl/abstract_config_value.rb +251 -11
- data/lib/hocon/impl/array_iterator.rb +19 -0
- data/lib/hocon/impl/config_boolean.rb +7 -1
- data/lib/hocon/impl/config_concatenation.rb +177 -28
- data/lib/hocon/impl/config_delayed_merge.rb +329 -0
- data/lib/hocon/impl/config_delayed_merge_object.rb +274 -0
- data/lib/hocon/impl/config_document_parser.rb +647 -0
- data/lib/hocon/impl/config_double.rb +44 -0
- data/lib/hocon/impl/config_impl.rb +143 -19
- data/lib/hocon/impl/config_impl_util.rb +18 -0
- data/lib/hocon/impl/config_include_kind.rb +10 -0
- data/lib/hocon/impl/config_int.rb +13 -1
- data/lib/hocon/impl/config_node_array.rb +11 -0
- data/lib/hocon/impl/config_node_comment.rb +19 -0
- data/lib/hocon/impl/config_node_complex_value.rb +54 -0
- data/lib/hocon/impl/config_node_concatenation.rb +11 -0
- data/lib/hocon/impl/config_node_field.rb +81 -0
- data/lib/hocon/impl/config_node_include.rb +33 -0
- data/lib/hocon/impl/config_node_object.rb +276 -0
- data/lib/hocon/impl/config_node_path.rb +48 -0
- data/lib/hocon/impl/config_node_root.rb +60 -0
- data/lib/hocon/impl/config_node_simple_value.rb +42 -0
- data/lib/hocon/impl/config_node_single_token.rb +17 -0
- data/lib/hocon/impl/config_null.rb +15 -7
- data/lib/hocon/impl/config_number.rb +43 -4
- data/lib/hocon/impl/config_parser.rb +403 -0
- data/lib/hocon/impl/config_reference.rb +142 -0
- data/lib/hocon/impl/config_string.rb +55 -7
- data/lib/hocon/impl/container.rb +29 -0
- data/lib/hocon/impl/default_transformer.rb +24 -15
- data/lib/hocon/impl/from_map_mode.rb +3 -1
- data/lib/hocon/impl/full_includer.rb +2 -0
- data/lib/hocon/impl/memo_key.rb +42 -0
- data/lib/hocon/impl/mergeable_value.rb +8 -0
- data/lib/hocon/impl/origin_type.rb +8 -2
- data/lib/hocon/impl/parseable.rb +455 -91
- data/lib/hocon/impl/path.rb +181 -59
- data/lib/hocon/impl/path_builder.rb +24 -3
- data/lib/hocon/impl/path_parser.rb +280 -0
- data/lib/hocon/impl/replaceable_merge_stack.rb +22 -0
- data/lib/hocon/impl/resolve_context.rb +254 -0
- data/lib/hocon/impl/resolve_memos.rb +21 -0
- data/lib/hocon/impl/resolve_result.rb +39 -0
- data/lib/hocon/impl/resolve_source.rb +354 -0
- data/lib/hocon/impl/resolve_status.rb +3 -1
- data/lib/hocon/impl/simple_config.rb +264 -10
- data/lib/hocon/impl/simple_config_document.rb +48 -0
- data/lib/hocon/impl/simple_config_list.rb +282 -8
- data/lib/hocon/impl/simple_config_object.rb +424 -88
- data/lib/hocon/impl/simple_config_origin.rb +263 -71
- data/lib/hocon/impl/simple_include_context.rb +31 -1
- data/lib/hocon/impl/simple_includer.rb +196 -1
- data/lib/hocon/impl/substitution_expression.rb +38 -0
- data/lib/hocon/impl/token.rb +17 -4
- data/lib/hocon/impl/token_type.rb +6 -2
- data/lib/hocon/impl/tokenizer.rb +339 -109
- data/lib/hocon/impl/tokens.rb +330 -79
- data/lib/hocon/impl/unmergeable.rb +14 -1
- data/lib/hocon/impl/unsupported_operation_error.rb +6 -0
- data/lib/hocon/impl/url.rb +37 -0
- data/lib/hocon/parser.rb +7 -0
- data/lib/hocon/parser/config_document.rb +92 -0
- data/lib/hocon/parser/config_document_factory.rb +36 -0
- data/lib/hocon/parser/config_node.rb +30 -0
- metadata +67 -43
- data/lib/hocon/impl/config_float.rb +0 -13
- data/lib/hocon/impl/parser.rb +0 -977
- data/lib/hocon/impl/properties_parser.rb +0 -83
@@ -1,24 +1,200 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'uri'
|
2
4
|
require 'hocon/impl'
|
5
|
+
require 'hocon/impl/url'
|
3
6
|
require 'hocon/impl/origin_type'
|
7
|
+
require 'hocon/config_error'
|
4
8
|
|
5
9
|
class Hocon::Impl::SimpleConfigOrigin
|
6
10
|
|
7
|
-
|
11
|
+
OriginType = Hocon::Impl::OriginType
|
12
|
+
|
13
|
+
def initialize(description, line_number, end_line_number,
|
14
|
+
origin_type, url_or_nil, resource_or_nil, comments_or_nil)
|
15
|
+
if !description
|
16
|
+
raise ArgumentError, "description may not be nil"
|
17
|
+
end
|
18
|
+
|
19
|
+
# HACK: naming this variable with an underscore, because the upstream library
|
20
|
+
# has both a member var and a no-arg method by the name "description", and
|
21
|
+
# I don't think Ruby can handle that.
|
22
|
+
@_description = description
|
23
|
+
@line_number = line_number
|
24
|
+
@end_line_number = end_line_number
|
25
|
+
@origin_type = origin_type
|
26
|
+
@url_or_nil = url_or_nil
|
27
|
+
@resource_or_nil = resource_or_nil
|
28
|
+
@comments_or_nil = comments_or_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :_description, :line_number, :end_line_number, :origin_type,
|
32
|
+
:url_or_nil, :resource_or_nil, :comments_or_nil
|
33
|
+
|
34
|
+
|
35
|
+
def self.new_simple(description)
|
36
|
+
self.new(description, -1, -1,
|
37
|
+
OriginType::GENERIC,
|
38
|
+
nil, nil, nil)
|
39
|
+
end
|
8
40
|
|
9
41
|
def self.new_file(file_path)
|
10
42
|
url = URI.join('file:///', file_path)
|
11
43
|
self.new(file_path, -1, -1,
|
12
|
-
|
13
|
-
url, nil)
|
44
|
+
OriginType::FILE,
|
45
|
+
url, nil, nil)
|
14
46
|
end
|
15
47
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
48
|
+
# NOTE: not porting `new_url` because we're not going to support URLs for now
|
49
|
+
|
50
|
+
def self.new_resource(resource, url = nil)
|
51
|
+
desc = nil
|
52
|
+
if ! url.nil?
|
53
|
+
desc = resource + " @ " + url.to_external_form
|
54
|
+
else
|
55
|
+
desc = resource
|
56
|
+
end
|
57
|
+
Hocon::Impl::SimpleConfigOrigin.new(desc, -1, -1, OriginType::RESOURCE,
|
58
|
+
url.nil? ? nil : url.to_external_form,
|
59
|
+
resource, nil)
|
20
60
|
end
|
21
61
|
|
62
|
+
def with_line_number(line_number)
|
63
|
+
if (line_number == @line_number) and
|
64
|
+
(line_number == @end_line_number)
|
65
|
+
self
|
66
|
+
else
|
67
|
+
Hocon::Impl::SimpleConfigOrigin.new(
|
68
|
+
@_description, line_number, line_number,
|
69
|
+
@origin_type, @url_or_nil, @resource_or_nil, @comments_or_nil)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_url(url)
|
74
|
+
SimpleConfigOrigin.new(@_description, line_number, end_line_number, origin_type,
|
75
|
+
url.nil? ? nil : url.to_s, resource_or_nil,
|
76
|
+
comments_or_nil)
|
77
|
+
end
|
78
|
+
|
79
|
+
def with_comments(comments)
|
80
|
+
if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(comments, @comments_or_nil)
|
81
|
+
self
|
82
|
+
else
|
83
|
+
Hocon::Impl::SimpleConfigOrigin.new(
|
84
|
+
@_description, @line_number, @end_line_number,
|
85
|
+
@origin_type, @url_or_nil, @resource_or_nil, comments)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def prepend_comments(comments)
|
90
|
+
if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(comments, @comments_or_nil)
|
91
|
+
self
|
92
|
+
elsif @comments_or_nil.nil?
|
93
|
+
with_comments(comments)
|
94
|
+
else
|
95
|
+
merged = comments + @comments_or_nil
|
96
|
+
with_comments(merged)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def append_comments(comments)
|
101
|
+
if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(comments, @comments_or_nil)
|
102
|
+
self
|
103
|
+
elsif comments_or_nil.nil?
|
104
|
+
with_comments(comments)
|
105
|
+
else
|
106
|
+
merged = comments_or_nil + comments
|
107
|
+
with_comments(merged)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def description
|
112
|
+
if @line_number < 0
|
113
|
+
_description
|
114
|
+
elsif end_line_number == line_number
|
115
|
+
"#{_description}: #{line_number}"
|
116
|
+
else
|
117
|
+
"#{_description}: #{line_number}-#{end_line_number}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def ==(other)
|
122
|
+
if other.is_a? Hocon::Impl::SimpleConfigOrigin
|
123
|
+
@_description == other._description &&
|
124
|
+
@line_number == other.line_number &&
|
125
|
+
@end_line_number == other.end_line_number &&
|
126
|
+
@origin_type == other.origin_type &&
|
127
|
+
Hocon::Impl::ConfigImplUtil.equals_handling_nil?(@url_or_nil, other.url_or_nil) &&
|
128
|
+
Hocon::Impl::ConfigImplUtil.equals_handling_nil?(@resource_or_nil, other.resource_or_nil)
|
129
|
+
else
|
130
|
+
false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def hash
|
135
|
+
h = 41 * (41 + @_description.hash)
|
136
|
+
h = 41 * (h + @line_number)
|
137
|
+
h = 41 * (h + @end_line_number)
|
138
|
+
h = 41 * (h + @origin_type.hash)
|
139
|
+
|
140
|
+
unless @url_or_nil.nil?
|
141
|
+
h = 41 * (h + @url_or_nil.hash)
|
142
|
+
end
|
143
|
+
|
144
|
+
unless @resource_or_nil.nil?
|
145
|
+
h = 41 * (h + @resource_or_nil.hash)
|
146
|
+
end
|
147
|
+
|
148
|
+
h
|
149
|
+
end
|
150
|
+
|
151
|
+
def to_s
|
152
|
+
"ConfigOrigin(#{_description})"
|
153
|
+
end
|
154
|
+
|
155
|
+
def filename
|
156
|
+
if origin_type == OriginType::FILE
|
157
|
+
_description
|
158
|
+
elsif ! url_or_nil.nil?
|
159
|
+
url = nil
|
160
|
+
begin
|
161
|
+
url = Hocon::Impl::Url.new(url_or_nil)
|
162
|
+
rescue Hocon::Impl::Url::MalformedUrlError => e
|
163
|
+
return nil
|
164
|
+
end
|
165
|
+
|
166
|
+
if url.get_protocol == "file"
|
167
|
+
url.get_file
|
168
|
+
else
|
169
|
+
nil
|
170
|
+
end
|
171
|
+
else
|
172
|
+
nil
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def url
|
177
|
+
if url_or_nil.nil?
|
178
|
+
nil
|
179
|
+
else
|
180
|
+
begin
|
181
|
+
Hocon::Impl::Url.new(url_or_nil)
|
182
|
+
rescue Hocon::Impl::Url::MalformedUrlError => e
|
183
|
+
nil
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def resource
|
189
|
+
resource_or_nil
|
190
|
+
end
|
191
|
+
|
192
|
+
def comments
|
193
|
+
@comments_or_nil || []
|
194
|
+
end
|
195
|
+
|
196
|
+
MERGE_OF_PREFIX = "merge of "
|
197
|
+
|
22
198
|
def self.remove_merge_of_prefix(desc)
|
23
199
|
if desc.start_with?(MERGE_OF_PREFIX)
|
24
200
|
desc = desc[MERGE_OF_PREFIX.length, desc.length - 1]
|
@@ -41,8 +217,8 @@ class Hocon::Impl::SimpleConfigOrigin
|
|
41
217
|
|
42
218
|
# first use the "description" field which has no line numbers
|
43
219
|
# cluttering it.
|
44
|
-
a_desc = remove_merge_of_prefix(a.
|
45
|
-
b_desc = remove_merge_of_prefix(b.
|
220
|
+
a_desc = remove_merge_of_prefix(a._description)
|
221
|
+
b_desc = remove_merge_of_prefix(b._description)
|
46
222
|
|
47
223
|
if a_desc == b_desc
|
48
224
|
merged_desc = a_desc
|
@@ -62,8 +238,8 @@ class Hocon::Impl::SimpleConfigOrigin
|
|
62
238
|
#
|
63
239
|
# description() method includes line numbers, so use it instead
|
64
240
|
# of description field.
|
65
|
-
a_full = remove_merge_of_prefix(a.
|
66
|
-
b_full = remove_merge_of_prefix(b.
|
241
|
+
a_full = remove_merge_of_prefix(a._description)
|
242
|
+
b_full = remove_merge_of_prefix(b._description)
|
67
243
|
|
68
244
|
merged_desc = "#{MERGE_OF_PREFIX}#{a_full},#{b_full}"
|
69
245
|
merged_start_line = -1
|
@@ -77,6 +253,13 @@ class Hocon::Impl::SimpleConfigOrigin
|
|
77
253
|
nil
|
78
254
|
end
|
79
255
|
|
256
|
+
merged_resource =
|
257
|
+
if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(a.resource_or_nil, b.resource_or_nil)
|
258
|
+
a.resource_or_nil
|
259
|
+
else
|
260
|
+
nil
|
261
|
+
end
|
262
|
+
|
80
263
|
if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(a.comments_or_nil, b.comments_or_nil)
|
81
264
|
merged_comments = a.comments_or_nil
|
82
265
|
else
|
@@ -91,84 +274,93 @@ class Hocon::Impl::SimpleConfigOrigin
|
|
91
274
|
|
92
275
|
Hocon::Impl::SimpleConfigOrigin.new(
|
93
276
|
merged_desc, merged_start_line, merged_end_line,
|
94
|
-
merged_type, merged_url, merged_comments)
|
277
|
+
merged_type, merged_url, merged_resource, merged_comments)
|
95
278
|
end
|
96
279
|
|
97
|
-
def self.
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
remaining.pop
|
280
|
+
def self.similarity(a, b)
|
281
|
+
count = 0
|
282
|
+
if a.origin_type == b.origin_type
|
283
|
+
count += 1
|
284
|
+
end
|
285
|
+
|
286
|
+
if a._description == b._description
|
287
|
+
count += 1
|
288
|
+
|
289
|
+
# only count these if the description field (which is the file
|
290
|
+
# or resource name) also matches.
|
291
|
+
if a.line_number == b.line_number
|
292
|
+
count += 1
|
111
293
|
end
|
112
294
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
end
|
295
|
+
if a.end_line_number == b.end_line_number
|
296
|
+
count += 1
|
297
|
+
end
|
117
298
|
|
299
|
+
if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(a.url_or_nil, b.url_or_nil)
|
300
|
+
count += 1
|
301
|
+
end
|
118
302
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
raise ArgumentError, "description may not be nil"
|
303
|
+
if Hocon::Impl::ConfigImplUtil.equals_handling_nil?(a.resource_or_nil, b.resource_or_nil)
|
304
|
+
count += 1
|
305
|
+
end
|
123
306
|
end
|
124
307
|
|
125
|
-
|
126
|
-
@line_number = line_number
|
127
|
-
@end_line_number = end_line_number
|
128
|
-
@origin_type = origin_type
|
129
|
-
@url_or_nil = url
|
130
|
-
@comments_or_nil = comments
|
308
|
+
count
|
131
309
|
end
|
132
310
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
def set_line_number(line_number)
|
137
|
-
if (line_number == @line_number) and
|
138
|
-
(line_number == @end_line_number)
|
139
|
-
self
|
311
|
+
def self.merge_three(a, b, c)
|
312
|
+
if similarity(a, b) >= similarity(b, c)
|
313
|
+
merge_two(merge_two(a, b), c)
|
140
314
|
else
|
141
|
-
|
142
|
-
@description, line_number, line_number,
|
143
|
-
@origin_type, @url_or_nil, @comments_or_nil)
|
315
|
+
merge_two(a, merge_two(b, c))
|
144
316
|
end
|
145
317
|
end
|
146
318
|
|
147
|
-
def
|
148
|
-
|
149
|
-
|
150
|
-
else
|
151
|
-
Hocon::Impl::SimpleConfigOrigin.new(
|
152
|
-
@description, @line_number, @end_line_number,
|
153
|
-
@origin_type, @url_or_nil, comments)
|
154
|
-
end
|
319
|
+
def self.merge_two_origins(a, b)
|
320
|
+
# a, b are ConfigOrigins
|
321
|
+
merge_two(a, b)
|
155
322
|
end
|
156
323
|
|
157
|
-
def
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
324
|
+
def self.merge_value_origins(stack)
|
325
|
+
# stack is an array of AbstractConfigValue
|
326
|
+
origins = stack.map { |v| v.origin}
|
327
|
+
merge_origins(origins)
|
328
|
+
end
|
329
|
+
|
330
|
+
# see also 'merge_two_origins' and 'merge_three_origins'
|
331
|
+
def self.merge_origins(stack)
|
332
|
+
# stack is an array of ConfigOrigin
|
333
|
+
if stack.empty?
|
334
|
+
raise Hocon::ConfigError::ConfigBugOrBrokenError, "can't merge empty list of origins"
|
335
|
+
elsif stack.length == 1
|
336
|
+
stack[0]
|
337
|
+
elsif stack.length == 2
|
338
|
+
merge_two(stack[0], stack[1])
|
162
339
|
else
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
340
|
+
remaining = []
|
341
|
+
stack.each do |o|
|
342
|
+
remaining << o
|
343
|
+
end
|
344
|
+
while remaining.size > 2
|
345
|
+
c = remaining.last
|
346
|
+
remaining.delete_at(remaining.size - 1)
|
347
|
+
b = remaining.last
|
348
|
+
remaining.delete_at(remaining.size - 1)
|
349
|
+
a = remaining.last
|
350
|
+
remaining.delete_at(remaining.size - 1)
|
351
|
+
|
352
|
+
merged = merge_three(a, b, c)
|
353
|
+
|
354
|
+
remaining << merged
|
355
|
+
end
|
356
|
+
|
357
|
+
# should be down to either 1 or 2
|
358
|
+
self.merge_origins(remaining)
|
167
359
|
end
|
168
360
|
end
|
169
361
|
|
170
|
-
|
171
|
-
|
172
|
-
|
362
|
+
# NOTE: skipping 'toFields', 'toFieldsDelta', 'fieldsDelta', 'fromFields',
|
363
|
+
# 'applyFieldsDelta', and 'fromBase' from upstream for now, because they appear
|
364
|
+
# to be about serialization and we probably won't be supporting that.
|
173
365
|
|
174
|
-
end
|
366
|
+
end
|
@@ -1,7 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require 'hocon/impl'
|
4
|
+
require 'hocon/impl/simple_includer'
|
5
|
+
require 'hocon/config_include_context'
|
6
|
+
require 'hocon/impl/config_impl'
|
2
7
|
|
3
8
|
class Hocon::Impl::SimpleIncludeContext
|
9
|
+
include Hocon::ConfigIncludeContext
|
10
|
+
|
4
11
|
def initialize(parseable)
|
5
12
|
@parseable = parseable
|
6
13
|
end
|
7
|
-
|
14
|
+
|
15
|
+
def with_parseable(parseable)
|
16
|
+
if parseable.equal?(@parseable)
|
17
|
+
self
|
18
|
+
else
|
19
|
+
self.class.new(parseable)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def relative_to(filename)
|
24
|
+
if Hocon::Impl::ConfigImpl.trace_loads_enabled
|
25
|
+
Hocon::Impl::ConfigImpl.trace("Looking for '#{filename}' relative to #{@parseable}")
|
26
|
+
end
|
27
|
+
if ! @parseable.nil?
|
28
|
+
@parseable.relative_to(filename)
|
29
|
+
else
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def parse_options
|
35
|
+
Hocon::Impl::SimpleIncluder.clear_for_include(@parseable.options)
|
36
|
+
end
|
37
|
+
end
|
@@ -1,7 +1,202 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'stringio'
|
1
4
|
require 'hocon/impl'
|
2
5
|
require 'hocon/impl/full_includer'
|
6
|
+
require 'hocon/impl/url'
|
7
|
+
require 'hocon/impl/config_impl'
|
8
|
+
require 'hocon/config_error'
|
9
|
+
require 'hocon/config_syntax'
|
10
|
+
require 'hocon/impl/simple_config_object'
|
11
|
+
require 'hocon/impl/simple_config_origin'
|
12
|
+
require 'hocon/config_includer_file'
|
13
|
+
require 'hocon/config_factory'
|
14
|
+
require 'hocon/impl/parseable'
|
3
15
|
|
4
16
|
class Hocon::Impl::SimpleIncluder < Hocon::Impl::FullIncluder
|
17
|
+
|
18
|
+
ConfigBugorBrokenError = Hocon::ConfigError::ConfigBugOrBrokenError
|
19
|
+
ConfigIOError = Hocon::ConfigError::ConfigIOError
|
20
|
+
SimpleConfigObject = Hocon::Impl::SimpleConfigObject
|
21
|
+
SimpleConfigOrigin = Hocon::Impl::SimpleConfigOrigin
|
22
|
+
|
23
|
+
|
24
|
+
def initialize(fallback)
|
25
|
+
@fallback = fallback
|
26
|
+
end
|
27
|
+
|
28
|
+
# ConfigIncludeContext does this for us on its options
|
29
|
+
def self.clear_for_include(options)
|
30
|
+
# the class loader and includer are inherited, but not this other stuff
|
31
|
+
options.set_syntax(nil).set_origin_description(nil).set_allow_missing(true)
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
# this is the heuristic includer
|
36
|
+
def include(context, name)
|
37
|
+
obj = self.class.include_without_fallback(context, name)
|
38
|
+
|
39
|
+
# now use the fallback includer if any and merge its result
|
40
|
+
if ! (@fallback.nil?)
|
41
|
+
obj.with_fallback(@fallback.include(context, name))
|
42
|
+
else
|
43
|
+
obj
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# the heuristic includer in static form
|
48
|
+
def self.include_without_fallback(context, name)
|
49
|
+
# the heuristic is valid URL then URL, else relative to including file;
|
50
|
+
# relativeTo in a file falls back to classpath inside relativeTo().
|
51
|
+
|
52
|
+
url = nil
|
53
|
+
begin
|
54
|
+
url = Hocon::Impl::Url.new(name)
|
55
|
+
rescue Hocon::Impl::Url::MalformedUrlError => e
|
56
|
+
url = nil
|
57
|
+
end
|
58
|
+
|
59
|
+
if !(url.nil?)
|
60
|
+
include_url_without_fallback(context, url)
|
61
|
+
else
|
62
|
+
source = RelativeNameSource.new(context)
|
63
|
+
from_basename(source, name, context.parse_options)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# NOTE: not porting `include_url` or `include_url_without_fallback` from upstream,
|
68
|
+
# because we probably won't support URL includes for now.
|
69
|
+
|
70
|
+
def include_file(context, file)
|
71
|
+
obj = self.class.include_file_without_fallback(context, file)
|
72
|
+
|
73
|
+
# now use the fallback includer if any and merge its result
|
74
|
+
if (!@fallback.nil?) && @fallback.is_a?(Hocon::ConfigIncluderFile)
|
75
|
+
obj.with_fallback(@fallback).include_file(context, file)
|
76
|
+
else
|
77
|
+
obj
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.include_file_without_fallback(context, file)
|
82
|
+
Hocon::ConfigFactory.parse_file_any_syntax(file, context.parse_options).root
|
83
|
+
end
|
84
|
+
|
85
|
+
# NOTE: not porting `include_resources` or `include_resources_without_fallback`
|
86
|
+
# for now because we're not going to support looking for things on the ruby
|
87
|
+
# load path for now.
|
88
|
+
|
89
|
+
def with_fallback(fallback)
|
90
|
+
if self.equal?(fallback)
|
91
|
+
raise ConfigBugOrBrokenError, "trying to create includer cycle"
|
92
|
+
elsif @fallback.equal?(fallback)
|
93
|
+
self
|
94
|
+
elsif @fallback.nil?
|
95
|
+
self.class.new(@fallback.with_fallback(fallback))
|
96
|
+
else
|
97
|
+
self.class.new(fallback)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
class NameSource
|
103
|
+
def name_to_parseable(name, parse_options)
|
104
|
+
raise Hocon::ConfigError::ConfigBugOrBrokenError,
|
105
|
+
"name_to_parseable must be implemented by subclass (#{self.class})"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class RelativeNameSource < NameSource
|
110
|
+
def initialize(context)
|
111
|
+
@context = context
|
112
|
+
end
|
113
|
+
|
114
|
+
def name_to_parseable(name, options)
|
115
|
+
p = @context.relative_to(name)
|
116
|
+
if p.nil?
|
117
|
+
# avoid returning nil
|
118
|
+
Hocon::Impl::Parseable.new_not_found(name, "include was not found: '#{name}'", options)
|
119
|
+
else
|
120
|
+
p
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# this function is a little tricky because there are three places we're
|
126
|
+
# trying to use it; for 'include "basename"' in a .conf file, for
|
127
|
+
# loading app.{conf,json,properties} from classpath, and for
|
128
|
+
# loading app.{conf,json,properties} from the filesystem.
|
129
|
+
def self.from_basename(source, name, options)
|
130
|
+
obj = nil
|
131
|
+
if name.end_with?(".conf") || name.end_with?(".json") || name.end_with?(".properties")
|
132
|
+
p = source.name_to_parseable(name, options)
|
133
|
+
|
134
|
+
obj = p.parse(p.options.set_allow_missing(options.allow_missing?))
|
135
|
+
else
|
136
|
+
conf_handle = source.name_to_parseable(name + ".conf", options)
|
137
|
+
json_handle = source.name_to_parseable(name + ".json", options)
|
138
|
+
got_something = false
|
139
|
+
fails = []
|
140
|
+
|
141
|
+
syntax = options.syntax
|
142
|
+
|
143
|
+
obj = SimpleConfigObject.empty(SimpleConfigOrigin.new_simple(name))
|
144
|
+
if syntax.nil? || (syntax == Hocon::ConfigSyntax::CONF)
|
145
|
+
begin
|
146
|
+
obj = conf_handle.parse(conf_handle.options.set_allow_missing(false).
|
147
|
+
set_syntax(Hocon::ConfigSyntax::CONF))
|
148
|
+
got_something = true
|
149
|
+
rescue ConfigIOError => e
|
150
|
+
fails << e
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
if syntax.nil? || (syntax == Hocon::ConfigSyntax::JSON)
|
155
|
+
begin
|
156
|
+
parsed = json_handle.parse(json_handle.options.set_allow_missing(false).
|
157
|
+
set_syntax(Hocon::ConfigSyntax::JSON))
|
158
|
+
obj = obj.with_fallback(parsed)
|
159
|
+
got_something = true
|
160
|
+
rescue ConfigIOError => e
|
161
|
+
fails << e
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# NOTE: skipping the upstream block here that would attempt to parse
|
166
|
+
# a java properties file.
|
167
|
+
|
168
|
+
if (! options.allow_missing?) && (! got_something)
|
169
|
+
if Hocon::Impl::ConfigImpl.trace_loads_enabled
|
170
|
+
# the individual exceptions should have been logged already
|
171
|
+
# with tracing enabled
|
172
|
+
Hocon::Impl::ConfigImpl.trace("Did not find '#{name}'" +
|
173
|
+
" with any extension (.conf, .json, .properties); " +
|
174
|
+
"exceptions should have been logged above.")
|
175
|
+
end
|
176
|
+
|
177
|
+
if fails.empty?
|
178
|
+
# this should not happen
|
179
|
+
raise ConfigBugOrBrokenError, "should not be reached: nothing found but no exceptions thrown"
|
180
|
+
else
|
181
|
+
sb = StringIO.new
|
182
|
+
fails.each do |t|
|
183
|
+
sb << t
|
184
|
+
sb << ", "
|
185
|
+
end
|
186
|
+
raise ConfigIOError.new(SimpleConfigOrigin.new_simple(name), sb.string, fails[0])
|
187
|
+
end
|
188
|
+
elsif !got_something
|
189
|
+
if Hocon::Impl::ConfigImpl.trace_loads_enabled
|
190
|
+
Hocon::Impl::ConfigImpl.trace("Did not find '#{name}'" +
|
191
|
+
" with any extension (.conf, .json, .properties); but '#{name}'" +
|
192
|
+
" is allowed to be missing. Exceptions from load attempts should have been logged above.")
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
obj
|
198
|
+
end
|
199
|
+
|
5
200
|
class Proxy < Hocon::Impl::FullIncluder
|
6
201
|
def initialize(delegate)
|
7
202
|
@delegate = delegate
|
@@ -16,4 +211,4 @@ class Hocon::Impl::SimpleIncluder < Hocon::Impl::FullIncluder
|
|
16
211
|
Proxy.new(includer)
|
17
212
|
end
|
18
213
|
end
|
19
|
-
end
|
214
|
+
end
|