1 // Copyright 2017 Google Inc. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
26 "github.com/golang/protobuf/proto"
27 "github.com/golang/protobuf/ptypes/any"
28 ext_plugin "github.com/googleapis/gnostic/extensions"
29 yaml "gopkg.in/yaml.v2"
32 // ExtensionHandler describes a binary that is called by the compiler to handle specification extensions.
33 type ExtensionHandler struct {
37 // HandleExtension calls a binary extension handler.
38 func HandleExtension(context *Context, in interface{}, extensionName string) (bool, *any.Any, error) {
40 var errFromPlugin error
41 var outFromPlugin *any.Any
43 if context != nil && context.ExtensionHandlers != nil && len(*(context.ExtensionHandlers)) != 0 {
44 for _, customAnyProtoGenerator := range *(context.ExtensionHandlers) {
45 outFromPlugin, errFromPlugin = customAnyProtoGenerator.handle(in, extensionName)
46 if outFromPlugin == nil {
54 return handled, outFromPlugin, errFromPlugin
57 func (extensionHandlers *ExtensionHandler) handle(in interface{}, extensionName string) (*any.Any, error) {
58 if extensionHandlers.Name != "" {
59 binary, _ := yaml.Marshal(in)
61 request := &ext_plugin.ExtensionHandlerRequest{}
63 version := &ext_plugin.Version{}
67 request.CompilerVersion = version
69 request.Wrapper = &ext_plugin.Wrapper{}
71 request.Wrapper.Version = "v2"
72 request.Wrapper.Yaml = string(binary)
73 request.Wrapper.ExtensionName = extensionName
75 requestBytes, _ := proto.Marshal(request)
76 cmd := exec.Command(extensionHandlers.Name)
77 cmd.Stdin = bytes.NewReader(requestBytes)
78 output, err := cmd.Output()
81 fmt.Printf("Error: %+v\n", err)
84 response := &ext_plugin.ExtensionHandlerResponse{}
85 err = proto.Unmarshal(output, response)
87 fmt.Printf("Error: %+v\n", err)
88 fmt.Printf("%s\n", string(output))
91 if !response.Handled {
94 if len(response.Error) != 0 {
95 message := fmt.Sprintf("Errors when parsing: %+v for field %s by vendor extension handler %s. Details %+v", in, extensionName, extensionHandlers.Name, strings.Join(response.Error, ","))
96 return nil, errors.New(message)
98 return response.Value, nil