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