You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2021/09/25 05:18:16 UTC

[shardingsphere] branch master updated: Add override argument interceptor (#12684)

This is an automated email from the ASF dual-hosted git repository.

zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 5b31bd6  Add override argument interceptor (#12684)
5b31bd6 is described below

commit 5b31bd6d3107f8bf8c4aae2f0908ca9eba33aecf
Author: Dachuan J <46...@users.noreply.github.com>
AuthorDate: Sat Sep 25 13:17:35 2021 +0800

    Add override argument interceptor (#12684)
    
    * Add override argument interceptor
    
    * Fix code style
---
 .../transformer/ShardingSphereTransformer.java     |  44 +++++++--
 .../ClassStaticMethodInterceptorArgsOverride.java  | 102 ++++++++++++++++++++
 .../InstanceMethodInterceptorArgsOverride.java     | 105 +++++++++++++++++++++
 ...seClassStaticMethodInterceptorArgsOverride.java |  31 ++++++
 ...mposeInstanceMethodInterceptorArgsOverride.java |  30 ++++++
 5 files changed, 305 insertions(+), 7 deletions(-)

diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/bytebuddy/transformer/ShardingSphereTransformer.java b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/bytebuddy/transformer/ShardingSphereTransformer.java
index fca066b..96c6420 100644
--- a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/bytebuddy/transformer/ShardingSphereTransformer.java
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/bytebuddy/transformer/ShardingSphereTransformer.java
@@ -39,11 +39,15 @@ import org.apache.shardingsphere.agent.api.point.InstanceMethodPoint;
 import org.apache.shardingsphere.agent.api.point.PluginInterceptorPoint;
 import org.apache.shardingsphere.agent.core.plugin.PluginLoader;
 import org.apache.shardingsphere.agent.core.plugin.interceptor.ClassStaticMethodAroundInterceptor;
+import org.apache.shardingsphere.agent.core.plugin.interceptor.ClassStaticMethodInterceptorArgsOverride;
 import org.apache.shardingsphere.agent.core.plugin.interceptor.ConstructorInterceptor;
 import org.apache.shardingsphere.agent.core.plugin.interceptor.InstanceMethodAroundInterceptor;
+import org.apache.shardingsphere.agent.core.plugin.interceptor.InstanceMethodInterceptorArgsOverride;
 import org.apache.shardingsphere.agent.core.plugin.interceptor.compose.ComposeClassStaticMethodAroundInterceptor;
+import org.apache.shardingsphere.agent.core.plugin.interceptor.compose.ComposeClassStaticMethodInterceptorArgsOverride;
 import org.apache.shardingsphere.agent.core.plugin.interceptor.compose.ComposeConstructorInterceptor;
 import org.apache.shardingsphere.agent.core.plugin.interceptor.compose.ComposeInstanceMethodAroundInterceptor;
+import org.apache.shardingsphere.agent.core.plugin.interceptor.compose.ComposeInstanceMethodInterceptorArgsOverride;
 
 import java.util.Collection;
 import java.util.LinkedList;
@@ -86,7 +90,7 @@ public final class ShardingSphereTransformer implements Transformer {
                     if (constructorPointList.isEmpty()) {
                         return null;
                     }
-                    if (constructorPointList.size() == 1) {
+                    if (1 == constructorPointList.size()) {
                         return new ShardingSphereTransformationPoint<>(methodDescription, new ConstructorInterceptor(pluginLoader.getOrCreateInstance(constructorPointList.get(0).getAdvice())));
                     } else {
                         List<ConstructorAdvice> constructorAdvices = constructorPointList.stream()
@@ -137,16 +141,30 @@ public final class ShardingSphereTransformer implements Transformer {
         if (classStaticMethodPoints.isEmpty()) {
             return null;
         }
-        if (classStaticMethodPoints.size() == 1) {
-            return new ShardingSphereTransformationPoint<>(methodDescription, new ClassStaticMethodAroundInterceptor(pluginLoader.getOrCreateInstance(classStaticMethodPoints.get(0).getAdvice())));
+        if (1 == classStaticMethodPoints.size()) {
+            if (classStaticMethodPoints.get(0).isOverrideArgs()) {
+                return new ShardingSphereTransformationPoint<>(methodDescription, 
+                        new ClassStaticMethodInterceptorArgsOverride(pluginLoader.getOrCreateInstance(classStaticMethodPoints.get(0).getAdvice())));
+            } else {
+                return new ShardingSphereTransformationPoint<>(methodDescription, 
+                        new ClassStaticMethodAroundInterceptor(pluginLoader.getOrCreateInstance(classStaticMethodPoints.get(0).getAdvice())));
+            }
         } else {
             Collection<ClassStaticMethodAroundAdvice> classStaticMethodAroundAdvices = new LinkedList<>();
+            boolean isArgsOverride = false;
             for (ClassStaticMethodPoint point : classStaticMethodPoints) {
+                if (point.isOverrideArgs()) {
+                    isArgsOverride = true;
+                }
                 if (null != point.getAdvice()) {
                     classStaticMethodAroundAdvices.add(pluginLoader.getOrCreateInstance(point.getAdvice()));
                 }
             }
-            return new ShardingSphereTransformationPoint<>(methodDescription, new ComposeClassStaticMethodAroundInterceptor(classStaticMethodAroundAdvices));
+            if (isArgsOverride) {
+                return new ShardingSphereTransformationPoint<>(methodDescription, new ComposeClassStaticMethodInterceptorArgsOverride(classStaticMethodAroundAdvices));
+            } else {
+                return new ShardingSphereTransformationPoint<>(methodDescription, new ComposeClassStaticMethodAroundInterceptor(classStaticMethodAroundAdvices));
+            }
         }
     }
     
@@ -175,16 +193,28 @@ public final class ShardingSphereTransformer implements Transformer {
         if (instanceMethodPoints.isEmpty()) {
             return null;
         }
-        if (instanceMethodPoints.size() == 1) {
-            return new ShardingSphereTransformationPoint<>(methodDescription, new InstanceMethodAroundInterceptor(pluginLoader.getOrCreateInstance(instanceMethodPoints.get(0).getAdvice())));
+        if (1 == instanceMethodPoints.size()) {
+            if (instanceMethodPoints.get(0).isOverrideArgs()) {
+                return new ShardingSphereTransformationPoint<>(methodDescription, new InstanceMethodInterceptorArgsOverride(pluginLoader.getOrCreateInstance(instanceMethodPoints.get(0).getAdvice())));
+            } else {
+                return new ShardingSphereTransformationPoint<>(methodDescription, new InstanceMethodAroundInterceptor(pluginLoader.getOrCreateInstance(instanceMethodPoints.get(0).getAdvice())));
+            }      
         } else {
             Collection<InstanceMethodAroundAdvice> instanceMethodAroundAdvices = new LinkedList<>();
+            boolean isArgsOverride = false;
             for (InstanceMethodPoint point : instanceMethodPoints) {
+                if (point.isOverrideArgs()) {
+                    isArgsOverride = true;
+                }
                 if (null != point.getAdvice()) {
                     instanceMethodAroundAdvices.add(pluginLoader.getOrCreateInstance(point.getAdvice()));
                 }
             }
-            return new ShardingSphereTransformationPoint<>(methodDescription, new ComposeInstanceMethodAroundInterceptor(instanceMethodAroundAdvices));
+            if (isArgsOverride) {
+                return new ShardingSphereTransformationPoint<>(methodDescription, new ComposeInstanceMethodInterceptorArgsOverride(instanceMethodAroundAdvices));
+            } else {
+                return new ShardingSphereTransformationPoint<>(methodDescription, new ComposeInstanceMethodAroundInterceptor(instanceMethodAroundAdvices));
+            }
         }
     }
 }
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/ClassStaticMethodInterceptorArgsOverride.java b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/ClassStaticMethodInterceptorArgsOverride.java
new file mode 100644
index 0000000..8d6bf6d
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/ClassStaticMethodInterceptorArgsOverride.java
@@ -0,0 +1,102 @@
+/*
+ * 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.shardingsphere.agent.core.plugin.interceptor;
+
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import net.bytebuddy.implementation.bind.annotation.AllArguments;
+import net.bytebuddy.implementation.bind.annotation.Morph;
+import net.bytebuddy.implementation.bind.annotation.Origin;
+import net.bytebuddy.implementation.bind.annotation.RuntimeType;
+import org.apache.shardingsphere.agent.api.advice.ClassStaticMethodAroundAdvice;
+import org.apache.shardingsphere.agent.api.advice.OverrideArgsInvoker;
+import org.apache.shardingsphere.agent.api.result.MethodInvocationResult;
+import org.apache.shardingsphere.agent.core.plugin.PluginContext;
+
+import java.lang.reflect.Method;
+
+/**
+ * Proxy class for ByteBuddy to intercept methods of target and weave pre- and post-method around the target method with args override.
+ */
+@RequiredArgsConstructor
+@Slf4j
+public class ClassStaticMethodInterceptorArgsOverride {
+    
+    private final ClassStaticMethodAroundAdvice classStaticMethodAroundAdvice;
+    
+    private boolean needCall = true;
+    
+    /**
+     * Only intercept static method.
+     *
+     * @param klass the class of target
+     * @param method the intercepted method
+     * @param args the all arguments of method
+     * @param callable the origin method invocation
+     * @return the return value of target invocation
+     */
+    @RuntimeType
+    @SneakyThrows
+    public Object intercept(@Origin final Class<?> klass, @Origin final Method method, @AllArguments final Object[] args, @Morph final OverrideArgsInvoker callable) {
+        MethodInvocationResult methodResult = new MethodInvocationResult();
+        Object result;
+        needCall = classStaticMethodAroundAdvice.disableCheck() || PluginContext.isPluginEnabled();
+        try {
+            if (needCall) {
+                classStaticMethodAroundAdvice.beforeMethod(klass, method, args, methodResult);
+            }
+            // CHECKSTYLE:OFF
+        } catch (final Throwable ex) {
+            // CHECKSTYLE:ON
+            log.error("Failed to execute the pre-method of method[{}] in class[{}]", method.getName(), klass, ex);
+        }
+        try {
+            if (methodResult.isRebased()) {
+                result = methodResult.getResult();
+            } else {
+                result = callable.call(args);
+            }
+            methodResult.rebase(result);
+            // CHECKSTYLE:OFF
+        } catch (final Throwable ex) {
+            // CHECKSTYLE:ON
+            try {
+                if (needCall) {
+                    classStaticMethodAroundAdvice.onThrowing(klass, method, args, ex);
+                }
+                // CHECKSTYLE:OFF
+            } catch (final Throwable ignored) {
+                // CHECKSTYLE:ON
+                log.error("Failed to execute the error handler of method[{}] in class[{}]", method.getName(), klass, ex);
+            }
+            throw ex;
+        } finally {
+            try {
+                if (needCall) {
+                    classStaticMethodAroundAdvice.afterMethod(klass, method, args, methodResult);
+                }
+                // CHECKSTYLE:OFF
+            } catch (final Throwable ex) {
+                // CHECKSTYLE:ON
+                log.error("Failed to execute the post-method of method[{}] in class[{}]", method.getName(), klass, ex);
+            }
+        }
+        return methodResult.isRebased() ? methodResult.getResult() : result;
+    }
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/InstanceMethodInterceptorArgsOverride.java b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/InstanceMethodInterceptorArgsOverride.java
new file mode 100644
index 0000000..38d78c1
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/InstanceMethodInterceptorArgsOverride.java
@@ -0,0 +1,105 @@
+/*
+ * 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.shardingsphere.agent.core.plugin.interceptor;
+
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import net.bytebuddy.implementation.bind.annotation.AllArguments;
+import net.bytebuddy.implementation.bind.annotation.Morph;
+import net.bytebuddy.implementation.bind.annotation.Origin;
+import net.bytebuddy.implementation.bind.annotation.RuntimeType;
+import net.bytebuddy.implementation.bind.annotation.This;
+import org.apache.shardingsphere.agent.api.advice.AdviceTargetObject;
+import org.apache.shardingsphere.agent.api.advice.InstanceMethodAroundAdvice;
+import org.apache.shardingsphere.agent.api.advice.OverrideArgsInvoker;
+import org.apache.shardingsphere.agent.api.result.MethodInvocationResult;
+import org.apache.shardingsphere.agent.core.plugin.PluginContext;
+
+import java.lang.reflect.Method;
+
+/**
+ * Proxy class for ByteBuddy to intercept methods of target and weave pre- and post-method around the target method with args override.
+ */
+@RequiredArgsConstructor
+@Slf4j
+public class InstanceMethodInterceptorArgsOverride {
+    
+    private final InstanceMethodAroundAdvice instanceMethodAroundAdvice;
+    
+    private boolean needCall = true;
+    
+    /**
+     * Only intercept instance method.
+     *
+     * @param target the target object
+     * @param method the intercepted method
+     * @param args the all arguments of method
+     * @param callable the origin method invocation
+     * @return the return value of target invocation
+     */
+    @RuntimeType
+    @SneakyThrows
+    public Object intercept(@This final Object target, @Origin final Method method, @AllArguments final Object[] args, @Morph final OverrideArgsInvoker callable) {
+        AdviceTargetObject instance = (AdviceTargetObject) target;
+        MethodInvocationResult methodResult = new MethodInvocationResult();
+        Object result;
+        needCall = instanceMethodAroundAdvice.disableCheck() || PluginContext.isPluginEnabled();
+        try {
+            if (needCall) {
+                instanceMethodAroundAdvice.beforeMethod(instance, method, args, methodResult);
+            }
+            // CHECKSTYLE:OFF
+        } catch (final Throwable ex) {
+            // CHECKSTYLE:ON
+            log.error("Failed to execute the pre-method of method[{}] in class[{}]", method.getName(), target.getClass(), ex);
+        }
+        try {
+            if (methodResult.isRebased()) {
+                result = methodResult.getResult();
+            } else {
+                result = callable.call(args);
+            }
+            methodResult.rebase(result);
+            // CHECKSTYLE:OFF
+        } catch (final Throwable ex) {
+            // CHECKSTYLE:ON
+            try {
+                if (needCall) {
+                    instanceMethodAroundAdvice.onThrowing(instance, method, args, ex);
+                }
+                // CHECKSTYLE:OFF
+            } catch (final Throwable ignored) {
+                // CHECKSTYLE:ON
+                log.error("Failed to execute the error handler of method[{}] in class[{}]", method.getName(), target.getClass(), ex);
+            }
+            throw ex;
+        } finally {
+            try {
+                if (needCall) {
+                    instanceMethodAroundAdvice.afterMethod(instance, method, args, methodResult);
+                }
+                // CHECKSTYLE:OFF
+            } catch (final Throwable ex) {
+                // CHECKSTYLE:ON
+                log.error("Failed to execute the post-method of method[{}] in class[{}]", method.getName(), target.getClass(), ex);
+            }
+        }
+        return methodResult.isRebased() ? methodResult.getResult() : result;
+    }
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/compose/ComposeClassStaticMethodInterceptorArgsOverride.java b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/compose/ComposeClassStaticMethodInterceptorArgsOverride.java
new file mode 100644
index 0000000..c5ec833
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/compose/ComposeClassStaticMethodInterceptorArgsOverride.java
@@ -0,0 +1,31 @@
+/*
+ * 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.shardingsphere.agent.core.plugin.interceptor.compose;
+
+import org.apache.shardingsphere.agent.api.advice.ClassStaticMethodAroundAdvice;
+import org.apache.shardingsphere.agent.core.bytebuddy.transformer.advice.ComposeClassStaticMethodAroundAdvice;
+import org.apache.shardingsphere.agent.core.plugin.interceptor.ClassStaticMethodInterceptorArgsOverride;
+
+import java.util.Collection;
+
+public final class ComposeClassStaticMethodInterceptorArgsOverride extends ClassStaticMethodInterceptorArgsOverride {
+    
+    public ComposeClassStaticMethodInterceptorArgsOverride(final Collection<ClassStaticMethodAroundAdvice> instanceMethodAroundAdvices) {
+        super(new ComposeClassStaticMethodAroundAdvice(instanceMethodAroundAdvices));
+    }
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/compose/ComposeInstanceMethodInterceptorArgsOverride.java b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/compose/ComposeInstanceMethodInterceptorArgsOverride.java
new file mode 100644
index 0000000..95a239f
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/interceptor/compose/ComposeInstanceMethodInterceptorArgsOverride.java
@@ -0,0 +1,30 @@
+/*
+ * 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.shardingsphere.agent.core.plugin.interceptor.compose;
+
+import org.apache.shardingsphere.agent.api.advice.InstanceMethodAroundAdvice;
+import org.apache.shardingsphere.agent.core.bytebuddy.transformer.advice.ComposeInstanceMethodAroundAdvice;
+import org.apache.shardingsphere.agent.core.plugin.interceptor.InstanceMethodInterceptorArgsOverride;
+
+import java.util.Collection;
+
+public class ComposeInstanceMethodInterceptorArgsOverride extends InstanceMethodInterceptorArgsOverride {
+    public ComposeInstanceMethodInterceptorArgsOverride(final Collection<InstanceMethodAroundAdvice> instanceMethodAroundAdvices) {
+        super(new ComposeInstanceMethodAroundAdvice(instanceMethodAroundAdvices));
+    }
+}