Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configurable default placeholder handling #71

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion load.go
Expand Up @@ -270,7 +270,7 @@ func must(p *Properties, err error) *Properties {
// with an empty string. Malformed expressions like "${ENV_VAR" will
// be reported as error.
func expandName(name string) (string, error) {
return expand(name, []string{}, "${", "}", make(map[string]string))
return expand(name, []string{}, "${", "}", make(map[string]string), HandleDefaultPlaceholderWithEnv)
}

// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string.
Expand Down
39 changes: 31 additions & 8 deletions properties.go
Expand Up @@ -62,6 +62,8 @@ type Properties struct {
// true Properties behaves like a simple key/value store and does
// not check for circular references on Get() or on Set().
DisableExpansion bool
// HandleDefaultPlaceholder controls the behavior of default placeholder
HandleDefaultPlaceholder HandleDefaultPlaceholder

// Stores the key/value pairs
m map[string]string
Expand All @@ -82,9 +84,12 @@ func NewProperties() *Properties {
return &Properties{
Prefix: "${",
Postfix: "}",
m: map[string]string{},
c: map[string][]string{},
k: []string{},

HandleDefaultPlaceholder: HandleDefaultPlaceholderWithEnv,

m: map[string]string{},
c: map[string][]string{},
k: []string{},
}
}

Expand Down Expand Up @@ -731,14 +736,17 @@ func (p *Properties) expand(key, input string) (string, error) {
if p.Prefix == "" && p.Postfix == "" {
return input, nil
}

return expand(input, []string{key}, p.Prefix, p.Postfix, p.m)
handleDefaultPlaceholder := HandleDefaultPlaceholderWithEnv
if p.HandleDefaultPlaceholder != nil {
handleDefaultPlaceholder = p.HandleDefaultPlaceholder
}
return expand(input, []string{key}, p.Prefix, p.Postfix, p.m, handleDefaultPlaceholder)
}

// expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values.
// The function keeps track of the keys that were already expanded and stops if it
// detects a circular reference or a malformed expression of the form '(prefix)key'.
func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) {
func expand(s string, keys []string, prefix, postfix string, values map[string]string, handleDefaultPlaceholder HandleDefaultPlaceholder) (string, error) {
if len(keys) > maxExpansionDepth {
return "", fmt.Errorf("expansion too deep")
}
Expand Down Expand Up @@ -773,16 +781,31 @@ func expand(s string, keys []string, prefix, postfix string, values map[string]s

val, ok := values[key]
if !ok {
val = os.Getenv(key)
val, ok = handleDefaultPlaceholder(key)
if !ok {
return "", fmt.Errorf("unresovled key: %v", key)
}
}
new_val, err := expand(val, append(keys, key), prefix, postfix, values)
new_val, err := expand(val, append(keys, key), prefix, postfix, values, handleDefaultPlaceholder)
if err != nil {
return "", err
}
s = s[:start] + new_val + s[end+1:]
}
}

type HandleDefaultPlaceholder func(key string) (string, bool)

func HandleDefaultPlaceholderWithEnv(key string) (string, bool) {
return os.Getenv(key), true
}

var _ HandleDefaultPlaceholder = os.LookupEnv

func HandleDefaultPlaceholderDummy(key string) (string, bool) {
return "", false
}

// encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters.
func encode(s string, special string, enc Encoding) string {
switch enc {
Expand Down