Skip to content

Commit

Permalink
Added ability to import xsd files from a file system
Browse files Browse the repository at this point in the history
  • Loading branch information
realmfoo committed Sep 29, 2017
1 parent a597d52 commit 1cbc239
Show file tree
Hide file tree
Showing 4 changed files with 277 additions and 63 deletions.
77 changes: 34 additions & 43 deletions gowsdl.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"log"
"net"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
Expand All @@ -28,7 +27,8 @@ const maxRecursion uint8 = 20

// GoWSDL defines the struct for WSDL generator.
type GoWSDL struct {
file, pkg string
loc *Location
pkg string
ignoreTLS bool
makePublicFn func(string) string
wsdl *WSDL
Expand Down Expand Up @@ -95,8 +95,13 @@ func NewGoWSDL(file, pkg string, ignoreTLS bool, exportAllTypes bool) (*GoWSDL,
makePublicFn = makePublic
}

r, err := ParseLocation(file)
if err != nil {
return nil, err
}

return &GoWSDL{
file: file,
loc: r,
pkg: pkg,
ignoreTLS: ignoreTLS,
makePublicFn: makePublicFn,
Expand Down Expand Up @@ -152,24 +157,21 @@ func (g *GoWSDL) Start() (map[string][]byte, error) {
return gocode, nil
}

func (g *GoWSDL) unmarshal() error {
var data []byte

parsedURL, err := url.Parse(g.file)
if parsedURL.Scheme == "" {
//log.Println("Reading", "file", g.file)

data, err = ioutil.ReadFile(g.file)
if err != nil {
return err
}
func (g *GoWSDL) fetchFile(loc *Location) (data []byte, err error) {
if loc.f != "" {
log.Println("Reading", "file", loc.f)
data, err = ioutil.ReadFile(loc.f)
} else {
log.Println("Downloading", "file", g.file)
log.Println("Downloading", "file", loc.u.String())
data, err = downloadFile(loc.u.String(), g.ignoreTLS)
}
return
}

data, err = downloadFile(g.file, g.ignoreTLS)
if err != nil {
return err
}
func (g *GoWSDL) unmarshal() error {
data, err := g.fetchFile(g.loc)
if err != nil {
return err
}

g.wsdl = new(WSDL)
Expand All @@ -179,7 +181,7 @@ func (g *GoWSDL) unmarshal() error {
}

for _, schema := range g.wsdl.Types.Schemas {
err = g.resolveXSDExternals(schema, parsedURL)
err = g.resolveXSDExternals(schema, g.loc)
if err != nil {
return err
}
Expand All @@ -188,30 +190,19 @@ func (g *GoWSDL) unmarshal() error {
return nil
}

func (g *GoWSDL) resolveXSDExternals(schema *XSDSchema, u *url.URL) error {
download := func(u1 *url.URL, loc string) error {
location, err := u1.Parse(loc)
func (g *GoWSDL) resolveXSDExternals(schema *XSDSchema, loc *Location) error {
download := func(base *Location, ref string) error {
location, err := base.Parse(ref)
if err != nil {
return err
}
_, schemaName := filepath.Split(location.Path)
if g.resolvedXSDExternals[schemaName] {
schemaKey := location.String()
if g.resolvedXSDExternals[location.String()] {
return nil
}

if !location.IsAbs() {
if !u1.IsAbs() {
return fmt.Errorf("Unable to resolve external schema %s through WSDL URL %s", location.String(), u1)
}
if location, err = url.Parse(u1.Scheme + "://" + u1.Host + location.String()); err != nil {
return err
}
}

log.Println("Downloading external schema", "location", location.String())

data, err := downloadFile(location.String(), g.ignoreTLS)
if err != nil {
var data []byte
if data, err = g.fetchFile(location); err != nil {
return err
}

Expand All @@ -237,19 +228,19 @@ func (g *GoWSDL) resolveXSDExternals(schema *XSDSchema, u *url.URL) error {
if g.resolvedXSDExternals == nil {
g.resolvedXSDExternals = make(map[string]bool, maxRecursion)
}
g.resolvedXSDExternals[schemaName] = true
g.resolvedXSDExternals[schemaKey] = true

return nil
}

for _, impts := range schema.Imports {
if e := download(u, impts.SchemaLocation); e != nil {
if e := download(loc, impts.SchemaLocation); e != nil {
return e
}
}

for _, incl := range schema.Includes {
if e := download(u, incl.SchemaLocation); e != nil {
if e := download(loc, incl.SchemaLocation); e != nil {
return e
}
}
Expand Down Expand Up @@ -417,9 +408,9 @@ func removeNS(xsdType string) string {

if len(r) == 2 {
return r[1]
} else {
return r[0]
}

return r[0]
}

func toGoType(xsdType string) string {
Expand Down
35 changes: 15 additions & 20 deletions gowsdl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ import (
)

func TestElementGenerationDoesntCommentOutStructProperty(t *testing.T) {
g := GoWSDL{
file: "fixtures/test.wsdl",
pkg: "myservice",
makePublicFn: makePublic,
g, err := NewGoWSDL("fixtures/test.wsdl", "myservice", false, true)
if err != nil {
t.Error(err)
}

resp, err := g.Start()
Expand All @@ -36,10 +35,9 @@ func TestElementGenerationDoesntCommentOutStructProperty(t *testing.T) {
}

func TestComplexTypeWithInlineSimpleType(t *testing.T) {
g := GoWSDL{
file: "fixtures/test.wsdl",
pkg: "myservice",
makePublicFn: makePublic,
g, err := NewGoWSDL("fixtures/test.wsdl", "myservice", false, true)
if err != nil {
t.Error(err)
}

resp, err := g.Start()
Expand Down Expand Up @@ -68,10 +66,9 @@ func TestVboxGeneratesWithoutSyntaxErrors(t *testing.T) {
}

for _, file := range files {
g := GoWSDL{
file: file,
pkg: "myservice",
makePublicFn: makePublic,
g, err := NewGoWSDL(file, "myservice", false, true)
if err != nil {
t.Error(err)
}

resp, err := g.Start()
Expand All @@ -94,10 +91,9 @@ func TestVboxGeneratesWithoutSyntaxErrors(t *testing.T) {
}

func TestSOAPHeaderGeneratesWithoutErrors(t *testing.T) {
g := GoWSDL{
file: "fixtures/ferry.wsdl",
pkg: "myservice",
makePublicFn: makePublic,
g, err := NewGoWSDL("fixtures/ferry.wsdl", "myservice", false, true)
if err != nil {
t.Error(err)
}

resp, err := g.Start()
Expand All @@ -111,10 +107,9 @@ func TestSOAPHeaderGeneratesWithoutErrors(t *testing.T) {

func TestEnumerationsGeneratedCorrectly(t *testing.T) {
enumStringTest := func(t *testing.T, fixtureWsdl string, varName string, typeName string, enumString string) {
g := GoWSDL{
file: "fixtures/" + fixtureWsdl,
pkg: "myservice",
makePublicFn: makePublic,
g, err := NewGoWSDL("fixtures/"+fixtureWsdl, "myservice", false, true)
if err != nil {
t.Error(err)
}

resp, err := g.Start()
Expand Down
81 changes: 81 additions & 0 deletions location.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package gowsdl

import (
"net/url"
"path/filepath"
)

// A Location encapsulate information about the loc of WSDL/XSD.
//
// It could be either URL or an absolute file path.
type Location struct {
u *url.URL
f string
}

// ParseLocation parses a rawloc into a Location structure.
//
// If rawloc is URL then it should be absolute.
// Relative file path will be converted into absolute path.
func ParseLocation(rawloc string) (*Location, error) {
u, _ := url.Parse(rawloc)
if u.Scheme != "" {
return &Location{u: u}, nil
}

absURI, err := filepath.Abs(rawloc)
if err != nil {
return nil, err
}

return &Location{f: absURI}, nil
}

// Parse parses path in the context of the receiver. The provided path may be relative or absolute.
// Parse returns nil, err on parse failure.
func (r *Location) Parse(ref string) (*Location, error) {
if r.u != nil {
u, err := r.u.Parse(ref)
if err != nil {
return nil, err
}
return &Location{u: u}, nil
}

if filepath.IsAbs(ref) {
return &Location{f: ref}, nil
}

if u, err := url.Parse(ref); err == nil {
if u.Scheme != "" {
return &Location{u: u}, nil
}
}

return &Location{f: filepath.Join(filepath.Dir(r.f), ref)}, nil
}

// IsFile determines whether the Location contains a file path.
func (r *Location) isFile() bool {
return r.f != ""
}

// IsFile determines whether the Location contains URL.
func (r *Location) isURL() bool {
return r.u != nil
}

// String reassembles the Location either into a valid URL string or a file path.
func (r *Location) String() string {
if r.isFile() {
return r.f
}
if r.isURL() {
return r.u.String()
}
return ""
}
Loading

0 comments on commit 1cbc239

Please sign in to comment.