diff --git a/FAQ.md b/FAQ.md
index a490847f0412..28e2f0cc564d 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -22,4 +22,4 @@ For committers, make sure select the right label and target branch for every PR,
[Example question](https://github.com/alibaba/dubbo/issues/742)
-Dubbo support to specify ip/port via system environment variables, examples can be found [here](https://github.com/dubbo/dubbo-samples/tree/master/dubbo-samples-docker).
\ No newline at end of file
+Dubbo supports specifying ip/port via system environment variables, examples can be found [here](https://github.com/dubbo/dubbo-samples/tree/master/dubbo-samples-docker).
diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md
index 403cb9135873..5427becaba5c 100644
--- a/PULL_REQUEST_TEMPLATE.md
+++ b/PULL_REQUEST_TEMPLATE.md
@@ -12,7 +12,7 @@ XXXXX
Follow this checklist to help us incorporate your contribution quickly and easily:
-- [x] Make sure there is a [GITHUB_issue](https://github.com/apache/incubator-dubbo/issues) filed for the change (usually before you start working on it). Trivial changes like typos do not require a GITHUB issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.
+- [x] Make sure there is a [GITHUB_issue](https://github.com/apache/incubator-dubbo/issues) field for the change (usually before you start working on it). Trivial changes like typos do not require a GITHUB issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.
- [ ] Format the pull request title like `[Dubbo-XXX] Fix UnknownException when host config not exist #XXX`. Each commit in the pull request should have a meaningful subject line and body.
- [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
- [ ] Write necessary unit-test to verify your logic correction, more mock a little better when cross module dependency exist. If the new feature or significant change is committed, please remember to add integration-test in [test module](https://github.com/apache/incubator-dubbo/tree/master/dubbo-test).
diff --git a/README.md b/README.md
index 75ec9704bdcb..6f41ccfda56d 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ There's a [README](https://github.com/dubbo/dubbo-samples/blob/master/dubbo-samp
com.alibabadubbo
- 2.6.4
+ 2.6.5
```
diff --git a/codestyle/checkstyle.xml b/codestyle/checkstyle.xml
index ffdafd15f441..621a9e37bca9 100644
--- a/codestyle/checkstyle.xml
+++ b/codestyle/checkstyle.xml
@@ -20,5 +20,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/codestyle/dubbo_codestyle_for_idea.xml b/codestyle/dubbo_codestyle_for_idea.xml
index 4c632e4b2888..1f87caa71352 100644
--- a/codestyle/dubbo_codestyle_for_idea.xml
+++ b/codestyle/dubbo_codestyle_for_idea.xml
@@ -5,8 +5,6 @@
-
-
diff --git a/dubbo-all/pom.xml b/dubbo-all/pom.xml
index f26a1e26bd47..12d9ec9efd30 100644
--- a/dubbo-all/pom.xml
+++ b/dubbo-all/pom.xml
@@ -320,7 +320,7 @@
org.apache.dubbo
- dubbo-bootstrap
+ dubbo-serialization-protostuff${project.version}compiletrue
@@ -431,7 +431,7 @@
org.apache.dubbo:dubbo-serialization-fstorg.apache.dubbo:dubbo-serialization-kryoorg.apache.dubbo:dubbo-serialization-jdk
- org.apache.dubbo:dubbo-bootstrap
+ org.apache.dubbo:dubbo-serialization-protostuff
@@ -595,4 +595,4 @@
-
\ No newline at end of file
+
diff --git a/dubbo-bom/pom.xml b/dubbo-bom/pom.xml
index 0bf81218d6aa..dac2456d830a 100644
--- a/dubbo-bom/pom.xml
+++ b/dubbo-bom/pom.xml
@@ -280,7 +280,7 @@
org.apache.dubbo
- dubbo-bootstrap
+ dubbo-serialization-protostuff${project.version}
diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
deleted file mode 100644
index b896c0ee8473..000000000000
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.bootstrap;
-
-import org.apache.dubbo.config.DubboShutdownHook;
-import org.apache.dubbo.config.ServiceConfig;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A bootstrap class to easily start and stop Dubbo via programmatic API.
- * The bootstrap class will be responsible to cleanup the resources during stop.
- */
-public class DubboBootstrap {
-
- /**
- * The list of ServiceConfig
- */
- private List serviceConfigList;
-
- /**
- * Whether register the shutdown hook during start?
- */
- private final boolean registerShutdownHookOnStart;
-
- /**
- * The shutdown hook used when Dubbo is running under embedded environment
- */
- private DubboShutdownHook shutdownHook;
-
- public DubboBootstrap() {
- this(true, DubboShutdownHook.getDubboShutdownHook());
- }
-
- public DubboBootstrap(boolean registerShutdownHookOnStart) {
- this(registerShutdownHookOnStart, DubboShutdownHook.getDubboShutdownHook());
- }
-
- public DubboBootstrap(boolean registerShutdownHookOnStart, DubboShutdownHook shutdownHook) {
- this.serviceConfigList = new ArrayList();
- this.shutdownHook = shutdownHook;
- this.registerShutdownHookOnStart = registerShutdownHookOnStart;
- }
-
- /**
- * Register service config to bootstrap, which will be called during {@link DubboBootstrap#stop()}
- * @param serviceConfig the service
- * @return the bootstrap instance
- */
- public DubboBootstrap registerServiceConfig(ServiceConfig serviceConfig) {
- serviceConfigList.add(serviceConfig);
- return this;
- }
-
- public void start() {
- if (registerShutdownHookOnStart) {
- registerShutdownHook();
- } else {
- // DubboShutdown hook has been registered in AbstractConfig,
- // we need to remove it explicitly
- removeShutdownHook();
- }
- for (ServiceConfig serviceConfig: serviceConfigList) {
- serviceConfig.export();
- }
- }
-
- public void stop() {
- for (ServiceConfig serviceConfig: serviceConfigList) {
- serviceConfig.unexport();
- }
- shutdownHook.destroyAll();
- if (registerShutdownHookOnStart) {
- removeShutdownHook();
- }
- }
-
- /**
- * Register the shutdown hook
- */
- public void registerShutdownHook() {
- Runtime.getRuntime().addShutdownHook(shutdownHook);
- }
-
- /**
- * Remove this shutdown hook
- */
- public void removeShutdownHook() {
- try {
- Runtime.getRuntime().removeShutdownHook(shutdownHook);
- }
- catch (IllegalStateException ex) {
- // ignore - VM is already shutting down
- }
- }
-}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalance.java
index 90bc60cf91c3..eea0ca319db4 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalance.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalance.java
@@ -34,13 +34,13 @@ public class RandomLoadBalance extends AbstractLoadBalance {
@Override
protected Invoker doSelect(List> invokers, URL url, Invocation invocation) {
int length = invokers.size(); // Number of invokers
- int totalWeight = 0; // The sum of weights
boolean sameWeight = true; // Every invoker has the same weight?
- for (int i = 0; i < length; i++) {
+ int firstWeight = getWeight(invokers.get(0), invocation);
+ int totalWeight = firstWeight; // The sum of weights
+ for (int i = 1; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
totalWeight += weight; // Sum
- if (sameWeight && i > 0
- && weight != getWeight(invokers.get(i - 1), invocation)) {
+ if (sameWeight && weight != firstWeight) {
sameWeight = false;
}
}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java
index f3b802ef680a..f0bd58ef3441 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalance.java
@@ -17,68 +17,137 @@
package org.apache.dubbo.rpc.cluster.loadbalance;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.AtomicPositiveInteger;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
-import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
/**
* Round robin load balance.
*/
public class RoundRobinLoadBalance extends AbstractLoadBalance {
-
public static final String NAME = "roundrobin";
+
+ private static int RECYCLE_PERIOD = 60000;
+
+ protected static class WeightedRoundRobin {
+ private int weight;
+ private AtomicLong current = new AtomicLong(0);
+ private long lastUpdate;
+ public int getWeight() {
+ return weight;
+ }
+ public void setWeight(int weight) {
+ this.weight = weight;
+ current.set(0);
+ }
+ public long increaseCurrent() {
+ return current.addAndGet(weight);
+ }
+ public void sel(int total) {
+ current.addAndGet(-1 * total);
+ }
+ public long getLastUpdate() {
+ return lastUpdate;
+ }
+ public void setLastUpdate(long lastUpdate) {
+ this.lastUpdate = lastUpdate;
+ }
+ }
- private final ConcurrentMap sequences = new ConcurrentHashMap();
-
- private final ConcurrentMap indexSeqs = new ConcurrentHashMap();
-
+ private ConcurrentMap> methodWeightMap = new ConcurrentHashMap>();
+ private AtomicBoolean updateLock = new AtomicBoolean();
+
+ /**
+ * get invoker addr list cached for specified invocation
+ *
+ * for unit test only
+ *
+ * @param invokers
+ * @param invocation
+ * @return
+ */
+ protected Collection getInvokerAddrList(List> invokers, Invocation invocation) {
+ String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
+ Map map = methodWeightMap.get(key);
+ if (map != null) {
+ return map.keySet();
+ }
+ return null;
+ }
+
@Override
protected Invoker doSelect(List> invokers, URL url, Invocation invocation) {
String key = invokers.get(0).getUrl().getServiceKey() + "." + invocation.getMethodName();
- int length = invokers.size(); // Number of invokers
- int maxWeight = 0; // The maximum weight
- int minWeight = Integer.MAX_VALUE; // The minimum weight
- final List> nonZeroWeightedInvokers = new ArrayList<>();
- for (int i = 0; i < length; i++) {
- int weight = getWeight(invokers.get(i), invocation);
- maxWeight = Math.max(maxWeight, weight); // Choose the maximum weight
- minWeight = Math.min(minWeight, weight); // Choose the minimum weight
- if (weight > 0) {
- nonZeroWeightedInvokers.add(invokers.get(i));
- }
- }
- AtomicPositiveInteger sequence = sequences.get(key);
- if (sequence == null) {
- sequences.putIfAbsent(key, new AtomicPositiveInteger());
- sequence = sequences.get(key);
+ ConcurrentMap map = methodWeightMap.get(key);
+ if (map == null) {
+ methodWeightMap.putIfAbsent(key, new ConcurrentHashMap());
+ map = methodWeightMap.get(key);
}
-
- if (maxWeight > 0 && minWeight < maxWeight) {
- AtomicPositiveInteger indexSeq = indexSeqs.get(key);
- if (indexSeq == null) {
- indexSeqs.putIfAbsent(key, new AtomicPositiveInteger(-1));
- indexSeq = indexSeqs.get(key);
+ int totalWeight = 0;
+ long maxCurrent = Long.MIN_VALUE;
+ long now = System.currentTimeMillis();
+ Invoker selectedInvoker = null;
+ WeightedRoundRobin selectedWRR = null;
+ for (Invoker invoker : invokers) {
+ String identifyString = invoker.getUrl().toIdentityString();
+ WeightedRoundRobin weightedRoundRobin = map.get(identifyString);
+ int weight = getWeight(invoker, invocation);
+ if (weight < 0) {
+ weight = 0;
}
- length = nonZeroWeightedInvokers.size();
- while (true) {
- int index = indexSeq.incrementAndGet() % length;
- int currentWeight;
- if (index == 0) {
- currentWeight = sequence.incrementAndGet() % maxWeight;
- } else {
- currentWeight = sequence.get() % maxWeight;
- }
- if (getWeight(nonZeroWeightedInvokers.get(index), invocation) > currentWeight) {
- return nonZeroWeightedInvokers.get(index);
+ if (weightedRoundRobin == null) {
+ weightedRoundRobin = new WeightedRoundRobin();
+ weightedRoundRobin.setWeight(weight);
+ map.putIfAbsent(identifyString, weightedRoundRobin);
+ weightedRoundRobin = map.get(identifyString);
+ }
+ if (weight != weightedRoundRobin.getWeight()) {
+ //weight changed
+ weightedRoundRobin.setWeight(weight);
+ }
+ long cur = weightedRoundRobin.increaseCurrent();
+ weightedRoundRobin.setLastUpdate(now);
+ if (cur > maxCurrent) {
+ maxCurrent = cur;
+ selectedInvoker = invoker;
+ selectedWRR = weightedRoundRobin;
+ }
+ totalWeight += weight;
+ }
+ if (!updateLock.get() && invokers.size() != map.size()) {
+ if (updateLock.compareAndSet(false, true)) {
+ try {
+ // copy -> modify -> update reference
+ ConcurrentMap newMap = new ConcurrentHashMap();
+ newMap.putAll(map);
+ Iterator> it = newMap.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry item = it.next();
+ if (now - item.getValue().getLastUpdate() > RECYCLE_PERIOD) {
+ it.remove();
+ }
+ }
+ methodWeightMap.put(key, newMap);
+ } finally {
+ updateLock.set(false);
}
}
}
- // Round robin
- return invokers.get(sequence.getAndIncrement() % length);
+ if (selectedInvoker != null) {
+ selectedWRR.sel(totalWeight);
+ return selectedInvoker;
+ }
+ // should not happen here
+ return invokers.get(0);
}
+
}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java
index 503ede9430ba..f45741ea97b1 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java
@@ -42,7 +42,7 @@
* ConditionRouter
*
*/
-public class ConditionRouter implements Router, Comparable {
+public class ConditionRouter implements Router {
private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class);
private static Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
index 38fd6166effc..4bcb43b7c08f 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
@@ -16,7 +16,6 @@
*/
package org.apache.dubbo.rpc.cluster.router.tag;
-
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
@@ -34,7 +33,7 @@
/**
* TagRouter
*/
-public class TagRouter implements Router, Comparable {
+public class TagRouter implements Router {
private static final Logger logger = LoggerFactory.getLogger(TagRouter.class);
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java
index 05ad427ce6eb..f827b08d51fb 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterFactory.java
@@ -16,7 +16,6 @@
*/
package org.apache.dubbo.rpc.cluster.router.tag;
-
import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.cluster.Router;
import org.apache.dubbo.rpc.cluster.RouterFactory;
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
index 59b16ed500d5..e8b80595e7da 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
@@ -26,10 +26,10 @@
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.dubbo.rpc.cluster.LoadBalance;
import org.apache.dubbo.rpc.support.RpcUtils;
@@ -138,10 +138,12 @@ protected Invoker select(LoadBalance loadbalance, Invocation invocation, List
}
private Invoker doSelect(LoadBalance loadbalance, Invocation invocation, List> invokers, List> selected) throws RpcException {
- if (invokers == null || invokers.isEmpty())
+ if (invokers == null || invokers.isEmpty()) {
return null;
- if (invokers.size() == 1)
+ }
+ if (invokers.size() == 1) {
return invokers.get(0);
+ }
Invoker invoker = loadbalance.select(invokers, getUrl(), invocation);
//If the `invoker` is in the `selected` or invoker is unavailable && availablecheck is true, reselect.
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java
index 25d4704602dc..0ae150f4be3d 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java
@@ -53,8 +53,8 @@ public FailoverClusterInvoker(Directory directory) {
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public Result doInvoke(Invocation invocation, final List> invokers, LoadBalance loadbalance) throws RpcException {
- List> copyinvokers = invokers;
- checkInvokers(copyinvokers, invocation);
+ List> copyInvokers = invokers;
+ checkInvokers(copyInvokers, invocation);
String methodName = RpcUtils.getMethodName(invocation);
int len = getUrl().getMethodParameter(methodName, Constants.RETRIES_KEY, Constants.DEFAULT_RETRIES) + 1;
if (len <= 0) {
@@ -62,18 +62,18 @@ public Result doInvoke(Invocation invocation, final List> invokers, L
}
// retry loop.
RpcException le = null; // last exception.
- List> invoked = new ArrayList>(copyinvokers.size()); // invoked invokers.
+ List> invoked = new ArrayList>(copyInvokers.size()); // invoked invokers.
Set providers = new HashSet(len);
for (int i = 0; i < len; i++) {
//Reselect before retry to avoid a change of candidate `invokers`.
//NOTE: if `invokers` changed, then `invoked` also lose accuracy.
if (i > 0) {
checkWhetherDestroyed();
- copyinvokers = list(invocation);
+ copyInvokers = list(invocation);
// check again
- checkInvokers(copyinvokers, invocation);
+ checkInvokers(copyInvokers, invocation);
}
- Invoker invoker = select(loadbalance, invocation, copyinvokers, invoked);
+ Invoker invoker = select(loadbalance, invocation, copyInvokers, invoked);
invoked.add(invoker);
RpcContext.getContext().setInvokers((List) invoked);
try {
@@ -83,7 +83,7 @@ public Result doInvoke(Invocation invocation, final List> invokers, L
+ " in the service " + getInterface().getName()
+ " was successful by the provider " + invoker.getUrl().getAddress()
+ ", but there have been failed providers " + providers
- + " (" + providers.size() + "/" + copyinvokers.size()
+ + " (" + providers.size() + "/" + copyInvokers.size()
+ ") from the registry " + directory.getUrl().getAddress()
+ " on the consumer " + NetUtils.getLocalHost()
+ " using the dubbo version " + Version.getVersion() + ". Last error is: "
@@ -104,7 +104,7 @@ public Result doInvoke(Invocation invocation, final List> invokers, L
throw new RpcException(le.getCode(), "Failed to invoke the method "
+ methodName + " in the service " + getInterface().getName()
+ ". Tried " + len + " times of the providers " + providers
- + " (" + providers.size() + "/" + copyinvokers.size()
+ + " (" + providers.size() + "/" + copyInvokers.size()
+ ") from the registry " + directory.getUrl().getAddress()
+ " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
+ Version.getVersion() + ". Last error is: "
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java
index ded3ad6af694..869ac524464c 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java
@@ -114,12 +114,12 @@ public int testSticky(String methodName, boolean check) {
given(invoker1.invoke(invocation)).willReturn(result);
given(invoker1.isAvailable()).willReturn(true);
- given(invoker1.getUrl()).willReturn(url);
+ given(invoker1.getUrl()).willReturn(url.setPort(1));
given(invoker1.getInterface()).willReturn(StickyTest.class);
given(invoker2.invoke(invocation)).willReturn(result);
given(invoker2.isAvailable()).willReturn(true);
- given(invoker2.getUrl()).willReturn(url);
+ given(invoker2.getUrl()).willReturn(url.setPort(2));
given(invoker2.getInterface()).willReturn(StickyTest.class);
invocation.setMethodName(methodName);
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java
index f9db9aeca091..f2af3d39dff1 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/LoadBalanceBaseTest.java
@@ -29,6 +29,9 @@
import org.junit.BeforeClass;
import org.junit.Test;
+import com.alibaba.fastjson.JSON;
+import org.mockito.Mockito;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -114,16 +117,21 @@ public void setUp() throws Exception {
public Map getInvokeCounter(int runs, String loadbalanceName) {
Map counter = new ConcurrentHashMap();
- LoadBalance lb = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName);
+ LoadBalance lb = getLoadBalance(loadbalanceName);
for (Invoker invoker : invokers) {
counter.put(invoker, new AtomicLong(0));
}
+ URL url = invokers.get(0).getUrl();
for (int i = 0; i < runs; i++) {
- Invoker sinvoker = lb.select(invokers, invokers.get(0).getUrl(), invocation);
+ Invoker sinvoker = lb.select(invokers, url, invocation);
counter.get(sinvoker).incrementAndGet();
}
return counter;
}
+
+ protected AbstractLoadBalance getLoadBalance(String loadbalanceName) {
+ return (AbstractLoadBalance) ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName);
+ }
@Test
public void testLoadBalanceWarmup() {
@@ -153,44 +161,83 @@ private static int calculateDefaultWarmupWeight(int uptime) {
}
/*------------------------------------test invokers for weight---------------------------------------*/
+
+ protected static class InvokeResult {
+ private AtomicLong count = new AtomicLong();
+ private int weight = 0;
+ private int totalWeight = 0;
+
+ public InvokeResult(int weight) {
+ this.weight = weight;
+ }
+
+ public AtomicLong getCount() {
+ return count;
+ }
+
+ public int getWeight() {
+ return weight;
+ }
+
+ public int getTotalWeight() {
+ return totalWeight;
+ }
+
+ public void setTotalWeight(int totalWeight) {
+ this.totalWeight = totalWeight;
+ }
+
+ public int getExpected(int runCount) {
+ return getWeight() * runCount / getTotalWeight();
+ }
+
+ public float getDeltaPercentage(int runCount) {
+ int expected = getExpected(runCount);
+ return Math.abs((expected - getCount().get()) * 100.0f / expected);
+ }
+
+ @Override
+ public String toString() {
+ return JSON.toJSONString(this);
+ }
+ }
protected List> weightInvokers = new ArrayList>();
protected Invoker weightInvoker1;
protected Invoker weightInvoker2;
protected Invoker weightInvoker3;
+ protected Invoker weightInvokerTmp;
@Before
public void before() throws Exception {
- weightInvoker1 = mock(Invoker.class);
- weightInvoker2 = mock(Invoker.class);
- weightInvoker3 = mock(Invoker.class);
+ weightInvoker1 = mock(Invoker.class, Mockito.withSettings().stubOnly());
+ weightInvoker2 = mock(Invoker.class, Mockito.withSettings().stubOnly());
+ weightInvoker3 = mock(Invoker.class, Mockito.withSettings().stubOnly());
+ weightInvokerTmp = mock(Invoker.class, Mockito.withSettings().stubOnly());
weightTestInvocation = new RpcInvocation();
weightTestInvocation.setMethodName("test");
- URL url1 = URL.valueOf("test1://0:1/DemoService");
- url1 = url1.addParameter(Constants.WEIGHT_KEY, 1);
- url1 = url1.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 1);
- url1 = url1.addParameter("active", 0);
-
- URL url2 = URL.valueOf("test2://0:9/DemoService");
- url2 = url2.addParameter(Constants.WEIGHT_KEY, 9);
- url2 = url2.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 9);
- url2 = url2.addParameter("active", 0);
-
- URL url3 = URL.valueOf("test3://1:6/DemoService");
- url3 = url3.addParameter(Constants.WEIGHT_KEY, 6);
- url3 = url3.addParameter(weightTestInvocation.getMethodName() + "." + Constants.WEIGHT_KEY, 6);
- url3 = url3.addParameter("active", 1);
+ URL url1 = URL.valueOf("test1://127.0.0.1:11/DemoService?weight=1&active=0");
+ URL url2 = URL.valueOf("test2://127.0.0.1:12/DemoService?weight=9&active=0");
+ URL url3 = URL.valueOf("test3://127.0.0.1:13/DemoService?weight=6&active=1");
+ URL urlTmp = URL.valueOf("test4://127.0.0.1:9999/DemoService?weight=11&active=0");
given(weightInvoker1.isAvailable()).willReturn(true);
+ given(weightInvoker1.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(weightInvoker1.getUrl()).willReturn(url1);
-
+
given(weightInvoker2.isAvailable()).willReturn(true);
+ given(weightInvoker2.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(weightInvoker2.getUrl()).willReturn(url2);
-
+
given(weightInvoker3.isAvailable()).willReturn(true);
+ given(weightInvoker3.getInterface()).willReturn(LoadBalanceBaseTest.class);
given(weightInvoker3.getUrl()).willReturn(url3);
+
+ given(weightInvokerTmp.isAvailable()).willReturn(true);
+ given(weightInvokerTmp.getInterface()).willReturn(LoadBalanceBaseTest.class);
+ given(weightInvokerTmp.getUrl()).willReturn(urlTmp);
weightInvokers.add(weightInvoker1);
weightInvokers.add(weightInvoker2);
@@ -203,4 +250,25 @@ public void before() throws Exception {
// weightTestRpcStatus3 active is 1
RpcStatus.beginCount(weightInvoker3.getUrl(), weightTestInvocation.getMethodName());
}
+
+ protected Map getWeightedInvokeResult(int runs, String loadbalanceName) {
+ Map counter = new ConcurrentHashMap();
+ AbstractLoadBalance lb = getLoadBalance(loadbalanceName);
+ int totalWeight = 0;
+ for (int i = 0; i < weightInvokers.size(); i ++) {
+ InvokeResult invokeResult = new InvokeResult(lb.getWeight(weightInvokers.get(i), weightTestInvocation));
+ counter.put(weightInvokers.get(i), invokeResult);
+ totalWeight += invokeResult.getWeight();
+ }
+ for (InvokeResult invokeResult : counter.values()) {
+ invokeResult.setTotalWeight(totalWeight);
+ }
+ URL url = weightInvokers.get(0).getUrl();
+ for (int i = 0; i < runs; i++) {
+ Invoker sinvoker = lb.select(weightInvokers, url, weightTestInvocation);
+ counter.get(sinvoker).getCount().incrementAndGet();
+ }
+ return counter;
+ }
+
}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java
index e10f69fea62e..5242f90badaf 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java
@@ -20,10 +20,29 @@
import org.junit.Assert;
import org.junit.Test;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
public class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest {
+
+ private void assertStrictWRRResult(int loop, Map resultMap) {
+ int invokeCount = 0;
+ for (InvokeResult invokeResult : resultMap.values()) {
+ int count = (int) invokeResult.getCount().get();
+ // Because it's a strictly round robin, so the abs delta should be < 10 too
+ Assert.assertTrue("delta with expected count should < 10",
+ Math.abs(invokeResult.getExpected(loop) - count) < 10);
+ invokeCount += count;
+ }
+ Assert.assertEquals("select failed!", invokeCount, loop);
+ }
+
@Test
public void testRoundRobinLoadBalanceSelect() {
int runs = 10000;
@@ -36,33 +55,114 @@ public void testRoundRobinLoadBalanceSelect() {
@Test
public void testSelectByWeight() {
- int sumInvoker1 = 0;
- int sumInvoker2 = 0;
- int sumInvoker3 = 0;
- int loop = 10000;
-
- RoundRobinLoadBalance lb = new RoundRobinLoadBalance();
- for (int i = 0; i < loop; i++) {
- Invoker selected = lb.select(weightInvokers, null, weightTestInvocation);
-
- if (selected.getUrl().getProtocol().equals("test1")) {
- sumInvoker1++;
- }
-
- if (selected.getUrl().getProtocol().equals("test2")) {
- sumInvoker2++;
+ final Map totalMap = new HashMap();
+ final AtomicBoolean shouldBegin = new AtomicBoolean(false);
+ final int runs = 10000;
+ List threads = new ArrayList();
+ int threadNum = 10;
+ for (int i = 0; i < threadNum; i ++) {
+ threads.add(new Thread() {
+ @Override
+ public void run() {
+ while (!shouldBegin.get()) {
+ try {
+ sleep(5);
+ } catch (InterruptedException e) {
+ }
+ }
+ Map resultMap = getWeightedInvokeResult(runs, RoundRobinLoadBalance.NAME);
+ synchronized (totalMap) {
+ for (Entry entry : resultMap.entrySet()) {
+ if (!totalMap.containsKey(entry.getKey())) {
+ totalMap.put(entry.getKey(), entry.getValue());
+ } else {
+ totalMap.get(entry.getKey()).getCount().addAndGet(entry.getValue().getCount().get());
+ }
+ }
+ }
+ }
+ });
+ }
+ for (Thread thread : threads) {
+ thread.start();
+ }
+ // let's rock it!
+ shouldBegin.set(true);
+ for (Thread thread : threads) {
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
}
-
- if (selected.getUrl().getProtocol().equals("test3")) {
- sumInvoker3++;
+ }
+ assertStrictWRRResult(runs * threadNum, totalMap);
+ }
+
+ @Test
+ public void testNodeCacheShouldNotRecycle() {
+ int loop = 10000;
+ //tmperately add a new invoker
+ weightInvokers.add(weightInvokerTmp);
+ try {
+ Map resultMap = getWeightedInvokeResult(loop, RoundRobinLoadBalance.NAME);
+ assertStrictWRRResult(loop, resultMap);
+
+ // inner nodes cache judgement
+ RoundRobinLoadBalance lb = (RoundRobinLoadBalance)getLoadBalance(RoundRobinLoadBalance.NAME);
+ Assert.assertEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
+
+ weightInvokers.remove(weightInvokerTmp);
+
+ resultMap = getWeightedInvokeResult(loop, RoundRobinLoadBalance.NAME);
+ assertStrictWRRResult(loop, resultMap);
+
+ Assert.assertNotEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
+ } finally {
+ //prevent other UT's failure
+ weightInvokers.remove(weightInvokerTmp);
+ }
+ }
+
+ @Test
+ public void testNodeCacheShouldRecycle() {
+ {
+ Field recycleTimeField = null;
+ try {
+ //change recycle time to 1 ms
+ recycleTimeField = RoundRobinLoadBalance.class.getDeclaredField("RECYCLE_PERIOD");
+ recycleTimeField.setAccessible(true);
+ recycleTimeField.setInt(RoundRobinLoadBalance.class, 10);
+ } catch (NoSuchFieldException e) {
+ Assert.assertTrue("getField failed", true);
+ } catch (SecurityException e) {
+ Assert.assertTrue("getField failed", true);
+ } catch (IllegalArgumentException e) {
+ Assert.assertTrue("getField failed", true);
+ } catch (IllegalAccessException e) {
+ Assert.assertTrue("getField failed", true);
}
}
-
- // 1 : 9 : 6
- System.out.println(sumInvoker1);
- System.out.println(sumInvoker2);
- System.out.println(sumInvoker3);
- Assert.assertEquals("select failed!", sumInvoker1 + sumInvoker2 + sumInvoker3, loop);
+
+ int loop = 10000;
+ //tmperately add a new invoker
+ weightInvokers.add(weightInvokerTmp);
+ try {
+ Map resultMap = getWeightedInvokeResult(loop, RoundRobinLoadBalance.NAME);
+ assertStrictWRRResult(loop, resultMap);
+
+ // inner nodes cache judgement
+ RoundRobinLoadBalance lb = (RoundRobinLoadBalance)getLoadBalance(RoundRobinLoadBalance.NAME);
+ Assert.assertEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
+
+ weightInvokers.remove(weightInvokerTmp);
+
+ resultMap = getWeightedInvokeResult(loop, RoundRobinLoadBalance.NAME);
+ assertStrictWRRResult(loop, resultMap);
+
+ Assert.assertEquals(weightInvokers.size(), lb.getInvokerAddrList(weightInvokers, weightTestInvocation).size());
+ } finally {
+ //prevent other UT's failure
+ weightInvokers.remove(weightInvokerTmp);
+ }
}
-
+
}
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java
index 8a01a99ec5e5..3d94b16b8200 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouterTest.java
@@ -17,22 +17,20 @@
package org.apache.dubbo.rpc.cluster.router.script;
+import java.util.ArrayList;
+import java.util.List;
+
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.cluster.Router;
import org.apache.dubbo.rpc.cluster.router.MockInvoker;
-
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
-import javax.script.ScriptException;
-import java.util.ArrayList;
-import java.util.List;
-
public class ScriptRouterTest {
private URL SCRIPT_URL = URL.valueOf("script://javascript?type=javascript");
@@ -85,5 +83,48 @@ public void testRoutePickInvokers() {
Assert.assertEquals(invoker3, filteredInvokers.get(1));
}
- //TODO Add tests for abnormal scene
+ @Test
+ public void testRouteHostFilter() {
+ List> invokers = new ArrayList>();
+ MockInvoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.134.108.1:20880/com.dubbo.HelloService"));
+ MockInvoker invoker2 = new MockInvoker(URL.valueOf("dubbo://10.134.108.2:20880/com.dubbo.HelloService"));
+ MockInvoker invoker3 = new MockInvoker(URL.valueOf("dubbo://10.134.108.3:20880/com.dubbo.HelloService"));
+ invokers.add(invoker1);
+ invokers.add(invoker2);
+ invokers.add(invoker3);
+
+ String script = "function route(invokers, invocation, context){ " +
+ " var result = new java.util.ArrayList(invokers.size()); " +
+ " var targetHost = new java.util.ArrayList(); " +
+ " targetHost.add(\"10.134.108.2\"); " +
+ " for (var i = 0; i < invokers.length; i++) { " +
+ " if(targetHost.contains(invokers[i].getUrl().getHost())){ " +
+ " result.add(invokers[i]); " +
+ " } " +
+ " } " +
+ " return result; " +
+ "} " +
+ "route(invokers, invocation, context) ";
+
+ Router router = new ScriptRouterFactory().getRouter(getRouteUrl(script));
+ List> routeResult = router.route(invokers, invokers.get(0).getUrl(), new RpcInvocation());
+ Assert.assertEquals(1, routeResult.size());
+ Assert.assertEquals(invoker2,routeResult.get(0));
+ }
+
+ @Test
+ public void testRoute_throwException() {
+ List> invokers = new ArrayList>();
+ MockInvoker invoker1 = new MockInvoker(URL.valueOf("dubbo://10.134.108.1:20880/com.dubbo.HelloService"));
+ MockInvoker invoker2 = new MockInvoker(URL.valueOf("dubbo://10.134.108.2:20880/com.dubbo.HelloService"));
+ MockInvoker invoker3 = new MockInvoker(URL.valueOf("dubbo://10.134.108.3:20880/com.dubbo.HelloService"));
+ invokers.add(invoker1);
+ invokers.add(invoker2);
+ invokers.add(invoker3);
+
+ String script = "/";
+ Router router = new ScriptRouterFactory().getRouter(getRouteUrl(script));
+ List> routeResult = router.route(invokers, invokers.get(0).getUrl(), new RpcInvocation());
+ Assert.assertEquals(3, routeResult.size());
+ }
}
\ No newline at end of file
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterTest.java
index 839af44efe9f..a3ba09240139 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterTest.java
@@ -26,8 +26,8 @@
import org.apache.dubbo.rpc.cluster.Router;
import org.apache.dubbo.rpc.cluster.RouterFactory;
import org.apache.dubbo.rpc.cluster.router.MockInvoker;
+import org.junit.After;
import org.junit.Assert;
-import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -47,8 +47,9 @@ public class TagRouterTest {
public static void setUpBeforeClass() throws Exception {
}
- @Before
- public void setUp() throws Exception {
+ @After
+ public void teardown() throws Exception {
+ RpcContext.getContext().clearAttachments();
}
@Test
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java
index 247a719ad84e..2039b0a0e4c2 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java
@@ -34,6 +34,7 @@
import org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance;
import org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance;
+import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -74,6 +75,11 @@ public class AbstractClusterInvokerTest {
public static void setUpBeforeClass() throws Exception {
}
+ @After
+ public void teardown() throws Exception {
+ RpcContext.getContext().clearAttachments();
+ }
+
@SuppressWarnings({"unchecked"})
@Before
public void setUp() throws Exception {
@@ -90,27 +96,27 @@ public void setUp() throws Exception {
given(invoker1.isAvailable()).willReturn(false);
given(invoker1.getInterface()).willReturn(IHelloService.class);
- given(invoker1.getUrl()).willReturn(turl.addParameter("name", "invoker1"));
+ given(invoker1.getUrl()).willReturn(turl.setPort(1).addParameter("name", "invoker1"));
given(invoker2.isAvailable()).willReturn(true);
given(invoker2.getInterface()).willReturn(IHelloService.class);
- given(invoker2.getUrl()).willReturn(turl.addParameter("name", "invoker2"));
+ given(invoker2.getUrl()).willReturn(turl.setPort(2).addParameter("name", "invoker2"));
given(invoker3.isAvailable()).willReturn(false);
given(invoker3.getInterface()).willReturn(IHelloService.class);
- given(invoker3.getUrl()).willReturn(turl.addParameter("name", "invoker3"));
+ given(invoker3.getUrl()).willReturn(turl.setPort(3).addParameter("name", "invoker3"));
given(invoker4.isAvailable()).willReturn(true);
given(invoker4.getInterface()).willReturn(IHelloService.class);
- given(invoker4.getUrl()).willReturn(turl.addParameter("name", "invoker4"));
+ given(invoker4.getUrl()).willReturn(turl.setPort(4).addParameter("name", "invoker4"));
given(invoker5.isAvailable()).willReturn(false);
given(invoker5.getInterface()).willReturn(IHelloService.class);
- given(invoker5.getUrl()).willReturn(turl.addParameter("name", "invoker5"));
+ given(invoker5.getUrl()).willReturn(turl.setPort(5).addParameter("name", "invoker5"));
given(mockedInvoker1.isAvailable()).willReturn(false);
given(mockedInvoker1.getInterface()).willReturn(IHelloService.class);
- given(mockedInvoker1.getUrl()).willReturn(turl.setProtocol("mock"));
+ given(mockedInvoker1.getUrl()).willReturn(turl.setPort(999).setProtocol("mock"));
invokers.add(invoker1);
dic = new StaticDirectory(url, invokers, null);
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
index 4d6e7585cf24..18ad19f5246e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
@@ -19,6 +19,7 @@
import java.util.concurrent.ExecutorService;
import java.util.regex.Pattern;
+
/**
* Constants
*/
@@ -246,6 +247,23 @@ public class Constants {
public static final String HEARTBEAT_KEY = "heartbeat";
+ /**
+ * Every heartbeat duration / HEATBEAT_CHECK_TICK, check if a heartbeat should be sent. Every heartbeat timeout
+ * duration / HEATBEAT_CHECK_TICK, check if a connection should be closed on server side, and if reconnect on
+ * client side
+ */
+ public static final int HEARTBEAT_CHECK_TICK = 3;
+
+ /**
+ * the least heartbeat during is 1000 ms.
+ */
+ public static final long LEAST_HEARTBEAT_DURATION = 1000;
+
+ /**
+ * ticks per wheel. Currently only contains two tasks, so 16 locations are enough
+ */
+ public static final int TICKS_PER_WHEEL = 16;
+
public static final String HEARTBEAT_TIMEOUT_KEY = "heartbeat.timeout";
public static final String CONNECT_TIMEOUT_KEY = "connect.timeout";
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java
index 39999279ecdd..529d3feb910c 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java
@@ -19,6 +19,7 @@
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import java.io.UnsupportedEncodingException;
@@ -42,20 +43,11 @@ public Parameters(String... pairs) {
}
public Parameters(Map parameters) {
- this.parameters = Collections.unmodifiableMap(parameters != null ? new HashMap(parameters) : new HashMap(0));
+ this.parameters = Collections.unmodifiableMap(parameters != null ? new HashMap<>(parameters) : new HashMap<>(0));
}
private static Map toMap(String... pairs) {
- Map parameters = new HashMap();
- if (pairs.length > 0) {
- if (pairs.length % 2 != 0) {
- throw new IllegalArgumentException("pairs must be even.");
- }
- for (int i = 0; i < pairs.length; i = i + 2) {
- parameters.put(pairs[i], pairs[i + 1]);
- }
- }
- return parameters;
+ return CollectionUtils.toStringMap(pairs);
}
public static Parameters parseParameters(String query) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
index a83ca91e227e..7a092ffd25de 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
@@ -118,7 +118,7 @@ public URL(String protocol, String host, int port) {
this(protocol, null, null, host, port, null, (Map) null);
}
- public URL(String protocol, String host, int port, String[] pairs) { // varargs ... confilict with the following path argument, use array instead.
+ public URL(String protocol, String host, int port, String[] pairs) { // varargs ... conflict with the following path argument, use array instead.
this(protocol, null, null, host, port, null, CollectionUtils.toStringMap(pairs));
}
@@ -206,14 +206,18 @@ public static URL valueOf(String url) {
}
i = url.indexOf("://");
if (i >= 0) {
- if (i == 0) throw new IllegalStateException("url missing protocol: \"" + url + "\"");
+ if (i == 0) {
+ throw new IllegalStateException("url missing protocol: \"" + url + "\"");
+ }
protocol = url.substring(0, i);
url = url.substring(i + 3);
} else {
// case: file:/path/to/file.txt
i = url.indexOf(":/");
if (i >= 0) {
- if (i == 0) throw new IllegalStateException("url missing protocol: \"" + url + "\"");
+ if (i == 0) {
+ throw new IllegalStateException("url missing protocol: \"" + url + "\"");
+ }
protocol = url.substring(0, i);
url = url.substring(i + 1);
}
@@ -246,7 +250,9 @@ public static URL valueOf(String url) {
url = url.substring(0, i);
}
}
- if (url.length() > 0) host = url;
+ if (url.length() > 0) {
+ host = url;
+ }
return new URL(protocol, username, password, host, port, path, parameters);
}
@@ -915,17 +921,23 @@ public URL addParameter(String key, double value) {
}
public URL addParameter(String key, Enum> value) {
- if (value == null) return this;
+ if (value == null) {
+ return this;
+ }
return addParameter(key, String.valueOf(value));
}
public URL addParameter(String key, Number value) {
- if (value == null) return this;
+ if (value == null) {
+ return this;
+ }
return addParameter(key, String.valueOf(value));
}
public URL addParameter(String key, CharSequence value) {
- if (value == null || value.length() == 0) return this;
+ if (value == null || value.length() == 0) {
+ return this;
+ }
return addParameter(key, String.valueOf(value));
}
@@ -984,7 +996,9 @@ public URL addParameters(Map parameters) {
}
}
// return immediately if there's no change
- if (hasAndEqual) return this;
+ if (hasAndEqual) {
+ return this;
+ }
Map map = new HashMap(getParameters());
map.putAll(parameters);
@@ -1055,35 +1069,47 @@ public URL clearParameters() {
}
public String getRawParameter(String key) {
- if ("protocol".equals(key))
+ if ("protocol".equals(key)) {
return protocol;
- if ("username".equals(key))
+ }
+ if ("username".equals(key)) {
return username;
- if ("password".equals(key))
+ }
+ if ("password".equals(key)) {
return password;
- if ("host".equals(key))
+ }
+ if ("host".equals(key)) {
return host;
- if ("port".equals(key))
+ }
+ if ("port".equals(key)) {
return String.valueOf(port);
- if ("path".equals(key))
+ }
+ if ("path".equals(key)) {
return path;
+ }
return getParameter(key);
}
public Map toMap() {
Map map = new HashMap(parameters);
- if (protocol != null)
+ if (protocol != null) {
map.put("protocol", protocol);
- if (username != null)
+ }
+ if (username != null) {
map.put("username", username);
- if (password != null)
+ }
+ if (password != null) {
map.put("password", password);
- if (host != null)
+ }
+ if (host != null) {
map.put("host", host);
- if (port > 0)
+ }
+ if (port > 0) {
map.put("port", String.valueOf(port));
- if (path != null)
+ }
+ if (path != null) {
map.put("path", path);
+ }
return map;
}
@@ -1218,7 +1244,9 @@ public InetSocketAddress toInetSocketAddress() {
public String getServiceKey() {
String inf = getServiceInterface();
- if (inf == null) return null;
+ if (inf == null) {
+ return null;
+ }
StringBuilder buf = new StringBuilder();
String group = getParameter(Constants.GROUP_KEY);
if (group != null && group.length() > 0) {
@@ -1359,45 +1387,61 @@ public int hashCode() {
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
URL other = (URL) obj;
if (host == null) {
- if (other.host != null)
+ if (other.host != null) {
return false;
- } else if (!host.equals(other.host))
+ }
+ } else if (!host.equals(other.host)) {
return false;
+ }
if (parameters == null) {
- if (other.parameters != null)
+ if (other.parameters != null) {
return false;
- } else if (!parameters.equals(other.parameters))
+ }
+ } else if (!parameters.equals(other.parameters)) {
return false;
+ }
if (password == null) {
- if (other.password != null)
+ if (other.password != null) {
return false;
- } else if (!password.equals(other.password))
+ }
+ } else if (!password.equals(other.password)) {
return false;
+ }
if (path == null) {
- if (other.path != null)
+ if (other.path != null) {
return false;
- } else if (!path.equals(other.path))
+ }
+ } else if (!path.equals(other.path)) {
return false;
- if (port != other.port)
+ }
+ if (port != other.port) {
return false;
+ }
if (protocol == null) {
- if (other.protocol != null)
+ if (other.protocol != null) {
return false;
- } else if (!protocol.equals(other.protocol))
+ }
+ } else if (!protocol.equals(other.protocol)) {
return false;
+ }
if (username == null) {
- if (other.username != null)
+ if (other.username != null) {
return false;
- } else if (!username.equals(other.username))
+ }
+ } else if (!username.equals(other.username)) {
return false;
+ }
return true;
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java
index 983cbb98e1dc..5c0ab763a70c 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java
@@ -41,9 +41,9 @@ public final class Version {
/**
* For protocol compatibility purpose.
- * Because {@link #isSupportResponseAttatchment} is checked for every call, int compare expect to has higher performance than string.
+ * Because {@link #isSupportResponseAttachment} is checked for every call, int compare expect to has higher performance than string.
*/
- private static final int LOWEST_VERSION_FOR_RESPONSE_ATTATCHMENT = 20002; // 2.0.2
+ private static final int LOWEST_VERSION_FOR_RESPONSE_ATTACHMENT = 20002; // 2.0.2
private static final Map VERSION2INT = new HashMap();
static {
@@ -62,7 +62,7 @@ public static String getVersion() {
return VERSION;
}
- public static boolean isSupportResponseAttatchment(String version) {
+ public static boolean isSupportResponseAttachment(String version) {
if (version == null || version.length() == 0) {
return false;
}
@@ -72,7 +72,7 @@ public static boolean isSupportResponseAttatchment(String version) {
return false;
}
- return iVersion >= LOWEST_VERSION_FOR_RESPONSE_ATTATCHMENT;
+ return iVersion >= LOWEST_VERSION_FOR_RESPONSE_ATTACHMENT;
}
public static int getIntVersion(String version) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java
index ea9f582648ac..a1bdc7af5eb6 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java
@@ -399,14 +399,16 @@ private static Object instantiateForDeserialize(JavaBeanDescriptor beanDescripto
}
result = Array.newInstance(componentType, beanDescriptor.propertySize());
cache.put(beanDescriptor, result);
- } else try {
- Class> cl = name2Class(loader, beanDescriptor.getClassName());
- result = instantiate(cl);
- cache.put(beanDescriptor, result);
- } catch (ClassNotFoundException e) {
- throw new RuntimeException(e.getMessage(), e);
- } catch (Exception e) {
- throw new RuntimeException(e.getMessage(), e);
+ } else {
+ try {
+ Class> cl = name2Class(loader, beanDescriptor.getClassName());
+ result = instantiate(cl);
+ cache.put(beanDescriptor, result);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
}
return result;
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java
index d9cee452a907..c044c7b297a0 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java
@@ -1,391 +1,391 @@
-/*
- * 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.common.bytecode;
-
-import org.apache.dubbo.common.utils.ClassHelper;
-import org.apache.dubbo.common.utils.ReflectUtils;
-
-import javassist.CannotCompileException;
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.CtConstructor;
-import javassist.CtField;
-import javassist.CtMethod;
-import javassist.CtNewConstructor;
-import javassist.CtNewMethod;
-import javassist.LoaderClassPath;
-import javassist.NotFoundException;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * ClassGenerator
- */
-public final class ClassGenerator {
-
- private static final AtomicLong CLASS_NAME_COUNTER = new AtomicLong(0);
- private static final String SIMPLE_NAME_TAG = "";
- private static final Map POOL_MAP = new ConcurrentHashMap(); //ClassLoader - ClassPool
- private ClassPool mPool;
- private CtClass mCtc;
- private String mClassName;
- private String mSuperClass;
- private Set mInterfaces;
- private List mFields;
- private List mConstructors;
- private List mMethods;
- private Map mCopyMethods; //
- private Map> mCopyConstructors; //
- private boolean mDefaultConstructor = false;
-
- private ClassGenerator() {
- }
-
- private ClassGenerator(ClassPool pool) {
- mPool = pool;
- }
-
- public static ClassGenerator newInstance() {
- return new ClassGenerator(getClassPool(Thread.currentThread().getContextClassLoader()));
- }
-
- public static ClassGenerator newInstance(ClassLoader loader) {
- return new ClassGenerator(getClassPool(loader));
- }
-
- public static boolean isDynamicClass(Class> cl) {
- return ClassGenerator.DC.class.isAssignableFrom(cl);
- }
-
- public static ClassPool getClassPool(ClassLoader loader) {
- if (loader == null) {
- return ClassPool.getDefault();
- }
-
- ClassPool pool = POOL_MAP.get(loader);
- if (pool == null) {
- pool = new ClassPool(true);
- pool.appendClassPath(new LoaderClassPath(loader));
- POOL_MAP.put(loader, pool);
- }
- return pool;
- }
-
- private static String modifier(int mod) {
- StringBuilder modifier = new StringBuilder();
- if (Modifier.isPublic(mod)) {
- modifier.append("public");
- }
- if (Modifier.isProtected(mod)) {
- modifier.append("protected");
- }
- if (Modifier.isPrivate(mod)) {
- modifier.append("private");
- }
-
- if (Modifier.isStatic(mod)) {
- modifier.append(" static");
- }
- if (Modifier.isVolatile(mod)) {
- modifier.append(" volatile");
- }
-
- return modifier.toString();
- }
-
- public String getClassName() {
- return mClassName;
- }
-
- public ClassGenerator setClassName(String name) {
- mClassName = name;
- return this;
- }
-
- public ClassGenerator addInterface(String cn) {
- if (mInterfaces == null) {
- mInterfaces = new HashSet();
- }
- mInterfaces.add(cn);
- return this;
- }
-
- public ClassGenerator addInterface(Class> cl) {
- return addInterface(cl.getName());
- }
-
- public ClassGenerator setSuperClass(String cn) {
- mSuperClass = cn;
- return this;
- }
-
- public ClassGenerator setSuperClass(Class> cl) {
- mSuperClass = cl.getName();
- return this;
- }
-
- public ClassGenerator addField(String code) {
- if (mFields == null) {
- mFields = new ArrayList();
- }
- mFields.add(code);
- return this;
- }
-
- public ClassGenerator addField(String name, int mod, Class> type) {
- return addField(name, mod, type, null);
- }
-
- public ClassGenerator addField(String name, int mod, Class> type, String def) {
- StringBuilder sb = new StringBuilder();
- sb.append(modifier(mod)).append(' ').append(ReflectUtils.getName(type)).append(' ');
- sb.append(name);
- if (def != null && def.length() > 0) {
- sb.append('=');
- sb.append(def);
- }
- sb.append(';');
- return addField(sb.toString());
- }
-
- public ClassGenerator addMethod(String code) {
- if (mMethods == null) {
- mMethods = new ArrayList();
- }
- mMethods.add(code);
- return this;
- }
-
- public ClassGenerator addMethod(String name, int mod, Class> rt, Class>[] pts, String body) {
- return addMethod(name, mod, rt, pts, null, body);
- }
-
- public ClassGenerator addMethod(String name, int mod, Class> rt, Class>[] pts, Class>[] ets,
- String body) {
- StringBuilder sb = new StringBuilder();
- sb.append(modifier(mod)).append(' ').append(ReflectUtils.getName(rt)).append(' ').append(name);
- sb.append('(');
- for (int i = 0; i < pts.length; i++) {
- if (i > 0) {
- sb.append(',');
- }
- sb.append(ReflectUtils.getName(pts[i]));
- sb.append(" arg").append(i);
- }
- sb.append(')');
- if (ets != null && ets.length > 0) {
- sb.append(" throws ");
- for (int i = 0; i < ets.length; i++) {
- if (i > 0) {
- sb.append(',');
- }
- sb.append(ReflectUtils.getName(ets[i]));
- }
- }
- sb.append('{').append(body).append('}');
- return addMethod(sb.toString());
- }
-
- public ClassGenerator addMethod(Method m) {
- addMethod(m.getName(), m);
- return this;
- }
-
- public ClassGenerator addMethod(String name, Method m) {
- String desc = name + ReflectUtils.getDescWithoutMethodName(m);
- addMethod(':' + desc);
- if (mCopyMethods == null) {
- mCopyMethods = new ConcurrentHashMap(8);
- }
- mCopyMethods.put(desc, m);
- return this;
- }
-
- public ClassGenerator addConstructor(String code) {
- if (mConstructors == null) {
- mConstructors = new LinkedList();
- }
- mConstructors.add(code);
- return this;
- }
-
- public ClassGenerator addConstructor(int mod, Class>[] pts, String body) {
- return addConstructor(mod, pts, null, body);
- }
-
- public ClassGenerator addConstructor(int mod, Class>[] pts, Class>[] ets, String body) {
- StringBuilder sb = new StringBuilder();
- sb.append(modifier(mod)).append(' ').append(SIMPLE_NAME_TAG);
- sb.append('(');
- for (int i = 0; i < pts.length; i++) {
- if (i > 0) {
- sb.append(',');
- }
- sb.append(ReflectUtils.getName(pts[i]));
- sb.append(" arg").append(i);
- }
- sb.append(')');
- if (ets != null && ets.length > 0) {
- sb.append(" throws ");
- for (int i = 0; i < ets.length; i++) {
- if (i > 0) {
- sb.append(',');
- }
- sb.append(ReflectUtils.getName(ets[i]));
- }
- }
- sb.append('{').append(body).append('}');
- return addConstructor(sb.toString());
- }
-
- public ClassGenerator addConstructor(Constructor> c) {
- String desc = ReflectUtils.getDesc(c);
- addConstructor(":" + desc);
- if (mCopyConstructors == null) {
- mCopyConstructors = new ConcurrentHashMap>(4);
- }
- mCopyConstructors.put(desc, c);
- return this;
- }
-
- public ClassGenerator addDefaultConstructor() {
- mDefaultConstructor = true;
- return this;
- }
-
- public ClassPool getClassPool() {
- return mPool;
- }
-
- public Class> toClass() {
- return toClass(ClassHelper.getClassLoader(ClassGenerator.class),
- getClass().getProtectionDomain());
- }
-
- public Class> toClass(ClassLoader loader, ProtectionDomain pd) {
- if (mCtc != null) {
- mCtc.detach();
- }
- long id = CLASS_NAME_COUNTER.getAndIncrement();
- try {
- CtClass ctcs = mSuperClass == null ? null : mPool.get(mSuperClass);
- if (mClassName == null) {
- mClassName = (mSuperClass == null || javassist.Modifier.isPublic(ctcs.getModifiers())
- ? ClassGenerator.class.getName() : mSuperClass + "$sc") + id;
- }
- mCtc = mPool.makeClass(mClassName);
- if (mSuperClass != null) {
- mCtc.setSuperclass(ctcs);
- }
- mCtc.addInterface(mPool.get(DC.class.getName())); // add dynamic class tag.
- if (mInterfaces != null) {
- for (String cl : mInterfaces) {
- mCtc.addInterface(mPool.get(cl));
- }
- }
- if (mFields != null) {
- for (String code : mFields) {
- mCtc.addField(CtField.make(code, mCtc));
- }
- }
- if (mMethods != null) {
- for (String code : mMethods) {
- if (code.charAt(0) == ':') {
- mCtc.addMethod(CtNewMethod.copy(getCtMethod(mCopyMethods.get(code.substring(1))),
- code.substring(1, code.indexOf('(')), mCtc, null));
- } else {
- mCtc.addMethod(CtNewMethod.make(code, mCtc));
- }
- }
- }
- if (mDefaultConstructor) {
- mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc));
- }
- if (mConstructors != null) {
- for (String code : mConstructors) {
- if (code.charAt(0) == ':') {
- mCtc.addConstructor(CtNewConstructor
- .copy(getCtConstructor(mCopyConstructors.get(code.substring(1))), mCtc, null));
- } else {
- String[] sn = mCtc.getSimpleName().split("\\$+"); // inner class name include $.
- mCtc.addConstructor(
- CtNewConstructor.make(code.replaceFirst(SIMPLE_NAME_TAG, sn[sn.length - 1]), mCtc));
- }
- }
- }
- return mCtc.toClass(loader, pd);
- } catch (RuntimeException e) {
- throw e;
- } catch (NotFoundException e) {
- throw new RuntimeException(e.getMessage(), e);
- } catch (CannotCompileException e) {
- throw new RuntimeException(e.getMessage(), e);
- }
- }
-
- public void release() {
- if (mCtc != null) {
- mCtc.detach();
- }
- if (mInterfaces != null) {
- mInterfaces.clear();
- }
- if (mFields != null) {
- mFields.clear();
- }
- if (mMethods != null) {
- mMethods.clear();
- }
- if (mConstructors != null) {
- mConstructors.clear();
- }
- if (mCopyMethods != null) {
- mCopyMethods.clear();
- }
- if (mCopyConstructors != null) {
- mCopyConstructors.clear();
- }
- }
-
- private CtClass getCtClass(Class> c) throws NotFoundException {
- return mPool.get(c.getName());
- }
-
- private CtMethod getCtMethod(Method m) throws NotFoundException {
- return getCtClass(m.getDeclaringClass())
- .getMethod(m.getName(), ReflectUtils.getDescWithoutMethodName(m));
- }
-
- private CtConstructor getCtConstructor(Constructor> c) throws NotFoundException {
- return getCtClass(c.getDeclaringClass()).getConstructor(ReflectUtils.getDesc(c));
- }
-
- public static interface DC {
-
- } // dynamic class tag interface.
+/*
+ * 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.common.bytecode;
+
+import org.apache.dubbo.common.utils.ClassHelper;
+import org.apache.dubbo.common.utils.ReflectUtils;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.CtNewConstructor;
+import javassist.CtNewMethod;
+import javassist.LoaderClassPath;
+import javassist.NotFoundException;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * ClassGenerator
+ */
+public final class ClassGenerator {
+
+ private static final AtomicLong CLASS_NAME_COUNTER = new AtomicLong(0);
+ private static final String SIMPLE_NAME_TAG = "";
+ private static final Map POOL_MAP = new ConcurrentHashMap(); //ClassLoader - ClassPool
+ private ClassPool mPool;
+ private CtClass mCtc;
+ private String mClassName;
+ private String mSuperClass;
+ private Set mInterfaces;
+ private List mFields;
+ private List mConstructors;
+ private List mMethods;
+ private Map mCopyMethods; //
+ private Map> mCopyConstructors; //
+ private boolean mDefaultConstructor = false;
+
+ private ClassGenerator() {
+ }
+
+ private ClassGenerator(ClassPool pool) {
+ mPool = pool;
+ }
+
+ public static ClassGenerator newInstance() {
+ return new ClassGenerator(getClassPool(Thread.currentThread().getContextClassLoader()));
+ }
+
+ public static ClassGenerator newInstance(ClassLoader loader) {
+ return new ClassGenerator(getClassPool(loader));
+ }
+
+ public static boolean isDynamicClass(Class> cl) {
+ return ClassGenerator.DC.class.isAssignableFrom(cl);
+ }
+
+ public static ClassPool getClassPool(ClassLoader loader) {
+ if (loader == null) {
+ return ClassPool.getDefault();
+ }
+
+ ClassPool pool = POOL_MAP.get(loader);
+ if (pool == null) {
+ pool = new ClassPool(true);
+ pool.appendClassPath(new LoaderClassPath(loader));
+ POOL_MAP.put(loader, pool);
+ }
+ return pool;
+ }
+
+ private static String modifier(int mod) {
+ StringBuilder modifier = new StringBuilder();
+ if (Modifier.isPublic(mod)) {
+ modifier.append("public");
+ }
+ if (Modifier.isProtected(mod)) {
+ modifier.append("protected");
+ }
+ if (Modifier.isPrivate(mod)) {
+ modifier.append("private");
+ }
+
+ if (Modifier.isStatic(mod)) {
+ modifier.append(" static");
+ }
+ if (Modifier.isVolatile(mod)) {
+ modifier.append(" volatile");
+ }
+
+ return modifier.toString();
+ }
+
+ public String getClassName() {
+ return mClassName;
+ }
+
+ public ClassGenerator setClassName(String name) {
+ mClassName = name;
+ return this;
+ }
+
+ public ClassGenerator addInterface(String cn) {
+ if (mInterfaces == null) {
+ mInterfaces = new HashSet();
+ }
+ mInterfaces.add(cn);
+ return this;
+ }
+
+ public ClassGenerator addInterface(Class> cl) {
+ return addInterface(cl.getName());
+ }
+
+ public ClassGenerator setSuperClass(String cn) {
+ mSuperClass = cn;
+ return this;
+ }
+
+ public ClassGenerator setSuperClass(Class> cl) {
+ mSuperClass = cl.getName();
+ return this;
+ }
+
+ public ClassGenerator addField(String code) {
+ if (mFields == null) {
+ mFields = new ArrayList();
+ }
+ mFields.add(code);
+ return this;
+ }
+
+ public ClassGenerator addField(String name, int mod, Class> type) {
+ return addField(name, mod, type, null);
+ }
+
+ public ClassGenerator addField(String name, int mod, Class> type, String def) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(modifier(mod)).append(' ').append(ReflectUtils.getName(type)).append(' ');
+ sb.append(name);
+ if (def != null && def.length() > 0) {
+ sb.append('=');
+ sb.append(def);
+ }
+ sb.append(';');
+ return addField(sb.toString());
+ }
+
+ public ClassGenerator addMethod(String code) {
+ if (mMethods == null) {
+ mMethods = new ArrayList();
+ }
+ mMethods.add(code);
+ return this;
+ }
+
+ public ClassGenerator addMethod(String name, int mod, Class> rt, Class>[] pts, String body) {
+ return addMethod(name, mod, rt, pts, null, body);
+ }
+
+ public ClassGenerator addMethod(String name, int mod, Class> rt, Class>[] pts, Class>[] ets,
+ String body) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(modifier(mod)).append(' ').append(ReflectUtils.getName(rt)).append(' ').append(name);
+ sb.append('(');
+ for (int i = 0; i < pts.length; i++) {
+ if (i > 0) {
+ sb.append(',');
+ }
+ sb.append(ReflectUtils.getName(pts[i]));
+ sb.append(" arg").append(i);
+ }
+ sb.append(')');
+ if (ets != null && ets.length > 0) {
+ sb.append(" throws ");
+ for (int i = 0; i < ets.length; i++) {
+ if (i > 0) {
+ sb.append(',');
+ }
+ sb.append(ReflectUtils.getName(ets[i]));
+ }
+ }
+ sb.append('{').append(body).append('}');
+ return addMethod(sb.toString());
+ }
+
+ public ClassGenerator addMethod(Method m) {
+ addMethod(m.getName(), m);
+ return this;
+ }
+
+ public ClassGenerator addMethod(String name, Method m) {
+ String desc = name + ReflectUtils.getDescWithoutMethodName(m);
+ addMethod(':' + desc);
+ if (mCopyMethods == null) {
+ mCopyMethods = new ConcurrentHashMap(8);
+ }
+ mCopyMethods.put(desc, m);
+ return this;
+ }
+
+ public ClassGenerator addConstructor(String code) {
+ if (mConstructors == null) {
+ mConstructors = new LinkedList();
+ }
+ mConstructors.add(code);
+ return this;
+ }
+
+ public ClassGenerator addConstructor(int mod, Class>[] pts, String body) {
+ return addConstructor(mod, pts, null, body);
+ }
+
+ public ClassGenerator addConstructor(int mod, Class>[] pts, Class>[] ets, String body) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(modifier(mod)).append(' ').append(SIMPLE_NAME_TAG);
+ sb.append('(');
+ for (int i = 0; i < pts.length; i++) {
+ if (i > 0) {
+ sb.append(',');
+ }
+ sb.append(ReflectUtils.getName(pts[i]));
+ sb.append(" arg").append(i);
+ }
+ sb.append(')');
+ if (ets != null && ets.length > 0) {
+ sb.append(" throws ");
+ for (int i = 0; i < ets.length; i++) {
+ if (i > 0) {
+ sb.append(',');
+ }
+ sb.append(ReflectUtils.getName(ets[i]));
+ }
+ }
+ sb.append('{').append(body).append('}');
+ return addConstructor(sb.toString());
+ }
+
+ public ClassGenerator addConstructor(Constructor> c) {
+ String desc = ReflectUtils.getDesc(c);
+ addConstructor(":" + desc);
+ if (mCopyConstructors == null) {
+ mCopyConstructors = new ConcurrentHashMap>(4);
+ }
+ mCopyConstructors.put(desc, c);
+ return this;
+ }
+
+ public ClassGenerator addDefaultConstructor() {
+ mDefaultConstructor = true;
+ return this;
+ }
+
+ public ClassPool getClassPool() {
+ return mPool;
+ }
+
+ public Class> toClass() {
+ return toClass(ClassHelper.getClassLoader(ClassGenerator.class),
+ getClass().getProtectionDomain());
+ }
+
+ public Class> toClass(ClassLoader loader, ProtectionDomain pd) {
+ if (mCtc != null) {
+ mCtc.detach();
+ }
+ long id = CLASS_NAME_COUNTER.getAndIncrement();
+ try {
+ CtClass ctcs = mSuperClass == null ? null : mPool.get(mSuperClass);
+ if (mClassName == null) {
+ mClassName = (mSuperClass == null || javassist.Modifier.isPublic(ctcs.getModifiers())
+ ? ClassGenerator.class.getName() : mSuperClass + "$sc") + id;
+ }
+ mCtc = mPool.makeClass(mClassName);
+ if (mSuperClass != null) {
+ mCtc.setSuperclass(ctcs);
+ }
+ mCtc.addInterface(mPool.get(DC.class.getName())); // add dynamic class tag.
+ if (mInterfaces != null) {
+ for (String cl : mInterfaces) {
+ mCtc.addInterface(mPool.get(cl));
+ }
+ }
+ if (mFields != null) {
+ for (String code : mFields) {
+ mCtc.addField(CtField.make(code, mCtc));
+ }
+ }
+ if (mMethods != null) {
+ for (String code : mMethods) {
+ if (code.charAt(0) == ':') {
+ mCtc.addMethod(CtNewMethod.copy(getCtMethod(mCopyMethods.get(code.substring(1))),
+ code.substring(1, code.indexOf('(')), mCtc, null));
+ } else {
+ mCtc.addMethod(CtNewMethod.make(code, mCtc));
+ }
+ }
+ }
+ if (mDefaultConstructor) {
+ mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc));
+ }
+ if (mConstructors != null) {
+ for (String code : mConstructors) {
+ if (code.charAt(0) == ':') {
+ mCtc.addConstructor(CtNewConstructor
+ .copy(getCtConstructor(mCopyConstructors.get(code.substring(1))), mCtc, null));
+ } else {
+ String[] sn = mCtc.getSimpleName().split("\\$+"); // inner class name include $.
+ mCtc.addConstructor(
+ CtNewConstructor.make(code.replaceFirst(SIMPLE_NAME_TAG, sn[sn.length - 1]), mCtc));
+ }
+ }
+ }
+ return mCtc.toClass(loader, pd);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (NotFoundException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ } catch (CannotCompileException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public void release() {
+ if (mCtc != null) {
+ mCtc.detach();
+ }
+ if (mInterfaces != null) {
+ mInterfaces.clear();
+ }
+ if (mFields != null) {
+ mFields.clear();
+ }
+ if (mMethods != null) {
+ mMethods.clear();
+ }
+ if (mConstructors != null) {
+ mConstructors.clear();
+ }
+ if (mCopyMethods != null) {
+ mCopyMethods.clear();
+ }
+ if (mCopyConstructors != null) {
+ mCopyConstructors.clear();
+ }
+ }
+
+ private CtClass getCtClass(Class> c) throws NotFoundException {
+ return mPool.get(c.getName());
+ }
+
+ private CtMethod getCtMethod(Method m) throws NotFoundException {
+ return getCtClass(m.getDeclaringClass())
+ .getMethod(m.getName(), ReflectUtils.getDescWithoutMethodName(m));
+ }
+
+ private CtConstructor getCtConstructor(Constructor> c) throws NotFoundException {
+ return getCtClass(c.getDeclaringClass()).getConstructor(ReflectUtils.getDesc(c));
+ }
+
+ public static interface DC {
+
+ } // dynamic class tag interface.
}
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java
index fe37f2f03140..df95dabf4452 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java
@@ -98,16 +98,18 @@ public static Mixin mixin(Class>[] ics, Class>[] dcs, ClassLoader cl) {
if (pkg == null) {
pkg = npkg;
} else {
- if (!pkg.equals(npkg))
+ if (!pkg.equals(npkg)) {
throw new IllegalArgumentException("non-public interfaces class from different packages");
+ }
}
}
ccp.addField("private " + dcs[i].getName() + " d" + i + ";");
code.append("d").append(i).append(" = (").append(dcs[i].getName()).append(")$1[").append(i).append("];\n");
- if (MixinAware.class.isAssignableFrom(dcs[i]))
+ if (MixinAware.class.isAssignableFrom(dcs[i])) {
code.append("d").append(i).append(".setMixinInstance(this);\n");
+ }
}
ccp.addConstructor(Modifier.PUBLIC, new Class>[]{Object[].class}, code.toString());
@@ -119,39 +121,45 @@ public static Mixin mixin(Class>[] ics, Class>[] dcs, ClassLoader cl) {
if (pkg == null) {
pkg = npkg;
} else {
- if (!pkg.equals(npkg))
+ if (!pkg.equals(npkg)) {
throw new IllegalArgumentException("non-public delegate class from different packages");
+ }
}
}
ccp.addInterface(ics[i]);
for (Method method : ics[i].getMethods()) {
- if ("java.lang.Object".equals(method.getDeclaringClass().getName()))
+ if ("java.lang.Object".equals(method.getDeclaringClass().getName())) {
continue;
+ }
String desc = ReflectUtils.getDesc(method);
- if (worked.contains(desc))
+ if (worked.contains(desc)) {
continue;
+ }
worked.add(desc);
int ix = findMethod(dcs, desc);
- if (ix < 0)
+ if (ix < 0) {
throw new RuntimeException("Missing method [" + desc + "] implement.");
+ }
Class> rt = method.getReturnType();
String mn = method.getName();
- if (Void.TYPE.equals(rt))
+ if (Void.TYPE.equals(rt)) {
ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(),
"d" + ix + "." + mn + "($$);");
- else
+ } else {
ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(),
"return ($r)d" + ix + "." + mn + "($$);");
+ }
}
}
- if (pkg == null)
+ if (pkg == null) {
pkg = PACKAGE_NAME;
+ }
// create MixinInstance class.
String micn = pkg + ".mixin" + id;
@@ -173,10 +181,12 @@ public static Mixin mixin(Class>[] ics, Class>[] dcs, ClassLoader cl) {
throw new RuntimeException(e.getMessage(), e);
} finally {
// release ClassGenerator
- if (ccp != null)
+ if (ccp != null) {
ccp.release();
- if (ccm != null)
+ }
+ if (ccm != null) {
ccm.release();
+ }
}
}
@@ -187,17 +197,20 @@ private static int findMethod(Class>[] dcs, String desc) {
cl = dcs[i];
methods = cl.getMethods();
for (Method method : methods) {
- if (desc.equals(ReflectUtils.getDesc(method)))
+ if (desc.equals(ReflectUtils.getDesc(method))) {
return i;
+ }
}
}
return -1;
}
private static void assertInterfaceArray(Class>[] ics) {
- for (int i = 0; i < ics.length; i++)
- if (!ics[i].isInterface())
+ for (int i = 0; i < ics.length; i++) {
+ if (!ics[i].isInterface()) {
throw new RuntimeException("Class " + ics[i].getName() + " is not a interface.");
+ }
+ }
}
/**
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
index 91c534f20149..150e946b6905 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
@@ -77,14 +77,16 @@ public static Proxy getProxy(Class>... ics) {
* @return Proxy instance.
*/
public static Proxy getProxy(ClassLoader cl, Class>... ics) {
- if (ics.length > 65535)
+ if (ics.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
+ }
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ics.length; i++) {
String itf = ics[i].getName();
- if (!ics[i].isInterface())
+ if (!ics[i].isInterface()) {
throw new RuntimeException(itf + " is not a interface.");
+ }
Class> tmp = null;
try {
@@ -92,8 +94,9 @@ public static Proxy getProxy(ClassLoader cl, Class>... ics) {
} catch (ClassNotFoundException e) {
}
- if (tmp != ics[i])
+ if (tmp != ics[i]) {
throw new IllegalArgumentException(ics[i] + " is not visible from class loader");
+ }
sb.append(itf).append(';');
}
@@ -117,8 +120,9 @@ public static Proxy getProxy(ClassLoader cl, Class>... ics) {
Object value = cache.get(key);
if (value instanceof Reference>) {
proxy = (Proxy) ((Reference>) value).get();
- if (proxy != null)
+ if (proxy != null) {
return proxy;
+ }
}
if (value == PendingGenerationMarker) {
@@ -149,16 +153,18 @@ public static Proxy getProxy(ClassLoader cl, Class>... ics) {
if (pkg == null) {
pkg = npkg;
} else {
- if (!pkg.equals(npkg))
+ if (!pkg.equals(npkg)) {
throw new IllegalArgumentException("non-public interfaces from different packages");
+ }
}
}
ccp.addInterface(ics[i]);
for (Method method : ics[i].getMethods()) {
String desc = ReflectUtils.getDesc(method);
- if (worked.contains(desc))
+ if (worked.contains(desc)) {
continue;
+ }
worked.add(desc);
int ix = methods.size();
@@ -166,19 +172,22 @@ public static Proxy getProxy(ClassLoader cl, Class>... ics) {
Class>[] pts = method.getParameterTypes();
StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];");
- for (int j = 0; j < pts.length; j++)
+ for (int j = 0; j < pts.length; j++) {
code.append(" args[").append(j).append("] = ($w)$").append(j + 1).append(";");
+ }
code.append(" Object ret = handler.invoke(this, methods[" + ix + "], args);");
- if (!Void.TYPE.equals(rt))
+ if (!Void.TYPE.equals(rt)) {
code.append(" return ").append(asArgument(rt, "ret")).append(";");
+ }
methods.add(method);
ccp.addMethod(method.getName(), method.getModifiers(), rt, pts, method.getExceptionTypes(), code.toString());
}
}
- if (pkg == null)
+ if (pkg == null) {
pkg = PACKAGE_NAME;
+ }
// create ProxyInstance class.
String pcn = pkg + ".proxy" + id;
@@ -205,15 +214,18 @@ public static Proxy getProxy(ClassLoader cl, Class>... ics) {
throw new RuntimeException(e.getMessage(), e);
} finally {
// release ClassGenerator
- if (ccp != null)
+ if (ccp != null) {
ccp.release();
- if (ccm != null)
+ }
+ if (ccm != null) {
ccm.release();
+ }
synchronized (cache) {
- if (proxy == null)
+ if (proxy == null) {
cache.remove(key);
- else
+ } else {
cache.put(key, new WeakReference(proxy));
+ }
cache.notifyAll();
}
}
@@ -222,22 +234,30 @@ public static Proxy getProxy(ClassLoader cl, Class>... ics) {
private static String asArgument(Class> cl, String name) {
if (cl.isPrimitive()) {
- if (Boolean.TYPE == cl)
+ if (Boolean.TYPE == cl) {
return name + "==null?false:((Boolean)" + name + ").booleanValue()";
- if (Byte.TYPE == cl)
+ }
+ if (Byte.TYPE == cl) {
return name + "==null?(byte)0:((Byte)" + name + ").byteValue()";
- if (Character.TYPE == cl)
+ }
+ if (Character.TYPE == cl) {
return name + "==null?(char)0:((Character)" + name + ").charValue()";
- if (Double.TYPE == cl)
+ }
+ if (Double.TYPE == cl) {
return name + "==null?(double)0:((Double)" + name + ").doubleValue()";
- if (Float.TYPE == cl)
+ }
+ if (Float.TYPE == cl) {
return name + "==null?(float)0:((Float)" + name + ").floatValue()";
- if (Integer.TYPE == cl)
+ }
+ if (Integer.TYPE == cl) {
return name + "==null?(int)0:((Integer)" + name + ").intValue()";
- if (Long.TYPE == cl)
+ }
+ if (Long.TYPE == cl) {
return name + "==null?(long)0:((Long)" + name + ").longValue()";
- if (Short.TYPE == cl)
+ }
+ if (Short.TYPE == cl) {
return name + "==null?(short)0:((Short)" + name + ").shortValue()";
+ }
throw new RuntimeException(name + " is unknown primitive type.");
}
return "(" + ReflectUtils.getName(cl) + ")" + name;
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java
index aebcda60a869..76113ba2e7b4 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java
@@ -77,11 +77,19 @@ public boolean hasProperty(String name) {
@Override
public Object invokeMethod(Object instance, String mn, Class>[] types, Object[] args) throws NoSuchMethodException {
- if ("getClass".equals(mn)) return instance.getClass();
- if ("hashCode".equals(mn)) return instance.hashCode();
- if ("toString".equals(mn)) return instance.toString();
+ if ("getClass".equals(mn)) {
+ return instance.getClass();
+ }
+ if ("hashCode".equals(mn)) {
+ return instance.hashCode();
+ }
+ if ("toString".equals(mn)) {
+ return instance.toString();
+ }
if ("equals".equals(mn)) {
- if (args.length == 1) return instance.equals(args[0]);
+ if (args.length == 1) {
+ return instance.equals(args[0]);
+ }
throw new IllegalArgumentException("Invoke method [" + mn + "] argument number error.");
}
throw new NoSuchMethodException("Method [" + mn + "] not found.");
@@ -97,10 +105,13 @@ public Object invokeMethod(Object instance, String mn, Class>[] types, Object[
*/
public static Wrapper getWrapper(Class> c) {
while (ClassGenerator.isDynamicClass(c)) // can not wrapper on dynamic class.
+ {
c = c.getSuperclass();
+ }
- if (c == Object.class)
+ if (c == Object.class) {
return OBJECT_WRAPPER;
+ }
Wrapper ret = WRAPPER_MAP.get(c);
if (ret == null) {
@@ -111,8 +122,9 @@ public static Wrapper getWrapper(Class> c) {
}
private static Wrapper makeWrapper(Class> c) {
- if (c.isPrimitive())
+ if (c.isPrimitive()) {
throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c);
+ }
String name = c.getName();
ClassLoader cl = ClassHelper.getClassLoader(c);
@@ -134,8 +146,9 @@ private static Wrapper makeWrapper(Class> c) {
for (Field f : c.getFields()) {
String fn = f.getName();
Class> ft = f.getType();
- if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers()))
+ if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers())) {
continue;
+ }
c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }");
c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }");
@@ -150,7 +163,9 @@ private static Wrapper makeWrapper(Class> c) {
}
for (Method m : methods) {
if (m.getDeclaringClass() == Object.class) //ignore Object's method.
+ {
continue;
+ }
String mn = m.getName();
c3.append(" if( \"").append(mn).append("\".equals( $2 ) ");
@@ -175,16 +190,18 @@ private static Wrapper makeWrapper(Class> c) {
c3.append(" ) { ");
- if (m.getReturnType() == Void.TYPE)
+ if (m.getReturnType() == Void.TYPE) {
c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;");
- else
+ } else {
c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");");
+ }
c3.append(" }");
mns.add(mn);
- if (m.getDeclaringClass() == c)
+ if (m.getDeclaringClass() == c) {
dmns.add(mn);
+ }
ms.put(ReflectUtils.getDesc(m), m);
}
if (hasMethod) {
@@ -215,8 +232,8 @@ private static Wrapper makeWrapper(Class> c) {
pts.put(pn, pt);
}
}
- c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
- c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
+ c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or setter method in class " + c.getName() + ".\"); }");
+ c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or setter method in class " + c.getName() + ".\"); }");
// make class
long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
@@ -229,8 +246,9 @@ private static Wrapper makeWrapper(Class> c) {
cc.addField("public static " + Map.class.getName() + " pts;"); // property type map.
cc.addField("public static String[] mns;"); // all method name array.
cc.addField("public static String[] dmns;"); // declared method name array.
- for (int i = 0, len = ms.size(); i < len; i++)
+ for (int i = 0, len = ms.size(); i < len; i++) {
cc.addField("public static Class[] mts" + i + ";");
+ }
cc.addMethod("public String[] getPropertyNames(){ return pns; }");
cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }");
@@ -249,8 +267,9 @@ private static Wrapper makeWrapper(Class> c) {
wc.getField("mns").set(null, mns.toArray(new String[0]));
wc.getField("dmns").set(null, dmns.toArray(new String[0]));
int ix = 0;
- for (Method m : ms.values())
+ for (Method m : ms.values()) {
wc.getField("mts" + ix++).set(null, m.getParameterTypes());
+ }
return (Wrapper) wc.newInstance();
} catch (RuntimeException e) {
throw e;
@@ -266,22 +285,30 @@ private static Wrapper makeWrapper(Class> c) {
private static String arg(Class> cl, String name) {
if (cl.isPrimitive()) {
- if (cl == Boolean.TYPE)
+ if (cl == Boolean.TYPE) {
return "((Boolean)" + name + ").booleanValue()";
- if (cl == Byte.TYPE)
+ }
+ if (cl == Byte.TYPE) {
return "((Byte)" + name + ").byteValue()";
- if (cl == Character.TYPE)
+ }
+ if (cl == Character.TYPE) {
return "((Character)" + name + ").charValue()";
- if (cl == Double.TYPE)
+ }
+ if (cl == Double.TYPE) {
return "((Number)" + name + ").doubleValue()";
- if (cl == Float.TYPE)
+ }
+ if (cl == Float.TYPE) {
return "((Number)" + name + ").floatValue()";
- if (cl == Integer.TYPE)
+ }
+ if (cl == Integer.TYPE) {
return "((Number)" + name + ").intValue()";
- if (cl == Long.TYPE)
+ }
+ if (cl == Long.TYPE) {
return "((Number)" + name + ").longValue()";
- if (cl == Short.TYPE)
+ }
+ if (cl == Short.TYPE) {
return "((Number)" + name + ").shortValue()";
+ }
throw new RuntimeException("Unknown primitive type: " + cl.getName());
}
return "(" + ReflectUtils.getName(cl) + ")" + name;
@@ -289,11 +316,14 @@ private static String arg(Class> cl, String name) {
private static String args(Class>[] cs, String name) {
int len = cs.length;
- if (len == 0) return "";
+ if (len == 0) {
+ return "";
+ }
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++) {
- if (i > 0)
+ if (i > 0) {
sb.append(',');
+ }
sb.append(arg(cs[i], name + "[" + i + "]"));
}
return sb.toString();
@@ -365,8 +395,9 @@ private static boolean hasMethods(Method[] methods) {
*/
public Object[] getPropertyValues(Object instance, String[] pns) throws NoSuchPropertyException, IllegalArgumentException {
Object[] ret = new Object[pns.length];
- for (int i = 0; i < ret.length; i++)
+ for (int i = 0; i < ret.length; i++) {
ret[i] = getPropertyValue(instance, pns[i]);
+ }
return ret;
}
@@ -378,11 +409,13 @@ public Object[] getPropertyValues(Object instance, String[] pns) throws NoSuchPr
* @param pvs property value array.
*/
public void setPropertyValues(Object instance, String[] pns, Object[] pvs) throws NoSuchPropertyException, IllegalArgumentException {
- if (pns.length != pvs.length)
+ if (pns.length != pvs.length) {
throw new IllegalArgumentException("pns.length != pvs.length");
+ }
- for (int i = 0; i < pns.length; i++)
+ for (int i = 0; i < pns.length; i++) {
setPropertyValue(instance, pns[i], pvs[i]);
+ }
}
/**
@@ -406,8 +439,11 @@ public void setPropertyValues(Object instance, String[] pns, Object[] pvs) throw
* @return has or has not.
*/
public boolean hasMethod(String name) {
- for (String mn : getMethodNames())
- if (mn.equals(name)) return true;
+ for (String mn : getMethodNames()) {
+ if (mn.equals(name)) {
+ return true;
+ }
+ }
return false;
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java
index 7c55a2910a3a..3b8961d83f23 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java
@@ -16,7 +16,6 @@
*/
package org.apache.dubbo.common.compiler;
-
import org.apache.dubbo.common.extension.SPI;
/**
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java
index b47857c6861f..a0c5cc6b4152 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java
@@ -16,7 +16,6 @@
*/
package org.apache.dubbo.common.compiler.support;
-
import org.apache.dubbo.common.compiler.Compiler;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.ExtensionLoader;
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java
index 8a8580d03d3b..9c2800cc217f 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java
@@ -168,8 +168,9 @@ public JavaFileManagerImpl(JavaFileManager fileManager, ClassLoaderImpl classLoa
@Override
public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
FileObject o = fileObjects.get(uri(location, packageName, relativeName));
- if (o != null)
+ if (o != null) {
return o;
+ }
return super.getFileForInput(location, packageName, relativeName);
}
@@ -196,8 +197,9 @@ public ClassLoader getClassLoader(JavaFileManager.Location location) {
@Override
public String inferBinaryName(Location loc, JavaFileObject file) {
- if (file instanceof JavaFileObjectImpl)
+ if (file instanceof JavaFileObjectImpl) {
return file.getName();
+ }
return super.inferBinaryName(loc, file);
}
diff --git a/dubbo-serialization/dubbo-serialization-fastjson/src/test/java/org/apache/dubbo/common/serialize/fastjson/model/Person.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/DisableInject.java
similarity index 68%
rename from dubbo-serialization/dubbo-serialization-fastjson/src/test/java/org/apache/dubbo/common/serialize/fastjson/model/Person.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/extension/DisableInject.java
index eadb684d15a3..577a28df6b4b 100644
--- a/dubbo-serialization/dubbo-serialization-fastjson/src/test/java/org/apache/dubbo/common/serialize/fastjson/model/Person.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/DisableInject.java
@@ -14,25 +14,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common.serialize.fastjson.model;
+package org.apache.dubbo.common.extension;
-public class Person {
- private String name;
- private int age;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface DisableInject {
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
index fcbb292ec728..31f72e669e7e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
@@ -105,8 +105,9 @@ private static boolean withExtensionAnnotation(Class type) {
@SuppressWarnings("unchecked")
public static ExtensionLoader getExtensionLoader(Class type) {
- if (type == null)
+ if (type == null) {
throw new IllegalArgumentException("Extension type == null");
+ }
if (!type.isInterface()) {
throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
}
@@ -277,8 +278,9 @@ private boolean isActive(String[] keys, URL url) {
*/
@SuppressWarnings("unchecked")
public T getLoadedExtension(String name) {
- if (name == null || name.length() == 0)
+ if (name == null || name.length() == 0) {
throw new IllegalArgumentException("Extension name == null");
+ }
Holder