class Hocon::Impl::Parseable

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.

Constants

MAX_INCLUDE_DEPTH

Public Class Methods

force_parsed_to_object(value) click to toggle source
# File lib/hocon/impl/parseable.rb, line 123
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
new() click to toggle source
# File lib/hocon/impl/parseable.rb, line 46
def initialize

end
new_file(file_path, options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 465
def self.new_file(file_path, options)
  ParseableFile.new(file_path, options)
end
new_not_found(what_not_found, message, options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 349
def self.new_not_found(what_not_found, message, options)
  ParseableNotFound.new(what_not_found, message, options)
end
new_resources(resource, options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 545
def self.new_resources(resource, options)
  ParseableResources.new(resource, options)
end
new_string(string, options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 391
def self.new_string(string, options)
  ParseableString.new(string, options)
end
parse_stack() click to toggle source

The upstream library seems to use this as a global way of keeping track of how many files have been included, to avoid cycles

# File lib/hocon/impl/parseable.rb, line 40
def self.parse_stack
  Thread.current[:hocon_parse_stack] ||= []
end
relative_to(file, filename) click to toggle source

NOTE: skipping ‘relativeTo(URL, String)` because we’re not supporting URLs for now

# File lib/hocon/impl/parseable.rb, line 314
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
syntax_from_extension(name) click to toggle source
# File lib/hocon/impl/parseable.rb, line 300
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
trace(message) click to toggle source
# File lib/hocon/impl/parseable.rb, line 93
def self.trace(message)
  if Hocon::Impl::ConfigImpl.trace_loads_enabled
    Hocon::Impl::ConfigImpl.trace(message)
  end
end

Public Instance Methods

content_type() click to toggle source
# File lib/hocon/impl/parseable.rb, line 103
def content_type
  nil
end
create_origin() click to toggle source
# File lib/hocon/impl/parseable.rb, line 288
def create_origin
  raise Hocon::ConfigError::ConfigBugOrBrokenError, "subclasses of `Parseable` must implement `create_origin` (#{self.class})"
end
custom_reader() click to toggle source
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 85
def custom_reader
  raise Hocon::ConfigError::ConfigBugOrBrokenError, "subclasses of `Parseable` must implement `custom_reader` (#{self.class})"
end
fixup_options(base_options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 50
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
guess_syntax() click to toggle source
# File lib/hocon/impl/parseable.rb, line 99
def guess_syntax
  nil
end
include_context() click to toggle source
# File lib/hocon/impl/parseable.rb, line 119
def include_context
  @include_context
end
options() click to toggle source
# File lib/hocon/impl/parseable.rb, line 292
def options
  @initial_options
end
origin() click to toggle source
# File lib/hocon/impl/parseable.rb, line 284
def origin
  @initial_origin
end
parse(base_options = nil) click to toggle source
# File lib/hocon/impl/parseable.rb, line 134
def parse(base_options = nil)
  if (base_options.nil?)
    base_options = options
  end
  stack = self.class.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
parse_config_document() click to toggle source
# File lib/hocon/impl/parseable.rb, line 280
def parse_config_document
  parse_document(options)
end
parse_document(base_options = nil) click to toggle source
# File lib/hocon/impl/parseable.rb, line 190
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
parse_document_from_origin(origin, final_options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 211
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
parse_value(base_options = nil) click to toggle source
# File lib/hocon/impl/parseable.rb, line 156
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
parse_value_from_origin(origin, final_options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 177
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
post_construct(base_options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 68
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
raw_parse_document(origin, final_options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 254
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
raw_parse_document_from_io(reader, origin, final_options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 273
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
raw_parse_value(origin, final_options) click to toggle source

this is parseValue without post-processing the IOException or handling options.getAllowMissing()

# File lib/hocon/impl/parseable.rb, line 227
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
raw_parse_value_from_io(io, origin, final_options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 248
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
reader(options) click to toggle source
# File lib/hocon/impl/parseable.rb, line 89
def reader(options)
  custom_reader
end
relative_to(filename) click to toggle source
# File lib/hocon/impl/parseable.rb, line 107
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
to_s() click to toggle source
# File lib/hocon/impl/parseable.rb, line 296
def to_s
  self.class.name.split('::').last
end