OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / github.com / magiconair / properties / load.go
diff --git a/vendor/github.com/magiconair/properties/load.go b/vendor/github.com/magiconair/properties/load.go
new file mode 100644 (file)
index 0000000..278cc2e
--- /dev/null
@@ -0,0 +1,241 @@
+// Copyright 2017 Frank Schroeder. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package properties
+
+import (
+       "fmt"
+       "io/ioutil"
+       "net/http"
+       "os"
+       "strings"
+)
+
+// Encoding specifies encoding of the input data.
+type Encoding uint
+
+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
+)
+
+// Load reads a buffer into a Properties struct.
+func Load(buf []byte, enc Encoding) (*Properties, error) {
+       return loadBuf(buf, enc)
+}
+
+// LoadString reads an UTF8 string into a properties struct.
+func LoadString(s string) (*Properties, error) {
+       return loadBuf([]byte(s), UTF8)
+}
+
+// LoadMap creates a new Properties struct from a string map.
+func LoadMap(m map[string]string) *Properties {
+       p := NewProperties()
+       for k, v := range m {
+               p.Set(k, v)
+       }
+       return p
+}
+
+// LoadFile reads a file into a Properties struct.
+func LoadFile(filename string, enc Encoding) (*Properties, error) {
+       return loadAll([]string{filename}, enc, false)
+}
+
+// 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 LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
+       return loadAll(filenames, enc, ignoreMissing)
+}
+
+// LoadURL reads the content of the URL into a Properties struct.
+//
+// The encoding is determined via the Content-Type header which
+// should be set to 'text/plain'. If the 'charset' parameter is
+// missing, 'iso-8859-1' or 'latin1' the encoding is set to
+// ISO-8859-1. If the 'charset' parameter is set to 'utf-8' the
+// encoding is set to UTF-8. A missing content type header is
+// interpreted as 'text/plain; charset=utf-8'.
+func LoadURL(url string) (*Properties, error) {
+       return loadAll([]string{url}, UTF8, false)
+}
+
+// LoadURLs reads the content of multiple URLs in the given order into a
+// Properties struct. If 'ignoreMissing' is true then a 404 status code will
+// not be reported as error. See LoadURL for the Content-Type header
+// and the encoding.
+func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) {
+       return loadAll(urls, UTF8, ignoreMissing)
+}
+
+// LoadAll reads the content of multiple URLs or files in the given order into a
+// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will
+// not be reported as error. Encoding sets the encoding for files. For the URLs please see
+// LoadURL for the Content-Type header and the encoding.
+func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
+       return loadAll(names, enc, ignoreMissing)
+}
+
+// MustLoadString reads an UTF8 string into a Properties struct and
+// panics on error.
+func MustLoadString(s string) *Properties {
+       return must(LoadString(s))
+}
+
+// MustLoadFile reads a file into a Properties struct and
+// panics on error.
+func MustLoadFile(filename string, enc Encoding) *Properties {
+       return must(LoadFile(filename, enc))
+}
+
+// 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 MustLoadFiles(filenames []string, enc Encoding, ignoreMissing bool) *Properties {
+       return must(LoadFiles(filenames, enc, ignoreMissing))
+}
+
+// MustLoadURL reads the content of a URL into a Properties struct and
+// panics on error.
+func MustLoadURL(url string) *Properties {
+       return must(LoadURL(url))
+}
+
+// MustLoadURLs reads the content of multiple URLs in the given order into a
+// Properties struct and panics on error. If 'ignoreMissing' is true then a 404
+// status code will not be reported as error.
+func MustLoadURLs(urls []string, ignoreMissing bool) *Properties {
+       return must(LoadURLs(urls, ignoreMissing))
+}
+
+// MustLoadAll reads the content of multiple URLs or files in the given order into a
+// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will
+// not be reported as error. Encoding sets the encoding for files. For the URLs please see
+// LoadURL for the Content-Type header and the encoding. It panics on error.
+func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties {
+       return must(LoadAll(names, enc, ignoreMissing))
+}
+
+func loadBuf(buf []byte, enc Encoding) (*Properties, error) {
+       p, err := parse(convert(buf, enc))
+       if err != nil {
+               return nil, err
+       }
+       return p, p.check()
+}
+
+func loadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
+       result := NewProperties()
+       for _, name := range names {
+               n, err := expandName(name)
+               if err != nil {
+                       return nil, err
+               }
+               var p *Properties
+               if strings.HasPrefix(n, "http://") || strings.HasPrefix(n, "https://") {
+                       p, err = loadURL(n, ignoreMissing)
+               } else {
+                       p, err = loadFile(n, enc, ignoreMissing)
+               }
+               if err != nil {
+                       return nil, err
+               }
+               result.Merge(p)
+
+       }
+       return result, result.check()
+}
+
+func loadFile(filename string, enc Encoding, ignoreMissing bool) (*Properties, error) {
+       data, err := ioutil.ReadFile(filename)
+       if err != nil {
+               if ignoreMissing && os.IsNotExist(err) {
+                       LogPrintf("properties: %s not found. skipping", filename)
+                       return NewProperties(), nil
+               }
+               return nil, err
+       }
+       p, err := parse(convert(data, enc))
+       if err != nil {
+               return nil, err
+       }
+       return p, nil
+}
+
+func loadURL(url string, ignoreMissing bool) (*Properties, error) {
+       resp, err := http.Get(url)
+       if err != nil {
+               return nil, fmt.Errorf("properties: error fetching %q. %s", url, err)
+       }
+       if resp.StatusCode == 404 && ignoreMissing {
+               LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode)
+               return NewProperties(), nil
+       }
+       if resp.StatusCode != 200 {
+               return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode)
+       }
+       body, err := ioutil.ReadAll(resp.Body)
+       if err != nil {
+               return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
+       }
+       if err = resp.Body.Close(); err != nil {
+               return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
+       }
+
+       ct := resp.Header.Get("Content-Type")
+       var enc Encoding
+       switch strings.ToLower(ct) {
+       case "text/plain", "text/plain; charset=iso-8859-1", "text/plain; charset=latin1":
+               enc = ISO_8859_1
+       case "", "text/plain; charset=utf-8":
+               enc = UTF8
+       default:
+               return nil, fmt.Errorf("properties: invalid content type %s", ct)
+       }
+
+       p, err := parse(convert(body, enc))
+       if err != nil {
+               return nil, err
+       }
+       return p, nil
+}
+
+func must(p *Properties, err error) *Properties {
+       if err != nil {
+               ErrorHandler(err)
+       }
+       return p
+}
+
+// expandName expands ${ENV_VAR} expressions in a name.
+// If the environment variable does not exist then it will be replaced
+// with an empty string. Malformed expressions like "${ENV_VAR" will
+// be reported as error.
+func expandName(name string) (string, error) {
+       return expand(name, make(map[string]bool), "${", "}", make(map[string]string))
+}
+
+// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string.
+// For ISO-8859-1 we can convert each byte straight into a rune since the
+// first 256 unicode code points cover ISO-8859-1.
+func convert(buf []byte, enc Encoding) string {
+       switch enc {
+       case UTF8:
+               return string(buf)
+       case ISO_8859_1:
+               runes := make([]rune, len(buf))
+               for i, b := range buf {
+                       runes[i] = rune(b)
+               }
+               return string(runes)
+       default:
+               ErrorHandler(fmt.Errorf("unsupported encoding %v", enc))
+       }
+       panic("ErrorHandler should exit")
+}