16
16
*/
17
17
package org .apache .dubbo .rpc .protocol .tri .h12 .grpc ;
18
18
19
+ import org .apache .dubbo .common .URL ;
20
+ import org .apache .dubbo .common .config .ConfigurationUtils ;
21
+ import org .apache .dubbo .common .io .StreamUtils ;
22
+ import org .apache .dubbo .common .utils .ArrayUtils ;
19
23
import org .apache .dubbo .remoting .http12 .exception .DecodeException ;
20
24
import org .apache .dubbo .remoting .http12 .exception .EncodeException ;
25
+ import org .apache .dubbo .remoting .http12 .exception .HttpStatusException ;
21
26
import org .apache .dubbo .remoting .http12 .message .HttpMessageCodec ;
22
27
import org .apache .dubbo .remoting .http12 .message .MediaType ;
28
+ import org .apache .dubbo .rpc .model .FrameworkModel ;
29
+ import org .apache .dubbo .rpc .model .MethodDescriptor ;
30
+ import org .apache .dubbo .rpc .model .PackableMethod ;
31
+ import org .apache .dubbo .rpc .model .PackableMethodFactory ;
23
32
24
33
import java .io .IOException ;
25
34
import java .io .InputStream ;
26
35
import java .io .OutputStream ;
27
36
import java .nio .charset .Charset ;
37
+ import java .util .Map ;
38
+ import java .util .concurrent .ConcurrentHashMap ;
28
39
29
- import com .google .protobuf .Message ;
30
-
31
- import static org .apache .dubbo .common .constants .CommonConstants .PROTOBUF_MESSAGE_CLASS_NAME ;
40
+ import static org .apache .dubbo .common .constants .CommonConstants .DEFAULT_KEY ;
41
+ import static org .apache .dubbo .common .constants .CommonConstants .DUBBO_PACKABLE_METHOD_FACTORY ;
32
42
33
43
public class GrpcCompositeCodec implements HttpMessageCodec {
34
44
35
- private final ProtobufHttpMessageCodec protobufHttpMessageCodec ;
45
+ private static final String PACKABLE_METHOD_CACHE = "PACKABLE_METHOD_CACHE" ;
36
46
37
- private final WrapperHttpMessageCodec wrapperHttpMessageCodec ;
47
+ private final URL url ;
38
48
39
- public GrpcCompositeCodec (
40
- ProtobufHttpMessageCodec protobufHttpMessageCodec , WrapperHttpMessageCodec wrapperHttpMessageCodec ) {
41
- this .protobufHttpMessageCodec = protobufHttpMessageCodec ;
42
- this .wrapperHttpMessageCodec = wrapperHttpMessageCodec ;
43
- }
49
+ private final FrameworkModel frameworkModel ;
50
+
51
+ private final String mediaType ;
44
52
45
- public void setEncodeTypes (Class <?>[] encodeTypes ) {
46
- this .wrapperHttpMessageCodec .setEncodeTypes (encodeTypes );
53
+ private PackableMethod packableMethod ;
54
+
55
+ public GrpcCompositeCodec (URL url , FrameworkModel frameworkModel , String mediaType ) {
56
+ this .url = url ;
57
+ this .frameworkModel = frameworkModel ;
58
+ this .mediaType = mediaType ;
47
59
}
48
60
49
- public void setDecodeTypes (Class <?>[] decodeTypes ) {
50
- this .wrapperHttpMessageCodec .setDecodeTypes (decodeTypes );
61
+ public void loadPackableMethod (MethodDescriptor methodDescriptor ) {
62
+ if (methodDescriptor instanceof PackableMethod ) {
63
+ packableMethod = (PackableMethod ) methodDescriptor ;
64
+ return ;
65
+ }
66
+ Map <MethodDescriptor , PackableMethod > cacheMap = (Map <MethodDescriptor , PackableMethod >) url .getServiceModel ()
67
+ .getServiceMetadata ()
68
+ .getAttributeMap ()
69
+ .computeIfAbsent (PACKABLE_METHOD_CACHE , k -> new ConcurrentHashMap <>());
70
+ packableMethod = cacheMap .computeIfAbsent (methodDescriptor , md -> frameworkModel
71
+ .getExtensionLoader (PackableMethodFactory .class )
72
+ .getExtension (ConfigurationUtils .getGlobalConfiguration (url .getApplicationModel ())
73
+ .getString (DUBBO_PACKABLE_METHOD_FACTORY , DEFAULT_KEY ))
74
+ .create (methodDescriptor , url , mediaType ));
51
75
}
52
76
53
77
@ Override
@@ -58,34 +82,38 @@ public void encode(OutputStream outputStream, Object data, Charset charset) thro
58
82
try {
59
83
int compressed = 0 ;
60
84
outputStream .write (compressed );
61
- if (isProtobuf (data )) {
62
- ProtobufWriter .write (protobufHttpMessageCodec , outputStream , data );
63
- return ;
64
- }
65
- // wrapper
66
- wrapperHttpMessageCodec .encode (outputStream , data );
67
- } catch (IOException e ) {
85
+ byte [] bytes = packableMethod .packResponse (data );
86
+ writeLength (outputStream , bytes .length );
87
+ outputStream .write (bytes );
88
+ } catch (HttpStatusException e ) {
89
+ throw e ;
90
+ } catch (Exception e ) {
68
91
throw new EncodeException (e );
69
92
}
70
93
}
71
94
72
95
@ Override
73
96
public Object decode (InputStream inputStream , Class <?> targetType , Charset charset ) throws DecodeException {
74
- if (isProtoClass (targetType )) {
75
- return protobufHttpMessageCodec .decode (inputStream , targetType , charset );
97
+ try {
98
+ byte [] data = StreamUtils .readBytes (inputStream );
99
+ return packableMethod .parseRequest (data );
100
+ } catch (HttpStatusException e ) {
101
+ throw e ;
102
+ } catch (Exception e ) {
103
+ throw new DecodeException (e );
76
104
}
77
- return wrapperHttpMessageCodec .decode (inputStream , targetType , charset );
78
105
}
79
106
80
107
@ Override
81
108
public Object [] decode (InputStream inputStream , Class <?>[] targetTypes , Charset charset ) throws DecodeException {
82
- if (targetTypes .length > 1 ) {
83
- return wrapperHttpMessageCodec .decode (inputStream , targetTypes , charset );
109
+ Object message = decode (inputStream , ArrayUtils .isEmpty (targetTypes ) ? null : targetTypes [0 ], charset );
110
+ if (message instanceof Object []) {
111
+ return (Object []) message ;
84
112
}
85
- return HttpMessageCodec . super . decode ( inputStream , targetTypes , charset ) ;
113
+ return new Object [] { message } ;
86
114
}
87
115
88
- private static void writeLength (OutputStream outputStream , int length ) {
116
+ private void writeLength (OutputStream outputStream , int length ) {
89
117
try {
90
118
outputStream .write (((length >> 24 ) & 0xFF ));
91
119
outputStream .write (((length >> 16 ) & 0xFF ));
@@ -100,39 +128,4 @@ private static void writeLength(OutputStream outputStream, int length) {
100
128
public MediaType mediaType () {
101
129
return MediaType .APPLICATION_GRPC ;
102
130
}
103
-
104
- private static boolean isProtobuf (Object data ) {
105
- if (data == null ) {
106
- return false ;
107
- }
108
- return isProtoClass (data .getClass ());
109
- }
110
-
111
- private static boolean isProtoClass (Class <?> clazz ) {
112
- while (clazz != Object .class && clazz != null ) {
113
- Class <?>[] interfaces = clazz .getInterfaces ();
114
- if (interfaces .length > 0 ) {
115
- for (Class <?> clazzInterface : interfaces ) {
116
- if (PROTOBUF_MESSAGE_CLASS_NAME .equalsIgnoreCase (clazzInterface .getName ())) {
117
- return true ;
118
- }
119
- }
120
- }
121
- clazz = clazz .getSuperclass ();
122
- }
123
- return false ;
124
- }
125
-
126
- /**
127
- * lazy init protobuf class
128
- */
129
- private static class ProtobufWriter {
130
-
131
- private static void write (HttpMessageCodec codec , OutputStream outputStream , Object data ) {
132
- int serializedSize = ((Message ) data ).getSerializedSize ();
133
- // write length
134
- writeLength (outputStream , serializedSize );
135
- codec .encode (outputStream , data );
136
- }
137
- }
138
131
}
0 commit comments