Internal implementation detail, not ABI stable, do not touch. For use only by the {@link com.typesafe.config} package. The point of this class is to avoid “propagating” each overload on “thing which can be parsed” through multiple interfaces. Most interfaces can have just one overload that takes a Parseable. Also it's used as an abstract “resource handle” in the ConfigIncluder interface.
# File lib/hocon/impl/parseable.rb, line 121 def self.force_parsed_to_object(value) if value.is_a? Hocon::Impl::AbstractConfigObject value else raise Hocon::ConfigError::ConfigWrongTypeError.with_expected_actual(value.origin, "", "object at file root", Hocon::ConfigValueType.value_type_name(value.value_type)) end end
# File lib/hocon/impl/parseable.rb, line 44 def initialize end
# File lib/hocon/impl/parseable.rb, line 463 def self.new_file(file_path, options) ParseableFile.new(file_path, options) end
# File lib/hocon/impl/parseable.rb, line 347 def self.new_not_found(what_not_found, message, options) ParseableNotFound.new(what_not_found, message, options) end
# File lib/hocon/impl/parseable.rb, line 543 def self.new_resources(resource, options) ParseableResources.new(resource, options) end
# File lib/hocon/impl/parseable.rb, line 389 def self.new_string(string, options) ParseableString.new(string, options) end
NOTE: skipping `relativeTo(URL, String)` because we're not supporting URLs for now
# File lib/hocon/impl/parseable.rb, line 312 def self.relative_to(file, filename) child = Pathname.new(filename) file = Pathname.new(file) if child.absolute? nil end parent = file.parent if parent.nil? nil else File.join(parent, filename) end end
# File lib/hocon/impl/parseable.rb, line 298 def self.syntax_from_extension(name) if name.end_with?(".json") Hocon::ConfigSyntax::JSON elsif name.end_with?(".conf") Hocon::ConfigSyntax::CONF else # Skipping PROPERTIES because we can't really support that in ruby nil end end
# File lib/hocon/impl/parseable.rb, line 91 def self.trace(message) if Hocon::Impl::ConfigImpl.trace_loads_enabled Hocon::Impl::ConfigImpl.trace(message) end end
# File lib/hocon/impl/parseable.rb, line 101 def content_type nil end
# File lib/hocon/impl/parseable.rb, line 286 def create_origin raise Hocon::ConfigError::ConfigBugOrBrokenError, "subclasses of `Parseable` must implement `create_origin` (#{self.class})" end
the general idea is that any work should be in here, not in the constructor, so that exceptions are thrown from the public parse() function and not from the creation of the Parseable. Essentially this is a lazy field. The parser should close the reader when it's done with it.
{//}# ALSO, IMPORTANT: if the file or URL is not found, this must throw. {//}# to support the “allow missing” feature.
# File lib/hocon/impl/parseable.rb, line 83 def custom_reader raise Hocon::ConfigError::ConfigBugOrBrokenError, "subclasses of `Parseable` must implement `custom_reader` (#{self.class})" end
# File lib/hocon/impl/parseable.rb, line 48 def fixup_options(base_options) syntax = base_options.syntax if !syntax syntax = guess_syntax end if !syntax syntax = Hocon::ConfigSyntax::CONF end modified = base_options.set_syntax(syntax) # make sure the app-provided includer falls back to default modified = modified.append_includer(Hocon::Impl::ConfigImpl.default_includer) # make sure the app-provided includer is complete modified = modified.set_includer(Hocon::Impl::SimpleIncluder.make_full(modified.includer)) modified end
# File lib/hocon/impl/parseable.rb, line 97 def guess_syntax nil end
# File lib/hocon/impl/parseable.rb, line 117 def include_context @include_context end
# File lib/hocon/impl/parseable.rb, line 290 def options @initial_options end
# File lib/hocon/impl/parseable.rb, line 282 def origin @initial_origin end
# File lib/hocon/impl/parseable.rb, line 132 def parse(base_options = nil) if (base_options.nil?) base_options = options end stack = @@parse_stack if stack.length >= MAX_INCLUDE_DEPTH raise Hocon::ConfigError::ConfigParseError.new(@initial_origin, "include statements nested more than #{MAX_INCLUDE_DEPTH} times, " + "you probably have a cycle in your includes. Trace: #{stack}", nil) end # Push into beginning of stack stack.unshift(self) begin self.class.force_parsed_to_object(parse_value(base_options)) ensure # Pop from beginning of stack stack.shift end end
# File lib/hocon/impl/parseable.rb, line 278 def parse_config_document parse_document(options) end
# File lib/hocon/impl/parseable.rb, line 188 def parse_document(base_options = nil) if base_options.nil? base_options = options end # note that we are NOT using our "initialOptions", # but using the ones from the passed-in options. The idea is that # callers can get our original options and then parse with different # ones if they want. options = fixup_options(base_options) # passed-in option can override origin origin = nil if ! options.origin_description.nil? origin = Hocon::Impl::SimpleConfigOrigin.new_simple(options.origin_description) else origin = @initial_origin end parse_document_from_origin(origin, options) end
# File lib/hocon/impl/parseable.rb, line 209 def parse_document_from_origin(origin, final_options) begin raw_parse_document(origin, final_options) rescue IOError => e if final_options.allow_missing? Hocon::Impl::SimpleConfigDocument.new( Hocon::Impl::ConfigNodeObject.new([]), final_options) else self.class.trace("exception loading #{origin.description}: #{e.class}: #{e.message}") raise ConfigIOError.new(origin, "#{e.class.name}: #{e.message}", e) end end end
# File lib/hocon/impl/parseable.rb, line 154 def parse_value(base_options = nil) if base_options.nil? base_options = options end # note that we are NOT using our "initialOptions", # but using the ones from the passed-in options. The idea is that # callers can get our original options and then parse with different # ones if they want. options = fixup_options(base_options) # passed-in options can override origin origin = if options.origin_description Hocon::Impl::SimpleConfigOrigin.new_simple(options.origin_description) else @initial_origin end parse_value_from_origin(origin, options) end
# File lib/hocon/impl/parseable.rb, line 175 def parse_value_from_origin(origin, final_options) begin raw_parse_value(origin, final_options) rescue IOError => e if final_options.allow_missing? Hocon::Impl::SimpleConfigObject.empty_missing(origin) else self.class.trace("exception loading #{origin.description}: #{e.class}: #{e.message}") raise Hocon::ConfigError::ConfigIOError.new(origin, "#{e.class.name}: #{e.message}", e) end end end
# File lib/hocon/impl/parseable.rb, line 66 def post_construct(base_options) @initial_options = fixup_options(base_options) @include_context = Hocon::Impl::SimpleIncludeContext.new(self) if @initial_options.origin_description @initial_origin = Hocon::Impl::SimpleConfigOrigin.new_simple(@initial_options.origin_description) else @initial_origin = create_origin end end
# File lib/hocon/impl/parseable.rb, line 252 def raw_parse_document(origin, final_options) reader = reader(final_options) content_type = content_type() options_with_content_type = nil if !(content_type.nil?) if Hocon::Impl::ConfigImpl.trace_loads_enabled && (! final_options.get_syntax.nil?) self.class.trace("Overriding syntax #{final_options.get_syntax} with Content-Type which specified #{content-type}") end options_with_content_type = final_options.set_syntax(content_type) else options_with_content_type = final_options end reader.open { |io| raw_parse_document_from_io(io, origin, options_with_content_type) } end
# File lib/hocon/impl/parseable.rb, line 271 def raw_parse_document_from_io(reader, origin, final_options) tokens = Hocon::Impl::Tokenizer.tokenize(origin, reader, final_options.syntax) Hocon::Impl::SimpleConfigDocument.new( Hocon::Impl::ConfigDocumentParser.parse(tokens, origin, final_options), final_options) end
this is parseValue without post-processing the IOException or handling options.getAllowMissing()
# File lib/hocon/impl/parseable.rb, line 225 def raw_parse_value(origin, final_options) reader = reader(final_options) # after reader() we will have loaded the Content-Type content_type = content_type() options_with_content_type = nil if !(content_type.nil?) if Hocon::Impl::ConfigImpl.trace_loads_enabled && (! final_options.get_syntax.nil?) self.class.trace("Overriding syntax #{final_options.get_syntax} with Content-Type which specified #{content-type}") end options_with_content_type = final_options.set_syntax(content_type) else options_with_content_type = final_options end reader.open { |io| raw_parse_value_from_io(io, origin, options_with_content_type) } end
# File lib/hocon/impl/parseable.rb, line 246 def raw_parse_value_from_io(io, origin, final_options) tokens = Hocon::Impl::Tokenizer.tokenize(origin, io, final_options.syntax) document = Hocon::Impl::ConfigDocumentParser.parse(tokens, origin, final_options) Hocon::Impl::ConfigParser.parse(document, origin, final_options, include_context) end
# File lib/hocon/impl/parseable.rb, line 87 def reader(options) custom_reader end
# File lib/hocon/impl/parseable.rb, line 105 def relative_to(filename) # fall back to classpath; we treat the "filename" as absolute # (don't add a package name in front), # if it starts with "/" then remove the "/", for consistency # with ParseableResources.relativeTo resource = filename if filename.start_with?("/") resource = filename.slice(1) end self.class.new_resources(resource, options.set_origin_description(nil)) end
# File lib/hocon/impl/parseable.rb, line 294 def to_s self.class.name.split('::').last end