diff --git a/LICENSE b/LICENSE
index 7b279f161126..685172ecd96c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -263,4 +263,13 @@ This product bundles and repackages the following code in Google Guava 16.0.1, w
* com.google.common.util.concurrent.ExecutionList
* com.google.common.util.concurrent.ListenableFuture
- * com.google.common.util.concurrent.ListenableFutureTask
\ No newline at end of file
+ * com.google.common.util.concurrent.ListenableFutureTask
+
+For the package com.alibaba.dubbo.common.threadlocal:
+
+This product contains a modified portion of 'Netty', an event-driven asynchronous network application framework also
+ under a "Apache License 2.0" license, see https://github.com/netty/netty/blob/4.1/LICENSE.txt:
+
+ * io.netty.util.concurrent.FastThreadLocal
+ * io.netty.util.internal.InternalThreadLocalMap
+
diff --git a/dependencies-bom/pom.xml b/dependencies-bom/pom.xml
index 94bfa1e86e81..89de3c3ce426 100644
--- a/dependencies-bom/pom.xml
+++ b/dependencies-bom/pom.xml
@@ -84,7 +84,7 @@
2.12.0
2.9.0
1.3.6
- 3.0.14
+ 3.1.15
0.8.0
4.0.38
3.1.0
@@ -107,6 +107,9 @@
1.2.2
3.4
0.6
+
+ 2.2.7
+ 1.2.0
@@ -321,6 +324,34 @@
commons-lang3
${commons_lang3_version}
+
+
+
+ javax.xml.bind
+ jaxb-api
+ ${jaxb_version}
+
+
+ com.sun.xml.bind
+ jaxb-impl
+ ${jaxb_version}
+
+
+ com.sun.xml.bind
+ jaxb-core
+ ${jaxb_version}
+
+
+ javax.activation
+ javax.activation-api
+ ${activation_version}
+
+
+ com.sun.activation
+ javax.activation
+ ${activation_version}
+
+
org.apache.curator
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
index 8694e48de352..37ec8a304bc0 100644
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
+++ b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
@@ -16,16 +16,11 @@
*/
package org.apache.dubbo.bootstrap;
-import com.alibaba.dubbo.common.extension.ExtensionLoader;
-import com.alibaba.dubbo.common.logger.Logger;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
+import com.alibaba.dubbo.config.DubboShutdownHook;
import com.alibaba.dubbo.config.ServiceConfig;
-import com.alibaba.dubbo.registry.support.AbstractRegistryFactory;
-import com.alibaba.dubbo.rpc.Protocol;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
/**
* A bootstrap class to easily start and stop Dubbo via programmatic API.
@@ -33,35 +28,33 @@
*/
public class DubboBootstrap {
- private static final Logger logger = LoggerFactory.getLogger(DubboBootstrap.class);
-
/**
* The list of ServiceConfig
*/
private List serviceConfigList;
/**
- * Has it already been destroyed or not?
+ * Whether register the shutdown hook during start?
*/
- private final AtomicBoolean destroyed;
+ private final boolean registerShutdownHookOnStart;
/**
* The shutdown hook used when Dubbo is running under embedded environment
*/
- private Thread shutdownHook;
+ 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.destroyed = new AtomicBoolean(false);
- this.shutdownHook = new Thread(new Runnable() {
- @Override
- public void run() {
- if (logger.isInfoEnabled()) {
- logger.info("Run shutdown hook now.");
- }
- destroy();
- }
- }, "DubboShutdownHook");
+ this.shutdownHook = shutdownHook;
+ this.registerShutdownHookOnStart = registerShutdownHookOnStart;
}
/**
@@ -69,13 +62,19 @@ public void run() {
* @param serviceConfig the service
* @return the bootstrap instance
*/
- public DubboBootstrap regsiterServiceConfig(ServiceConfig serviceConfig) {
+ public DubboBootstrap registerServiceConfig(ServiceConfig serviceConfig) {
serviceConfigList.add(serviceConfig);
return this;
}
public void start() {
- registerShutdownHook();
+ if (registerShutdownHookOnStart) {
+ registerShutdownHook();
+ } else {
+ // DubboShutdown hook has been registered in AbstractConfig,
+ // we need to remove it explicitly
+ removeShutdownHook();
+ }
for (ServiceConfig serviceConfig: serviceConfigList) {
serviceConfig.export();
}
@@ -85,8 +84,10 @@ public void stop() {
for (ServiceConfig serviceConfig: serviceConfigList) {
serviceConfig.unexport();
}
- destroy();
- removeShutdownHook();
+ shutdownHook.destroyAll();
+ if (registerShutdownHookOnStart) {
+ removeShutdownHook();
+ }
}
/**
@@ -107,27 +108,4 @@ public void removeShutdownHook() {
// ignore - VM is already shutting down
}
}
-
- /**
- * Destroy all the resources, including registries and protocols.
- */
- private void destroy() {
- if (!destroyed.compareAndSet(false, true)) {
- return;
- }
- // destroy all the registries
- AbstractRegistryFactory.destroyAll();
- // destroy all the protocols
- ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Protocol.class);
- for (String protocolName : loader.getLoadedExtensions()) {
- try {
- Protocol protocol = loader.getLoadedExtension(protocolName);
- if (protocol != null) {
- protocol.destroy();
- }
- } catch (Throwable t) {
- logger.warn(t.getMessage(), t);
- }
- }
- }
}
diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
index 44c751d9a2f6..ec86f1d02b00 100644
--- a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
+++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
@@ -101,10 +101,10 @@ private String toKey(Object[] args) {
private Invoker selectForKey(long hash) {
Map.Entry> entry = virtualInvokers.tailMap(hash, true).firstEntry();
- if (entry == null) {
- entry = virtualInvokers.firstEntry();
- }
- return entry.getValue();
+ if (entry == null) {
+ entry = virtualInvokers.firstEntry();
+ }
+ return entry.getValue();
}
private long hash(byte[] digest, int number) {
diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/FailbackClusterInvoker.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/FailbackClusterInvoker.java
index 17b50fff69c5..3cc22a8439b0 100644
--- a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/FailbackClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/FailbackClusterInvoker.java
@@ -18,12 +18,13 @@
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
-import com.alibaba.dubbo.common.utils.NamedThreadFactory;
+import com.alibaba.dubbo.common.threadlocal.NamedInternalThreadFactory;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcResult;
+import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.cluster.Directory;
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
@@ -50,7 +51,13 @@ public class FailbackClusterInvoker extends AbstractClusterInvoker {
private static final long RETRY_FAILED_PERIOD = 5 * 1000;
- private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2, new NamedThreadFactory("failback-cluster-timer", true));
+ /**
+ * Use {@link NamedInternalThreadFactory} to produce {@link com.alibaba.dubbo.common.threadlocal.InternalThread}
+ * which with the use of {@link com.alibaba.dubbo.common.threadlocal.InternalThreadLocal} in {@link RpcContext}.
+ */
+ private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2,
+ new NamedInternalThreadFactory("failback-cluster-timer", true));
+
private final ConcurrentMap> failed = new ConcurrentHashMap>();
private volatile ScheduledFuture> retryFuture;
diff --git a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ForkingClusterInvoker.java b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ForkingClusterInvoker.java
index dd6b90120f15..7d9a58d824ba 100644
--- a/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ForkingClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/com/alibaba/dubbo/rpc/cluster/support/ForkingClusterInvoker.java
@@ -17,7 +17,7 @@
package com.alibaba.dubbo.rpc.cluster.support;
import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.utils.NamedThreadFactory;
+import com.alibaba.dubbo.common.threadlocal.NamedInternalThreadFactory;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
@@ -43,7 +43,12 @@
*/
public class ForkingClusterInvoker extends AbstractClusterInvoker {
- private final ExecutorService executor = Executors.newCachedThreadPool(new NamedThreadFactory("forking-cluster-timer", true));
+ /**
+ * Use {@link NamedInternalThreadFactory} to produce {@link com.alibaba.dubbo.common.threadlocal.InternalThread}
+ * which with the use of {@link com.alibaba.dubbo.common.threadlocal.InternalThreadLocal} in {@link RpcContext}.
+ */
+ private final ExecutorService executor = Executors.newCachedThreadPool(
+ new NamedInternalThreadFactory("forking-cluster-timer", true));
public ForkingClusterInvoker(Directory directory) {
super(directory);
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java
index 55e86d0382fe..404fe8f6b511 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java
@@ -156,7 +156,7 @@ public class Constants {
public static final String LOADBALANCE_KEY = "loadbalance";
- // key for router type, for e.g., "script"/"file", corresponding to ScriptRouterFactory.NAME, FileRouterFactory.NAME
+ // key for router type, for e.g., "script"/"file", corresponding to ScriptRouterFactory.NAME, FileRouterFactory.NAME
public static final String ROUTER_KEY = "router";
public static final String CLUSTER_KEY = "cluster";
@@ -624,7 +624,7 @@ public class Constants {
public static final String QOS_PORT = "qos.port";
public static final String ACCEPT_FOREIGN_IP = "qos.accept.foreign.ip";
-
+
public static final String HESSIAN2_REQUEST_KEY = "hessian2.request";
public static final boolean DEFAULT_HESSIAN2_REQUEST = false;
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Version.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Version.java
index 97e3a2173dc6..b84aaa5bfba5 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/Version.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Version.java
@@ -23,17 +23,28 @@
import java.net.URL;
import java.security.CodeSource;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
/**
* Version
*/
public final class Version {
-
- private static final String DEFAULT_DUBBO_VERSION = "2.0.0";
private static final Logger logger = LoggerFactory.getLogger(Version.class);
- private static final String VERSION = getVersion(Version.class, DEFAULT_DUBBO_VERSION);
+
+ // Dubbo RPC protocol version
+ public static final String DEFAULT_DUBBO_PROTOCOL_VERSION = "2.0.2";
+ // Dubbo implementation version, usually is jar version.
+ private static final String VERSION = getVersion(Version.class, "");
+
+ /**
+ * For protocol compatibility purpose.
+ * Because {@link #isSupportResponseAttatchment} is checked for every call, int compare expect to has higher performance than string.
+ */
+ private static final int LOWEST_VERSION_FOR_RESPONSE_ATTATCHMENT = 202; // 2.0.2
+ private static final Map VERSION2INT = new HashMap();
static {
// check if there's duplicated jar
@@ -43,10 +54,39 @@ public final class Version {
private Version() {
}
+ public static String getProtocolVersion() {
+ return DEFAULT_DUBBO_PROTOCOL_VERSION;
+ }
+
public static String getVersion() {
return VERSION;
}
+ public static boolean isSupportResponseAttatchment(String version) {
+ if (version == null || version.length() == 0) {
+ return false;
+ }
+ return getIntVersion(version) >= LOWEST_VERSION_FOR_RESPONSE_ATTATCHMENT;
+ }
+
+ public static int getIntVersion(String version) {
+ Integer v = VERSION2INT.get(version);
+ if (v == null) {
+ v = parseInt(version);
+ VERSION2INT.put(version, v);
+ }
+ return v;
+ }
+
+ private static int parseInt(String version) {
+ int v = 0;
+ String[] vArr = version.split("\\.");
+ int len = vArr.length;
+ for (int i = 1; i <= len; i++) {
+ v += Integer.parseInt(vArr[len - i]) * Math.pow(10, i - 1);
+ }
+ return v;
+ }
private static boolean hasResource(String path) {
try {
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocal.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocal.java
index d3d6489f994a..bbf412d628d8 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocal.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocal.java
@@ -1,18 +1,17 @@
/*
- * 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
+ * Copyright 2014 The Netty Project
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * The Netty Project 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.
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
*/
package com.alibaba.dubbo.common.threadlocal;
diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocalMap.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocalMap.java
index e2aa0fd30dc2..6b0300bf640b 100644
--- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocalMap.java
+++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/threadlocal/InternalThreadLocalMap.java
@@ -1,18 +1,17 @@
/*
- * 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
+ * Copyright 2014 The Netty Project
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * The Netty Project 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.
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
*/
package com.alibaba.dubbo.common.threadlocal;
diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/DubboAppenderTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/DubboAppenderTest.java
new file mode 100644
index 000000000000..3abede3b9177
--- /dev/null
+++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/DubboAppenderTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.dubbo.common.utils;
+
+import com.alibaba.dubbo.common.utils.DubboAppender;
+import com.alibaba.dubbo.common.utils.Log;
+import org.apache.log4j.Category;
+import org.apache.log4j.Level;
+import org.apache.log4j.spi.LoggingEvent;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class DubboAppenderTest {
+ private LoggingEvent event;
+
+ @Before
+ public void setUp() throws Exception {
+ Level level = Mockito.mock(Level.class);
+ Category category = Mockito.mock(Category.class);
+ event = Mockito.mock(LoggingEvent.class);
+ Mockito.when(event.getLogger()).thenReturn(category);
+ Mockito.when(event.getLevel()).thenReturn(level);
+ Mockito.when(event.getThreadName()).thenReturn("thread-name");
+ Mockito.when(event.getMessage()).thenReturn("message");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ DubboAppender.clear();
+ DubboAppender.doStop();
+ }
+
+ @Test
+ public void testAvailable() throws Exception {
+ assertThat(DubboAppender.available, is(false));
+ DubboAppender.doStart();
+ assertThat(DubboAppender.available, is(true));
+ DubboAppender.doStop();
+ assertThat(DubboAppender.available, is(false));
+ }
+
+ @Test
+ public void testAppend() throws Exception {
+ DubboAppender appender = new DubboAppender();
+ appender.append(event);
+ assertThat(DubboAppender.logList, hasSize(0));
+ DubboAppender.doStart();
+ appender.append(event);
+ assertThat(DubboAppender.logList, hasSize(1));
+ Log log = DubboAppender.logList.get(0);
+ assertThat(log.getLogThread(), equalTo("thread-name"));
+ }
+
+ @Test
+ public void testClear() throws Exception {
+ DubboAppender.doStart();
+ DubboAppender appender = new DubboAppender();
+ appender.append(event);
+ assertThat(DubboAppender.logList, hasSize(1));
+ DubboAppender.clear();
+ assertThat(DubboAppender.logList, hasSize(0));
+ }
+}
diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/ExecutorUtilTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/ExecutorUtilTest.java
new file mode 100644
index 000000000000..4fc1984bf5ad
--- /dev/null
+++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/ExecutorUtilTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.dubbo.common.utils;
+
+import com.alibaba.dubbo.common.Constants;
+import com.alibaba.dubbo.common.URL;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class ExecutorUtilTest {
+ @Test
+ public void testIsTerminated() throws Exception {
+ ExecutorService executor = Mockito.mock(ExecutorService.class);
+ when(executor.isTerminated()).thenReturn(true);
+ assertThat(ExecutorUtil.isTerminated(executor), is(true));
+ Executor executor2 = Mockito.mock(Executor.class);
+ assertThat(ExecutorUtil.isTerminated(executor2), is(false));
+ }
+
+ @Test
+ public void testGracefulShutdown1() throws Exception {
+ ExecutorService executor = Mockito.mock(ExecutorService.class);
+ when(executor.isTerminated()).thenReturn(false, true);
+ when(executor.awaitTermination(20, TimeUnit.MILLISECONDS)).thenReturn(false);
+ ExecutorUtil.gracefulShutdown(executor, 20);
+ verify(executor).shutdown();
+ verify(executor).shutdownNow();
+ }
+
+ @Test
+ public void testGracefulShutdown2() throws Exception {
+ ExecutorService executor = Mockito.mock(ExecutorService.class);
+ when(executor.isTerminated()).thenReturn(false, false, false);
+ when(executor.awaitTermination(20, TimeUnit.MILLISECONDS)).thenReturn(false);
+ when(executor.awaitTermination(10, TimeUnit.MILLISECONDS)).thenReturn(false, true);
+ ExecutorUtil.gracefulShutdown(executor, 20);
+ Thread.sleep(2000);
+ verify(executor).shutdown();
+ verify(executor, atLeast(2)).shutdownNow();
+ }
+
+ @Test
+ public void testShutdownNow() throws Exception {
+ ExecutorService executor = Mockito.mock(ExecutorService.class);
+ when(executor.isTerminated()).thenReturn(false, true);
+ ExecutorUtil.shutdownNow(executor, 20);
+ verify(executor).shutdownNow();
+ verify(executor).awaitTermination(20, TimeUnit.MILLISECONDS);
+ }
+
+ @Test
+ public void testSetThreadName() throws Exception {
+ URL url = new URL("dubbo", "localhost", 1234).addParameter(Constants.THREAD_NAME_KEY, "custom-thread");
+ url = ExecutorUtil.setThreadName(url, "default-name");
+ assertThat(url.getParameter(Constants.THREAD_NAME_KEY), equalTo("custom-thread-localhost:1234"));
+ }
+}
diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/HolderTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/HolderTest.java
new file mode 100644
index 000000000000..1fba4ba9dca7
--- /dev/null
+++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/HolderTest.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.dubbo.common.utils;
+
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class HolderTest {
+ @Test
+ public void testSetAndGet() throws Exception {
+ Holder holder = new Holder();
+ String message = "hello";
+ holder.set(message);
+ assertThat(holder.get(), is(message));
+ }
+}
diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/IOUtilsTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/IOUtilsTest.java
new file mode 100644
index 000000000000..a6d79663e754
--- /dev/null
+++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/IOUtilsTest.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.dubbo.common.utils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class IOUtilsTest {
+ @Rule
+ public TemporaryFolder tmpDir = new TemporaryFolder();
+
+ private static String TEXT = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
+ private InputStream is;
+ private OutputStream os;
+ private Reader reader;
+ private Writer writer;
+
+ @Before
+ public void setUp() throws Exception {
+ is = new ByteArrayInputStream(TEXT.getBytes("UTF-8"));
+ os = new ByteArrayOutputStream();
+ reader = new StringReader(TEXT);
+ writer = new StringWriter();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ is.close();
+ os.close();
+ reader.close();
+ writer.close();
+ }
+
+ @Test
+ public void testWrite1() throws Exception {
+ assertThat((int) IOUtils.write(is, os, 16), equalTo(TEXT.length()));
+ }
+
+ @Test
+ public void testWrite2() throws Exception {
+ assertThat((int) IOUtils.write(reader, writer, 16), equalTo(TEXT.length()));
+ }
+
+ @Test
+ public void testWrite3() throws Exception {
+ assertThat((int) IOUtils.write(writer, TEXT), equalTo(TEXT.length()));
+ }
+
+ @Test
+ public void testWrite4() throws Exception {
+ assertThat((int) IOUtils.write(is, os), equalTo(TEXT.length()));
+ }
+
+ @Test
+ public void testWrite5() throws Exception {
+ assertThat((int) IOUtils.write(reader, writer), equalTo(TEXT.length()));
+ }
+
+ @Test
+ public void testLines() throws Exception {
+ File file = tmpDir.newFile();
+ IOUtils.writeLines(file, new String[]{TEXT});
+ String[] lines = IOUtils.readLines(file);
+ assertThat(lines.length, equalTo(1));
+ assertThat(lines[0], equalTo(TEXT));
+ }
+
+ @Test
+ public void testReadLines() throws Exception {
+ String[] lines = IOUtils.readLines(is);
+ assertThat(lines.length, equalTo(1));
+ assertThat(lines[0], equalTo(TEXT));
+ }
+
+ @Test
+ public void testWriteLines() throws Exception {
+ IOUtils.writeLines(os, new String[]{TEXT});
+ ByteArrayOutputStream bos = (ByteArrayOutputStream) os;
+ assertThat(new String(bos.toByteArray()), equalTo(TEXT + "\n"));
+ }
+
+ @Test
+ public void testRead() throws Exception {
+ assertThat(IOUtils.read(reader), equalTo(TEXT));
+ }
+
+ @Test
+ public void testAppendLines() throws Exception {
+ File file = tmpDir.newFile();
+ IOUtils.appendLines(file, new String[]{"a", "b", "c"});
+ String[] lines = IOUtils.readLines(file);
+ assertThat(lines.length, equalTo(3));
+ assertThat(lines[0], equalTo("a"));
+ assertThat(lines[1], equalTo("b"));
+ assertThat(lines[2], equalTo("c"));
+ }
+}
diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/JVMUtilTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/JVMUtilTest.java
new file mode 100644
index 000000000000..ca90930ebeb7
--- /dev/null
+++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/utils/JVMUtilTest.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.dubbo.common.utils;
+
+public class JVMUtilTest {
+}
diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/version/VersionTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/version/VersionTest.java
new file mode 100644
index 000000000000..139216b0955d
--- /dev/null
+++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/version/VersionTest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.common.version;
+
+
+import com.alibaba.dubbo.common.Version;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class VersionTest {
+
+ @Test
+ public void testGetProtocolVersion() {
+ Assert.assertEquals(Version.getProtocolVersion(), Version.DEFAULT_DUBBO_PROTOCOL_VERSION);
+ }
+
+ @Test
+ public void testSupportResponseAttatchment() {
+ Assert.assertTrue(Version.isSupportResponseAttatchment("2.0.2"));
+ Assert.assertTrue(Version.isSupportResponseAttatchment("2.0.3"));
+ Assert.assertFalse(Version.isSupportResponseAttatchment("2.0.0"));
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractConfig.java
index 84ad29e7bbe3..782215debcc4 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractConfig.java
@@ -71,6 +71,9 @@ public abstract class AbstractConfig implements Serializable {
legacyProperties.put("dubbo.consumer.retries", "dubbo.service.max.retry.providers");
legacyProperties.put("dubbo.consumer.check", "dubbo.service.allow.no.provider");
legacyProperties.put("dubbo.service.url", "dubbo.service.address");
+
+ // this is only for compatibility
+ Runtime.getRuntime().addShutdownHook(DubboShutdownHook.getDubboShutdownHook());
}
protected String id;
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java
index a42d07c10935..168bb10d2ea8 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java
@@ -174,7 +174,7 @@ protected List loadRegistries(boolean provider) {
appendParameters(map, application);
appendParameters(map, config);
map.put("path", RegistryService.class.getName());
- map.put("dubbo", Version.getVersion());
+ map.put("dubbo", Version.getProtocolVersion());
map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
if (ConfigUtils.getPid() > 0) {
map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
@@ -220,7 +220,7 @@ protected URL loadMonitor(URL registryURL) {
appendProperties(monitor);
Map map = new HashMap();
map.put(Constants.INTERFACE_KEY, MonitorService.class.getName());
- map.put("dubbo", Version.getVersion());
+ map.put("dubbo", Version.getProtocolVersion());
map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
if (ConfigUtils.getPid() > 0) {
map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/DubboShutdownHook.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/DubboShutdownHook.java
new file mode 100644
index 000000000000..348c5e610353
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/DubboShutdownHook.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.config;
+
+import com.alibaba.dubbo.common.extension.ExtensionLoader;
+import com.alibaba.dubbo.common.logger.Logger;
+import com.alibaba.dubbo.common.logger.LoggerFactory;
+import com.alibaba.dubbo.registry.support.AbstractRegistryFactory;
+import com.alibaba.dubbo.rpc.Protocol;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * The shutdown hook thread to do the clean up stuff.
+ * This is a singleton in order to ensure there is only one shutdown hook registered.
+ * Because {@link ApplicationShutdownHooks} use {@link java.util.IdentityHashMap}
+ * to store the shutdown hooks.
+ */
+public class DubboShutdownHook extends Thread {
+
+ private static final Logger logger = LoggerFactory.getLogger(DubboShutdownHook.class);
+
+ private static final DubboShutdownHook dubboShutdownHook = new DubboShutdownHook("DubboShutdownHook");
+
+ public static DubboShutdownHook getDubboShutdownHook() {
+ return dubboShutdownHook;
+ }
+
+ /**
+ * Has it already been destroyed or not?
+ */
+ private final AtomicBoolean destroyed;
+
+ private DubboShutdownHook(String name) {
+ super(name);
+ this.destroyed = new AtomicBoolean(false);
+ }
+
+ @Override
+ public void run() {
+ if (logger.isInfoEnabled()) {
+ logger.info("Run shutdown hook now.");
+ }
+ destroyAll();
+ }
+
+ /**
+ * Destroy all the resources, including registries and protocols.
+ */
+ public void destroyAll() {
+ if (!destroyed.compareAndSet(false, true)) {
+ return;
+ }
+ // destroy all the registries
+ AbstractRegistryFactory.destroyAll();
+ // destroy all the protocols
+ ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Protocol.class);
+ for (String protocolName : loader.getLoadedExtensions()) {
+ try {
+ Protocol protocol = loader.getLoadedExtension(protocolName);
+ if (protocol != null) {
+ protocol.destroy();
+ }
+ } catch (Throwable t) {
+ logger.warn(t.getMessage(), t);
+ }
+ }
+ }
+
+
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java
index b15129bf6fbd..b901beddd996 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ProtocolConfig.java
@@ -454,10 +454,18 @@ public void setExtension(String extension) {
this.extension = extension;
}
- public void destory() {
+ public void destroy() {
if (name != null) {
ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).destroy();
}
}
+ /**
+ * Just for compatibility.
+ * It should be deleted in the next major version, say 2.7.x.
+ */
+ @Deprecated
+ public static void destroyAll() {
+ DubboShutdownHook.getDubboShutdownHook().destroyAll();
+ }
}
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java
index 7b5175243a16..c6c75b16c684 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java
@@ -280,7 +280,7 @@ private void init() {
Map map = new HashMap();
Map
+
+ com.alibaba
+ dubbo-config-spring
+ ${project.parent.version}
+
\ No newline at end of file
diff --git a/dubbo-container/dubbo-container-spring/src/main/java/com/alibaba/dubbo/container/spring/SpringContainer.java b/dubbo-container/dubbo-container-spring/src/main/java/com/alibaba/dubbo/container/spring/SpringContainer.java
index d21f3a5636f0..d4c03c679966 100644
--- a/dubbo-container/dubbo-container-spring/src/main/java/com/alibaba/dubbo/container/spring/SpringContainer.java
+++ b/dubbo-container/dubbo-container-spring/src/main/java/com/alibaba/dubbo/container/spring/SpringContainer.java
@@ -19,6 +19,7 @@
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.ConfigUtils;
+import com.alibaba.dubbo.config.spring.initializer.DubboApplicationListener;
import com.alibaba.dubbo.container.Container;
import org.springframework.context.support.ClassPathXmlApplicationContext;
@@ -43,7 +44,10 @@ public void start() {
if (configPath == null || configPath.length() == 0) {
configPath = DEFAULT_SPRING_CONFIG;
}
- context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"));
+ context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"), false);
+ context.addApplicationListener(new DubboApplicationListener());
+ context.registerShutdownHook();
+ context.refresh();
context.start();
}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryDirectory.java
index e832daec5010..4bd0908a1edb 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryDirectory.java
@@ -557,10 +557,10 @@ private void destroyUnusedInvokers(Map> oldUrlInvokerMap, Map
try {
invoker.destroy();
if (logger.isDebugEnabled()) {
- logger.debug("destory invoker[" + invoker.getUrl() + "] success. ");
+ logger.debug("destroy invoker[" + invoker.getUrl() + "] success. ");
}
} catch (Exception e) {
- logger.warn("destory invoker[" + invoker.getUrl() + "] faild. " + e.getMessage(), e);
+ logger.warn("destroy invoker[" + invoker.getUrl() + "] faild. " + e.getMessage(), e);
}
}
}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryProtocol.java
index 3f5b731745fd..fd414edd1357 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryProtocol.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/com/alibaba/dubbo/registry/integration/RegistryProtocol.java
@@ -50,6 +50,7 @@
import static com.alibaba.dubbo.common.Constants.ACCEPT_FOREIGN_IP;
import static com.alibaba.dubbo.common.Constants.QOS_ENABLE;
import static com.alibaba.dubbo.common.Constants.QOS_PORT;
+import static com.alibaba.dubbo.common.Constants.VALIDATION_KEY;
/**
* RegistryProtocol
@@ -227,7 +228,8 @@ private URL getRegistedProviderUrl(final Invoker> originInvoker) {
.removeParameter(Constants.BIND_PORT_KEY)
.removeParameter(QOS_ENABLE)
.removeParameter(QOS_PORT)
- .removeParameter(ACCEPT_FOREIGN_IP);
+ .removeParameter(ACCEPT_FOREIGN_IP)
+ .removeParameter(VALIDATION_KEY);
return registedProviderUrl;
}
diff --git a/dubbo-registry/dubbo-registry-redis/src/main/java/com/alibaba/dubbo/registry/redis/RedisRegistry.java b/dubbo-registry/dubbo-registry-redis/src/main/java/com/alibaba/dubbo/registry/redis/RedisRegistry.java
index 6a997918abfe..3c19f86899ef 100644
--- a/dubbo-registry/dubbo-registry-redis/src/main/java/com/alibaba/dubbo/registry/redis/RedisRegistry.java
+++ b/dubbo-registry/dubbo-registry-redis/src/main/java/com/alibaba/dubbo/registry/redis/RedisRegistry.java
@@ -134,10 +134,12 @@ public RedisRegistry(URL url) {
}
if (StringUtils.isEmpty(password)) {
this.jedisPools.put(address, new JedisPool(config, host, port,
- url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT)));
+ url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT), null,
+ url.getParameter("db.index", 0)));
} else {
this.jedisPools.put(address, new JedisPool(config, host, port,
- url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT), password));
+ url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT), password,
+ url.getParameter("db.index", 0)));
}
}
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/codec/ExchangeCodec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/codec/ExchangeCodec.java
index 10025d26bb09..c1b8e0962261 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/codec/ExchangeCodec.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/codec/ExchangeCodec.java
@@ -16,6 +16,7 @@
*/
package com.alibaba.dubbo.remoting.exchange.codec;
+import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.common.io.Bytes;
import com.alibaba.dubbo.common.io.StreamUtils;
import com.alibaba.dubbo.common.logger.Logger;
@@ -173,7 +174,7 @@ protected Object decodeBody(Channel channel, InputStream is, byte[] header) thro
} else {
// decode request.
Request req = new Request(id);
- req.setVersion("2.0.0");
+ req.setVersion(Version.getProtocolVersion());
req.setTwoWay((flag & FLAG_TWOWAY) != 0);
if ((flag & FLAG_EVENT) != 0) {
req.setEvent(Request.HEARTBEAT_EVENT);
@@ -231,7 +232,7 @@ protected void encodeRequest(Channel channel, ChannelBuffer buffer, Request req)
if (req.isEvent()) {
encodeEventData(channel, out, req.getData());
} else {
- encodeRequestData(channel, out, req.getData());
+ encodeRequestData(channel, out, req.getData(), req.getVersion());
}
out.flushBuffer();
if (out instanceof Cleanable) {
@@ -274,7 +275,7 @@ protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response re
if (res.isHeartbeat()) {
encodeHeartbeatData(channel, out, res.getResult());
} else {
- encodeResponseData(channel, out, res.getResult());
+ encodeResponseData(channel, out, res.getResult(), res.getVersion());
}
} else out.writeUTF(res.getErrorMessage());
out.flushBuffer();
@@ -442,4 +443,13 @@ protected void encodeResponseData(Channel channel, ObjectOutput out, Object data
encodeResponseData(out, data);
}
+ protected void encodeRequestData(Channel channel, ObjectOutput out, Object data, String version) throws IOException {
+ encodeRequestData(out, data);
+ }
+
+ protected void encodeResponseData(Channel channel, ObjectOutput out, Object data, String version) throws IOException {
+ encodeResponseData(out, data);
+ }
+
+
}
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java
index 7b6bd8c43c72..3c0fb65c6b71 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeChannel.java
@@ -18,6 +18,7 @@
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.remoting.Channel;
@@ -88,7 +89,7 @@ public void send(Object message, boolean sent) throws RemotingException {
channel.send(message, sent);
} else {
Request request = new Request();
- request.setVersion("2.0.0");
+ request.setVersion(Version.getProtocolVersion());
request.setTwoWay(false);
request.setData(message);
channel.send(request, sent);
@@ -107,7 +108,7 @@ public ResponseFuture request(Object request, int timeout) throws RemotingExcept
}
// create request.
Request req = new Request();
- req.setVersion("2.0.0");
+ req.setVersion(Version.getProtocolVersion());
req.setTwoWay(true);
req.setData(request);
DefaultFuture future = new DefaultFuture(channel, req, timeout);
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java
index 2ab32f008d1b..6e520e3acb8d 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeaderExchangeServer.java
@@ -29,6 +29,7 @@
import com.alibaba.dubbo.remoting.exchange.ExchangeChannel;
import com.alibaba.dubbo.remoting.exchange.ExchangeServer;
import com.alibaba.dubbo.remoting.exchange.Request;
+
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collection;
@@ -133,7 +134,7 @@ private void sendChannelReadOnlyEvent() {
Request request = new Request();
request.setEvent(Request.READONLY_EVENT);
request.setTwoWay(false);
- request.setVersion(Version.getVersion());
+ request.setVersion(Version.getProtocolVersion());
Collection channels = getChannels();
for (Channel channel : channels) {
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartBeatTask.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartBeatTask.java
index ce529b9882c0..5dd00d6a2049 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartBeatTask.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/exchange/support/header/HeartBeatTask.java
@@ -17,6 +17,7 @@
package com.alibaba.dubbo.remoting.exchange.support.header;
+import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.remoting.Channel;
@@ -57,7 +58,7 @@ public void run() {
if ((lastRead != null && now - lastRead > heartbeat)
|| (lastWrite != null && now - lastWrite > heartbeat)) {
Request req = new Request();
- req.setVersion("2.0.0");
+ req.setVersion(Version.getProtocolVersion());
req.setTwoWay(true);
req.setEvent(Request.HEARTBEAT_EVENT);
channel.send(req);
diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/com/alibaba/dubbo/remoting/codec/ExchangeCodecTest.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/com/alibaba/dubbo/remoting/codec/ExchangeCodecTest.java
index 0f36da42f1be..e372e14f6509 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/test/java/com/alibaba/dubbo/remoting/codec/ExchangeCodecTest.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/com/alibaba/dubbo/remoting/codec/ExchangeCodecTest.java
@@ -18,6 +18,7 @@
import com.alibaba.dubbo.common.Constants;
+import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
import com.alibaba.dubbo.common.io.Bytes;
import com.alibaba.dubbo.common.io.UnsafeByteArrayOutputStream;
@@ -216,7 +217,7 @@ public void test_Decode_Return_Request_Event_Object() throws IOException {
Assert.assertEquals(person, obj.getData());
Assert.assertEquals(true, obj.isTwoWay());
Assert.assertEquals(true, obj.isEvent());
- Assert.assertEquals("2.0.0", obj.getVersion());
+ Assert.assertEquals(Version.getProtocolVersion(), obj.getVersion());
System.out.println(obj);
}
@@ -231,7 +232,7 @@ public void test_Decode_Return_Request_Event_String() throws IOException {
Assert.assertEquals(event, obj.getData());
Assert.assertEquals(true, obj.isTwoWay());
Assert.assertEquals(true, obj.isEvent());
- Assert.assertEquals("2.0.0", obj.getVersion());
+ Assert.assertEquals(Version.getProtocolVersion(), obj.getVersion());
System.out.println(obj);
}
@@ -244,7 +245,7 @@ public void test_Decode_Return_Request_Heartbeat_Object() throws IOException {
Assert.assertEquals(null, obj.getData());
Assert.assertEquals(true, obj.isTwoWay());
Assert.assertEquals(true, obj.isHeartbeat());
- Assert.assertEquals("2.0.0", obj.getVersion());
+ Assert.assertEquals(Version.getProtocolVersion(), obj.getVersion());
System.out.println(obj);
}
@@ -259,7 +260,7 @@ public void test_Decode_Return_Request_Object() throws IOException {
Assert.assertEquals(person, obj.getData());
Assert.assertEquals(true, obj.isTwoWay());
Assert.assertEquals(false, obj.isHeartbeat());
- Assert.assertEquals("2.0.0", obj.getVersion());
+ Assert.assertEquals(Version.getProtocolVersion(), obj.getVersion());
System.out.println(obj);
}
@@ -350,7 +351,7 @@ public void test_Encode_Response() throws IOException {
Assert.assertEquals(response.isHeartbeat(), obj.isHeartbeat());
Assert.assertEquals(person, obj.getResult());
// encode response verson ??
-// Assert.assertEquals(response.getVersion(), obj.getVersion());
+// Assert.assertEquals(response.getProtocolVersion(), obj.getVersion());
}
@@ -380,7 +381,7 @@ public void test_Encode_Error_Response() throws IOException {
Assert.assertEquals(response.isHeartbeat(), obj.isHeartbeat());
Assert.assertEquals(badString, obj.getErrorMessage());
Assert.assertEquals(null, obj.getResult());
-// Assert.assertEquals(response.getVersion(), obj.getVersion());
+// Assert.assertEquals(response.getProtocolVersion(), obj.getVersion());
}
// http://code.alibabatech.com/jira/browse/DUBBO-392
@@ -388,7 +389,7 @@ public void test_Encode_Error_Response() throws IOException {
public void testMessageLengthGreaterThanMessageActualLength() throws Exception {
Channel channel = getCliendSideChannel(url);
Request request = new Request(1L);
- request.setVersion("2.0.0");
+ request.setVersion(Version.getProtocolVersion());
Date date = new Date();
request.setData(date);
ChannelBuffer encodeBuffer = ChannelBuffers.dynamicBuffer(1024);
diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/com/alibaba/dubbo/remoting/transport/codec/DeprecatedExchangeCodec.java b/dubbo-remoting/dubbo-remoting-api/src/test/java/com/alibaba/dubbo/remoting/transport/codec/DeprecatedExchangeCodec.java
index d70edb1c693d..2b44ada3941c 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/test/java/com/alibaba/dubbo/remoting/transport/codec/DeprecatedExchangeCodec.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/test/java/com/alibaba/dubbo/remoting/transport/codec/DeprecatedExchangeCodec.java
@@ -16,6 +16,7 @@
*/
package com.alibaba.dubbo.remoting.transport.codec;
+import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.common.io.Bytes;
import com.alibaba.dubbo.common.io.StreamUtils;
import com.alibaba.dubbo.common.io.UnsafeByteArrayInputStream;
@@ -164,7 +165,7 @@ protected Object decodeBody(Channel channel, InputStream is, byte[] header) thro
} else {
// decode request.
Request req = new Request(id);
- req.setVersion("2.0.0");
+ req.setVersion(Version.getProtocolVersion());
req.setTwoWay((flag & FLAG_TWOWAY) != 0);
if ((flag & FLAG_EVENT) != 0) {
req.setEvent(Request.HEARTBEAT_EVENT);
diff --git a/dubbo-remoting/dubbo-remoting-netty4/pom.xml b/dubbo-remoting/dubbo-remoting-netty4/pom.xml
index ef74d0ceb48a..566db4377a4e 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/pom.xml
+++ b/dubbo-remoting/dubbo-remoting-netty4/pom.xml
@@ -44,5 +44,11 @@
io.netty
netty-all
+
+ com.alibaba
+ dubbo-serialization-hessian2
+ ${project.parent.version}
+ test
+
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/ClientReconnectTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/ClientReconnectTest.java
new file mode 100644
index 000000000000..59597bb16209
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/ClientReconnectTest.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.remoting.transport.netty4;
+
+import com.alibaba.dubbo.common.Constants;
+import com.alibaba.dubbo.common.utils.DubboAppender;
+import com.alibaba.dubbo.common.utils.NetUtils;
+import com.alibaba.dubbo.remoting.Channel;
+import com.alibaba.dubbo.remoting.Client;
+import com.alibaba.dubbo.remoting.RemotingException;
+import com.alibaba.dubbo.remoting.Server;
+import com.alibaba.dubbo.remoting.exchange.Exchangers;
+import com.alibaba.dubbo.remoting.exchange.support.ExchangeHandlerAdapter;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Client reconnect test
+ */
+public class ClientReconnectTest {
+ public static void main(String[] args) {
+ System.out.println(3 % 1);
+ }
+
+ @Before
+ public void clear() {
+ DubboAppender.clear();
+ }
+
+ @Test
+ public void testReconnect() throws RemotingException, InterruptedException {
+ {
+ int port = NetUtils.getAvailablePort();
+ Client client = startClient(port, 200);
+ Assert.assertEquals(false, client.isConnected());
+ Server server = startServer(port);
+ for (int i = 0; i < 100 && !client.isConnected(); i++) {
+ Thread.sleep(10);
+ }
+ Assert.assertEquals(true, client.isConnected());
+ client.close(2000);
+ server.close(2000);
+ }
+ {
+ int port = NetUtils.getAvailablePort();
+ Client client = startClient(port, 20000);
+ Assert.assertEquals(false, client.isConnected());
+ Server server = startServer(port);
+ for (int i = 0; i < 5; i++) {
+ Thread.sleep(200);
+ }
+ Assert.assertEquals(false, client.isConnected());
+ client.close(2000);
+ server.close(2000);
+ }
+ }
+
+
+ public Client startClient(int port, int reconnectPeriod) throws RemotingException {
+ final String url = "exchange://127.0.0.1:" + port + "/client.reconnect.test?client=netty4&check=false&" + Constants.RECONNECT_KEY + "=" + reconnectPeriod;
+ return Exchangers.connect(url);
+ }
+
+ public Server startServer(int port) throws RemotingException {
+ final String url = "exchange://127.0.0.1:" + port + "/client.reconnect.test?server=netty4";
+ return Exchangers.bind(url, new HandlerAdapter());
+ }
+
+ static class HandlerAdapter extends ExchangeHandlerAdapter {
+ @Override
+ public void connected(Channel channel) throws RemotingException {
+ }
+
+ @Override
+ public void disconnected(Channel channel) throws RemotingException {
+ }
+
+ @Override
+ public void caught(Channel channel, Throwable exception) throws RemotingException {
+ }
+ }
+}
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/ClientToServerTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/ClientToServerTest.java
new file mode 100644
index 000000000000..d780e5bd3241
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/ClientToServerTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.remoting.transport.netty4;
+
+import com.alibaba.dubbo.remoting.RemotingException;
+import com.alibaba.dubbo.remoting.exchange.ExchangeChannel;
+import com.alibaba.dubbo.remoting.exchange.ExchangeServer;
+import com.alibaba.dubbo.remoting.exchange.ResponseFuture;
+import com.alibaba.dubbo.remoting.exchange.support.Replier;
+import junit.framework.TestCase;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * ClientToServer
+ */
+public abstract class ClientToServerTest extends TestCase {
+
+ protected static final String LOCALHOST = "127.0.0.1";
+
+ protected ExchangeServer server;
+
+ protected ExchangeChannel client;
+
+ protected WorldHandler handler = new WorldHandler();
+
+ protected abstract ExchangeServer newServer(int port, Replier> receiver) throws RemotingException;
+
+ protected abstract ExchangeChannel newClient(int port) throws RemotingException;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ int port = (int) (1000 * Math.random() + 10000);
+ server = newServer(port, handler);
+ client = newClient(port);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ try {
+ if (server != null)
+ server.close();
+ } finally {
+ if (client != null)
+ client.close();
+ }
+ }
+
+ @Test
+ public void testFuture() throws Exception {
+ ResponseFuture future = client.request(new World("world"));
+ Hello result = (Hello) future.get();
+ Assert.assertEquals("hello,world", result.getName());
+ }
+}
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/ClientsTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/ClientsTest.java
new file mode 100644
index 000000000000..c14bca249861
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/ClientsTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.remoting.transport.netty4;
+
+import com.alibaba.dubbo.common.extension.ExtensionLoader;
+import com.alibaba.dubbo.remoting.Transporter;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+public class ClientsTest {
+ @Test
+ public void testGetTransportEmpty() {
+ try {
+ ExtensionLoader.getExtensionLoader(Transporter.class).getExtension("");
+ fail();
+ } catch (IllegalArgumentException expected) {
+ assertThat(expected.getMessage(), containsString("Extension name == null"));
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetTransportNull() {
+ String name = null;
+ ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(name);
+ }
+
+ @Test
+ public void testGetTransport3() {
+ String name = "netty4";
+ assertEquals(NettyTransporter.class, ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(name).getClass());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testGetTransportWrong() {
+ String name = "nety";
+ assertNull(ExtensionLoader.getExtensionLoader(Transporter.class).getExtension(name).getClass());
+ }
+}
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/Hello.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/Hello.java
new file mode 100644
index 000000000000..fe2d31026bc2
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/Hello.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.remoting.transport.netty4;
+
+import java.io.Serializable;
+
+/**
+ * Result
+ */
+public class Hello implements Serializable {
+
+ private static final long serialVersionUID = 753429849957096150L;
+
+ private String name;
+
+ public Hello() {
+ }
+
+ public Hello(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/NettyClientToServerTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/NettyClientToServerTest.java
new file mode 100644
index 000000000000..2c7ada22eaea
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/NettyClientToServerTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.remoting.transport.netty4;
+
+import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.remoting.RemotingException;
+import com.alibaba.dubbo.remoting.exchange.ExchangeChannel;
+import com.alibaba.dubbo.remoting.exchange.ExchangeServer;
+import com.alibaba.dubbo.remoting.exchange.Exchangers;
+import com.alibaba.dubbo.remoting.exchange.support.Replier;
+
+/**
+ * Netty4ClientToServerTest
+ */
+public class NettyClientToServerTest extends ClientToServerTest {
+
+ protected ExchangeServer newServer(int port, Replier> receiver) throws RemotingException {
+ return Exchangers.bind(URL.valueOf("exchange://localhost:" + port + "?server=netty4"), receiver);
+ }
+
+ protected ExchangeChannel newClient(int port) throws RemotingException {
+ return Exchangers.connect(URL.valueOf("exchange://localhost:" + port + "?client=netty4"));
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/World.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/World.java
new file mode 100644
index 000000000000..5895f9babbd1
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/World.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.remoting.transport.netty4;
+
+import java.io.Serializable;
+
+/**
+ * Data
+ */
+public class World implements Serializable {
+
+ private static final long serialVersionUID = 8563900571013747774L;
+
+ private String name;
+
+ public World() {
+ }
+
+ public World(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/WorldHandler.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/WorldHandler.java
new file mode 100644
index 000000000000..c0b2fcdb0ec8
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/com/alibaba/dubbo/remoting/transport/netty4/WorldHandler.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.remoting.transport.netty4;
+
+import com.alibaba.dubbo.remoting.RemotingException;
+import com.alibaba.dubbo.remoting.exchange.ExchangeChannel;
+import com.alibaba.dubbo.remoting.exchange.support.Replier;
+
+/**
+ * DataHandler
+ */
+public class WorldHandler implements Replier {
+
+ public Class interest() {
+ return World.class;
+ }
+
+ public Object reply(ExchangeChannel channel, World msg) throws RemotingException {
+ return new Hello("hello," + msg.getName());
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java
index 9efd8b454938..685effd465d3 100644
--- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java
+++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/com/alibaba/dubbo/remoting/zookeeper/support/AbstractZookeeperClient.java
@@ -52,12 +52,14 @@ public URL getUrl() {
@Override
public void create(String path, boolean ephemeral) {
+ if (!ephemeral) {
+ if (checkExists(path)) {
+ return;
+ }
+ }
int i = path.lastIndexOf('/');
if (i > 0) {
- String parentPath = path.substring(0, i);
- if (!checkExists(parentPath)) {
- create(parentPath, false);
- }
+ create(path.substring(0, i), false);
}
if (ephemeral) {
createEphemeral(path);
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
index bf56e2d12d46..6bb4d867d887 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcContext.java
@@ -55,6 +55,12 @@ protected RpcContext initialValue() {
return new RpcContext();
}
};
+ private static final InternalThreadLocal SERVER_LOCAL = new InternalThreadLocal() {
+ @Override
+ protected RpcContext initialValue() {
+ return new RpcContext();
+ }
+ };
private final Map attachments = new HashMap();
private final Map values = new HashMap();
@@ -88,6 +94,24 @@ protected RpcContext initialValue() {
protected RpcContext() {
}
+ /**
+ * get server side context.
+ *
+ * @return server context
+ */
+ public static RpcContext getServerContext() {
+ return SERVER_LOCAL.get();
+ }
+
+ /**
+ * remove server side context.
+ *
+ * @see com.alibaba.dubbo.rpc.filter.ContextFilter
+ */
+ public static void removeServerContext() {
+ SERVER_LOCAL.remove();
+ }
+
/**
* get context.
*
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcResult.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcResult.java
index ac4504a8096d..8d3811bde40e 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcResult.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcResult.java
@@ -107,9 +107,17 @@ public Map getAttachments() {
* @param map contains all key-value pairs to append
*/
public void setAttachments(Map map) {
- if (map != null && map.size() > 0) {
- attachments.putAll(map);
+ this.attachments = map == null ? new HashMap() : map;
+ }
+
+ public void addAttachments(Map map) {
+ if (map == null) {
+ return;
+ }
+ if (this.attachments == null) {
+ this.attachments = new HashMap();
}
+ this.attachments.putAll(map);
}
@Override
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ConsumerContextFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ConsumerContextFilter.java
index ba2cd758981c..8c9f822d7fd6 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ConsumerContextFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ConsumerContextFilter.java
@@ -26,6 +26,7 @@
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcInvocation;
+import com.alibaba.dubbo.rpc.RpcResult;
/**
* ConsumerContextInvokerFilter
@@ -45,7 +46,9 @@ public Result invoke(Invoker> invoker, Invocation invocation) throws RpcExcept
((RpcInvocation) invocation).setInvoker(invoker);
}
try {
- return invoker.invoke(invocation);
+ RpcResult result = (RpcResult) invoker.invoke(invocation);
+ RpcContext.getServerContext().setAttachments(result.getAttachments());
+ return result;
} finally {
RpcContext.getContext().clearAttachments();
}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ContextFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ContextFilter.java
index d0b7da145e56..ed852bf50a3b 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ContextFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/ContextFilter.java
@@ -25,6 +25,7 @@
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcInvocation;
+import com.alibaba.dubbo.rpc.RpcResult;
import java.util.HashMap;
import java.util.Map;
@@ -69,9 +70,13 @@ public Result invoke(Invoker> invoker, Invocation invocation) throws RpcExcept
((RpcInvocation) invocation).setInvoker(invoker);
}
try {
- return invoker.invoke(invocation);
+ RpcResult result = (RpcResult) invoker.invoke(invocation);
+ // pass attachments to result
+ result.addAttachments(RpcContext.getServerContext().getAttachments());
+ return result;
} finally {
RpcContext.removeContext();
+ RpcContext.getServerContext().clearAttachments();
}
}
}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
index 7fdaf83fd343..4002f04e3aa8 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
@@ -90,7 +90,10 @@ public Object decode(Channel channel, InputStream input) throws IOException {
ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType)
.deserialize(channel.getUrl(), input);
- setAttachment(Constants.DUBBO_VERSION_KEY, in.readUTF());
+ String dubboVersion = in.readUTF();
+ request.setVersion(dubboVersion);
+ setAttachment(Constants.DUBBO_VERSION_KEY, dubboVersion);
+
setAttachment(Constants.PATH_KEY, in.readUTF());
setAttachment(Constants.VERSION_KEY, in.readUTF());
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java
index 9e84e88e7073..f774557a6047 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java
@@ -35,6 +35,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;
+import java.util.Map;
public class DecodeableRpcResult extends RpcResult implements Codec, Decodeable {
@@ -97,6 +98,35 @@ public Object decode(Channel channel, InputStream input) throws IOException {
throw new IOException(StringUtils.toString("Read response data failed.", e));
}
break;
+ case DubboCodec.RESPONSE_NULL_VALUE_WITH_ATTACHMENTS:
+ try {
+ setAttachments((Map) in.readObject(Map.class));
+ } catch (ClassNotFoundException e) {
+ throw new IOException(StringUtils.toString("Read response data failed.", e));
+ }
+ break;
+ case DubboCodec.RESPONSE_VALUE_WITH_ATTACHMENTS:
+ try {
+ Type[] returnType = RpcUtils.getReturnTypes(invocation);
+ setValue(returnType == null || returnType.length == 0 ? in.readObject() :
+ (returnType.length == 1 ? in.readObject((Class>) returnType[0])
+ : in.readObject((Class>) returnType[0], returnType[1])));
+ setAttachments((Map) in.readObject(Map.class));
+ } catch (ClassNotFoundException e) {
+ throw new IOException(StringUtils.toString("Read response data failed.", e));
+ }
+ break;
+ case DubboCodec.RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS:
+ try {
+ Object obj = in.readObject();
+ if (obj instanceof Throwable == false)
+ throw new IOException("Response data error, expect Throwable, but get " + obj);
+ setException((Throwable) obj);
+ setAttachments((Map) in.readObject(Map.class));
+ } catch (ClassNotFoundException e) {
+ throw new IOException(StringUtils.toString("Read response data failed.", e));
+ }
+ break;
default:
throw new IOException("Unknown result flag, expect '0' '1' '2', get " + flag);
}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCodec.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCodec.java
index 8c633f79166d..80e420905104 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCodec.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboCodec.java
@@ -49,10 +49,13 @@
public class DubboCodec extends ExchangeCodec implements Codec2 {
public static final String NAME = "dubbo";
- public static final String DUBBO_VERSION = Version.getVersion(DubboCodec.class, Version.getVersion());
+ public static final String DUBBO_VERSION = Version.getProtocolVersion();
public static final byte RESPONSE_WITH_EXCEPTION = 0;
public static final byte RESPONSE_VALUE = 1;
public static final byte RESPONSE_NULL_VALUE = 2;
+ public static final byte RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS = 3;
+ public static final byte RESPONSE_VALUE_WITH_ATTACHMENTS = 4;
+ public static final byte RESPONSE_NULL_VALUE_WITH_ATTACHMENTS = 5;
public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
public static final Class>[] EMPTY_CLASS_ARRAY = new Class>[0];
private static final Logger log = LoggerFactory.getLogger(DubboCodec.class);
@@ -109,7 +112,7 @@ protected Object decodeBody(Channel channel, InputStream is, byte[] header) thro
} else {
// decode request.
Request req = new Request(id);
- req.setVersion("2.0.0");
+ req.setVersion(Version.getProtocolVersion());
req.setTwoWay((flag & FLAG_TWOWAY) != 0);
if ((flag & FLAG_EVENT) != 0) {
req.setEvent(Request.HEARTBEAT_EVENT);
@@ -162,9 +165,19 @@ private byte[] readMessageData(InputStream is) throws IOException {
@Override
protected void encodeRequestData(Channel channel, ObjectOutput out, Object data) throws IOException {
+ encodeRequestData(channel, out, data, DUBBO_VERSION);
+ }
+
+ @Override
+ protected void encodeResponseData(Channel channel, ObjectOutput out, Object data) throws IOException {
+ encodeResponseData(channel, out, data, DUBBO_VERSION);
+ }
+
+ @Override
+ protected void encodeRequestData(Channel channel, ObjectOutput out, Object data, String version) throws IOException {
RpcInvocation inv = (RpcInvocation) data;
- out.writeUTF(inv.getAttachment(Constants.DUBBO_VERSION_KEY, DUBBO_VERSION));
+ out.writeUTF(version);
out.writeUTF(inv.getAttachment(Constants.PATH_KEY));
out.writeUTF(inv.getAttachment(Constants.VERSION_KEY));
@@ -179,21 +192,28 @@ protected void encodeRequestData(Channel channel, ObjectOutput out, Object data)
}
@Override
- protected void encodeResponseData(Channel channel, ObjectOutput out, Object data) throws IOException {
+ protected void encodeResponseData(Channel channel, ObjectOutput out, Object data, String version) throws IOException {
Result result = (Result) data;
-
+ // currently, the version value in Response records the version of Request
+ boolean attach = Version.isSupportResponseAttatchment(version);
Throwable th = result.getException();
if (th == null) {
Object ret = result.getValue();
if (ret == null) {
- out.writeByte(RESPONSE_NULL_VALUE);
+ out.writeByte(attach ? RESPONSE_NULL_VALUE_WITH_ATTACHMENTS : RESPONSE_NULL_VALUE);
} else {
- out.writeByte(RESPONSE_VALUE);
+ out.writeByte(attach ? RESPONSE_VALUE_WITH_ATTACHMENTS : RESPONSE_VALUE);
out.writeObject(ret);
}
} else {
- out.writeByte(RESPONSE_WITH_EXCEPTION);
+ out.writeByte(attach ? RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS : RESPONSE_WITH_EXCEPTION);
out.writeObject(th);
}
+
+ if (attach) {
+ // returns current version of Response to consumer side.
+ result.getAttachments().put(Constants.DUBBO_VERSION_KEY, Version.getProtocolVersion());
+ out.writeObject(result.getAttachments());
+ }
}
}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocol.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocol.java
index 4e8b971328df..017e4a93df38 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/DubboProtocol.java
@@ -65,6 +65,7 @@ public class DubboProtocol extends AbstractProtocol {
private final Map serverMap = new ConcurrentHashMap(); //
private final Map referenceClientMap = new ConcurrentHashMap(); //
private final ConcurrentMap ghostClientMap = new ConcurrentHashMap();
+ private final ConcurrentMap locks = new ConcurrentHashMap();
private final Set optimizers = new ConcurrentHashSet();
//consumer side export a stub service for dispatching event
//servicekey-stubmethods
@@ -373,11 +374,18 @@ private ExchangeClient getSharedClient(URL url) {
referenceClientMap.remove(key);
}
}
- synchronized (key.intern()) {
+
+ locks.putIfAbsent(key, new Object());
+ synchronized (locks.get(key)) {
+ if (referenceClientMap.containsKey(key)) {
+ return referenceClientMap.get(key);
+ }
+
ExchangeClient exchangeClient = initClient(url);
client = new ReferenceCountExchangeClient(exchangeClient, ghostClientMap);
referenceClientMap.put(key, client);
ghostClientMap.remove(key);
+ locks.remove(key);
return client;
}
}
diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocolTest.java b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocolTest.java
index 6e8ab72e174f..877ecd388426 100644
--- a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocolTest.java
+++ b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocolTest.java
@@ -51,7 +51,7 @@ public void testHessianProtocol() {
invoker.destroy();
exporter.unexport();
}
-
+
@Test
public void testOverload() {
HessianServiceImpl server = new HessianServiceImpl();
diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java
index c2f05d28e8c7..8629425145ea 100644
--- a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java
+++ b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java
@@ -23,7 +23,7 @@
public interface HessianService {
String sayHello(String name);
-
+
String sayHello(String name, int times);
void timeOut(int millis);
diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianServiceImpl.java b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianServiceImpl.java
index cc1fe3cad1ee..855de0a28a51 100644
--- a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianServiceImpl.java
+++ b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianServiceImpl.java
@@ -27,7 +27,7 @@ public String sayHello(String name) {
called = true;
return "Hello, " + name;
}
-
+
public String sayHello(String name, int times) {
called = true;
StringBuilder sb = new StringBuilder();
diff --git a/dubbo-rpc/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiProtocol.java b/dubbo-rpc/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiProtocol.java
index 8b01c1d934e5..55fe9326925e 100644
--- a/dubbo-rpc/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-rmi/src/main/java/com/alibaba/dubbo/rpc/protocol/rmi/RmiProtocol.java
@@ -78,7 +78,7 @@ public void run() {
protected T doRefer(final Class serviceType, final URL url) throws RpcException {
final RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
// RMI needs extra parameter since it uses customized remote invocation object
- if (url.getParameter(Constants.DUBBO_VERSION_KEY, Version.getVersion()).equals(Version.getVersion())) {
+ if (url.getParameter(Constants.DUBBO_VERSION_KEY, Version.getProtocolVersion()).equals(Version.getProtocolVersion())) {
// Check dubbo version on provider, this feature only support
rmiProxyFactoryBean.setRemoteInvocationFactory(new RemoteInvocationFactory() {
@Override
diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/test/java/com/alibaba/dubbo/rpc/protocol/thrift/AbstractTest.java b/dubbo-rpc/dubbo-rpc-thrift/src/test/java/com/alibaba/dubbo/rpc/protocol/thrift/AbstractTest.java
index 742e1a5d44ed..13e8d5f7cd44 100644
--- a/dubbo-rpc/dubbo-rpc-thrift/src/test/java/com/alibaba/dubbo/rpc/protocol/thrift/AbstractTest.java
+++ b/dubbo-rpc/dubbo-rpc-thrift/src/test/java/com/alibaba/dubbo/rpc/protocol/thrift/AbstractTest.java
@@ -102,12 +102,12 @@ protected void destroy() throws Exception {
invoker = null;
}
- try{
- if(serverTransport != null){
+ try {
+ if (serverTransport != null) {
// release port if used
serverTransport.close();
}
- }catch (Exception e) {
+ } catch (Exception e) {
// ignore
}
diff --git a/dubbo-rpc/dubbo-rpc-webservice/pom.xml b/dubbo-rpc/dubbo-rpc-webservice/pom.xml
index a2b656de6959..cdb5403a4ed5 100644
--- a/dubbo-rpc/dubbo-rpc-webservice/pom.xml
+++ b/dubbo-rpc/dubbo-rpc-webservice/pom.xml
@@ -40,6 +40,26 @@
dubbo-remoting-http
${project.parent.version}
+
+ javax.xml.bind
+ jaxb-api
+
+
+ com.sun.xml.bind
+ jaxb-impl
+
+
+ com.sun.xml.bind
+ jaxb-core
+
+
+ javax.activation
+ javax.activation-api
+
+
+ com.sun.activation
+ javax.activation
+
org.apache.cxf
cxf-rt-frontend-simple
@@ -53,4 +73,5 @@
spring-context
+
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-webservice/src/main/java/com/alibaba/dubbo/rpc/protocol/webservice/WebServiceProtocol.java b/dubbo-rpc/dubbo-rpc-webservice/src/main/java/com/alibaba/dubbo/rpc/protocol/webservice/WebServiceProtocol.java
index 995f5c5f7210..f501a42043a3 100644
--- a/dubbo-rpc/dubbo-rpc-webservice/src/main/java/com/alibaba/dubbo/rpc/protocol/webservice/WebServiceProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-webservice/src/main/java/com/alibaba/dubbo/rpc/protocol/webservice/WebServiceProtocol.java
@@ -95,7 +95,12 @@ protected Runnable doExport(T impl, Class type, URL url) throws RpcExcept
return new Runnable() {
@Override
public void run() {
- serverFactoryBean.destroy();
+ if(serverFactoryBean.getServer()!= null) {
+ serverFactoryBean.getServer().destroy();
+ }
+ if(serverFactoryBean.getBus()!=null) {
+ serverFactoryBean.getBus().shutdown(true);
+ }
}
};
}
diff --git a/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/DemoService.java b/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/DemoService.java
new file mode 100644
index 000000000000..d3c664cb1ca3
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/DemoService.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.rpc.protocol.webservice;
+
+/**
+ * TestService
+ */
+
+public interface DemoService {
+ void sayHello(String name);
+
+ String echo(String text);
+
+ long timestamp();
+
+ void throwTimeout();
+
+ String getThreadName();
+
+ int getSize(String[] strs);
+
+ int getSize(Object[] os);
+
+ Object invoke(String service, String method) throws Exception;
+
+ int stringLength(String str);
+
+ User create(int age, String name);
+}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/DemoServiceImpl.java b/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/DemoServiceImpl.java
new file mode 100644
index 000000000000..96e02c879f95
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/DemoServiceImpl.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.rpc.protocol.webservice;
+
+import com.alibaba.dubbo.rpc.RpcContext;
+
+/**
+ * DemoServiceImpl
+ */
+
+public class DemoServiceImpl implements DemoService {
+ public DemoServiceImpl() {
+ super();
+ }
+
+ public void sayHello(String name) {
+ System.out.println("hello " + name);
+ }
+
+ public String echo(String text) {
+ return text;
+ }
+
+ public long timestamp() {
+ return System.currentTimeMillis();
+ }
+
+ public String getThreadName() {
+ return Thread.currentThread().getName();
+ }
+
+ public int getSize(String[] strs) {
+ if (strs == null)
+ return -1;
+ return strs.length;
+ }
+
+ public int getSize(Object[] os) {
+ if (os == null)
+ return -1;
+ return os.length;
+ }
+
+ public Object invoke(String service, String method) throws Exception {
+ System.out.println("RpcContext.getContext().getRemoteHost()=" + RpcContext.getContext().getRemoteHost());
+ return service + ":" + method;
+ }
+
+ public User create(int age, String name){
+ User user = new User();
+ user.setAge(age);
+ user.setName(name);
+ return user;
+ }
+
+ public int stringLength(String str) {
+ return str.length();
+ }
+
+ public void throwTimeout() {
+ try {
+ Thread.sleep(6000);
+ } catch (InterruptedException e) {
+ }
+ }
+}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/User.java b/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/User.java
new file mode 100644
index 000000000000..866e36b95871
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/User.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.rpc.protocol.webservice;
+
+public class User {
+ private int age;
+ private String name;
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/WebserviceProtocolTest.java b/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/WebserviceProtocolTest.java
new file mode 100644
index 000000000000..98e77385f9b9
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-webservice/src/test/java/com/alibaba/dubbo/rpc/protocol/webservice/WebserviceProtocolTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.alibaba.dubbo.rpc.protocol.webservice;
+
+import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.common.extension.ExtensionLoader;
+import com.alibaba.dubbo.rpc.Protocol;
+import com.alibaba.dubbo.rpc.ProxyFactory;
+import com.alibaba.dubbo.rpc.service.EchoService;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+
+/**
+ * @author kimmking
+ */
+
+public class WebserviceProtocolTest {
+ private Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+ private ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+
+ @Test
+ public void testDemoProtocol() throws Exception {
+ DemoService service = new DemoServiceImpl();
+ protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("webservice://127.0.0.1:9019/" + DemoService.class.getName() + "?codec=exchange")));
+ service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("webservice://127.0.0.1:9019/" + DemoService.class.getName() + "?codec=exchange")));
+ assertEquals(service.getSize(new String[]{"", "", ""}), 3);
+ }
+
+ @Test
+ public void testWebserviceProtocol() throws Exception {
+ DemoService service = new DemoServiceImpl();
+ protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("webservice://127.0.0.1:9019/" + DemoService.class.getName())));
+ service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("webservice://127.0.0.1:9019/" + DemoService.class.getName())));
+ assertEquals(service.create(1,"kk").getName(), "kk");
+ assertEquals(service.getSize(null), -1);
+ assertEquals(service.getSize(new String[]{"", "", ""}), 3);
+ Object object = service.invoke("webservice://127.0.0.1:9019/" + DemoService.class.getName() + "", "invoke");
+ System.out.println(object);
+ assertEquals("webservice://127.0.0.1:9019/com.alibaba.dubbo.rpc.protocol.webservice.DemoService:invoke", object);
+
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < 1024 * 32 + 32; i++)
+ buf.append('A');
+ assertEquals(32800,service.stringLength(buf.toString()));
+
+// a method start with $ is illegal in soap
+// // cast to EchoService
+// EchoService echo = proxy.getProxy(protocol.refer(EchoService.class, URL.valueOf("webservice://127.0.0.1:9010/" + DemoService.class.getName() + "?client=netty")));
+// assertEquals(echo.echo(buf.toString()), buf.toString());
+// assertEquals(echo.$echo("test"), "test");
+// assertEquals(echo.$echo("abcdefg"), "abcdefg");
+// assertEquals(echo.$echo(1234), 1234);
+ }
+
+
+}
\ No newline at end of file
diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractDeserializer.java
index e3e6c5e9adfb..1946f4a84d2e 100644
--- a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractDeserializer.java
+++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractDeserializer.java
@@ -80,7 +80,7 @@ public Object readList(AbstractHessianInput in, int length)
@Override
public Object readList(AbstractHessianInput in, int length, Class> expectType) throws IOException {
- if(expectType == null) {
+ if (expectType == null) {
return readList(in, length);
}
throw new UnsupportedOperationException(String.valueOf(this));
@@ -94,8 +94,8 @@ public Object readLengthList(AbstractHessianInput in, int length)
@Override
public Object readLengthList(AbstractHessianInput in, int length, Class> expectType) throws IOException {
- if(expectType == null){
- return readLengthList(in , length);
+ if (expectType == null) {
+ return readLengthList(in, length);
}
throw new UnsupportedOperationException(String.valueOf(this));
}
@@ -115,7 +115,7 @@ public Object readMap(AbstractHessianInput in)
@Override
public Object readMap(AbstractHessianInput in, Class> expectKeyType, Class> expectValueType) throws IOException {
- if(expectKeyType == null && expectValueType == null){
+ if (expectKeyType == null && expectValueType == null) {
return readMap(in);
}
throw new UnsupportedOperationException(String.valueOf(this));
@@ -140,12 +140,11 @@ protected String codeName(int ch) {
protected SerializerFactory findSerializerFactory(AbstractHessianInput in) {
SerializerFactory serializerFactory = null;
- if(in instanceof Hessian2Input) {
+ if (in instanceof Hessian2Input) {
serializerFactory = ((Hessian2Input) in).findSerializerFactory();
- }
- else if(in instanceof HessianInput) {
+ } else if (in instanceof HessianInput) {
serializerFactory = ((HessianInput) in).getSerializerFactory();
}
- return serializerFactory == null? new SerializerFactory(): serializerFactory;
+ return serializerFactory == null ? new SerializerFactory() : serializerFactory;
}
}
diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianInput.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianInput.java
index 7d265decc6a8..1d63fec368a3 100644
--- a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianInput.java
+++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/AbstractHessianInput.java
@@ -340,10 +340,10 @@ abstract public Object readObject(Class expectedClass)
*
* @param expectedClass the expected class if the protocol doesn't supply it.
* @param expectedTypes the runtime type hints, eg: expectedClass equals Map, expectedTypes can
- * equals String.class, Short.class
+ * equals String.class, Short.class
*/
public Object readObject(Class expectedClass, Class>... expectedTypes)
- throws IOException{
+ throws IOException {
throw new UnsupportedOperationException(String.valueOf(this));
}
@@ -355,11 +355,12 @@ abstract public Object readObject()
/**
* Reads an arbitrary object from the input stream.
+ *
* @param expectedTypes the runtime type hints, eg: expectedTypes can
- * equals String.class, Short.class for HashMap
+ * equals String.class, Short.class for HashMap
*/
public Object readObject(List> expectedTypes)
- throws IOException{
+ throws IOException {
throw new UnsupportedOperationException(String.valueOf(this));
}
diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionDeserializer.java
index 2d3390b0098a..1d3bc89234dc 100644
--- a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionDeserializer.java
+++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/CollectionDeserializer.java
@@ -87,7 +87,7 @@ public Object readList(AbstractHessianInput in, int length, Class> expectType)
Deserializer deserializer = null;
SerializerFactory factory = findSerializerFactory(in);
- if(expectType != null){
+ if (expectType != null) {
deserializer = factory.getDeserializer(expectType.getName());
}
@@ -114,7 +114,7 @@ public Object readLengthList(AbstractHessianInput in, int length, Class> expec
Deserializer deserializer = null;
SerializerFactory factory = findSerializerFactory(in);
- if(expectType != null){
+ if (expectType != null) {
deserializer = factory.getDeserializer(expectType.getName());
}
diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Deserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Deserializer.java
index 86d0bb3f439e..d8b682490fa5 100644
--- a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Deserializer.java
+++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Deserializer.java
@@ -64,7 +64,6 @@ public Object readList(AbstractHessianInput in, int length)
throws IOException;
/**
- *
* deserialize list object from expect type.
*
* @param in
@@ -74,13 +73,12 @@ public Object readList(AbstractHessianInput in, int length)
* @throws IOException
*/
public Object readList(AbstractHessianInput in, int length, Class> expectType)
- throws IOException;
+ throws IOException;
public Object readLengthList(AbstractHessianInput in, int length)
throws IOException;
/**
- *
* deserialize list object from expect type.
*
* @param in
@@ -90,7 +88,7 @@ public Object readLengthList(AbstractHessianInput in, int length)
* @throws IOException
*/
public Object readLengthList(AbstractHessianInput in, int length, Class> expectType)
- throws IOException;
+ throws IOException;
public Object readMap(AbstractHessianInput in)
throws IOException;
@@ -103,8 +101,8 @@ public Object readMap(AbstractHessianInput in)
* @return
* @throws IOException
*/
- public Object readMap(AbstractHessianInput in, Class> expectKeyType, Class> expectValueType )
- throws IOException;
+ public Object readMap(AbstractHessianInput in, Class> expectKeyType, Class> expectValueType)
+ throws IOException;
public Object readObject(AbstractHessianInput in, String[] fieldNames)
throws IOException;
diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Input.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Input.java
index 85d18a97009e..8d6d7d7b7007 100644
--- a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Input.java
+++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/Hessian2Input.java
@@ -55,7 +55,6 @@
import java.io.Reader;
import java.lang.reflect.Field;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -2092,8 +2091,8 @@ public Object readObject(Class expectedClass, Class>... expectedTypes) throws
boolean keyValuePair = expectedTypes != null && expectedTypes.length == 2;
// fix deserialize of short type
return reader.readMap(this
- , keyValuePair ? expectedTypes[0] : null
- , keyValuePair ? expectedTypes[1] : null);
+ , keyValuePair ? expectedTypes[0] : null
+ , keyValuePair ? expectedTypes[1] : null);
}
case 'M': {
@@ -2213,7 +2212,7 @@ public Object readObject(Class expectedClass, Class>... expectedTypes) throws
boolean valueType = expectedTypes != null && expectedTypes.length == 1;
// fix deserialize of short type
- Object v = reader.readList(this, -1, valueType ? expectedTypes[0] : null);
+ Object v = reader.readList(this, -1, valueType ? expectedTypes[0] : null);
return v;
}
@@ -2392,7 +2391,7 @@ public Object readObject(List> expectedTypes) throws IOException {
case 0xd6:
case 0xd7:
return Integer.valueOf(((tag - BC_INT_SHORT_ZERO) << 16)
- + 256 * read() + read());
+ + 256 * read() + read());
case 'I':
return Integer.valueOf(parseInt());
@@ -2702,8 +2701,8 @@ public Object readObject(List> expectedTypes) throws IOException {
reader = findSerializerFactory().getDeserializer(Map.class);
return reader.readMap(this
- , keyValuePair ? expectedTypes.get(0) : null
- , keyValuePair ? expectedTypes.get(1) : null);
+ , keyValuePair ? expectedTypes.get(0) : null
+ , keyValuePair ? expectedTypes.get(1) : null);
}
case 'M': {
diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/JavaDeserializer.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/JavaDeserializer.java
index fb5b3127b554..229f6858ed1a 100644
--- a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/JavaDeserializer.java
+++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/JavaDeserializer.java
@@ -66,7 +66,7 @@
*/
public class JavaDeserializer extends AbstractMapDeserializer {
private static final Logger log
- = Logger.getLogger(JavaDeserializer.class.getName());
+ = Logger.getLogger(JavaDeserializer.class.getName());
private Class _type;
private HashMap _fieldMap;
@@ -156,10 +156,10 @@ else if (double.class.equals(cl))
}
static void logDeserializeError(Field field, Object obj, Object value,
- Throwable e)
- throws IOException {
+ Throwable e)
+ throws IOException {
String fieldName = (field.getDeclaringClass().getName()
- + "." + field.getName());
+ + "." + field.getName());
if (e instanceof HessianFieldException)
throw (HessianFieldException) e;
@@ -168,7 +168,7 @@ else if (e instanceof IOException)
if (value != null)
throw new HessianFieldException(fieldName + ": " + value.getClass().getName() + " (" + value + ")"
- + " cannot be assigned to '" + field.getType().getName() + "'", e);
+ + " cannot be assigned to '" + field.getType().getName() + "'", e);
else
throw new HessianFieldException(fieldName + ": " + field.getType().getName() + " cannot be assigned from null", e);
}
@@ -180,7 +180,7 @@ public Class getType() {
@Override
public Object readMap(AbstractHessianInput in)
- throws IOException {
+ throws IOException {
try {
Object obj = instantiate();
@@ -196,7 +196,7 @@ public Object readMap(AbstractHessianInput in)
@Override
public Object readObject(AbstractHessianInput in, String[] fieldNames)
- throws IOException {
+ throws IOException {
try {
Object obj = instantiate();
@@ -221,7 +221,7 @@ protected Method getReadResolve(Class cl) {
Method method = methods[i];
if (method.getName().equals("readResolve") &&
- method.getParameterTypes().length == 0)
+ method.getParameterTypes().length == 0)
return method;
}
}
@@ -230,7 +230,7 @@ protected Method getReadResolve(Class cl) {
}
public Object readMap(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
try {
int ref = in.addRef(obj);
@@ -261,9 +261,9 @@ public Object readMap(AbstractHessianInput in, Object obj)
}
public Object readObject(AbstractHessianInput in,
- Object obj,
- String[] fieldNames)
- throws IOException {
+ Object obj,
+ String[] fieldNames)
+ throws IOException {
try {
int ref = in.addRef(obj);
@@ -292,7 +292,7 @@ public Object readObject(AbstractHessianInput in,
}
private Object resolve(Object obj)
- throws Exception {
+ throws Exception {
// if there's a readResolve method, call it
try {
if (_readResolve != null)
@@ -306,7 +306,7 @@ private Object resolve(Object obj)
}
protected Object instantiate()
- throws Exception {
+ throws Exception {
try {
if (_constructor != null)
return _constructor.newInstance(_constructorArgs);
@@ -329,7 +329,7 @@ protected HashMap getFieldMap(Class cl) {
Field field = fields[i];
if (Modifier.isTransient(field.getModifiers())
- || Modifier.isStatic(field.getModifiers()))
+ || Modifier.isStatic(field.getModifiers()))
continue;
else if (fieldMap.get(field.getName()) != null)
continue;
@@ -368,15 +368,13 @@ else if (byte.class.equals(type)) {
deser = new SqlTimeFieldDeserializer(field);
}
// support generic type of map
- else if(Map.class.equals(type)
- && field.getGenericType() != field.getType()){
+ else if (Map.class.equals(type)
+ && field.getGenericType() != field.getType()) {
deser = new ObjectMapFieldDeserializer(field);
- }
- else if(List.class.equals(type)
- && field.getGenericType() != field.getType()){
+ } else if (List.class.equals(type)
+ && field.getGenericType() != field.getType()) {
deser = new ObjectListFieldDeserializer(field);
- }
- else {
+ } else {
deser = new ObjectFieldDeserializer(field);
}
@@ -389,7 +387,7 @@ else if(List.class.equals(type)
abstract static class FieldDeserializer {
abstract void deserialize(AbstractHessianInput in, Object obj)
- throws IOException;
+ throws IOException;
}
static class ObjectFieldDeserializer extends FieldDeserializer {
@@ -401,7 +399,7 @@ static class ObjectFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
Object value = null;
try {
@@ -423,7 +421,7 @@ static class BooleanFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
boolean value = false;
try {
@@ -445,7 +443,7 @@ static class ByteFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
int value = 0;
try {
@@ -467,7 +465,7 @@ static class ShortFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
int value = 0;
try {
@@ -489,16 +487,16 @@ static class ObjectMapFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
Object value = null;
try {
- Type[] types = ((ParameterizedType)_field.getGenericType()).getActualTypeArguments();
+ Type[] types = ((ParameterizedType) _field.getGenericType()).getActualTypeArguments();
value = in.readObject(_field.getType(),
- isPrimitive(types[0]) ? (Class>)types[0] : null,
- isPrimitive(types[1]) ? (Class>)types[1] : null
- );
+ isPrimitive(types[0]) ? (Class>) types[0] : null,
+ isPrimitive(types[1]) ? (Class>) types[1] : null
+ );
_field.set(obj, value);
} catch (Exception e) {
@@ -516,14 +514,14 @@ static class ObjectListFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
Object value = null;
try {
- Type[] types = ((ParameterizedType)_field.getGenericType()).getActualTypeArguments();
+ Type[] types = ((ParameterizedType) _field.getGenericType()).getActualTypeArguments();
value = in.readObject(_field.getType(),
- isPrimitive(types[0]) ? (Class>)types[0] : null
+ isPrimitive(types[0]) ? (Class>) types[0] : null
);
_field.set(obj, value);
@@ -542,7 +540,7 @@ static class IntFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
int value = 0;
try {
@@ -564,7 +562,7 @@ static class LongFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
long value = 0;
try {
@@ -586,7 +584,7 @@ static class FloatFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
double value = 0;
try {
@@ -608,7 +606,7 @@ static class DoubleFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
double value = 0;
try {
@@ -630,7 +628,7 @@ static class StringFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
String value = null;
try {
@@ -652,7 +650,7 @@ static class SqlDateFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
java.sql.Date value = null;
try {
@@ -676,7 +674,7 @@ static class SqlTimestampFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
java.sql.Timestamp value = null;
try {
@@ -700,7 +698,7 @@ static class SqlTimeFieldDeserializer extends FieldDeserializer {
@Override
void deserialize(AbstractHessianInput in, Object obj)
- throws IOException {
+ throws IOException {
java.sql.Time value = null;
try {
@@ -715,43 +713,42 @@ void deserialize(AbstractHessianInput in, Object obj)
}
/**
- * @see java.lang.Boolean#TYPE
- * @see java.lang.Character#TYPE
- * @see java.lang.Byte#TYPE
- * @see java.lang.Short#TYPE
- * @see java.lang.Integer#TYPE
- * @see java.lang.Long#TYPE
- * @see java.lang.Float#TYPE
- * @see java.lang.Double#TYPE
- * @see java.lang.Void#TYPE
+ * @see java.lang.Boolean#TYPE
+ * @see java.lang.Character#TYPE
+ * @see java.lang.Byte#TYPE
+ * @see java.lang.Short#TYPE
+ * @see java.lang.Integer#TYPE
+ * @see java.lang.Long#TYPE
+ * @see java.lang.Float#TYPE
+ * @see java.lang.Double#TYPE
+ * @see java.lang.Void#TYPE
*/
private static boolean isPrimitive(Type type) {
- try{
- if(type != null) {
- if(type instanceof Class>){
- Class> clazz = (Class>)type;
+ try {
+ if (type != null) {
+ if (type instanceof Class>) {
+ Class> clazz = (Class>) type;
return clazz.isPrimitive()
- || PRIMITIVE_TYPE.containsKey(clazz.getName());
+ || PRIMITIVE_TYPE.containsKey(clazz.getName());
}
}
- }
- catch (Exception e){
+ } catch (Exception e) {
// ignore exception
}
return false;
}
- static final Map PRIMITIVE_TYPE = new HashMap(){
+ static final Map PRIMITIVE_TYPE = new HashMap() {
{
- put(Boolean.class.getName() , true );
- put(Character.class.getName() , true );
- put(Byte.class.getName() , true );
- put(Short.class.getName() , true );
- put(Integer.class.getName() , true );
- put(Long.class.getName() , true );
- put(Float.class.getName() , true );
- put(Double.class.getName() , true );
- put(Void.class.getName() , true );
+ put(Boolean.class.getName(), true);
+ put(Character.class.getName(), true);
+ put(Byte.class.getName(), true);
+ put(Short.class.getName(), true);
+ put(Integer.class.getName(), true);
+ put(Long.class.getName(), true);
+ put(Float.class.getName(), true);
+ put(Double.class.getName(), true);
+ put(Void.class.getName(), true);
}
};
}
diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/SerializerFactory.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/SerializerFactory.java
index 39bc5c194a76..b233fdb4a4c6 100644
--- a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/SerializerFactory.java
+++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/SerializerFactory.java
@@ -499,7 +499,7 @@ public Object readMap(AbstractHessianInput in, String type)
* Reads the object as a map.
*/
public Object readMap(AbstractHessianInput in, String type, Class> expectKeyType, Class> expectValueType)
- throws HessianProtocolException, IOException {
+ throws HessianProtocolException, IOException {
Deserializer deserializer = getDeserializer(type);
if (deserializer != null)
diff --git a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java
index 66a8b8036713..0b92f47be26c 100644
--- a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java
+++ b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java
@@ -40,16 +40,16 @@ public void serialize_string_short_map_then_deserialize() throws Exception {
Hessian2StringShortType stringShort = new Hessian2StringShortType();
Map stringShortMap = new HashMap();
- stringShortMap.put("first", (short)0);
- stringShortMap.put("last", (short)60);
+ stringShortMap.put("first", (short) 0);
+ stringShortMap.put("last", (short) 60);
stringShort.stringShortMap = stringShortMap;
Hessian2StringShortType deserialize = baseHessian2Serialize(stringShort);
assertTrue(deserialize.stringShortMap != null);
assertTrue(deserialize.stringShortMap.size() == 2);
assertTrue(deserialize.stringShortMap.get("last") instanceof Short);
- assertEquals(Short.valueOf((short)0), deserialize.stringShortMap.get("first"));
- assertEquals(Short.valueOf((short)60), deserialize.stringShortMap.get("last"));
+ assertEquals(Short.valueOf((short) 0), deserialize.stringShortMap.get("first"));
+ assertEquals(Short.valueOf((short) 60), deserialize.stringShortMap.get("last"));
}
@Test
@@ -57,15 +57,15 @@ public void serialize_string_byte_map_then_deserialize() throws Exception {
Hessian2StringShortType stringShort = new Hessian2StringShortType();
Map stringByteMap = new HashMap();
- stringByteMap.put("first", (byte)0);
- stringByteMap.put("last", (byte)60);
+ stringByteMap.put("first", (byte) 0);
+ stringByteMap.put("last", (byte) 60);
stringShort.stringByteMap = stringByteMap;
Hessian2StringShortType deserialize = baseHessian2Serialize(stringShort);
assertTrue(deserialize.stringByteMap != null);
assertTrue(deserialize.stringByteMap.size() == 2);
assertTrue(deserialize.stringByteMap.get("last") instanceof Byte);
- assertEquals(Byte.valueOf((byte)0), deserialize.stringByteMap.get("first"));
+ assertEquals(Byte.valueOf((byte) 0), deserialize.stringByteMap.get("first"));
assertEquals(Byte.valueOf((byte) 60), deserialize.stringByteMap.get("last"));
}
@@ -73,8 +73,8 @@ public void serialize_string_byte_map_then_deserialize() throws Exception {
public void serialize_map_then_deserialize() throws Exception {
Map stringShortMap = new HashMap();
- stringShortMap.put("first", (short)0);
- stringShortMap.put("last", (short)60);
+ stringShortMap.put("first", (short) 0);
+ stringShortMap.put("last", (short) 60);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
Hessian2Output out = new Hessian2Output(bout);
@@ -88,8 +88,8 @@ public void serialize_map_then_deserialize() throws Exception {
assertTrue(deserialize != null);
assertTrue(deserialize.size() == 2);
assertTrue(deserialize.get("last") instanceof Short);
- assertEquals(Short.valueOf((short)0), deserialize.get("first"));
- assertEquals(Short.valueOf((short)60), deserialize.get("last"));
+ assertEquals(Short.valueOf((short) 0), deserialize.get("first"));
+ assertEquals(Short.valueOf((short) 60), deserialize.get("last"));
}
@Test
@@ -126,10 +126,10 @@ public void serialize_string_person_map_then_deserialize() throws Exception {
Hessian2StringShortType stringShort = new Hessian2StringShortType();
Map stringPersonTypeMap = new HashMap();
stringPersonTypeMap.put("first", new PersonType(
- "jason.shang", 26, (double) 0.1, (short)1, (byte)2, Arrays.asList((short)1,(short)1)
+ "jason.shang", 26, (double) 0.1, (short) 1, (byte) 2, Arrays.asList((short) 1, (short) 1)
));
stringPersonTypeMap.put("last", new PersonType(
- "jason.shang2", 52, (double) 0.2, (short)2, (byte)4, Arrays.asList((short)2,(short)2)
+ "jason.shang2", 52, (double) 0.2, (short) 2, (byte) 4, Arrays.asList((short) 2, (short) 2)
));
stringShort.stringPersonTypeMap = stringPersonTypeMap;
@@ -149,11 +149,11 @@ public void serialize_string_person_map_then_deserialize() throws Exception {
assertEquals(new PersonType(
- "jason.shang", 26, (double) 0.1, (short)1, (byte)2, Arrays.asList((short)1,(short)1)
+ "jason.shang", 26, (double) 0.1, (short) 1, (byte) 2, Arrays.asList((short) 1, (short) 1)
), deserialize.stringPersonTypeMap.get("first"));
assertEquals(new PersonType(
- "jason.shang2", 52, (double) 0.2, (short)2, (byte)4, Arrays.asList((short)2,(short)2)
+ "jason.shang2", 52, (double) 0.2, (short) 2, (byte) 4, Arrays.asList((short) 2, (short) 2)
), deserialize.stringPersonTypeMap.get("last"));
}
@@ -162,8 +162,8 @@ public void serialize_string_person_map_then_deserialize() throws Exception {
public void serialize_list_then_deserialize() throws Exception {
List shortList = new ArrayList();
- shortList.add((short)0);
- shortList.add((short)60);
+ shortList.add((short) 0);
+ shortList.add((short) 60);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
Hessian2Output out = new Hessian2Output(bout);
@@ -177,8 +177,8 @@ public void serialize_list_then_deserialize() throws Exception {
assertTrue(deserialize != null);
assertTrue(deserialize.size() == 2);
assertTrue(deserialize.get(1) instanceof Short);
- assertEquals(Short.valueOf((short)0), deserialize.get(0));
- assertEquals(Short.valueOf((short)60), deserialize.get(1));
+ assertEquals(Short.valueOf((short) 0), deserialize.get(0));
+ assertEquals(Short.valueOf((short) 60), deserialize.get(1));
}
@Test
diff --git a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/Hessian2StringShortType.java b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/Hessian2StringShortType.java
index 5924b237c066..4bc77c9d2c5e 100644
--- a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/Hessian2StringShortType.java
+++ b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/Hessian2StringShortType.java
@@ -20,9 +20,7 @@
import java.util.Map;
/**
- *
* test short serialize & deserialize model
- *
*/
public class Hessian2StringShortType implements Serializable {
@@ -32,7 +30,7 @@ public class Hessian2StringShortType implements Serializable {
public Map stringPersonTypeMap;
- public Hessian2StringShortType(){
+ public Hessian2StringShortType() {
}
}
diff --git a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/PersonType.java b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/PersonType.java
index 4d3a9ebab6a3..7e37c9951de0 100644
--- a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/PersonType.java
+++ b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/beans/PersonType.java
@@ -25,7 +25,7 @@ public class PersonType implements Serializable {
int age;
double money;
short p1;
- byte p2;
+ byte p2;
List p3;
public PersonType(String name, int age, double money, short p1, byte p2, List p3) {
diff --git a/pom.xml b/pom.xml
index c8536aef145b..e45ca67b5e83 100644
--- a/pom.xml
+++ b/pom.xml
@@ -333,6 +333,10 @@
true
true
+
+ ${project.version}
+ ${project.version}
+
@@ -494,6 +498,9 @@
**/resources/META-INF/**
**/com/caucho/hessian/**
+
+ **/com/alibaba/common/threadlocal/InternalThreadLocal.java
+ **/com/alibaba/common/threadlocal/InternalThreadLocalMap.java