1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 *   http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20package thrift
21
22import (
23	"context"
24	"strings"
25)
26
27const (
28	UNKNOWN_APPLICATION_EXCEPTION  = 0
29	UNKNOWN_METHOD                 = 1
30	INVALID_MESSAGE_TYPE_EXCEPTION = 2
31	WRONG_METHOD_NAME              = 3
32	BAD_SEQUENCE_ID                = 4
33	MISSING_RESULT                 = 5
34	INTERNAL_ERROR                 = 6
35	PROTOCOL_ERROR                 = 7
36	INVALID_TRANSFORM              = 8
37	INVALID_PROTOCOL               = 9
38	UNSUPPORTED_CLIENT_TYPE        = 10
39	VALIDATION_FAILED              = 11
40)
41
42var defaultApplicationExceptionMessage = map[int32]string{
43	UNKNOWN_APPLICATION_EXCEPTION:  "unknown application exception",
44	UNKNOWN_METHOD:                 "unknown method",
45	INVALID_MESSAGE_TYPE_EXCEPTION: "invalid message type",
46	WRONG_METHOD_NAME:              "wrong method name",
47	BAD_SEQUENCE_ID:                "bad sequence ID",
48	MISSING_RESULT:                 "missing result",
49	INTERNAL_ERROR:                 "unknown internal error",
50	PROTOCOL_ERROR:                 "unknown protocol error",
51	INVALID_TRANSFORM:              "Invalid transform",
52	INVALID_PROTOCOL:               "Invalid protocol",
53	UNSUPPORTED_CLIENT_TYPE:        "Unsupported client type",
54	VALIDATION_FAILED:              "validation failed",
55}
56
57// Application level Thrift exception
58type TApplicationException interface {
59	TException
60	TypeId() int32
61	Read(ctx context.Context, iprot TProtocol) error
62	Write(ctx context.Context, oprot TProtocol) error
63}
64
65type ValidationError struct {
66	message     string
67	check       string
68	fieldSymbol string
69}
70
71func (e *ValidationError) Check() string {
72	return e.check
73}
74
75func (e *ValidationError) TypeName() string {
76	return strings.Split(e.fieldSymbol, ".")[0]
77}
78
79func (e *ValidationError) Field() string {
80	if fs := strings.Split(e.fieldSymbol, "."); len(fs) > 1 {
81		return fs[1]
82	}
83	return e.fieldSymbol
84}
85
86func (e *ValidationError) FieldSymbol() string {
87	return e.fieldSymbol
88}
89
90func (e ValidationError) Error() string {
91	return e.message
92}
93
94type tApplicationException struct {
95	message string
96	type_   int32
97	err     error
98}
99
100var _ TApplicationException = (*tApplicationException)(nil)
101
102func (tApplicationException) TExceptionType() TExceptionType {
103	return TExceptionTypeApplication
104}
105
106func (e tApplicationException) Error() string {
107	if e.message != "" {
108		return e.message
109	}
110	return defaultApplicationExceptionMessage[e.type_]
111}
112
113func (e tApplicationException) Unwrap() error {
114	return e.err
115}
116
117func NewTApplicationException(type_ int32, message string) TApplicationException {
118	return &tApplicationException{message, type_, nil}
119}
120
121func NewValidationException(type_ int32, check string, field string, message string) TApplicationException {
122	return &tApplicationException{
123		type_:   type_,
124		message: message,
125		err:     &ValidationError{message: message, check: check, fieldSymbol: field},
126	}
127}
128
129func (p *tApplicationException) TypeId() int32 {
130	return p.type_
131}
132
133func (p *tApplicationException) Read(ctx context.Context, iprot TProtocol) error {
134	// TODO: this should really be generated by the compiler
135	_, err := iprot.ReadStructBegin(ctx)
136	if err != nil {
137		return err
138	}
139
140	message := ""
141	type_ := int32(UNKNOWN_APPLICATION_EXCEPTION)
142
143	for {
144		_, ttype, id, err := iprot.ReadFieldBegin(ctx)
145		if err != nil {
146			return err
147		}
148		if ttype == STOP {
149			break
150		}
151		switch id {
152		case 1:
153			if ttype == STRING {
154				if message, err = iprot.ReadString(ctx); err != nil {
155					return err
156				}
157			} else {
158				if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil {
159					return err
160				}
161			}
162		case 2:
163			if ttype == I32 {
164				if type_, err = iprot.ReadI32(ctx); err != nil {
165					return err
166				}
167			} else {
168				if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil {
169					return err
170				}
171			}
172		default:
173			if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil {
174				return err
175			}
176		}
177		if err = iprot.ReadFieldEnd(ctx); err != nil {
178			return err
179		}
180	}
181	if err := iprot.ReadStructEnd(ctx); err != nil {
182		return err
183	}
184
185	p.message = message
186	p.type_ = type_
187
188	return nil
189}
190
191func (p *tApplicationException) Write(ctx context.Context, oprot TProtocol) (err error) {
192	err = oprot.WriteStructBegin(ctx, "TApplicationException")
193	if err != nil {
194		return
195	}
196	if len(p.Error()) > 0 {
197		err = oprot.WriteFieldBegin(ctx, "message", STRING, 1)
198		if err != nil {
199			return
200		}
201		err = oprot.WriteString(ctx, p.Error())
202		if err != nil {
203			return
204		}
205		err = oprot.WriteFieldEnd(ctx)
206		if err != nil {
207			return
208		}
209	}
210	err = oprot.WriteFieldBegin(ctx, "type", I32, 2)
211	if err != nil {
212		return
213	}
214	err = oprot.WriteI32(ctx, p.type_)
215	if err != nil {
216		return
217	}
218	err = oprot.WriteFieldEnd(ctx)
219	if err != nil {
220		return
221	}
222	err = oprot.WriteFieldStop(ctx)
223	if err != nil {
224		return
225	}
226	err = oprot.WriteStructEnd(ctx)
227	return
228}
229