- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
- package parser
-
- import (
- "bytes"
- "fmt"
- "github.com/seata/seata-go/pkg/saga/statemachine"
- "io"
- "os"
-
- "github.com/knadh/koanf"
- "github.com/knadh/koanf/parsers/json"
- "github.com/knadh/koanf/parsers/yaml"
- "github.com/knadh/koanf/providers/rawbytes"
- )
-
- // ConfigParser is a general configuration parser interface, used to agree on the implementation of different types of parsers
- type ConfigParser interface {
- Parse(configContent []byte) (*statemachine.StateMachineObject, error)
- }
-
- type JSONConfigParser struct{}
-
- func NewJSONConfigParser() *JSONConfigParser {
- return &JSONConfigParser{}
- }
-
- func (p *JSONConfigParser) Parse(configContent []byte) (*statemachine.StateMachineObject, error) {
- if configContent == nil || len(configContent) == 0 {
- return nil, fmt.Errorf("empty JSON config content")
- }
-
- k := koanf.New(".")
- if err := k.Load(rawbytes.Provider(configContent), json.Parser()); err != nil {
- return nil, fmt.Errorf("failed to parse JSON config content: %w", err)
- }
-
- var stateMachineObject statemachine.StateMachineObject
- if err := k.Unmarshal("", &stateMachineObject); err != nil {
- return nil, fmt.Errorf("failed to unmarshal JSON config to struct: %w", err)
- }
-
- return &stateMachineObject, nil
- }
-
- type YAMLConfigParser struct{}
-
- func NewYAMLConfigParser() *YAMLConfigParser {
- return &YAMLConfigParser{}
- }
-
- func (p *YAMLConfigParser) Parse(configContent []byte) (*statemachine.StateMachineObject, error) {
- if configContent == nil || len(configContent) == 0 {
- return nil, fmt.Errorf("empty YAML config content")
- }
-
- k := koanf.New(".")
- if err := k.Load(rawbytes.Provider(configContent), yaml.Parser()); err != nil {
- return nil, fmt.Errorf("failed to parse YAML config content: %w", err)
- }
-
- var stateMachineObject statemachine.StateMachineObject
- if err := k.Unmarshal("", &stateMachineObject); err != nil {
- return nil, fmt.Errorf("failed to unmarshal YAML config to struct: %w", err)
- }
-
- return &stateMachineObject, nil
- }
-
- type StateMachineConfigParser struct{}
-
- func NewStateMachineConfigParser() *StateMachineConfigParser {
- return &StateMachineConfigParser{}
- }
-
- func (p *StateMachineConfigParser) CheckConfigFile(filePath string) error {
- _, err := os.Stat(filePath)
- if os.IsNotExist(err) {
- return fmt.Errorf("config file %s does not exist: %w", filePath, err)
- }
- if err != nil {
- return fmt.Errorf("failed to access config file %s: %w", filePath, err)
- }
- return nil
- }
-
- func (p *StateMachineConfigParser) ReadConfigFile(configFilePath string) ([]byte, error) {
- file, _ := os.Open(configFilePath)
- defer func(file *os.File) {
- _ = file.Close()
- }(file)
-
- var buf bytes.Buffer
- _, err := io.Copy(&buf, file)
- if err != nil {
- return nil, fmt.Errorf("failed to read config file %s: %w", configFilePath, err)
- }
-
- return buf.Bytes(), nil
- }
-
- func (p *StateMachineConfigParser) getParser(content []byte) (ConfigParser, error) {
- k := koanf.New(".")
- if err := k.Load(rawbytes.Provider(content), json.Parser()); err == nil {
- return NewJSONConfigParser(), nil
- }
-
- k = koanf.New(".")
- if err := k.Load(rawbytes.Provider(content), yaml.Parser()); err == nil {
- return NewYAMLConfigParser(), nil
- }
-
- return nil, fmt.Errorf("unsupported config file format")
- }
-
- func (p *StateMachineConfigParser) Parse(content []byte) (*statemachine.StateMachineObject, error) {
- parser, err := p.getParser(content)
- if err != nil {
- return nil, err
- }
-
- return parser.Parse(content)
- }
|