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 attributes = new HashMap(); map.put(Constants.SIDE_KEY, Constants.CONSUMER_SIDE); - map.put(Constants.DUBBO_VERSION_KEY, Version.getVersion()); + map.put(Constants.DUBBO_VERSION_KEY, 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/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ServiceConfig.java index d04d51c66604..8637662d3357 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ServiceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ServiceConfig.java @@ -367,7 +367,7 @@ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List r Map map = new HashMap(); map.put(Constants.SIDE_KEY, Constants.PROVIDER_SIDE); - map.put(Constants.DUBBO_VERSION_KEY, Version.getVersion()); + map.put(Constants.DUBBO_VERSION_KEY, 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/test/java/com/alibaba/dubbo/config/ProtocolConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/ProtocolConfigTest.java index 4d10c72b738a..797471c6a99f 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/ProtocolConfigTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/ProtocolConfigTest.java @@ -39,7 +39,7 @@ public void testDestroy() throws Exception { MockProtocol2.delegate = protocol; ProtocolConfig protocolConfig = new ProtocolConfig(); protocolConfig.setName("mockprotocol2"); - protocolConfig.destory(); + protocolConfig.destroy(); Mockito.verify(protocol).destroy(); } diff --git a/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/cache/CacheTest.java b/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/cache/CacheTest.java index 521642ec198b..ebda6ba532af 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/cache/CacheTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/cache/CacheTest.java @@ -29,6 +29,7 @@ import com.alibaba.dubbo.config.ServiceConfig; import com.alibaba.dubbo.rpc.Invocation; import com.alibaba.dubbo.rpc.RpcInvocation; + import junit.framework.TestCase; import org.junit.Test; diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java index a4c05c3abc84..389515d1f1d0 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java @@ -17,7 +17,12 @@ package com.alibaba.dubbo.config.spring.extension; import com.alibaba.dubbo.common.extension.ExtensionFactory; +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; import com.alibaba.dubbo.common.utils.ConcurrentHashSet; + +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; import org.springframework.context.ApplicationContext; import java.util.Set; @@ -26,6 +31,7 @@ * SpringExtensionFactory */ public class SpringExtensionFactory implements ExtensionFactory { + private static final Logger logger = LoggerFactory.getLogger(SpringExtensionFactory.class); private static final Set contexts = new ConcurrentHashSet(); @@ -37,6 +43,11 @@ public static void removeApplicationContext(ApplicationContext context) { contexts.remove(context); } + // currently for test purpose + public static void clearContexts() { + contexts.clear(); + } + @Override @SuppressWarnings("unchecked") public T getExtension(Class type, String name) { @@ -48,6 +59,23 @@ public T getExtension(Class type, String name) { } } } + + logger.warn("No spring extension(bean) named:" + name + ", try to find an extension(bean) of type " + type.getName()); + + for (ApplicationContext context : contexts) { + try { + return context.getBean(type); + } catch (NoUniqueBeanDefinitionException multiBeanExe) { + throw multiBeanExe; + } catch (NoSuchBeanDefinitionException noBeanExe) { + if (logger.isDebugEnabled()) { + logger.debug("Error when get spring extension(bean) for type:" + type.getName(), noBeanExe); + } + } + } + + logger.warn("No spring extension(bean) named:" + name + ", type:" + type.getName() + " found, stop get bean."); + return null; } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/initializer/DubboApplicationListener.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/initializer/DubboApplicationListener.java index 43ee49ded8c7..c3d72981b984 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/initializer/DubboApplicationListener.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/initializer/DubboApplicationListener.java @@ -31,7 +31,11 @@ public class DubboApplicationListener implements ApplicationListenerorg.springframework spring-context + + 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