<commit_before>package ru.circumflex
package core

import java.util.{Date, ResourceBundle, Locale}
import java.text.SimpleDateFormat
import collection.mutable.{HashMap, Map}

/*!# Configuration API

This singleton can be used to retrieve Circumflex configuration parameters
throughout your application.

Configuration parameters are read from `cx.properties` which should be available
in classpath.

You can also configure your application in runtime, just add your configuration
parameters into `Circumflex` using methods of Scala's `Map` interface.
Note, however, that `Circumflex` singleton is not thread-safe, so it is a best
practice to only set configuration parameters inside some initialization block
which will be executed only once by only one thread.

[Circumflex Maven Plugin](http://circumflex.ru/projects/maven-plugin/index.html)
enables you to configure your application at build time using Maven properties
(specified either in application's `pom.xml` or in `settings.xml`) and system
properties (specified in command line). This is very robust production scenario,
because it allows different configurations in different environments without
manual filtering sources and resources.
*/
object Circumflex extends HashMap[String, Any] with UntypedContainer {

  // The configuration object is initialized by reading `cx.properties`.
  try {
    val bundle = ResourceBundle.getBundle(
      "cx", Locale.getDefault, Thread.currentThread.getContextClassLoader)
    val keys = bundle.getKeys
    while (keys.hasMoreElements) {
      val k = keys.nextElement
      this(k) = bundle.getString(k)
    }
  } catch {
    case e: Exception => CX_LOG.error("Could not read configuration parameters from cx.properties.")
  }

  override def stringPrefix = "cx"
}

/*! Several helper methods allow you to obtain parameter precisely in the type you expect:

  * `getAs[T]` returns `Option[T]`;
  * `as[T]` returns `[T]`;
  * `getXXX` returns `XXX` trying to coerce the value to the `XXX` type.

A `ClassCastException` is thrown if the configuration contains the value
with different type than you expect.

Circumflex configuration (and every untyped container) also offers you a convenient
way to configure different implementations of components and services, such as configuring
dialects or connection providers for [Circumflex ORM](http://circumflex.ru/projects/orm/index.html)
or request routers for [Circumflex Web Framework](http://circumflex.ru/projects/web/index.html).<commit_msg>Due to ugly maven-scala-plugin class loading, we now try to get cx.properties using different class loaders.<commit_after>package ru.circumflex
package core

import java.text.SimpleDateFormat
import collection.mutable.{HashMap, Map}
import java.util.{MissingResourceException, Date, ResourceBundle, Locale}

/*!# Configuration API

This singleton can be used to retrieve Circumflex configuration parameters
throughout your application.

Configuration parameters are read from `cx.properties` which should be available
in classpath.

You can also configure your application in runtime, just add your configuration
parameters into `Circumflex` using methods of Scala's `Map` interface.
Note, however, that `Circumflex` singleton is not thread-safe, so it is a best
practice to only set configuration parameters inside some initialization block
which will be executed only once by only one thread.

[Circumflex Maven Plugin](http://circumflex.ru/projects/maven-plugin/index.html)
enables you to configure your application at build time using Maven properties
(specified either in application's `pom.xml` or in `settings.xml`) and system
properties (specified in command line). This is very robust production scenario,
because it allows different configurations in different environments without
manual filtering sources and resources.
*/
object Circumflex extends HashMap[String, Any] with UntypedContainer {

  def locateBundle: Option[ResourceBundle] = try {
    Some(ResourceBundle.getBundle(
      "cx", Locale.getDefault, Thread.currentThread.getContextClassLoader))
  } catch {
    case e: MissingResourceException =>
      CX_LOG.trace("Could not find ResourceBundle for Circumflex configuration" +
          " using thread context class loader.")
      try {
        Some(ResourceBundle.getBundle("cx"))
      } catch {
        case e: MissingResourceException =>
          CX_LOG.error("cx.properties not found in classpath. " +
              "Starting with empty configuration.")
          None
      }
  }

  // The configuration object is initialized by reading `cx.properties`.
  try {
    locateBundle.map { bundle =>
      val keys = bundle.getKeys
      while (keys.hasMoreElements) {
        val k = keys.nextElement
        this(k) = bundle.getString(k)
      }
    }
  } catch {
    case e: Exception =>
      CX_LOG.error("Could not read configuration parameters from cx.properties.", e)
  }

  override def stringPrefix = "cx"
}

/*! Several helper methods allow you to obtain parameter precisely in the type you expect:

  * `getAs[T]` returns `Option[T]`;
  * `as[T]` returns `[T]`;
  * `getXXX` returns `XXX` trying to coerce the value to the `XXX` type.

A `ClassCastException` is thrown if the configuration contains the value
with different type than you expect.

Circumflex configuration (and every untyped container) also offers you a convenient
way to configure different implementations of components and services, such as configuring
dialects or connection providers for [Circumflex ORM](http://circumflex.ru/projects/orm/index.html)
or request routers for [Circumflex Web Framework](http://circumflex.ru/projects/web/index.html).
{'fraction_non_alphanumeric': 0.07611966719773411, 'fraction_numerical': 0.0, 'mean_word_length': 4.401529636711281, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6979001', 'n_tokens_mistral': 1491, 'n_tokens_neox': 1423, 'n_words': 604}