add compatible com.alibaba.xxx.RpcInvocation (#5167)

diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/RpcInvocation.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/RpcInvocation.java
new file mode 100644
index 0000000..52ed7dc
--- /dev/null
+++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/RpcInvocation.java
@@ -0,0 +1,203 @@
+/*
+ * 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 com.alibaba.dubbo.rpc;
+
+import com.alibaba.dubbo.common.Constants;
+import com.alibaba.dubbo.common.URL;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class RpcInvocation implements Invocation, Serializable {
+
+    private static final long serialVersionUID = -4355285085441097045L;
+
+    private String methodName;
+
+    private Class<?>[] parameterTypes;
+
+    private Object[] arguments;
+
+    private Map<String, String> attachments;
+
+    private transient Invoker<?> invoker;
+
+    public RpcInvocation() {
+    }
+
+    public RpcInvocation(Invocation invocation, Invoker<?> invoker) {
+        this(invocation.getMethodName(), invocation.getParameterTypes(),
+                invocation.getArguments(), new HashMap<String, String>(invocation.getAttachments()),
+                invocation.getInvoker());
+        if (invoker != null) {
+            URL url = invoker.getUrl();
+            setAttachment(Constants.PATH_KEY, url.getPath());
+            if (url.hasParameter(Constants.INTERFACE_KEY)) {
+                setAttachment(Constants.INTERFACE_KEY, url.getParameter(Constants.INTERFACE_KEY));
+            }
+            if (url.hasParameter(Constants.GROUP_KEY)) {
+                setAttachment(Constants.GROUP_KEY, url.getParameter(Constants.GROUP_KEY));
+            }
+            if (url.hasParameter(Constants.VERSION_KEY)) {
+                setAttachment(Constants.VERSION_KEY, url.getParameter(Constants.VERSION_KEY, "0.0.0"));
+            }
+            if (url.hasParameter(Constants.TIMEOUT_KEY)) {
+                setAttachment(Constants.TIMEOUT_KEY, url.getParameter(Constants.TIMEOUT_KEY));
+            }
+            if (url.hasParameter(Constants.TOKEN_KEY)) {
+                setAttachment(Constants.TOKEN_KEY, url.getParameter(Constants.TOKEN_KEY));
+            }
+            if (url.hasParameter(Constants.APPLICATION_KEY)) {
+                setAttachment(Constants.APPLICATION_KEY, url.getParameter(Constants.APPLICATION_KEY));
+            }
+        }
+    }
+
+    public RpcInvocation(Invocation invocation) {
+        this(invocation.getMethodName(), invocation.getParameterTypes(),
+                invocation.getArguments(), invocation.getAttachments(), invocation.getInvoker());
+    }
+
+    public RpcInvocation(Method method, Object[] arguments) {
+        this(method.getName(), method.getParameterTypes(), arguments, null, null);
+    }
+
+    public RpcInvocation(Method method, Object[] arguments, Map<String, String> attachment) {
+        this(method.getName(), method.getParameterTypes(), arguments, attachment, null);
+    }
+
+    public RpcInvocation(String methodName, Class<?>[] parameterTypes, Object[] arguments) {
+        this(methodName, parameterTypes, arguments, null, null);
+    }
+
+    public RpcInvocation(String methodName, Class<?>[] parameterTypes, Object[] arguments, Map<String, String> attachments) {
+        this(methodName, parameterTypes, arguments, attachments, null);
+    }
+
+    public RpcInvocation(String methodName, Class<?>[] parameterTypes, Object[] arguments, Map<String, String> attachments, Invoker<?> invoker) {
+        this.methodName = methodName;
+        this.parameterTypes = parameterTypes == null ? new Class<?>[0] : parameterTypes;
+        this.arguments = arguments == null ? new Object[0] : arguments;
+        this.attachments = attachments == null ? new HashMap<String, String>() : attachments;
+        this.invoker = invoker;
+    }
+
+    public Invoker<?> getInvoker() {
+        return invoker;
+    }
+
+    public void setInvoker(Invoker<?> invoker) {
+        this.invoker = invoker;
+    }
+
+    public String getMethodName() {
+        return methodName;
+    }
+
+    public void setMethodName(String methodName) {
+        this.methodName = methodName;
+    }
+
+    public Class<?>[] getParameterTypes() {
+        return parameterTypes;
+    }
+
+    public void setParameterTypes(Class<?>[] parameterTypes) {
+        this.parameterTypes = parameterTypes == null ? new Class<?>[0] : parameterTypes;
+    }
+
+    public Object[] getArguments() {
+        return arguments;
+    }
+
+    public void setArguments(Object[] arguments) {
+        this.arguments = arguments == null ? new Object[0] : arguments;
+    }
+
+    public Map<String, String> getAttachments() {
+        return attachments;
+    }
+
+    public void setAttachments(Map<String, String> attachments) {
+        this.attachments = attachments == null ? new HashMap<String, String>() : attachments;
+    }
+
+    public void setAttachment(String key, String value) {
+        if (attachments == null) {
+            attachments = new HashMap<String, String>();
+        }
+        attachments.put(key, value);
+    }
+
+    public void setAttachmentIfAbsent(String key, String value) {
+        if (attachments == null) {
+            attachments = new HashMap<String, String>();
+        }
+        if (!attachments.containsKey(key)) {
+            attachments.put(key, value);
+        }
+    }
+
+    public void addAttachments(Map<String, String> attachments) {
+        if (attachments == null) {
+            return;
+        }
+        if (this.attachments == null) {
+            this.attachments = new HashMap<String, String>();
+        }
+        this.attachments.putAll(attachments);
+    }
+
+    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 String getAttachment(String key) {
+        if (attachments == null) {
+            return null;
+        }
+        return attachments.get(key);
+    }
+
+    public String getAttachment(String key, String defaultValue) {
+        if (attachments == null) {
+            return defaultValue;
+        }
+        String value = attachments.get(key);
+        if (value == null || value.length() == 0) {
+            return defaultValue;
+        }
+        return value;
+    }
+
+    @Override
+    public String toString() {
+        return "RpcInvocation [methodName=" + methodName + ", parameterTypes="
+                + Arrays.toString(parameterTypes) + ", arguments=" + Arrays.toString(arguments)
+                + ", attachments=" + attachments + "]";
+    }
+
+}