Merge pull request #102 from aliiohs/feature/FixDateNilBug
Fix: date nil bug
diff --git a/README.md b/README.md
index 67157ac..019882c 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
---
-It's a golang hessian library used by [Apache/dubbo-go](github.com/apache/dubbo-go).
+It's a golang hessian library used by [Apache/dubbo-go](https://github.com/apache/dubbo-go).
## Feature List
diff --git a/go.sum b/go.sum
index dd2e8c8..e009cc5 100644
--- a/go.sum
+++ b/go.sum
@@ -2,8 +2,6 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dubbogo/gost v1.0.1-0.20190709080436-ae4ac3e96ad1 h1:RrdI0SvwHR2DKNLJj+heaIbeb9qYig9QlniddKB6ViU=
-github.com/dubbogo/gost v1.0.1-0.20190709080436-ae4ac3e96ad1/go.mod h1:R7wZm1DrmrKGr50mBZVcg6C9ekG8aL5hP+sgWcIDwQg=
github.com/dubbogo/gost v1.1.1 h1:JCM7vx5edPIjDA5ovJTuzEEXuw2t7xLyrlgi2mi5jHI=
github.com/dubbogo/gost v1.1.1/go.mod h1:R7wZm1DrmrKGr50mBZVcg6C9ekG8aL5hP+sgWcIDwQg=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
diff --git a/hessian.go b/hessian.go
index 1811c55..8fb34ae 100644
--- a/hessian.go
+++ b/hessian.go
@@ -17,7 +17,6 @@
import (
"bufio"
"encoding/binary"
- "reflect"
"time"
)
@@ -77,12 +76,13 @@
if header.ResponseStatus == Zero {
return packRequest(service, header, body)
}
- return packResponse(header, map[string]string{}, body)
+ return packResponse(header, body)
+
case PackageRequest, PackageRequest_TwoWay:
return packRequest(service, header, body)
case PackageResponse:
- return packResponse(header, map[string]string{}, body)
+ return packResponse(header, body)
default:
return nil, perrors.Errorf("Unrecognised message type: %v", header.Type)
@@ -175,16 +175,15 @@
switch h.pkgType & 0x2f {
case PackageResponse | PackageHeartbeat | PackageResponse_Exception, PackageResponse | PackageResponse_Exception:
- rsp, ok := rspObj.(*Response)
- if !ok {
- return perrors.Errorf("@rspObj is not *Response, it is %s", reflect.TypeOf(rspObj).String())
- }
- rsp.Exception = ErrJavaException
decoder := NewDecoder(buf[:])
exception, err := decoder.Decode()
if err != nil {
return perrors.WithStack(err)
}
+ rsp, ok := rspObj.(*Response)
+ if !ok {
+ return perrors.Errorf("java exception:%s", exception.(string))
+ }
rsp.Exception = perrors.Errorf("java exception:%s", exception.(string))
return nil
case PackageRequest | PackageHeartbeat, PackageResponse | PackageHeartbeat:
@@ -196,11 +195,7 @@
}
case PackageResponse:
if rspObj != nil {
- rsp, ok := rspObj.(*Response)
- if !ok {
- rsp = &Response{RspObj: rspObj}
- }
- if err = unpackResponseBody(buf, rsp); err != nil {
+ if err = unpackResponseBody(buf, rspObj); err != nil {
return perrors.WithStack(err)
}
}
diff --git a/java_exception.go b/java_exception.go
index 010a6dc..abe725d 100644
--- a/java_exception.go
+++ b/java_exception.go
@@ -17,6 +17,7 @@
import "github.com/dubbogo/hessian2/java_exception"
func init() {
+ RegisterPOJO(&java_exception.Method{})
RegisterPOJO(&java_exception.Class{})
RegisterPOJO(&java_exception.Throwable{})
RegisterPOJO(&java_exception.Exception{})
@@ -104,4 +105,7 @@
RegisterPOJO(&java_exception.IllegalFormatCodePointException{})
RegisterPOJO(&java_exception.MissingFormatArgumentException{})
RegisterPOJO(&java_exception.MissingFormatWidthException{})
+ RegisterPOJO(&java_exception.DubboGenericException{})
+ RegisterPOJO(&java_exception.IncompleteAnnotationException{})
+ RegisterPOJO(&java_exception.AnnotationTypeMismatchException{})
}
diff --git a/java_exception/annotation_type_mismatch_exception.go b/java_exception/annotation_type_mismatch_exception.go
new file mode 100644
index 0000000..e1b44ff
--- /dev/null
+++ b/java_exception/annotation_type_mismatch_exception.go
@@ -0,0 +1,37 @@
+// Copyright 2016-2019 yiduwangkai@gmail.com
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java_exception
+
+type AnnotationTypeMismatchException struct {
+ SerialVersionUID int64
+ DetailMessage string
+ StackTrace []StackTraceElement
+ FoundType string
+ Element Method
+ SuppressedExceptions []Throwabler
+ Cause Throwabler
+}
+
+func NewAnnotationTypeMismatchException(detailMessage string) *AnnotationTypeMismatchException {
+ return &AnnotationTypeMismatchException{DetailMessage: detailMessage, StackTrace: []StackTraceElement{}}
+}
+
+func (e AnnotationTypeMismatchException) Error() string {
+ return e.DetailMessage
+}
+
+func (AnnotationTypeMismatchException) JavaClassName() string {
+ return "java.lang.annotation.AnnotationTypeMismatchException"
+}
diff --git a/java_exception/dubbo_generic_exception.go b/java_exception/dubbo_generic_exception.go
new file mode 100644
index 0000000..83cfc8b
--- /dev/null
+++ b/java_exception/dubbo_generic_exception.go
@@ -0,0 +1,37 @@
+// Copyright 2016-2019 tianying Pan
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java_exception
+
+type DubboGenericException struct {
+ SerialVersionUID int64
+ DetailMessage string
+ SuppressedExceptions []Throwabler
+ StackTrace []StackTraceElement
+ Cause Throwabler
+ ExceptionClass string
+ ExceptionMessage string
+}
+
+func NewDubboGenericException(exceptionClass, exceptionMessage string) *DubboGenericException {
+ return &DubboGenericException{ExceptionClass: exceptionClass, ExceptionMessage: exceptionMessage}
+}
+
+func (e DubboGenericException) Error() string {
+ return e.DetailMessage
+}
+
+func (DubboGenericException) JavaClassName() string {
+ return "com.alibaba.dubbo.rpc.service.GenericException"
+}
diff --git a/java_exception/exception.go b/java_exception/exception.go
index 2a458a2..73a4477 100644
--- a/java_exception/exception.go
+++ b/java_exception/exception.go
@@ -90,6 +90,15 @@
Name string
}
+type Method struct {
+ Name string
+}
+
+
+func (Method) JavaClassName() string {
+ return "java.lang.reflect.Method"
+}
+
func (Class) JavaClassName() string {
return "java.lang.Class"
}
diff --git a/java_exception/incomplete_annotation_exception.go b/java_exception/incomplete_annotation_exception.go
new file mode 100644
index 0000000..b18378a
--- /dev/null
+++ b/java_exception/incomplete_annotation_exception.go
@@ -0,0 +1,37 @@
+// Copyright 2016-2019 yiduwangkai@gmail.com
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java_exception
+
+type IncompleteAnnotationException struct {
+ SerialVersionUID int64
+ DetailMessage string
+ StackTrace []StackTraceElement
+ ElementName string
+ AnnotationType Class
+ SuppressedExceptions []Throwabler
+ Cause Throwabler
+}
+
+func NewIncompleteAnnotationException(detailMessage string) *IncompleteAnnotationException {
+ return &IncompleteAnnotationException{DetailMessage: detailMessage, StackTrace: []StackTraceElement{}}
+}
+
+func (e IncompleteAnnotationException) Error() string {
+ return e.DetailMessage
+}
+
+func (IncompleteAnnotationException) JavaClassName() string {
+ return "java.lang.annotation.IncompleteAnnotationException"
+}
diff --git a/java_exception_test.go b/java_exception_test.go
index bf5b06e..6af7841 100644
--- a/java_exception_test.go
+++ b/java_exception_test.go
@@ -106,6 +106,9 @@
doTestException(t, "throw_IllegalFormatCodePointException", "Code point = 0x1")
doTestException(t, "throw_MissingFormatArgumentException", "Format specifier 'MissingFormatArgumentException'")
doTestException(t, "throw_MissingFormatWidthException", "MissingFormatWidthException")
+ doTestException(t, "throw_DubboGenericException", "DubboGenericException")
+ doTestException(t, "throw_IncompleteAnnotationException", "java.lang.Override missing element IncompleteAnnotationException")
+ doTestException(t, "throw_AnnotationTypeMismatchException", "Incorrectly typed data found for annotation element null (Found data of type AnnotationTypeMismatchException)")
}
func doTestException(t *testing.T, method, content string) {
diff --git a/request.go b/request.go
index 58cc051..d7b2d84 100644
--- a/request.go
+++ b/request.go
@@ -146,20 +146,43 @@
return types, nil
}
+type Request struct {
+ Params interface{}
+ Attachments map[string]string
+}
+
+// NewRequest create a new Request
+func NewRequest(params interface{}, atta map[string]string) *Request {
+ if atta == nil {
+ atta = make(map[string]string)
+ }
+ return &Request{
+ Params: params,
+ Attachments: atta,
+ }
+}
+
+func EnsureRequest(body interface{}) *Request {
+ if req, ok := body.(*Request); ok {
+ return req
+ }
+ return NewRequest(body, nil)
+}
+
// dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/codec/ExchangeCodec.java
// v2.5.4 line 204 encodeRequest
-// todo: attachments
-func packRequest(service Service, header DubboHeader, params interface{}) ([]byte, error) {
+func packRequest(service Service, header DubboHeader, req interface{}) ([]byte, error) {
var (
- err error
- types string
- byteArray []byte
- version string
- pkgLen int
- serviceParams map[string]string
+ err error
+ types string
+ byteArray []byte
+ version string
+ pkgLen int
)
- args, ok := params.([]interface{})
+ request := EnsureRequest(req)
+
+ args, ok := request.Params.([]interface{})
if !ok {
return nil, perrors.Errorf("@params is not of type: []interface{}")
}
@@ -212,18 +235,17 @@
encoder.Encode(v)
}
- serviceParams = make(map[string]string)
- serviceParams[PATH_KEY] = service.Path
- serviceParams[GROUP_KEY] = service.Group
- serviceParams[INTERFACE_KEY] = service.Interface
+ request.Attachments[PATH_KEY] = service.Path
+ request.Attachments[GROUP_KEY] = service.Group
+ request.Attachments[INTERFACE_KEY] = service.Interface
if len(version) != 0 {
- serviceParams[VERSION_KEY] = version
+ request.Attachments[VERSION_KEY] = version
}
if service.Timeout != 0 {
- serviceParams[TIMEOUT_KEY] = strconv.Itoa(int(service.Timeout / time.Millisecond))
+ request.Attachments[TIMEOUT_KEY] = strconv.Itoa(int(service.Timeout / time.Millisecond))
}
- encoder.Encode(serviceParams)
+ encoder.Encode(request.Attachments)
END:
byteArray = encoder.Buffer()
diff --git a/response.go b/response.go
index da9bb34..3ca0219 100644
--- a/response.go
+++ b/response.go
@@ -28,19 +28,43 @@
)
type Response struct {
- RspObj interface{}
- Exception error
- //Attachments map[string]string
+ RspObj interface{}
+ Exception error
+ Attachments map[string]string
+}
+
+// NewResponse create a new Response
+func NewResponse(rspObj interface{}, exception error, attachments map[string]string) *Response {
+ if attachments == nil {
+ attachments = make(map[string]string)
+ }
+ return &Response{
+ RspObj: rspObj,
+ Exception: exception,
+ Attachments: attachments,
+ }
+}
+
+func EnsureResponse(body interface{}) *Response {
+ if res, ok := body.(*Response); ok {
+ return res
+ }
+ if exp, ok := body.(error); ok {
+ return NewResponse(nil, exp, nil)
+ }
+ return NewResponse(body, nil, nil)
}
// dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/codec/ExchangeCodec.java
// v2.7.1 line 256 encodeResponse
// hessian encode response
-func packResponse(header DubboHeader, attachments map[string]string, ret interface{}) ([]byte, error) {
+func packResponse(header DubboHeader, ret interface{}) ([]byte, error) {
var (
byteArray []byte
)
+ response := EnsureResponse(ret)
+
hb := header.Type == PackageHeartbeat
// magic
@@ -70,7 +94,7 @@
// com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec.DubboCodec.java
// v2.7.1 line191 encodeResponseData
- atta := isSupportResponseAttachment(attachments[DUBBO_VERSION_KEY])
+ atta := isSupportResponseAttachment(response.Attachments[DUBBO_VERSION_KEY])
var resWithException, resValue, resNullValue int32
if atta {
@@ -83,35 +107,33 @@
resNullValue = RESPONSE_NULL_VALUE
}
- if e, ok := ret.(error); ok { // throw error
+ if response.Exception != nil { // throw error
encoder.Encode(resWithException)
- if t, ok := e.(java_exception.Throwabler); ok {
+ if t, ok := response.Exception.(java_exception.Throwabler); ok {
encoder.Encode(t)
} else {
- encoder.Encode(java_exception.NewThrowable(e.Error()))
+ encoder.Encode(java_exception.NewThrowable(response.Exception.Error()))
}
} else {
- if ret == nil {
+ if response.RspObj == nil {
encoder.Encode(resNullValue)
} else {
encoder.Encode(resValue)
- encoder.Encode(ret) // result
+ encoder.Encode(response.RspObj) // result
}
}
if atta {
- encoder.Encode(attachments) // attachments
+ encoder.Encode(response.Attachments) // attachments
}
}
} else {
// com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec
// v2.6.5 line280 encodeResponse
- if e, ok := ret.(error); ok { // throw error
- encoder.Encode(e.Error())
- } else if e, ok := ret.(string); ok {
- encoder.Encode(e)
+ if response.Exception != nil { // throw error
+ encoder.Encode(response.Exception.Error())
} else {
- return nil, perrors.New("Ret must be error or string!")
+ encoder.Encode(response.RspObj)
}
}
@@ -128,8 +150,7 @@
}
// hessian decode response body
-// todo: need to read attachments
-func unpackResponseBody(buf []byte, response *Response) error {
+func unpackResponseBody(buf []byte, resp interface{}) error {
// body
decoder := NewDecoder(buf[:])
rspType, err := decoder.Decode()
@@ -137,17 +158,32 @@
return perrors.WithStack(err)
}
+ response := EnsureResponse(resp)
+
switch rspType {
case RESPONSE_WITH_EXCEPTION, RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS:
expt, err := decoder.Decode()
if err != nil {
return perrors.WithStack(err)
}
+ if rspType == RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS {
+ attachments, err := decoder.Decode()
+ if err != nil {
+ return perrors.WithStack(err)
+ }
+ atta, ok := attachments.(map[string]string)
+ if ok {
+ response.Attachments = atta
+ } else {
+ return perrors.Errorf("get wrong attachments: %+v", atta)
+ }
+ }
+
if e, ok := expt.(error); ok {
response.Exception = e
- return nil
+ } else {
+ response.Exception = perrors.Errorf("got exception: %+v", expt)
}
- response.Exception = perrors.Errorf("got exception: %+v", expt)
return nil
case RESPONSE_VALUE, RESPONSE_VALUE_WITH_ATTACHMENTS:
@@ -155,9 +191,34 @@
if err != nil {
return perrors.WithStack(err)
}
+ if rspType == RESPONSE_VALUE_WITH_ATTACHMENTS {
+ attachments, err := decoder.Decode()
+ if err != nil {
+ return perrors.WithStack(err)
+ }
+ atta, ok := attachments.(map[string]string)
+ if ok {
+ response.Attachments = atta
+ } else {
+ return perrors.Errorf("get wrong attachments: %+v", atta)
+ }
+ }
+
return perrors.WithStack(ReflectResponse(rsp, response.RspObj))
case RESPONSE_NULL_VALUE, RESPONSE_NULL_VALUE_WITH_ATTACHMENTS:
+ if rspType == RESPONSE_NULL_VALUE_WITH_ATTACHMENTS {
+ attachments, err := decoder.Decode()
+ if err != nil {
+ return perrors.WithStack(err)
+ }
+ atta, ok := attachments.(map[string]string)
+ if ok {
+ response.Attachments = atta
+ } else {
+ return perrors.Errorf("get wrong attachments: %+v", atta)
+ }
+ }
return nil
}
diff --git a/test_hessian/pom.xml b/test_hessian/pom.xml
index 031ddd1..e15e228 100644
--- a/test_hessian/pom.xml
+++ b/test_hessian/pom.xml
@@ -25,6 +25,11 @@
<version>9.4.16.v20190411</version>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>dubbo</artifactId>
+ <version>2.6.5</version>
+ </dependency>
</dependencies>
<build>
diff --git a/test_hessian/src/main/java/test/TestThrowable.java b/test_hessian/src/main/java/test/TestThrowable.java
index faf4b64..7e40b7e 100644
--- a/test_hessian/src/main/java/test/TestThrowable.java
+++ b/test_hessian/src/main/java/test/TestThrowable.java
@@ -14,13 +14,16 @@
package test;
+
+import com.alibaba.dubbo.rpc.service.GenericException;
+
import java.io.*;
-import java.lang.*;
-import java.lang.annotation.*;
+import java.lang.annotation.AnnotationTypeMismatchException;
+import java.lang.annotation.IncompleteAnnotationException;
import java.lang.instrument.IllegalClassFormatException;
-import java.lang.invoke.WrongMethodTypeException;
-import java.lang.invoke.LambdaConversionException;
import java.lang.instrument.UnmodifiableClassException;
+import java.lang.invoke.LambdaConversionException;
+import java.lang.invoke.WrongMethodTypeException;
import java.lang.reflect.*;
import java.time.DateTimeException;
import java.time.format.DateTimeParseException;
@@ -390,4 +393,17 @@
public static Object throw_MissingFormatWidthException() {
return new MissingFormatWidthException("MissingFormatWidthException");
}
+
+ public static Object throw_DubboGenericException() {
+ return new GenericException("DubboGenericExceptionClass","DubboGenericException");
+ }
+
+ public static Object throw_IncompleteAnnotationException() {
+ return new IncompleteAnnotationException(Override.class, "IncompleteAnnotationException");
+ }
+
+ public static Object throw_AnnotationTypeMismatchException() {
+ return new AnnotationTypeMismatchException(Override.class.getEnclosingMethod(), "AnnotationTypeMismatchException");
+ }
+
}