Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
bdd6a6ae
Commit
bdd6a6ae
authored
Sep 10, 2015
by
astaxie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
golint config
parent
d7aaf2eb
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
194 additions
and
190 deletions
+194
-190
config.go
config/config.go
+10
-9
fake.go
config/fake.go
+21
-20
ini.go
config/ini.go
+41
-41
json.go
config/json.go
+25
-25
xml.go
config/xml/xml.go
+48
-47
yaml.go
config/yaml/yaml.go
+49
-48
No files found.
config/config.go
View file @
bdd6a6ae
...
...
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Package config is used to parse config
// Usage:
// import(
// "github.com/astaxie/beego/config"
...
...
@@ -45,8 +46,8 @@ import (
"fmt"
)
// Config
Contain
er defines how to get and set value from configuration raw data.
type
Config
Contain
er
interface
{
// Configer defines how to get and set value from configuration raw data.
type
Configer
interface
{
Set
(
key
,
val
string
)
error
// support section::key type in given key when using ini type.
String
(
key
string
)
string
// support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
Strings
(
key
string
)
[]
string
//get string slice
...
...
@@ -65,10 +66,10 @@ type ConfigContainer interface {
SaveConfigFile
(
filename
string
)
error
}
// Config is the adapter interface for parsing config file to get raw data to Config
Contain
er.
// Config is the adapter interface for parsing config file to get raw data to Configer.
type
Config
interface
{
Parse
(
key
string
)
(
Config
Contain
er
,
error
)
ParseData
(
data
[]
byte
)
(
Config
Contain
er
,
error
)
Parse
(
key
string
)
(
Configer
,
error
)
ParseData
(
data
[]
byte
)
(
Configer
,
error
)
}
var
adapters
=
make
(
map
[
string
]
Config
)
...
...
@@ -86,9 +87,9 @@ func Register(name string, adapter Config) {
adapters
[
name
]
=
adapter
}
// adapterName is ini/json/xml/yaml.
//
NewConfig
adapterName is ini/json/xml/yaml.
// filename is the config file path.
func
NewConfig
(
adapterName
,
filename
string
)
(
Config
Contain
er
,
error
)
{
func
NewConfig
(
adapterName
,
filename
string
)
(
Configer
,
error
)
{
adapter
,
ok
:=
adapters
[
adapterName
]
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"config: unknown adaptername %q (forgotten import?)"
,
adapterName
)
...
...
@@ -96,9 +97,9 @@ func NewConfig(adapterName, filename string) (ConfigContainer, error) {
return
adapter
.
Parse
(
filename
)
}
// adapterName is ini/json/xml/yaml.
//
NewConfigData
adapterName is ini/json/xml/yaml.
// data is the config data.
func
NewConfigData
(
adapterName
string
,
data
[]
byte
)
(
Config
Contain
er
,
error
)
{
func
NewConfigData
(
adapterName
string
,
data
[]
byte
)
(
Configer
,
error
)
{
adapter
,
ok
:=
adapters
[
adapterName
]
if
!
ok
{
return
nil
,
fmt
.
Errorf
(
"config: unknown adaptername %q (forgotten import?)"
,
adapterName
)
...
...
config/fake.go
View file @
bdd6a6ae
...
...
@@ -38,11 +38,11 @@ func (c *fakeConfigContainer) String(key string) string {
}
func
(
c
*
fakeConfigContainer
)
DefaultString
(
key
string
,
defaultval
string
)
string
{
if
v
:=
c
.
getData
(
key
);
v
==
""
{
v
:=
c
.
getData
(
key
)
if
v
==
""
{
return
defaultval
}
else
{
return
v
}
return
v
}
func
(
c
*
fakeConfigContainer
)
Strings
(
key
string
)
[]
string
{
...
...
@@ -50,11 +50,11 @@ func (c *fakeConfigContainer) Strings(key string) []string {
}
func
(
c
*
fakeConfigContainer
)
DefaultStrings
(
key
string
,
defaultval
[]
string
)
[]
string
{
if
v
:=
c
.
Strings
(
key
);
len
(
v
)
==
0
{
v
:=
c
.
Strings
(
key
)
if
len
(
v
)
==
0
{
return
defaultval
}
else
{
return
v
}
return
v
}
func
(
c
*
fakeConfigContainer
)
Int
(
key
string
)
(
int
,
error
)
{
...
...
@@ -62,11 +62,11 @@ func (c *fakeConfigContainer) Int(key string) (int, error) {
}
func
(
c
*
fakeConfigContainer
)
DefaultInt
(
key
string
,
defaultval
int
)
int
{
if
v
,
err
:=
c
.
Int
(
key
);
err
!=
nil
{
v
,
err
:=
c
.
Int
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
func
(
c
*
fakeConfigContainer
)
Int64
(
key
string
)
(
int64
,
error
)
{
...
...
@@ -74,11 +74,11 @@ func (c *fakeConfigContainer) Int64(key string) (int64, error) {
}
func
(
c
*
fakeConfigContainer
)
DefaultInt64
(
key
string
,
defaultval
int64
)
int64
{
if
v
,
err
:=
c
.
Int64
(
key
);
err
!=
nil
{
v
,
err
:=
c
.
Int64
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
func
(
c
*
fakeConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
...
...
@@ -86,11 +86,11 @@ func (c *fakeConfigContainer) Bool(key string) (bool, error) {
}
func
(
c
*
fakeConfigContainer
)
DefaultBool
(
key
string
,
defaultval
bool
)
bool
{
if
v
,
err
:=
c
.
Bool
(
key
);
err
!=
nil
{
v
,
err
:=
c
.
Bool
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
func
(
c
*
fakeConfigContainer
)
Float
(
key
string
)
(
float64
,
error
)
{
...
...
@@ -98,11 +98,11 @@ func (c *fakeConfigContainer) Float(key string) (float64, error) {
}
func
(
c
*
fakeConfigContainer
)
DefaultFloat
(
key
string
,
defaultval
float64
)
float64
{
if
v
,
err
:=
c
.
Float
(
key
);
err
!=
nil
{
v
,
err
:=
c
.
Float
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
func
(
c
*
fakeConfigContainer
)
DIY
(
key
string
)
(
interface
{},
error
)
{
...
...
@@ -120,9 +120,10 @@ func (c *fakeConfigContainer) SaveConfigFile(filename string) error {
return
errors
.
New
(
"not implement in the fakeConfigContainer"
)
}
var
_
Config
Contain
er
=
new
(
fakeConfigContainer
)
var
_
Configer
=
new
(
fakeConfigContainer
)
func
NewFakeConfig
()
ConfigContainer
{
// NewFakeConfig return a fake Congiger
func
NewFakeConfig
()
Configer
{
return
&
fakeConfigContainer
{
data
:
make
(
map
[
string
]
string
),
}
...
...
config/ini.go
View file @
bdd6a6ae
...
...
@@ -31,23 +31,23 @@ import (
)
var
(
DEFAULT_SECTION
=
"default"
// default section means if some ini items not in a section, make them in default section,
bNumComment
=
[]
byte
{
'#'
}
// number signal
bSemComment
=
[]
byte
{
';'
}
// semicolon signal
bEmpty
=
[]
byte
{}
bEqual
=
[]
byte
{
'='
}
// equal signal
bDQuote
=
[]
byte
{
'"'
}
// quote signal
sectionStart
=
[]
byte
{
'['
}
// section start signal
sectionEnd
=
[]
byte
{
']'
}
// section end signal
lineBreak
=
"
\n
"
defaultSection
=
"default"
// default section means if some ini items not in a section, make them in default section,
bNumComment
=
[]
byte
{
'#'
}
// number signal
bSemComment
=
[]
byte
{
';'
}
// semicolon signal
bEmpty
=
[]
byte
{}
bEqual
=
[]
byte
{
'='
}
// equal signal
bDQuote
=
[]
byte
{
'"'
}
// quote signal
sectionStart
=
[]
byte
{
'['
}
// section start signal
sectionEnd
=
[]
byte
{
']'
}
// section end signal
lineBreak
=
"
\n
"
)
// IniConfig implements Config to parse ini file.
type
IniConfig
struct
{
}
// Parse
File
creates a new Config and parses the file configuration from the named file.
func
(
ini
*
IniConfig
)
Parse
(
name
string
)
(
Config
Contain
er
,
error
)
{
// Parse creates a new Config and parses the file configuration from the named file.
func
(
ini
*
IniConfig
)
Parse
(
name
string
)
(
Configer
,
error
)
{
return
ini
.
parseFile
(
name
)
}
...
...
@@ -77,7 +77,7 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) {
buf
.
ReadByte
()
}
}
section
:=
DEFAULT_SECTION
section
:=
defaultSection
for
{
line
,
_
,
err
:=
buf
.
ReadLine
()
if
err
==
io
.
EOF
{
...
...
@@ -171,7 +171,8 @@ func (ini *IniConfig) parseFile(name string) (*IniConfigContainer, error) {
return
cfg
,
nil
}
func
(
ini
*
IniConfig
)
ParseData
(
data
[]
byte
)
(
ConfigContainer
,
error
)
{
// ParseData parse ini the data
func
(
ini
*
IniConfig
)
ParseData
(
data
[]
byte
)
(
Configer
,
error
)
{
// Save memory data to temporary file
tmpName
:=
path
.
Join
(
os
.
TempDir
(),
"beego"
,
fmt
.
Sprintf
(
"%d"
,
time
.
Now
()
.
Nanosecond
()))
os
.
MkdirAll
(
path
.
Dir
(
tmpName
),
os
.
ModePerm
)
...
...
@@ -181,7 +182,7 @@ func (ini *IniConfig) ParseData(data []byte) (ConfigContainer, error) {
return
ini
.
Parse
(
tmpName
)
}
// A Config represents the ini configuration.
//
IniConfigContainer
A Config represents the ini configuration.
// When set and get value, support key as section:name type.
type
IniConfigContainer
struct
{
filename
string
...
...
@@ -199,11 +200,11 @@ func (c *IniConfigContainer) Bool(key string) (bool, error) {
// DefaultBool returns the boolean value for a given key.
// if err != nil return defaltval
func
(
c
*
IniConfigContainer
)
DefaultBool
(
key
string
,
defaultval
bool
)
bool
{
if
v
,
err
:=
c
.
Bool
(
key
);
err
!=
nil
{
v
,
err
:=
c
.
Bool
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Int returns the integer value for a given key.
...
...
@@ -214,11 +215,11 @@ func (c *IniConfigContainer) Int(key string) (int, error) {
// DefaultInt returns the integer value for a given key.
// if err != nil return defaltval
func
(
c
*
IniConfigContainer
)
DefaultInt
(
key
string
,
defaultval
int
)
int
{
if
v
,
err
:=
c
.
Int
(
key
);
err
!=
nil
{
v
,
err
:=
c
.
Int
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Int64 returns the int64 value for a given key.
...
...
@@ -229,11 +230,11 @@ func (c *IniConfigContainer) Int64(key string) (int64, error) {
// DefaultInt64 returns the int64 value for a given key.
// if err != nil return defaltval
func
(
c
*
IniConfigContainer
)
DefaultInt64
(
key
string
,
defaultval
int64
)
int64
{
if
v
,
err
:=
c
.
Int64
(
key
);
err
!=
nil
{
v
,
err
:=
c
.
Int64
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Float returns the float value for a given key.
...
...
@@ -244,11 +245,11 @@ func (c *IniConfigContainer) Float(key string) (float64, error) {
// DefaultFloat returns the float64 value for a given key.
// if err != nil return defaltval
func
(
c
*
IniConfigContainer
)
DefaultFloat
(
key
string
,
defaultval
float64
)
float64
{
if
v
,
err
:=
c
.
Float
(
key
);
err
!=
nil
{
v
,
err
:=
c
.
Float
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// String returns the string value for a given key.
...
...
@@ -259,11 +260,11 @@ func (c *IniConfigContainer) String(key string) string {
// DefaultString returns the string value for a given key.
// if err != nil return defaltval
func
(
c
*
IniConfigContainer
)
DefaultString
(
key
string
,
defaultval
string
)
string
{
if
v
:=
c
.
String
(
key
);
v
==
""
{
v
:=
c
.
String
(
key
)
if
v
==
""
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Strings returns the []string value for a given key.
...
...
@@ -274,20 +275,19 @@ func (c *IniConfigContainer) Strings(key string) []string {
// DefaultStrings returns the []string value for a given key.
// if err != nil return defaltval
func
(
c
*
IniConfigContainer
)
DefaultStrings
(
key
string
,
defaultval
[]
string
)
[]
string
{
if
v
:=
c
.
Strings
(
key
);
len
(
v
)
==
0
{
v
:=
c
.
Strings
(
key
)
if
len
(
v
)
==
0
{
return
defaultval
}
else
{
return
v
}
return
v
}
// GetSection returns map for the given section
func
(
c
*
IniConfigContainer
)
GetSection
(
section
string
)
(
map
[
string
]
string
,
error
)
{
if
v
,
ok
:=
c
.
data
[
section
];
ok
{
return
v
,
nil
}
else
{
return
nil
,
errors
.
New
(
"not exist setction"
)
}
return
nil
,
errors
.
New
(
"not exist setction"
)
}
// SaveConfigFile save the config into file
...
...
@@ -301,7 +301,7 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
buf
:=
bytes
.
NewBuffer
(
nil
)
// Save default section at first place
if
dt
,
ok
:=
c
.
data
[
DEFAULT_SECTION
];
ok
{
if
dt
,
ok
:=
c
.
data
[
defaultSection
];
ok
{
for
key
,
val
:=
range
dt
{
if
key
!=
" "
{
// Write key comments.
...
...
@@ -325,7 +325,7 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
}
// Save named sections
for
section
,
dt
:=
range
c
.
data
{
if
section
!=
DEFAULT_SECTION
{
if
section
!=
defaultSection
{
// Write section comments.
if
v
,
ok
:=
c
.
sectionComment
[
section
];
ok
{
if
_
,
err
=
buf
.
WriteString
(
string
(
bNumComment
)
+
v
+
lineBreak
);
err
!=
nil
{
...
...
@@ -367,7 +367,7 @@ func (c *IniConfigContainer) SaveConfigFile(filename string) (err error) {
return
nil
}
//
WriteValue
writes a new value for key.
//
Set
writes a new value for key.
// if write to one section, the key need be "section::key".
// if the section is not existed, it panics.
func
(
c
*
IniConfigContainer
)
Set
(
key
,
value
string
)
error
{
...
...
@@ -379,14 +379,14 @@ func (c *IniConfigContainer) Set(key, value string) error {
var
(
section
,
k
string
sectionKey
[]
string
=
strings
.
Split
(
key
,
"::"
)
sectionKey
=
strings
.
Split
(
key
,
"::"
)
)
if
len
(
sectionKey
)
>=
2
{
section
=
sectionKey
[
0
]
k
=
sectionKey
[
1
]
}
else
{
section
=
DEFAULT_SECTION
section
=
defaultSection
k
=
sectionKey
[
0
]
}
...
...
@@ -415,13 +415,13 @@ func (c *IniConfigContainer) getdata(key string) string {
var
(
section
,
k
string
sectionKey
[]
string
=
strings
.
Split
(
strings
.
ToLower
(
key
),
"::"
)
sectionKey
=
strings
.
Split
(
strings
.
ToLower
(
key
),
"::"
)
)
if
len
(
sectionKey
)
>=
2
{
section
=
sectionKey
[
0
]
k
=
sectionKey
[
1
]
}
else
{
section
=
DEFAULT_SECTION
section
=
defaultSection
k
=
sectionKey
[
0
]
}
if
v
,
ok
:=
c
.
data
[
section
];
ok
{
...
...
config/json.go
View file @
bdd6a6ae
...
...
@@ -23,12 +23,12 @@ import (
"sync"
)
// J
son
Config is a json config parser and implements Config interface.
type
J
son
Config
struct
{
// J
SON
Config is a json config parser and implements Config interface.
type
J
SON
Config
struct
{
}
// Parse returns a ConfigContainer with parsed json config map.
func
(
js
*
J
sonConfig
)
Parse
(
filename
string
)
(
ConfigContain
er
,
error
)
{
func
(
js
*
J
SONConfig
)
Parse
(
filename
string
)
(
Config
er
,
error
)
{
file
,
err
:=
os
.
Open
(
filename
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -43,8 +43,8 @@ func (js *JsonConfig) Parse(filename string) (ConfigContainer, error) {
}
// ParseData returns a ConfigContainer with json string
func
(
js
*
J
sonConfig
)
ParseData
(
data
[]
byte
)
(
ConfigContain
er
,
error
)
{
x
:=
&
J
son
ConfigContainer
{
func
(
js
*
J
SONConfig
)
ParseData
(
data
[]
byte
)
(
Config
er
,
error
)
{
x
:=
&
J
SON
ConfigContainer
{
data
:
make
(
map
[
string
]
interface
{}),
}
err
:=
json
.
Unmarshal
(
data
,
&
x
.
data
)
...
...
@@ -59,15 +59,15 @@ func (js *JsonConfig) ParseData(data []byte) (ConfigContainer, error) {
return
x
,
nil
}
// A Config represents the json configuration.
//
JSONConfigContainer
A Config represents the json configuration.
// Only when get value, support key as section:name type.
type
J
son
ConfigContainer
struct
{
type
J
SON
ConfigContainer
struct
{
data
map
[
string
]
interface
{}
sync
.
RWMutex
}
// Bool returns the boolean value for a given key.
func
(
c
*
J
son
ConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
func
(
c
*
J
SON
ConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
val
:=
c
.
getData
(
key
)
if
val
!=
nil
{
if
v
,
ok
:=
val
.
(
bool
);
ok
{
...
...
@@ -80,7 +80,7 @@ func (c *JsonConfigContainer) Bool(key string) (bool, error) {
// DefaultBool return the bool value if has no error
// otherwise return the defaultval
func
(
c
*
J
son
ConfigContainer
)
DefaultBool
(
key
string
,
defaultval
bool
)
bool
{
func
(
c
*
J
SON
ConfigContainer
)
DefaultBool
(
key
string
,
defaultval
bool
)
bool
{
if
v
,
err
:=
c
.
Bool
(
key
);
err
==
nil
{
return
v
}
...
...
@@ -88,7 +88,7 @@ func (c *JsonConfigContainer) DefaultBool(key string, defaultval bool) bool {
}
// Int returns the integer value for a given key.
func
(
c
*
J
son
ConfigContainer
)
Int
(
key
string
)
(
int
,
error
)
{
func
(
c
*
J
SON
ConfigContainer
)
Int
(
key
string
)
(
int
,
error
)
{
val
:=
c
.
getData
(
key
)
if
val
!=
nil
{
if
v
,
ok
:=
val
.
(
float64
);
ok
{
...
...
@@ -101,7 +101,7 @@ func (c *JsonConfigContainer) Int(key string) (int, error) {
// DefaultInt returns the integer value for a given key.
// if err != nil return defaltval
func
(
c
*
J
son
ConfigContainer
)
DefaultInt
(
key
string
,
defaultval
int
)
int
{
func
(
c
*
J
SON
ConfigContainer
)
DefaultInt
(
key
string
,
defaultval
int
)
int
{
if
v
,
err
:=
c
.
Int
(
key
);
err
==
nil
{
return
v
}
...
...
@@ -109,7 +109,7 @@ func (c *JsonConfigContainer) DefaultInt(key string, defaultval int) int {
}
// Int64 returns the int64 value for a given key.
func
(
c
*
J
son
ConfigContainer
)
Int64
(
key
string
)
(
int64
,
error
)
{
func
(
c
*
J
SON
ConfigContainer
)
Int64
(
key
string
)
(
int64
,
error
)
{
val
:=
c
.
getData
(
key
)
if
val
!=
nil
{
if
v
,
ok
:=
val
.
(
float64
);
ok
{
...
...
@@ -122,7 +122,7 @@ func (c *JsonConfigContainer) Int64(key string) (int64, error) {
// DefaultInt64 returns the int64 value for a given key.
// if err != nil return defaltval
func
(
c
*
J
son
ConfigContainer
)
DefaultInt64
(
key
string
,
defaultval
int64
)
int64
{
func
(
c
*
J
SON
ConfigContainer
)
DefaultInt64
(
key
string
,
defaultval
int64
)
int64
{
if
v
,
err
:=
c
.
Int64
(
key
);
err
==
nil
{
return
v
}
...
...
@@ -130,7 +130,7 @@ func (c *JsonConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
}
// Float returns the float value for a given key.
func
(
c
*
J
son
ConfigContainer
)
Float
(
key
string
)
(
float64
,
error
)
{
func
(
c
*
J
SON
ConfigContainer
)
Float
(
key
string
)
(
float64
,
error
)
{
val
:=
c
.
getData
(
key
)
if
val
!=
nil
{
if
v
,
ok
:=
val
.
(
float64
);
ok
{
...
...
@@ -143,7 +143,7 @@ func (c *JsonConfigContainer) Float(key string) (float64, error) {
// DefaultFloat returns the float64 value for a given key.
// if err != nil return defaltval
func
(
c
*
J
son
ConfigContainer
)
DefaultFloat
(
key
string
,
defaultval
float64
)
float64
{
func
(
c
*
J
SON
ConfigContainer
)
DefaultFloat
(
key
string
,
defaultval
float64
)
float64
{
if
v
,
err
:=
c
.
Float
(
key
);
err
==
nil
{
return
v
}
...
...
@@ -151,7 +151,7 @@ func (c *JsonConfigContainer) DefaultFloat(key string, defaultval float64) float
}
// String returns the string value for a given key.
func
(
c
*
J
son
ConfigContainer
)
String
(
key
string
)
string
{
func
(
c
*
J
SON
ConfigContainer
)
String
(
key
string
)
string
{
val
:=
c
.
getData
(
key
)
if
val
!=
nil
{
if
v
,
ok
:=
val
.
(
string
);
ok
{
...
...
@@ -163,7 +163,7 @@ func (c *JsonConfigContainer) String(key string) string {
// DefaultString returns the string value for a given key.
// if err != nil return defaltval
func
(
c
*
J
son
ConfigContainer
)
DefaultString
(
key
string
,
defaultval
string
)
string
{
func
(
c
*
J
SON
ConfigContainer
)
DefaultString
(
key
string
,
defaultval
string
)
string
{
// TODO FIXME should not use "" to replace non existance
if
v
:=
c
.
String
(
key
);
v
!=
""
{
return
v
...
...
@@ -172,7 +172,7 @@ func (c *JsonConfigContainer) DefaultString(key string, defaultval string) strin
}
// Strings returns the []string value for a given key.
func
(
c
*
J
son
ConfigContainer
)
Strings
(
key
string
)
[]
string
{
func
(
c
*
J
SON
ConfigContainer
)
Strings
(
key
string
)
[]
string
{
stringVal
:=
c
.
String
(
key
)
if
stringVal
==
""
{
return
[]
string
{}
...
...
@@ -182,7 +182,7 @@ func (c *JsonConfigContainer) Strings(key string) []string {
// DefaultStrings returns the []string value for a given key.
// if err != nil return defaltval
func
(
c
*
J
son
ConfigContainer
)
DefaultStrings
(
key
string
,
defaultval
[]
string
)
[]
string
{
func
(
c
*
J
SON
ConfigContainer
)
DefaultStrings
(
key
string
,
defaultval
[]
string
)
[]
string
{
if
v
:=
c
.
Strings
(
key
);
len
(
v
)
>
0
{
return
v
}
...
...
@@ -190,7 +190,7 @@ func (c *JsonConfigContainer) DefaultStrings(key string, defaultval []string) []
}
// GetSection returns map for the given section
func
(
c
*
J
son
ConfigContainer
)
GetSection
(
section
string
)
(
map
[
string
]
string
,
error
)
{
func
(
c
*
J
SON
ConfigContainer
)
GetSection
(
section
string
)
(
map
[
string
]
string
,
error
)
{
if
v
,
ok
:=
c
.
data
[
section
];
ok
{
return
v
.
(
map
[
string
]
string
),
nil
}
...
...
@@ -198,7 +198,7 @@ func (c *JsonConfigContainer) GetSection(section string) (map[string]string, err
}
// SaveConfigFile save the config into file
func
(
c
*
J
son
ConfigContainer
)
SaveConfigFile
(
filename
string
)
(
err
error
)
{
func
(
c
*
J
SON
ConfigContainer
)
SaveConfigFile
(
filename
string
)
(
err
error
)
{
// Write configuration file by filename.
f
,
err
:=
os
.
Create
(
filename
)
if
err
!=
nil
{
...
...
@@ -214,7 +214,7 @@ func (c *JsonConfigContainer) SaveConfigFile(filename string) (err error) {
}
// Set writes a new value for key.
func
(
c
*
J
son
ConfigContainer
)
Set
(
key
,
val
string
)
error
{
func
(
c
*
J
SON
ConfigContainer
)
Set
(
key
,
val
string
)
error
{
c
.
Lock
()
defer
c
.
Unlock
()
c
.
data
[
key
]
=
val
...
...
@@ -222,7 +222,7 @@ func (c *JsonConfigContainer) Set(key, val string) error {
}
// DIY returns the raw value by a given key.
func
(
c
*
J
son
ConfigContainer
)
DIY
(
key
string
)
(
v
interface
{},
err
error
)
{
func
(
c
*
J
SON
ConfigContainer
)
DIY
(
key
string
)
(
v
interface
{},
err
error
)
{
val
:=
c
.
getData
(
key
)
if
val
!=
nil
{
return
val
,
nil
...
...
@@ -231,7 +231,7 @@ func (c *JsonConfigContainer) DIY(key string) (v interface{}, err error) {
}
// section.key or key
func
(
c
*
J
son
ConfigContainer
)
getData
(
key
string
)
interface
{}
{
func
(
c
*
J
SON
ConfigContainer
)
getData
(
key
string
)
interface
{}
{
if
len
(
key
)
==
0
{
return
nil
}
...
...
@@ -261,5 +261,5 @@ func (c *JsonConfigContainer) getData(key string) interface{} {
}
func
init
()
{
Register
(
"json"
,
&
J
son
Config
{})
Register
(
"json"
,
&
J
SON
Config
{})
}
config/xml/xml.go
View file @
bdd6a6ae
...
...
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
p
ackage xml for config provider
//
P
ackage xml for config provider
//
// depend on github.com/beego/x2j
//
...
...
@@ -45,20 +45,20 @@ import (
"github.com/beego/x2j"
)
//
Xml
Config is a xml config parser and implements Config interface.
// Config is a xml config parser and implements Config interface.
// xml configurations should be included in <config></config> tag.
// only support key/value pair as <key>value</key> as each item.
type
XML
Config
struct
{}
type
Config
struct
{}
// Parse returns a ConfigContainer with parsed xml config map.
func
(
xc
*
XMLConfig
)
Parse
(
filename
string
)
(
config
.
ConfigContain
er
,
error
)
{
func
(
xc
*
Config
)
Parse
(
filename
string
)
(
config
.
Config
er
,
error
)
{
file
,
err
:=
os
.
Open
(
filename
)
if
err
!=
nil
{
return
nil
,
err
}
defer
file
.
Close
()
x
:=
&
XML
ConfigContainer
{
data
:
make
(
map
[
string
]
interface
{})}
x
:=
&
ConfigContainer
{
data
:
make
(
map
[
string
]
interface
{})}
content
,
err
:=
ioutil
.
ReadAll
(
file
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -73,84 +73,86 @@ func (xc *XMLConfig) Parse(filename string) (config.ConfigContainer, error) {
return
x
,
nil
}
func
(
x
*
XMLConfig
)
ParseData
(
data
[]
byte
)
(
config
.
ConfigContainer
,
error
)
{
// ParseData xml data
func
(
xc
*
Config
)
ParseData
(
data
[]
byte
)
(
config
.
Configer
,
error
)
{
// Save memory data to temporary file
tmpName
:=
path
.
Join
(
os
.
TempDir
(),
"beego"
,
fmt
.
Sprintf
(
"%d"
,
time
.
Now
()
.
Nanosecond
()))
os
.
MkdirAll
(
path
.
Dir
(
tmpName
),
os
.
ModePerm
)
if
err
:=
ioutil
.
WriteFile
(
tmpName
,
data
,
0655
);
err
!=
nil
{
return
nil
,
err
}
return
x
.
Parse
(
tmpName
)
return
x
c
.
Parse
(
tmpName
)
}
// A Config represents the xml configuration.
type
XML
ConfigContainer
struct
{
//
ConfigContainer
A Config represents the xml configuration.
type
ConfigContainer
struct
{
data
map
[
string
]
interface
{}
sync
.
Mutex
}
// Bool returns the boolean value for a given key.
func
(
c
*
XML
ConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
func
(
c
*
ConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
return
strconv
.
ParseBool
(
c
.
data
[
key
]
.
(
string
))
}
// DefaultBool return the bool value if has no error
// otherwise return the defaultval
func
(
c
*
XMLConfigContainer
)
DefaultBool
(
key
string
,
defaultval
bool
)
bool
{
if
v
,
err
:=
c
.
Bool
(
key
);
err
!=
nil
{
func
(
c
*
ConfigContainer
)
DefaultBool
(
key
string
,
defaultval
bool
)
bool
{
v
,
err
:=
c
.
Bool
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Int returns the integer value for a given key.
func
(
c
*
XML
ConfigContainer
)
Int
(
key
string
)
(
int
,
error
)
{
func
(
c
*
ConfigContainer
)
Int
(
key
string
)
(
int
,
error
)
{
return
strconv
.
Atoi
(
c
.
data
[
key
]
.
(
string
))
}
// DefaultInt returns the integer value for a given key.
// if err != nil return defaltval
func
(
c
*
XMLConfigContainer
)
DefaultInt
(
key
string
,
defaultval
int
)
int
{
if
v
,
err
:=
c
.
Int
(
key
);
err
!=
nil
{
func
(
c
*
ConfigContainer
)
DefaultInt
(
key
string
,
defaultval
int
)
int
{
v
,
err
:=
c
.
Int
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Int64 returns the int64 value for a given key.
func
(
c
*
XML
ConfigContainer
)
Int64
(
key
string
)
(
int64
,
error
)
{
func
(
c
*
ConfigContainer
)
Int64
(
key
string
)
(
int64
,
error
)
{
return
strconv
.
ParseInt
(
c
.
data
[
key
]
.
(
string
),
10
,
64
)
}
// DefaultInt64 returns the int64 value for a given key.
// if err != nil return defaltval
func
(
c
*
XMLConfigContainer
)
DefaultInt64
(
key
string
,
defaultval
int64
)
int64
{
if
v
,
err
:=
c
.
Int64
(
key
);
err
!=
nil
{
func
(
c
*
ConfigContainer
)
DefaultInt64
(
key
string
,
defaultval
int64
)
int64
{
v
,
err
:=
c
.
Int64
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Float returns the float value for a given key.
func
(
c
*
XML
ConfigContainer
)
Float
(
key
string
)
(
float64
,
error
)
{
func
(
c
*
ConfigContainer
)
Float
(
key
string
)
(
float64
,
error
)
{
return
strconv
.
ParseFloat
(
c
.
data
[
key
]
.
(
string
),
64
)
}
// DefaultFloat returns the float64 value for a given key.
// if err != nil return defaltval
func
(
c
*
XMLConfigContainer
)
DefaultFloat
(
key
string
,
defaultval
float64
)
float64
{
if
v
,
err
:=
c
.
Float
(
key
);
err
!=
nil
{
func
(
c
*
ConfigContainer
)
DefaultFloat
(
key
string
,
defaultval
float64
)
float64
{
v
,
err
:=
c
.
Float
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// String returns the string value for a given key.
func
(
c
*
XML
ConfigContainer
)
String
(
key
string
)
string
{
func
(
c
*
ConfigContainer
)
String
(
key
string
)
string
{
if
v
,
ok
:=
c
.
data
[
key
]
.
(
string
);
ok
{
return
v
}
...
...
@@ -159,40 +161,39 @@ func (c *XMLConfigContainer) String(key string) string {
// DefaultString returns the string value for a given key.
// if err != nil return defaltval
func
(
c
*
XMLConfigContainer
)
DefaultString
(
key
string
,
defaultval
string
)
string
{
if
v
:=
c
.
String
(
key
);
v
==
""
{
func
(
c
*
ConfigContainer
)
DefaultString
(
key
string
,
defaultval
string
)
string
{
v
:=
c
.
String
(
key
)
if
v
==
""
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Strings returns the []string value for a given key.
func
(
c
*
XML
ConfigContainer
)
Strings
(
key
string
)
[]
string
{
func
(
c
*
ConfigContainer
)
Strings
(
key
string
)
[]
string
{
return
strings
.
Split
(
c
.
String
(
key
),
";"
)
}
// DefaultStrings returns the []string value for a given key.
// if err != nil return defaltval
func
(
c
*
XMLConfigContainer
)
DefaultStrings
(
key
string
,
defaultval
[]
string
)
[]
string
{
if
v
:=
c
.
Strings
(
key
);
len
(
v
)
==
0
{
func
(
c
*
ConfigContainer
)
DefaultStrings
(
key
string
,
defaultval
[]
string
)
[]
string
{
v
:=
c
.
Strings
(
key
)
if
len
(
v
)
==
0
{
return
defaultval
}
else
{
return
v
}
return
v
}
// GetSection returns map for the given section
func
(
c
*
XML
ConfigContainer
)
GetSection
(
section
string
)
(
map
[
string
]
string
,
error
)
{
func
(
c
*
ConfigContainer
)
GetSection
(
section
string
)
(
map
[
string
]
string
,
error
)
{
if
v
,
ok
:=
c
.
data
[
section
];
ok
{
return
v
.
(
map
[
string
]
string
),
nil
}
else
{
return
nil
,
errors
.
New
(
"not exist setction"
)
}
return
nil
,
errors
.
New
(
"not exist setction"
)
}
// SaveConfigFile save the config into file
func
(
c
*
XML
ConfigContainer
)
SaveConfigFile
(
filename
string
)
(
err
error
)
{
func
(
c
*
ConfigContainer
)
SaveConfigFile
(
filename
string
)
(
err
error
)
{
// Write configuration file by filename.
f
,
err
:=
os
.
Create
(
filename
)
if
err
!=
nil
{
...
...
@@ -207,8 +208,8 @@ func (c *XMLConfigContainer) SaveConfigFile(filename string) (err error) {
return
err
}
//
WriteValue
writes a new value for key.
func
(
c
*
XML
ConfigContainer
)
Set
(
key
,
val
string
)
error
{
//
Set
writes a new value for key.
func
(
c
*
ConfigContainer
)
Set
(
key
,
val
string
)
error
{
c
.
Lock
()
defer
c
.
Unlock
()
c
.
data
[
key
]
=
val
...
...
@@ -216,7 +217,7 @@ func (c *XMLConfigContainer) Set(key, val string) error {
}
// DIY returns the raw value by a given key.
func
(
c
*
XML
ConfigContainer
)
DIY
(
key
string
)
(
v
interface
{},
err
error
)
{
func
(
c
*
ConfigContainer
)
DIY
(
key
string
)
(
v
interface
{},
err
error
)
{
if
v
,
ok
:=
c
.
data
[
key
];
ok
{
return
v
,
nil
}
...
...
@@ -224,5 +225,5 @@ func (c *XMLConfigContainer) DIY(key string) (v interface{}, err error) {
}
func
init
()
{
config
.
Register
(
"xml"
,
&
XML
Config
{})
config
.
Register
(
"xml"
,
&
Config
{})
}
config/yaml/yaml.go
View file @
bdd6a6ae
...
...
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
p
ackage yaml for config provider
//
P
ackage yaml for config provider
//
// depend on github.com/beego/goyaml2
//
...
...
@@ -46,22 +46,23 @@ import (
"github.com/beego/goyaml2"
)
//
YAML
Config is a yaml config parser and implements Config interface.
type
YAML
Config
struct
{}
// Config is a yaml config parser and implements Config interface.
type
Config
struct
{}
// Parse returns a ConfigContainer with parsed yaml config map.
func
(
yaml
*
YAMLConfig
)
Parse
(
filename
string
)
(
y
config
.
ConfigContain
er
,
err
error
)
{
func
(
yaml
*
Config
)
Parse
(
filename
string
)
(
y
config
.
Config
er
,
err
error
)
{
cnf
,
err
:=
ReadYmlReader
(
filename
)
if
err
!=
nil
{
return
}
y
=
&
YAML
ConfigContainer
{
y
=
&
ConfigContainer
{
data
:
cnf
,
}
return
}
func
(
yaml
*
YAMLConfig
)
ParseData
(
data
[]
byte
)
(
config
.
ConfigContainer
,
error
)
{
// ParseData parse yaml data
func
(
yaml
*
Config
)
ParseData
(
data
[]
byte
)
(
config
.
Configer
,
error
)
{
// Save memory data to temporary file
tmpName
:=
path
.
Join
(
os
.
TempDir
(),
"beego"
,
fmt
.
Sprintf
(
"%d"
,
time
.
Now
()
.
Nanosecond
()))
os
.
MkdirAll
(
path
.
Dir
(
tmpName
),
os
.
ModePerm
)
...
...
@@ -71,7 +72,7 @@ func (yaml *YAMLConfig) ParseData(data []byte) (config.ConfigContainer, error) {
return
yaml
.
Parse
(
tmpName
)
}
// Read yaml file to map.
// Read
YmlReader Read
yaml file to map.
// if json like, use json package, unless goyaml2 package.
func
ReadYmlReader
(
path
string
)
(
cnf
map
[
string
]
interface
{},
err
error
)
{
f
,
err
:=
os
.
Open
(
path
)
...
...
@@ -112,14 +113,14 @@ func ReadYmlReader(path string) (cnf map[string]interface{}, err error) {
return
}
// A Config represents the yaml configuration.
type
YAML
ConfigContainer
struct
{
//
ConfigContainer
A Config represents the yaml configuration.
type
ConfigContainer
struct
{
data
map
[
string
]
interface
{}
sync
.
Mutex
}
// Bool returns the boolean value for a given key.
func
(
c
*
YAML
ConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
func
(
c
*
ConfigContainer
)
Bool
(
key
string
)
(
bool
,
error
)
{
if
v
,
ok
:=
c
.
data
[
key
]
.
(
bool
);
ok
{
return
v
,
nil
}
...
...
@@ -128,16 +129,16 @@ func (c *YAMLConfigContainer) Bool(key string) (bool, error) {
// DefaultBool return the bool value if has no error
// otherwise return the defaultval
func
(
c
*
YAMLConfigContainer
)
DefaultBool
(
key
string
,
defaultval
bool
)
bool
{
if
v
,
err
:=
c
.
Bool
(
key
);
err
!=
nil
{
func
(
c
*
ConfigContainer
)
DefaultBool
(
key
string
,
defaultval
bool
)
bool
{
v
,
err
:=
c
.
Bool
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Int returns the integer value for a given key.
func
(
c
*
YAML
ConfigContainer
)
Int
(
key
string
)
(
int
,
error
)
{
func
(
c
*
ConfigContainer
)
Int
(
key
string
)
(
int
,
error
)
{
if
v
,
ok
:=
c
.
data
[
key
]
.
(
int64
);
ok
{
return
int
(
v
),
nil
}
...
...
@@ -146,16 +147,16 @@ func (c *YAMLConfigContainer) Int(key string) (int, error) {
// DefaultInt returns the integer value for a given key.
// if err != nil return defaltval
func
(
c
*
YAMLConfigContainer
)
DefaultInt
(
key
string
,
defaultval
int
)
int
{
if
v
,
err
:=
c
.
Int
(
key
);
err
!=
nil
{
func
(
c
*
ConfigContainer
)
DefaultInt
(
key
string
,
defaultval
int
)
int
{
v
,
err
:=
c
.
Int
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Int64 returns the int64 value for a given key.
func
(
c
*
YAML
ConfigContainer
)
Int64
(
key
string
)
(
int64
,
error
)
{
func
(
c
*
ConfigContainer
)
Int64
(
key
string
)
(
int64
,
error
)
{
if
v
,
ok
:=
c
.
data
[
key
]
.
(
int64
);
ok
{
return
v
,
nil
}
...
...
@@ -164,16 +165,16 @@ func (c *YAMLConfigContainer) Int64(key string) (int64, error) {
// DefaultInt64 returns the int64 value for a given key.
// if err != nil return defaltval
func
(
c
*
YAMLConfigContainer
)
DefaultInt64
(
key
string
,
defaultval
int64
)
int64
{
if
v
,
err
:=
c
.
Int64
(
key
);
err
!=
nil
{
func
(
c
*
ConfigContainer
)
DefaultInt64
(
key
string
,
defaultval
int64
)
int64
{
v
,
err
:=
c
.
Int64
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Float returns the float value for a given key.
func
(
c
*
YAML
ConfigContainer
)
Float
(
key
string
)
(
float64
,
error
)
{
func
(
c
*
ConfigContainer
)
Float
(
key
string
)
(
float64
,
error
)
{
if
v
,
ok
:=
c
.
data
[
key
]
.
(
float64
);
ok
{
return
v
,
nil
}
...
...
@@ -182,16 +183,16 @@ func (c *YAMLConfigContainer) Float(key string) (float64, error) {
// DefaultFloat returns the float64 value for a given key.
// if err != nil return defaltval
func
(
c
*
YAMLConfigContainer
)
DefaultFloat
(
key
string
,
defaultval
float64
)
float64
{
if
v
,
err
:=
c
.
Float
(
key
);
err
!=
nil
{
func
(
c
*
ConfigContainer
)
DefaultFloat
(
key
string
,
defaultval
float64
)
float64
{
v
,
err
:=
c
.
Float
(
key
)
if
err
!=
nil
{
return
defaultval
}
else
{
return
v
}
return
v
}
// String returns the string value for a given key.
func
(
c
*
YAML
ConfigContainer
)
String
(
key
string
)
string
{
func
(
c
*
ConfigContainer
)
String
(
key
string
)
string
{
if
v
,
ok
:=
c
.
data
[
key
]
.
(
string
);
ok
{
return
v
}
...
...
@@ -200,40 +201,40 @@ func (c *YAMLConfigContainer) String(key string) string {
// DefaultString returns the string value for a given key.
// if err != nil return defaltval
func
(
c
*
YAMLConfigContainer
)
DefaultString
(
key
string
,
defaultval
string
)
string
{
if
v
:=
c
.
String
(
key
);
v
==
""
{
func
(
c
*
ConfigContainer
)
DefaultString
(
key
string
,
defaultval
string
)
string
{
v
:=
c
.
String
(
key
)
if
v
==
""
{
return
defaultval
}
else
{
return
v
}
return
v
}
// Strings returns the []string value for a given key.
func
(
c
*
YAML
ConfigContainer
)
Strings
(
key
string
)
[]
string
{
func
(
c
*
ConfigContainer
)
Strings
(
key
string
)
[]
string
{
return
strings
.
Split
(
c
.
String
(
key
),
";"
)
}
// DefaultStrings returns the []string value for a given key.
// if err != nil return defaltval
func
(
c
*
YAMLConfigContainer
)
DefaultStrings
(
key
string
,
defaultval
[]
string
)
[]
string
{
if
v
:=
c
.
Strings
(
key
);
len
(
v
)
==
0
{
func
(
c
*
ConfigContainer
)
DefaultStrings
(
key
string
,
defaultval
[]
string
)
[]
string
{
v
:=
c
.
Strings
(
key
)
if
len
(
v
)
==
0
{
return
defaultval
}
else
{
return
v
}
return
v
}
// GetSection returns map for the given section
func
(
c
*
YAMLConfigContainer
)
GetSection
(
section
string
)
(
map
[
string
]
string
,
error
)
{
if
v
,
ok
:=
c
.
data
[
section
];
ok
{
func
(
c
*
ConfigContainer
)
GetSection
(
section
string
)
(
map
[
string
]
string
,
error
)
{
v
,
ok
:=
c
.
data
[
section
]
if
ok
{
return
v
.
(
map
[
string
]
string
),
nil
}
else
{
return
nil
,
errors
.
New
(
"not exist setction"
)
}
return
nil
,
errors
.
New
(
"not exist setction"
)
}
// SaveConfigFile save the config into file
func
(
c
*
YAML
ConfigContainer
)
SaveConfigFile
(
filename
string
)
(
err
error
)
{
func
(
c
*
ConfigContainer
)
SaveConfigFile
(
filename
string
)
(
err
error
)
{
// Write configuration file by filename.
f
,
err
:=
os
.
Create
(
filename
)
if
err
!=
nil
{
...
...
@@ -244,8 +245,8 @@ func (c *YAMLConfigContainer) SaveConfigFile(filename string) (err error) {
return
err
}
//
WriteValue
writes a new value for key.
func
(
c
*
YAML
ConfigContainer
)
Set
(
key
,
val
string
)
error
{
//
Set
writes a new value for key.
func
(
c
*
ConfigContainer
)
Set
(
key
,
val
string
)
error
{
c
.
Lock
()
defer
c
.
Unlock
()
c
.
data
[
key
]
=
val
...
...
@@ -253,7 +254,7 @@ func (c *YAMLConfigContainer) Set(key, val string) error {
}
// DIY returns the raw value by a given key.
func
(
c
*
YAML
ConfigContainer
)
DIY
(
key
string
)
(
v
interface
{},
err
error
)
{
func
(
c
*
ConfigContainer
)
DIY
(
key
string
)
(
v
interface
{},
err
error
)
{
if
v
,
ok
:=
c
.
data
[
key
];
ok
{
return
v
,
nil
}
...
...
@@ -261,5 +262,5 @@ func (c *YAMLConfigContainer) DIY(key string) (v interface{}, err error) {
}
func
init
()
{
config
.
Register
(
"yaml"
,
&
YAML
Config
{})
config
.
Register
(
"yaml"
,
&
Config
{})
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment