1// Copyright 2017 Frank Schroeder. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Package properties provides functions for reading and writing 6// ISO-8859-1 and UTF-8 encoded .properties files and has 7// support for recursive property expansion. 8// 9// Java properties files are ISO-8859-1 encoded and use Unicode 10// literals for characters outside the ISO character set. Unicode 11// literals can be used in UTF-8 encoded properties files but 12// aren't necessary. 13// 14// To load a single properties file use MustLoadFile(): 15// 16// p := properties.MustLoadFile(filename, properties.UTF8) 17// 18// To load multiple properties files use MustLoadFiles() 19// which loads the files in the given order and merges the 20// result. Missing properties files can be ignored if the 21// 'ignoreMissing' flag is set to true. 22// 23// Filenames can contain environment variables which are expanded 24// before loading. 25// 26// f1 := "/etc/myapp/myapp.conf" 27// f2 := "/home/${USER}/myapp.conf" 28// p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true) 29// 30// All of the different key/value delimiters ' ', ':' and '=' are 31// supported as well as the comment characters '!' and '#' and 32// multi-line values. 33// 34// ! this is a comment 35// # and so is this 36// 37// # the following expressions are equal 38// key value 39// key=value 40// key:value 41// key = value 42// key : value 43// key = val\ 44// ue 45// 46// Properties stores all comments preceding a key and provides 47// GetComments() and SetComments() methods to retrieve and 48// update them. The convenience functions GetComment() and 49// SetComment() allow access to the last comment. The 50// WriteComment() method writes properties files including 51// the comments and with the keys in the original order. 52// This can be used for sanitizing properties files. 53// 54// Property expansion is recursive and circular references 55// and malformed expressions are not allowed and cause an 56// error. Expansion of environment variables is supported. 57// 58// # standard property 59// key = value 60// 61// # property expansion: key2 = value 62// key2 = ${key} 63// 64// # recursive expansion: key3 = value 65// key3 = ${key2} 66// 67// # circular reference (error) 68// key = ${key} 69// 70// # malformed expression (error) 71// key = ${ke 72// 73// # refers to the users' home dir 74// home = ${HOME} 75// 76// # local key takes precendence over env var: u = foo 77// USER = foo 78// u = ${USER} 79// 80// The default property expansion format is ${key} but can be 81// changed by setting different pre- and postfix values on the 82// Properties object. 83// 84// p := properties.NewProperties() 85// p.Prefix = "#[" 86// p.Postfix = "]#" 87// 88// Properties provides convenience functions for getting typed 89// values with default values if the key does not exist or the 90// type conversion failed. 91// 92// # Returns true if the value is either "1", "on", "yes" or "true" 93// # Returns false for every other value and the default value if 94// # the key does not exist. 95// v = p.GetBool("key", false) 96// 97// # Returns the value if the key exists and the format conversion 98// # was successful. Otherwise, the default value is returned. 99// v = p.GetInt64("key", 999) 100// v = p.GetUint64("key", 999) 101// v = p.GetFloat64("key", 123.0) 102// v = p.GetString("key", "def") 103// v = p.GetDuration("key", 999) 104// 105// As an alterantive properties may be applied with the standard 106// library's flag implementation at any time. 107// 108// # Standard configuration 109// v = flag.Int("key", 999, "help message") 110// flag.Parse() 111// 112// # Merge p into the flag set 113// p.MustFlag(flag.CommandLine) 114// 115// Properties provides several MustXXX() convenience functions 116// which will terminate the app if an error occurs. The behavior 117// of the failure is configurable and the default is to call 118// log.Fatal(err). To have the MustXXX() functions panic instead 119// of logging the error set a different ErrorHandler before 120// you use the Properties package. 121// 122// properties.ErrorHandler = properties.PanicHandler 123// 124// # Will panic instead of logging an error 125// p := properties.MustLoadFile("config.properties") 126// 127// You can also provide your own ErrorHandler function. The only requirement 128// is that the error handler function must exit after handling the error. 129// 130// properties.ErrorHandler = func(err error) { 131// fmt.Println(err) 132// os.Exit(1) 133// } 134// 135// # Will write to stdout and then exit 136// p := properties.MustLoadFile("config.properties") 137// 138// Properties can also be loaded into a struct via the `Decode` 139// method, e.g. 140// 141// type S struct { 142// A string `properties:"a,default=foo"` 143// D time.Duration `properties:"timeout,default=5s"` 144// E time.Time `properties:"expires,layout=2006-01-02,default=2015-01-01"` 145// } 146// 147// See `Decode()` method for the full documentation. 148// 149// The following documents provide a description of the properties 150// file format. 151// 152// http://en.wikipedia.org/wiki/.properties 153// 154// http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29 155// 156package properties 157