blob: 899939745464eb73121e0447f28595e8fb3efede [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.dubbo.gateway.provider;
import org.apache.dubbo.common.beanutil.JavaBeanDescriptor;
import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil;
import org.apache.dubbo.common.serialize.Cleanable;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.gateway.common.OmnipotentCommonConstants;
import org.apache.dubbo.remoting.Channel;
import org.apache.dubbo.remoting.exchange.Request;
import org.apache.dubbo.remoting.transport.CodecSupport;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation;
import org.apache.dubbo.rpc.protocol.dubbo.DubboCodec;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_VERSION;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHOD_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.gateway.common.OmnipotentCommonConstants.$INVOKE_OMN;
import static org.apache.dubbo.gateway.common.OmnipotentCommonConstants.ORIGIN_GENERIC_PARAMETER_TYPES;
import static org.apache.dubbo.gateway.common.OmnipotentCommonConstants.ORIGIN_GROUP_KEY;
import static org.apache.dubbo.gateway.common.OmnipotentCommonConstants.ORIGIN_PARAMETER_TYPES_DESC;
import static org.apache.dubbo.rpc.Constants.SERIALIZATION_ID_KEY;
public class SnfDecodeableRpcInvocation extends DecodeableRpcInvocation {
private static final String DEFAULT_OMNIPOTENT_SERVICE = OmnipotentService.class.getName();
public SnfDecodeableRpcInvocation(FrameworkModel frameworkModel, Channel channel, Request request, InputStream is, byte id) {
super(frameworkModel, channel, request, is, id);
}
@Override
public Object decode(Channel channel, InputStream input) throws IOException {
ObjectInput in = CodecSupport.getSerialization(serializationType)
.deserialize(channel.getUrl(), input);
this.put(SERIALIZATION_ID_KEY, serializationType);
String dubboVersion = in.readUTF();
request.setVersion(dubboVersion);
setAttachment(DUBBO_VERSION_KEY, dubboVersion);
String path = in.readUTF();
setAttachment(PATH_KEY, path);
String version = in.readUTF();
setAttachment(VERSION_KEY, version);
setMethodName(in.readUTF());
String desc = in.readUTF();
setParameterTypesDesc(desc);
ClassLoader originClassLoader = Thread.currentThread().getContextClassLoader();
try {
Object[] args = DubboCodec.EMPTY_OBJECT_ARRAY;
Class<?>[] pts = DubboCodec.EMPTY_CLASS_ARRAY;
if (desc.length() > 0) {
pts = drawPts(path, version, desc, pts);
if (pts == DubboCodec.EMPTY_CLASS_ARRAY) {
// Service not found ,pts = JavaBeanDescriptor
pts = ReflectUtils.desc2classArray(desc);
}
args = drawArgs(in, pts);
}
setParameterTypes(pts);
setAttachment(ORIGIN_GENERIC_PARAMETER_TYPES, pts);
Map<String, Object> map = in.readAttachments();
Class<?>[] retryPts = null;
if (CollectionUtils.isNotEmptyMap(map)) {
if (map.containsKey(ORIGIN_PARAMETER_TYPES_DESC)) {
String originParameterTypesDesc = map.get(ORIGIN_PARAMETER_TYPES_DESC).toString();
retryPts = drawPts(path, version, originParameterTypesDesc, DubboCodec.EMPTY_CLASS_ARRAY);
boolean snf = (retryPts == DubboCodec.EMPTY_CLASS_ARRAY) && !RpcUtils.isGenericCall(originParameterTypesDesc, getMethodName()) && !RpcUtils.isEcho(originParameterTypesDesc, getMethodName());
if (snf) {
setAttachment(OmnipotentCommonConstants.ORIGIN_PATH_KEY, getAttachment(PATH_KEY));
// Replace serviceName in req with omn
setAttachment(PATH_KEY, DEFAULT_OMNIPOTENT_SERVICE);
setAttachment(INTERFACE_KEY, DEFAULT_OMNIPOTENT_SERVICE);
// version
setAttachment(OmnipotentCommonConstants.ORIGIN_VERSION_KEY, getAttachment(VERSION_KEY));
setAttachment(VERSION_KEY, DEFAULT_VERSION);
// method
setAttachment(OmnipotentCommonConstants.ORIGIN_METHOD_KEY, getMethodName());
setAttachment(METHOD_KEY, $INVOKE_OMN);
setMethodName($INVOKE_OMN);
setParameterTypes(new Class<?>[]{Invocation.class});
// Omn needs to use the default path, version and group,
// and the original value starts with origin to save the variable
map.remove(PATH_KEY);
map.remove(VERSION_KEY);
if (map.containsKey(GROUP_KEY)) {
map.put(ORIGIN_GROUP_KEY, map.get(GROUP_KEY));
map.remove(GROUP_KEY);
}
retryPts = (Class<?>[]) getObjectAttachments().get(ORIGIN_GENERIC_PARAMETER_TYPES);
}
}
addObjectAttachments(map);
}
boolean isConvert = false;
for (Class<?> clazz : pts) {
if (clazz == JavaBeanDescriptor.class) {
isConvert = true;
break;
}
}
// isConvert = snf
if (isConvert) {
setParameterTypes(retryPts);
pts = retryPts;
Object[] newArgs = new Object[args.length];
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof JavaBeanDescriptor) {
newArgs[i] = JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) args[i]);
}
}
args = newArgs;
}
decodeArgument(channel, pts, args);
} catch (ClassNotFoundException e) {
throw new IOException(StringUtils.toString("Read invocation data failed.", e));
} finally {
Thread.currentThread().setContextClassLoader(originClassLoader);
if (in instanceof Cleanable) {
((Cleanable) in).cleanup();
}
}
return this;
}
}