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 120 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", value.value_type.name) end end
# File lib/hocon/impl/parseable.rb, line 43 def initialize end
# File lib/hocon/impl/parseable.rb, line 462 def self.new_file(file_path, options) ParseableFile.new(file_path, options) end
# File lib/hocon/impl/parseable.rb, line 346 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 542 def self.new_resources(resource, options) ParseableResources.new(resource, options) end
# File lib/hocon/impl/parseable.rb, line 388 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 311 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 297 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 90 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 100 def content_type nil end
# File lib/hocon/impl/parseable.rb, line 285 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 82 def custom_reader raise Hocon::ConfigError::ConfigBugOrBrokenError, "subclasses of `Parseable` must implement `custom_reader` (#{self.class})" end
# File lib/hocon/impl/parseable.rb, line 47 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 96 def guess_syntax nil end
# File lib/hocon/impl/parseable.rb, line 116 def include_context @include_context end
# File lib/hocon/impl/parseable.rb, line 289 def options @initial_options end
# File lib/hocon/impl/parseable.rb, line 281 def origin @initial_origin end
# File lib/hocon/impl/parseable.rb, line 131 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 277 def parse_config_document parse_document(options) end
# File lib/hocon/impl/parseable.rb, line 187 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 208 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 153 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 174 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 65 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 251 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 270 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 224 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 245 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 86 def reader(options) custom_reader end
# File lib/hocon/impl/parseable.rb, line 104 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 293 def to_s self.class.name.split('::').last end