This is an automated email from the ASF dual-hosted git repository.
xiaoyu 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 0bfe11e feature: introduce shardingsphere agent (#8307)
0bfe11e is described below
commit 0bfe11eb839d1bb2bda84ae1cf7495eb6c0c8bda
Author: Daming <[email protected]>
AuthorDate: Mon Nov 23 22:54:11 2020 +0800
feature: introduce shardingsphere agent (#8307)
* feature: introduce shardingsphere agent
* replace version with property
* fix checkstyle
* fix javadoc
* fix checkstyle
* fix javadoc
* fix javadoc
---
.../shardingsphere-agent-bootstrap/pom.xml | 26 ++
.../agent/bootstrap/ShardingSphereAgent.java | 28 +-
.../shardingsphere-agent-core/pom.xml | 74 +++++
.../shardingsphere/agent/core/LoggingListener.java | 58 ++++
.../agent/core/ShardingSphereTransformer.java | 103 +++++++
.../agent/core/plugin/PluginAdviceDefine.java | 300 +++++++++++++++++++++
.../agent/core/plugin/PluginLoader.java | 95 +++++++
.../core/plugin/advice/ConstructorAdvice.java} | 26 +-
.../advice/ConstructorMethodInterceptor.java | 54 ++++
.../core/plugin/advice/MethodAroundAdvice.java | 57 ++++
.../plugin/advice/MethodAroundInterceptor.java | 96 +++++++
.../plugin/advice/MethodInvocationResult.java} | 48 ++--
.../core/plugin/advice/OverrideArgsInvoker.java} | 27 +-
.../plugin/advice/StaticMethodAroundAdvice.java | 57 ++++
.../advice/StaticMethodAroundInterceptor.java | 94 +++++++
.../agent/core/plugin/advice/TargetObject.java} | 33 ++-
.../core/plugin/point/ClassStaticMethodPoint.java | 68 +++++
.../agent/core/plugin/point/ConstructorPoint.java | 55 ++++
.../core/plugin/point/InstanceMethodPoint.java | 66 +++++
19 files changed, 1292 insertions(+), 73 deletions(-)
diff --git a/shardingsphere-agent/shardingsphere-agent-bootstrap/pom.xml
b/shardingsphere-agent/shardingsphere-agent-bootstrap/pom.xml
index 53fff43..f263a85 100644
--- a/shardingsphere-agent/shardingsphere-agent-bootstrap/pom.xml
+++ b/shardingsphere-agent/shardingsphere-agent-bootstrap/pom.xml
@@ -29,6 +29,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <shade.package>org.apache.shardingsphere.dependencies</shade.package>
<premain.class>org.apache.shardingsphere.agent.bootstrap.ShardingSphereAgent</premain.class>
<can.redefine.classes>true</can.redefine.classes>
<can.retransform.classes>true</can.retransform.classes>
@@ -40,6 +41,19 @@
<artifactId>shardingsphere-agent-core</artifactId>
<version>${project.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>net.bytebuddy</groupId>
+ <artifactId>byte-buddy</artifactId>
+ <version>${bytebuddy.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>net.bytebuddy</groupId>
+ <artifactId>byte-buddy-agent</artifactId>
+ <version>${bytebuddy.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
@@ -72,9 +86,21 @@
</transformers>
<artifactSet>
<excludes>
+
<exclude>net.bytebuddy:byte-buddy:jar:</exclude>
+ <exclude>com.google.*:*</exclude>
+ <exclude>com.google.guava:guava</exclude>
+
<exclude>org.checkerframework:checker-compat-qual</exclude>
+
<exclude>org.codehaus.mojo:animal-sniffer-annotations</exclude>
+ <exclude>io.perfmark:*</exclude>
<exclude>org.slf4j:*</exclude>
</excludes>
</artifactSet>
+ <relocations>
+ <relocation>
+ <pattern>net.bytebuddy</pattern>
+
<shadedPattern>${shade.package}.net.bytebuddy</shadedPattern>
+ </relocation>
+ </relocations>
</configuration>
</execution>
</executions>
diff --git
a/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
b/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
index 817fe08..360dfa3 100644
---
a/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
+++
b/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
@@ -18,12 +18,20 @@
package org.apache.shardingsphere.agent.bootstrap;
-import java.io.IOException;
-import java.lang.instrument.Instrumentation;
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.agent.builder.AgentBuilder;
+import net.bytebuddy.dynamic.scaffold.TypeValidation;
+import net.bytebuddy.matcher.ElementMatchers;
+import org.apache.shardingsphere.agent.core.LoggingListener;
+import org.apache.shardingsphere.agent.core.ShardingSphereTransformer;
import org.apache.shardingsphere.agent.core.config.AgentConfiguration;
import org.apache.shardingsphere.agent.core.config.AgentConfigurationLoader;
+import org.apache.shardingsphere.agent.core.plugin.PluginLoader;
import org.apache.shardingsphere.agent.core.utils.SingletonHolder;
+import java.io.IOException;
+import java.lang.instrument.Instrumentation;
+
/**
* ShardingSphere agent.
*/
@@ -39,5 +47,21 @@ public class ShardingSphereAgent {
public static void premain(final String agentArgs, final Instrumentation
instrumentation) throws IOException {
AgentConfiguration agentConfiguration =
AgentConfigurationLoader.load();
SingletonHolder.INSTANCE.put(agentConfiguration);
+
+ ByteBuddy byteBuddy = new ByteBuddy().with(TypeValidation.ENABLED);
+
+ AgentBuilder builder = new AgentBuilder.Default()
+ .with(byteBuddy)
+ .ignore(ElementMatchers.isSynthetic())
+
.or(ElementMatchers.nameStartsWith("org.apache.shardingsphere.agent."))
+
.or(ElementMatchers.not(ElementMatchers.nameStartsWith("org.apache.shardingsphere.")));
+
+ PluginLoader pluginLoader = new PluginLoader();
+
+ builder.type(pluginLoader.typeMatcher())
+ .transform(new ShardingSphereTransformer(pluginLoader))
+ .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
+ .with(new LoggingListener())
+ .installOn(instrumentation);
}
}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/pom.xml
b/shardingsphere-agent/shardingsphere-agent-core/pom.xml
index f0c7b4a..9e57825 100644
--- a/shardingsphere-agent/shardingsphere-agent-core/pom.xml
+++ b/shardingsphere-agent/shardingsphere-agent-core/pom.xml
@@ -27,12 +27,86 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>shardingsphere-agent-core</artifactId>
+
+ <properties>
+ <shade.package>org.apache.shardingsphere.dependencies</shade.package>
+ </properties>
<dependencies>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>net.bytebuddy</groupId>
+ <artifactId>byte-buddy</artifactId>
+ <version>${bytebuddy.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>net.bytebuddy</groupId>
+ <artifactId>byte-buddy-agent</artifactId>
+ <version>${bytebuddy.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${guava.version}</version>
+ </dependency>
+
</dependencies>
+ <build>
+ <finalName>shardingsphere-agent</finalName>
+ <plugins>
+ <plugin>
+ <artifactId>maven-shade-plugin</artifactId>
+ <configuration>
+
<createDependencyReducedPom>false</createDependencyReducedPom>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <artifactSet>
+ <excludes>
+
<exclude>net.bytebuddy:byte-buddy:jar:</exclude>
+ <exclude>com.google.*:*</exclude>
+ <exclude>com.google.guava:guava</exclude>
+
<exclude>org.checkerframework:checker-compat-qual</exclude>
+
<exclude>org.codehaus.mojo:animal-sniffer-annotations</exclude>
+ <exclude>io.perfmark:*</exclude>
+ <exclude>org.slf4j:*</exclude>
+ </excludes>
+ </artifactSet>
+ <relocations>
+ <relocation>
+ <pattern>com.google</pattern>
+
<shadedPattern>${shade.package}.com.google</shadedPattern>
+ </relocation>
+ <relocation>
+ <pattern>io.perfmark</pattern>
+
<shadedPattern>${shade.package}.io.perfmark</shadedPattern>
+ </relocation>
+ <relocation>
+ <pattern>org.slf4j</pattern>
+
<shadedPattern>${shade.package}.org.slf4j</shadedPattern>
+ </relocation>
+ <relocation>
+ <pattern>org.checkerframework</pattern>
+
<shadedPattern>${shade.package}.org.checkerframework</shadedPattern>
+ </relocation>
+ </relocations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/LoggingListener.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/LoggingListener.java
new file mode 100644
index 0000000..34d0934
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/LoggingListener.java
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+import lombok.extern.slf4j.Slf4j;
+import net.bytebuddy.agent.builder.AgentBuilder;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.dynamic.DynamicType;
+import net.bytebuddy.utility.JavaModule;
+
+/**
+ * Listener to log what is informed about events that occur during an
instrumentation process.
+ */
+@Slf4j
+public class LoggingListener implements AgentBuilder.Listener {
+
+ @Override
+ public void onDiscovery(final String typeName, final ClassLoader
classLoader, final JavaModule module, final boolean loaded) {
+
+ }
+
+ @Override
+ public void onTransformation(final TypeDescription typeDescription, final
ClassLoader classLoader, final JavaModule module, final boolean loaded, final
DynamicType dynamicType) {
+ if (log.isDebugEnabled()) {
+ log.debug("On transformation class {}.",
typeDescription.getTypeName());
+ }
+ }
+
+ @Override
+ public void onIgnored(final TypeDescription typeDescription, final
ClassLoader classLoader, final JavaModule module, final boolean loaded) {
+ }
+
+ @Override
+ public void onError(final String typeName, final ClassLoader classLoader,
final JavaModule module, final boolean loaded, final Throwable throwable) {
+ log.error("Failed to instrument {}.", typeName, throwable);
+ }
+
+ @Override
+ public void onComplete(final String typeName, final ClassLoader
classLoader, final JavaModule module, final boolean loaded) {
+
+ }
+}
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/ShardingSphereTransformer.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/ShardingSphereTransformer.java
new file mode 100644
index 0000000..0e352c9
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/ShardingSphereTransformer.java
@@ -0,0 +1,103 @@
+/*
+ * 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;
+
+import lombok.extern.slf4j.Slf4j;
+import net.bytebuddy.agent.builder.AgentBuilder;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.dynamic.DynamicType;
+import net.bytebuddy.implementation.FieldAccessor;
+import net.bytebuddy.implementation.MethodDelegation;
+import net.bytebuddy.implementation.SuperMethodCall;
+import net.bytebuddy.jar.asm.Opcodes;
+import net.bytebuddy.utility.JavaModule;
+import org.apache.shardingsphere.agent.core.plugin.PluginAdviceDefine;
+import org.apache.shardingsphere.agent.core.plugin.PluginLoader;
+import
org.apache.shardingsphere.agent.core.plugin.advice.ConstructorMethodInterceptor;
+import
org.apache.shardingsphere.agent.core.plugin.advice.MethodAroundInterceptor;
+import
org.apache.shardingsphere.agent.core.plugin.advice.StaticMethodAroundInterceptor;
+import org.apache.shardingsphere.agent.core.plugin.advice.TargetObject;
+import
org.apache.shardingsphere.agent.core.plugin.point.ClassStaticMethodPoint;
+import org.apache.shardingsphere.agent.core.plugin.point.ConstructorPoint;
+import org.apache.shardingsphere.agent.core.plugin.point.InstanceMethodPoint;
+
+import java.util.Map;
+
+/**
+ * Shardingsphere transformer.
+ */
+@Slf4j
+public class ShardingSphereTransformer implements AgentBuilder.Transformer {
+
+ private final PluginLoader pluginLoader;
+
+ public ShardingSphereTransformer(final PluginLoader pluginLoader) {
+ this.pluginLoader = pluginLoader;
+ }
+
+ @Override
+ public DynamicType.Builder<?> transform(final DynamicType.Builder<?>
builder, final TypeDescription typeDescription, final ClassLoader classLoader,
final JavaModule module) {
+ if (pluginLoader.containsType(typeDescription)) {
+
+ DynamicType.Builder<?> newBuilder =
builder.defineField("_SSExtraData_", Map.class, Opcodes.ACC_PRIVATE |
Opcodes.ACC_VOLATILE)
+ .implement(TargetObject.class)
+ .intercept(FieldAccessor.ofField("_SSExtraData_"));
+
+ final PluginAdviceDefine define =
pluginLoader.loadPluginAdviceDefine(typeDescription);
+ for (ConstructorPoint point : define.getConstructorPoints()) {
+ try {
+ final ConstructorMethodInterceptor interceptor = new
ConstructorMethodInterceptor(pluginLoader.getInstance(point.getAdvice()));
+ newBuilder =
newBuilder.constructor(point.getConstructorMatcher())
+
.intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration().to(interceptor)));
+ // CHECKSTYLE:OFF
+ } catch (Exception e) {
+ // CHECKSTYLE:ON
+ log.error("Failed to load advice class: {}",
point.getAdvice(), e);
+ }
+ }
+
+ for (ClassStaticMethodPoint point :
define.getClassStaticMethodPoints()) {
+ try {
+ final StaticMethodAroundInterceptor interceptor = new
StaticMethodAroundInterceptor(pluginLoader.getInstance(point.getAdvice()));
+ newBuilder = newBuilder.method(point.getMethodsMatcher())
+
.intercept(MethodDelegation.withDefaultConfiguration().to(interceptor));
+ // CHECKSTYLE:OFF
+ } catch (Exception e) {
+ // CHECKSTYLE:ON
+ log.error("Failed to load advice class: {}",
point.getAdvice(), e);
+ }
+ }
+
+ for (InstanceMethodPoint point : define.getInstanceMethodPoints())
{
+ try {
+ final MethodAroundInterceptor interceptor = new
MethodAroundInterceptor(pluginLoader.getInstance(point.getAdvice()));
+ newBuilder = newBuilder.method(point.getMethodMatcher())
+
.intercept(MethodDelegation.withDefaultConfiguration().to(interceptor));
+ // CHECKSTYLE:OFF
+ } catch (Exception e) {
+ // CHECKSTYLE:ON
+ log.error("Failed to load advice class: {}",
point.getAdvice(), e);
+ }
+ }
+ return newBuilder;
+ }
+
+ return builder;
+ }
+}
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/PluginAdviceDefine.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/PluginAdviceDefine.java
new file mode 100644
index 0000000..fcc7b19
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/PluginAdviceDefine.java
@@ -0,0 +1,300 @@
+/*
+ * 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;
+
+import com.google.common.collect.Lists;
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import net.bytebuddy.matcher.ElementMatchers;
+import
org.apache.shardingsphere.agent.core.plugin.point.ClassStaticMethodPoint;
+import org.apache.shardingsphere.agent.core.plugin.point.ConstructorPoint;
+import org.apache.shardingsphere.agent.core.plugin.point.InstanceMethodPoint;
+
+import java.util.List;
+
+/**
+ * Plugin advice define.
+ *
+ * <code>
+ * PluginAdviceDefine.intercept("Target.class")
+ * .onConstructor(ElementMatchers.any()).implement("Advice.class").build()
+ * .method(ElementMatchers.named("greet").implement("Advice.class").build()
+ *
.staticMethod(ElementMatchers.named("of").implement("OfAdvice.class").build()
+ * .install();
+ * </code>
+ */
+public final class PluginAdviceDefine {
+
+ private final List<ConstructorPoint> constructorPoints;
+
+ private final List<InstanceMethodPoint> instanceMethodPoints;
+
+ private final List<ClassStaticMethodPoint> classStaticMethodPoints;
+
+ private PluginAdviceDefine(final List<ConstructorPoint> constructorPoints,
+ final List<InstanceMethodPoint>
instanceMethodPoints,
+ final List<ClassStaticMethodPoint>
classStaticMethodPoints) {
+ this.constructorPoints = constructorPoints;
+ this.instanceMethodPoints = instanceMethodPoints;
+ this.classStaticMethodPoints = classStaticMethodPoints;
+ }
+
+ /**
+ * Intercept target class.
+ *
+ * @param classNameOfTarget a class name of wanted advice target.
+ * @return builder.
+ */
+ public static Builder intercept(final String classNameOfTarget) {
+ return new Builder(classNameOfTarget);
+ }
+
+ /**
+ * To get static method point configurations.
+ *
+ * @return series of static method point configuration.
+ */
+ public List<ClassStaticMethodPoint> getClassStaticMethodPoints() {
+ return classStaticMethodPoints;
+ }
+
+ /**
+ * To get constructor point configurations.
+ *
+ * @return series of constructor point configuration.
+ */
+ public List<ConstructorPoint> getConstructorPoints() {
+ return constructorPoints;
+ }
+
+ /**
+ * To get instance point configurations.
+ *
+ * @return series of instance method point configuration.
+ */
+ public List<InstanceMethodPoint> getInstanceMethodPoints() {
+ return instanceMethodPoints;
+ }
+
+ /**
+ * Plugin advice configuration builder.
+ */
+ public static final class Builder {
+ private final List<ConstructorPoint> constructorPoints =
Lists.newArrayList();
+
+ private final List<InstanceMethodPoint> instanceMethodPoints =
Lists.newArrayList();
+
+ private final List<ClassStaticMethodPoint> classStaticMethodPoints =
Lists.newArrayList();
+
+ private final String classNameOfTarget;
+
+ private Builder(final String classNameOfTarget) {
+ this.classNameOfTarget = classNameOfTarget;
+ }
+
+ /**
+ * Intercept the new target.
+ *
+ * @param classNameOfTarget the class name of target.
+ * @return configuration builder.
+ */
+ public Builder intercept(final String classNameOfTarget) {
+ // TODO not-implemented yet
+ return this;
+ }
+
+ /**
+ * Configure the intercepting point on constructor.
+ *
+ * @param matcher constraints
+ * @return configuration builder
+ */
+ public ConstructorPointBuilder onConstructor(final ElementMatcher<?
super MethodDescription> matcher) {
+ return new ConstructorPointBuilder(this, matcher);
+ }
+
+ /**
+ * Configure the intercepting point around instance method.
+ *
+ * @param matcher constraints
+ * @return configuration builder
+ */
+ public InstanceMethodPointBuilder method(final ElementMatcher<? super
MethodDescription> matcher) {
+ return new InstanceMethodPointBuilder(this, matcher);
+ }
+
+ /**
+ * Configure the intercepting point around instance method.
+ *
+ * @param matcher constraints
+ * @return configuration builder
+ */
+ public StaticMethodPointBuilder staticMethod(final ElementMatcher<?
super MethodDescription> matcher) {
+ return new StaticMethodPointBuilder(this, matcher);
+ }
+
+
+ /**
+ * Build configuration.
+ *
+ * @return plugin advice definition.
+ */
+ public PluginAdviceDefine install() {
+ return new PluginAdviceDefine(constructorPoints,
instanceMethodPoints, classStaticMethodPoints);
+ }
+
+ /**
+ * Instance method intercepting point configuration builder.
+ */
+ public static final class InstanceMethodPointBuilder {
+ private final Builder builder;
+
+ private String classNameOfAdvice;
+
+ private boolean overrideArgs;
+
+ private ElementMatcher<? super MethodDescription> matcher;
+
+ private InstanceMethodPointBuilder(final Builder builder, final
ElementMatcher<? super MethodDescription> matcher) {
+ this.builder = builder;
+ this.matcher = matcher;
+ }
+
+ /**
+ * Configure implementation for interceptor point.
+ *
+ * @param classNameOfAdvice the class name of advice
+ * @return instance method point builder.
+ */
+ public InstanceMethodPointBuilder implement(final String
classNameOfAdvice) {
+ this.classNameOfAdvice = classNameOfAdvice;
+ return this;
+ }
+
+ /**
+ * Configure whether or not override the origin method arguments.
+ *
+ * @param overrideArgs whether to override origin method arguments.
+ * @return instance method point configurer.
+ */
+ public InstanceMethodPointBuilder overrideArgs(final boolean
overrideArgs) {
+ this.overrideArgs = overrideArgs;
+ return this;
+ }
+
+ /**
+ * Build instance methods configuration.
+ *
+ * @return plugin advice builder.
+ */
+ public Builder build() {
+ builder.instanceMethodPoints.add(new
InstanceMethodPoint(matcher, classNameOfAdvice, overrideArgs));
+ return builder;
+ }
+ }
+
+ /**
+ * Static method intercepting point configuration builder.
+ */
+ public static final class StaticMethodPointBuilder {
+ private final Builder builder;
+
+ private String classNameOfAdvice;
+
+ private boolean overrideArgs;
+
+ private ElementMatcher<? super MethodDescription> matcher;
+
+ private StaticMethodPointBuilder(final Builder builder, final
ElementMatcher<? super MethodDescription> matcher) {
+ this.builder = builder;
+ this.matcher = ElementMatchers.isStatic().and(matcher);
+ }
+
+ /**
+ * Configure implementation for intercepting point.
+ *
+ * @param classNameOfAdvice the class name of advice
+ * @return static method point configurer.
+ */
+ public StaticMethodPointBuilder implement(final String
classNameOfAdvice) {
+ this.classNameOfAdvice = classNameOfAdvice;
+ return this;
+ }
+
+ /**
+ * Configure whether or not override the origin method arguments.
+ *
+ * @param overrideArgs whether to override origin method arguments.
+ * @return static method point configurer.
+ */
+ public StaticMethodPointBuilder overrideArgs(final boolean
overrideArgs) {
+ this.overrideArgs = overrideArgs;
+ return this;
+ }
+
+ /**
+ * Build static methods configuration.
+ *
+ * @return plugin advice builder.
+ */
+ public Builder build() {
+ builder.classStaticMethodPoints.add(new
ClassStaticMethodPoint(matcher, classNameOfAdvice, overrideArgs));
+ return builder;
+ }
+
+ }
+
+ /**
+ * Instance constructor intercepting point configuration builder.
+ */
+ public static final class ConstructorPointBuilder {
+ private final Builder builder;
+
+ private String classNameOfAdvice;
+
+ private ElementMatcher<? super MethodDescription> matcher;
+
+ private ConstructorPointBuilder(final Builder builder, final
ElementMatcher<? super MethodDescription> matcher) {
+ this.builder = builder;
+ this.matcher = ElementMatchers.isConstructor().and(matcher);
+ }
+
+ /**
+ * Configure implementation for intercepting point.
+ *
+ * @param classNameOfAdvice the class name of advice
+ * @return constructor point builder.
+ */
+ public ConstructorPointBuilder implement(final String
classNameOfAdvice) {
+ this.classNameOfAdvice = classNameOfAdvice;
+ return this;
+ }
+
+ /**
+ * Build constructor point configuration.
+ *
+ * @return plugin advice builder.
+ */
+ public Builder build() {
+ builder.constructorPoints.add(new ConstructorPoint(matcher,
classNameOfAdvice));
+ return builder;
+ }
+ }
+ }
+}
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/PluginLoader.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/PluginLoader.java
new file mode 100644
index 0000000..7a7f548
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/PluginLoader.java
@@ -0,0 +1,95 @@
+/*
+ * 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;
+
+import lombok.SneakyThrows;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Plugins loader.
+ * TODO not-implemented yet
+ */
+public class PluginLoader extends ClassLoader {
+
+ private final ConcurrentHashMap<String, Object> objectPool = new
ConcurrentHashMap<>();
+
+ private final ReentrantLock lock = new ReentrantLock();
+
+ /**
+ * To find all intercepting target classes then to build TypeMatcher.
+ *
+ * @return type matcher
+ */
+ public ElementMatcher<? super TypeDescription> typeMatcher() {
+ return null;
+ }
+
+ /**
+ * To detect the type whether or not exists.
+ *
+ * @param typeDescription TypeDescription
+ * @return contains when it is true.
+ */
+ public boolean containsType(final TypeDescription typeDescription) {
+ return false;
+ }
+
+ /**
+ * Load the definition configuration by TypeDescription.
+ *
+ * @param typeDescription TypeDescription
+ * @return the plugin definition configurations.
+ */
+ public PluginAdviceDefine loadPluginAdviceDefine(final TypeDescription
typeDescription) {
+ return null;
+ }
+
+ /**
+ * To get or create instance of the advice class. Create new one and
caching when it is not exist.
+ *
+ * @param classNameOfAdvice the class name of advice
+ * @param <T> the advice type.
+ * @return instance of advice
+ */
+ @SneakyThrows({ClassNotFoundException.class, IllegalAccessException.class,
InstantiationException.class})
+ public <T> T getInstance(final String classNameOfAdvice) {
+
+ if (objectPool.containsKey(classNameOfAdvice)) {
+ return (T) objectPool.get(classNameOfAdvice);
+ }
+
+ lock.lock();
+ try {
+ Object inst = objectPool.get(classNameOfAdvice);
+ if (Objects.isNull(inst)) {
+ inst = Class.forName(classNameOfAdvice, true, this)
+ .newInstance();
+ objectPool.put(classNameOfAdvice, inst);
+ }
+ return (T) inst;
+ } finally {
+ lock.unlock();
+ }
+ }
+}
diff --git
a/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/ConstructorAdvice.java
similarity index 50%
copy from
shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
copy to
shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/ConstructorAdvice.java
index 817fe08..560f4ad 100644
---
a/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/ConstructorAdvice.java
@@ -16,28 +16,18 @@
*
*/
-package org.apache.shardingsphere.agent.bootstrap;
-
-import java.io.IOException;
-import java.lang.instrument.Instrumentation;
-import org.apache.shardingsphere.agent.core.config.AgentConfiguration;
-import org.apache.shardingsphere.agent.core.config.AgentConfigurationLoader;
-import org.apache.shardingsphere.agent.core.utils.SingletonHolder;
+package org.apache.shardingsphere.agent.core.plugin.advice;
/**
- * ShardingSphere agent.
+ * Weaving the advice around the constructor of target class.
*/
-public class ShardingSphereAgent {
-
+public interface ConstructorAdvice {
+
/**
- * Premain for instrumentation.
+ * Intercept the target's constructor. This method is weaved after the
constructor execution.
*
- * @param agentArgs agent args
- * @param instrumentation instrumentation
- * @throws IOException IO exception
+ * @param target intercepted target object
+ * @param args all arguments of the intercepted constructor
*/
- public static void premain(final String agentArgs, final Instrumentation
instrumentation) throws IOException {
- AgentConfiguration agentConfiguration =
AgentConfigurationLoader.load();
- SingletonHolder.INSTANCE.put(agentConfiguration);
- }
+ void onConstructor(TargetObject target, Object[] args);
}
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/ConstructorMethodInterceptor.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/ConstructorMethodInterceptor.java
new file mode 100644
index 0000000..dfa3916
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/ConstructorMethodInterceptor.java
@@ -0,0 +1,54 @@
+/*
+ * 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.advice;
+
+import lombok.extern.slf4j.Slf4j;
+import net.bytebuddy.implementation.bind.annotation.AllArguments;
+import net.bytebuddy.implementation.bind.annotation.RuntimeType;
+import net.bytebuddy.implementation.bind.annotation.This;
+
+/**
+ * Proxy class for ByteBuddy to intercept methods of target and weave
post-method after constructor.
+ */
+@Slf4j
+public class ConstructorMethodInterceptor {
+ private final ConstructorAdvice advice;
+
+ public ConstructorMethodInterceptor(final ConstructorAdvice advice) {
+ this.advice = advice;
+ }
+
+ /**
+ * Intercept constructor.
+ *
+ * @param target the target object
+ * @param args the all constructor arguments
+ */
+ @RuntimeType
+ public void intercept(final @This TargetObject target, final @AllArguments
Object[] args) {
+ try {
+ advice.onConstructor(target, args);
+ // CHECKSTYLE:OFF
+ } catch (Throwable throwable) {
+ // CHECKSTYLE:ON
+ log.error("Constructor advice execution error. class: {}",
target.getClass().getTypeName(), throwable);
+ }
+ }
+
+}
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/MethodAroundAdvice.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/MethodAroundAdvice.java
new file mode 100644
index 0000000..cb43791
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/MethodAroundAdvice.java
@@ -0,0 +1,57 @@
+/*
+ * 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.advice;
+
+import java.lang.reflect.Method;
+
+/**
+ * Weaving the advice around the target method.
+ */
+public interface MethodAroundAdvice {
+
+ /**
+ * Intercept the target method and weave the method before origin method.
It will invoke before the origin calling.
+ *
+ * @param target the target object
+ * @param method the target method
+ * @param args all method arguments
+ * @param result wrapped class of result to detect whether or not to
execute the origin method.
+ */
+ void beforeMethod(TargetObject target, Method method, Object[] args,
MethodInvocationResult result);
+
+ /**
+ * Intercept the target method and weave the method after origin method.
It will invoke after the origin calling.
+ *
+ * @param target the target object
+ * @param method the target method
+ * @param args all method arguments
+ * @param result wrapped class of result to detect whether or not to
execute the origin method.
+ */
+ void afterMethod(TargetObject target, Method method, Object[] args,
MethodInvocationResult result);
+
+ /**
+ * Weaving the method after origin method throwing.
+ *
+ * @param target the target object
+ * @param method the target method
+ * @param args all method arguments
+ * @param throwable exception from target method.
+ */
+ void onThrowing(TargetObject target, Method method, Object[] args,
Throwable throwable);
+}
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/MethodAroundInterceptor.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/MethodAroundInterceptor.java
new file mode 100644
index 0000000..123f50e
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/MethodAroundInterceptor.java
@@ -0,0 +1,96 @@
+/*
+ * 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.advice;
+
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import net.bytebuddy.implementation.bind.annotation.AllArguments;
+import net.bytebuddy.implementation.bind.annotation.Origin;
+import net.bytebuddy.implementation.bind.annotation.RuntimeType;
+import net.bytebuddy.implementation.bind.annotation.SuperCall;
+import net.bytebuddy.implementation.bind.annotation.This;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+
+/**
+ * Proxy class for ByteBuddy to intercept methods of target and weave pre- and
post-method around the target method.
+ */
+@Slf4j
+public class MethodAroundInterceptor {
+ private final MethodAroundAdvice advice;
+
+ public MethodAroundInterceptor(final MethodAroundAdvice advice) {
+ this.advice = advice;
+ }
+
+ /**
+ * Only intercept instance method.
+ *
+ * @param target the target object
+ * @param method the intercepted method
+ * @param args the all arguments of method
+ * @param uber the origin method invocation
+ * @return the return value of target invocation
+ */
+ @RuntimeType
+ @SneakyThrows
+ public Object intercept(final @This Object target, final @Origin Method
method, final @AllArguments Object[] args, final @SuperCall Callable<?> uber) {
+ final TargetObject instance = (TargetObject) target;
+ final MethodInvocationResult result = new MethodInvocationResult();
+
+ Object ret;
+
+ try {
+ advice.beforeMethod(instance, method, args, result);
+ // CHECKSTYLE:OFF
+ } catch (Throwable throwable) {
+ // CHECKSTYLE:ON
+ log.error("Failed to execute the pre-method of method[{}] in
class[{}].", method.getName(), target.getClass(), throwable);
+ }
+
+ try {
+ if (result.isRebased()) {
+ ret = result.getResult();
+ } else {
+ ret = uber.call();
+ }
+ // CHECKSTYLE:OFF
+ } catch (Throwable throwable) {
+ // CHECKSTYLE:ON
+ try {
+ advice.onThrowing(instance, method, args, throwable);
+ // CHECKSTYLE:OFF
+ } catch (Throwable adviceException) {
+ // CHECKSTYLE:ON
+ log.error("Failed to execute the error handler of method[{}]
in class[{}].", method.getName(), target.getClass(), adviceException);
+ }
+ throw throwable;
+ } finally {
+ try {
+ advice.afterMethod(instance, method, args, result);
+ // CHECKSTYLE:OFF
+ } catch (Throwable throwable) {
+ // CHECKSTYLE:ON
+ log.error("Failed to execute the post-method of method[{}] in
class[{}].", method.getName(), target.getClass(), throwable);
+ }
+ }
+ return ret;
+ }
+}
diff --git
a/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/MethodInvocationResult.java
similarity index 50%
copy from
shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
copy to
shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/MethodInvocationResult.java
index 817fe08..fea7038 100644
---
a/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/MethodInvocationResult.java
@@ -16,28 +16,42 @@
*
*/
-package org.apache.shardingsphere.agent.bootstrap;
-
-import java.io.IOException;
-import java.lang.instrument.Instrumentation;
-import org.apache.shardingsphere.agent.core.config.AgentConfiguration;
-import org.apache.shardingsphere.agent.core.config.AgentConfigurationLoader;
-import org.apache.shardingsphere.agent.core.utils.SingletonHolder;
+package org.apache.shardingsphere.agent.core.plugin.advice;
/**
- * ShardingSphere agent.
+ * The advice method invocation result.
*/
-public class ShardingSphereAgent {
-
+public class MethodInvocationResult {
+ private boolean isRebased;
+
+ private Object result;
+
+ /**
+ * To replace the origin result.
+ *
+ * @param result rebase the origin result
+ */
+ public void rebase(final Object result) {
+ isRebased = true;
+ this.result = result;
+ }
+
/**
- * Premain for instrumentation.
+ * Whether or not to discard origin method.
*
- * @param agentArgs agent args
- * @param instrumentation instrumentation
- * @throws IOException IO exception
+ * @return to replace the origin result if true.
*/
- public static void premain(final String agentArgs, final Instrumentation
instrumentation) throws IOException {
- AgentConfiguration agentConfiguration =
AgentConfigurationLoader.load();
- SingletonHolder.INSTANCE.put(agentConfiguration);
+ public boolean isRebased() {
+ return isRebased;
}
+
+ /**
+ * Result that is provided by per-method advice.
+ *
+ * @return the advice result.
+ */
+ public Object getResult() {
+ return result;
+ }
+
}
diff --git
a/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/OverrideArgsInvoker.java
similarity index 50%
copy from
shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
copy to
shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/OverrideArgsInvoker.java
index 817fe08..cc1f2fc 100644
---
a/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/OverrideArgsInvoker.java
@@ -16,28 +16,19 @@
*
*/
-package org.apache.shardingsphere.agent.bootstrap;
-
-import java.io.IOException;
-import java.lang.instrument.Instrumentation;
-import org.apache.shardingsphere.agent.core.config.AgentConfiguration;
-import org.apache.shardingsphere.agent.core.config.AgentConfigurationLoader;
-import org.apache.shardingsphere.agent.core.utils.SingletonHolder;
+package org.apache.shardingsphere.agent.core.plugin.advice;
/**
- * ShardingSphere agent.
+ * Super(origin) method invoker for ByteBuddy only.
*/
-public class ShardingSphereAgent {
-
+public interface OverrideArgsInvoker {
+
/**
- * Premain for instrumentation.
+ * Invocation origin method.
*
- * @param agentArgs agent args
- * @param instrumentation instrumentation
- * @throws IOException IO exception
+ * @param args the origin method arguments.
+ * @return the result of the origin method.
*/
- public static void premain(final String agentArgs, final Instrumentation
instrumentation) throws IOException {
- AgentConfiguration agentConfiguration =
AgentConfigurationLoader.load();
- SingletonHolder.INSTANCE.put(agentConfiguration);
- }
+ Object call(Object[] args);
+
}
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/StaticMethodAroundAdvice.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/StaticMethodAroundAdvice.java
new file mode 100644
index 0000000..602ac41
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/StaticMethodAroundAdvice.java
@@ -0,0 +1,57 @@
+/*
+ * 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.advice;
+
+import java.lang.reflect.Method;
+
+/**
+ * Weaving the advice around the static methods of target class.
+ */
+public interface StaticMethodAroundAdvice {
+
+ /**
+ * Intercept the target method and weave the method before origin method.
It will invoke before the origin calling.
+ *
+ * @param klass the target class
+ * @param method the target method
+ * @param args all method arguments
+ * @param result wrapped class of result to detect whether or not to
execute the origin method.
+ */
+ void beforeMethod(Class<?> klass, Method method, Object[] args,
MethodInvocationResult result);
+
+ /**
+ * Intercept the target method and weave the method after origin method.
It will invoke after the origin calling.
+ *
+ * @param klass the target class
+ * @param method the target method
+ * @param args all method arguments
+ * @param result wrapped class of result to detect whether or not to
execute the origin method.
+ */
+ void afterMethod(Class<?> klass, Method method, Object[] args,
MethodInvocationResult result);
+
+ /**
+ * Weaving the method after origin method throwing.
+ *
+ * @param klass the target class
+ * @param method the target method
+ * @param args all method arguments
+ * @param throwable exception from target method.
+ */
+ void onThrowing(Class<?> klass, Method method, Object[] args, Throwable
throwable);
+}
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/StaticMethodAroundInterceptor.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/StaticMethodAroundInterceptor.java
new file mode 100644
index 0000000..32078ae
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/StaticMethodAroundInterceptor.java
@@ -0,0 +1,94 @@
+/*
+ * 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.advice;
+
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import net.bytebuddy.implementation.bind.annotation.AllArguments;
+import net.bytebuddy.implementation.bind.annotation.Origin;
+import net.bytebuddy.implementation.bind.annotation.RuntimeType;
+import net.bytebuddy.implementation.bind.annotation.SuperCall;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+
+/**
+ * Proxy class for ByteBuddy to intercept methods of target and weave pre- and
post-method around the target method.
+ */
+@Slf4j
+public class StaticMethodAroundInterceptor {
+
+ private final StaticMethodAroundAdvice advice;
+
+ public StaticMethodAroundInterceptor(final StaticMethodAroundAdvice
advice) {
+ this.advice = advice;
+ }
+
+ /**
+ * Only intercept static method.
+ *
+ * @param klass the class of target
+ * @param method the intercepted method
+ * @param args the all arguments of method
+ * @param uber the origin method invocation
+ * @return the return value of target invocation
+ */
+ @RuntimeType
+ @SneakyThrows
+ public Object intercept(final @Origin Class<?> klass, final @Origin Method
method, final @AllArguments Object[] args, final @SuperCall Callable<?> uber) {
+ final MethodInvocationResult result = new MethodInvocationResult();
+ final Object ret;
+
+ try {
+ advice.afterMethod(klass, method, args, result);
+ // CHECKSTYLE:OFF
+ } catch (Throwable throwable) {
+ // CHECKSTYLE:ON
+ log.error("Failed to execute the pre-method of method[{}] in
class[{}].", method.getName(), klass, throwable);
+ }
+
+ try {
+ if (result.isRebased()) {
+ ret = result.getResult();
+ } else {
+ ret = uber.call();
+ }
+ // CHECKSTYLE:OFF
+ } catch (Throwable throwable) {
+ // CHECKSTYLE:ON
+ try {
+ advice.onThrowing(klass, method, args, throwable);
+ // CHECKSTYLE:OFF
+ } catch (Throwable ignore) {
+ // CHECKSTYLE:ON
+ log.error("Failed to execute the error handler of method[{}]
in class[{}].", method.getName(), klass, throwable);
+ }
+ throw throwable;
+ } finally {
+ try {
+ advice.beforeMethod(klass, method, args, result);
+ // CHECKSTYLE:OFF
+ } catch (Throwable throwable) {
+ // CHECKSTYLE:ON
+ log.error("Failed to execute the post-method of method[{}] in
class[{}].", method.getName(), klass, throwable);
+ }
+ }
+ return ret;
+ }
+}
diff --git
a/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/TargetObject.java
similarity index 50%
copy from
shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
copy to
shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/TargetObject.java
index 817fe08..b959dad 100644
---
a/shardingsphere-agent/shardingsphere-agent-bootstrap/src/main/java/org/apache/shardingsphere/agent/bootstrap/ShardingSphereAgent.java
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/advice/TargetObject.java
@@ -16,28 +16,25 @@
*
*/
-package org.apache.shardingsphere.agent.bootstrap;
-
-import java.io.IOException;
-import java.lang.instrument.Instrumentation;
-import org.apache.shardingsphere.agent.core.config.AgentConfiguration;
-import org.apache.shardingsphere.agent.core.config.AgentConfigurationLoader;
-import org.apache.shardingsphere.agent.core.utils.SingletonHolder;
+package org.apache.shardingsphere.agent.core.plugin.advice;
/**
- * ShardingSphere agent.
+ * Wrapped class for target and provide a context to store variable during
invocation.
*/
-public class ShardingSphereAgent {
-
+public interface TargetObject {
+
/**
- * Premain for instrumentation.
+ * Get the variable from context.
*
- * @param agentArgs agent args
- * @param instrumentation instrumentation
- * @throws IOException IO exception
+ * @return the attachment.
*/
- public static void premain(final String agentArgs, final Instrumentation
instrumentation) throws IOException {
- AgentConfiguration agentConfiguration =
AgentConfigurationLoader.load();
- SingletonHolder.INSTANCE.put(agentConfiguration);
- }
+ Object getAttachment();
+
+ /**
+ * Store a variable into context.
+ *
+ * @param attachment what variable you want to store.
+ */
+ void setAttachment(Object attachment);
+
}
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/point/ClassStaticMethodPoint.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/point/ClassStaticMethodPoint.java
new file mode 100644
index 0000000..d15c3b1
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/point/ClassStaticMethodPoint.java
@@ -0,0 +1,68 @@
+/*
+ * 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.point;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+/**
+ * Configuration of static method intercepting point.
+ */
+public class ClassStaticMethodPoint {
+
+ private final ElementMatcher<? super MethodDescription> matcher;
+
+ private final String advice;
+
+ private final boolean overrideArgs;
+
+ public ClassStaticMethodPoint(final ElementMatcher<? super
MethodDescription> matcher, final String advice, final boolean overrideArgs) {
+ this.matcher = matcher;
+ this.advice = advice;
+ this.overrideArgs = overrideArgs;
+ }
+
+ /**
+ * To detect target method constraints.
+ *
+ * @return constraints
+ */
+ public ElementMatcher<? super MethodDescription> getMethodsMatcher() {
+ return matcher;
+ }
+
+ /**
+ * To get the class name of advice.
+ *
+ * @return the class name of advice.
+ */
+ public String getAdvice() {
+ return advice;
+ }
+
+ /**
+ * To detect whether to override origin arguments.
+ *
+ * @return override if true
+ */
+ public boolean isOverrideArgs() {
+ return overrideArgs;
+ }
+
+}
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/point/ConstructorPoint.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/point/ConstructorPoint.java
new file mode 100644
index 0000000..a64e789
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/point/ConstructorPoint.java
@@ -0,0 +1,55 @@
+/*
+ * 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.point;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+/**
+ * Configuration of constructor intercepting point.
+ */
+public class ConstructorPoint {
+ private final ElementMatcher<? super MethodDescription> matcher;
+
+ private final String advice;
+
+ public ConstructorPoint(final ElementMatcher<? super MethodDescription>
matcher, final String advice) {
+ this.matcher = matcher;
+ this.advice = advice;
+ }
+
+ /**
+ * To detect target constructor constraints.
+ *
+ * @return constraints
+ */
+ public ElementMatcher<? super MethodDescription> getConstructorMatcher() {
+ return matcher;
+ }
+
+ /**
+ * To get the class name of advice.
+ *
+ * @return the class name of advice.
+ */
+ public String getAdvice() {
+ return advice;
+ }
+
+}
diff --git
a/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/point/InstanceMethodPoint.java
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/point/InstanceMethodPoint.java
new file mode 100644
index 0000000..b380023
--- /dev/null
+++
b/shardingsphere-agent/shardingsphere-agent-core/src/main/java/org/apache/shardingsphere/agent/core/plugin/point/InstanceMethodPoint.java
@@ -0,0 +1,66 @@
+/*
+ * 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.point;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+/**
+ * Configuration of instance method intercepting point.
+ */
+public class InstanceMethodPoint {
+ private final ElementMatcher<? super MethodDescription> matcher;
+
+ private final String advice;
+
+ private final boolean overrideArgs;
+
+ public InstanceMethodPoint(final ElementMatcher<? super MethodDescription>
matcher, final String advice, final boolean overrideArgs) {
+ this.matcher = matcher;
+ this.advice = advice;
+ this.overrideArgs = overrideArgs;
+ }
+
+ /**
+ * Detecting target method constraints but static methods.
+ *
+ * @return constraints
+ */
+ public ElementMatcher<? super MethodDescription> getMethodMatcher() {
+ return matcher;
+ }
+
+ /**
+ * To get the class name of advice.
+ *
+ * @return the class name of advice.
+ */
+ public String getAdvice() {
+ return advice;
+ }
+
+ /**
+ * To detect whether to override origin arguments.
+ *
+ * @return override if true
+ */
+ public boolean isOverrideArgs() {
+ return overrideArgs;
+ }
+}