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 44c751d9a2f..ec86f1d02b0 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-common/src/main/java/com/alibaba/dubbo/common/Constants.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/Constants.java index 55e86d0382f..404fe8f6b51 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 97e3a2173dc..b84aaa5bfba 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/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 00000000000..139216b0955 --- /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/AbstractInterfaceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/AbstractInterfaceConfig.java index a42d07c1093..168bb10d2ea 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/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/com/alibaba/dubbo/config/ReferenceConfig.java index 7b5175243a1..c6c75b16c68 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 d04d51c6660..8637662d335 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/cache/CacheTest.java b/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/cache/CacheTest.java index 521642ec198..ebda6ba532a 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/schema/DubboBeanDefinitionParser.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/schema/DubboBeanDefinitionParser.java index c9c912d9586..48192a94877 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/schema/DubboBeanDefinitionParser.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/schema/DubboBeanDefinitionParser.java @@ -31,6 +31,7 @@ import com.alibaba.dubbo.config.spring.ReferenceBean; import com.alibaba.dubbo.config.spring.ServiceBean; import com.alibaba.dubbo.rpc.Protocol; + import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; @@ -213,7 +214,7 @@ private static BeanDefinition parse(Element element, ParserContext parserContext String invokeRefMethod = value.substring(index + 1); reference = new RuntimeBeanReference(invokeRef); beanDefinition.getPropertyValues().addPropertyValue("oninvokeMethod", invokeRefMethod); - }else { + } else { if ("ref".equals(property) && parserContext.getRegistry().containsBeanDefinition(value)) { BeanDefinition refBean = parserContext.getRegistry().getBeanDefinition(value); if (!refBean.isSingleton()) { 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 10025d26bb0..c1b8e096226 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 7b6bd8c43c7..3c0fb65c6b7 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 2ab32f008d1..6e520e3acb8 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 ce529b9882c..5dd00d6a204 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 0f36da42f1b..e372e14f650 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 d70edb1c693..2b44ada3941 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-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 bf56e2d12d4..6bb4d867d88 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 ac4504a8096..8d3811bde40 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 ba2cd758981..8c9f822d7fd 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 d0b7da145e5..ed852bf50a3 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 7fdaf83fd34..4002f04e3aa 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 9e84e88e707..f774557a604 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 8c633f79166..80e42090510 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-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 6e8ab72e174..877ecd38842 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 c2f05d28e8c..8629425145e 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 cc1fe3cad1e..855de0a28a5 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 8b01c1d934e..55fe9326925 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 742e1a5d44e..13e8d5f7cd4 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/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 e3e6c5e9adf..1946f4a84d2 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 7d265decc6a..1d63fec368a 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 2d3390b0098..1d3bc89234d 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 86d0bb3f439..d8b682490fa 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 85d18a97009..8d6d7d7b700 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 fb5b3127b55..229f6858ed1 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 39bc5c194a7..b233fdb4a4c 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 66a8b803671..0b92f47be26 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 5924b237c06..4bc77c9d2c5 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 4d3a9ebab6a..7e37c9951de 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 fa9992f8f90..e45ca67b5e8 100644 --- a/pom.xml +++ b/pom.xml @@ -333,6 +333,10 @@ true true + + ${project.version} + ${project.version} +