blob: f94c001989ed6d4800989d82b6917740f09d43b1 [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.rpc;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.MethodDescriptor;
import org.apache.dubbo.rpc.model.ServiceDescriptor;
import org.apache.dubbo.rpc.model.ServiceRepository;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_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.PATH_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
/**
* RPC Invocation.
*
* @serial Don't change the class name and properties.
*/
public class RpcInvocation implements Invocation, Serializable {
private static final long serialVersionUID = -4355285085441097045L;
private String targetServiceUniqueName;
private String protocolServiceKey;
private String methodName;
private String serviceName;
private transient Class<?>[] parameterTypes;
private String parameterTypesDesc;
private String[] compatibleParamSignatures;
private Object[] arguments;
/**
* Passed to the remote server during RPC call
*/
private Map<String, Object> attachments;
/**
* Only used on the caller side, will not appear on the wire.
*/
private Map<Object, Object> attributes = new HashMap<>();
private transient Invoker<?> invoker;
private transient Class<?> returnType;
private transient Type[] returnTypes;
private transient InvokeMode invokeMode;
public RpcInvocation() {
}
public RpcInvocation(Invocation invocation, Invoker<?> invoker) {
this(invocation.getMethodName(), invocation.getServiceName(), invocation.getProtocolServiceKey(),
invocation.getParameterTypes(), invocation.getArguments(), new HashMap<>(invocation.getObjectAttachments()),
invocation.getInvoker(), invocation.getAttributes());
if (invoker != null) {
URL url = invoker.getUrl();
setAttachment(PATH_KEY, url.getPath());
if (url.hasParameter(INTERFACE_KEY)) {
setAttachment(INTERFACE_KEY, url.getParameter(INTERFACE_KEY));
}
if (url.hasParameter(GROUP_KEY)) {
setAttachment(GROUP_KEY, url.getParameter(GROUP_KEY));
}
if (url.hasParameter(VERSION_KEY)) {
setAttachment(VERSION_KEY, url.getParameter(VERSION_KEY, "0.0.0"));
}
if (url.hasParameter(TIMEOUT_KEY)) {
setAttachment(TIMEOUT_KEY, url.getParameter(TIMEOUT_KEY));
}
if (url.hasParameter(TOKEN_KEY)) {
setAttachment(TOKEN_KEY, url.getParameter(TOKEN_KEY));
}
if (url.hasParameter(APPLICATION_KEY)) {
setAttachment(APPLICATION_KEY, url.getParameter(APPLICATION_KEY));
}
}
this.targetServiceUniqueName = invocation.getTargetServiceUniqueName();
this.protocolServiceKey = invocation.getProtocolServiceKey();
}
public RpcInvocation(Invocation invocation) {
this(invocation.getMethodName(), invocation.getServiceName(), invocation.getProtocolServiceKey(), invocation.getParameterTypes(),
invocation.getArguments(), invocation.getObjectAttachments(), invocation.getInvoker(), invocation.getAttributes());
this.targetServiceUniqueName = invocation.getTargetServiceUniqueName();
}
public RpcInvocation(Method method, String serviceName, String protocolServiceKey, Object[] arguments) {
this(method, serviceName, protocolServiceKey, arguments, null, null);
}
public RpcInvocation(Method method, String serviceName, String protocolServiceKey, Object[] arguments, Map<String, Object> attachment, Map<Object, Object> attributes) {
this(method.getName(), serviceName, protocolServiceKey, method.getParameterTypes(), arguments, attachment, null, attributes);
}
public RpcInvocation(String methodName, String serviceName, String protocolServiceKey, Class<?>[] parameterTypes, Object[] arguments) {
this(methodName, serviceName, protocolServiceKey, parameterTypes, arguments, null, null, null);
}
public RpcInvocation(String methodName, String serviceName, String protocolServiceKey, Class<?>[] parameterTypes, Object[] arguments, Map<String, Object> attachments) {
this(methodName, serviceName, protocolServiceKey, parameterTypes, arguments, attachments, null, null);
}
public RpcInvocation(String methodName, String serviceName, String protocolServiceKey, Class<?>[] parameterTypes, Object[] arguments,
Map<String, Object> attachments, Invoker<?> invoker, Map<Object, Object> attributes) {
this.methodName = methodName;
this.serviceName = serviceName;
this.protocolServiceKey = protocolServiceKey;
this.parameterTypes = parameterTypes == null ? new Class<?>[0] : parameterTypes;
this.arguments = arguments == null ? new Object[0] : arguments;
this.attachments = attachments == null ? new HashMap<>() : attachments;
this.attributes = attributes == null ? new HashMap<>() : attributes;
this.invoker = invoker;
initParameterDesc();
}
private void initParameterDesc() {
ServiceRepository repository = ApplicationModel.getServiceRepository();
if (StringUtils.isNotEmpty(serviceName)) {
ServiceDescriptor serviceDescriptor = repository.lookupService(serviceName);
if (serviceDescriptor != null) {
MethodDescriptor methodDescriptor = serviceDescriptor.getMethod(methodName, parameterTypes);
if (methodDescriptor != null) {
this.parameterTypesDesc = methodDescriptor.getParamDesc();
this.compatibleParamSignatures = methodDescriptor.getCompatibleParamSignatures();
this.returnTypes = methodDescriptor.getReturnTypes();
this.returnType = methodDescriptor.getReturnClass();
}
}
}
if (parameterTypesDesc == null) {
this.parameterTypesDesc = ReflectUtils.getDesc(this.getParameterTypes());
this.compatibleParamSignatures = Stream.of(this.parameterTypes).map(Class::getName).toArray(String[]::new);
this.returnTypes = RpcUtils.getReturnTypes(this);
this.returnType = RpcUtils.getReturnType(this);
}
}
@Override
public Invoker<?> getInvoker() {
return invoker;
}
public void setInvoker(Invoker<?> invoker) {
this.invoker = invoker;
}
@Override
public Object put(Object key, Object value) {
return attributes.put(key, value);
}
@Override
public Object get(Object key) {
return attributes.get(key);
}
@Override
public Map<Object, Object> getAttributes() {
return attributes;
}
@Override
public String getTargetServiceUniqueName() {
return targetServiceUniqueName;
}
@Override
public String getProtocolServiceKey() {
return protocolServiceKey;
}
public void setTargetServiceUniqueName(String targetServiceUniqueName) {
this.targetServiceUniqueName = targetServiceUniqueName;
}
@Override
public String getMethodName() {
return methodName;
}
@Override
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
@Override
public Class<?>[] getParameterTypes() {
return parameterTypes;
}
public void setParameterTypes(Class<?>[] parameterTypes) {
this.parameterTypes = parameterTypes == null ? new Class<?>[0] : parameterTypes;
}
public String getParameterTypesDesc() {
return parameterTypesDesc;
}
public void setParameterTypesDesc(String parameterTypesDesc) {
this.parameterTypesDesc = parameterTypesDesc;
}
@Override
public String[] getCompatibleParamSignatures() {
return compatibleParamSignatures;
}
// parameter signatures can be set independently, it is useful when the service type is not found on caller side and
// the invocation is not generic invocation either.
public void setCompatibleParamSignatures(String[] compatibleParamSignatures) {
this.compatibleParamSignatures = compatibleParamSignatures;
}
@Override
public Object[] getArguments() {
return arguments;
}
public void setArguments(Object[] arguments) {
this.arguments = arguments == null ? new Object[0] : arguments;
}
@Override
public Map<String, Object> getObjectAttachments() {
return attachments;
}
@Override
public void setAttachment(String key, String value) {
setObjectAttachment(key, value);
}
@Deprecated
@Override
public Map<String, String> getAttachments() {
return new AttachmentsAdapter.ObjectToStringMap(attachments);
}
@Deprecated
public void setAttachments(Map<String, String> attachments) {
this.attachments = attachments == null ? new HashMap<>() : new HashMap<>(attachments);
}
public void setObjectAttachments(Map<String, Object> attachments) {
this.attachments = attachments == null ? new HashMap<>() : attachments;
}
@Override
public void setAttachment(String key, Object value) {
setObjectAttachment(key, value);
}
@Override
public void setObjectAttachment(String key, Object value) {
if (attachments == null) {
attachments = new HashMap<>();
}
attachments.put(key, value);
}
@Override
public void setAttachmentIfAbsent(String key, String value) {
setObjectAttachmentIfAbsent(key, value);
}
@Override
public void setAttachmentIfAbsent(String key, Object value) {
setObjectAttachmentIfAbsent(key, value);
}
@Override
public void setObjectAttachmentIfAbsent(String key, Object value) {
if (attachments == null) {
attachments = new HashMap<>();
}
if (!attachments.containsKey(key)) {
attachments.put(key, value);
}
}
@Deprecated
public void addAttachments(Map<String, String> attachments) {
if (attachments == null) {
return;
}
if (this.attachments == null) {
this.attachments = new HashMap<>();
}
this.attachments.putAll(attachments);
}
public void addObjectAttachments(Map<String, Object> attachments) {
if (attachments == null) {
return;
}
if (this.attachments == null) {
this.attachments = new HashMap<>();
}
this.attachments.putAll(attachments);
}
@Deprecated
public void addAttachmentsIfAbsent(Map<String, String> attachments) {
if (attachments == null) {
return;
}
for (Map.Entry<String, String> entry : attachments.entrySet()) {
setAttachmentIfAbsent(entry.getKey(), entry.getValue());
}
}
public void addObjectAttachmentsIfAbsent(Map<String, Object> attachments) {
if (attachments == null) {
return;
}
for (Map.Entry<String, Object> entry : attachments.entrySet()) {
setAttachmentIfAbsent(entry.getKey(), entry.getValue());
}
}
@Override
public String getAttachment(String key) {
if (attachments == null) {
return null;
}
Object value = attachments.get(key);
if (value instanceof String) {
return (String) value;
}
return null;
}
@Override
public Object getObjectAttachment(String key) {
if (attachments == null) {
return null;
}
return attachments.get(key);
}
@Override
@Deprecated
public String getAttachment(String key, String defaultValue) {
if (attachments == null) {
return defaultValue;
}
Object value = attachments.get(key);
if (value instanceof String) {
String strValue = (String) value;
if (StringUtils.isEmpty(strValue)) {
return defaultValue;
} else {
return strValue;
}
}
return null;
}
@Deprecated
@Override
public Object getObjectAttachment(String key, Object defaultValue) {
if (attachments == null) {
return defaultValue;
}
Object value = attachments.get(key);
if (value == null) {
return defaultValue;
}
return value;
}
public Class<?> getReturnType() {
return returnType;
}
public void setReturnType(Class<?> returnType) {
this.returnType = returnType;
}
public Type[] getReturnTypes() {
return returnTypes;
}
public void setReturnTypes(Type[] returnTypes) {
this.returnTypes = returnTypes;
}
public InvokeMode getInvokeMode() {
return invokeMode;
}
public void setInvokeMode(InvokeMode invokeMode) {
this.invokeMode = invokeMode;
}
@Override
public String toString() {
return "RpcInvocation [methodName=" + methodName + ", parameterTypes="
+ Arrays.toString(parameterTypes) + ", arguments=" + Arrays.toString(arguments)
+ ", attachments=" + attachments + "]";
}
}