hocon 0.0.7 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|