forked from LaconicNetwork/kompose
This adds github.com/pkg/errors to glide.yaml followed by glide and glide-vc commands. The github.com/pkg/errors package is currently required mainly for the errors.Wrap() and errors.New() methods, since this lets us to annotate the errors while passing the error message up the call stack.
287 lines
5.8 KiB
Go
287 lines
5.8 KiB
Go
// Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// author xeipuuv
|
|
// author-github https://github.com/xeipuuv
|
|
// author-mail xeipuuv@gmail.com
|
|
//
|
|
// repository-name gojsonschema
|
|
// repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language.
|
|
//
|
|
// description Different strategies to load JSON files.
|
|
// Includes References (file and HTTP), JSON strings and Go types.
|
|
//
|
|
// created 01-02-2015
|
|
|
|
package gojsonschema
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/xeipuuv/gojsonreference"
|
|
)
|
|
|
|
// JSON loader interface
|
|
|
|
type JSONLoader interface {
|
|
jsonSource() interface{}
|
|
loadJSON() (interface{}, error)
|
|
loadSchema() (*Schema, error)
|
|
}
|
|
|
|
// JSON Reference loader
|
|
// references are used to load JSONs from files and HTTP
|
|
|
|
type jsonReferenceLoader struct {
|
|
source string
|
|
}
|
|
|
|
func (l *jsonReferenceLoader) jsonSource() interface{} {
|
|
return l.source
|
|
}
|
|
|
|
func NewReferenceLoader(source string) *jsonReferenceLoader {
|
|
return &jsonReferenceLoader{source: source}
|
|
}
|
|
|
|
func (l *jsonReferenceLoader) loadJSON() (interface{}, error) {
|
|
|
|
var err error
|
|
|
|
reference, err := gojsonreference.NewJsonReference(l.jsonSource().(string))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
refToUrl := reference
|
|
refToUrl.GetUrl().Fragment = ""
|
|
|
|
var document interface{}
|
|
|
|
if reference.HasFileScheme {
|
|
|
|
filename := strings.Replace(refToUrl.String(), "file://", "", -1)
|
|
if runtime.GOOS == "windows" {
|
|
// on Windows, a file URL may have an extra leading slash, use slashes
|
|
// instead of backslashes, and have spaces escaped
|
|
if strings.HasPrefix(filename, "/") {
|
|
filename = filename[1:]
|
|
}
|
|
filename = filepath.FromSlash(filename)
|
|
filename = strings.Replace(filename, "%20", " ", -1)
|
|
}
|
|
|
|
document, err = l.loadFromFile(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
} else {
|
|
|
|
document, err = l.loadFromHTTP(refToUrl.String())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
}
|
|
|
|
return document, nil
|
|
|
|
}
|
|
|
|
func (l *jsonReferenceLoader) loadSchema() (*Schema, error) {
|
|
|
|
var err error
|
|
|
|
d := Schema{}
|
|
d.pool = newSchemaPool()
|
|
d.referencePool = newSchemaReferencePool()
|
|
|
|
d.documentReference, err = gojsonreference.NewJsonReference(l.jsonSource().(string))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
spd, err := d.pool.GetDocument(d.documentReference)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = d.parse(spd.Document)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &d, nil
|
|
|
|
}
|
|
|
|
func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error) {
|
|
|
|
resp, err := http.Get(address)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// must return HTTP Status 200 OK
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, errors.New(formatErrorDescription(Locale.httpBadStatus(), ErrorDetails{"status": resp.Status}))
|
|
}
|
|
|
|
bodyBuff, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return decodeJsonUsingNumber(bytes.NewReader(bodyBuff))
|
|
|
|
}
|
|
|
|
func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) {
|
|
|
|
bodyBuff, err := ioutil.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return decodeJsonUsingNumber(bytes.NewReader(bodyBuff))
|
|
|
|
}
|
|
|
|
// JSON string loader
|
|
|
|
type jsonStringLoader struct {
|
|
source string
|
|
}
|
|
|
|
func (l *jsonStringLoader) jsonSource() interface{} {
|
|
return l.source
|
|
}
|
|
|
|
func NewStringLoader(source string) *jsonStringLoader {
|
|
return &jsonStringLoader{source: source}
|
|
}
|
|
|
|
func (l *jsonStringLoader) loadJSON() (interface{}, error) {
|
|
|
|
return decodeJsonUsingNumber(strings.NewReader(l.jsonSource().(string)))
|
|
|
|
}
|
|
|
|
func (l *jsonStringLoader) loadSchema() (*Schema, error) {
|
|
|
|
var err error
|
|
|
|
document, err := l.loadJSON()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
d := Schema{}
|
|
d.pool = newSchemaPool()
|
|
d.referencePool = newSchemaReferencePool()
|
|
d.documentReference, err = gojsonreference.NewJsonReference("#")
|
|
d.pool.SetStandaloneDocument(document)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = d.parse(document)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &d, nil
|
|
|
|
}
|
|
|
|
// JSON Go (types) loader
|
|
// used to load JSONs from the code as maps, interface{}, structs ...
|
|
|
|
type jsonGoLoader struct {
|
|
source interface{}
|
|
}
|
|
|
|
func (l *jsonGoLoader) jsonSource() interface{} {
|
|
return l.source
|
|
}
|
|
|
|
func NewGoLoader(source interface{}) *jsonGoLoader {
|
|
return &jsonGoLoader{source: source}
|
|
}
|
|
|
|
func (l *jsonGoLoader) loadJSON() (interface{}, error) {
|
|
|
|
// convert it to a compliant JSON first to avoid types "mismatches"
|
|
|
|
jsonBytes, err := json.Marshal(l.jsonSource())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return decodeJsonUsingNumber(bytes.NewReader(jsonBytes))
|
|
|
|
}
|
|
|
|
func (l *jsonGoLoader) loadSchema() (*Schema, error) {
|
|
|
|
var err error
|
|
|
|
document, err := l.loadJSON()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
d := Schema{}
|
|
d.pool = newSchemaPool()
|
|
d.referencePool = newSchemaReferencePool()
|
|
d.documentReference, err = gojsonreference.NewJsonReference("#")
|
|
d.pool.SetStandaloneDocument(document)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = d.parse(document)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &d, nil
|
|
|
|
}
|
|
|
|
func decodeJsonUsingNumber(r io.Reader) (interface{}, error) {
|
|
|
|
var document interface{}
|
|
|
|
decoder := json.NewDecoder(r)
|
|
decoder.UseNumber()
|
|
|
|
err := decoder.Decode(&document)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return document, nil
|
|
|
|
}
|