properties

package
v1.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 13, 2015 License: MIT, BSD-2-Clause Imports: 12 Imported by: 0

README

Overview Build Status

properties is a Go library for reading and writing properties files.

It supports reading from multiple files and Spring style recursive property expansion of expressions like ${key} to their corresponding value. Value expressions can refer to other keys like in ${key} or to environment variables like in ${USER}. Filenames can also contain environment variables like in /home/${USER}/myapp.properties.

Comments and the order of keys are preserved. Comments can be modified and can be written to the output.

The properties library supports both ISO-8859-1 and UTF-8 encoded data.

Starting from version 1.3.0 the behavior of the MustXXX() functions is configurable by providing a custom ErrorHandler function. The default has changed from panic to log.Fatal but this is configurable and custom error handling functions can be provided. See the package documentation for details.

Getting Started

import "github.com/magiconair/properties"

func main() {
	p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8)
	host := p.MustGetString("host")
	port := p.GetInt("port", 8080)
}

Read the full documentation on GoDoc GoDoc

Installation and Upgrade

$ go get -u github.com/magiconair/properties

For testing and debugging you need the go-check library

$ go get -u gopkg.in/check.v1

History

v1.5.5, 31 Jul 2015

v1.5.4, 23 Jun 2015

  • Issue #5: Allow disabling of property expansion DisableExpansion. When property expansion is disabled Properties become a simple key/value store and don't check for circular references.

v1.5.3, 02 Jun 2015

v1.5.2, 10 Apr 2015

v1.5.1, 08 Dec 2014

v1.5.0, 18 Nov 2014

  • Added support for single and multi-line comments (reading, writing and updating)
  • The order of keys is now preserved
  • Calling Set() with an empty key now silently ignores the call and does not create a new entry
  • Added a MustSet() method
  • Migrated test library from launchpad.net/gocheck to gopkg.in/check.v1

v1.4.2, 15 Nov 2014

  • Issue #2: Fixed goroutine leak in parser which created two lexers but cleaned up only one

v1.4.1, 13 Nov 2014

  • Issue #1: Fixed bug in Keys() method which returned an empty string

v1.4.0, 23 Sep 2014

v1.3.0, 18 Mar 2014

  • Added support for time.Duration
  • Made MustXXX() failure behavior configurable (log.Fatal, panic, custom)
  • Changed default of MustXXX() failure from panic to log.Fatal

v1.2.0, 05 Mar 2014

  • Added MustGet... functions
  • Added support for int and uint with range checks on 32 bit platforms

v1.1.0, 20 Jan 2014

  • Renamed from goproperties to properties
  • Added support for expansion of environment vars in filenames and value expressions
  • Fixed bug where value expressions were not at the start of the string

v1.0.0, 7 Jan 2014

  • Initial release

License

2 clause BSD license. See LICENSE file for details.

ToDo

  • Dump contents with passwords and secrets obscured

Documentation

Overview

Package properties provides functions for reading and writing ISO-8859-1 and UTF-8 encoded .properties files and has support for recursive property expansion.

Java properties files are ISO-8859-1 encoded and use Unicode literals for characters outside the ISO character set. Unicode literals can be used in UTF-8 encoded properties files but aren't necessary.

To load a single properties file use MustLoadFile():

p := properties.MustLoadFile(filename, properties.UTF8)

To load multiple properties files use MustLoadFiles() which loads the files in the given order and merges the result. Missing properties files can be ignored if the 'ignoreMissing' flag is set to true.

Filenames can contain environment variables which are expanded before loading.

f1 := "/etc/myapp/myapp.conf"
f2 := "/home/${USER}/myapp.conf"
p := MustLoadFiles([]string{f1, f2}, properties.UTF8, true)

All of the different key/value delimiters ' ', ':' and '=' are supported as well as the comment characters '!' and '#' and multi-line values.

! this is a comment
# and so is this

# the following expressions are equal
key value
key=value
key:value
key = value
key : value
key = val\
      ue

Properties stores all comments preceding a key and provides GetComments() and SetComments() methods to retrieve and update them. The convenience functions GetComment() and SetComment() allow access to the last comment. The WriteComment() method writes properties files including the comments and with the keys in the original order. This can be used for sanitizing properties files.

Property expansion is recursive and circular references and malformed expressions are not allowed and cause an error. Expansion of environment variables is supported.

# standard property
key = value

# property expansion: key2 = value
key2 = ${key}

# recursive expansion: key3 = value
key3 = ${key2}

# circular reference (error)
key = ${key}

# malformed expression (error)
key = ${ke

# refers to the users' home dir
home = ${HOME}

# local key takes precendence over env var: u = foo
USER = foo
u = ${USER}

The default property expansion format is ${key} but can be changed by setting different pre- and postfix values on the Properties object.

p := properties.NewProperties()
p.Prefix = "#["
p.Postfix = "]#"

Properties provides convenience functions for getting typed values with default values if the key does not exist or the type conversion failed.

# Returns true if the value is either "1", "on", "yes" or "true"
# Returns false for every other value and the default value if
# the key does not exist.
v = p.GetBool("key", false)

# Returns the value if the key exists and the format conversion
# was successful. Otherwise, the default value is returned.
v = p.GetInt64("key", 999)
v = p.GetUint64("key", 999)
v = p.GetFloat64("key", 123.0)
v = p.GetString("key", "def")
v = p.GetDuration("key", 999)

Properties provides several MustXXX() convenience functions which will terminate the app if an error occurs. The behavior of the failure is configurable and the default is to call log.Fatal(err). To have the MustXXX() functions panic instead of logging the error set a different ErrorHandler before you use the Properties package.

properties.ErrorHandler = properties.PanicHandler

# Will panic instead of logging an error
p := properties.MustLoadFile("config.properties")

You can also provide your own ErrorHandler function. The only requirement is that the error handler function must exit after handling the error.

  properties.ErrorHandler = func(err error) {
	     fmt.Println(err)
      os.Exit(1)
  }

  # Will write to stdout and then exit
  p := properties.MustLoadFile("config.properties")

The following documents provide a description of the properties file format.

http://en.wikipedia.org/wiki/.properties

http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29

Example
// Decode some key/value pairs with expressions
p, err := Load([]byte("key=value\nkey2=${key}"), ISO_8859_1)
if err != nil {
	log.Fatal(err)
}

// Get a valid key
if v, ok := p.Get("key"); ok {
	fmt.Println(v)
}

// Get an invalid key
if _, ok := p.Get("does not exist"); !ok {
	fmt.Println("invalid key")
}

// Get a key with a default value
v := p.GetString("does not exist", "some value")
fmt.Println(v)

// Dump the expanded key/value pairs of the Properties
fmt.Println("Expanded key/value pairs")
fmt.Println(p)
Output:

value
invalid key
some value
Expanded key/value pairs
key = value
key2 = value

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrorHandler = LogFatalHandler

ErrorHandler is the function which handles failures of the MustXXX() functions. The default is LogFatalHandler.

Functions

func LogFatalHandler

func LogFatalHandler(err error)

LogFatalHandler handles the error by logging a fatal error and exiting.

func PanicHandler

func PanicHandler(err error)

PanicHandler handles the error by panicking.

Types

type Encoding

type Encoding uint

Encoding specifies encoding of the input data.

const (
	// UTF8 interprets the input data as UTF-8.
	UTF8 Encoding = 1 << iota

	// ISO_8859_1 interprets the input data as ISO-8859-1.
	ISO_8859_1
)

type ErrorHandlerFunc

type ErrorHandlerFunc func(error)

ErrorHandlerFunc defines the type of function which handles failures of the MustXXX() functions. An error handler function must exit the application after handling the error.

type Properties

type Properties struct {
	// Pre-/Postfix for property expansion.
	Prefix  string
	Postfix string

	// DisableExpansion controls the expansion of properties on Get()
	// and the check for circular references on Set(). When set to
	// true Properties behaves like a simple key/value store and does
	// not check for circular references on Get() or on Set().
	DisableExpansion bool
	// contains filtered or unexported fields
}

A Properties contains the key/value pairs from the properties input. All values are stored in unexpanded form and are expanded at runtime

func Load

func Load(buf []byte, enc Encoding) (*Properties, error)

Load reads a buffer into a Properties struct.

Example (Iso88591)
buf := []byte("key = ISO-8859-1 value with unicode literal \\u2318 and umlaut \xE4") // 0xE4 == ä
p, _ := Load(buf, ISO_8859_1)
v, ok := p.Get("key")
fmt.Println(ok)
fmt.Println(v)
Output:

true
ISO-8859-1 value with unicode literal ⌘ and umlaut ä
Example (Utf8)
p, _ := Load([]byte("key = UTF-8 value with unicode character ⌘ and umlaut ä"), UTF8)
v, ok := p.Get("key")
fmt.Println(ok)
fmt.Println(v)
Output:

true
UTF-8 value with unicode character ⌘ and umlaut ä

func LoadFile

func LoadFile(filename string, enc Encoding) (*Properties, error)

LoadFile reads a file into a Properties struct.

func LoadFiles

func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error)

LoadFiles reads multiple files in the given order into a Properties struct. If 'ignoreMissing' is true then non-existent files will not be reported as error.

func MustLoadFile

func MustLoadFile(filename string, enc Encoding) *Properties

MustLoadFile reads a file into a Properties struct and panics on error.

func MustLoadFiles

func MustLoadFiles(filenames []string, enc Encoding, ignoreMissing bool) *Properties

MustLoadFiles reads multiple files in the given order into a Properties struct and panics on error. If 'ignoreMissing' is true then non-existent files will not be reported as error.

func NewProperties

func NewProperties() *Properties

NewProperties creates a new Properties struct with the default configuration for "${key}" expressions.

func (*Properties) ClearComments

func (p *Properties) ClearComments()

ClearComments removes the comments for all keys.

func (*Properties) Delete

func (p *Properties) Delete(key string)

Delete removes the key and its comments.

func (*Properties) Filter

func (p *Properties) Filter(pattern string) (*Properties, error)

Filter returns a new properties object which contains all properties for which the key matches the pattern.

func (*Properties) FilterPrefix

func (p *Properties) FilterPrefix(prefix string) *Properties

FilterPrefix returns a new properties object which contains all properties for which the key starts with the prefix.

func (*Properties) FilterRegexp

func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties

FilterRegexp returns a new properties object which contains all properties for which the key matches the regular expression.

func (*Properties) Get

func (p *Properties) Get(key string) (value string, ok bool)

Get returns the expanded value for the given key if exists. Otherwise, ok is false.

func (*Properties) GetBool

func (p *Properties) GetBool(key string, def bool) bool

GetBool checks if the expanded value is one of '1', 'yes', 'true' or 'on' if the key exists. The comparison is case-insensitive. If the key does not exist the default value is returned.

Example
var input = `
	key=1
	key2=On
	key3=YES
	key4=true`
p, _ := Load([]byte(input), ISO_8859_1)
fmt.Println(p.GetBool("key", false))
fmt.Println(p.GetBool("key2", false))
fmt.Println(p.GetBool("key3", false))
fmt.Println(p.GetBool("key4", false))
fmt.Println(p.GetBool("keyX", false))
Output:

true
true
true
true
false

func (*Properties) GetComment

func (p *Properties) GetComment(key string) string

GetComment returns the last comment before the given key or an empty string.

func (*Properties) GetComments

func (p *Properties) GetComments(key string) []string

GetComments returns all comments that appeared before the given key or nil.

func (*Properties) GetDuration

func (p *Properties) GetDuration(key string, def time.Duration) time.Duration

GetDuration parses the expanded value as an time.Duration (in ns) if the key exists. If key does not exist or the value cannot be parsed the default value is returned. In almost all cases you want to use GetParsedDuration().

func (*Properties) GetFloat64

func (p *Properties) GetFloat64(key string, def float64) float64

GetFloat64 parses the expanded value as a float64 if the key exists. If key does not exist or the value cannot be parsed the default value is returned.

func (*Properties) GetInt

func (p *Properties) GetInt(key string, def int) int

GetInt parses the expanded value as an int if the key exists. If key does not exist or the value cannot be parsed the default value is returned. If the value does not fit into an int the function panics with an out of range error.

func (*Properties) GetInt64

func (p *Properties) GetInt64(key string, def int64) int64

GetInt64 parses the expanded value as an int64 if the key exists. If key does not exist or the value cannot be parsed the default value is returned.

func (*Properties) GetParsedDuration

func (p *Properties) GetParsedDuration(key string, def time.Duration) time.Duration

GetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. If key does not exist or the value cannot be parsed the default value is returned.

func (*Properties) GetString

func (p *Properties) GetString(key, def string) string

GetString returns the expanded value for the given key if exists or the default value otherwise.

Example
p, _ := Load([]byte("key=value"), ISO_8859_1)
v := p.GetString("another key", "default value")
fmt.Println(v)
Output:

default value

func (*Properties) GetUint

func (p *Properties) GetUint(key string, def uint) uint

GetUint parses the expanded value as an uint if the key exists. If key does not exist or the value cannot be parsed the default value is returned. If the value does not fit into an int the function panics with an out of range error.

func (*Properties) GetUint64

func (p *Properties) GetUint64(key string, def uint64) uint64

GetUint64 parses the expanded value as an uint64 if the key exists. If key does not exist or the value cannot be parsed the default value is returned.

func (*Properties) Keys

func (p *Properties) Keys() []string

Keys returns all keys in the same order as in the input.

func (*Properties) Len

func (p *Properties) Len() int

Len returns the number of keys.

func (*Properties) MustGet

func (p *Properties) MustGet(key string) string

MustGet returns the expanded value for the given key if exists. Otherwise, it panics.

func (*Properties) MustGetBool

func (p *Properties) MustGetBool(key string) bool

MustGetBool checks if the expanded value is one of '1', 'yes', 'true' or 'on' if the key exists. The comparison is case-insensitive. If the key does not exist the function panics.

func (*Properties) MustGetDuration

func (p *Properties) MustGetDuration(key string) time.Duration

MustGetDuration parses the expanded value as an time.Duration (in ns) if the key exists. If key does not exist or the value cannot be parsed the function panics. In almost all cases you want to use MustGetParsedDuration().

func (*Properties) MustGetFloat64

func (p *Properties) MustGetFloat64(key string) float64

MustGetFloat64 parses the expanded value as a float64 if the key exists. If key does not exist or the value cannot be parsed the function panics.

func (*Properties) MustGetInt

func (p *Properties) MustGetInt(key string) int

MustGetInt parses the expanded value as an int if the key exists. If key does not exist or the value cannot be parsed the function panics. If the value does not fit into an int the function panics with an out of range error.

func (*Properties) MustGetInt64

func (p *Properties) MustGetInt64(key string) int64

MustGetInt64 parses the expanded value as an int if the key exists. If key does not exist or the value cannot be parsed the function panics.

func (*Properties) MustGetParsedDuration

func (p *Properties) MustGetParsedDuration(key string) time.Duration

MustGetParsedDuration parses the expanded value with time.ParseDuration() if the key exists. If key does not exist or the value cannot be parsed the function panics.

func (*Properties) MustGetString

func (p *Properties) MustGetString(key string) string

MustGetString returns the expanded value for the given key if exists or panics otherwise.

func (*Properties) MustGetUint

func (p *Properties) MustGetUint(key string) uint

MustGetUint parses the expanded value as an int if the key exists. If key does not exist or the value cannot be parsed the function panics. If the value does not fit into an int the function panics with an out of range error.

func (*Properties) MustGetUint64

func (p *Properties) MustGetUint64(key string) uint64

MustGetUint64 parses the expanded value as an int if the key exists. If key does not exist or the value cannot be parsed the function panics.

func (*Properties) MustSet

func (p *Properties) MustSet(key, value string) (prev string, ok bool)

MustSet sets the property key to the corresponding value. If a value for key existed before then ok is true and prev contains the previous value. An empty key is silently ignored.

func (*Properties) Set

func (p *Properties) Set(key, value string) (prev string, ok bool, err error)

Set sets the property key to the corresponding value. If a value for key existed before then ok is true and prev contains the previous value. If the value contains a circular reference or a malformed expression then an error is returned. An empty key is silently ignored.

func (*Properties) SetComment

func (p *Properties) SetComment(key, comment string)

SetComment sets the comment for the key.

func (*Properties) SetComments

func (p *Properties) SetComments(key string, comments []string)

SetComments sets the comments for the key. If the comments are nil then all comments for this key are deleted.

func (*Properties) String

func (p *Properties) String() string

String returns a string of all expanded 'key = value' pairs.

func (*Properties) Write

func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error)

Write writes all unexpanded 'key = value' pairs to the given writer. Write returns the number of bytes written and any write error encountered.

func (*Properties) WriteComment

func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n int, err error)

WriteComment writes all unexpanced 'key = value' pairs to the given writer. If prefix is not empty then comments are written with a blank line and the given prefix. The prefix should be either "# " or "! " to be compatible with the properties file format. Otherwise, the properties parser will not be able to read the file back in. It returns the number of bytes written and any write error encountered.

Notes

Bugs

  • Set() does not check for invalid unicode literals since this is currently handled by the lexer.

  • Write() does not allow to configure the newline character. Therefore, on Windows LF is used.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL