Skip to content

Instantly share code, notes, and snippets.

@ktprezes
Created January 14, 2023 20:45
Show Gist options
  • Save ktprezes/c295f374328948d0af2630583499eca4 to your computer and use it in GitHub Desktop.
Save ktprezes/c295f374328948d0af2630583499eca4 to your computer and use it in GitHub Desktop.
Kotlin - reading resource bundle from the XML file(s) instead of '.properties' file(s)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>default locales related file</comment>
<entry key="app_name">My App</entry>
<entry key="prop1">Example 1</entry>
</properties>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>polish locales related file</comment>
<entry key="app_name">Moja apka</entry>
<entry key="prop1">Przykład 1</entry>
</properties>
import utils.XMLResourceBundle
import utils.XMLResourceBundleControl
import java.util.*
fun main() {
val resBndl1 = ResourceBundle.getBundle("props", Locale.forLanguageTag("pl"), XMLResourceBundleControl())
println(resBndl1.getString("app_name") // prints: "Moja apka"
val resBndl2 = XMLResourceBundle.getBundle("props") // gets default Locale
println(resBndl2.getString("prop1") // prints: "Example 1"
} // fun main()
package utils
import java.io.InputStream
import java.util.*
// see also:
// https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/util/ResourceBundle.Control.html
// https://gist.github.com/asicfr/1b76ea60029264d7be15d019a866e1a4
/**
* Represents ResourceBundle read from the XML file instead of the '.properties' file
*/
class XMLResourceBundle(stream: InputStream?) : ResourceBundle() {
private val props: Properties = Properties()
private val selfKeys: Set<String>
get() = props.keys.map { it.toString() }.toSet()
init { props.loadFromXML(stream) }
public override fun handleKeySet(): Set<String> = selfKeys
// implementation of abstract methods of the parent class ResourceBundle
override fun handleGetObject(key: String): Any? = props.getProperty(key)
override fun getKeys(): Enumeration<String> =
Collections.enumeration(selfKeys union if (parent != null) parent.keySet() else emptySet())
companion object {
fun getBundle(
baseName: String,
locale: Locale = Locale.getDefault(),
loader: ClassLoader? = null
): XMLResourceBundle = (
if (loader == null)
ResourceBundle.getBundle(baseName, locale, XMLResourceBundleControl())
else
ResourceBundle.getBundle(baseName, locale, loader, XMLResourceBundleControl())
) as XMLResourceBundle
} // companion object
} // class XMLResourceBundle(stream:InputStream?)
package utils
import java.io.BufferedInputStream
import java.io.IOException
import java.util.*
// see also:
// https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/util/ResourceBundle.Control.html
// https://gist.github.com/asicfr/1b76ea60029264d7be15d019a866e1a4
class XMLResourceBundleControl : ResourceBundle.Control() {
@Throws(IllegalAccessException::class, InstantiationException::class, IOException::class)
override fun newBundle(
baseName: String?,
locale: Locale?,
format: String?,
loader: ClassLoader?,
reload: Boolean
): ResourceBundle? {
require(!(baseName == null || locale == null || format == null || loader == null)) {
"baseName, locale, format and loader cannot be all null"
}
require(format == XML) { "format must be xml" }
val bundleName: String = toBundleName(baseName, locale)
val resourceName = toResourceName(bundleName, format)
val url = loader.getResource(resourceName) ?: return null
val urlConn = url.openConnection() ?: return null
if (reload) { urlConn.useCaches = false }
return urlConn.getInputStream()?.use { stream -> BufferedInputStream(stream).use (::XMLResourceBundle) }
} // override fun newBundle(...): ResourceBundle?
override fun getFormats(baseName: String?): List<String> = SINGLETON_LIST
companion object {
private const val XML = "xml"
private val SINGLETON_LIST = listOf(XML)
}
} // class XMLResourceBundleControl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment